diff --git a/.vite/build.ts b/.vite/build.ts index 1be46ad5a..1e9f12a41 100644 --- a/.vite/build.ts +++ b/.vite/build.ts @@ -41,6 +41,21 @@ const packageOptions = { packageName: 'mermaid-mindmap', file: 'detector.ts', }, + 'mermaid-timeline': { + name: 'mermaid-timeline', + packageName: 'mermaid-timeline', + file: 'diagram-definition.ts', + }, + // 'mermaid-timeline-detector': { + // name: 'mermaid-timeline-detector', + // packageName: 'mermaid-timeline', + // file: 'detector.ts', + // }, + // 'mermaid-example-diagram': { + // name: 'mermaid-example-diagram', + // packageName: 'mermaid-example-diagram', + // file: 'diagram-definition.ts', + // }, // 'mermaid-example-diagram-detector': { // name: 'mermaid-example-diagram-detector', // packageName: 'mermaid-example-diagram', @@ -123,6 +138,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions) 'packages/mermaid-mindmap/src/**', 'packages/mermaid/src/**', // 'packages/mermaid-example-diagram/src/**', + 'packages/mermaid-timeline/src/**', ], }; } @@ -150,6 +166,8 @@ if (watch) { if (!mermaidOnly) { build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-mindmap' })); // build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' })); + build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-timeline' })); + //build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-timeline-detector' })); } } else if (visualize) { await build(getBuildConfig({ minify: false, core: true, entryName: 'mermaid' })); diff --git a/.vite/server.ts b/.vite/server.ts index 334398dd8..eb72a93d9 100644 --- a/.vite/server.ts +++ b/.vite/server.ts @@ -24,6 +24,7 @@ async function createServer() { app.use(express.static('./packages/mermaid/dist')); app.use(express.static('./packages/mermaid-example-diagram/dist')); app.use(express.static('./packages/mermaid-mindmap/dist')); + app.use(express.static('./packages/mermaid-timeline/dist')); app.use(vite.middlewares); app.use(express.static('demos')); app.use(express.static('cypress/platform')); diff --git a/Setup.md b/Setup.md new file mode 100644 index 000000000..4d09fcfca --- /dev/null +++ b/Setup.md @@ -0,0 +1,1755 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. Please edit the corresponding file in src/docs. + + + +## mermaidAPI + +This is the API to be used when optionally handling the integration with the web page, instead of +using the default integration provided by mermaid.js. + +The core of this api is the [**render**][1] function which, given a graph +definition as text, renders the graph/diagram and returns an svg element for the graph. + +It is then up to the user of the API to make use of the svg, either insert it somewhere in the +page or do something completely different. + +In addition to the render function, a number of behavioral configuration options are available. + +## Configuration + +**Configuration methods in Mermaid version 8.6.0 have been updated, to learn more\[[click +here][2]].** + +## **What follows are config instructions for older versions** + +These are the default options which can be overridden with the initialization call like so: + +**Example 1:**
 mermaid.initialize({ flowchart:{ htmlLabels: false } }); 
+ +**Example 2:**
  
+ +A summary of all options and their defaults is found [here][3]. +A description of each option follows below. + +## theme + +Theme , the CSS style sheet + +| Parameter | Description | Type | Required | Values | +| --------- | --------------- | ------ | -------- | ---------------------------------------------- | +| theme | Built in Themes | string | Optional | 'default', 'forest', 'dark', 'neutral', 'null' | + +**Notes:** To disable any pre-defined mermaid theme, use "null".
 "theme": "forest",
+"themeCSS": ".node rect { fill: red; }" 
+ +## fontFamily + +| Parameter | Description | Type | Required | Values | +| ---------- | ------------------------------------------------------ | ------ | -------- | --------------------------- | +| fontFamily | specifies the font to be used in the rendered diagrams | string | Required | Any Possible CSS FontFamily | + +**Notes:** Default value: '"trebuchet ms", verdana, arial, sans-serif;'. + +## logLevel + +| Parameter | Description | Type | Required | Values | +| --------- | ----------------------------------------------------- | ------ | -------- | -------- | --------------------------------------------- | +| logLevel | This option decides the amount of logging to be used. | string | number | Required | 'trace','debug','info','warn','error','fatal' | + +**Notes:** + +- Trace: 0 +- Debug: 1 +- Info: 2 +- Warn: 3 +- Error: 4 +- Fatal: 5 (default) + +## securityLevel + +| Parameter | Description | Type | Required | Values | +| ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ | +| securityLevel | Level of trust for parsed diagram | string | Required | 'sandbox', 'strict', 'loose', 'antiscript' | + +**Notes**: + +- **strict**: (**default**) tags in text are encoded, click functionality is disabled +- **loose**: tags in text are allowed, click functionality is enabled +- **antiscript**: html tags in text are allowed, (only script element is removed), click + functionality is enabled +- **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This + prevent any JavaScript from running in the context. This may hinder interactive functionality + of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc. + +## startOnLoad + +| Parameter | Description | Type | Required | Values | +| ----------- | -------------------------------------------- | ------- | -------- | ----------- | +| startOnLoad | Dictates whether mermaid starts on Page load | boolean | Required | true, false | + +**Notes:** Default value: true + +## arrowMarkerAbsolute + +| Parameter | Description | Type | Required | Values | +| ------------------- | ---------------------------------------------------------------------------- | ------- | -------- | ----------- | +| arrowMarkerAbsolute | Controls whether or arrow markers in html code are absolute paths or anchors | boolean | Required | true, false | + +**Notes**: + +This matters if you are using base tag settings. + +Default value: false + +## secure + +This option controls which currentConfig keys are considered _secure_ and can only be changed +via call to mermaidAPI.initialize. Calls to mermaidAPI.reinitialize cannot make changes to the +`secure` keys in the current currentConfig. This prevents malicious graph directives from +overriding a site's default security. + +**Notes**: + +Default value: \['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'] + +## deterministicIds + +This option controls if the generated ids of nodes in the SVG are generated randomly or based +on a seed. If set to false, the IDs are generated based on the current date and thus are not +deterministic. This is the default behaviour. + +**Notes**: + +This matters if your files are checked into sourcecontrol e.g. git and should not change unless +content is changed. + +Default value: false + +## deterministicIDSeed + +This option is the optional seed for deterministic ids. if set to undefined but +deterministicIds is true, a simple number iterator is used. You can set this attribute to base +the seed on a static string. + +## flowchart + +The object containing configurations specific for flowcharts + +### diagramPadding + +| Parameter | Description | Type | Required | Values | +| -------------- | ----------------------------------------------- | ------- | -------- | ------------------ | +| diagramPadding | Amount of padding around the diagram as a whole | Integer | Required | Any Positive Value | + +**Notes:** + +The amount of padding around the diagram as a whole so that embedded diagrams have margins, +expressed in pixels + +Default value: 8 + +### htmlLabels + +| Parameter | Description | Type | Required | Values | +| ---------- | -------------------------------------------------------------------------------------------- | ------- | -------- | ----------- | +| htmlLabels | Flag for setting whether or not a html tag should be used for rendering labels on the edges. | boolean | Required | true, false | + +**Notes:** Default value: true. + +### nodeSpacing + +| Parameter | Description | Type | Required | Values | +| ----------- | --------------------------------------------------- | ------- | -------- | ------------------- | +| nodeSpacing | Defines the spacing between nodes on the same level | Integer | Required | Any positive Number | + +**Notes:** + +Pertains to horizontal spacing for TB (top to bottom) or BT (bottom to top) graphs, and the +vertical spacing for LR as well as RL graphs.\*\* + +Default value: 50 + +### rankSpacing + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------------------------------------------------- | ------- | -------- | ------------------- | +| rankSpacing | Defines the spacing between nodes on different levels | Integer | Required | Any Positive Number | + +**Notes**: + +Pertains to vertical spacing for TB (top to bottom) or BT (bottom to top), and the horizontal +spacing for LR as well as RL graphs. + +Default value 50 + +### curve + +| Parameter | Description | Type | Required | Values | +| --------- | -------------------------------------------------- | ------ | -------- | ----------------------------- | +| curve | Defines how mermaid renders curves for flowcharts. | string | Required | 'basis', 'linear', 'cardinal' | + +**Notes:** + +Default Value: 'basis' + +### useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See notes | boolean | 4 | true, false | + +**Notes:** + +When this flag is set the height and width is set to 100% and is then scaling with the +available space if not the absolute space required is used. + +Default value: true + +### defaultRenderer + +| Parameter | Description | Type | Required | Values | +| --------------- | ----------- | ------- | -------- | ----------------------- | +| defaultRenderer | See notes | boolean | 4 | dagre-d3, dagre-wrapper | + +**Notes:** + +Decides which rendering engine that is to be used for the rendering. Legal values are: +dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid + +Default value: 'dagre-wrapper' + +## sequence + +The object containing configurations specific for sequence diagrams + +### activationWidth + +| Parameter | Description | Type | Required | Values | +| --------------- | ---------------------------- | ------- | -------- | ------------------ | +| activationWidth | Width of the activation rect | Integer | Required | Any Positive Value | + +**Notes:** Default value :10 + +### diagramMarginX + +| Parameter | Description | Type | Required | Values | +| -------------- | ---------------------------------------------------- | ------- | -------- | ------------------ | +| diagramMarginX | Margin to the right and left of the sequence diagram | Integer | Required | Any Positive Value | + +**Notes:** Default value: 50 + +### diagramMarginY + +| Parameter | Description | Type | Required | Values | +| -------------- | ------------------------------------------------- | ------- | -------- | ------------------ | +| diagramMarginY | Margin to the over and under the sequence diagram | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### actorMargin + +| Parameter | Description | Type | Required | Values | +| ----------- | --------------------- | ------- | -------- | ------------------ | +| actorMargin | Margin between actors | Integer | Required | Any Positive Value | + +**Notes:** Default value: 50 + +### width + +| Parameter | Description | Type | Required | Values | +| --------- | -------------------- | ------- | -------- | ------------------ | +| width | Width of actor boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 150 + +### height + +| Parameter | Description | Type | Required | Values | +| --------- | --------------------- | ------- | -------- | ------------------ | +| height | Height of actor boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 65 + +### boxMargin + +| Parameter | Description | Type | Required | Values | +| --------- | ------------------------ | ------- | -------- | ------------------ | +| boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### boxTextMargin + +| Parameter | Description | Type | Required | Values | +| ------------- | -------------------------------------------- | ------- | -------- | ------------------ | +| boxTextMargin | Margin around the text in loop/alt/opt boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 5 + +### noteMargin + +| Parameter | Description | Type | Required | Values | +| ---------- | ------------------- | ------- | -------- | ------------------ | +| noteMargin | margin around notes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### messageMargin + +| Parameter | Description | Type | Required | Values | +| ------------- | ---------------------- | ------- | -------- | ------------------ | +| messageMargin | Space between messages | Integer | Required | Any Positive Value | + +**Notes:** Default value: 35 + +### messageAlign + +| Parameter | Description | Type | Required | Values | +| ------------ | --------------------------- | ------ | -------- | ------------------------- | +| messageAlign | Multiline message alignment | string | Required | 'left', 'center', 'right' | + +**Notes:** Default value: 'center' + +### mirrorActors + +| Parameter | Description | Type | Required | Values | +| ------------ | --------------------------- | ------- | -------- | ----------- | +| mirrorActors | Mirror actors under diagram | boolean | Required | true, false | + +**Notes:** Default value: true + +### forceMenus + +| Parameter | Description | Type | Required | Values | +| ---------- | ----------------------------------------------------------------------- | ------- | -------- | ----------- | +| forceMenus | forces actor popup menus to always be visible (to support E2E testing). | Boolean | Required | True, False | + +**Notes:** + +Default value: false. + +### bottomMarginAdj + +| Parameter | Description | Type | Required | Values | +| --------------- | ------------------------------------------ | ------- | -------- | ------------------ | +| bottomMarginAdj | Prolongs the edge of the diagram downwards | Integer | Required | Any Positive Value | + +**Notes:** + +Depending on css styling this might need adjustment. + +Default value: 1 + +### useMaxWidth + +| 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 + +### rightAngles + +| Parameter | Description | Type | Required | Values | +| ----------- | ------------------------------------ | ------- | -------- | ----------- | +| rightAngles | display curve arrows as right angles | boolean | Required | true, false | + +**Notes:** + +This will display arrows that start and begin at the same node as right angles, rather than a +curve + +Default value: false + +### showSequenceNumbers + +| Parameter | Description | Type | Required | Values | +| ------------------- | ------------------------------- | ------- | -------- | ----------- | +| showSequenceNumbers | This will show the node numbers | boolean | Required | true, false | + +**Notes:** Default value: false + +### actorFontSize + +| Parameter | Description | Type | Required | Values | +| ------------- | -------------------------------------------------- | ------- | -------- | ------------------ | +| actorFontSize | This sets the font size of the actor's description | Integer | Require | Any Positive Value | + +**Notes:** **Default value 14**.. + +### actorFontFamily + +| Parameter | Description | Type | Required | Values | +| --------------- | ---------------------------------------------------- | ------ | -------- | --------------------------- | +| actorFontFamily | This sets the font family of the actor's description | string | Required | Any Possible CSS FontFamily | + +**Notes:** Default value: "'Open Sans", sans-serif' + +### actorFontWeight + +This sets the font weight of the actor's description + +**Notes:** Default value: 400. + +### noteFontSize + +| Parameter | Description | Type | Required | Values | +| ------------ | ----------------------------------------------- | ------- | -------- | ------------------ | +| noteFontSize | This sets the font size of actor-attached notes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 14 + +### noteFontFamily + +| Parameter | Description | Type | Required | Values | +| -------------- | -------------------------------------------------- | ------ | -------- | --------------------------- | +| noteFontFamily | This sets the font family of actor-attached notes. | string | Required | Any Possible CSS FontFamily | + +**Notes:** Default value: ''"trebuchet ms", verdana, arial, sans-serif' + +### noteFontWeight + +This sets the font weight of the note's description + +**Notes:** Default value: 400 + +### noteAlign + +| Parameter | Description | Type | Required | Values | +| --------- | ---------------------------------------------------- | ------ | -------- | ------------------------- | +| noteAlign | This sets the text alignment of actor-attached notes | string | required | 'left', 'center', 'right' | + +**Notes:** Default value: 'center' + +### messageFontSize + +| Parameter | Description | Type | Required | Values | +| --------------- | ----------------------------------------- | ------- | -------- | ------------------- | +| messageFontSize | This sets the font size of actor messages | Integer | Required | Any Positive Number | + +**Notes:** Default value: 16 + +### messageFontFamily + +| Parameter | Description | Type | Required | Values | +| ----------------- | ------------------------------------------- | ------ | -------- | --------------------------- | +| messageFontFamily | This sets the font family of actor messages | string | Required | Any Possible CSS FontFamily | + +**Notes:** Default value: '"trebuchet ms", verdana, arial, sans-serif' + +### messageFontWeight + +This sets the font weight of the message's description + +**Notes:** Default value: 400. + +### wrap + +This sets the auto-wrap state for the diagram + +**Notes:** Default value: false. + +### wrapPadding + +This sets the auto-wrap padding for the diagram (sides only) + +**Notes:** Default value: 0. + +### labelBoxWidth + +This sets the width of the loop-box (loop, alt, opt, par) + +**Notes:** Default value: 50. + +### labelBoxHeight + +This sets the height of the loop-box (loop, alt, opt, par) + +**Notes:** Default value: 20. + +## gantt + +The object containing configurations specific for gantt diagrams + +### titleTopMargin + +### titleTopMargin + +| Parameter | Description | Type | Required | Values | +| -------------- | ---------------------------------------------- | ------- | -------- | ------------------ | +| titleTopMargin | Margin top for the text over the gantt diagram | Integer | Required | Any Positive Value | + +**Notes:** Default value: 25 + +### barHeight + +| Parameter | Description | Type | Required | Values | +| --------- | ----------------------------------- | ------- | -------- | ------------------ | +| barHeight | The height of the bars in the graph | Integer | Required | Any Positive Value | + +**Notes:** Default value: 20 + +### barGap + +| Parameter | Description | Type | Required | Values | +| --------- | ---------------------------------------------------------------- | ------- | -------- | ------------------ | +| barGap | The margin between the different activities in the gantt diagram | Integer | Optional | Any Positive Value | + +**Notes:** Default value: 4 + +### topPadding + +| Parameter | Description | Type | Required | Values | +| ---------- | -------------------------------------------------------------------------- | ------- | -------- | ------------------ | +| topPadding | Margin between title and gantt diagram and between axis and gantt diagram. | Integer | Required | Any Positive Value | + +**Notes:** Default value: 50 + +### rightPadding + +| Parameter | Description | Type | Required | Values | +| ------------ | ----------------------------------------------------------------------- | ------- | -------- | ------------------ | +| rightPadding | The space allocated for the section name to the right of the activities | Integer | Required | Any Positive Value | + +**Notes:** Default value: 75 + +### leftPadding + +| Parameter | Description | Type | Required | Values | +| ----------- | ---------------------------------------------------------------------- | ------- | -------- | ------------------ | +| leftPadding | The space allocated for the section name to the left of the activities | Integer | Required | Any Positive Value | + +**Notes:** Default value: 75 + +### gridLineStartPadding + +| Parameter | Description | Type | Required | Values | +| -------------------- | -------------------------------------------- | ------- | -------- | ------------------ | +| gridLineStartPadding | Vertical starting position of the grid lines | Integer | Required | Any Positive Value | + +**Notes:** Default value: 35 + +### fontSize + +| Parameter | Description | Type | Required | Values | +| --------- | ----------- | ------- | -------- | ------------------ | +| fontSize | Font size | Integer | Required | Any Positive Value | + +**Notes:** Default value: 11 + +### sectionFontSize + +| Parameter | Description | Type | Required | Values | +| --------------- | ---------------------- | ------- | -------- | ------------------ | +| sectionFontSize | Font size for sections | Integer | Required | Any Positive Value | + +**Notes:** Default value: 11 + +### numberSectionStyles + +| Parameter | Description | Type | Required | Values | +| ------------------- | ---------------------------------------- | ------- | -------- | ------------------ | +| numberSectionStyles | The number of alternating section styles | Integer | 4 | Any Positive Value | + +**Notes:** Default value: 4 + +### axisFormat + +| Parameter | Description | Type | Required | Values | +| ---------- | --------------------------- | ---- | -------- | ---------------- | +| axisFormat | Datetime format of the axis | 3 | Required | Date in yy-mm-dd | + +**Notes:** + +This might need adjustment to match your locale and preferences + +Default value: '%Y-%m-%d'. + +### useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See notes | boolean | 4 | true, false | + +**Notes:** + +When this flag is set the height and width is set to 100% and is then scaling with the +available space if not the absolute space required is used. + +Default value: true + +### topAxis + +| Parameter | Description | Type | Required | Values | +| --------- | ----------- | ------- | -------- | ----------- | +| topAxis | See notes | Boolean | 4 | True, False | + +**Notes:** when this flag is set date labels will be added to the top of the chart + +**Default value false**. + +## journey + +The object containing configurations specific for journey diagrams + +### diagramMarginX + +| Parameter | Description | Type | Required | Values | +| -------------- | ---------------------------------------------------- | ------- | -------- | ------------------ | +| diagramMarginX | Margin to the right and left of the sequence diagram | Integer | Required | Any Positive Value | + +**Notes:** Default value: 50 + +### diagramMarginY + +| Parameter | Description | Type | Required | Values | +| -------------- | -------------------------------------------------- | ------- | -------- | ------------------ | +| diagramMarginY | Margin to the over and under the sequence diagram. | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### leftMargin + +| Parameter | Description | Type | Required | Values | +| ----------- | --------------------- | ------- | -------- | ------------------ | +| actorMargin | Margin between actors | Integer | Required | Any Positive Value | + +**Notes:** Default value: 50 + +### width + +| Parameter | Description | Type | Required | Values | +| --------- | -------------------- | ------- | -------- | ------------------ | +| width | Width of actor boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 150 + +### height + +| Parameter | Description | Type | Required | Values | +| --------- | --------------------- | ------- | -------- | ------------------ | +| height | Height of actor boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 65 + +### boxMargin + +| Parameter | Description | Type | Required | Values | +| --------- | ------------------------ | ------- | -------- | ------------------ | +| boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### boxTextMargin + +| Parameter | Description | Type | Required | Values | +| ------------- | -------------------------------------------- | ------- | -------- | ------------------ | +| boxTextMargin | Margin around the text in loop/alt/opt boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 5 + +### noteMargin + +| Parameter | Description | Type | Required | Values | +| ---------- | ------------------- | ------- | -------- | ------------------ | +| noteMargin | Margin around notes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### messageMargin + +| Parameter | Description | Type | Required | Values | +| ------------- | ----------------------- | ------- | -------- | ------------------ | +| messageMargin | Space between messages. | Integer | Required | Any Positive Value | + +**Notes:** + +Space between messages. + +Default value: 35 + +### messageAlign + +| Parameter | Description | Type | Required | Values | +| ------------ | --------------------------- | ---- | -------- | ------------------------- | +| messageAlign | Multiline message alignment | 3 | 4 | 'left', 'center', 'right' | + +**Notes:** Default value: 'center' + +### bottomMarginAdj + +| Parameter | Description | Type | Required | Values | +| --------------- | ------------------------------------------ | ------- | -------- | ------------------ | +| bottomMarginAdj | Prolongs the edge of the diagram downwards | Integer | 4 | Any Positive Value | + +**Notes:** + +Depending on css styling this might need adjustment. + +Default value: 1 + +### useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See notes | boolean | 4 | true, false | + +**Notes:** + +When this flag is set the height and width is set to 100% and is then scaling with the +available space if not the absolute space required is used. + +Default value: true + +### rightAngles + +| Parameter | Description | Type | Required | Values | +| ----------- | --------------------------------- | ---- | -------- | ----------- | +| rightAngles | Curved Arrows become Right Angles | 3 | 4 | true, false | + +**Notes:** + +This will display arrows that start and begin at the same node as right angles, rather than a +curves + +Default value: false + +## timeline + +The object containing configurations specific for timeline diagrams + +### diagramMarginX + +| Parameter | Description | Type | Required | Values | +| -------------- | ---------------------------------------------------- | ------- | -------- | ------------------ | +| diagramMarginX | Margin to the right and left of the sequence diagram | Integer | Required | Any Positive Value | + +**Notes:** Default value: 50 + +### diagramMarginY + +| Parameter | Description | Type | Required | Values | +| -------------- | -------------------------------------------------- | ------- | -------- | ------------------ | +| diagramMarginY | Margin to the over and under the sequence diagram. | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### leftMargin + +| Parameter | Description | Type | Required | Values | +| ----------- | --------------------- | ------- | -------- | ------------------ | +| actorMargin | Margin between actors | Integer | Required | Any Positive Value | + +**Notes:** Default value: 50 + +### width + +| Parameter | Description | Type | Required | Values | +| --------- | -------------------- | ------- | -------- | ------------------ | +| width | Width of actor boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 150 + +### height + +| Parameter | Description | Type | Required | Values | +| --------- | --------------------- | ------- | -------- | ------------------ | +| height | Height of actor boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 65 + +### boxMargin + +| Parameter | Description | Type | Required | Values | +| --------- | ------------------------ | ------- | -------- | ------------------ | +| boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### boxTextMargin + +| Parameter | Description | Type | Required | Values | +| ------------- | -------------------------------------------- | ------- | -------- | ------------------ | +| boxTextMargin | Margin around the text in loop/alt/opt boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 5 + +### noteMargin + +| Parameter | Description | Type | Required | Values | +| ---------- | ------------------- | ------- | -------- | ------------------ | +| noteMargin | Margin around notes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### messageMargin + +| Parameter | Description | Type | Required | Values | +| ------------- | ----------------------- | ------- | -------- | ------------------ | +| messageMargin | Space between messages. | Integer | Required | Any Positive Value | + +**Notes:** + +Space between messages. + +Default value: 35 + +### messageAlign + +| Parameter | Description | Type | Required | Values | +| ------------ | --------------------------- | ---- | -------- | ------------------------- | +| messageAlign | Multiline message alignment | 3 | 4 | 'left', 'center', 'right' | + +**Notes:** Default value: 'center' + +### bottomMarginAdj + +| Parameter | Description | Type | Required | Values | +| --------------- | ------------------------------------------ | ------- | -------- | ------------------ | +| bottomMarginAdj | Prolongs the edge of the diagram downwards | Integer | 4 | Any Positive Value | + +**Notes:** + +Depending on css styling this might need adjustment. + +Default value: 1 + +### useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See notes | boolean | 4 | true, false | + +**Notes:** + +When this flag is set the height and width is set to 100% and is then scaling with the +available space if not the absolute space required is used. + +Default value: true + +### rightAngles + +| Parameter | Description | Type | Required | Values | +| ----------- | --------------------------------- | ---- | -------- | ----------- | +| rightAngles | Curved Arrows become Right Angles | 3 | 4 | true, false | + +**Notes:** + +This will display arrows that start and begin at the same node as right angles, rather than a +curves + +Default value: false + +## useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See notes | boolean | 4 | true, false | + +**Notes:** + +When this flag is set the height and width is set to 100% and is then scaling with the +available space if not the absolute space required is used. + +Default value: true + +## defaultRenderer + +| Parameter | Description | Type | Required | Values | +| --------------- | ----------- | ------- | -------- | ----------------------- | +| defaultRenderer | See notes | boolean | 4 | dagre-d3, dagre-wrapper | + +**Notes**: + +Decides which rendering engine that is to be used for the rendering. Legal values are: +dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid + +Default value: 'dagre-d3' + +## useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See notes | boolean | 4 | true, false | + +**Notes:** + +When this flag is set the height and width is set to 100% and is then scaling with the +available space if not the absolute space required is used. + +Default value: true + +## defaultRenderer + +| Parameter | Description | Type | Required | Values | +| --------------- | ----------- | ------- | -------- | ----------------------- | +| defaultRenderer | See notes | boolean | 4 | dagre-d3, dagre-wrapper | + +**Notes:** + +Decides which rendering engine that is to be used for the rendering. Legal values are: +dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid + +Default value: 'dagre-d3' + +## er + +The object containing configurations specific for entity relationship diagrams + +### diagramPadding + +| Parameter | Description | Type | Required | Values | +| -------------- | ----------------------------------------------- | ------- | -------- | ------------------ | +| diagramPadding | Amount of padding around the diagram as a whole | Integer | Required | Any Positive Value | + +**Notes:** + +The amount of padding around the diagram as a whole so that embedded diagrams have margins, +expressed in pixels + +Default value: 20 + +### layoutDirection + +| Parameter | Description | Type | Required | Values | +| --------------- | ---------------------------------------- | ------ | -------- | ---------------------- | +| layoutDirection | Directional bias for layout of entities. | string | Required | "TB", "BT", "LR", "RL" | + +**Notes:** + +'TB' for Top-Bottom, 'BT'for Bottom-Top, 'LR' for Left-Right, or 'RL' for Right to Left. + +T = top, B = bottom, L = left, and R = right. + +Default value: 'TB' + +### minEntityWidth + +| Parameter | Description | Type | Required | Values | +| -------------- | ---------------------------------- | ------- | -------- | ------------------ | +| minEntityWidth | The minimum width of an entity box | Integer | Required | Any Positive Value | + +**Notes:** Expressed in pixels. Default value: 100 + +### minEntityHeight + +| Parameter | Description | Type | Required | Values | +| --------------- | ----------------------------------- | ------- | -------- | ------------------ | +| minEntityHeight | The minimum height of an entity box | Integer | 4 | Any Positive Value | + +**Notes:** Expressed in pixels Default value: 75 + +### entityPadding + +| Parameter | Description | Type | Required | Values | +| ------------- | ------------------------------------------------------------ | ------- | -------- | ------------------ | +| entityPadding | Minimum internal padding between text in box and box borders | Integer | 4 | Any Positive Value | + +**Notes:** + +The minimum internal padding between text in an entity box and the enclosing box borders, +expressed in pixels. + +Default value: 15 + +### stroke + +| Parameter | Description | Type | Required | Values | +| --------- | ----------------------------------- | ------ | -------- | -------------------- | +| stroke | Stroke color of box edges and lines | string | 4 | Any recognized color | + +**Notes:** Default value: 'gray' + +### fill + +| Parameter | Description | Type | Required | Values | +| --------- | -------------------------- | ------ | -------- | -------------------- | +| fill | Fill color of entity boxes | string | 4 | Any recognized color | + +**Notes:** Default value: 'honeydew' + +### fontSize + +| Parameter | Description | Type | Required | Values | +| --------- | ------------------- | ------- | -------- | ------------------ | +| fontSize | Font Size in pixels | Integer | | Any Positive Value | + +**Notes:** + +Font size (expressed as an integer representing a number of pixels) Default value: 12 + +### useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See Notes | boolean | Required | true, false | + +**Notes:** + +When this flag is set to true, the diagram width is locked to 100% and scaled based on +available space. If set to false, the diagram reserves its absolute width. + +Default value: true + +## pie + +The object containing configurations specific for pie diagrams + +### useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See Notes | boolean | Required | true, false | + +**Notes:** + +When this flag is set to true, the diagram width is locked to 100% and scaled based on +available space. If set to false, the diagram reserves its absolute width. + +Default value: true + +## requirement + +The object containing configurations specific for req diagrams + +### useMaxWidth + +| Parameter | Description | Type | Required | Values | +| ----------- | ----------- | ------- | -------- | ----------- | +| useMaxWidth | See Notes | boolean | Required | true, false | + +**Notes:** + +When this flag is set to true, the diagram width is locked to 100% and scaled based on +available space. If set to false, the diagram reserves its absolute width. + +Default value: true + +## c4 + +The object containing configurations specific for c4 diagrams + +### diagramMarginX + +| 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 + +### diagramMarginY + +| Parameter | Description | Type | Required | Values | +| -------------- | ------------------------------------------- | ------- | -------- | ------------------ | +| diagramMarginY | Margin to the over and under the c4 diagram | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### c4ShapeMargin + +| Parameter | Description | Type | Required | Values | +| ------------- | --------------------- | ------- | -------- | ------------------ | +| c4ShapeMargin | Margin between shapes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 50 + +### c4ShapePadding + +| Parameter | Description | Type | Required | Values | +| -------------- | ---------------------- | ------- | -------- | ------------------ | +| c4ShapePadding | Padding between shapes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 20 + +### width + +| Parameter | Description | Type | Required | Values | +| --------- | --------------------- | ------- | -------- | ------------------ | +| width | Width of person boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 216 + +### height + +| Parameter | Description | Type | Required | Values | +| --------- | ---------------------- | ------- | -------- | ------------------ | +| height | Height of person boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 60 + +### boxMargin + +| Parameter | Description | Type | Required | Values | +| --------- | ------------------- | ------- | -------- | ------------------ | +| boxMargin | Margin around boxes | Integer | Required | Any Positive Value | + +**Notes:** Default value: 10 + +### useMaxWidth + +| 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 + +### c4ShapeInRow + +| 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 + +### c4BoundaryInRow + +| 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 + +### personFontSize + +This sets the font size of Person shape for the diagram + +**Notes:** Default value: 14. + +### personFontFamily + +This sets the font family of Person shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### personFontWeight + +This sets the font weight of Person shape for the diagram + +**Notes:** Default value: normal. + +### external_personFontSize + +This sets the font size of External Person shape for the diagram + +**Notes:** Default value: 14. + +### external_personFontFamily + +This sets the font family of External Person shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_personFontWeight + +This sets the font weight of External Person shape for the diagram + +**Notes:** Default value: normal. + +### systemFontSize + +This sets the font size of System shape for the diagram + +**Notes:** Default value: 14. + +### systemFontFamily + +This sets the font family of System shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### systemFontWeight + +This sets the font weight of System shape for the diagram + +**Notes:** Default value: normal. + +### external_systemFontSize + +This sets the font size of External System shape for the diagram + +**Notes:** Default value: 14. + +### external_systemFontFamily + +This sets the font family of External System shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_systemFontWeight + +This sets the font weight of External System shape for the diagram + +**Notes:** Default value: normal. + +### system_dbFontSize + +This sets the font size of System DB shape for the diagram + +**Notes:** Default value: 14. + +### system_dbFontFamily + +This sets the font family of System DB shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### system_dbFontWeight + +This sets the font weight of System DB shape for the diagram + +**Notes:** Default value: normal. + +### external_system_dbFontSize + +This sets the font size of External System DB shape for the diagram + +**Notes:** Default value: 14. + +### external_system_dbFontFamily + +This sets the font family of External System DB shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_system_dbFontWeight + +This sets the font weight of External System DB shape for the diagram + +**Notes:** Default value: normal. + +### system_queueFontSize + +This sets the font size of System Queue shape for the diagram + +**Notes:** Default value: 14. + +### system_queueFontFamily + +This sets the font family of System Queue shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### system_queueFontWeight + +This sets the font weight of System Queue shape for the diagram + +**Notes:** Default value: normal. + +### external_system_queueFontSize + +This sets the font size of External System Queue shape for the diagram + +**Notes:** Default value: 14. + +### external_system_queueFontFamily + +This sets the font family of External System Queue shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_system_queueFontWeight + +This sets the font weight of External System Queue shape for the diagram + +**Notes:** Default value: normal. + +### boundaryFontSize + +This sets the font size of Boundary shape for the diagram + +**Notes:** Default value: 14. + +### boundaryFontFamily + +This sets the font family of Boundary shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### boundaryFontWeight + +This sets the font weight of Boundary shape for the diagram + +**Notes:** Default value: normal. + +### messageFontSize + +This sets the font size of Message shape for the diagram + +**Notes:** Default value: 12. + +### messageFontFamily + +This sets the font family of Message shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### messageFontWeight + +This sets the font weight of Message shape for the diagram + +**Notes:** Default value: normal. + +### containerFontSize + +This sets the font size of Container shape for the diagram + +**Notes:** Default value: 14. + +### containerFontFamily + +This sets the font family of Container shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### containerFontWeight + +This sets the font weight of Container shape for the diagram + +**Notes:** Default value: normal. + +### external_containerFontSize + +This sets the font size of External Container shape for the diagram + +**Notes:** Default value: 14. + +### external_containerFontFamily + +This sets the font family of External Container shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_containerFontWeight + +This sets the font weight of External Container shape for the diagram + +**Notes:** Default value: normal. + +### container_dbFontSize + +This sets the font size of Container DB shape for the diagram + +**Notes:** Default value: 14. + +### container_dbFontFamily + +This sets the font family of Container DB shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### container_dbFontWeight + +This sets the font weight of Container DB shape for the diagram + +**Notes:** Default value: normal. + +### external_container_dbFontSize + +This sets the font size of External Container DB shape for the diagram + +**Notes:** Default value: 14. + +### external_container_dbFontFamily + +This sets the font family of External Container DB shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_container_dbFontWeight + +This sets the font weight of External Container DB shape for the diagram + +**Notes:** Default value: normal. + +### container_queueFontSize + +This sets the font size of Container Queue shape for the diagram + +**Notes:** Default value: 14. + +### container_queueFontFamily + +This sets the font family of Container Queue shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### container_queueFontWeight + +This sets the font weight of Container Queue shape for the diagram + +**Notes:** Default value: normal. + +### external_container_queueFontSize + +This sets the font size of External Container Queue shape for the diagram + +**Notes:** Default value: 14. + +### external_container_queueFontFamily + +This sets the font family of External Container Queue shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_container_queueFontWeight + +This sets the font weight of External Container Queue shape for the diagram + +**Notes:** Default value: normal. + +### componentFontSize + +This sets the font size of Component shape for the diagram + +**Notes:** Default value: 14. + +### componentFontFamily + +This sets the font family of Component shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### componentFontWeight + +This sets the font weight of Component shape for the diagram + +**Notes:** Default value: normal. + +### external_componentFontSize + +This sets the font size of External Component shape for the diagram + +**Notes:** Default value: 14. + +### external_componentFontFamily + +This sets the font family of External Component shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_componentFontWeight + +This sets the font weight of External Component shape for the diagram + +**Notes:** Default value: normal. + +### component_dbFontSize + +This sets the font size of Component DB shape for the diagram + +**Notes:** Default value: 14. + +### component_dbFontFamily + +This sets the font family of Component DB shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### component_dbFontWeight + +This sets the font weight of Component DB shape for the diagram + +**Notes:** Default value: normal. + +### external_component_dbFontSize + +This sets the font size of External Component DB shape for the diagram + +**Notes:** Default value: 14. + +### external_component_dbFontFamily + +This sets the font family of External Component DB shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_component_dbFontWeight + +This sets the font weight of External Component DB shape for the diagram + +**Notes:** Default value: normal. + +### component_queueFontSize + +This sets the font size of Component Queue shape for the diagram + +**Notes:** Default value: 14. + +### component_queueFontFamily + +This sets the font family of Component Queue shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### component_queueFontWeight + +This sets the font weight of Component Queue shape for the diagram + +**Notes:** Default value: normal. + +### external_component_queueFontSize + +This sets the font size of External Component Queue shape for the diagram + +**Notes:** Default value: 14. + +### external_component_queueFontFamily + +This sets the font family of External Component Queue shape for the diagram + +**Notes:** Default value: "Open Sans", sans-serif. + +### external_component_queueFontWeight + +This sets the font weight of External Component Queue shape for the diagram + +**Notes:** Default value: normal. + +### wrap + +This sets the auto-wrap state for the diagram + +**Notes:** Default value: true. + +### wrapPadding + +This sets the auto-wrap padding for the diagram (sides only) + +**Notes:** Default value: 0. + +## parse + +### Parameters + +- `text` **[string][4]** +- `parseError` **[Function][5]?** + +Returns **[boolean][6]** + +## setSiteConfig + +## setSiteConfig + +| Function | Description | Type | Values | +| ------------- | ------------------------------------- | ----------- | --------------------------------------- | +| setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array | + +**Notes:** Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls +to reset() will reset the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig) +will reset siteConfig and currentConfig to the defaultConfig Note: currentConfig is set in this +function _Default value: At default, will mirror Global Config_ + +### Parameters + +- `conf` **MermaidConfig** The base currentConfig to use as siteConfig + +Returns **[object][7]** The siteConfig + +## getSiteConfig + +## getSiteConfig + +| Function | Description | Type | Values | +| ------------- | ------------------------------------------------- | ----------- | -------------------------------- | +| setSiteConfig | Returns the current siteConfig base configuration | Get Request | Returns Any Values in siteConfig | + +**Notes**: Returns **any** values in siteConfig. + +Returns **[object][7]** The siteConfig + +## setConfig + +## setConfig + +| Function | Description | Type | Values | +| ------------- | ------------------------------------- | ----------- | --------------------------------------- | +| setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array | + +**Notes**: Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure +keys. Any values found in conf with key found in siteConfig.secure will be replaced with the +corresponding siteConfig value. + +### Parameters + +- `conf` **any** The potential currentConfig + +Returns **any** The currentConfig merged with the sanitized conf + +## render + +Function that renders an svg with a graph from a chart definition. Usage example below. + +```javascript +mermaidAPI.initialize({ + startOnLoad: true, +}); +$(function () { + const graphDefinition = 'graph TB\na-->b'; + const cb = function (svgGraph) { + console.log(svgGraph); + }; + mermaidAPI.render('id1', graphDefinition, cb); +}); +``` + +### Parameters + +- `id` **[string][4]** The id of the element to be rendered +- `text` **[string][4]** The graph definition +- `cb` **function (svgCode: [string][4], bindFunctions: function (element: [Element][8]): void): void** +- `container` **[Element][8]** Selector to element in which a div with the graph temporarily will be + inserted. If one is provided a hidden div will be inserted in the body of the page instead. The + element will be removed when rendering is completed. + +Returns **void** + +## getConfig + +## getConfig + +| Function | Description | Type | Return Values | +| --------- | ------------------------- | ----------- | ------------------------------ | +| getConfig | Obtains the currentConfig | Get Request | Any Values from current Config | + +**Notes**: Returns **any** the currentConfig + +Returns **any** The currentConfig + +## sanitize + +## sanitize + +| Function | Description | Type | Values | +| -------- | -------------------------------------- | ----------- | ------ | +| sanitize | Sets the siteConfig to desired values. | Put Request | None | + +Ensures options parameter does not attempt to override siteConfig secure keys **Notes**: modifies +options in-place + +### Parameters + +- `options` **any** The potential setConfig parameter + +## addDirective + +Pushes in a directive to the configuration + +### Parameters + +- `directive` **[object][7]** The directive to push in + +## reset + +## reset + +| Function | Description | Type | Required | Values | +| -------- | ---------------------------- | ----------- | -------- | ------ | +| reset | Resets currentConfig to conf | Put Request | Required | None | + +## conf + +| Parameter | Description | Type | Required | Values | +| --------- | -------------------------------------------------------------- | ---------- | -------- | -------------------------------------------- | +| conf | base set of values, which currentConfig could be **reset** to. | Dictionary | Required | Any Values, with respect to the secure Array | + +**Notes**: (default: current siteConfig ) (optional, default `getSiteConfig()`) + +### Parameters + +- `config` (optional, default `siteConfig`) + +Returns **void** + +## initialize + +### Parameters + +- `options` **MermaidConfig** + +## + +## mermaidAPI configuration defaults + +```html + +``` + +[1]: Setup.md?id=render +[2]: 8.6.0_docs.md +[3]: #mermaidapi-configuration-defaults +[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function +[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[8]: https://developer.mozilla.org/docs/Web/API/Element diff --git a/cypress/platform/ashish2.html b/cypress/platform/ashish2.html new file mode 100644 index 000000000..e10ea6a2d --- /dev/null +++ b/cypress/platform/ashish2.html @@ -0,0 +1,162 @@ + + + + + + + + + + +
Security check
+
+flowchart TD
+    A --> B
+    B --> C
+    A --> C
+    
+
+classDiagram
+        direction LR
+        class Student {
+          -idCard : IdCard
+        }
+        class IdCard{
+          -id : int
+          -name : string
+        }
+        class Bike{
+          -id : int
+          -name : string
+        }
+        Student "1" --o "1" IdCard : carries
+        Student "1" --o "1" Bike : rides
+    
+
+ timeline
+        title History of Social Media Platform
+          2002 : LinkedIn
+          2004 : Facebook : Google
+          2005 : Youtube
+          2006 : Twitter
+          2007 : Tumblr
+          2008s : Instagram
+          2010 : Pinterest
+    
+
+mindmap
+  root
+    child1((Circle))
+        grandchild 1
+        grandchild 2
+    child2(Round rectangle)
+        grandchild 3
+        grandchild 4
+    child3[Square]
+        grandchild 5
+        ::icon(mdi mdi-fire)
+        gc6((grand
child 6)) + ::icon(mdi mdi-fire) + gc7((grand
grand
child 8)) +
+
+      gantt
+        title Style today marker (vertical line should be 5px wide and half-transparent blue)
+        dateFormat YYYY-MM-DD
+        axisFormat %d
+        todayMarker stroke-width:5px,stroke:#00f,opacity:0.5
+        section Section1
+        Today: 1, -1h
+    
+ + + + + + + + diff --git a/cypress/platform/class.html b/cypress/platform/class.html index 85fae2a77..1d72c34a5 100644 --- a/cypress/platform/class.html +++ b/cypress/platform/class.html @@ -46,13 +46,9 @@
       %%{init: {'theme': 'base',  'fontFamily': 'courier', 'themeVariables': {  'primaryColor': '#fff000'}}}%%
       classDiagram-v2
-       class BankAccount{
-        +String owner
-        +BigDecimal balance
-        +deposit(amount) bool
-        +withdrawl(amount) int
-       }
-       cssClass "BankAccount" customCss
+classA <|-- classB : implements
+classC *-- classD : composition
+classE o-- classF : aggregation
     
         %%{init: {'theme': 'base',  'fontFamily': 'courier', 'themeVariables': {  'primaryColor': '#fff000'}}}%%
diff --git a/demos/timeline.html b/demos/timeline.html
new file mode 100644
index 000000000..f90f37675
--- /dev/null
+++ b/demos/timeline.html
@@ -0,0 +1,38 @@
+
+
+  
+    
+    
+    Mermaid Quick Test Page
+    
+    
+  
+
+  
+    
+        timeline
+        title My day
+        section Go to work
+          1930 : first step : second step
+               : third step
+          1940 : fourth step : fifth step
+				
+ + + + + diff --git a/packages/mermaid-example-diagram/src/mermaidUtils.ts b/packages/mermaid-example-diagram/src/mermaidUtils.ts index 8894abdff..698203f19 100644 --- a/packages/mermaid-example-diagram/src/mermaidUtils.ts +++ b/packages/mermaid-example-diagram/src/mermaidUtils.ts @@ -22,6 +22,7 @@ export const log: Record = { export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void; export let getConfig: () => object; export let sanitizeText: (str: string) => string; +export let commonDb: any; /** * Placeholder for the real function that will be injected by mermaid. */ @@ -41,15 +42,17 @@ export let setupGraphViewbox: ( * @param _getConfig - getConfig from mermaid/src/diagramAPI.ts * @param _sanitizeText - sanitizeText from mermaid/src/diagramAPI.ts * @param _setupGraphViewbox - setupGraphViewbox from mermaid/src/diagramAPI.ts + * @param _commonDb */ export const injectUtils = ( _log: Record, _setLogLevel: typeof setLogLevel, _getConfig: typeof getConfig, _sanitizeText: typeof sanitizeText, - _setupGraphViewbox: typeof setupGraphViewbox + _setupGraphViewbox: typeof setupGraphViewbox, + _commonDb: any ) => { - _log.debug('Mermaid utils injected into example-diagram'); + _log.info('Mermaid utils injected into timeline-diagram'); log.trace = _log.trace; log.debug = _log.debug; log.info = _log.info; @@ -60,4 +63,6 @@ export const injectUtils = ( getConfig = _getConfig; sanitizeText = _sanitizeText; setupGraphViewbox = _setupGraphViewbox; + commonDb = _commonDb; + }; diff --git a/packages/mermaid-mindmap/src/mermaidUtils.ts b/packages/mermaid-mindmap/src/mermaidUtils.ts index 7d8ac38bf..4834b936d 100644 --- a/packages/mermaid-mindmap/src/mermaidUtils.ts +++ b/packages/mermaid-mindmap/src/mermaidUtils.ts @@ -26,6 +26,7 @@ export const log: Record = { export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void; export let getConfig: () => object; export let sanitizeText: (str: string) => string; +export let commonDb: () => object; // eslint-disable @typescript-eslint/no-explicit-any export let setupGraphViewbox: ( graph: any, @@ -39,7 +40,8 @@ export const injectUtils = ( _setLogLevel: any, _getConfig: any, _sanitizeText: any, - _setupGraphViewbox: any + _setupGraphViewbox: any, + _commonDb: any ) => { _log.info('Mermaid utils injected'); log.trace = _log.trace; @@ -52,4 +54,5 @@ export const injectUtils = ( getConfig = _getConfig; sanitizeText = _sanitizeText; setupGraphViewbox = _setupGraphViewbox; + commonDb= _commonDb; }; diff --git a/packages/mermaid-mindmap/src/mindmapRenderer.js b/packages/mermaid-mindmap/src/mindmapRenderer.js index 9fd557e51..17f2d0097 100644 --- a/packages/mermaid-mindmap/src/mindmapRenderer.js +++ b/packages/mermaid-mindmap/src/mindmapRenderer.js @@ -11,7 +11,7 @@ cytoscape.use(coseBilkent); /** * @param {any} svg The svg element to draw the diagram onto - * @param {object} mindmap The mindmap data and hierarchy + * @param {object} mindmap The maindmap data and hierarchy * @param section * @param {object} conf The configuration object */ @@ -89,6 +89,7 @@ function addNodes(mindmap, cy, conf, level) { /** * @param node * @param conf + * @param cy */ function layoutMindmap(node, conf) { return new Promise((resolve) => { @@ -109,7 +110,7 @@ function layoutMindmap(node, conf) { renderEl.remove(); addNodes(node, cy, conf, 0); - // Make cytoscape care about the dimensions of the nodes + // Make cytoscape care about the dimensisions of the nodes cy.nodes().forEach(function (n) { n.layoutDimensions = () => { const data = n.data(); @@ -131,7 +132,10 @@ function layoutMindmap(node, conf) { }); } /** + * @param node * @param cy + * @param positionedMindmap + * @param conf */ function positionNodes(cy) { cy.nodes().map((node, id) => { @@ -169,7 +173,7 @@ export const draw = async (text, id, version, diagObj) => { log.debug('Renering info diagram\n' + text); const securityLevel = getConfig().securityLevel; - // Handle root and Document for when rendering in sandbox mode + // Handle root and Document for when rendering in sanbox mode let sandboxElement; if (securityLevel === 'sandbox') { sandboxElement = select('#i' + id); diff --git a/packages/mermaid-timeline/package.json b/packages/mermaid-timeline/package.json new file mode 100644 index 000000000..0c2ebf136 --- /dev/null +++ b/packages/mermaid-timeline/package.json @@ -0,0 +1,69 @@ +{ + "name": "@mermaid-js/mermaid-timeline", + "version": "9.2.0-rc2", + "description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", + "main": "dist/mermaid-timeline.core.mjs", + "module": "dist/mermaid-timeline.core.mjs", + "type": "module", + "exports": { + ".": { + "require": "./dist/mermaid-timeline.min.js", + "import": "./dist/mermaid-timeline.core.mjs" + }, + "./*": "./*" + }, + "keywords": [ + "diagram", + "markdown", + "timeline", + "mermaid" + ], + "scripts": { + "clean": "rimraf dist", + "build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly", + "build:watch": "yarn build:code --watch", + "build:esbuild": "concurrently \"yarn build:code\" \"yarn build:types\"", + "build": "yarn clean; yarn build:esbuild", + "dev": "node .esbuild/serve.cjs", + "release": "yarn build", + "lint": "eslint --cache --ignore-path .gitignore . && yarn lint:jison && prettier --check .", + "lint:fix": "eslint --fix --ignore-path .gitignore . && prettier --write .", + "lint:jison": "ts-node-esm src/jison/lint.mts", + "todo-prepare": "concurrently \"husky install ../../.husky\" \"yarn build\"", + "todo-pre-commit": "lint-staged" + }, + "repository": { + "type": "git", + "url": "https://github.com/mermaid-js/mermaid" + }, + "author": "Knut Sveidqvist", + "license": "MIT", + "standard": { + "ignore": [ + "**/parser/*.js", + "dist/**/*.js", + "cypress/**/*.js" + ], + "globals": [ + "page" + ] + }, + "dependencies": { + "d3": "^7.0.0", + "khroma": "^2.0.0" + }, + "devDependencies": { + "concurrently": "^7.4.0", + "rimraf": "^3.0.2" + }, + "resolutions": { + "d3": "^7.0.0" + }, + "files": [ + "dist" + ], + "sideEffects": [ + "**/*.css", + "**/*.scss" + ] +} \ No newline at end of file diff --git a/packages/mermaid-timeline/src/detector.ts b/packages/mermaid-timeline/src/detector.ts new file mode 100644 index 000000000..411fe48d6 --- /dev/null +++ b/packages/mermaid-timeline/src/detector.ts @@ -0,0 +1,20 @@ +import type { ExternalDiagramDefinition } from 'mermaid'; + +const id = 'timeline'; + +const detector = (txt: string) => { + return txt.match(/^\s*timeline/) !== null; +}; + +const loader = async () => { + const { diagram } = await import('./diagram-definition'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid-timeline/src/diagram-definition.ts b/packages/mermaid-timeline/src/diagram-definition.ts new file mode 100644 index 000000000..9f18f261d --- /dev/null +++ b/packages/mermaid-timeline/src/diagram-definition.ts @@ -0,0 +1,14 @@ +// @ts-ignore: TODO Fix ts errors +import parser from './parser/timeline.jison'; +import * as db from './timelineDb'; +import renderer from './timelineRenderer'; +import styles from './styles'; +import { injectUtils } from './mermaidUtils'; + +export const diagram = { + db, + renderer, + parser, + styles, + injectUtils, +}; diff --git a/packages/mermaid-timeline/src/mermaidUtils.ts b/packages/mermaid-timeline/src/mermaidUtils.ts new file mode 100644 index 000000000..7dc3732a8 --- /dev/null +++ b/packages/mermaid-timeline/src/mermaidUtils.ts @@ -0,0 +1,70 @@ +const warning = () => null; +let localCommonDb = {}; + +export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; + +export const LEVELS: Record = { + trace: 0, + debug: 1, + info: 2, + warn: 3, + error: 4, + fatal: 5, +}; + +export const log: Record = { + trace: warning, + debug: warning, + info: warning, + warn: warning, + error: warning, + fatal: warning, +}; +export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void; +export let getConfig: () => object; +export let sanitizeText: (str: string) => string; +export const getCommonDb=() => localCommonDb; +/** + * Placeholder for the real function that will be injected by mermaid. + */ +// eslint-disable @typescript-eslint/no-explicit-any +export let setupGraphViewbox: ( + graph: any, + svgElem: any, + padding: any, + useMaxWidth: boolean +) => void; + + + +/** + * Function called by mermaid that injects utility functions that help the diagram to be a good citizen. + * @param _log + * @param _setLogLevel + * @param _getConfig + * @param _sanitizeText + * @param _setupGraphViewbox + * @param _commonDb + */ +export const injectUtils = ( + _log: Record, + _setLogLevel: any, + _getConfig: any, + _sanitizeText: any, + _setupGraphViewbox: any, + _commonDb: any +) => { + _log.info('Mermaid utils injected into timeline-diagram'); + log.trace = _log.trace; + log.debug = _log.debug; + log.info = _log.info; + log.warn = _log.warn; + log.error = _log.error; + log.fatal = _log.fatal; + setLogLevel = _setLogLevel; + getConfig = _getConfig; + sanitizeText = _sanitizeText; + setupGraphViewbox = _setupGraphViewbox; + localCommonDb = _commonDb; + +}; diff --git a/packages/mermaid-timeline/src/parser/timeline.jison b/packages/mermaid-timeline/src/parser/timeline.jison new file mode 100644 index 000000000..4f8ac5cbc --- /dev/null +++ b/packages/mermaid-timeline/src/parser/timeline.jison @@ -0,0 +1,106 @@ +/** mermaid + * https://mermaidjs.github.io/ + * (c) 2015 Knut Sveidqvist + * MIT license. + */ +%lex +%options case-insensitive +%x acc_title +%x acc_descr +%x acc_descr_multiline + +// Directive states +%x open_directive type_directive arg_directive + + +%% + +\%\%\{ { this.begin('open_directive'); return 'open_directive'; } +((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } +":" { this.popState(); this.begin('arg_directive'); return ':'; } +\}\%\% { this.popState(); this.popState(); return 'close_directive'; } +((?:(?!\}\%\%).|\n)*) return 'arg_directive'; +\%%(?!\{)[^\n]* /* skip comments */ +[^\}]\%\%[^\n]* /* skip comments */ +[\n]+ return 'NEWLINE'; +\s+ /* skip whitespace */ +\#[^\n]* /* skip comments */ + +"timeline" return 'timeline'; +"title"\s[^#\n;]+ return 'title'; +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"; +"section"\s[^#:\n;]+ return 'section'; + +// event starting with "==>" keyword +":"\s[^#:\n;]+ return 'event'; +[^#:\n;]+ return 'period'; + + +<> return 'EOF'; +. return 'INVALID'; + +/lex + +%left '^' + +%start start + +%% /* language grammar */ + +start + : timeline document 'EOF' { return $2; } + | directive start + ; + +document + : /* empty */ { $$ = [] } + | document line {$1.push($2);$$ = $1} + ; + +line + : SPACE statement { $$ = $2 } + | statement { $$ = $1 } + | NEWLINE { $$=[];} + | EOF { $$=[];} + ; + +directive + : openDirective typeDirective closeDirective 'NEWLINE' + | openDirective typeDirective ':' argDirective closeDirective 'NEWLINE' + ; + +statement + : title {yy.getCommonDb().setDiagramTitle($1.substr(6));$$=$1.substr(6);} + | acc_title acc_title_value { $$=$2.trim();yy.getCommonDb().setAccTitle($$); } + | acc_descr acc_descr_value { $$=$2.trim();yy.getCommonDb().setAccDescription($$); } + | acc_descr_multiline_value { $$=$1.trim();yy.getCommonDb().setAccDescription($$); } + | section {yy.addSection($1.substr(8));$$=$1.substr(8);} + | period {yy.addTask($1,0,'');$$=$1;} + | period event {yy.addTask($1,0,$2.substr(2));$$=$1;} + | event {yy.addEvent($1.substr(2));$$=$1;} + | directive + ; + +openDirective + : open_directive { yy.parseDirective('%%{', 'open_directive'); } + ; + +typeDirective + : type_directive { yy.parseDirective($1, 'type_directive'); } + ; + +argDirective + : arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); } + ; + +closeDirective + : close_directive { yy.parseDirective('}%%', 'close_directive', 'timeline'); } + ; + +%% diff --git a/packages/mermaid-timeline/src/parser/timeline.spec.js b/packages/mermaid-timeline/src/parser/timeline.spec.js new file mode 100644 index 000000000..cc54d9f78 --- /dev/null +++ b/packages/mermaid-timeline/src/parser/timeline.spec.js @@ -0,0 +1,150 @@ +import { parser } from './journey'; +import journeyDb from '../journeyDb'; + +const parserFnConstructor = (str) => { + return () => { + parser.parse(str); + }; +}; + +describe('when parsing a journey diagram it', function () { + beforeEach(function () { + parser.yy = journeyDb; + parser.yy.clear(); + }); + + it('should handle a title definition', function () { + const str = 'journey\ntitle Adding journey diagram functionality to mermaid'; + + expect(parserFnConstructor(str)).not.toThrow(); + }); + + it('should handle an accessibility description (accDescr)', function () { + const str = + 'journey\n' + + 'accDescr: A user journey for family shopping\n' + + 'title Adding journey diagram functionality to mermaid\n' + + 'section Order from website'; + + expect(parserFnConstructor(str)).not.toThrow(); + }); + it('should handle an accessibility multiline description (accDescr)', function () { + const str = + 'journey\n' + + `accDescr { + A user journey for + family shopping + }` + + 'title Adding journey diagram functionality to mermaid\n' + + 'accTitle: Adding acc journey diagram functionality to mermaid\n' + + 'section Order from website'; + + expect(parserFnConstructor(str)).not.toThrow(); + expect(journeyDb.getAccDescription()).toBe('A user journey for\nfamily shopping'); + expect(journeyDb.getDiagramTitle()).toBe('Adding journey diagram functionality to mermaid'); + expect(journeyDb.getAccTitle()).toBe('Adding acc journey diagram functionality to mermaid'); + }); + it('should handle an accessibility title (accDescr)', function () { + const str = `journey + accTitle: The title + section Order from website`; + + expect(parserFnConstructor(str)).not.toThrow(); + expect(journeyDb.getAccDescription()).toBe(''); + expect(journeyDb.getAccTitle()).toBe('The title'); + }); + + it('should handle a section definition', function () { + const str = + 'journey\n' + + 'title Adding journey diagram functionality to mermaid\n' + + 'section Order from website'; + + expect(parserFnConstructor(str)).not.toThrow(); + }); + it('should handle multiline section titles with different line breaks', function () { + const str = + 'journey\n' + + 'title Adding gantt diagram functionality to mermaid\n' + + 'section Line1
Line2
Line3
Line4Line5'; + + expect(parserFnConstructor(str)).not.toThrow(); + }); + + it('should handle a task definition', function () { + const str = + 'journey\n' + + 'title Adding journey diagram functionality to mermaid\n' + + 'section Documentation\n' + + 'A task: 5: Alice, Bob, Charlie\n' + + 'B task: 3:Bob, Charlie\n' + + 'C task: 5\n' + + 'D task: 5: Charlie, Alice\n' + + 'E task: 5:\n' + + 'section Another section\n' + + 'P task: 5:\n' + + 'Q task: 5:\n' + + 'R task: 5:'; + expect(parserFnConstructor(str)).not.toThrow(); + + const tasks = parser.yy.getTasks(); + expect(tasks.length).toEqual(8); + + expect(tasks[0]).toEqual({ + score: 5, + people: ['Alice', 'Bob', 'Charlie'], + section: 'Documentation', + task: 'A task', + type: 'Documentation', + }); + expect(tasks[1]).toEqual({ + score: 3, + people: ['Bob', 'Charlie'], + section: 'Documentation', + type: 'Documentation', + task: 'B task', + }); + expect(tasks[2]).toEqual({ + score: 5, + people: [], + section: 'Documentation', + type: 'Documentation', + task: 'C task', + }); + expect(tasks[3]).toEqual({ + score: 5, + people: ['Charlie', 'Alice'], + section: 'Documentation', + task: 'D task', + type: 'Documentation', + }); + expect(tasks[4]).toEqual({ + score: 5, + people: [''], + section: 'Documentation', + type: 'Documentation', + task: 'E task', + }); + expect(tasks[5]).toEqual({ + score: 5, + people: [''], + section: 'Another section', + type: 'Another section', + task: 'P task', + }); + expect(tasks[6]).toEqual({ + score: 5, + people: [''], + section: 'Another section', + type: 'Another section', + task: 'Q task', + }); + expect(tasks[7]).toEqual({ + score: 5, + people: [''], + section: 'Another section', + type: 'Another section', + task: 'R task', + }); + }); +}); diff --git a/packages/mermaid-timeline/src/styles.js b/packages/mermaid-timeline/src/styles.js new file mode 100644 index 000000000..51d69f58d --- /dev/null +++ b/packages/mermaid-timeline/src/styles.js @@ -0,0 +1,78 @@ +import { darken, lighten, isDark } from 'khroma'; + +const genSections = (options) => { + let sections = ''; + + for (let i = 0; i < options.THEME_COLOR_LIMIT; i++) { + options['lineColor' + i] = options['lineColor' + i] || options['cScaleInv' + i]; + if (isDark(options['lineColor' + i])) { + options['lineColor' + i] = lighten(options['lineColor' + i], 20); + } else { + options['lineColor' + i] = darken(options['lineColor' + i], 20); + } + } + + for (let i = 0; i < options.THEME_COLOR_LIMIT; i++) { + const sw = '' + (17 - 3 * i); + sections += ` + .section-${i - 1} rect, .section-${i - 1} path, .section-${i - 1} circle, .section-${ + i - 1 + } path { + fill: ${options['cScale' + i]}; + } + .section-${i - 1} text { + fill: ${options['cScaleLabel' + i]}; + } + .node-icon-${i - 1} { + font-size: 40px; + color: ${options['cScaleLabel' + i]}; + } + .section-edge-${i - 1}{ + stroke: ${options['cScale' + i]}; + } + .edge-depth-${i - 1}{ + stroke-width: ${sw}; + } + .section-${i - 1} line { + stroke: ${options['cScaleInv' + i]} ; + stroke-width: 3; + } + + .disabled, .disabled circle, .disabled text { + fill: lightgray; + } + .disabled text { + fill: #efefef; + } + `; + } + return sections; +}; + +const getStyles = (options) => + ` + .edge { + stroke-width: 3; + } + ${genSections(options)} + .section-root rect, .section-root path, .section-root circle { + fill: ${options.git0}; + } + .section-root text { + fill: ${options.gitBranchLabel0}; + } + .icon-container { + height:100%; + display: flex; + justify-content: center; + align-items: center; + } + .edge { + fill: none; + } + .eventWrapper { + filter: brightness(120%); + + } +`; +export default getStyles; diff --git a/packages/mermaid-timeline/src/svgDraw.js b/packages/mermaid-timeline/src/svgDraw.js new file mode 100644 index 000000000..bed0e2942 --- /dev/null +++ b/packages/mermaid-timeline/src/svgDraw.js @@ -0,0 +1,604 @@ +import { arc as d3arc , select} from 'd3'; +const MAX_SECTIONS = 12; + +export const drawRect = function (elem, rectData) { + const rectElem = elem.append('rect'); + rectElem.attr('x', rectData.x); + rectElem.attr('y', rectData.y); + rectElem.attr('fill', rectData.fill); + rectElem.attr('stroke', rectData.stroke); + rectElem.attr('width', rectData.width); + rectElem.attr('height', rectData.height); + rectElem.attr('rx', rectData.rx); + rectElem.attr('ry', rectData.ry); + + if (typeof rectData.class !== 'undefined') { + rectElem.attr('class', rectData.class); + } + + return rectElem; +}; + +export const drawFace = function (element, faceData) { + const radius = 15; + const circleElement = element + .append('circle') + .attr('cx', faceData.cx) + .attr('cy', faceData.cy) + .attr('class', 'face') + .attr('r', radius) + .attr('stroke-width', 2) + .attr('overflow', 'visible'); + + const face = element.append('g'); + + //left eye + face + .append('circle') + .attr('cx', faceData.cx - radius / 3) + .attr('cy', faceData.cy - radius / 3) + .attr('r', 1.5) + .attr('stroke-width', 2) + .attr('fill', '#666') + .attr('stroke', '#666'); + + //right eye + face + .append('circle') + .attr('cx', faceData.cx + radius / 3) + .attr('cy', faceData.cy - radius / 3) + .attr('r', 1.5) + .attr('stroke-width', 2) + .attr('fill', '#666') + .attr('stroke', '#666'); + + /** @param {any} face */ + function smile(face) { + const arc = d3arc() + .startAngle(Math.PI / 2) + .endAngle(3 * (Math.PI / 2)) + .innerRadius(radius / 2) + .outerRadius(radius / 2.2); + //mouth + face + .append('path') + .attr('class', 'mouth') + .attr('d', arc) + .attr('transform', 'translate(' + faceData.cx + ',' + (faceData.cy + 2) + ')'); + } + + /** @param {any} face */ + function sad(face) { + const arc = d3arc() + .startAngle((3 * Math.PI) / 2) + .endAngle(5 * (Math.PI / 2)) + .innerRadius(radius / 2) + .outerRadius(radius / 2.2); + //mouth + face + .append('path') + .attr('class', 'mouth') + .attr('d', arc) + .attr('transform', 'translate(' + faceData.cx + ',' + (faceData.cy + 7) + ')'); + } + + /** @param {any} face */ + function ambivalent(face) { + face + .append('line') + .attr('class', 'mouth') + .attr('stroke', 2) + .attr('x1', faceData.cx - 5) + .attr('y1', faceData.cy + 7) + .attr('x2', faceData.cx + 5) + .attr('y2', faceData.cy + 7) + .attr('class', 'mouth') + .attr('stroke-width', '1px') + .attr('stroke', '#666'); + } + + if (faceData.score > 3) { + smile(face); + } else if (faceData.score < 3) { + sad(face); + } else { + ambivalent(face); + } + + return circleElement; +}; + +export const drawCircle = function (element, circleData) { + const circleElement = element.append('circle'); + circleElement.attr('cx', circleData.cx); + circleElement.attr('cy', circleData.cy); + circleElement.attr('class', 'actor-' + circleData.pos); + circleElement.attr('fill', circleData.fill); + circleElement.attr('stroke', circleData.stroke); + circleElement.attr('r', circleData.r); + + if (typeof circleElement.class !== 'undefined') { + circleElement.attr('class', circleElement.class); + } + + if (typeof circleData.title !== 'undefined') { + circleElement.append('title').text(circleData.title); + } + + return circleElement; +}; + +export const drawText = function (elem, textData) { + // Remove and ignore br:s + const nText = textData.text.replace(//gi, ' '); + + const textElem = elem.append('text'); + textElem.attr('x', textData.x); + textElem.attr('y', textData.y); + textElem.attr('class', 'legend'); + + textElem.style('text-anchor', textData.anchor); + + if (typeof textData.class !== 'undefined') { + textElem.attr('class', textData.class); + } + + const span = textElem.append('tspan'); + span.attr('x', textData.x + textData.textMargin * 2); + span.text(nText); + + return textElem; +}; + +export const drawLabel = function (elem, txtObject) { + /** + * @param {any} x + * @param {any} y + * @param {any} width + * @param {any} height + * @param {any} cut + */ + function genPoints(x, y, width, height, cut) { + return ( + x + + ',' + + y + + ' ' + + (x + width) + + ',' + + y + + ' ' + + (x + width) + + ',' + + (y + height - cut) + + ' ' + + (x + width - cut * 1.2) + + ',' + + (y + height) + + ' ' + + x + + ',' + + (y + height) + ); + } + const polygon = elem.append('polygon'); + polygon.attr('points', genPoints(txtObject.x, txtObject.y, 50, 20, 7)); + polygon.attr('class', 'labelBox'); + + txtObject.y = txtObject.y + txtObject.labelMargin; + txtObject.x = txtObject.x + 0.5 * txtObject.labelMargin; + drawText(elem, txtObject); +}; + +export const drawSection = function (elem, section, conf) { + const g = elem.append('g'); + + const rect = getNoteRect(); + rect.x = section.x; + rect.y = section.y; + rect.fill = section.fill; + rect.width = conf.width; + rect.height = conf.height; + rect.class = 'journey-section section-type-' + section.num; + rect.rx = 3; + rect.ry = 3; + drawRect(g, rect); + + _drawTextCandidateFunc(conf)( + section.text, + g, + rect.x, + rect.y, + rect.width, + rect.height, + { class: 'journey-section section-type-' + section.num }, + conf, + section.colour + ); +}; + +let taskCount = -1; +/** + * Draws an actor in the diagram with the attached line + * + * @param {any} elem The HTML element + * @param {any} task The task to render + * @param {any} conf The global configuration + */ +export const drawTask = function (elem, task, conf) { + const center = task.x + conf.width / 2; + const g = elem.append('g'); + taskCount++; + const maxHeight = 300 + 5 * 30; + g.append('line') + .attr('id', 'task' + taskCount) + .attr('x1', center) + .attr('y1', task.y) + .attr('x2', center) + .attr('y2', maxHeight) + .attr('class', 'task-line') + .attr('stroke-width', '1px') + .attr('stroke-dasharray', '4 2') + .attr('stroke', '#666'); + + drawFace(g, { + cx: center, + cy: 300 + (5 - task.score) * 30, + score: task.score, + }); + + const rect = getNoteRect(); + rect.x = task.x; + rect.y = task.y; + rect.fill = task.fill; + rect.width = conf.width; + rect.height = conf.height; + rect.class = 'task task-type-' + task.num; + rect.rx = 3; + rect.ry = 3; + drawRect(g, rect); + + let xPos = task.x + 14; + // task.people.forEach((person) => { + // const colour = task.actors[person].color; + + // const circle = { + // cx: xPos, + // cy: task.y, + // r: 7, + // fill: colour, + // stroke: '#000', + // title: person, + // pos: task.actors[person].position, + // }; + + // drawCircle(g, circle); + // xPos += 10; + // }); + + _drawTextCandidateFunc(conf)( + task.task, + g, + rect.x, + rect.y, + rect.width, + rect.height, + { class: 'task' }, + conf, + task.colour + ); +}; + +/** + * Draws a background rectangle + * + * @param {any} elem The html element + * @param {any} bounds The bounds of the drawing + */ +export const drawBackgroundRect = function (elem, bounds) { + const rectElem = drawRect(elem, { + x: bounds.startx, + y: bounds.starty, + width: bounds.stopx - bounds.startx, + height: bounds.stopy - bounds.starty, + fill: bounds.fill, + class: 'rect', + }); + rectElem.lower(); +}; + +export const getTextObj = function () { + return { + x: 0, + y: 0, + fill: undefined, + 'text-anchor': 'start', + width: 100, + height: 100, + textMargin: 0, + rx: 0, + ry: 0, + }; +}; + +export const getNoteRect = function () { + return { + x: 0, + y: 0, + width: 100, + anchor: 'start', + height: 100, + rx: 0, + ry: 0, + }; +}; + +const _drawTextCandidateFunc = (function () { + /** + * @param {any} content + * @param {any} g + * @param {any} x + * @param {any} y + * @param {any} width + * @param {any} height + * @param {any} textAttrs + * @param {any} colour + */ + function byText(content, g, x, y, width, height, textAttrs, colour) { + const text = g + .append('text') + .attr('x', x + width / 2) + .attr('y', y + height / 2 + 5) + .style('font-color', colour) + .style('text-anchor', 'middle') + .text(content); + _setTextAttrs(text, textAttrs); + } + + /** + * @param {any} content + * @param {any} g + * @param {any} x + * @param {any} y + * @param {any} width + * @param {any} height + * @param {any} textAttrs + * @param {any} conf + * @param {any} colour + */ + function byTspan(content, g, x, y, width, height, textAttrs, conf, colour) { + const { taskFontSize, taskFontFamily } = conf; + + const lines = content.split(//gi); + for (let i = 0; i < lines.length; i++) { + const dy = i * taskFontSize - (taskFontSize * (lines.length - 1)) / 2; + const text = g + .append('text') + .attr('x', x + width / 2) + .attr('y', y) + .attr('fill', colour) + .style('text-anchor', 'middle') + .style('font-size', taskFontSize) + .style('font-family', taskFontFamily); + text + .append('tspan') + .attr('x', x + width / 2) + .attr('dy', dy) + .text(lines[i]); + + text + .attr('y', y + height / 2.0) + .attr('dominant-baseline', 'central') + .attr('alignment-baseline', 'central'); + + _setTextAttrs(text, textAttrs); + } + } + + /** + * @param {any} content + * @param {any} g + * @param {any} x + * @param {any} y + * @param {any} width + * @param {any} height + * @param {any} textAttrs + * @param {any} conf + */ + function byFo(content, g, x, y, width, height, textAttrs, conf) { + const body = g.append('switch'); + const f = body + .append('foreignObject') + .attr('x', x) + .attr('y', y) + .attr('width', width) + .attr('height', height) + .attr('position', 'fixed'); + + const text = f + .append('xhtml:div') + .style('display', 'table') + .style('height', '100%') + .style('width', '100%'); + + text + .append('div') + .attr('class', 'label') + .style('display', 'table-cell') + .style('text-align', 'center') + .style('vertical-align', 'middle') + .text(content); + + byTspan(content, body, x, y, width, height, textAttrs, conf); + _setTextAttrs(text, textAttrs); + } + + /** + * @param {any} toText + * @param {any} fromTextAttrsDict + */ + function _setTextAttrs(toText, fromTextAttrsDict) { + for (const key in fromTextAttrsDict) { + if (key in fromTextAttrsDict) { + // noinspection JSUnfilteredForInLoop + toText.attr(key, fromTextAttrsDict[key]); + } + } + } + + return function (conf) { + return conf.textPlacement === 'fo' ? byFo : conf.textPlacement === 'old' ? byText : byTspan; + }; +})(); + +const initGraphics = function (graphics) { + graphics + .append('defs') + .append('marker') + .attr('id', 'arrowhead') + .attr('refX', 5) + .attr('refY', 2) + .attr('markerWidth', 6) + .attr('markerHeight', 4) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 0,0 V 4 L6,2 Z'); // this is actual shape for arrowhead +}; + +/** + * @param {string} text The text to be wrapped + * @param {number} width The max width of the text + */ +function wrap(text, width) { + text.each(function () { + var text = select(this), + words = text + .text() + .split(/(\s+|
)/) + .reverse(), + word, + line = [], + lineHeight = 1.1, // ems + y = text.attr('y'), + dy = parseFloat(text.attr('dy')), + tspan = text + .text(null) + .append('tspan') + .attr('x', 0) + .attr('y', y) + .attr('dy', dy + 'em'); + for (let j = 0; j < words.length; j++) { + word = words[words.length - 1 - j]; + line.push(word); + tspan.text(line.join(' ').trim()); + if (tspan.node().getComputedTextLength() > width || word === '
') { + line.pop(); + tspan.text(line.join(' ').trim()); + if (word === '
') { + line = ['']; + } else { + line = [word]; + } + + tspan = text + .append('tspan') + .attr('x', 0) + .attr('y', y) + .attr('dy', lineHeight + 'em') + .text(word); + } + } + }); +} + +export const drawNode = function (elem, node, fullSection, conf) { + const section = (fullSection % MAX_SECTIONS) - 1; + const nodeElem = elem.append('g'); + node.section = section; + nodeElem.attr( + 'class', + (node.class ? node.class + ' ' : '') + + 'timeline-node ' + + (section < 0 ? 'section-root' : 'section-' + section) + ); + const bkgElem = nodeElem.append('g'); + + // Create the wrapped text element + const textElem = nodeElem.append('g'); + + const txt = textElem + .append('text') + .text(node.descr) + .attr('dy', '1em') + .attr('alignment-baseline', 'middle') + .attr('dominant-baseline', 'middle') + .attr('text-anchor', 'middle') + .call(wrap, node.width); + const bbox = txt.node().getBBox(); + const fontSize = conf.fontSize && conf.fontSize.replace ? conf.fontSize.replace('px', '') : conf.fontSize; + node.height = bbox.height + fontSize * 1.1 * 0.5 + node.padding; + node.height = Math.max(node.height, node.maxHeight); + node.width = node.width + 2 * node.padding; + + textElem.attr('transform', 'translate(' + node.width / 2 + ', ' + node.padding / 2 + ')'); + + // Create the background element + defaultBkg(bkgElem, node, section, conf); + + + return node; +}; + + export const getVirtualNodeHeight = function (elem,node,conf) { + const textElem = elem.append('g'); + const txt = textElem + .append('text') + .text(node.descr) + .attr('dy', '1em') + .attr('alignment-baseline', 'middle') + .attr('dominant-baseline', 'middle') + .attr('text-anchor', 'middle') + .call(wrap, node.width); + const bbox = txt.node().getBBox(); + const fontSize = conf.fontSize && conf.fontSize.replace ? conf.fontSize.replace('px', '') : conf.fontSize; + textElem.remove(); + return bbox.height + fontSize * 1.1 * 0.5 + node.padding; +}; + + +const defaultBkg = function (elem, node, section) { + const rd = 5; + elem + .append('path') + .attr('id', 'node-' + node.id) + .attr('class', 'node-bkg node-' + node.type) + .attr( + 'd', + `M0 ${node.height - rd} v${-node.height + 2 * rd} q0,-5 5,-5 h${ + node.width - 2 * rd + } q5,0 5,5 v${node.height - rd} H0 Z` + ); + + elem + .append('line') + .attr('class', 'node-line-' + section) + .attr('x1', 0) + .attr('y1', node.height) + .attr('x2', node.width) + .attr('y2', node.height); +}; + +export default { + drawRect, + drawCircle, + drawSection, + drawText, + drawLabel, + drawTask, + drawBackgroundRect, + getTextObj, + getNoteRect, + initGraphics, + drawNode, + getVirtualNodeHeight, +}; diff --git a/packages/mermaid-timeline/src/timelineDb.js b/packages/mermaid-timeline/src/timelineDb.js new file mode 100644 index 000000000..dda3a97cb --- /dev/null +++ b/packages/mermaid-timeline/src/timelineDb.js @@ -0,0 +1,100 @@ +import { getCommonDb as _getCommonDb,log } from './mermaidUtils'; + +let currentSection = ''; +let currentTaskId = 0; + +const sections = []; +const tasks = []; +const rawTasks = []; + +export const getCommonDb = _getCommonDb; + +export const clear = function () { + sections.length = 0; + tasks.length = 0; + currentSection = ''; + rawTasks.length = 0; + _getCommonDb().clear(); +}; + +export const addSection = function (txt) { + currentSection = txt; + sections.push(txt); +}; + +export const getSections = function () { + return sections; +}; + +export const getTasks = function () { + let allItemsProcessed = compileTasks(); + const maxDepth = 100; + let iterationCount = 0; + while (!allItemsProcessed && iterationCount < maxDepth) { + allItemsProcessed = compileTasks(); + iterationCount++; + } + + tasks.push(...rawTasks); + + return tasks; +}; + +export const addTask = function (period, length, event) { + + const rawTask = { + id: currentTaskId++, + section: currentSection, + type: currentSection, + task: period, + score : length?length:0, + //if event is defined, then add it the events array + events: event?[event]:[], + }; + rawTasks.push(rawTask); +}; + +export const addEvent = function (event) { + // fetch current task with currnetTaskId + const currentTask = rawTasks.find((task) => task.id === currentTaskId - 1); + //add event to the events array + currentTask.events.push(event); +}; + + +export const addTaskOrg = function (descr) { + const newTask = { + section: currentSection, + type: currentSection, + description: descr, + task: descr, + classes: [], + }; + tasks.push(newTask); +}; + +const compileTasks = function () { + const compileTask = function (pos) { + return rawTasks[pos].processed; + }; + + let allProcessed = true; + for (let i = 0; i < rawTasks.length; i++) { + compileTask(i); + + allProcessed = allProcessed && rawTasks[i].processed; + } + return allProcessed; +}; + +export default { + clear, + getCommonDb, + addSection, + getSections, + getTasks, + addTask, + addTaskOrg, + addEvent, +}; + diff --git a/packages/mermaid-timeline/src/timelineDb.spec.js b/packages/mermaid-timeline/src/timelineDb.spec.js new file mode 100644 index 000000000..3a17ca202 --- /dev/null +++ b/packages/mermaid-timeline/src/timelineDb.spec.js @@ -0,0 +1,91 @@ +import journeyDb from './journeyDb'; + +describe('when using the journeyDb', function () { + beforeEach(function () { + journeyDb.clear(); + }); + + describe('when calling the clear function', function () { + beforeEach(function () { + journeyDb.addSection('weekends skip test'); + journeyDb.addTask('test1', '4: id1, id3'); + journeyDb.addTask('test2', '2: id2'); + journeyDb.clear(); + }); + + it.each` + fn | expected + ${'getTasks'} | ${[]} + ${'getAccTitle'} | ${''} + ${'getSections'} | ${[]} + ${'getActors'} | ${[]} + `('should clear $fn', ({ fn, expected }) => { + expect(journeyDb[fn]()).toEqual(expected); + }); + }); + + describe('when calling the clear function', function () { + beforeEach(function () { + journeyDb.addSection('weekends skip test'); + journeyDb.addTask('test1', '3: id1, id3'); + journeyDb.addTask('test2', '1: id2'); + journeyDb.clear(); + }); + it.each` + fn | expected + ${'getTasks'} | ${[]} + ${'getAccTitle'} | ${''} + ${'getAccDescription'} | ${''} + ${'getSections'} | ${[]} + `('should clear $fn', ({ fn, expected }) => { + expect(journeyDb[fn]()).toEqual(expected); + }); + }); + + describe('tasks and actors should be added', function () { + journeyDb.setAccTitle('Shopping'); + journeyDb.setAccDescription('A user journey for family shopping'); + journeyDb.addSection('Journey to the shops'); + journeyDb.addTask('Get car keys', ':5:Dad'); + journeyDb.addTask('Go to car', ':3:Dad, Mum, Child#1, Child#2'); + journeyDb.addTask('Drive to supermarket', ':4:Dad'); + journeyDb.addSection('Do shopping'); + journeyDb.addTask('Go shopping', ':5:Mum'); + + expect(journeyDb.getAccTitle()).toEqual('Shopping'); + expect(journeyDb.getAccDescription()).toEqual('A user journey for family shopping'); + expect(journeyDb.getTasks()).toEqual([ + { + score: 5, + people: ['Dad'], + section: 'Journey to the shops', + task: 'Get car keys', + type: 'Journey to the shops', + }, + { + score: 3, + people: ['Dad', 'Mum', 'Child#1', 'Child#2'], + section: 'Journey to the shops', + task: 'Go to car', + type: 'Journey to the shops', + }, + { + score: 4, + people: ['Dad'], + section: 'Journey to the shops', + task: 'Drive to supermarket', + type: 'Journey to the shops', + }, + { + score: 5, + people: ['Mum'], + section: 'Do shopping', + task: 'Go shopping', + type: 'Do shopping', + }, + ]); + expect(journeyDb.getActors()).toEqual(['Child#1', 'Child#2', 'Dad', 'Mum']); + + expect(journeyDb.getSections()).toEqual(['Journey to the shops', 'Do shopping']); + }); +}); diff --git a/packages/mermaid-timeline/src/timelineRenderer.ts b/packages/mermaid-timeline/src/timelineRenderer.ts new file mode 100644 index 000000000..aa3e2199c --- /dev/null +++ b/packages/mermaid-timeline/src/timelineRenderer.ts @@ -0,0 +1,415 @@ +// @ts-nocheck TODO: fix file +import { select } from 'd3'; +import svgDraw from './svgDraw'; +import { configureSvgSize } from '../../setupGraphViewbox'; +import addSVGAccessibilityFields from '../../accessibility'; + +import { log, getConfig, setupGraphViewbox } from './mermaidUtils'; + +export const setConf = function (cnf) { + const keys = Object.keys(cnf); + + keys.forEach(function (key) { + conf[key] = cnf[key]; + }); +}; + +export const draw = function (text, id, version, diagObj) { + //1. Fetch the configuration + const conf = getConfig(); + const LEFT_MARGIN = conf.leftMargin?conf.leftMargin:50; + + //2. Clear the diagram db before parsing + diagObj.db.clear(); + + //3. Parse the diagram text + diagObj.parser.parse(text + '\n'); + + log.info('timeline', diagObj.db); + + const securityLevel = conf.securityLevel; + // Handle root and Document for when rendering in sandbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + + // Init bounds + bounds.init(); + + + + const svg = root.select('#' + id); + + svg.append('g'); + + //4. Fetch the diagram data + const tasks = diagObj.db.getTasks(); + const title = diagObj.db.getCommonDb().getDiagramTitle(); + + //log tasks + log.info(tasks); + + //5. Initialize the diagram + svgDraw.initGraphics(svg); + + //bounds.insert(0, 0, LEFT_MARGIN, 0); + // fetch Sections + const sections = diagObj.db.getSections(); + // log sections + log.info(sections); + + let maxSectionHeight = 0; + let maxTaskHeight = 0; + let sectionBeginX = 0; + let sectionBeginY = 0; + let masterX = 50 + LEFT_MARGIN; + sectionBeginX = masterX; + let masterY = 50; + sectionBeginY=50; + //draw sections + let sectionNumber = 0; + + //Calculate the max height of the sections + sections.forEach(function (section) { + const sectionNode = { + number: sectionNumber, + descr: section, + section: sectionNumber, + width: 150, + padding: 20, + maxHeight: maxSectionHeight, + }; + const sectionHeight = svgDraw.getVirtualNodeHeight(svg, sectionNode, conf); + log.info('sectionHeight before draw', sectionHeight); + maxSectionHeight = Math.max(maxSectionHeight, sectionHeight +20); + }); + +//tasks length and maxEventCount +let maxEventCount = 0; + log.info('tasks.length', tasks.length); + //calculate max task height + // for loop till tasks.length + for (let i = 0; i < tasks.length; i++) { + const task = tasks[i]; + + const taskNode = { + number: i, + descr: task, + section: task.section, + width: 150, + padding: 20, + maxHeight: maxTaskHeight, + }; + const taskHeight = svgDraw.getVirtualNodeHeight(svg, taskNode, conf); + log.info('taskHeight before draw', taskHeight); + maxTaskHeight = Math.max(maxTaskHeight, taskHeight + 20); + + //calculate maxEventCount + maxEventCount = Math.max(maxEventCount, task.events.length); + } + + + log.info('maxSectionHeight before draw', maxSectionHeight); + log.info('maxTaskHeight before draw', maxTaskHeight); + + if (sections && sections.length > 0) { + sections.forEach((section) => { + + const sectionNode = { + number: sectionNumber, + descr: section, + section: sectionNumber, + width: 150, + padding: 20, + maxHeight: maxSectionHeight, + }; + //log section node + log.info('sectionNode', sectionNode); + const sectionNodeWrapper = svg.append('g'); + const node = svgDraw.drawNode(sectionNodeWrapper, sectionNode, sectionNumber, conf); + // add node to section list + //sectionList.push(node); + //const nodeHeight = node.height + 20; + //Post process the node + //append g + + sectionNodeWrapper.attr( + 'transform', + `translate(${masterX}, ${sectionBeginY})` + ); + //maxSectionHeight = Math.max(maxSectionHeight, nodeHeight); + masterY += maxSectionHeight + 50; + + + + //draw tasks for this section + //filter task where tasks.section == section + const tasksForSection = tasks.filter((task) => task.section === section); + if (tasksForSection.length > 0) { + + + drawTasks(svg, tasksForSection, sectionNumber, masterX, masterY, maxTaskHeight, conf, maxEventCount,false); + } + // todo replace with total width of section and its tasks + masterX += 200 * Math.max(tasksForSection.length, 1); + + masterY = sectionBeginY; + sectionNumber++; + }); + } else { + //draw tasks + drawTasks(svg, tasks, sectionNumber, masterX, masterY, maxTaskHeight, conf, maxEventCount,true); + } + + + + + // draw tasks + //drawTasks(svg, tasks, 0); + + const box = bounds.getBounds(); + if (title) { + svg + .append('text') + .text(title) + .attr('x', LEFT_MARGIN) + .attr('font-size', '4ex') + .attr('font-weight', 'bold') + .attr('y', 25); + } + + const height = box.stopy - box.starty + 2 * conf.diagramMarginY; + const width = LEFT_MARGIN + box.stopx + 2 * conf.diagramMarginX; + +// Setup the view box and size of the svg element + setupGraphViewbox(undefined, svg, conf.timeline.padding, conf.timeline.useMaxWidth); + + //5. Draw the diagram + const maxTaskLength = 500; + + // Draw activity line + svg + .append('line') + .attr('x1', LEFT_MARGIN) + .attr('y1', maxSectionHeight + maxTaskHeight +150) // One section head + one task + margins + .attr('x2', tasks && tasks.length? (tasks.length*200)+ 400 : 400) // Subtract stroke width so arrow point is retained + .attr('y2', maxSectionHeight + maxTaskHeight +150) + .attr('stroke-width', 4) + .attr('stroke', 'black') + .attr('marker-end', 'url(#arrowhead)'); + + const extraVertForTitle = title ? 70 : 0; + svg.attr('viewBox', `${box.startx} -25 ${width} ${height + extraVertForTitle}`); + svg.attr('preserveAspectRatio', 'xMinYMin meet'); + svg.attr('height', height + extraVertForTitle + 25); + + // addSVGAccessibilityFields(diagObj.db, diagram, id); +}; + +export const bounds = { + data: { + startx: undefined, + stopx: undefined, + starty: undefined, + stopy: undefined, + }, + verticalPos: 0, + + sequenceItems: [], + init: function () { + this.sequenceItems = []; + this.data = { + startx: undefined, + stopx: undefined, + starty: undefined, + stopy: undefined, + }; + this.verticalPos = 0; + }, + updateVal: function (obj, key, val, fun) { + if (typeof obj[key] === 'undefined') { + obj[key] = val; + } else { + obj[key] = fun(val, obj[key]); + } + }, + updateBounds: function (startx, starty, stopx, stopy) { + const conf = getConfig().timeline; + // eslint-disable-next-line @typescript-eslint/no-this-alias + const _self = this; + let cnt = 0; + /** @param {any} type */ + function updateFn(type) { + return function updateItemBounds(item) { + cnt++; + // The loop sequenceItems is a stack so the biggest margins in the beginning of the sequenceItems + const n = _self.sequenceItems.length - cnt + 1; + _self.updateVal(item, 'starty', starty - n * conf.boxMargin, Math.min); + _self.updateVal(item, 'stopy', stopy + n * conf.boxMargin, Math.max); + + _self.updateVal(bounds.data, 'startx', startx - n * conf.boxMargin, Math.min); + _self.updateVal(bounds.data, 'stopx', stopx + n * conf.boxMargin, Math.max); + + if (!(type === 'activation')) { + _self.updateVal(item, 'startx', startx - n * conf.boxMargin, Math.min); + _self.updateVal(item, 'stopx', stopx + n * conf.boxMargin, Math.max); + + _self.updateVal(bounds.data, 'starty', starty - n * conf.boxMargin, Math.min); + _self.updateVal(bounds.data, 'stopy', stopy + n * conf.boxMargin, Math.max); + } + }; + } + + this.sequenceItems.forEach(updateFn()); + }, + insert: function (startx, starty, stopx, stopy) { + const _startx = Math.min(startx, stopx); + const _stopx = Math.max(startx, stopx); + const _starty = Math.min(starty, stopy); + const _stopy = Math.max(starty, stopy); + + this.updateVal(bounds.data, 'startx', _startx, Math.min); + this.updateVal(bounds.data, 'starty', _starty, Math.min); + this.updateVal(bounds.data, 'stopx', _stopx, Math.max); + this.updateVal(bounds.data, 'stopy', _stopy, Math.max); + + this.updateBounds(_startx, _starty, _stopx, _stopy); + }, + bumpVerticalPos: function (bump) { + this.verticalPos = this.verticalPos + bump; + this.data.stopy = this.verticalPos; + }, + getVerticalPos: function () { + return this.verticalPos; + }, + getBounds: function () { + return this.data; + }, +}; + + + +export const drawTasks = function (diagram, tasks, sectionColor, masterX, masterY, maxTaskHeight,conf,maxEventCount, isWithoutSections) { + + const taskBeginY = masterY; + + const taskBeginX = masterX; + + // Draw the tasks + for (let i = 0; i < tasks.length; i++) { + + const task = tasks[i]; + // create node from task + const taskNode = { + descr: task.task, + section: sectionColor, + number : sectionColor, + width: 150, + padding: 20, + maxHeight: maxTaskHeight, + }; + + //log task node + log.info('taskNode', taskNode); + // create task wrapper + const taskWrapper = diagram.append('g').attr('class', 'taskWrapper'); + const node = svgDraw.drawNode(taskWrapper, taskNode, sectionColor, conf); + const taskHeight = node.height; + //log task height + log.info('taskHeight after draw', taskHeight); + taskWrapper.attr( + 'transform', + `translate(${masterX}, ${masterY})` + ); + + // update max task height + maxTaskHeight = Math.max(maxTaskHeight, taskHeight); + + + + // if task has events, draw them + if (task.events) { + // draw a line between the task and the events + const lineWrapper = diagram.append('g').attr('class', 'lineWrapper'); + + let linelength = maxTaskHeight; + + + + //add margin to task + masterY += 100; + linelength = linelength+ drawEvents(diagram, task.events, sectionColor, masterX, masterY, conf); + masterY -= 100; + + lineWrapper + .append('line') + .attr('x1', masterX + 190/2) + .attr('y1', masterY + maxTaskHeight) // One section head + one task + margins + .attr('x2', masterX + 190/2) // Subtract stroke width so arrow point is retained + .attr('y2', masterY + linelength + maxEventCount * 100) + .attr('stroke-width', 2) + .attr('stroke', 'black') + .attr('marker-end', 'url(#arrowhead)') + .attr('stroke-dasharray', "5,5"); + } + + + + masterX = masterX + 200; + if (isWithoutSections) { + sectionColor++; + } + } + + +// reset Y coordinate for next section + masterY= masterY -10; ; +}; + +export const drawEvents = function (diagram, events, sectionColor, masterX, masterY, conf) { + + let maxEventHeight = 0; + const eventBeginY = masterY; + masterY = masterY + 100 + // Draw the events + for (let i = 0; i < events.length; i++) { + const event = events[i]; + // create node from event + const eventNode = { + descr: event, + section: sectionColor, + number : sectionColor, + width: 150, + padding: 20, + maxHeight: 50, + }; + + //log task node + log.info('eventNode', eventNode); + // create event wrapper + const eventWrapper = diagram.append('g').attr('class', 'eventWrapper'); + const node = svgDraw.drawNode(eventWrapper, eventNode, sectionColor, conf) + const eventHeight = node.height; + maxEventHeight= maxEventHeight + eventHeight; + eventWrapper.attr( + 'transform', + `translate(${masterX}, ${masterY})` + ); + masterY = masterY + 10 + eventHeight; + + } + // set masterY back to eventBeginY + masterY = eventBeginY; + return maxEventHeight; + +}; + +export default { + setConf, + draw, +}; diff --git a/packages/mermaid-timeline/src/types/index.d.ts b/packages/mermaid-timeline/src/types/index.d.ts new file mode 100644 index 000000000..999ff2f49 --- /dev/null +++ b/packages/mermaid-timeline/src/types/index.d.ts @@ -0,0 +1,7 @@ +export {}; + +declare global { + interface Window { + mermaid: any; // 👈️ turn off type checking + } +} diff --git a/packages/mermaid-timeline/tsconfig.json b/packages/mermaid-timeline/tsconfig.json new file mode 100644 index 000000000..310137cc0 --- /dev/null +++ b/packages/mermaid-timeline/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "module": "esnext", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["./src/**/*.ts"], + "typeRoots": ["./src/types"] +} diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index ff199ca8b..63fe078fa 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -26,6 +26,7 @@ export interface MermaidConfig { sequence?: SequenceDiagramConfig; gantt?: GanttDiagramConfig; journey?: JourneyDiagramConfig; + timeline?: TimelineDiagramConfig; class?: ClassDiagramConfig; state?: StateDiagramConfig; er?: ErDiagramConfig; @@ -292,6 +293,29 @@ export interface JourneyDiagramConfig extends BaseDiagramConfig { sectionColours?: string[]; } +export interface TimelineDiagramConfig extends BaseDiagramConfig { + diagramMarginX?: number; + diagramMarginY?: number; + leftMargin?: number; + width?: number; + height?: number; + boxMargin?: number; + boxTextMargin?: number; + noteMargin?: number; + messageMargin?: number; + messageAlign?: string; + bottomMarginAdj?: number; + rightAngles?: boolean; + taskFontSize?: string | number; + taskFontFamily?: string; + taskMargin?: number; + activationWidth?: number; + textPlacement?: string; + actorColours?: string[]; + sectionFills?: string[]; + sectionColours?: string[]; +} + export interface GanttDiagramConfig extends BaseDiagramConfig { titleTopMargin?: number; barHeight?: number; diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts index 37d4f71ff..5bb4a1bd8 100644 --- a/packages/mermaid/src/defaultConfig.ts +++ b/packages/mermaid/src/defaultConfig.ts @@ -861,6 +861,155 @@ const config: Partial = { sectionFills: ['#191970', '#8B008B', '#4B0082', '#2F4F4F', '#800000', '#8B4513', '#00008B'], sectionColours: ['#fff'], }, + /** The object containing configurations specific for timeline diagrams */ + timeline: { + /** + * | Parameter | Description | Type | Required | Values | + * | -------------- | ---------------------------------------------------- | ------- | -------- | ------------------ | + * | diagramMarginX | Margin to the right and left of the sequence 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 sequence diagram. | Integer | Required | Any Positive Value | + * + * **Notes:** Default value: 10 + */ + diagramMarginY: 10, + + /** + * | Parameter | Description | Type | Required | Values | + * | ----------- | --------------------- | ------- | -------- | ------------------ | + * | actorMargin | Margin between actors | Integer | Required | Any Positive Value | + * + * **Notes:** Default value: 50 + */ + leftMargin: 150, + + /** + * | Parameter | Description | Type | Required | Values | + * | --------- | -------------------- | ------- | -------- | ------------------ | + * | width | Width of actor boxes | Integer | Required | Any Positive Value | + * + * **Notes:** Default value: 150 + */ + width: 150, + + /** + * | Parameter | Description | Type | Required | Values | + * | --------- | --------------------- | ------- | -------- | ------------------ | + * | height | Height of actor boxes | Integer | Required | Any Positive Value | + * + * **Notes:** Default value: 65 + */ + height: 50, + + /** + * | 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 | + * | ------------- | -------------------------------------------- | ------- | -------- | ------------------ | + * | boxTextMargin | Margin around the text in loop/alt/opt boxes | Integer | Required | Any Positive Value | + * + * **Notes:** Default value: 5 + */ + boxTextMargin: 5, + + /** + * | Parameter | Description | Type | Required | Values | + * | ---------- | ------------------- | ------- | -------- | ------------------ | + * | noteMargin | Margin around notes | Integer | Required | Any Positive Value | + * + * **Notes:** Default value: 10 + */ + noteMargin: 10, + + /** + * | Parameter | Description | Type | Required | Values | + * | ------------- | ----------------------- | ------- | -------- | ------------------ | + * | messageMargin | Space between messages. | Integer | Required | Any Positive Value | + * + * **Notes:** + * + * Space between messages. + * + * Default value: 35 + */ + messageMargin: 35, + + /** + * | Parameter | Description | Type | Required | Values | + * | ------------ | --------------------------- | ---- | -------- | ------------------------- | + * | messageAlign | Multiline message alignment | 3 | 4 | 'left', 'center', 'right' | + * + * **Notes:** Default value: 'center' + */ + messageAlign: 'center', + + /** + * | Parameter | Description | Type | Required | Values | + * | --------------- | ------------------------------------------ | ------- | -------- | ------------------ | + * | bottomMarginAdj | Prolongs the edge of the diagram downwards | Integer | 4 | Any Positive Value | + * + * **Notes:** + * + * Depending on css styling this might need adjustment. + * + * Default value: 1 + */ + bottomMarginAdj: 1, + + /** + * | Parameter | Description | Type | Required | Values | + * | ----------- | ----------- | ------- | -------- | ----------- | + * | useMaxWidth | See notes | boolean | 4 | true, false | + * + * **Notes:** + * + * When this flag is set the height and width is set to 100% and is then scaling with the + * available space if not the absolute space required is used. + * + * Default value: true + */ + useMaxWidth: true, + + /** + * | Parameter | Description | Type | Required | Values | + * | ----------- | --------------------------------- | ---- | -------- | ----------- | + * | rightAngles | Curved Arrows become Right Angles | 3 | 4 | true, false | + * + * **Notes:** + * + * This will display arrows that start and begin at the same node as right angles, rather than a + * curves + * + * Default value: false + */ + rightAngles: false, + taskFontSize: 14, + taskFontFamily: '"Open Sans", sans-serif', + taskMargin: 50, + // width of activation box + activationWidth: 10, + + // text placement as: tspan | fo | old only text as before + textPlacement: 'fo', + actorColours: ['#8FBC8F', '#7CFC00', '#00FFFF', '#20B2AA', '#B0E0E6', '#FFFFE0'], + + sectionFills: ['#191970', '#8B008B', '#4B0082', '#2F4F4F', '#800000', '#8B4513', '#00008B'], + sectionColours: ['#fff'], + }, class: { /** * ### titleTopMargin diff --git a/packages/mermaid/src/diagram-api/diagramAPI.ts b/packages/mermaid/src/diagram-api/diagramAPI.ts index 748cc5f96..ddb22df2c 100644 --- a/packages/mermaid/src/diagram-api/diagramAPI.ts +++ b/packages/mermaid/src/diagram-api/diagramAPI.ts @@ -5,6 +5,8 @@ import { sanitizeText as _sanitizeText } from '../diagrams/common/common'; import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox'; import { addStylesForDiagram } from '../styles'; import { DiagramDefinition, DiagramDetector } from './types'; +import * as _commonDb from '../commonDb'; + /* Packaging and exposing resources for external diagrams so that they can import @@ -16,6 +18,7 @@ export const setLogLevel = _setLogLevel; export const getConfig = _getConfig; export const sanitizeText = (text: string) => _sanitizeText(text, getConfig()); export const setupGraphViewbox = _setupGraphViewbox; +export const getCommonDb = () => { return _commonDb }; const diagrams: Record = {}; export interface Detectors { @@ -46,7 +49,7 @@ export const registerDiagram = ( addStylesForDiagram(id, diagram.styles); if (diagram.injectUtils) { - diagram.injectUtils(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox); + diagram.injectUtils(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox,getCommonDb()); } }; diff --git a/packages/mermaid/src/diagram-api/types.ts b/packages/mermaid/src/diagram-api/types.ts index 23810d133..652f35402 100644 --- a/packages/mermaid/src/diagram-api/types.ts +++ b/packages/mermaid/src/diagram-api/types.ts @@ -6,6 +6,7 @@ export interface InjectUtils { _getConfig: any; _sanitizeText: any; _setupGraphViewbox: any; + _commonDb: any; } /** @@ -27,7 +28,8 @@ export interface DiagramDefinition { _setLogLevel: InjectUtils['_setLogLevel'], _getConfig: InjectUtils['_getConfig'], _sanitizeText: InjectUtils['_sanitizeText'], - _setupGraphViewbox: InjectUtils['_setupGraphViewbox'] + _setupGraphViewbox: InjectUtils['_setupGraphViewbox'], + _commonDb: InjectUtils['_commonDb'] ) => void; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5de78bdb1..2ba8f0776 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -349,6 +349,22 @@ importers: specifier: ^3.0.2 version: 3.0.2 + packages/mermaid-timeline: + dependencies: + d3: + specifier: ^7.0.0 + version: 7.6.1 + khroma: + specifier: ^2.0.0 + version: 2.0.0 + devDependencies: + concurrently: + specifier: ^7.4.0 + version: 7.5.0 + rimraf: + specifier: ^3.0.2 + version: 3.0.2 + tests/webpack: dependencies: '@mermaid-js/mermaid-mindmap': @@ -3634,7 +3650,7 @@ packages: /axios/0.21.4_debug@4.3.2: resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} dependencies: - follow-redirects: 1.15.2_debug@4.3.2 + follow-redirects: 1.15.2 transitivePeerDependencies: - debug dev: true @@ -6309,7 +6325,7 @@ packages: resolution: {integrity: sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==} dev: true - /follow-redirects/1.15.2_debug@4.3.2: + /follow-redirects/1.15.2: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} peerDependencies: @@ -6317,8 +6333,6 @@ packages: peerDependenciesMeta: debug: optional: true - dependencies: - debug: 4.3.2 dev: true /foreground-child/2.0.0: @@ -6911,7 +6925,7 @@ packages: engines: {node: '>=8.0.0'} dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.2_debug@4.3.2 + follow-redirects: 1.15.2 requires-port: 1.0.0 transitivePeerDependencies: - debug