Merge pull request #3038 from pinghe/develop
Add C4 Diagram. Compatible with C4-PlantUML syntax.
This commit is contained in:
commit
3300ad09f3
159
demos/index.html
159
demos/index.html
|
@ -20,6 +20,165 @@
|
|||
</div>
|
||||
|
||||
<hr />
|
||||
<div class="mermaid">
|
||||
C4Context
|
||||
title System Context diagram for Internet Banking System
|
||||
Enterprise_Boundary(b0, "BankBoundary0") {
|
||||
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
|
||||
Person(customerB, "Banking Customer B")
|
||||
Person_Ext(customerC, "Banking Customer C", "desc")
|
||||
|
||||
Person(customerD, "Banking Customer D", "A customer of the bank, <br/> with personal bank accounts.")
|
||||
|
||||
System(SystemAA, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.")
|
||||
|
||||
Enterprise_Boundary(b1, "BankBoundary") {
|
||||
|
||||
SystemDb_Ext(SystemE, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
||||
|
||||
System_Boundary(b2, "BankBoundary2") {
|
||||
System(SystemA, "Banking System A")
|
||||
System(SystemB, "Banking System B", "A system of the bank, with personal bank accounts. next line.")
|
||||
}
|
||||
|
||||
System_Ext(SystemC, "E-mail system", "The internal Microsoft Exchange e-mail system.")
|
||||
SystemDb(SystemD, "Banking System D Database", "A system of the bank, with personal bank accounts.")
|
||||
|
||||
Boundary(b3, "BankBoundary3", "boundary") {
|
||||
SystemQueue(SystemF, "Banking System F Queue", "A system of the bank.")
|
||||
SystemQueue_Ext(SystemG, "Banking System G Queue", "A system of the bank, with personal bank accounts.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BiRel(customerA, SystemAA, "Uses")
|
||||
BiRel(SystemAA, SystemE, "Uses")
|
||||
Rel(SystemAA, SystemC, "Sends e-mails", "SMTP")
|
||||
Rel(SystemC, customerA, "Sends e-mails to")
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
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")
|
||||
|
||||
Container_Boundary(c1, "Internet Banking") {
|
||||
Container(spa, "Single-Page App", "JavaScript, Angular", "Provides all the Internet banking functionality to cutomers via their web browser")
|
||||
Container_Ext(mobile_app, "Mobile App", "C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device")
|
||||
Container(web_app, "Web Application", "Java, Spring MVC", "Delivers the static content and the Internet banking SPA")
|
||||
ContainerDb(database, "Database", "SQL Database", "Stores user registration information, hashed auth credentials, access logs, etc.")
|
||||
ContainerDb_Ext(backend_api, "API Application", "Java, Docker Container", "Provides Internet banking functionality via API")
|
||||
|
||||
}
|
||||
|
||||
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")
|
||||
Rel(customer, spa, "Uses", "HTTPS")
|
||||
Rel(customer, mobile_app, "Uses")
|
||||
|
||||
Rel(web_app, spa, "Delivers")
|
||||
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")
|
||||
Rel(backend_api, email_system, "Sends e-mails using", "sync, SMTP")
|
||||
Rel(backend_api, banking_system, "Uses", "sync/async, XML/HTTPS")
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
C4Component
|
||||
title Component diagram for Internet Banking System - API Application
|
||||
|
||||
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
|
||||
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile mobile device.")
|
||||
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
|
||||
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
||||
|
||||
Container_Boundary(api, "API Application") {
|
||||
Component(sign, "Sign In Controller", "MVC Rest Controlle", "Allows users to sign in to the internet banking system")
|
||||
Component(accounts, "Accounts Summary Controller", "MVC Rest Controller", "Provides customers with a summary of their bank accounts")
|
||||
Component(security, "Security Component", "Spring Bean", "Provides functionality related to singing in, changing passwords, etc.")
|
||||
Component(mbsfacade, "Mainframe Banking System Facade", "Spring Bean", "A facade onto the mainframe banking system.")
|
||||
|
||||
Rel(sign, security, "Uses")
|
||||
Rel(accounts, mbsfacade, "Uses")
|
||||
Rel(security, db, "Read & write to", "JDBC")
|
||||
Rel(mbsfacade, mbs, "Uses", "XML/HTTPS")
|
||||
}
|
||||
|
||||
Rel_Back(spa, sign, "Uses", "JSON/HTTPS")
|
||||
Rel(spa, accounts, "Uses", "JSON/HTTPS")
|
||||
|
||||
Rel(ma, sign, "Uses", "JSON/HTTPS")
|
||||
Rel(ma, accounts, "Uses", "JSON/HTTPS")
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
C4Dynamic
|
||||
title Dynamic diagram for Internet Banking System - API Application
|
||||
|
||||
ContainerDb(c4, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
|
||||
Container(c1, "Single-Page Application", "JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser.")
|
||||
Container_Boundary(b, "API Application") {
|
||||
Component(c3, "Security Component", "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.")
|
||||
Component(c2, "Sign In Controller", "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System.")
|
||||
}
|
||||
Rel(c1, c2, "Submits credentials to", "JSON/HTTPS")
|
||||
Rel(c2, c3, "Calls isAuthenticated() on")
|
||||
Rel(c3, c4, "select * from users where username = ?", "JDBC")
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
C4Deployment
|
||||
title Deployment Diagram for Internet Banking System - Live
|
||||
|
||||
Deployment_Node(mob, "Customer's mobile device", "Apple IOS or Android"){
|
||||
Container(mobile, "Mobile App", "Xamarin", "Provides a limited subset of the Internet Banking functionality to customers via their mobile device.")
|
||||
}
|
||||
|
||||
Deployment_Node(comp, "Customer's computer", "Mircosoft Windows or Apple macOS"){
|
||||
Deployment_Node(browser, "Web Browser", "Google Chrome, Mozilla Firefox,<br/> Apple Safari or Microsoft Edge"){
|
||||
Container(spa, "Single Page Application", "JavaScript and Angular", "Provides all of the Internet Banking functionality to customers via their web browser.")
|
||||
}
|
||||
}
|
||||
|
||||
Deployment_Node(plc, "Big Bank plc", "Big Bank plc data center"){
|
||||
Deployment_Node(dn, "bigbank-api*** x8", "Ubuntu 16.04 LTS"){
|
||||
Deployment_Node(apache, "Apache Tomcat", "Apache Tomcat 8.x"){
|
||||
Container(api, "API Application", "Java and Spring MVC", "Provides Internet Banking functionality via a JSON/HTTPS API.")
|
||||
}
|
||||
}
|
||||
Deployment_Node(bb2, "bigbank-web*** x4", "Ubuntu 16.04 LTS"){
|
||||
Deployment_Node(apache2, "Apache Tomcat", "Apache Tomcat 8.x"){
|
||||
Container(web, "Web Application", "Java and Spring MVC", "Delivers the static content and the Internet Banking single page application.")
|
||||
}
|
||||
}
|
||||
Deployment_Node(bigbankdb01, "bigbank-db01", "Ubuntu 16.04 LTS"){
|
||||
Deployment_Node(oracle, "Oracle - Primary", "Oracle 12c"){
|
||||
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
|
||||
}
|
||||
}
|
||||
Deployment_Node(bigbankdb02, "bigbank-db02", "Ubuntu 16.04 LTS") {
|
||||
Deployment_Node(oracle2, "Oracle - Secondary", "Oracle 12c") {
|
||||
ContainerDb(db2, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rel(mobile, api, "Makes API calls to", "json/HTTPS")
|
||||
Rel(spa, api, "Makes API calls to", "json/HTTPS")
|
||||
Rel_U(web, spa, "Delivers to the customer's web browser")
|
||||
Rel(api, db, "Reads from and writes to", "JDBC")
|
||||
Rel(api, db2, "Reads from and writes to", "JDBC")
|
||||
Rel_R(db, db2, "Replicates data to")
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="mermaid">
|
||||
pie
|
||||
title Key elements in Product X
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import c4Db from './diagrams/c4/c4Db';
|
||||
import c4Renderer from './diagrams/c4/c4Renderer';
|
||||
import c4Parser from './diagrams/c4/parser/c4Diagram';
|
||||
import classDb from './diagrams/class/classDb';
|
||||
import classRenderer from './diagrams/class/classRenderer';
|
||||
import classRendererV2 from './diagrams/class/classRenderer-v2';
|
||||
|
@ -49,6 +52,12 @@ class Diagram {
|
|||
this.type = utils.detectType(txt, cnf);
|
||||
log.debug('Type ' + this.type);
|
||||
switch (this.type) {
|
||||
case 'c4':
|
||||
this.parser = c4Parser;
|
||||
this.parser.parser.yy = c4Db;
|
||||
this.db = c4Db;
|
||||
this.renderer = c4Renderer;
|
||||
break;
|
||||
case 'gitGraph':
|
||||
this.parser = gitGraphParser;
|
||||
this.parser.parser.yy = gitGraphAst;
|
||||
|
|
|
@ -1059,6 +1059,405 @@ const config = {
|
|||
showCommitLabel: true,
|
||||
showBranches: true,
|
||||
},
|
||||
|
||||
/** The object containing configurations specific for c4 diagrams */
|
||||
c4: {
|
||||
useWidth: undefined,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ |
|
||||
* | diagramMarginX | Margin to the right and left of the c4 diagram | Integer | Required | Any Positive Value |
|
||||
*
|
||||
* **Notes:** Default value: 50
|
||||
*/
|
||||
diagramMarginX: 50,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | -------------- | ------------------------------------------- | ------- | -------- | ------------------ |
|
||||
* | diagramMarginY | Margin to the over and under the c4 diagram | Integer | Required | Any Positive Value |
|
||||
*
|
||||
* **Notes:** Default value: 10
|
||||
*/
|
||||
diagramMarginY: 10,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | ----------- | --------------------- | ------- | -------- | ------------------ |
|
||||
* | shapeMargin | Margin between shapes | Integer | Required | Any Positive Value |
|
||||
*
|
||||
* **Notes:** Default value: 50
|
||||
*/
|
||||
c4ShapeMargin: 50,
|
||||
|
||||
c4ShapePadding: 20,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | --------- | --------------------- | ------- | -------- | ------------------ |
|
||||
* | width | Width of person boxes | Integer | Required | Any Positive Value |
|
||||
*
|
||||
* **Notes:** Default value: 216
|
||||
*/
|
||||
width: 216,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | --------- | ---------------------- | ------- | -------- | ------------------ |
|
||||
* | height | Height of person boxes | Integer | Required | Any Positive Value |
|
||||
*
|
||||
* **Notes:** Default value: 60
|
||||
*/
|
||||
height: 60,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | --------- | ------------------------ | ------- | -------- | ------------------ |
|
||||
* | boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value |
|
||||
*
|
||||
* **Notes:** Default value: 10
|
||||
*/
|
||||
boxMargin: 10,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | ----------- | ----------- | ------- | -------- | ----------- |
|
||||
* | useMaxWidth | See Notes | boolean | Required | true, false |
|
||||
*
|
||||
* **Notes:** When this flag is set to true, the height and width is set to 100% and is then
|
||||
* scaling with the available space. If set to false, the absolute space required is used.
|
||||
*
|
||||
* Default value: true
|
||||
*/
|
||||
useMaxWidth: true,
|
||||
|
||||
c4ShapeInRow: 4,
|
||||
nextLinePaddingX: 0,
|
||||
|
||||
c4BoundaryInRow: 2,
|
||||
|
||||
personFontSize: 14,
|
||||
personFontFamily: '"Open Sans", sans-serif',
|
||||
personFontWeight: 'normal',
|
||||
|
||||
external_personFontSize: 14,
|
||||
external_personFontFamily: '"Open Sans", sans-serif',
|
||||
external_personFontWeight: 'normal',
|
||||
|
||||
systemFontSize: 14,
|
||||
systemFontFamily: '"Open Sans", sans-serif',
|
||||
systemFontWeight: 'normal',
|
||||
|
||||
external_systemFontSize: 14,
|
||||
external_systemFontFamily: '"Open Sans", sans-serif',
|
||||
external_systemFontWeight: 'normal',
|
||||
|
||||
system_dbFontSize: 14,
|
||||
system_dbFontFamily: '"Open Sans", sans-serif',
|
||||
system_dbFontWeight: 'normal',
|
||||
|
||||
external_system_dbFontSize: 14,
|
||||
external_system_dbFontFamily: '"Open Sans", sans-serif',
|
||||
external_system_dbFontWeight: 'normal',
|
||||
|
||||
system_queueFontSize: 14,
|
||||
system_queueFontFamily: '"Open Sans", sans-serif',
|
||||
system_queueFontWeight: 'normal',
|
||||
|
||||
external_system_queueFontSize: 14,
|
||||
external_system_queueFontFamily: '"Open Sans", sans-serif',
|
||||
external_system_queueFontWeight: 'normal',
|
||||
|
||||
boundaryFontSize: 14,
|
||||
boundaryFontFamily: '"Open Sans", sans-serif',
|
||||
boundaryFontWeight: 'normal',
|
||||
|
||||
messageFontSize: 12,
|
||||
messageFontFamily: '"Open Sans", sans-serif',
|
||||
messageFontWeight: 'normal',
|
||||
|
||||
containerFontSize: 14,
|
||||
containerFontFamily: '"Open Sans", sans-serif',
|
||||
containerFontWeight: 'normal',
|
||||
|
||||
external_containerFontSize: 14,
|
||||
external_containerFontFamily: '"Open Sans", sans-serif',
|
||||
external_containerFontWeight: 'normal',
|
||||
|
||||
container_dbFontSize: 14,
|
||||
container_dbFontFamily: '"Open Sans", sans-serif',
|
||||
container_dbFontWeight: 'normal',
|
||||
|
||||
external_container_dbFontSize: 14,
|
||||
external_container_dbFontFamily: '"Open Sans", sans-serif',
|
||||
external_container_dbFontWeight: 'normal',
|
||||
|
||||
container_queueFontSize: 14,
|
||||
container_queueFontFamily: '"Open Sans", sans-serif',
|
||||
container_queueFontWeight: 'normal',
|
||||
|
||||
external_container_queueFontSize: 14,
|
||||
external_container_queueFontFamily: '"Open Sans", sans-serif',
|
||||
external_container_queueFontWeight: 'normal',
|
||||
|
||||
componentFontSize: 14,
|
||||
componentFontFamily: '"Open Sans", sans-serif',
|
||||
componentFontWeight: 'normal',
|
||||
|
||||
external_componentFontSize: 14,
|
||||
external_componentFontFamily: '"Open Sans", sans-serif',
|
||||
external_componentFontWeight: 'normal',
|
||||
|
||||
component_dbFontSize: 14,
|
||||
component_dbFontFamily: '"Open Sans", sans-serif',
|
||||
component_dbFontWeight: 'normal',
|
||||
|
||||
external_component_dbFontSize: 14,
|
||||
external_component_dbFontFamily: '"Open Sans", sans-serif',
|
||||
external_component_dbFontWeight: 'normal',
|
||||
|
||||
component_queueFontSize: 14,
|
||||
component_queueFontFamily: '"Open Sans", sans-serif',
|
||||
component_queueFontWeight: 'normal',
|
||||
|
||||
external_component_queueFontSize: 14,
|
||||
external_component_queueFontFamily: '"Open Sans", sans-serif',
|
||||
external_component_queueFontWeight: 'normal',
|
||||
|
||||
/**
|
||||
* This sets the auto-wrap state for the diagram
|
||||
*
|
||||
* **Notes:** Default value: true.
|
||||
*/
|
||||
wrap: true,
|
||||
|
||||
/**
|
||||
* This sets the auto-wrap padding for the diagram (sides only)
|
||||
*
|
||||
* **Notes:** Default value: 0.
|
||||
*/
|
||||
wrapPadding: 10,
|
||||
|
||||
personFont: function () {
|
||||
return {
|
||||
fontFamily: this.personFontFamily,
|
||||
fontSize: this.personFontSize,
|
||||
fontWeight: this.personFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_personFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_personFontFamily,
|
||||
fontSize: this.external_personFontSize,
|
||||
fontWeight: this.external_personFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
systemFont: function () {
|
||||
return {
|
||||
fontFamily: this.systemFontFamily,
|
||||
fontSize: this.systemFontSize,
|
||||
fontWeight: this.systemFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_systemFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_systemFontFamily,
|
||||
fontSize: this.external_systemFontSize,
|
||||
fontWeight: this.external_systemFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
system_dbFont: function () {
|
||||
return {
|
||||
fontFamily: this.system_dbFontFamily,
|
||||
fontSize: this.system_dbFontSize,
|
||||
fontWeight: this.system_dbFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_system_dbFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_system_dbFontFamily,
|
||||
fontSize: this.external_system_dbFontSize,
|
||||
fontWeight: this.external_system_dbFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
system_queueFont: function () {
|
||||
return {
|
||||
fontFamily: this.system_queueFontFamily,
|
||||
fontSize: this.system_queueFontSize,
|
||||
fontWeight: this.system_queueFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_system_queueFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_system_queueFontFamily,
|
||||
fontSize: this.external_system_queueFontSize,
|
||||
fontWeight: this.external_system_queueFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
containerFont: function () {
|
||||
return {
|
||||
fontFamily: this.containerFontFamily,
|
||||
fontSize: this.containerFontSize,
|
||||
fontWeight: this.containerFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_containerFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_containerFontFamily,
|
||||
fontSize: this.external_containerFontSize,
|
||||
fontWeight: this.external_containerFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
container_dbFont: function () {
|
||||
return {
|
||||
fontFamily: this.container_dbFontFamily,
|
||||
fontSize: this.container_dbFontSize,
|
||||
fontWeight: this.container_dbFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_container_dbFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_container_dbFontFamily,
|
||||
fontSize: this.external_container_dbFontSize,
|
||||
fontWeight: this.external_container_dbFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
container_queueFont: function () {
|
||||
return {
|
||||
fontFamily: this.container_queueFontFamily,
|
||||
fontSize: this.container_queueFontSize,
|
||||
fontWeight: this.container_queueFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_container_queueFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_container_queueFontFamily,
|
||||
fontSize: this.external_container_queueFontSize,
|
||||
fontWeight: this.external_container_queueFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
componentFont: function () {
|
||||
return {
|
||||
fontFamily: this.componentFontFamily,
|
||||
fontSize: this.componentFontSize,
|
||||
fontWeight: this.componentFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_componentFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_componentFontFamily,
|
||||
fontSize: this.external_componentFontSize,
|
||||
fontWeight: this.external_componentFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
component_dbFont: function () {
|
||||
return {
|
||||
fontFamily: this.component_dbFontFamily,
|
||||
fontSize: this.component_dbFontSize,
|
||||
fontWeight: this.component_dbFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_component_dbFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_component_dbFontFamily,
|
||||
fontSize: this.external_component_dbFontSize,
|
||||
fontWeight: this.external_component_dbFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
component_queueFont: function () {
|
||||
return {
|
||||
fontFamily: this.component_queueFontFamily,
|
||||
fontSize: this.component_queueFontSize,
|
||||
fontWeight: this.component_queueFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
external_component_queueFont: function () {
|
||||
return {
|
||||
fontFamily: this.external_component_queueFontFamily,
|
||||
fontSize: this.external_component_queueFontSize,
|
||||
fontWeight: this.external_component_queueFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
boundaryFont: function () {
|
||||
return {
|
||||
fontFamily: this.boundaryFontFamily,
|
||||
fontSize: this.boundaryFontSize,
|
||||
fontWeight: this.boundaryFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
messageFont: function () {
|
||||
return {
|
||||
fontFamily: this.messageFontFamily,
|
||||
fontSize: this.messageFontSize,
|
||||
fontWeight: this.messageFontWeight,
|
||||
};
|
||||
},
|
||||
|
||||
// ' Colors
|
||||
// ' ##################################
|
||||
person_bg_color: '#08427B',
|
||||
person_border_color: '#073B6F',
|
||||
external_person_bg_color: '#686868',
|
||||
external_person_border_color: '#8A8A8A',
|
||||
system_bg_color: '#1168BD',
|
||||
system_border_color: '#3C7FC0',
|
||||
system_db_bg_color: '#1168BD',
|
||||
system_db_border_color: '#3C7FC0',
|
||||
system_queue_bg_color: '#1168BD',
|
||||
system_queue_border_color: '#3C7FC0',
|
||||
external_system_bg_color: '#999999',
|
||||
external_system_border_color: '#8A8A8A',
|
||||
external_system_db_bg_color: '#999999',
|
||||
external_system_db_border_color: '#8A8A8A',
|
||||
external_system_queue_bg_color: '#999999',
|
||||
external_system_queue_border_color: '#8A8A8A',
|
||||
container_bg_color: '#438DD5',
|
||||
container_border_color: '#3C7FC0',
|
||||
container_db_bg_color: '#438DD5',
|
||||
container_db_border_color: '#3C7FC0',
|
||||
container_queue_bg_color: '#438DD5',
|
||||
container_queue_border_color: '#3C7FC0',
|
||||
external_container_bg_color: '#B3B3B3',
|
||||
external_container_border_color: '#A6A6A6',
|
||||
external_container_db_bg_color: '#B3B3B3',
|
||||
external_container_db_border_color: '#A6A6A6',
|
||||
external_container_queue_bg_color: '#B3B3B3',
|
||||
external_container_queue_border_color: '#A6A6A6',
|
||||
component_bg_color: '#85BBF0',
|
||||
component_border_color: '#78A8D8',
|
||||
component_db_bg_color: '#85BBF0',
|
||||
component_db_border_color: '#78A8D8',
|
||||
component_queue_bg_color: '#85BBF0',
|
||||
component_queue_border_color: '#78A8D8',
|
||||
external_component_bg_color: '#CCCCCC',
|
||||
external_component_border_color: '#BFBFBF',
|
||||
external_component_db_bg_color: '#CCCCCC',
|
||||
external_component_db_border_color: '#BFBFBF',
|
||||
external_component_queue_bg_color: '#CCCCCC',
|
||||
external_component_queue_border_color: '#BFBFBF',
|
||||
},
|
||||
};
|
||||
|
||||
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
|
||||
|
|
|
@ -0,0 +1,486 @@
|
|||
import mermaidAPI from '../../mermaidAPI';
|
||||
import * as configApi from '../../config';
|
||||
import { log } from '../../logger';
|
||||
import { sanitizeText } from '../common/common';
|
||||
|
||||
let c4ShapeArray = [];
|
||||
let boundaryParseStack = [''];
|
||||
let currentBoundaryParse = 'global';
|
||||
let parentBoundaryParse = '';
|
||||
let boundarys = [
|
||||
{
|
||||
alias: 'global',
|
||||
label: { text: 'global' },
|
||||
type: { text: 'global' },
|
||||
tags: null,
|
||||
link: null,
|
||||
parentBoundary: '',
|
||||
},
|
||||
];
|
||||
let rels = [];
|
||||
let title = '';
|
||||
let wrapEnabled = false;
|
||||
let description = '';
|
||||
var c4Type;
|
||||
|
||||
export const getC4Type = function () {
|
||||
return c4Type;
|
||||
};
|
||||
|
||||
export const setC4Type = function (c4TypeParam) {
|
||||
let sanitizedText = sanitizeText(c4TypeParam, configApi.getConfig());
|
||||
c4Type = sanitizedText;
|
||||
};
|
||||
|
||||
export const parseDirective = function (statement, context, type) {
|
||||
mermaidAPI.parseDirective(this, statement, context, type);
|
||||
};
|
||||
|
||||
//type, from, to, label, ?techn, ?descr, ?sprite, ?tags, $link
|
||||
export const addRel = function (type, from, to, label, techn, descr, sprite, tags, link) {
|
||||
// Don't allow label nulling
|
||||
if (
|
||||
type === undefined ||
|
||||
type === null ||
|
||||
from === undefined ||
|
||||
from === null ||
|
||||
to === undefined ||
|
||||
to === null ||
|
||||
label === undefined ||
|
||||
label === null
|
||||
)
|
||||
return;
|
||||
|
||||
let rel = {};
|
||||
const old = rels.find((rel) => rel.from === from && rel.to === to);
|
||||
if (old) {
|
||||
rel = old;
|
||||
} else {
|
||||
rels.push(rel);
|
||||
}
|
||||
|
||||
rel.type = type;
|
||||
rel.from = from;
|
||||
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 };
|
||||
}
|
||||
|
||||
// rel.techn = techn;
|
||||
rel.sprite = sprite;
|
||||
rel.tags = tags;
|
||||
rel.link = link;
|
||||
rel.wrap = autoWrap();
|
||||
};
|
||||
|
||||
//type, alias, label, ?descr, ?sprite, ?tags, $link
|
||||
export const addPersonOrSystem = function (typeC4Shape, alias, label, descr, sprite, tags, link) {
|
||||
// Don't allow label nulling
|
||||
if (alias === null || label === null) return;
|
||||
|
||||
let personOrSystem = {};
|
||||
const old = c4ShapeArray.find((personOrSystem) => personOrSystem.alias === alias);
|
||||
if (old && alias === old.alias) {
|
||||
personOrSystem = old;
|
||||
} else {
|
||||
personOrSystem.alias = alias;
|
||||
c4ShapeArray.push(personOrSystem);
|
||||
}
|
||||
|
||||
// Don't allow null labels, either
|
||||
if (label === undefined || label === null) {
|
||||
personOrSystem.label = { text: '' };
|
||||
} else {
|
||||
personOrSystem.label = { text: label };
|
||||
}
|
||||
|
||||
if (descr === undefined || descr === null) {
|
||||
personOrSystem.descr = { text: '' };
|
||||
} else {
|
||||
personOrSystem.descr = { text: descr };
|
||||
}
|
||||
|
||||
personOrSystem.wrap = autoWrap();
|
||||
personOrSystem.sprite = sprite;
|
||||
personOrSystem.tags = tags;
|
||||
personOrSystem.link = link;
|
||||
personOrSystem.typeC4Shape = { text: typeC4Shape };
|
||||
personOrSystem.parentBoundary = currentBoundaryParse;
|
||||
};
|
||||
|
||||
//type, alias, label, ?techn, ?descr ?sprite, ?tags, $link
|
||||
export const addContainer = function (typeC4Shape, alias, label, techn, descr, sprite, tags, link) {
|
||||
// Don't allow label nulling
|
||||
if (alias === null || label === null) return;
|
||||
|
||||
let container = {};
|
||||
const old = c4ShapeArray.find((container) => container.alias === alias);
|
||||
if (old && alias === old.alias) {
|
||||
container = old;
|
||||
} else {
|
||||
container.alias = alias;
|
||||
c4ShapeArray.push(container);
|
||||
}
|
||||
|
||||
// Don't allow null labels, either
|
||||
if (label === undefined || label === null) {
|
||||
container.label = { text: '' };
|
||||
} else {
|
||||
container.label = { text: label };
|
||||
}
|
||||
|
||||
if (techn === undefined || techn === null) {
|
||||
container.techn = { text: '' };
|
||||
} else {
|
||||
container.techn = { text: techn };
|
||||
}
|
||||
|
||||
if (descr === undefined || descr === null) {
|
||||
container.descr = { text: '' };
|
||||
} else {
|
||||
container.descr = { text: descr };
|
||||
}
|
||||
|
||||
container.sprite = sprite;
|
||||
container.tags = tags;
|
||||
container.link = link;
|
||||
container.wrap = autoWrap();
|
||||
container.typeC4Shape = { text: typeC4Shape };
|
||||
container.parentBoundary = currentBoundaryParse;
|
||||
};
|
||||
|
||||
//type, alias, label, ?techn, ?descr ?sprite, ?tags, $link
|
||||
export const addComponent = function (typeC4Shape, alias, label, techn, descr, sprite, tags, link) {
|
||||
// Don't allow label nulling
|
||||
if (alias === null || label === null) return;
|
||||
|
||||
let component = {};
|
||||
const old = c4ShapeArray.find((component) => component.alias === alias);
|
||||
if (old && alias === old.alias) {
|
||||
component = old;
|
||||
} else {
|
||||
component.alias = alias;
|
||||
c4ShapeArray.push(component);
|
||||
}
|
||||
|
||||
// Don't allow null labels, either
|
||||
if (label === undefined || label === null) {
|
||||
component.label = { text: '' };
|
||||
} else {
|
||||
component.label = { text: label };
|
||||
}
|
||||
|
||||
if (techn === undefined || techn === null) {
|
||||
component.techn = { text: '' };
|
||||
} else {
|
||||
component.techn = { text: techn };
|
||||
}
|
||||
|
||||
if (descr === undefined || descr === null) {
|
||||
component.descr = { text: '' };
|
||||
} else {
|
||||
component.descr = { text: descr };
|
||||
}
|
||||
|
||||
component.sprite = sprite;
|
||||
component.tags = tags;
|
||||
component.link = link;
|
||||
component.wrap = autoWrap();
|
||||
component.typeC4Shape = { text: typeC4Shape };
|
||||
component.parentBoundary = currentBoundaryParse;
|
||||
};
|
||||
|
||||
//alias, label, ?type, ?tags, $link
|
||||
export const addPersonOrSystemBoundary = function (alias, label, type, tags, link) {
|
||||
// if (parentBoundary === null) return;
|
||||
|
||||
// Don't allow label nulling
|
||||
if (alias === null || label === null) return;
|
||||
|
||||
let boundary = {};
|
||||
const old = boundarys.find((boundary) => boundary.alias === alias);
|
||||
if (old && alias === old.alias) {
|
||||
boundary = old;
|
||||
} else {
|
||||
boundary.alias = alias;
|
||||
boundarys.push(boundary);
|
||||
}
|
||||
|
||||
// Don't allow null labels, either
|
||||
if (label === undefined || label === null) {
|
||||
boundary.label = { text: '' };
|
||||
} else {
|
||||
boundary.label = { text: label };
|
||||
}
|
||||
|
||||
if (type === undefined || type === null) {
|
||||
boundary.type = { text: 'system' };
|
||||
} else {
|
||||
boundary.type = { text: type };
|
||||
}
|
||||
|
||||
boundary.tags = tags;
|
||||
boundary.link = link;
|
||||
boundary.parentBoundary = currentBoundaryParse;
|
||||
boundary.wrap = autoWrap();
|
||||
|
||||
parentBoundaryParse = currentBoundaryParse;
|
||||
currentBoundaryParse = alias;
|
||||
boundaryParseStack.push(parentBoundaryParse);
|
||||
};
|
||||
|
||||
//alias, label, ?type, ?tags, $link
|
||||
export const addContainerBoundary = function (alias, label, type, tags, link) {
|
||||
// if (parentBoundary === null) return;
|
||||
|
||||
// Don't allow label nulling
|
||||
if (alias === null || label === null) return;
|
||||
|
||||
let boundary = {};
|
||||
const old = boundarys.find((boundary) => boundary.alias === alias);
|
||||
if (old && alias === old.alias) {
|
||||
boundary = old;
|
||||
} else {
|
||||
boundary.alias = alias;
|
||||
boundarys.push(boundary);
|
||||
}
|
||||
|
||||
// Don't allow null labels, either
|
||||
if (label === undefined || label === null) {
|
||||
boundary.label = { text: '' };
|
||||
} else {
|
||||
boundary.label = { text: label };
|
||||
}
|
||||
|
||||
if (type === undefined || type === null) {
|
||||
boundary.type = { text: 'container' };
|
||||
} else {
|
||||
boundary.type = { text: type };
|
||||
}
|
||||
|
||||
boundary.tags = tags;
|
||||
boundary.link = link;
|
||||
boundary.parentBoundary = currentBoundaryParse;
|
||||
boundary.wrap = autoWrap();
|
||||
|
||||
parentBoundaryParse = currentBoundaryParse;
|
||||
currentBoundaryParse = alias;
|
||||
boundaryParseStack.push(parentBoundaryParse);
|
||||
};
|
||||
|
||||
//alias, label, ?type, ?descr, ?sprite, ?tags, $link
|
||||
export const addDeploymentNode = function (
|
||||
nodeType,
|
||||
alias,
|
||||
label,
|
||||
type,
|
||||
descr,
|
||||
sprite,
|
||||
tags,
|
||||
link
|
||||
) {
|
||||
// if (parentBoundary === null) return;
|
||||
|
||||
// Don't allow label nulling
|
||||
if (alias === null || label === null) return;
|
||||
|
||||
let boundary = {};
|
||||
const old = boundarys.find((boundary) => boundary.alias === alias);
|
||||
if (old && alias === old.alias) {
|
||||
boundary = old;
|
||||
} else {
|
||||
boundary.alias = alias;
|
||||
boundarys.push(boundary);
|
||||
}
|
||||
|
||||
// Don't allow null labels, either
|
||||
if (label === undefined || label === null) {
|
||||
boundary.label = { text: '' };
|
||||
} else {
|
||||
boundary.label = { text: label };
|
||||
}
|
||||
|
||||
if (type === undefined || type === null) {
|
||||
boundary.type = { text: 'node' };
|
||||
} else {
|
||||
boundary.type = { text: type };
|
||||
}
|
||||
|
||||
if (descr === undefined || descr === null) {
|
||||
boundary.descr = { text: '' };
|
||||
} else {
|
||||
boundary.descr = { text: type };
|
||||
}
|
||||
|
||||
boundary.tags = tags;
|
||||
boundary.link = link;
|
||||
boundary.nodeType = nodeType;
|
||||
boundary.parentBoundary = currentBoundaryParse;
|
||||
boundary.wrap = autoWrap();
|
||||
|
||||
parentBoundaryParse = currentBoundaryParse;
|
||||
currentBoundaryParse = alias;
|
||||
boundaryParseStack.push(parentBoundaryParse);
|
||||
};
|
||||
|
||||
export const popBoundaryParseStack = function () {
|
||||
currentBoundaryParse = parentBoundaryParse;
|
||||
boundaryParseStack.pop();
|
||||
parentBoundaryParse = boundaryParseStack.pop();
|
||||
boundaryParseStack.push(parentBoundaryParse);
|
||||
};
|
||||
|
||||
export const getCurrentBoundaryParse = function () {
|
||||
return currentBoundaryParse;
|
||||
};
|
||||
|
||||
export const getParentBoundaryParse = function () {
|
||||
return parentBoundaryParse;
|
||||
};
|
||||
|
||||
export const getC4ShapeArray = function (parentBoundary) {
|
||||
if (parentBoundary === undefined || parentBoundary === null) return c4ShapeArray;
|
||||
else
|
||||
return c4ShapeArray.filter((personOrSystem) => {
|
||||
return personOrSystem.parentBoundary === parentBoundary;
|
||||
});
|
||||
};
|
||||
export const getC4Shape = function (alias) {
|
||||
return c4ShapeArray.find((personOrSystem) => personOrSystem.alias === alias);
|
||||
};
|
||||
export const getC4ShapeKeys = function (parentBoundary) {
|
||||
return Object.keys(getC4ShapeArray(parentBoundary));
|
||||
};
|
||||
|
||||
export const getBoundarys = function (parentBoundary) {
|
||||
if (parentBoundary === undefined || parentBoundary === null) return boundarys;
|
||||
else return boundarys.filter((boundary) => boundary.parentBoundary === parentBoundary);
|
||||
};
|
||||
|
||||
export const getRels = function () {
|
||||
return rels;
|
||||
};
|
||||
|
||||
export const getTitle = function () {
|
||||
return title;
|
||||
};
|
||||
|
||||
export const setWrap = function (wrapSetting) {
|
||||
wrapEnabled = wrapSetting;
|
||||
};
|
||||
|
||||
export const autoWrap = function () {
|
||||
return wrapEnabled;
|
||||
};
|
||||
|
||||
export const clear = function () {
|
||||
c4ShapeArray = [];
|
||||
boundarys = [
|
||||
{
|
||||
alias: 'global',
|
||||
label: { text: 'global' },
|
||||
type: { text: 'global' },
|
||||
tags: null,
|
||||
link: null,
|
||||
parentBoundary: '',
|
||||
},
|
||||
];
|
||||
parentBoundaryParse = '';
|
||||
currentBoundaryParse = 'global';
|
||||
boundaryParseStack = [''];
|
||||
rels = [];
|
||||
};
|
||||
|
||||
export const LINETYPE = {
|
||||
SOLID: 0,
|
||||
DOTTED: 1,
|
||||
NOTE: 2,
|
||||
SOLID_CROSS: 3,
|
||||
DOTTED_CROSS: 4,
|
||||
SOLID_OPEN: 5,
|
||||
DOTTED_OPEN: 6,
|
||||
LOOP_START: 10,
|
||||
LOOP_END: 11,
|
||||
ALT_START: 12,
|
||||
ALT_ELSE: 13,
|
||||
ALT_END: 14,
|
||||
OPT_START: 15,
|
||||
OPT_END: 16,
|
||||
ACTIVE_START: 17,
|
||||
ACTIVE_END: 18,
|
||||
PAR_START: 19,
|
||||
PAR_AND: 20,
|
||||
PAR_END: 21,
|
||||
RECT_START: 22,
|
||||
RECT_END: 23,
|
||||
SOLID_POINT: 24,
|
||||
DOTTED_POINT: 25,
|
||||
};
|
||||
|
||||
export const ARROWTYPE = {
|
||||
FILLED: 0,
|
||||
OPEN: 1,
|
||||
};
|
||||
|
||||
export const PLACEMENT = {
|
||||
LEFTOF: 0,
|
||||
RIGHTOF: 1,
|
||||
OVER: 2,
|
||||
};
|
||||
|
||||
export const setTitle = function (txt) {
|
||||
let sanitizedText = sanitizeText(txt, configApi.getConfig());
|
||||
title = sanitizedText;
|
||||
};
|
||||
|
||||
const setAccDescription = function (description_lex) {
|
||||
let sanitizedText = sanitizeText(description_lex, configApi.getConfig());
|
||||
description = sanitizedText;
|
||||
};
|
||||
|
||||
const getAccDescription = function () {
|
||||
return description;
|
||||
};
|
||||
|
||||
export default {
|
||||
addPersonOrSystem,
|
||||
addPersonOrSystemBoundary,
|
||||
addContainer,
|
||||
addContainerBoundary,
|
||||
addComponent,
|
||||
addDeploymentNode,
|
||||
popBoundaryParseStack,
|
||||
addRel,
|
||||
autoWrap,
|
||||
setWrap,
|
||||
getC4ShapeArray,
|
||||
getC4Shape,
|
||||
getC4ShapeKeys,
|
||||
getBoundarys,
|
||||
getCurrentBoundaryParse,
|
||||
getParentBoundaryParse,
|
||||
getRels,
|
||||
getTitle,
|
||||
getC4Type,
|
||||
getAccDescription,
|
||||
setAccDescription,
|
||||
parseDirective,
|
||||
getConfig: () => configApi.getConfig().c4,
|
||||
clear,
|
||||
LINETYPE,
|
||||
ARROWTYPE,
|
||||
PLACEMENT,
|
||||
setTitle,
|
||||
setC4Type,
|
||||
// apply,
|
||||
};
|
|
@ -0,0 +1,670 @@
|
|||
import { select } from 'd3';
|
||||
import svgDraw, { drawText, fixLifeLineHeights } from './svgDraw';
|
||||
import { log } from '../../logger';
|
||||
import { parser } from './parser/c4Diagram';
|
||||
import common from '../common/common';
|
||||
import c4Db from './c4Db';
|
||||
import * as configApi from '../../config';
|
||||
import utils, {
|
||||
wrapLabel,
|
||||
calculateTextWidth,
|
||||
calculateTextHeight,
|
||||
assignWithDepth,
|
||||
configureSvgSize,
|
||||
} from '../../utils';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
|
||||
let globalBoundaryMaxX = 0,
|
||||
globalBoundaryMaxY = 0;
|
||||
|
||||
parser.yy = c4Db;
|
||||
|
||||
let conf = {};
|
||||
|
||||
class Bounds {
|
||||
constructor() {
|
||||
this.name = '';
|
||||
this.data = {};
|
||||
this.data.startx = undefined;
|
||||
this.data.stopx = undefined;
|
||||
this.data.starty = undefined;
|
||||
this.data.stopy = undefined;
|
||||
this.data.widthLimit = undefined;
|
||||
|
||||
this.nextData = {};
|
||||
this.nextData.startx = undefined;
|
||||
this.nextData.stopx = undefined;
|
||||
this.nextData.starty = undefined;
|
||||
this.nextData.stopy = undefined;
|
||||
this.nextData.cnt = 0;
|
||||
|
||||
setConf(parser.yy.getConfig());
|
||||
}
|
||||
|
||||
setData(startx, stopx, starty, stopy) {
|
||||
this.nextData.startx = this.data.startx = startx;
|
||||
this.nextData.stopx = this.data.stopx = stopx;
|
||||
this.nextData.starty = this.data.starty = starty;
|
||||
this.nextData.stopy = this.data.stopy = stopy;
|
||||
}
|
||||
|
||||
updateVal(obj, key, val, fun) {
|
||||
if (typeof obj[key] === 'undefined') {
|
||||
obj[key] = val;
|
||||
} else {
|
||||
obj[key] = fun(val, obj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
insert(c4Shape) {
|
||||
this.nextData.cnt = this.nextData.cnt + 1;
|
||||
let _startx =
|
||||
this.nextData.startx === this.nextData.stopx
|
||||
? this.nextData.stopx + c4Shape.margin
|
||||
: this.nextData.stopx + c4Shape.margin * 2;
|
||||
let _stopx = _startx + c4Shape.width;
|
||||
let _starty = this.nextData.starty + c4Shape.margin * 2;
|
||||
let _stopy = _starty + c4Shape.height;
|
||||
if (
|
||||
_startx >= this.data.widthLimit ||
|
||||
_stopx >= this.data.widthLimit ||
|
||||
this.nextData.cnt > conf.c4ShapeInRow
|
||||
) {
|
||||
_startx = this.nextData.startx + c4Shape.margin + conf.nextLinePaddingX;
|
||||
_starty = this.nextData.stopy + c4Shape.margin * 2;
|
||||
|
||||
this.nextData.stopx = _stopx = _startx + c4Shape.width;
|
||||
this.nextData.starty = this.nextData.stopy;
|
||||
this.nextData.stopy = _stopy = _starty + c4Shape.height;
|
||||
this.nextData.cnt = 1;
|
||||
}
|
||||
|
||||
c4Shape.x = _startx;
|
||||
c4Shape.y = _starty;
|
||||
|
||||
this.updateVal(this.data, 'startx', _startx, Math.min);
|
||||
this.updateVal(this.data, 'starty', _starty, Math.min);
|
||||
this.updateVal(this.data, 'stopx', _stopx, Math.max);
|
||||
this.updateVal(this.data, 'stopy', _stopy, Math.max);
|
||||
|
||||
this.updateVal(this.nextData, 'startx', _startx, Math.min);
|
||||
this.updateVal(this.nextData, 'starty', _starty, Math.min);
|
||||
this.updateVal(this.nextData, 'stopx', _stopx, Math.max);
|
||||
this.updateVal(this.nextData, 'stopy', _stopy, Math.max);
|
||||
}
|
||||
|
||||
init() {
|
||||
this.name = '';
|
||||
this.data = {
|
||||
startx: undefined,
|
||||
stopx: undefined,
|
||||
starty: undefined,
|
||||
stopy: undefined,
|
||||
widthLimit: undefined,
|
||||
};
|
||||
this.nextData = {
|
||||
startx: undefined,
|
||||
stopx: undefined,
|
||||
starty: undefined,
|
||||
stopy: undefined,
|
||||
cnt: 0,
|
||||
};
|
||||
setConf(parser.yy.getConfig());
|
||||
}
|
||||
|
||||
bumpLastMargin(margin) {
|
||||
this.data.stopx += margin;
|
||||
this.data.stopy += margin;
|
||||
}
|
||||
}
|
||||
|
||||
export const setConf = function (cnf) {
|
||||
assignWithDepth(conf, cnf);
|
||||
|
||||
if (cnf.fontFamily) {
|
||||
conf.personFontFamily = conf.systemFontFamily = conf.messageFontFamily = cnf.fontFamily;
|
||||
}
|
||||
if (cnf.fontSize) {
|
||||
conf.personFontSize = conf.systemFontSize = conf.messageFontSize = cnf.fontSize;
|
||||
}
|
||||
if (cnf.fontWeight) {
|
||||
conf.personFontWeight = conf.systemFontWeight = conf.messageFontWeight = cnf.fontWeight;
|
||||
}
|
||||
};
|
||||
|
||||
const c4ShapeFont = (cnf, typeC4Shape) => {
|
||||
return {
|
||||
fontFamily: cnf[typeC4Shape + 'FontFamily'],
|
||||
fontSize: cnf[typeC4Shape + 'FontSize'],
|
||||
fontWeight: cnf[typeC4Shape + 'FontWeight'],
|
||||
};
|
||||
};
|
||||
|
||||
const boundaryFont = (cnf) => {
|
||||
return {
|
||||
fontFamily: cnf.boundaryFontFamily,
|
||||
fontSize: cnf.boundaryFontSize,
|
||||
fontWeight: cnf.boundaryFontWeight,
|
||||
};
|
||||
};
|
||||
|
||||
const messageFont = (cnf) => {
|
||||
return {
|
||||
fontFamily: cnf.messageFontFamily,
|
||||
fontSize: cnf.messageFontSize,
|
||||
fontWeight: cnf.messageFontWeight,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @param textType
|
||||
* @param c4Shape
|
||||
* @param c4ShapeTextWrap
|
||||
* @param textConf
|
||||
* @param textLimitWidth
|
||||
*/
|
||||
function calcC4ShapeTextWH(textType, c4Shape, c4ShapeTextWrap, textConf, textLimitWidth) {
|
||||
if (!c4Shape[textType].width) {
|
||||
if (c4ShapeTextWrap) {
|
||||
c4Shape[textType].text = wrapLabel(c4Shape[textType].text, textLimitWidth, textConf);
|
||||
c4Shape[textType].textLines = c4Shape[textType].text.split(common.lineBreakRegex).length;
|
||||
// c4Shape[textType].width = calculateTextWidth(c4Shape[textType].text, textConf);
|
||||
c4Shape[textType].width = textLimitWidth;
|
||||
// c4Shape[textType].height = c4Shape[textType].textLines * textConf.fontSize;
|
||||
c4Shape[textType].height = calculateTextHeight(c4Shape[textType].text, textConf);
|
||||
} else {
|
||||
let lines = c4Shape[textType].text.split(common.lineBreakRegex);
|
||||
c4Shape[textType].textLines = lines.length;
|
||||
let lineHeight = 0;
|
||||
c4Shape[textType].height = 0;
|
||||
c4Shape[textType].width = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
c4Shape[textType].width = Math.max(
|
||||
calculateTextWidth(lines[i], textConf),
|
||||
c4Shape[textType].width
|
||||
);
|
||||
lineHeight = calculateTextHeight(lines[i], textConf);
|
||||
c4Shape[textType].height = c4Shape[textType].height + lineHeight;
|
||||
}
|
||||
// c4Shapes[textType].height = c4Shapes[textType].textLines * textConf.fontSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const drawBoundary = function (diagram, boundary, bounds) {
|
||||
boundary.x = bounds.data.startx;
|
||||
boundary.y = bounds.data.starty;
|
||||
boundary.width = bounds.data.stopx - bounds.data.startx;
|
||||
boundary.height = bounds.data.stopy - bounds.data.starty;
|
||||
|
||||
boundary.label.y = conf.c4ShapeMargin - 35;
|
||||
|
||||
let boundaryTextWrap = boundary.wrap && conf.wrap;
|
||||
let boundaryLabelConf = boundaryFont(conf);
|
||||
boundaryLabelConf.fontSize = boundaryLabelConf.fontSize + 2;
|
||||
boundaryLabelConf.fontWeight = 'bold';
|
||||
let textLimitWidth = calculateTextWidth(boundary.label.text, boundaryLabelConf);
|
||||
calcC4ShapeTextWH('label', boundary, boundaryTextWrap, boundaryLabelConf, textLimitWidth);
|
||||
|
||||
svgDraw.drawBoundary(diagram, boundary, conf);
|
||||
};
|
||||
|
||||
export const drawC4ShapeArray = function (currentBounds, diagram, c4ShapeArray, c4ShapeKeys) {
|
||||
// Upper Y is relative point
|
||||
let Y = 0;
|
||||
// Draw the c4ShapeArray
|
||||
for (let i = 0; i < c4ShapeKeys.length; i++) {
|
||||
Y = 0;
|
||||
const c4Shape = c4ShapeArray[c4ShapeKeys[i]];
|
||||
|
||||
// calc c4 shape type width and height
|
||||
|
||||
let c4ShapeTypeConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
|
||||
c4ShapeTypeConf.fontSize = c4ShapeTypeConf.fontSize - 2;
|
||||
c4Shape.typeC4Shape.width = calculateTextWidth(
|
||||
'<<' + c4Shape.typeC4Shape.text + '>>',
|
||||
c4ShapeTypeConf
|
||||
);
|
||||
c4Shape.typeC4Shape.height = c4ShapeTypeConf.fontSize + 2;
|
||||
c4Shape.typeC4Shape.Y = conf.c4ShapePadding;
|
||||
Y = c4Shape.typeC4Shape.Y + c4Shape.typeC4Shape.height - 4;
|
||||
|
||||
// set image width and height c4Shape.x + c4Shape.width / 2 - 24, c4Shape.y + 28
|
||||
// let imageWidth = 0,
|
||||
// imageHeight = 0,
|
||||
// imageY = 0;
|
||||
//
|
||||
c4Shape.image = { width: 0, height: 0, Y: 0 };
|
||||
switch (c4Shape.typeC4Shape.text) {
|
||||
case 'person':
|
||||
case 'external_person':
|
||||
c4Shape.image.width = 48;
|
||||
c4Shape.image.height = 48;
|
||||
c4Shape.image.Y = Y;
|
||||
Y = c4Shape.image.Y + c4Shape.image.height;
|
||||
break;
|
||||
}
|
||||
if (c4Shape.sprite) {
|
||||
c4Shape.image.width = 48;
|
||||
c4Shape.image.height = 48;
|
||||
c4Shape.image.Y = Y;
|
||||
Y = c4Shape.image.Y + c4Shape.image.height;
|
||||
}
|
||||
|
||||
// Y = conf.c4ShapePadding + c4Shape.image.height;
|
||||
|
||||
let c4ShapeTextWrap = c4Shape.wrap && conf.wrap;
|
||||
let textLimitWidth = conf.width - conf.c4ShapePadding * 2;
|
||||
|
||||
let c4ShapeLabelConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
|
||||
c4ShapeLabelConf.fontSize = c4ShapeLabelConf.fontSize + 2;
|
||||
c4ShapeLabelConf.fontWeight = 'bold';
|
||||
calcC4ShapeTextWH('label', c4Shape, c4ShapeTextWrap, c4ShapeLabelConf, textLimitWidth);
|
||||
c4Shape['label'].Y = Y + 8;
|
||||
Y = c4Shape['label'].Y + c4Shape['label'].height;
|
||||
|
||||
if (c4Shape.type && c4Shape.type.text !== '') {
|
||||
c4Shape.type.text = '[' + c4Shape.type.text + ']';
|
||||
let c4ShapeTypeConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
|
||||
calcC4ShapeTextWH('type', c4Shape, c4ShapeTextWrap, c4ShapeTypeConf, textLimitWidth);
|
||||
c4Shape['type'].Y = Y + 5;
|
||||
Y = c4Shape['type'].Y + c4Shape['type'].height;
|
||||
} else if (c4Shape.techn && c4Shape.techn.text !== '') {
|
||||
c4Shape.techn.text = '[' + c4Shape.techn.text + ']';
|
||||
let c4ShapeTechnConf = c4ShapeFont(conf, c4Shape.techn.text);
|
||||
calcC4ShapeTextWH('techn', c4Shape, c4ShapeTextWrap, c4ShapeTechnConf, textLimitWidth);
|
||||
c4Shape['techn'].Y = Y + 5;
|
||||
Y = c4Shape['techn'].Y + c4Shape['techn'].height;
|
||||
}
|
||||
|
||||
let rectHeight = Y;
|
||||
let rectWidth = c4Shape.label.width;
|
||||
|
||||
if (c4Shape.descr && c4Shape.descr.text !== '') {
|
||||
let c4ShapeDescrConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text);
|
||||
calcC4ShapeTextWH('descr', c4Shape, c4ShapeTextWrap, c4ShapeDescrConf, textLimitWidth);
|
||||
c4Shape['descr'].Y = Y + 20;
|
||||
Y = c4Shape['descr'].Y + c4Shape['descr'].height;
|
||||
|
||||
rectWidth = Math.max(c4Shape.label.width, c4Shape.descr.width);
|
||||
rectHeight = Y - c4Shape['descr'].textLines * 5;
|
||||
}
|
||||
|
||||
rectWidth = rectWidth + conf.c4ShapePadding;
|
||||
// let rectHeight =
|
||||
|
||||
c4Shape.width = Math.max(c4Shape.width || conf.width, rectWidth, conf.width);
|
||||
c4Shape.height = Math.max(c4Shape.height || conf.height, rectHeight, conf.height);
|
||||
c4Shape.margin = c4Shape.margin || conf.c4ShapeMargin;
|
||||
|
||||
currentBounds.insert(c4Shape);
|
||||
|
||||
const height = svgDraw.drawC4Shape(diagram, c4Shape, conf);
|
||||
}
|
||||
|
||||
currentBounds.bumpLastMargin(conf.c4ShapeMargin);
|
||||
};
|
||||
|
||||
class Point {
|
||||
constructor(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
/* * *
|
||||
* Get the intersection of the line between the center point of a rectangle and a point outside the rectangle.
|
||||
* Algorithm idea.
|
||||
* Using a point outside the rectangle as the coordinate origin, the graph is divided into four quadrants, and each quadrant is divided into two cases, with separate treatment on the coordinate axes
|
||||
* 1. The case of coordinate axes.
|
||||
* 1. The case of the negative x-axis
|
||||
* 2. The case of the positive x-axis
|
||||
* 3. The case of the positive y-axis
|
||||
* 4. The negative y-axis case
|
||||
* 2. Quadrant cases.
|
||||
* 2.1. first quadrant: the case where the line intersects the left side of the rectangle; the case where it intersects the lower side of the rectangle
|
||||
* 2.2. second quadrant: the case where the line intersects the right side of the rectangle; the case where it intersects the lower edge of the rectangle
|
||||
* 2.3. third quadrant: the case where the line intersects the right side of the rectangle; the case where it intersects the upper edge of the rectangle
|
||||
* 2.4. fourth quadrant: the case where the line intersects the left side of the rectangle; the case where it intersects the upper side of the rectangle
|
||||
*
|
||||
*/
|
||||
let getIntersectPoint = function (fromNode, endPoint) {
|
||||
let x1 = fromNode.x;
|
||||
|
||||
let y1 = fromNode.y;
|
||||
|
||||
let x2 = endPoint.x;
|
||||
|
||||
let y2 = endPoint.y;
|
||||
|
||||
let fromCenterX = x1 + fromNode.width / 2;
|
||||
|
||||
let fromCenterY = y1 + fromNode.height / 2;
|
||||
|
||||
let dx = Math.abs(x1 - x2);
|
||||
|
||||
let dy = Math.abs(y1 - y2);
|
||||
|
||||
let tanDYX = dy / dx;
|
||||
|
||||
let fromDYX = fromNode.height / fromNode.width;
|
||||
|
||||
let returnPoint = null;
|
||||
|
||||
if (y1 == y2 && x1 < x2) {
|
||||
returnPoint = new Point(x1 + fromNode.width, fromCenterY);
|
||||
} else if (y1 == y2 && x1 > x2) {
|
||||
returnPoint = new Point(x1, fromCenterY);
|
||||
} else if (x1 == x2 && y1 < y2) {
|
||||
returnPoint = new Point(fromCenterX, y1 + fromNode.height);
|
||||
} else if (x1 == x2 && y1 > y2) {
|
||||
returnPoint = new Point(fromCenterX, y1);
|
||||
}
|
||||
|
||||
if (x1 > x2 && y1 < y2) {
|
||||
if (fromDYX >= tanDYX) {
|
||||
returnPoint = new Point(x1, fromCenterY + (tanDYX * fromNode.width) / 2);
|
||||
} else {
|
||||
returnPoint = new Point(
|
||||
fromCenterX - ((dx / dy) * fromNode.height) / 2,
|
||||
y1 + fromNode.height
|
||||
);
|
||||
}
|
||||
} else if (x1 < x2 && y1 < y2) {
|
||||
//
|
||||
if (fromDYX >= tanDYX) {
|
||||
returnPoint = new Point(x1 + fromNode.width, fromCenterY + (tanDYX * fromNode.width) / 2);
|
||||
} else {
|
||||
returnPoint = new Point(
|
||||
fromCenterX + ((dx / dy) * fromNode.height) / 2,
|
||||
y1 + fromNode.height
|
||||
);
|
||||
}
|
||||
} else if (x1 < x2 && y1 > y2) {
|
||||
if (fromDYX >= tanDYX) {
|
||||
returnPoint = new Point(x1 + fromNode.width, fromCenterY - (tanDYX * fromNode.width) / 2);
|
||||
} else {
|
||||
returnPoint = new Point(fromCenterX + ((fromNode.height / 2) * dx) / dy, y1);
|
||||
}
|
||||
} else if (x1 > x2 && y1 > y2) {
|
||||
if (fromDYX >= tanDYX) {
|
||||
returnPoint = new Point(x1, fromCenterY - (fromNode.width / 2) * tanDYX);
|
||||
} else {
|
||||
returnPoint = new Point(fromCenterX - ((fromNode.height / 2) * dx) / dy, y1);
|
||||
}
|
||||
}
|
||||
return returnPoint;
|
||||
};
|
||||
|
||||
let getIntersectPoints = function (fromNode, endNode) {
|
||||
let endIntersectPoint = { x: 0, y: 0 };
|
||||
endIntersectPoint.x = endNode.x + endNode.width / 2;
|
||||
endIntersectPoint.y = endNode.y + endNode.height / 2;
|
||||
let startPoint = getIntersectPoint(fromNode, endIntersectPoint);
|
||||
|
||||
endIntersectPoint.x = fromNode.x + fromNode.width / 2;
|
||||
endIntersectPoint.y = fromNode.y + fromNode.height / 2;
|
||||
let endPoint = getIntersectPoint(endNode, endIntersectPoint);
|
||||
return { startPoint: startPoint, endPoint: endPoint };
|
||||
};
|
||||
|
||||
export const drawRels = function (diagram, rels, getC4ShapeObj) {
|
||||
let i = 0;
|
||||
for (let rel of rels) {
|
||||
i = i + 1;
|
||||
let relTextWrap = rel.wrap && conf.wrap;
|
||||
let relConf = messageFont(conf);
|
||||
let diagramType = parser.yy.getC4Type();
|
||||
if (diagramType === 'C4Dynamic') rel.label.text = i + ': ' + rel.label.text;
|
||||
let textLimitWidth = calculateTextWidth(rel.label.text, relConf);
|
||||
calcC4ShapeTextWH('label', rel, relTextWrap, relConf, textLimitWidth);
|
||||
|
||||
if (rel.techn && rel.techn.text !== '') {
|
||||
textLimitWidth = calculateTextWidth(rel.techn.text, relConf);
|
||||
calcC4ShapeTextWH('techn', rel, relTextWrap, relConf, textLimitWidth);
|
||||
}
|
||||
|
||||
if (rel.descr && rel.descr.text !== '') {
|
||||
textLimitWidth = calculateTextWidth(rel.descr.text, relConf);
|
||||
calcC4ShapeTextWH('descr', rel, relTextWrap, relConf, textLimitWidth);
|
||||
}
|
||||
|
||||
let fromNode = getC4ShapeObj(rel.from);
|
||||
let endNode = getC4ShapeObj(rel.to);
|
||||
let points = getIntersectPoints(fromNode, endNode);
|
||||
rel.startPoint = points.startPoint;
|
||||
rel.endPoint = points.endPoint;
|
||||
}
|
||||
svgDraw.drawRels(diagram, rels, conf);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param diagram
|
||||
* @param parentBoundaryAlias
|
||||
* @param parentBounds
|
||||
* @param currentBoundarys
|
||||
*/
|
||||
function drawInsideBoundary(diagram, parentBoundaryAlias, parentBounds, currentBoundarys) {
|
||||
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);
|
||||
// Math.min(
|
||||
// conf.width * conf.c4ShapeInRow + conf.c4ShapeMargin * conf.c4ShapeInRow * 2,
|
||||
// parentBounds.data.widthLimit / Math.min(conf.c4BoundaryInRow, currentBoundarys.length)
|
||||
// );
|
||||
for (let i = 0; i < currentBoundarys.length; i++) {
|
||||
let currentBoundary = currentBoundarys[i];
|
||||
let Y = 0;
|
||||
currentBoundary.image = { width: 0, height: 0, Y: 0 };
|
||||
if (currentBoundary.sprite) {
|
||||
currentBoundary.image.width = 48;
|
||||
currentBoundary.image.height = 48;
|
||||
currentBoundary.image.Y = Y;
|
||||
Y = currentBoundary.image.Y + currentBoundary.image.height;
|
||||
}
|
||||
|
||||
let currentBoundaryTextWrap = currentBoundary.wrap && conf.wrap;
|
||||
|
||||
let currentBoundaryLabelConf = boundaryFont(conf);
|
||||
currentBoundaryLabelConf.fontSize = currentBoundaryLabelConf.fontSize + 2;
|
||||
currentBoundaryLabelConf.fontWeight = 'bold';
|
||||
calcC4ShapeTextWH(
|
||||
'label',
|
||||
currentBoundary,
|
||||
currentBoundaryTextWrap,
|
||||
currentBoundaryLabelConf,
|
||||
currentBounds.data.widthLimit
|
||||
);
|
||||
currentBoundary['label'].Y = Y + 8;
|
||||
Y = currentBoundary['label'].Y + currentBoundary['label'].height;
|
||||
|
||||
if (currentBoundary.type && currentBoundary.type.text !== '') {
|
||||
currentBoundary.type.text = '[' + currentBoundary.type.text + ']';
|
||||
let currentBoundaryTypeConf = boundaryFont(conf);
|
||||
calcC4ShapeTextWH(
|
||||
'type',
|
||||
currentBoundary,
|
||||
currentBoundaryTextWrap,
|
||||
currentBoundaryTypeConf,
|
||||
currentBounds.data.widthLimit
|
||||
);
|
||||
currentBoundary['type'].Y = Y + 5;
|
||||
Y = currentBoundary['type'].Y + currentBoundary['type'].height;
|
||||
}
|
||||
|
||||
if (currentBoundary.descr && currentBoundary.descr.text !== '') {
|
||||
let currentBoundaryDescrConf = boundaryFont(conf);
|
||||
currentBoundaryDescrConf.fontSize = currentBoundaryDescrConf.fontSize - 2;
|
||||
calcC4ShapeTextWH(
|
||||
'descr',
|
||||
currentBoundary,
|
||||
currentBoundaryTextWrap,
|
||||
currentBoundaryDescrConf,
|
||||
currentBounds.data.widthLimit
|
||||
);
|
||||
currentBoundary['descr'].Y = Y + 20;
|
||||
Y = currentBoundary['descr'].Y + currentBoundary['descr'].height;
|
||||
}
|
||||
|
||||
if (i == 0 || i % conf.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;
|
||||
|
||||
currentBounds.setData(_x, _x, _y, _y);
|
||||
} else {
|
||||
// Calculate the drawing start point of the currentBoundarys.
|
||||
let _x =
|
||||
currentBounds.data.stopx !== currentBounds.data.startx
|
||||
? currentBounds.data.stopx + conf.diagramMarginX
|
||||
: currentBounds.data.startx;
|
||||
let _y = currentBounds.data.starty;
|
||||
|
||||
currentBounds.setData(_x, _x, _y, _y);
|
||||
}
|
||||
currentBounds.name = currentBoundary.alias;
|
||||
let currentPersonOrSystemArray = parser.yy.getC4ShapeArray(currentBoundary.alias);
|
||||
let currentPersonOrSystemKeys = parser.yy.getC4ShapeKeys(currentBoundary.alias);
|
||||
|
||||
if (currentPersonOrSystemKeys.length > 0) {
|
||||
drawC4ShapeArray(
|
||||
currentBounds,
|
||||
diagram,
|
||||
currentPersonOrSystemArray,
|
||||
currentPersonOrSystemKeys
|
||||
);
|
||||
}
|
||||
parentBoundaryAlias = currentBoundary.alias;
|
||||
let nextCurrentBoundarys = parser.yy.getBoundarys(parentBoundaryAlias);
|
||||
|
||||
if (nextCurrentBoundarys.length > 0) {
|
||||
// draw boundary inside currentBoundary
|
||||
// bounds.init();
|
||||
// parentBoundaryWidthLimit = bounds.data.stopx - bounds.startx;
|
||||
drawInsideBoundary(diagram, parentBoundaryAlias, currentBounds, nextCurrentBoundarys);
|
||||
}
|
||||
// draw boundary
|
||||
if (currentBoundary.alias !== 'global') drawBoundary(diagram, currentBoundary, currentBounds);
|
||||
parentBounds.data.stopy = Math.max(
|
||||
currentBounds.data.stopy + conf.c4ShapeMargin,
|
||||
parentBounds.data.stopy
|
||||
);
|
||||
parentBounds.data.stopx = Math.max(
|
||||
currentBounds.data.stopx + conf.c4ShapeMargin,
|
||||
parentBounds.data.stopx
|
||||
);
|
||||
globalBoundaryMaxX = Math.max(globalBoundaryMaxX, parentBounds.data.stopx);
|
||||
globalBoundaryMaxY = Math.max(globalBoundaryMaxY, parentBounds.data.stopy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a sequenceDiagram in the tag with id: id based on the graph definition in text.
|
||||
*
|
||||
* @param {any} text
|
||||
* @param {any} id
|
||||
*/
|
||||
export const draw = function (text, id) {
|
||||
conf = configApi.getConfig().c4;
|
||||
const securityLevel = configApi.getConfig().securityLevel;
|
||||
// Handle root and ocument for when rendering in sanbox mode
|
||||
let sandboxElement;
|
||||
if (securityLevel === 'sandbox') {
|
||||
sandboxElement = select('#i' + id);
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
: select('body');
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
|
||||
parser.yy.clear();
|
||||
parser.yy.setWrap(conf.wrap);
|
||||
parser.parse(text + '\n');
|
||||
|
||||
log.debug(`C:${JSON.stringify(conf, null, 2)}`);
|
||||
|
||||
const diagram =
|
||||
securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : select(`[id="${id}"]`);
|
||||
|
||||
svgDraw.insertComputerIcon(diagram);
|
||||
svgDraw.insertDatabaseIcon(diagram);
|
||||
svgDraw.insertClockIcon(diagram);
|
||||
|
||||
let screenBounds = new Bounds();
|
||||
screenBounds.setData(
|
||||
conf.diagramMarginX,
|
||||
conf.diagramMarginX,
|
||||
conf.diagramMarginY,
|
||||
conf.diagramMarginY
|
||||
);
|
||||
|
||||
screenBounds.data.widthLimit = screen.availWidth;
|
||||
globalBoundaryMaxX = conf.diagramMarginX;
|
||||
globalBoundaryMaxY = conf.diagramMarginY;
|
||||
|
||||
const title = parser.yy.getTitle();
|
||||
const c4type = parser.yy.getC4Type();
|
||||
let currentBoundarys = parser.yy.getBoundarys('');
|
||||
// switch (c4type) {
|
||||
// case 'C4Context':
|
||||
drawInsideBoundary(diagram, '', screenBounds, currentBoundarys);
|
||||
// break;
|
||||
// }
|
||||
|
||||
// The arrow head definition is attached to the svg once
|
||||
svgDraw.insertArrowHead(diagram);
|
||||
svgDraw.insertArrowEnd(diagram);
|
||||
svgDraw.insertArrowCrossHead(diagram);
|
||||
svgDraw.insertArrowFilledHead(diagram);
|
||||
|
||||
drawRels(diagram, parser.yy.getRels(), parser.yy.getC4Shape);
|
||||
|
||||
screenBounds.data.stopx = globalBoundaryMaxX;
|
||||
screenBounds.data.stopy = globalBoundaryMaxY;
|
||||
|
||||
const box = screenBounds.data;
|
||||
|
||||
// Make sure the height of the diagram supports long menus.
|
||||
let boxHeight = box.stopy - box.starty;
|
||||
|
||||
let height = boxHeight + 2 * conf.diagramMarginY;
|
||||
|
||||
// Make sure the width of the diagram supports wide menus.
|
||||
let boxWidth = box.stopx - box.startx;
|
||||
const width = boxWidth + 2 * conf.diagramMarginX;
|
||||
|
||||
if (title) {
|
||||
diagram
|
||||
.append('text')
|
||||
.text(title)
|
||||
.attr('x', (box.stopx - box.startx) / 2 - 4 * conf.diagramMarginX)
|
||||
.attr('y', box.starty + conf.diagramMarginY);
|
||||
}
|
||||
|
||||
configureSvgSize(diagram, height, width, conf.useMaxWidth);
|
||||
|
||||
const extraVertForTitle = title ? 60 : 0;
|
||||
diagram.attr(
|
||||
'viewBox',
|
||||
box.startx -
|
||||
conf.diagramMarginX +
|
||||
' -' +
|
||||
(conf.diagramMarginY + extraVertForTitle) +
|
||||
' ' +
|
||||
width +
|
||||
' ' +
|
||||
(height + extraVertForTitle)
|
||||
);
|
||||
|
||||
addSVGAccessibilityFields(parser.yy, diagram, id);
|
||||
log.debug(`models:`, box);
|
||||
};
|
||||
|
||||
export default {
|
||||
drawPersonOrSystemArray: drawC4ShapeArray,
|
||||
drawBoundary,
|
||||
setConf,
|
||||
draw,
|
||||
};
|
|
@ -0,0 +1,312 @@
|
|||
/** mermaid
|
||||
* https://mermaidjs.github.io/
|
||||
* (c) 2022 mzhx.meng@gmail.com
|
||||
* MIT license.
|
||||
*/
|
||||
|
||||
/* lexical grammar */
|
||||
%lex
|
||||
|
||||
/* context */
|
||||
%x person
|
||||
%x person_ext
|
||||
%x system
|
||||
%x system_db
|
||||
%x system_queue
|
||||
%x system_ext
|
||||
%x system_ext_db
|
||||
%x system_ext_queue
|
||||
%x boundary
|
||||
%x enterprise_boundary
|
||||
%x system_boundary
|
||||
%x rel
|
||||
%x birel
|
||||
%x rel_u
|
||||
%x rel_d
|
||||
%x rel_l
|
||||
%x rel_r
|
||||
|
||||
/* container */
|
||||
%x container
|
||||
%x container_db
|
||||
%x container_queue
|
||||
%x container_ext
|
||||
%x container_ext_db
|
||||
%x container_ext_queue
|
||||
%x container_boundary
|
||||
|
||||
/* component */
|
||||
%x component
|
||||
%x component_db
|
||||
%x component_queue
|
||||
%x component_ext
|
||||
%x component_ext_db
|
||||
%x component_ext_queue
|
||||
|
||||
/* Dynamic diagram */
|
||||
%x rel_index
|
||||
%x index
|
||||
|
||||
/* Deployment diagram */
|
||||
%x node
|
||||
%x node_l
|
||||
%x node_r
|
||||
|
||||
/* Relationship Types */
|
||||
%x rel
|
||||
%x rel_bi
|
||||
%x rel_u
|
||||
%x rel_d
|
||||
%x rel_l
|
||||
%x rel_r
|
||||
%x rel_b
|
||||
|
||||
%x attribute
|
||||
%x string
|
||||
|
||||
%x open_directive
|
||||
%x type_directive
|
||||
%x arg_directive
|
||||
|
||||
%%
|
||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||
.*direction\s+TB[^\n]* return 'direction_tb';
|
||||
.*direction\s+BT[^\n]* return 'direction_bt';
|
||||
.*direction\s+RL[^\n]* return 'direction_rl';
|
||||
.*direction\s+LR[^\n]* return 'direction_lr';
|
||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||
<arg_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';
|
||||
|
||||
\s*(\r?\n)+ return 'NEWLINE';
|
||||
\s+ /* skip whitespace */
|
||||
"C4Context" return 'C4_CONTEXT';
|
||||
"C4Container" return 'C4_CONTAINER';
|
||||
"C4Component" return 'C4_COMPONENT';
|
||||
"C4Dynamic" return 'C4_DYNAMIC';
|
||||
"C4Deployment" return 'C4_DEPLOYMENT';
|
||||
|
||||
"Person_Ext" { this.begin("person_ext"); console.log('begin person_ext'); return 'PERSON_EXT';}
|
||||
"Person" { this.begin("person"); console.log('begin person'); return 'PERSON';}
|
||||
"SystemQueue_Ext" { this.begin("system_ext_queue"); console.log('begin system_ext_queue'); return 'SYSTEM_EXT_QUEUE';}
|
||||
"SystemDb_Ext" { this.begin("system_ext_db"); console.log('begin system_ext_db'); return 'SYSTEM_EXT_DB';}
|
||||
"System_Ext" { this.begin("system_ext"); console.log('begin system_ext'); return 'SYSTEM_EXT';}
|
||||
"SystemQueue" { this.begin("system_queue"); console.log('begin system_queue'); return 'SYSTEM_QUEUE';}
|
||||
"SystemDb" { this.begin("system_db"); console.log('begin system_db'); return 'SYSTEM_DB';}
|
||||
"System" { this.begin("system"); console.log('begin system'); return 'SYSTEM';}
|
||||
|
||||
"Boundary" { this.begin("boundary"); console.log('begin boundary'); return 'BOUNDARY';}
|
||||
"Enterprise_Boundary" { this.begin("enterprise_boundary"); console.log('begin enterprise_boundary'); return 'ENTERPRISE_BOUNDARY';}
|
||||
"System_Boundary" { this.begin("system_boundary"); console.log('begin system_boundary'); return 'SYSTEM_BOUNDARY';}
|
||||
|
||||
"ContainerQueue_Ext" { this.begin("container_ext_queue"); console.log('begin container_ext_queue'); return 'CONTAINER_EXT_QUEUE';}
|
||||
"ContainerDb_Ext" { this.begin("container_ext_db"); console.log('begin container_ext_db'); return 'CONTAINER_EXT_DB';}
|
||||
"Container_Ext" { this.begin("container_ext"); console.log('begin container_ext'); return 'CONTAINER_EXT';}
|
||||
"ContainerQueue" { this.begin("container_queue"); console.log('begin container_queue'); return 'CONTAINER_QUEUE';}
|
||||
"ContainerDb" { this.begin("container_db"); console.log('begin container_db'); return 'CONTAINER_DB';}
|
||||
"Container" { this.begin("container"); console.log('begin container'); return 'CONTAINER';}
|
||||
|
||||
"Container_Boundary" { this.begin("container_boundary"); console.log('begin container_boundary'); return 'CONTAINER_BOUNDARY';}
|
||||
|
||||
"ComponentQueue_Ext" { this.begin("component_ext_queue"); console.log('begin component_ext_queue'); return 'COMPONENT_EXT_QUEUE';}
|
||||
"ComponentDb_Ext" { this.begin("component_ext_db"); console.log('begin component_ext_db'); return 'COMPONENT_EXT_DB';}
|
||||
"Component_Ext" { this.begin("component_ext"); console.log('begin component_ext'); return 'COMPONENT_EXT';}
|
||||
"ComponentQueue" { this.begin("component_queue"); console.log('begin component_queue'); return 'COMPONENT_QUEUE';}
|
||||
"ComponentDb" { this.begin("component_db"); console.log('begin component_db'); return 'COMPONENT_DB';}
|
||||
"Component" { this.begin("component"); console.log('begin component'); return 'COMPONENT';}
|
||||
|
||||
"Deployment_Node" { this.begin("node"); console.log('begin node'); return 'NODE';}
|
||||
"Node" { this.begin("node"); console.log('begin node'); return 'NODE';}
|
||||
"Node_L" { this.begin("node_l"); console.log('begin node_l'); return 'NODE_L';}
|
||||
"Node_R" { this.begin("node_r"); console.log('begin node_r'); return 'NODE_R';}
|
||||
|
||||
|
||||
"Rel" { this.begin("rel"); console.log('begin rel'); return 'REL';}
|
||||
"BiRel" { this.begin("birel"); console.log('begin birel'); return 'BIREL';}
|
||||
"Rel_Up" { this.begin("rel_u"); console.log('begin rel_u'); return 'REL_U';}
|
||||
"Rel_U" { this.begin("rel_u"); console.log('begin rel_u'); return 'REL_U';}
|
||||
"Rel_Down" { this.begin("rel_d"); console.log('begin rel_d'); return 'REL_D';}
|
||||
"Rel_D" { this.begin("rel_d"); console.log('begin rel_d'); return 'REL_D';}
|
||||
"Rel_Left" { this.begin("rel_l"); console.log('begin rel_l'); return 'REL_L';}
|
||||
"Rel_L" { this.begin("rel_l"); console.log('begin rel_l'); return 'REL_L';}
|
||||
"Rel_Right" { this.begin("rel_r"); console.log('begin rel_r'); return 'REL_R';}
|
||||
"Rel_R" { this.begin("rel_r"); console.log('begin rel_r'); return 'REL_R';}
|
||||
"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';}
|
||||
|
||||
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index><<EOF>> return "EOF_IN_STRUCT";
|
||||
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index>[(][ ]*[,] { console.log('begin attribute with ATTRIBUTE_EMPTY'); this.begin("attribute"); return "ATTRIBUTE_EMPTY";}
|
||||
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index>[(] { console.log('begin attribute'); this.begin("attribute"); }
|
||||
<person,person_ext,system_ext_queue,system_ext_db,system_ext,system_queue,system_db,system,boundary,enterprise_boundary,system_boundary,container_ext_db,container_ext,container_queue,container_db,container,container_boundary,component_ext_db,component_ext,component_queue,component_db,component,node,node_l,node_r,rel,birel,rel_u,rel_d,rel_l,rel_r,rel_b,rel_index,attribute>[)] { console.log('STOP attribute'); this.popState();console.log('STOP diagram'); this.popState();}
|
||||
|
||||
<attribute>",," { console.log(',,'); return 'ATTRIBUTE_EMPTY';}
|
||||
<attribute>"," { console.log(','); }
|
||||
<attribute>[ ]*["]["] { console.log('ATTRIBUTE_EMPTY'); return 'ATTRIBUTE_EMPTY';}
|
||||
<attribute>[ ]*["] { console.log('begin string'); this.begin("string");}
|
||||
<string>["] { console.log('STOP string'); this.popState(); }
|
||||
<string>[^"]* { console.log('STR'); return "STR";}
|
||||
<attribute>[^,]+ { console.log('not STR'); return "STR";}
|
||||
|
||||
'{' { /* this.begin("lbrace"); */ console.log('begin boundary block'); return "LBRACE";}
|
||||
'}' { /* this.popState(); */ console.log('STOP boundary block'); return "RBRACE";}
|
||||
|
||||
[\s]+ return 'SPACE';
|
||||
[\n\r]+ return 'EOL';
|
||||
<<EOF>> return 'EOF';
|
||||
|
||||
/lex
|
||||
|
||||
/* operator associations and precedence */
|
||||
|
||||
%left '^'
|
||||
|
||||
%start start
|
||||
|
||||
%% /* language grammar */
|
||||
|
||||
start
|
||||
: mermaidDoc
|
||||
| direction
|
||||
| directive start
|
||||
;
|
||||
|
||||
direction
|
||||
: direction_tb
|
||||
{ yy.setDirection('TB');}
|
||||
| direction_bt
|
||||
{ yy.setDirection('BT');}
|
||||
| direction_rl
|
||||
{ yy.setDirection('RL');}
|
||||
| direction_lr
|
||||
{ yy.setDirection('LR');}
|
||||
;
|
||||
|
||||
mermaidDoc
|
||||
: graphConfig
|
||||
;
|
||||
|
||||
directive
|
||||
: openDirective typeDirective closeDirective NEWLINE
|
||||
| openDirective typeDirective ':' argDirective closeDirective NEWLINE
|
||||
;
|
||||
|
||||
openDirective
|
||||
: open_directive { console.log("open_directive: ", $1); yy.parseDirective('%%{', 'open_directive'); }
|
||||
;
|
||||
|
||||
typeDirective
|
||||
: type_directive { }
|
||||
;
|
||||
|
||||
argDirective
|
||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); console.log("arg_directive: ", $1); yy.parseDirective($1, 'arg_directive'); }
|
||||
;
|
||||
|
||||
closeDirective
|
||||
: close_directive { console.log("close_directive: ", $1); yy.parseDirective('}%%', 'close_directive', 'c4Context'); }
|
||||
;
|
||||
|
||||
graphConfig
|
||||
: C4_CONTEXT NEWLINE statements EOF {yy.setC4Type($1)}
|
||||
| C4_CONTAINER NEWLINE statements EOF {yy.setC4Type($1)}
|
||||
| C4_COMPONENT NEWLINE statements EOF {yy.setC4Type($1)}
|
||||
| C4_DYNAMIC NEWLINE statements EOF {yy.setC4Type($1)}
|
||||
| C4_DEPLOYMENT NEWLINE statements EOF {yy.setC4Type($1)}
|
||||
;
|
||||
|
||||
statements
|
||||
: otherStatements
|
||||
| diagramStatements
|
||||
| otherStatements diagramStatements
|
||||
;
|
||||
|
||||
otherStatements
|
||||
: otherStatement
|
||||
| otherStatement NEWLINE
|
||||
| otherStatement NEWLINE otherStatements
|
||||
;
|
||||
|
||||
otherStatement
|
||||
: title {yy.setTitle($1.substring(6));$$=$1.substring(6);}
|
||||
| accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);}
|
||||
;
|
||||
|
||||
boundaryStatement
|
||||
: boundaryStartStatement diagramStatements boundaryStopStatement
|
||||
;
|
||||
|
||||
boundaryStartStatement
|
||||
: boundaryStart LBRACE NEWLINE
|
||||
| boundaryStart NEWLINE LBRACE
|
||||
| boundaryStart NEWLINE LBRACE NEWLINE
|
||||
;
|
||||
|
||||
boundaryStart
|
||||
: ENTERPRISE_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
|
||||
| SYSTEM_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
|
||||
| BOUNDARY attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
|
||||
| CONTAINER_BOUNDARY attributes {console.log($1,JSON.stringify($2)); $2.splice(2, 0, 'CONTAINER'); yy.addContainerBoundary(...$2); $$=$2;}
|
||||
| NODE attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('node', ...$2); $$=$2;}
|
||||
| NODE_L attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('nodeL', ...$2); $$=$2;}
|
||||
| NODE_R attributes {console.log($1,JSON.stringify($2)); yy.addDeploymentNode('nodeR', ...$2); $$=$2;}
|
||||
;
|
||||
|
||||
boundaryStopStatement
|
||||
: RBRACE { yy.popBoundaryParseStack() }
|
||||
;
|
||||
|
||||
diagramStatements
|
||||
: diagramStatement
|
||||
| diagramStatement NEWLINE
|
||||
| diagramStatement NEWLINE statements
|
||||
;
|
||||
|
||||
diagramStatement
|
||||
: PERSON attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('person', ...$2); $$=$2;}
|
||||
| PERSON_EXT attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_person', ...$2); $$=$2;}
|
||||
| SYSTEM attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system', ...$2); $$=$2;}
|
||||
| SYSTEM_DB attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system_db', ...$2); $$=$2;}
|
||||
| SYSTEM_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('system_queue', ...$2); $$=$2;}
|
||||
| SYSTEM_EXT attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system', ...$2); $$=$2;}
|
||||
| SYSTEM_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system_db', ...$2); $$=$2;}
|
||||
| SYSTEM_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addPersonOrSystem('external_system_queue', ...$2); $$=$2;}
|
||||
| CONTAINER attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container', ...$2); $$=$2;}
|
||||
| CONTAINER_DB attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container_db', ...$2); $$=$2;}
|
||||
| CONTAINER_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addContainer('container_queue', ...$2); $$=$2;}
|
||||
| CONTAINER_EXT attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container', ...$2); $$=$2;}
|
||||
| CONTAINER_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container_db', ...$2); $$=$2;}
|
||||
| CONTAINER_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addContainer('external_container_queue', ...$2); $$=$2;}
|
||||
| COMPONENT attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component', ...$2); $$=$2;}
|
||||
| COMPONENT_DB attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component_db', ...$2); $$=$2;}
|
||||
| COMPONENT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addComponent('component_queue', ...$2); $$=$2;}
|
||||
| COMPONENT_EXT attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component', ...$2); $$=$2;}
|
||||
| COMPONENT_EXT_DB attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component_db', ...$2); $$=$2;}
|
||||
| COMPONENT_EXT_QUEUE attributes {console.log($1,JSON.stringify($2)); yy.addComponent('external_component_queue', ...$2); $$=$2;}
|
||||
| boundaryStatement
|
||||
| REL attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel', ...$2); $$=$2;}
|
||||
| BIREL attributes {console.log($1,JSON.stringify($2)); yy.addRel('birel', ...$2); $$=$2;}
|
||||
| REL_U attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_u', ...$2); $$=$2;}
|
||||
| REL_D attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_d', ...$2); $$=$2;}
|
||||
| REL_L attributes {console.log($1,JSON.stringify($2)); yy.addRel('rel_l', ...$2); $$=$2;}
|
||||
| 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;}
|
||||
;
|
||||
|
||||
attributes
|
||||
: attribute { console.log('PUSH ATTRIBUTE: ', $1); $$ = [$1]; }
|
||||
| attribute attributes { console.log('PUSH ATTRIBUTE: ', $1); $2.unshift($1); $$=$2;}
|
||||
;
|
||||
|
||||
attribute
|
||||
: STR { $$ = $1.trim(); }
|
||||
| ATTRIBUTE { $$ = $1.trim(); }
|
||||
| ATTRIBUTE_EMPTY { $$ = ""; }
|
||||
;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
const getStyles = (options) =>
|
||||
`.person {
|
||||
stroke: ${options.personBorder};
|
||||
fill: ${options.personBkg};
|
||||
}
|
||||
`;
|
||||
|
||||
export default getStyles;
|
File diff suppressed because one or more lines are too long
|
@ -19,6 +19,9 @@ import { select } from 'd3';
|
|||
import { compile, serialize, stringify } from 'stylis';
|
||||
import pkg from '../package.json';
|
||||
import * as configApi from './config';
|
||||
import c4Db from './diagrams/c4/c4Db';
|
||||
import c4Renderer from './diagrams/c4/c4Renderer';
|
||||
import c4Parser from './diagrams/c4/parser/c4Diagram';
|
||||
import classDb from './diagrams/class/classDb';
|
||||
import classRenderer from './diagrams/class/classRenderer';
|
||||
import classRendererV2 from './diagrams/class/classRenderer-v2';
|
||||
|
@ -84,6 +87,11 @@ function parse(text) {
|
|||
|
||||
log.debug('Type ' + graphType);
|
||||
switch (graphType) {
|
||||
case 'c4':
|
||||
c4Db.clear();
|
||||
parser = c4Parser;
|
||||
parser.parser.yy = c4Parser;
|
||||
break;
|
||||
case 'gitGraph':
|
||||
gitGraphAst.clear();
|
||||
parser = gitGraphParser;
|
||||
|
@ -449,6 +457,10 @@ const render = function (id, _txt, cb, container) {
|
|||
|
||||
try {
|
||||
switch (graphType) {
|
||||
case 'c4':
|
||||
c4Renderer.setConf(cnf.c4);
|
||||
c4Renderer.draw(txt, id);
|
||||
break;
|
||||
case 'gitGraph':
|
||||
// cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
//gitGraphRenderer.setConf(cnf.git);
|
||||
|
|
|
@ -9,6 +9,7 @@ import requirement from './diagrams/requirement/styles';
|
|||
import sequence from './diagrams/sequence/styles';
|
||||
import stateDiagram from './diagrams/state/styles';
|
||||
import journey from './diagrams/user-journey/styles';
|
||||
import c4 from './diagrams/c4/styles';
|
||||
|
||||
const themes = {
|
||||
flowchart,
|
||||
|
@ -26,6 +27,7 @@ const themes = {
|
|||
er,
|
||||
journey,
|
||||
requirement,
|
||||
c4,
|
||||
};
|
||||
|
||||
export const calcThemeVariables = (theme, userOverRides) => theme.calcColors(userOverRides);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
.person {
|
||||
stroke: $personBorder;
|
||||
fill: $personBkg;
|
||||
}
|
|
@ -56,6 +56,11 @@ $critBorderColor: #ff8888;
|
|||
$critBkgColor: red;
|
||||
$todayLineColor: red;
|
||||
|
||||
/* C4 Context Diagram variables */
|
||||
|
||||
$personBorder: $border1;
|
||||
$personBkg: $mainBkg;
|
||||
|
||||
/* state colors */
|
||||
$labelColor: black;
|
||||
|
||||
|
|
|
@ -95,6 +95,11 @@ class Theme {
|
|||
this.taskTextDarkColor = this.taskTextDarkColor || this.textColor;
|
||||
this.taskTextClickableColor = this.taskTextClickableColor || '#003163';
|
||||
|
||||
/* Sequence Diagram variables */
|
||||
|
||||
this.personBorder = this.personBorder || this.primaryBorderColor;
|
||||
this.personBkg = this.personBkg || this.mainBkg;
|
||||
|
||||
/* state colors */
|
||||
this.transitionColor = this.transitionColor || this.lineColor;
|
||||
this.transitionLabelColor = this.transitionLabelColor || this.textColor;
|
||||
|
|
|
@ -78,6 +78,11 @@ class Theme {
|
|||
this.taskTextDarkColor = 'calculated';
|
||||
this.todayLineColor = '#DB5757';
|
||||
|
||||
/* C4 Context Diagram variables */
|
||||
|
||||
this.personBorder = 'calculated';
|
||||
this.personBkg = 'calculated';
|
||||
|
||||
/* state colors */
|
||||
this.labelColor = 'calculated';
|
||||
|
||||
|
|
|
@ -103,6 +103,11 @@ class Theme {
|
|||
this.critBkgColor = 'red';
|
||||
this.todayLineColor = 'red';
|
||||
|
||||
/* C4 Context Diagram variables */
|
||||
|
||||
this.personBorder = 'calculated';
|
||||
this.personBkg = 'calculated';
|
||||
|
||||
/* state colors */
|
||||
this.labelColor = 'black';
|
||||
this.errorBkgColor = '#552222';
|
||||
|
|
|
@ -76,6 +76,11 @@ class Theme {
|
|||
this.critBkgColor = 'red';
|
||||
this.todayLineColor = 'red';
|
||||
|
||||
/* C4 Context Diagram variables */
|
||||
|
||||
this.personBorder = 'calculated';
|
||||
this.personBkg = 'calculated';
|
||||
|
||||
/* state colors */
|
||||
this.labelColor = 'black';
|
||||
|
||||
|
|
|
@ -89,6 +89,11 @@ class Theme {
|
|||
this.critBorderColor = 'calculated';
|
||||
this.todayLineColor = 'calculated';
|
||||
|
||||
/* C4 Context Diagram variables */
|
||||
|
||||
this.personBorder = 'calculated';
|
||||
this.personBkg = 'calculated';
|
||||
|
||||
/* state colors */
|
||||
this.labelColor = 'black';
|
||||
|
||||
|
|
|
@ -185,6 +185,10 @@ export const detectDirective = function (text, type = null) {
|
|||
*/
|
||||
export const detectType = function (text, cnf) {
|
||||
text = text.replace(directive, '').replace(anyComment, '\n');
|
||||
if (text.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/)) {
|
||||
return 'c4';
|
||||
}
|
||||
|
||||
if (text.match(/^\s*sequenceDiagram/)) {
|
||||
return 'sequence';
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue