diff --git a/demos/index.html b/demos/index.html index 0abe627a7..ccf9cdf2a 100644 --- a/demos/index.html +++ b/demos/index.html @@ -20,6 +20,7 @@
+
C4Context title System Context diagram for Internet Banking System @@ -55,14 +56,22 @@ Enterprise_Boundary(b0, "BankBoundary0") { BiRel(SystemAA, SystemE, "Uses") Rel(SystemAA, SystemC, "Sends e-mails", "SMTP") Rel(SystemC, customerA, "Sends e-mails to") + + UpdateElementStyle(customerA, $fontColor="red", $bgColor="grey", $borderColor="red") + UpdateRelStyle(customerA, SystemAA, $textColor="blue", $lineColor="blue", $offsetX="5") + UpdateRelStyle(SystemAA, SystemE, $textColor="blue", $lineColor="blue", $offsetY="-10") + UpdateRelStyle(SystemAA, SystemC, $textColor="blue", $lineColor="blue", $offsetY="-40", $offsetX="-50") + UpdateRelStyle(SystemC, customerA, $textColor="red", $lineColor="red", $offsetX="-50", $offsetY="20") + + UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
C4Container title Container diagram for Internet Banking System - System_Ext(email_system, "E-Mail System", "The internal Microsoft Exchange system") - Person(customer, Customer, "A customer of the bank, with personal bank accounts") + System_Ext(email_system, "E-Mail System", "The internal Microsoft Exchange system", $tags="v1.0") + Person(customer, Customer, "A customer of the bank, with personal bank accounts", $tags="v1.0") Container_Boundary(c1, "Internet Banking") { Container(spa, "Single-Page App", "JavaScript, Angular", "Provides all the Internet banking functionality to cutomers via their web browser") @@ -76,17 +85,26 @@ Enterprise_Boundary(b0, "BankBoundary0") { System_Ext(banking_system, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.") Rel(customer, web_app, "Uses", "HTTPS") + UpdateRelStyle(customer, web_app, $offsetY="60", $offsetX="90") Rel(customer, spa, "Uses", "HTTPS") + UpdateRelStyle(customer, spa, $offsetY="-40") Rel(customer, mobile_app, "Uses") + UpdateRelStyle(customer, mobile_app, $offsetY="-30") Rel(web_app, spa, "Delivers") + UpdateRelStyle(web_app, spa, $offsetX="130") Rel(spa, backend_api, "Uses", "async, JSON/HTTPS") Rel(mobile_app, backend_api, "Uses", "async, JSON/HTTPS") Rel_Back(database, backend_api, "Reads from and writes to", "sync, JDBC") Rel(email_system, customer, "Sends e-mails to") + UpdateRelStyle(email_system, customer, $offsetX="-45") Rel(backend_api, email_system, "Sends e-mails using", "sync, SMTP") + UpdateRelStyle(backend_api, email_system, $offsetY="-60") Rel(backend_api, banking_system, "Uses", "sync/async, XML/HTTPS") + UpdateRelStyle(backend_api, banking_system, $offsetY="-50", $offsetX="-140") + +
@@ -130,6 +148,10 @@ Enterprise_Boundary(b0, "BankBoundary0") { Rel(c1, c2, "Submits credentials to", "JSON/HTTPS") Rel(c2, c3, "Calls isAuthenticated() on") Rel(c3, c4, "select * from users where username = ?", "JDBC") + + UpdateRelStyle(c1, c2, $textColor="red", $offsetY="-40") + UpdateRelStyle(c2, c3, $textColor="red", $offsetX="-40", $offsetY="60") + UpdateRelStyle(c3, c4, $textColor="red", $offsetY="-40", $offsetX="10")
diff --git a/src/defaultConfig.js b/src/defaultConfig.js index d5c69dfdb..f877097ed 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -1084,14 +1084,21 @@ const config = { diagramMarginY: 10, /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | --------------------- | ------- | -------- | ------------------ | - * | shapeMargin | Margin between shapes | Integer | Required | Any Positive Value | + * | Parameter | Description | Type | Required | Values | + * | ------------- | --------------------- | ------- | -------- | ------------------ | + * | c4ShapeMargin | Margin between shapes | Integer | Required | Any Positive Value | * * **Notes:** Default value: 50 */ c4ShapeMargin: 50, + /** + * | Parameter | Description | Type | Required | Values | + * | -------------- | ---------------------- | ------- | -------- | ------------------ | + * | c4ShapePadding | Padding between shapes | Integer | Required | Any Positive Value | + * + * **Notes:** Default value: 20 + */ c4ShapePadding: 20, /** @@ -1113,9 +1120,9 @@ const config = { height: 60, /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ------------------------ | ------- | -------- | ------------------ | - * | boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value | + * | Parameter | Description | Type | Required | Values | + * | --------- | ------------------- | ------- | -------- | ------------------ | + * | boxMargin | Margin around boxes | Integer | Required | Any Positive Value | * * **Notes:** Default value: 10 */ @@ -1133,97 +1140,446 @@ const config = { */ useMaxWidth: true, + /** + * | Parameter | Description | Type | Required | Values | + * | ------------ | ----------- | ------- | -------- | ------------------ | + * | c4ShapeInRow | See Notes | Integer | Required | Any Positive Value | + * + * **Notes:** How many shapes to place in each row. + * + * Default value: 4 + */ c4ShapeInRow: 4, + nextLinePaddingX: 0, + /** + * | Parameter | Description | Type | Required | Values | + * | --------------- | ----------- | ------- | -------- | ------------------ | + * | c4BoundaryInRow | See Notes | Integer | Required | Any Positive Value | + * + * **Notes:** How many boundarys to place in each row. + * + * Default value: 2 + */ c4BoundaryInRow: 2, + /** + * This sets the font size of Person shape for the diagram + * + * **Notes:** Default value: 14. + */ personFontSize: 14, + /** + * This sets the font family of Person shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ personFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Person shape for the diagram + * + * **Notes:** Default value: normal. + */ personFontWeight: 'normal', + /** + * This sets the font size of External Person shape for the diagram + * + * **Notes:** Default value: 14. + */ external_personFontSize: 14, + /** + * This sets the font family of External Person shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_personFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External Person shape for the diagram + * + * **Notes:** Default value: normal. + */ external_personFontWeight: 'normal', + /** + * This sets the font size of System shape for the diagram + * + * **Notes:** Default value: 14. + */ systemFontSize: 14, + /** + * This sets the font family of System shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ systemFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of System shape for the diagram + * + * **Notes:** Default value: normal. + */ systemFontWeight: 'normal', + /** + * This sets the font size of External System shape for the diagram + * + * **Notes:** Default value: 14. + */ external_systemFontSize: 14, + /** + * This sets the font family of External System shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_systemFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External System shape for the diagram + * + * **Notes:** Default value: normal. + */ external_systemFontWeight: 'normal', + /** + * This sets the font size of System DB shape for the diagram + * + * **Notes:** Default value: 14. + */ system_dbFontSize: 14, + /** + * This sets the font family of System DB shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ system_dbFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of System DB shape for the diagram + * + * **Notes:** Default value: normal. + */ system_dbFontWeight: 'normal', + /** + * This sets the font size of External System DB shape for the diagram + * + * **Notes:** Default value: 14. + */ external_system_dbFontSize: 14, + /** + * This sets the font family of External System DB shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_system_dbFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External System DB shape for the diagram + * + * **Notes:** Default value: normal. + */ external_system_dbFontWeight: 'normal', + /** + * This sets the font size of System Queue shape for the diagram + * + * **Notes:** Default value: 14. + */ system_queueFontSize: 14, + /** + * This sets the font family of System Queue shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ system_queueFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of System Queue shape for the diagram + * + * **Notes:** Default value: normal. + */ system_queueFontWeight: 'normal', + /** + * This sets the font size of External System Queue shape for the diagram + * + * **Notes:** Default value: 14. + */ external_system_queueFontSize: 14, + /** + * This sets the font family of External System Queue shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_system_queueFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External System Queue shape for the diagram + * + * **Notes:** Default value: normal. + */ external_system_queueFontWeight: 'normal', + /** + * This sets the font size of Boundary shape for the diagram + * + * **Notes:** Default value: 14. + */ boundaryFontSize: 14, + /** + * This sets the font family of Boundary shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ boundaryFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Boundary shape for the diagram + * + * **Notes:** Default value: normal. + */ boundaryFontWeight: 'normal', + /** + * This sets the font size of Message shape for the diagram + * + * **Notes:** Default value: 12. + */ messageFontSize: 12, + /** + * This sets the font family of Message shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ messageFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Message shape for the diagram + * + * **Notes:** Default value: normal. + */ messageFontWeight: 'normal', + /** + * This sets the font size of Container shape for the diagram + * + * **Notes:** Default value: 14. + */ containerFontSize: 14, + /** + * This sets the font family of Container shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ containerFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Container shape for the diagram + * + * **Notes:** Default value: normal. + */ containerFontWeight: 'normal', + /** + * This sets the font size of External Container shape for the diagram + * + * **Notes:** Default value: 14. + */ external_containerFontSize: 14, + /** + * This sets the font family of External Container shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_containerFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External Container shape for the diagram + * + * **Notes:** Default value: normal. + */ external_containerFontWeight: 'normal', + /** + * This sets the font size of Container DB shape for the diagram + * + * **Notes:** Default value: 14. + */ container_dbFontSize: 14, + /** + * This sets the font family of Container DB shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ container_dbFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Container DB shape for the diagram + * + * **Notes:** Default value: normal. + */ container_dbFontWeight: 'normal', + /** + * This sets the font size of External Container DB shape for the diagram + * + * **Notes:** Default value: 14. + */ external_container_dbFontSize: 14, + /** + * This sets the font family of External Container DB shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_container_dbFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External Container DB shape for the diagram + * + * **Notes:** Default value: normal. + */ external_container_dbFontWeight: 'normal', + /** + * This sets the font size of Container Queue shape for the diagram + * + * **Notes:** Default value: 14. + */ container_queueFontSize: 14, + /** + * This sets the font family of Container Queue shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ container_queueFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Container Queue shape for the diagram + * + * **Notes:** Default value: normal. + */ container_queueFontWeight: 'normal', + /** + * This sets the font size of External Container Queue shape for the diagram + * + * **Notes:** Default value: 14. + */ external_container_queueFontSize: 14, + /** + * This sets the font family of External Container Queue shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_container_queueFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External Container Queue shape for the diagram + * + * **Notes:** Default value: normal. + */ external_container_queueFontWeight: 'normal', + /** + * This sets the font size of Component shape for the diagram + * + * **Notes:** Default value: 14. + */ componentFontSize: 14, + /** + * This sets the font family of Component shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ componentFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Component shape for the diagram + * + * **Notes:** Default value: normal. + */ componentFontWeight: 'normal', + /** + * This sets the font size of External Component shape for the diagram + * + * **Notes:** Default value: 14. + */ external_componentFontSize: 14, + /** + * This sets the font family of External Component shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_componentFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External Component shape for the diagram + * + * **Notes:** Default value: normal. + */ external_componentFontWeight: 'normal', + /** + * This sets the font size of Component DB shape for the diagram + * + * **Notes:** Default value: 14. + */ component_dbFontSize: 14, + /** + * This sets the font family of Component DB shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ component_dbFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Component DB shape for the diagram + * + * **Notes:** Default value: normal. + */ component_dbFontWeight: 'normal', + /** + * This sets the font size of External Component DB shape for the diagram + * + * **Notes:** Default value: 14. + */ external_component_dbFontSize: 14, + /** + * This sets the font family of External Component DB shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_component_dbFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External Component DB shape for the diagram + * + * **Notes:** Default value: normal. + */ external_component_dbFontWeight: 'normal', + /** + * This sets the font size of Component Queue shape for the diagram + * + * **Notes:** Default value: 14. + */ component_queueFontSize: 14, + /** + * This sets the font family of Component Queue shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ component_queueFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of Component Queue shape for the diagram + * + * **Notes:** Default value: normal. + */ component_queueFontWeight: 'normal', + /** + * This sets the font size of External Component Queue shape for the diagram + * + * **Notes:** Default value: 14. + */ external_component_queueFontSize: 14, + /** + * This sets the font family of External Component Queue shape for the diagram + * + * **Notes:** Default value: "Open Sans", sans-serif. + */ external_component_queueFontFamily: '"Open Sans", sans-serif', + /** + * This sets the font weight of External Component Queue shape for the diagram + * + * **Notes:** Default value: normal. + */ external_component_queueFontWeight: 'normal', /** diff --git a/src/diagrams/c4/c4Db.js b/src/diagrams/c4/c4Db.js index b346d9b16..d53d6d31f 100644 --- a/src/diagrams/c4/c4Db.js +++ b/src/diagrams/c4/c4Db.js @@ -22,6 +22,8 @@ let rels = []; let title = ''; let wrapEnabled = false; let description = ''; +let c4ShapeInRow = 4; +let c4BoundaryInRow = 2; var c4Type; export const getC4Type = function () { @@ -65,22 +67,46 @@ export const addRel = function (type, from, to, label, techn, descr, sprite, tag rel.to = to; rel.label = { text: label }; - if (descr === undefined || descr === null) { - rel.descr = { text: '' }; - } else { - rel.descr = { text: descr }; - } - if (techn === undefined || techn === null) { rel.techn = { text: '' }; } else { - rel.techn = { text: techn }; + if (typeof techn === 'object') { + let [key, value] = Object.entries(techn)[0]; + rel[key] = { text: value }; + } else { + rel.techn = { text: techn }; + } } - // rel.techn = techn; - rel.sprite = sprite; - rel.tags = tags; - rel.link = link; + if (descr === undefined || descr === null) { + rel.descr = { text: '' }; + } else { + if (typeof descr === 'object') { + let [key, value] = Object.entries(descr)[0]; + rel[key] = { text: value }; + } else { + rel.descr = { text: descr }; + } + } + + if (typeof sprite === 'object') { + let [key, value] = Object.entries(sprite)[0]; + rel[key] = value; + } else { + rel.sprite = sprite; + } + if (typeof tags === 'object') { + let [key, value] = Object.entries(tags)[0]; + rel[key] = value; + } else { + rel.tags = tags; + } + if (typeof link === 'object') { + let [key, value] = Object.entries(link)[0]; + rel[key] = value; + } else { + rel.link = link; + } rel.wrap = autoWrap(); }; @@ -108,15 +134,35 @@ export const addPersonOrSystem = function (typeC4Shape, alias, label, descr, spr if (descr === undefined || descr === null) { personOrSystem.descr = { text: '' }; } else { - personOrSystem.descr = { text: descr }; + if (typeof descr === 'object') { + let [key, value] = Object.entries(descr)[0]; + personOrSystem[key] = { text: value }; + } else { + personOrSystem.descr = { text: descr }; + } } - personOrSystem.wrap = autoWrap(); - personOrSystem.sprite = sprite; - personOrSystem.tags = tags; - personOrSystem.link = link; + if (typeof sprite === 'object') { + let [key, value] = Object.entries(sprite)[0]; + personOrSystem[key] = value; + } else { + personOrSystem.sprite = sprite; + } + if (typeof tags === 'object') { + let [key, value] = Object.entries(tags)[0]; + personOrSystem[key] = value; + } else { + personOrSystem.tags = tags; + } + if (typeof link === 'object') { + let [key, value] = Object.entries(link)[0]; + personOrSystem[key] = value; + } else { + personOrSystem.link = link; + } personOrSystem.typeC4Shape = { text: typeC4Shape }; personOrSystem.parentBoundary = currentBoundaryParse; + personOrSystem.wrap = autoWrap(); }; //type, alias, label, ?techn, ?descr ?sprite, ?tags, $link @@ -143,18 +189,43 @@ export const addContainer = function (typeC4Shape, alias, label, techn, descr, s if (techn === undefined || techn === null) { container.techn = { text: '' }; } else { - container.techn = { text: techn }; + if (typeof techn === 'object') { + let [key, value] = Object.entries(techn)[0]; + container[key] = { text: value }; + } else { + container.techn = { text: techn }; + } } if (descr === undefined || descr === null) { container.descr = { text: '' }; } else { - container.descr = { text: descr }; + if (typeof descr === 'object') { + let [key, value] = Object.entries(descr)[0]; + container[key] = { text: value }; + } else { + container.descr = { text: descr }; + } } - container.sprite = sprite; - container.tags = tags; - container.link = link; + if (typeof sprite === 'object') { + let [key, value] = Object.entries(sprite)[0]; + container[key] = value; + } else { + container.sprite = sprite; + } + if (typeof tags === 'object') { + let [key, value] = Object.entries(tags)[0]; + container[key] = value; + } else { + container.tags = tags; + } + if (typeof link === 'object') { + let [key, value] = Object.entries(link)[0]; + container[key] = value; + } else { + container.link = link; + } container.wrap = autoWrap(); container.typeC4Shape = { text: typeC4Shape }; container.parentBoundary = currentBoundaryParse; @@ -184,18 +255,43 @@ export const addComponent = function (typeC4Shape, alias, label, techn, descr, s if (techn === undefined || techn === null) { component.techn = { text: '' }; } else { - component.techn = { text: techn }; + if (typeof techn === 'object') { + let [key, value] = Object.entries(techn)[0]; + component[key] = { text: value }; + } else { + component.techn = { text: techn }; + } } if (descr === undefined || descr === null) { component.descr = { text: '' }; } else { - component.descr = { text: descr }; + if (typeof descr === 'object') { + let [key, value] = Object.entries(descr)[0]; + component[key] = { text: value }; + } else { + component.descr = { text: descr }; + } } - component.sprite = sprite; - component.tags = tags; - component.link = link; + if (typeof sprite === 'object') { + let [key, value] = Object.entries(sprite)[0]; + component[key] = value; + } else { + component.sprite = sprite; + } + if (typeof tags === 'object') { + let [key, value] = Object.entries(tags)[0]; + component[key] = value; + } else { + component.tags = tags; + } + if (typeof link === 'object') { + let [key, value] = Object.entries(link)[0]; + component[key] = value; + } else { + component.link = link; + } component.wrap = autoWrap(); component.typeC4Shape = { text: typeC4Shape }; component.parentBoundary = currentBoundaryParse; @@ -227,11 +323,26 @@ export const addPersonOrSystemBoundary = function (alias, label, type, tags, lin if (type === undefined || type === null) { boundary.type = { text: 'system' }; } else { - boundary.type = { text: type }; + if (typeof type === 'object') { + let [key, value] = Object.entries(type)[0]; + boundary[key] = { text: value }; + } else { + boundary.type = { text: type }; + } } - boundary.tags = tags; - boundary.link = link; + if (typeof tags === 'object') { + let [key, value] = Object.entries(tags)[0]; + boundary[key] = value; + } else { + boundary.tags = tags; + } + if (typeof link === 'object') { + let [key, value] = Object.entries(link)[0]; + boundary[key] = value; + } else { + boundary.link = link; + } boundary.parentBoundary = currentBoundaryParse; boundary.wrap = autoWrap(); @@ -266,11 +377,26 @@ export const addContainerBoundary = function (alias, label, type, tags, link) { if (type === undefined || type === null) { boundary.type = { text: 'container' }; } else { - boundary.type = { text: type }; + if (typeof type === 'object') { + let [key, value] = Object.entries(type)[0]; + boundary[key] = { text: value }; + } else { + boundary.type = { text: type }; + } } - boundary.tags = tags; - boundary.link = link; + if (typeof tags === 'object') { + let [key, value] = Object.entries(tags)[0]; + boundary[key] = value; + } else { + boundary.tags = tags; + } + if (typeof link === 'object') { + let [key, value] = Object.entries(link)[0]; + boundary[key] = value; + } else { + boundary.link = link; + } boundary.parentBoundary = currentBoundaryParse; boundary.wrap = autoWrap(); @@ -314,17 +440,37 @@ export const addDeploymentNode = function ( if (type === undefined || type === null) { boundary.type = { text: 'node' }; } else { - boundary.type = { text: type }; + if (typeof type === 'object') { + let [key, value] = Object.entries(type)[0]; + boundary[key] = { text: value }; + } else { + boundary.type = { text: type }; + } } if (descr === undefined || descr === null) { boundary.descr = { text: '' }; } else { - boundary.descr = { text: type }; + if (typeof descr === 'object') { + let [key, value] = Object.entries(descr)[0]; + boundary[key] = { text: value }; + } else { + boundary.descr = { text: descr }; + } } - boundary.tags = tags; - boundary.link = link; + if (typeof tags === 'object') { + let [key, value] = Object.entries(tags)[0]; + boundary[key] = value; + } else { + boundary.tags = tags; + } + if (typeof link === 'object') { + let [key, value] = Object.entries(link)[0]; + boundary[key] = value; + } else { + boundary.link = link; + } boundary.nodeType = nodeType; boundary.parentBoundary = currentBoundaryParse; boundary.wrap = autoWrap(); @@ -341,6 +487,177 @@ export const popBoundaryParseStack = function () { boundaryParseStack.push(parentBoundaryParse); }; +//elementName, ?bgColor, ?fontColor, ?borderColor, ?shadowing, ?shape, ?sprite, ?techn, ?legendText, ?legendSprite +export const updateElStyle = function ( + typeC4Shape, + elementName, + bgColor, + fontColor, + borderColor, + shadowing, + shape, + sprite, + techn, + legendText, + legendSprite +) { + let old = c4ShapeArray.find((element) => element.alias === elementName); + if (old === undefined) { + old = boundarys.find((element) => element.alias === elementName); + if (old === undefined) { + return; + } + } + if (bgColor !== undefined && bgColor !== null) { + if (typeof bgColor === 'object') { + let [key, value] = Object.entries(bgColor)[0]; + old[key] = value; + } else { + old.bgColor = bgColor; + } + } + if (fontColor !== undefined && fontColor !== null) { + if (typeof fontColor === 'object') { + let [key, value] = Object.entries(fontColor)[0]; + old[key] = value; + } else { + old.fontColor = fontColor; + } + } + if (borderColor !== undefined && borderColor !== null) { + if (typeof borderColor === 'object') { + let [key, value] = Object.entries(borderColor)[0]; + old[key] = value; + } else { + old.borderColor = borderColor; + } + } + if (shadowing !== undefined && shadowing !== null) { + if (typeof shadowing === 'object') { + let [key, value] = Object.entries(shadowing)[0]; + old[key] = value; + } else { + old.shadowing = shadowing; + } + } + if (shape !== undefined && shape !== null) { + if (typeof shape === 'object') { + let [key, value] = Object.entries(shape)[0]; + old[key] = value; + } else { + old.shape = shape; + } + } + if (sprite !== undefined && sprite !== null) { + if (typeof sprite === 'object') { + let [key, value] = Object.entries(sprite)[0]; + old[key] = value; + } else { + old.sprite = sprite; + } + } + if (techn !== undefined && techn !== null) { + if (typeof techn === 'object') { + let [key, value] = Object.entries(techn)[0]; + old[key] = value; + } else { + old.techn = techn; + } + } + if (legendText !== undefined && legendText !== null) { + if (typeof legendText === 'object') { + let [key, value] = Object.entries(legendText)[0]; + old[key] = value; + } else { + old.legendText = legendText; + } + } + if (legendSprite !== undefined && legendSprite !== null) { + if (typeof legendSprite === 'object') { + let [key, value] = Object.entries(legendSprite)[0]; + old[key] = value; + } else { + old.legendSprite = legendSprite; + } + } +}; + +//textColor, lineColor, ?offsetX, ?offsetY +export const updateRelStyle = function ( + typeC4Shape, + from, + to, + textColor, + lineColor, + offsetX, + offsetY +) { + const old = rels.find((rel) => rel.from === from && rel.to === to); + if (old === undefined) { + return; + } + if (textColor !== undefined && textColor !== null) { + if (typeof textColor === 'object') { + let [key, value] = Object.entries(textColor)[0]; + old[key] = value; + } else { + old.textColor = textColor; + } + } + if (lineColor !== undefined && lineColor !== null) { + if (typeof lineColor === 'object') { + let [key, value] = Object.entries(lineColor)[0]; + old[key] = value; + } else { + old.lineColor = lineColor; + } + } + if (offsetX !== undefined && offsetX !== null) { + if (typeof offsetX === 'object') { + let [key, value] = Object.entries(offsetX)[0]; + old[key] = parseInt(value); + } else { + old.offsetX = parseInt(offsetX); + } + } + if (offsetY !== undefined && offsetY !== null) { + if (typeof offsetY === 'object') { + let [key, value] = Object.entries(offsetY)[0]; + old[key] = parseInt(value); + } else { + old.offsetY = parseInt(offsetY); + } + } +}; + +//?c4ShapeInRow, ?c4BoundaryInRow +export const updateLayoutConfig = function (typeC4Shape, c4ShapeInRowParam, c4BoundaryInRowParam) { + let c4ShapeInRowValue = c4ShapeInRow; + let c4BoundaryInRowValue = c4BoundaryInRow; + + if (typeof c4ShapeInRowParam === 'object') { + let [key, value] = Object.entries(c4ShapeInRowParam)[0]; + c4ShapeInRowValue = parseInt(value); + } else { + c4ShapeInRowValue = parseInt(c4ShapeInRowParam); + } + if (typeof c4BoundaryInRowParam === 'object') { + let [key, value] = Object.entries(c4BoundaryInRowParam)[0]; + c4BoundaryInRowValue = parseInt(value); + } else { + c4BoundaryInRowValue = parseInt(c4BoundaryInRowParam); + } + + if (c4ShapeInRowValue >= 1) c4ShapeInRow = c4ShapeInRowValue; + if (c4BoundaryInRowValue >= 1) c4BoundaryInRow = c4BoundaryInRowValue; +}; + +export const getC4ShapeInRow = function () { + return c4ShapeInRow; +}; +export const getC4BoundaryInRow = function () { + return c4BoundaryInRow; +}; export const getCurrentBoundaryParse = function () { return currentBoundaryParse; }; @@ -400,6 +717,13 @@ export const clear = function () { currentBoundaryParse = 'global'; boundaryParseStack = ['']; rels = []; + + boundaryParseStack = ['']; + title = ''; + wrapEnabled = false; + description = ''; + c4ShapeInRow = 4; + c4BoundaryInRow = 2; }; export const LINETYPE = { @@ -453,6 +777,9 @@ export default { addDeploymentNode, popBoundaryParseStack, addRel, + updateElStyle, + updateRelStyle, + updateLayoutConfig, autoWrap, setWrap, getC4ShapeArray, @@ -464,6 +791,8 @@ export default { getRels, getTitle, getC4Type, + getC4ShapeInRow, + getC4BoundaryInRow, setAccTitle, getAccTitle, getAccDescription, diff --git a/src/diagrams/c4/c4Renderer.js b/src/diagrams/c4/c4Renderer.js index d71e70e2e..1ff42575a 100644 --- a/src/diagrams/c4/c4Renderer.js +++ b/src/diagrams/c4/c4Renderer.js @@ -17,6 +17,9 @@ import addSVGAccessibilityFields from '../../accessibility'; let globalBoundaryMaxX = 0, globalBoundaryMaxY = 0; +let c4ShapeInRow = 4; +let c4BoundaryInRow = 2; + parser.yy = c4Db; let conf = {}; @@ -68,7 +71,7 @@ class Bounds { if ( _startx >= this.data.widthLimit || _stopx >= this.data.widthLimit || - this.nextData.cnt > conf.c4ShapeInRow + this.nextData.cnt > c4ShapeInRow ) { _startx = this.nextData.startx + c4Shape.margin + conf.nextLinePaddingX; _starty = this.nextData.stopy + c4Shape.margin * 2; @@ -448,7 +451,7 @@ function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentB let currentBounds = new Bounds(); // Calculate the width limit of the boundar. label/type 的长度, currentBounds.data.widthLimit = - parentBounds.data.widthLimit / Math.min(conf.c4BoundaryInRow, currentBoundarys.length); + parentBounds.data.widthLimit / Math.min(c4BoundaryInRow, currentBoundarys.length); // Math.min( // conf.width * conf.c4ShapeInRow + conf.c4ShapeMargin * conf.c4ShapeInRow * 2, // parentBounds.data.widthLimit / Math.min(conf.c4BoundaryInRow, currentBoundarys.length) @@ -507,7 +510,7 @@ function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentB Y = currentBoundary['descr'].Y + currentBoundary['descr'].height; } - if (i == 0 || i % conf.c4BoundaryInRow === 0) { + if (i == 0 || i % c4BoundaryInRow === 0) { // Calculate the drawing start point of the currentBoundarys. let _x = parentBounds.data.startx + conf.diagramMarginX; let _y = parentBounds.data.stopy + conf.diagramMarginY + Y; @@ -579,10 +582,15 @@ export const draw = function (text, id) { : select('body'); const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + let db = parser.yy; + parser.yy.clear(); parser.yy.setWrap(conf.wrap); parser.parse(text + '\n'); + c4ShapeInRow = db.getC4ShapeInRow(); + c4BoundaryInRow = db.getC4BoundaryInRow(); + log.debug(`C:${JSON.stringify(conf, null, 2)}`); const diagram = @@ -593,6 +601,7 @@ export const draw = function (text, id) { svgDraw.insertClockIcon(diagram); let screenBounds = new Bounds(); + screenBounds.setData( conf.diagramMarginX, conf.diagramMarginX, diff --git a/src/diagrams/c4/parser/c4Diagram.jison b/src/diagrams/c4/parser/c4Diagram.jison index 9b57e3cf1..10783db53 100644 --- a/src/diagrams/c4/parser/c4Diagram.jison +++ b/src/diagrams/c4/parser/c4Diagram.jison @@ -61,14 +61,27 @@ %x rel_r %x rel_b +/* Custom tags/stereotypes */ +%x update_el_style +%x update_rel_style +%x update_layout_config + %x attribute %x string +%x string_kv +%x string_kv_key +%x string_kv_value %x open_directive %x type_directive %x arg_directive +%x close_directive +%x acc_title +%x acc_descr +%x acc_descr_multiline %% + \%\%\{ { this.begin('open_directive'); return 'open_directive'; } .*direction\s+TB[^\n]* return 'direction_tb'; .*direction\s+BT[^\n]* return 'direction_bt'; @@ -78,11 +91,21 @@ ":" { this.popState(); this.begin('arg_directive'); return ':'; } \}\%\% { this.popState(); this.popState(); return 'close_directive'; } ((?:(?!\}\%\%).|\n)*) return 'arg_directive'; -\%\%(?!\{)*[^\n]*(\r?\n?)+ /* skip comments */ -\%\%[^\n]*(\r?\n)* c /* skip comments */ + "title"\s[^#\n;]+ return 'title'; "accDescription"\s[^#\n;]+ return 'accDescription'; +accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } +accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } +accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} +[\}] { this.popState(); } +[^\}]* return "acc_descr_multiline_value"; + + +\%\%(?!\{)*[^\n]*(\r?\n?)+ /* skip comments */ +\%\%[^\n]*(\r?\n)* c /* skip comments */ \s*(\r?\n)+ return 'NEWLINE'; \s+ /* skip whitespace */ @@ -140,10 +163,14 @@ "Rel_Back" { this.begin("rel_b"); console.log('begin rel_b'); return 'REL_B';} "RelIndex" { this.begin("rel_index"); console.log('begin rel_index'); return 'REL_INDEX';} -<> return "EOF_IN_STRUCT"; -[(][ ]*[,] { console.log('begin attribute with ATTRIBUTE_EMPTY'); this.begin("attribute"); return "ATTRIBUTE_EMPTY";} -[(] { console.log('begin attribute'); this.begin("attribute"); } -[)] { console.log('STOP attribute'); this.popState();console.log('STOP diagram'); this.popState();} +"UpdateElementStyle" { this.begin("update_el_style"); console.log('begin update_el_style'); return 'UPDATE_EL_STYLE';} +"UpdateRelStyle" { this.begin("update_rel_style"); console.log('begin update_rel_style'); return 'UPDATE_REL_STYLE';} +"UpdateLayoutConfig" { this.begin("update_layout_config"); console.log('begin update_layout_config'); return 'UPDATE_LAYOUT_CONFIG';} + +<> return "EOF_IN_STRUCT"; +[(][ ]*[,] { console.log('begin attribute with ATTRIBUTE_EMPTY'); this.begin("attribute"); return "ATTRIBUTE_EMPTY";} +[(] { console.log('begin attribute'); this.begin("attribute"); } +[)] { console.log('STOP attribute'); this.popState();console.log('STOP diagram'); this.popState();} ",," { console.log(',,'); return 'ATTRIBUTE_EMPTY';} "," { console.log(','); } @@ -151,6 +178,13 @@ [ ]*["] { console.log('begin string'); this.begin("string");} ["] { console.log('STOP string'); this.popState(); } [^"]* { console.log('STR'); return "STR";} + +[ ]*[\$] { console.log('begin string_kv'); this.begin("string_kv");} +[^=]* { console.log('STR_KEY'); this.begin("string_kv_key"); return "STR_KEY";} +[=][ ]*["] { console.log('begin string_kv_value'); this.popState(); this.begin("string_kv_value"); } +[^"]+ { console.log('STR_VALUE'); return "STR_VALUE";} +["] { console.log('STOP string_kv_value'); this.popState(); this.popState(); } + [^,]+ { console.log('not STR'); return "STR";} '{' { /* this.begin("lbrace"); */ console.log('begin boundary block'); return "LBRACE";} @@ -235,6 +269,9 @@ otherStatements otherStatement : title {yy.setTitle($1.substring(6));$$=$1.substring(6);} | accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);} + | acc_title acc_title_value { $$=$2.trim();yy.setTitle($$); } + | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } + | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } ; boundaryStatement @@ -297,6 +334,9 @@ diagramStatement | REL_R attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_r', ...$2); $$=$2;} | REL_B attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_b', ...$2); $$=$2;} | REL_INDEX attributes {console.log($1,JSON.stringify($2)); $2.splice(0, 1); yy.addRel('rel', ...$2); $$=$2;} + | UPDATE_EL_STYLE attributes {console.log($1,JSON.stringify($2)); yy.updateElStyle('update_el_style', ...$2); $$=$2;} + | UPDATE_REL_STYLE attributes {console.log($1,JSON.stringify($2)); yy.updateRelStyle('update_rel_style', ...$2); $$=$2;} + | UPDATE_LAYOUT_CONFIG attributes {console.log($1,JSON.stringify($2)); yy.updateLayoutConfig('update_layout_config', ...$2); $$=$2;} ; attributes @@ -306,7 +346,7 @@ attributes attribute : STR { $$ = $1.trim(); } + | STR_KEY STR_VALUE { console.log('kv: ', $1, $2); let kv={}; kv[$1.trim()]=$2.trim(); $$=kv; } | ATTRIBUTE { $$ = $1.trim(); } | ATTRIBUTE_EMPTY { $$ = ""; } ; - diff --git a/src/diagrams/c4/svgDraw.js b/src/diagrams/c4/svgDraw.js index fb3a276db..c30a00c38 100644 --- a/src/diagrams/c4/svgDraw.js +++ b/src/diagrams/c4/svgDraw.js @@ -216,6 +216,11 @@ export const drawRels = (elem, rels, conf) => { const relsElem = elem.append('g'); let i = 0; for (let rel of rels) { + let textColor = rel.textColor ? rel.textColor : '#444444'; + let strokeColor = rel.lineColor ? rel.lineColor : '#444444'; + let offsetX = rel.offsetX ? parseInt(rel.offsetX) : 0; + let offsetY = rel.offsetY ? parseInt(rel.offsetY) : 0; + let url = ''; if (i === 0) { let line = relsElem.append('line'); @@ -225,7 +230,7 @@ export const drawRels = (elem, rels, conf) => { line.attr('y2', rel.endPoint.y); line.attr('stroke-width', '1'); - line.attr('stroke', '#444444'); + line.attr('stroke', strokeColor); line.style('fill', 'none'); if (rel.type !== 'rel_b') line.attr('marker-end', 'url(' + url + '#arrowhead)'); if (rel.type === 'birel' || rel.type === 'rel_b') @@ -236,7 +241,7 @@ export const drawRels = (elem, rels, conf) => { line .attr('fill', 'none') .attr('stroke-width', '1') - .attr('stroke', '#444444') + .attr('stroke', strokeColor) .attr( 'd', 'Mstartx,starty Qcontrolx,controly stopx,stopy ' @@ -261,11 +266,15 @@ export const drawRels = (elem, rels, conf) => { _drawTextCandidateFunc(conf)( rel.label.text, relsElem, - Math.min(rel.startPoint.x, rel.endPoint.x) + Math.abs(rel.endPoint.x - rel.startPoint.x) / 2, - Math.min(rel.startPoint.y, rel.endPoint.y) + Math.abs(rel.endPoint.y - rel.startPoint.y) / 2, + Math.min(rel.startPoint.x, rel.endPoint.x) + + Math.abs(rel.endPoint.x - rel.startPoint.x) / 2 + + offsetX, + Math.min(rel.startPoint.y, rel.endPoint.y) + + Math.abs(rel.endPoint.y - rel.startPoint.y) / 2 + + offsetY, rel.label.width, rel.label.height, - { fill: '#444444' }, + { fill: textColor }, messageConf ); @@ -275,14 +284,16 @@ export const drawRels = (elem, rels, conf) => { '[' + rel.techn.text + ']', relsElem, Math.min(rel.startPoint.x, rel.endPoint.x) + - Math.abs(rel.endPoint.x - rel.startPoint.x) / 2, + Math.abs(rel.endPoint.x - rel.startPoint.x) / 2 + + offsetX, Math.min(rel.startPoint.y, rel.endPoint.y) + Math.abs(rel.endPoint.y - rel.startPoint.y) / 2 + conf.messageFontSize + - 5, + 5 + + offsetY, Math.max(rel.label.width, rel.techn.width), rel.techn.height, - { fill: '#444444', 'font-style': 'italic' }, + { fill: textColor, 'font-style': 'italic' }, messageConf ); } @@ -299,13 +310,17 @@ export const drawRels = (elem, rels, conf) => { const drawBoundary = function (elem, boundary, conf) { const boundaryElem = elem.append('g'); + let fillColor = boundary.bgColor ? boundary.bgColor : 'none'; + let strokeColor = boundary.borderColor ? boundary.borderColor : '#444444'; + let fontColor = boundary.fontColor ? boundary.fontColor : 'black'; + let attrsValue = { 'stroke-width': 1.0, 'stroke-dasharray': '7.0,7.0' }; if (boundary.nodeType) attrsValue = { 'stroke-width': 1.0 }; let rectData = { x: boundary.x, y: boundary.y, - fill: 'none', - stroke: '#444444', + fill: fillColor, + stroke: strokeColor, width: boundary.width, height: boundary.height, rx: 2.5, @@ -319,6 +334,7 @@ const drawBoundary = function (elem, boundary, conf) { let boundaryConf = conf.boundaryFont(); boundaryConf.fontWeight = 'bold'; boundaryConf.fontSize = boundaryConf.fontSize + 2; + boundaryConf.fontColor = fontColor; _drawTextCandidateFunc(conf)( boundary.label.text, boundaryElem, @@ -333,6 +349,7 @@ const drawBoundary = function (elem, boundary, conf) { // draw type if (boundary.type && boundary.type.text !== '') { boundaryConf = conf.boundaryFont(); + boundaryConf.fontColor = fontColor; _drawTextCandidateFunc(conf)( boundary.type.text, boundaryElem, @@ -349,6 +366,7 @@ const drawBoundary = function (elem, boundary, conf) { if (boundary.descr && boundary.descr.text !== '') { boundaryConf = conf.boundaryFont(); boundaryConf.fontSize = boundaryConf.fontSize - 2; + boundaryConf.fontColor = fontColor; _drawTextCandidateFunc(conf)( boundary.descr.text, boundaryElem, @@ -363,8 +381,12 @@ const drawBoundary = function (elem, boundary, conf) { }; export const drawC4Shape = function (elem, c4Shape, conf) { - let fillColor = conf[c4Shape.typeC4Shape.text + '_bg_color']; - let strokeColor = conf[c4Shape.typeC4Shape.text + '_border_color']; + let fillColor = c4Shape.bgColor ? c4Shape.bgColor : conf[c4Shape.typeC4Shape.text + '_bg_color']; + let strokeColor = c4Shape.borderColor + ? c4Shape.borderColor + : conf[c4Shape.typeC4Shape.text + '_border_color']; + let fontColor = c4Shape.fontColor ? c4Shape.fontColor : '#FFFFFF'; + let personImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAACD0lEQVR4Xu2YoU4EMRCGT+4j8Ai8AhaH4QHgAUjQuFMECUgMIUgwJAgMhgQsAYUiJCiQIBBY+EITsjfTdme6V24v4c8vyGbb+ZjOtN0bNcvjQXmkH83WvYBWto6PLm6v7p7uH1/w2fXD+PBycX1Pv2l3IdDm/vn7x+dXQiAubRzoURa7gRZWd0iGRIiJbOnhnfYBQZNJjNbuyY2eJG8fkDE3bbG4ep6MHUAsgYxmE3nVs6VsBWJSGccsOlFPmLIViMzLOB7pCVO2AtHJMohH7Fh6zqitQK7m0rJvAVYgGcEpe//PLdDz65sM4pF9N7ICcXDKIB5Nv6j7tD0NoSdM2QrU9Gg0ewE1LqBhHR3BBdvj2vapnidjHxD/q6vd7Pvhr31AwcY8eXMTXAKECZZJFXuEq27aLgQK5uLMohCenGGuGewOxSjBvYBqeG6B+Nqiblggdjnc+ZXDy+FNFpFzw76O3UBAROuXh6FoiAcf5g9eTvUgzy0nWg6I8cXHRUpg5bOVBCo+KDpFajOf23GgPme7RSQ+lacIENUgJ6gg1k6HjgOlqnLqip4tEuhv0hNEMXUD0clyXE3p6pZA0S2nnvTlXwLJEZWlb7cTQH1+USgTN4VhAenm/wea1OCAOmqo6fE1WCb9WSKBah+rbUWPWAmE2Rvk0ApiB45eOyNAzU8xcTvj8KvkKEoOaIYeHNA3ZuygAvFMUO0AAAAASUVORK5CYII='; switch (c4Shape.typeC4Shape.text) { @@ -473,7 +495,7 @@ export const drawC4Shape = function (elem, c4Shape, conf) { let c4ShapeFontConf = getC4ShapeFont(conf, c4Shape.typeC4Shape.text); c4ShapeElem .append('text') - .attr('fill', '#FFFFFF') + .attr('fill', fontColor) .attr('font-family', c4ShapeFontConf.fontFamily) .attr('font-size', c4ShapeFontConf.fontSize - 2) .attr('font-style', 'italic') @@ -502,6 +524,7 @@ export const drawC4Shape = function (elem, c4Shape, conf) { let textFontConf = conf[c4Shape.typeC4Shape.text + 'Font'](); textFontConf.fontWeight = 'bold'; textFontConf.fontSize = textFontConf.fontSize + 2; + textFontConf.fontColor = fontColor; _drawTextCandidateFunc(conf)( c4Shape.label.text, c4ShapeElem, @@ -509,12 +532,13 @@ export const drawC4Shape = function (elem, c4Shape, conf) { c4Shape.y + c4Shape.label.Y, c4Shape.width, c4Shape.height, - { fill: '#FFFFFF' }, + { fill: fontColor }, textFontConf ); // draw techn/type textFontConf = conf[c4Shape.typeC4Shape.text + 'Font'](); + textFontConf.fontColor = fontColor; if (c4Shape.thchn && c4Shape.thchn.text !== '') { _drawTextCandidateFunc(conf)( @@ -524,7 +548,7 @@ export const drawC4Shape = function (elem, c4Shape, conf) { c4Shape.y + c4Shape.thchn.Y, c4Shape.width, c4Shape.height, - { fill: '#FFFFFF', 'font-style': 'italic' }, + { fill: fontColor, 'font-style': 'italic' }, textFontConf ); } else if (c4Shape.type && c4Shape.type.text !== '') { @@ -535,7 +559,7 @@ export const drawC4Shape = function (elem, c4Shape, conf) { c4Shape.y + c4Shape.type.Y, c4Shape.width, c4Shape.height, - { fill: '#FFFFFF', 'font-style': 'italic' }, + { fill: fontColor, 'font-style': 'italic' }, textFontConf ); } @@ -543,6 +567,7 @@ export const drawC4Shape = function (elem, c4Shape, conf) { // draw descr if (c4Shape.descr && c4Shape.descr.text !== '') { textFontConf = conf.personFont(); + textFontConf.fontColor = fontColor; _drawTextCandidateFunc(conf)( c4Shape.descr.text, c4ShapeElem, @@ -550,7 +575,7 @@ export const drawC4Shape = function (elem, c4Shape, conf) { c4Shape.y + c4Shape.descr.Y, c4Shape.width, c4Shape.height, - { fill: '#FFFFFF' }, + { fill: fontColor }, textFontConf ); }