From 82ac6675357276d249f45b1b6e691285ed03c5d6 Mon Sep 17 00:00:00 2001
From: Per Brolin
+ graph TB
+ subgraph One
+ a1-->a2-->a3
+ end
+
+
+ graph TB
+ a_a --> b_b:::apa --> c_c:::apa
+ classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
+ class a_a apa;
+
+
+ graph TB
+ a_a(Aftonbladet) --> b_b[gorilla]:::apa --> c_c{chimp}:::apa -->a_a
+ a_a --> c --> d_d --> c_c
+ classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
+ class a_a apa;
+ click a_a "http://www.aftonbladet.se" "apa"
+
+
+
+
+
diff --git a/packages/mermaid/src/diagram-api/detectType.ts b/packages/mermaid/src/diagram-api/detectType.ts
index 1ea4f2b4d..c27f79b6c 100644
--- a/packages/mermaid/src/diagram-api/detectType.ts
+++ b/packages/mermaid/src/diagram-api/detectType.ts
@@ -44,8 +44,10 @@ export const detectType = function (text: string, config?: MermaidConfig): strin
throw new Error(`No diagram type detected for text: ${text}`);
};
-export const addDiagram = ({ id, detector, loader }: ExternalDiagramDefinition) => {
- addDetector(id, detector, loader);
+export const registerLazyLoadedDiagrams = (...diagrams: ExternalDiagramDefinition[]) => {
+ for (const { id, detector, loader } of diagrams) {
+ addDetector(id, detector, loader);
+ }
};
export const addDetector = (key: string, detector: DiagramDetector, loader?: DiagramLoader) => {
diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.ts
index 64a7e5ad8..c6b8b579a 100644
--- a/packages/mermaid/src/diagram-api/diagram-orchestration.ts
+++ b/packages/mermaid/src/diagram-api/diagram-orchestration.ts
@@ -14,7 +14,7 @@ import state from '../diagrams/state/stateDetector';
import stateV2 from '../diagrams/state/stateDetector-V2';
import journey from '../diagrams/user-journey/journeyDetector';
import error from '../diagrams/error/errorDetector';
-import { addDiagram } from './detectType';
+import { registerLazyLoadedDiagrams } from './detectType';
let hasLoadedDiagrams = false;
export const addDiagrams = () => {
@@ -24,20 +24,22 @@ export const addDiagrams = () => {
// This is added here to avoid race-conditions.
// We could optimize the loading logic somehow.
hasLoadedDiagrams = true;
- addDiagram(error);
- addDiagram(c4);
- addDiagram(classDiagram);
- addDiagram(classDiagramV2);
- addDiagram(er);
- addDiagram(gantt);
- addDiagram(info);
- addDiagram(pie);
- addDiagram(requirement);
- addDiagram(sequence);
- addDiagram(flowchart);
- addDiagram(flowchartV2);
- addDiagram(git);
- addDiagram(state);
- addDiagram(stateV2);
- addDiagram(journey);
+ registerLazyLoadedDiagrams(
+ error,
+ c4,
+ classDiagram,
+ classDiagramV2,
+ er,
+ gantt,
+ info,
+ pie,
+ requirement,
+ sequence,
+ flowchart,
+ flowchartV2,
+ git,
+ state,
+ stateV2,
+ journey
+ );
};
diff --git a/packages/mermaid/src/mermaid.ts b/packages/mermaid/src/mermaid.ts
index 3a8da77ad..268a830ec 100644
--- a/packages/mermaid/src/mermaid.ts
+++ b/packages/mermaid/src/mermaid.ts
@@ -6,7 +6,7 @@ import type { MermaidConfig } from './config.type';
import { log } from './logger';
import utils from './utils';
import { mermaidAPI } from './mermaidAPI';
-import { addDetector } from './diagram-api/detectType';
+import { registerLazyLoadedDiagrams } from './diagram-api/detectType';
import { isDetailedError, type DetailedError } from './utils';
import { registerDiagram } from './diagram-api/diagramAPI';
import { ExternalDiagramDefinition } from './diagram-api/types';
@@ -175,17 +175,6 @@ const initThrowsErrors = function (
}
};
-/**
- * This is an internal function and should not be made public, as it will likely change.
- * @internal
- * @param diagrams - Array of {@link ExternalDiagramDefinition}.
- */
-const registerLazyLoadedDiagrams = (diagrams: ExternalDiagramDefinition[]) => {
- for (const { id, detector, loader } of diagrams) {
- addDetector(id, detector, loader);
- }
-};
-
/**
* This is an internal function and should not be made public, as it will likely change.
* @internal
@@ -333,7 +322,7 @@ const registerExternalDiagrams = async (
} = {}
) => {
if (lazyLoad) {
- registerLazyLoadedDiagrams(diagrams);
+ registerLazyLoadedDiagrams(...diagrams);
} else {
await loadExternalDiagrams(diagrams);
}
From e861fbb5170a5ade38db52320f55dd580547e522 Mon Sep 17 00:00:00 2001
From: Sidharth Vinod
- graph TD
- A[Client] --> B[Load Balancer]
- B --> C[Server01]
+ graph TD
+ A[Client] --> B[Load Balancer]
+ B --> C[Server01]
B --> D[Server02]
@@ -156,18 +156,18 @@ Please refer to the [Mindmap](./mindmap.md?id=integrating-with-your-librarywebsi
Here is one mermaid diagram:
- graph TD
- A[Client] --> B[Load Balancer]
- B --> C[Server1]
+ graph TD
+ A[Client] --> B[Load Balancer]
+ B --> C[Server1]
B --> D[Server2]
And here is another:
- graph TD
+ graph TD
A[Client] -->|tcp_123| B
- B(Load Balancer)
- B -->|tcp_456| C[Server1]
+ B(Load Balancer)
+ B -->|tcp_456| C[Server1]
B -->|tcp_456| D[Server2]
@@ -189,15 +189,15 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file,
- graph LR
- A --- B
- B-->C[fa:fa-ban forbidden]
+ graph LR
+ A --- B
+ B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner);
- graph TD
- A[Client] --> B[Load Balancer]
- B --> C[Server1]
+ graph TD
+ A[Client] --> B[Load Balancer]
+ B --> C[Server1]
B --> D[Server2]
+
+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 @@
+
+
+
+
+
+
+
+
+
+
+
+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 @@
+
+
+
+
+
+
+ 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
Line2
Line3Line4
Line5';
+
+ 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
-flowchart TD
- A --> B
- B --> C
- A --> C
+ timeline
+ title My day
+ section section with no tasks
+ section Go to work at the dog office
+ 1930 : first step : second step
+ : third step
+ 1940 : fourth step : fifth step
+ section Go home
+ 1950 : India got independent and already won war against Pakistan
+ 1960 : India fights poverty, looses war to China
+ 1970 : Green Revolution comes to india
+ section Another section with no tasks
+ I am a big big big tasks
+ I am not so big tasks
+
+
+ timeline
+ title England's History Timeline
+ section Stone Age
+ 7600 BC : Britain's oldest known house was built in Orkney, Scotland
+ 6000 BC : Sea levels rise and Britain becomes an island. The people who live here are hunter-gatherers.
+ section Broze Age
+ 2300 BC : People arrive from Europe and settle in Britain. They bring farming and metalworking.
+ : New styles of pottery and ways of burying the dead appear.
+ 2200 BC : The last major building works are completed at Stonehenge. People now bury their dead in stone circles.
+ : The first metal objects are made in Britain.Some other nice things happen.
+
-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
+ section Rise of Social Media
+ 2002 : LinkedIn
+ 2004 : Facebook : Google
+ 2005 : Youtube
+ 2006 : Twitter
+ 2007 : Tumblr
+ 2008s : Instagram
+ 2010 : Pinterest
+
+
+ timeline
+ title History of Social Media Platform
+ 2002 : LinkedIn
+ 2004 : Facebook : Google
+ 2005 : Youtube
+ 2006 : Twitter
+ 2007 : Tumblr
+ 2008s : Instagram
+ 2010 : Pinterest
timeline
From 5cfa919672ebeaaf5b45bc21a32d7cf49dd8cba2 Mon Sep 17 00:00:00 2001
From: Alois Klink
/gi, '
');
@@ -288,8 +289,7 @@ const initThrowsErrorsAsync = async function (
txt = element.innerHTML;
// transforms the html to pure text
- txt = utils
- .entityDecode(txt)
+ txt = dedent(utils.entityDecode(txt)) // removes indentation, required for YAML parsing
.trim()
.replace(/
/gi, '
');
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ebb71f65e..cc91b753c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -211,6 +211,9 @@ importers:
stylis:
specifier: ^4.1.2
version: 4.1.2
+ ts-dedent:
+ specifier: ^2.2.0
+ version: 2.2.0
uuid:
specifier: ^9.0.0
version: 9.0.0
@@ -3634,7 +3637,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 +6312,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 +6320,6 @@ packages:
peerDependenciesMeta:
debug:
optional: true
- dependencies:
- debug: 4.3.2
dev: true
/foreground-child/2.0.0:
@@ -6911,7 +6912,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
@@ -10613,6 +10614,11 @@ packages:
resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==}
dev: true
+ /ts-dedent/2.2.0:
+ resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==}
+ engines: {node: '>=6.10'}
+ dev: false
+
/ts-node/10.9.1_cbe7ovvae6zqfnmtgctpgpys54:
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true
From 4cc3b17d362b3c8edff9ac0ab7d7248a309fa988 Mon Sep 17 00:00:00 2001
From: Alois Klink Class diagram demos
----
-title: Demo Class Diagram
----
- classDiagram
+ ---
+ title: Demo Class Diagram
+ ---
+ classDiagram
accTitle: Demo Class Diagram
accDescr: This class diagram show the abstract Animal class, and 3 classes that inherit from it: Duck, Fish, and Zebra.
diff --git a/demos/er.html b/demos/er.html
index 06fbf020e..b5d1966f7 100644
--- a/demos/er.html
+++ b/demos/er.html
@@ -19,43 +19,42 @@
+ ---
+ title: This is a title
+ ---
+ erDiagram
+ %% title This is a title
+ %% accDescription Test a description
----
-title: This is a title
----
-erDiagram
- %% title This is a title
- %% accDescription Test a description
+ "Person . CUSTOMER"||--o{ ORDER : places
- "Person . CUSTOMER"||--o{ ORDER : places
+ ORDER ||--|{ "€£LINE_ITEM ¥" : contains
- ORDER ||--|{ "€£LINE_ITEM ¥" : contains
+ "Person . CUSTOMER" }|..|{ "Address//StreetAddress::[DELIVERY ADDRESS]" : uses
- "Person . CUSTOMER" }|..|{ "Address//StreetAddress::[DELIVERY ADDRESS]" : uses
+ "Address//StreetAddress::[DELIVERY ADDRESS]" {
+ int customerID FK
+ string line1 "this is the first address line comment"
+ string line2
+ string city
+ string region
+ string state
+ string postal_code
+ string country
+ }
- "Address//StreetAddress::[DELIVERY ADDRESS]" {
- int customerID FK
- string line1 "this is the first address line comment"
- string line2
- string city
- string region
- string state
- string postal_code
- string country
- }
+ "a_~`!@#$^&*()-_=+[]{}|/;:'.?¡⁄™€£‹¢›∞fi§‡•°ª·º‚≠±œŒ∑„®†ˇ¥Á¨ˆˆØπ∏“«»åÅßÍ∂΃ϩ˙Ó∆Ô˚¬Ò…ÚæÆΩ¸≈π˛çÇ√◊∫ı˜µÂ≤¯≥˘÷¿" {
+ string name "this is an entity with an absurd name just to show characters that are now acceptable as long as the name is in double quotes"
+ }
- "a_~`!@#$^&*()-_=+[]{}|/;:'.?¡⁄™€£‹¢›∞fi§‡•°ª·º‚≠±œŒ∑„®†ˇ¥Á¨ˆˆØπ∏“«»åÅßÍ∂΃ϩ˙Ó∆Ô˚¬Ò…ÚæÆΩ¸≈π˛çÇ√◊∫ı˜µÂ≤¯≥˘÷¿" {
- string name "this is an entity with an absurd name just to show characters that are now acceptable as long as the name is in double quotes"
- }
-
- "€£LINE_ITEM ¥" {
- int orderID FK
- int currencyId FK
- number price
- number quantity
- number adjustment
- number final_price
- }
+ "€£LINE_ITEM ¥" {
+ int orderID FK
+ int currencyId FK
+ number price
+ number quantity
+ number adjustment
+ number final_price
+ }
diff --git a/demos/flowchart.html b/demos/flowchart.html
index 7251e586e..60e6160c3 100644
--- a/demos/flowchart.html
+++ b/demos/flowchart.html
@@ -17,9 +17,9 @@
Sample 1
graph
----
-title: This is a complicated flow
----
+ ---
+ title: This is a complicated flow
+ ---
graph LR
accTitle: This is a complicated flow
accDescr: This is the descriptoin for the complicated flow.
@@ -224,9 +224,9 @@ title: This is a complicated flow
Sample 2
graph
----
-title: What to buy
----
+ ---
+ title: What to buy
+ ---
graph TD
accTitle: What to buy
accDescr: Options of what to buy with Christmas money
diff --git a/demos/git.html b/demos/git.html
index 99c53d7d0..5e683152a 100644
--- a/demos/git.html
+++ b/demos/git.html
@@ -16,9 +16,9 @@
Git diagram demo
----
-title: Simple Git diagram
----
+ ---
+ title: Simple Git diagram
+ ---
gitGraph:
options
{
diff --git a/demos/journey.html b/demos/journey.html
index dadcfb13c..96c89a215 100644
--- a/demos/journey.html
+++ b/demos/journey.html
@@ -16,9 +16,9 @@
Journey diagram demo
----
-title: My working day
----
+ ---
+ title: My working day
+ ---
journey
accTitle: Very simple journey demo
accDescr: 2 main sections: work and home, each with just a few tasks
diff --git a/demos/state.html b/demos/state.html
index 3d070f379..9251e837c 100644
--- a/demos/state.html
+++ b/demos/state.html
@@ -17,11 +17,11 @@
State diagram demos
Very simple showing change from State1 to State2
----
-title: Very simple diagram
----
- stateDiagram
- accTitle: This is the accessible title
+ ---
+ title: Very simple diagram
+ ---
+ stateDiagram
+ accTitle: This is the accessible title
accDescr:This is an accessible description
State1 --> State2
@@ -47,13 +47,13 @@ title: Very simple diagram
---- -title: Very simple diagram ---- - stateDiagram + --- + title: Very simple diagram + --- + stateDiagram direction TB - accTitle: This is the accessible title + accTitle: This is the accessible title accDescr: This is an accessible description classDef notMoving fill:white From accba3f408d1f1a9a68a05fff9899e2d51627fe7 Mon Sep 17 00:00:00 2001 From: Alois KlinkDate: Thu, 1 Dec 2022 22:43:03 +0000 Subject: [PATCH 029/309] chore: improve errors for bad YAML frontmatter Adds a custom error message for any mermaid diagram that starts with a `---`. Normally, these are expected to be part of a YAML front-matter block, but indentation issues or a missing closing `---` may cause these to be not parsed correctly. --- .../src/diagram-api/diagram-orchestration.ts | 27 +++++++++++++++++++ packages/mermaid/src/mermaidAPI.spec.ts | 13 +++++++++ packages/mermaid/src/utils.spec.js | 4 +-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.ts index a26edb303..6c7ab6907 100644 --- a/packages/mermaid/src/diagram-api/diagram-orchestration.ts +++ b/packages/mermaid/src/diagram-api/diagram-orchestration.ts @@ -125,6 +125,33 @@ export const addDiagrams = () => { }, (text) => text.toLowerCase().trim() === 'error' ); + registerDiagram( + '---', + // --- diagram type may appear if YAML front-matter is not parsed correctly + { + db: { + clear: () => { + // Quite ok, clear needs to be there for --- to work as a regular diagram + }, + }, + styles: errorStyles, // should never be used + renderer: errorRenderer, // should never be used + parser: { + parser: { yy: {} }, + parse: () => { + throw new Error( + 'Diagrams beginning with --- are not valid. ' + + 'If you were trying to use a YAML front-matter, please ensure that ' + + "you've correctly opened and closed the YAML front-matter with unindented `---` blocks" + ); + }, + }, + init: () => null, // no op + }, + (text) => { + return text.toLowerCase().trimStart().startsWith('---'); + } + ); registerDiagram( 'c4', diff --git a/packages/mermaid/src/mermaidAPI.spec.ts b/packages/mermaid/src/mermaidAPI.spec.ts index 55d46ae7c..092661dc6 100644 --- a/packages/mermaid/src/mermaidAPI.spec.ts +++ b/packages/mermaid/src/mermaidAPI.spec.ts @@ -629,6 +629,19 @@ describe('mermaidAPI', function () { expect(mermaid.parseError).toEqual(undefined); expect(() => mermaidAPI.parse('this is not a mermaid diagram definition')).toThrow(); }); + it('throws for a nicer error for a invalid definition starting with `---`', function () { + expect(mermaid.parseError).toEqual(undefined); + expect(() => + mermaidAPI.parse(` + --- + title: a malformed YAML front-matter + `) + ).toThrow( + 'Diagrams beginning with --- are not valid. ' + + 'If you were trying to use a YAML front-matter, please ensure that ' + + "you've correctly opened and closed the YAML front-matter with unindented `---` blocks" + ); + }); it('does not throw for a valid definition', function () { expect(() => mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).not.toThrow(); }); diff --git a/packages/mermaid/src/utils.spec.js b/packages/mermaid/src/utils.spec.js index 54262f10e..bdf94d992 100644 --- a/packages/mermaid/src/utils.spec.js +++ b/packages/mermaid/src/utils.spec.js @@ -238,9 +238,9 @@ Alice->Bob: hi`; const type = detectType(str); expect(type).toBe('gitGraph'); }); - it('should not allow frontmatter with leading spaces', function () { + it('should handle malformed frontmatter (with leading spaces) with `---` error graphtype', function () { const str = ' ---\ntitle: foo\n---\n gitGraph TB:\nbfs1:queue'; - expect(() => detectType(str)).toThrow('No diagram type detected for text'); + expect(detectType(str)).toBe('---'); }); }); describe('when finding substring in array ', function () { From 4f1b26fd765658b1cf01e0b1ab71597a5e44ec7b Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Fri, 2 Dec 2022 08:06:16 +0100 Subject: [PATCH 030/309] Adding new flowchart renderer using cytoscape --- .vite/build.ts | 7 + cypress/platform/knsv2.html | 27 +- packages/mermaid-flowchart-v3/package.json | 66 ++ packages/mermaid-flowchart-v3/src/detector.ts | 24 + .../src/diagram-definition.ts | 14 + .../src/flowRenderer-v3.js | 674 ++++++++++++++++++ .../mermaid-flowchart-v3/src/mermaidUtils.ts | 56 ++ packages/mermaid-flowchart-v3/src/styles.ts | 114 +++ packages/mermaid/src/dagre-wrapper/nodes.js | 1 + .../mermaid/src/diagrams/flowchart/flowDb.js | 9 +- .../src/diagrams/flowchart/parser/flow.jison | 1 + pnpm-lock.yaml | 60 +- 12 files changed, 1026 insertions(+), 27 deletions(-) create mode 100644 packages/mermaid-flowchart-v3/package.json create mode 100644 packages/mermaid-flowchart-v3/src/detector.ts create mode 100644 packages/mermaid-flowchart-v3/src/diagram-definition.ts create mode 100644 packages/mermaid-flowchart-v3/src/flowRenderer-v3.js create mode 100644 packages/mermaid-flowchart-v3/src/mermaidUtils.ts create mode 100644 packages/mermaid-flowchart-v3/src/styles.ts diff --git a/.vite/build.ts b/.vite/build.ts index 1be46ad5a..77cace03e 100644 --- a/.vite/build.ts +++ b/.vite/build.ts @@ -41,6 +41,11 @@ const packageOptions = { packageName: 'mermaid-mindmap', file: 'detector.ts', }, + 'mermaid-flowchart-v3': { + name: 'mermaid-flowchart-v3', + packageName: 'mermaid-flowchart-v3', + file: 'detector.ts', + }, // 'mermaid-example-diagram-detector': { // name: 'mermaid-example-diagram-detector', // packageName: 'mermaid-example-diagram', @@ -120,6 +125,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions) if (watch && config.build) { config.build.watch = { include: [ + 'packages/mermaid-flowchart-v3/src/**', 'packages/mermaid-mindmap/src/**', 'packages/mermaid/src/**', // 'packages/mermaid-example-diagram/src/**', @@ -148,6 +154,7 @@ const main = async () => { if (watch) { build(getBuildConfig({ minify: false, watch, core: true, entryName: 'mermaid' })); if (!mermaidOnly) { + build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-flowchart-v3' })); build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-mindmap' })); // build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' })); } diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index ba7f41601..b5b8eea5e 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -56,14 +56,20 @@ Security check-graph LR - subgraph external - inside - end - outside --> external ---mindmap +cyto LR + subgraph test + inside1 --> inside2 + end + subgraph test2 + inside3 --> inside4 + end + out ++ a(letter a
a) ---> b(letter b)--> c(letter c) --> d -->e(letter e
e) --> a b <--> + d(letter b
d) ++ mindmap root child1((Circle)) grandchild 1 @@ -78,7 +84,7 @@ mindmap ::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 @@ -96,9 +102,10 @@ mindmap +``` + +You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/fcf53c98c25604c90a218104268c339be53035a6/src/lib/util/mermaid.ts) to see how the async loading is done. diff --git a/packages/mermaid/src/docs/vite.config.ts b/packages/mermaid/src/docs/vite.config.ts index 15652c21c..a1d92c736 100644 --- a/packages/mermaid/src/docs/vite.config.ts +++ b/packages/mermaid/src/docs/vite.config.ts @@ -36,6 +36,10 @@ export default defineConfig({ __dirname, '../../../mermaid-mindmap/dist/mermaid-mindmap.esm.min.mjs' ), // Use this one to build + '@mermaid-js/mermaid-timeline': path.join( + __dirname, + '../../../mermaid-timeline/dist/mermaid-timeline.esm.min.mjs' + ), }, }, server: { From d6ddf9568ef3ac93e23c546cb59168e0a38feb84 Mon Sep 17 00:00:00 2001 From: Sidharth VinodDate: Fri, 16 Dec 2022 00:49:35 +0530 Subject: [PATCH 066/309] Fix theming doc --- docs/book/class.png | Bin 0 -> 34954 bytes docs/book/cover.jpg | Bin 0 -> 17803 bytes docs/book/er.png | Bin 0 -> 13419 bytes docs/book/flowchart.png | Bin 0 -> 14794 bytes docs/book/gantt.png | Bin 0 -> 43239 bytes docs/book/index.html | 340 ++++++++++++++++++++ docs/book/sequence-diagram.png | Bin 0 -> 19823 bytes docs/book/state.png | Bin 0 -> 15574 bytes docs/config/theming.md | 6 - packages/mermaid/src/docs/config/theming.md | 6 - 10 files changed, 340 insertions(+), 12 deletions(-) create mode 100644 docs/book/class.png create mode 100644 docs/book/cover.jpg create mode 100644 docs/book/er.png create mode 100644 docs/book/flowchart.png create mode 100644 docs/book/gantt.png create mode 100644 docs/book/index.html create mode 100644 docs/book/sequence-diagram.png create mode 100644 docs/book/state.png diff --git a/docs/book/class.png b/docs/book/class.png new file mode 100644 index 0000000000000000000000000000000000000000..5b2f663d86f967ca5d96c5fffca73b6e8efb3ad4 GIT binary patch literal 34954 zcmb@uby$?&*DpMD$p9kV0@5MULw87bqeu-c5<@E>D2RZBbhos04Im-i-7PT0(0y*d z&w1Y8?>g^up7Xxfb@=O^JJw!n?X^BD_TGHbR9D2urNjk+K={f^a@rseIuZmz17QO< zKoNGN9w1N @0>@WC$VUQ#K9ZBAOsVYent! z=q Y7*r7PwH>i#11DJ40m==CY-k#wYQj z14X%ynAy1h1}4E)eX{U+$#jdGR=fB0@G$54x2M$crZb-(mu~vw^~avf(Ia%MIT&;q z*fiqaaPc_vkPB_q$TuhinP%bE0CF 7a7rKA(cQh5g-B&5?V`|wK@N*CwK84G-4gmdaoYxvp;F~Hbx zXwR>~ #rILNYg&e4nY54@NRN7!Sqxn zq(VVEoi)jL>FUgA8{Z_teCm0o2F6M xOmr8z~| zz=e9B?QJ<~U%A;;q<`9r+Oedmz_Tnc{32(aF-Xc%aHYW%p~JkN@vXVo{6sKqU)KOZ z{#FSR*ij^JO@AEe;sok!JM&X{Dnci`@LUQJOw1m;h4<=P-{kWajKO)6t7)C|pCruE z+>W9DAk@Esl@eaU2%$1e2Kz5=g#7DL#jaV5VgEe @u 3istxTX`YJCW57CQi841d9k@E^jk>;J&(|Eo;= zr?|P_KL1PLf0O;+E;lGl{z2(?+C=|*?EbGq3dZB=&DuEzY%Ns4(mq@kZy#YzMoEW1 zrf1W5@(UU+;_R {nMd_aE{yzDSysXpIx6DYiKI{6cKC;iOBP^^ )ip50a zNjC5ZsnrUg2DhSMc3mIN-8nvne~5v%rGZf2D@s-`Tn%KqM1o$XZk2If*}kThnlI@d z_QsNuv=#!b7wk<)=w>mD`7yk8d$*m>d6KUmRWF3a>UH=mAjo=LF?qAr%a})#j~1_y zZLneaJRFT)kZAZG6aitU_&PkVSnOZ;k2N6al=FHv$*sBvY L~6A5hgqe;n2xK zBo5MV_6t29xHUw$)AP%6JIXWk^i!S7%dgmLC=K}MTo)8Hpa!_06) N%?IX8 zlTD|}%)R*+md`*h?y}gT0edf$5-kc}Yl`!4=k}g}^v9Cfus`?&LWl~nZnHfnWWE8K z`dq;0nyWmtsWQm(8{`%AvtWAF%f+mml%@|w82>WqEX9}2B)^v@ixmRIo`xMkn2)re z11cwP2Te{_2gndcJQGOg`UKmgCoa4pc$aP->4FQVrV+c7rF4A-4Ugny?~C$l|7?1? zZ T0lopm`}R$gQL4LSM9s zj8wAxyb>1yfF5i91Bx<7t$Xk5*&OlqdY^kiF^iC2)0sM3jh9&uAjW$vrc#U6M88IU zJgw}%e&2l4VFdf|0ZBoIxhYMtP~C2U0M*-6HjI1efZlbUH=l{7hDG(GdR(6QyT$Pw zfmco!ELu>GXlfBOHN!z8gasdNTk*oq=Zn-mA`ChjF4;XCY?>5f{Vo&AS>OUKVPCtD zEYmrVtWzs>2rS#vYMM`C4lN9V8F#FRYw|a{Ii4)~=AJY!p8ts*0V-?y{??@JjQp?> zq&YNig6Iw1>IFg@p8eMvi*!`iEwm#~EeLg%8KC1(YMyeX*4aV4YSFrvBK0WaATF6g z86fgT%r`Wlbk5a)BFRh7iSY2h0im3 yXa^P!H$0Vb5vLtE&WS({=q9Zuve1@-sAl!8ai7wdS*H zuA^RuCX>?0AG<~$-%~IcwTwUA{|Y3@sF%BLI^9;X@}Su1R$GrwY{nlt5Mze7EHz>= z4`{Yn1!$e3rXuz4iAYeUG!%?S{cS zG0GOQiaCTHL=Pu_?&^UwSd<#%2H!4-_| i&AuwGSN+rSJ+R^_6OQ0)ZCs{AKN+z zKz*`L3hUIUmT!gH#|r{r)?5DyDJEO$Uh7~3mwhXvfv);${FDj4!8adCbj=YbERH}* z6VtE6t{V8(!a3RTNe@bdfMhfJP6}E^RFK5+fREj+r=|X+GRW5$UaNSSbrVMdN^AXr z2S I&f^1jJaG6lWDGS@yMLMIUO zNHRvNFTws3sBxCD|Gl+gPf4-=$58wjQj-|fldjRUl!0$*44&~dG%s}$F c!!%5}rCSM{x%L}2}WpREd z=wyEo?yWW_vwGRBUb(W|S>G3aT=EC5>T?vx>ZC?}8DMF2+0F(xJp3gOzoB`LKOPj& zD&*O1MNYDb0{>U68}Y(y7KL@~^C$B8;_O^ct6q0XP2^T^zWVJ^S^ A >YfW<*V2P%Gd)@fojd!)rGRf`<)~gb~4p3KEe8|8D;0w3Y!@nG2n0 z`h%(;X4+F6widEvX-T@0;nuF0djh|3r6?_1;jKWh{r2)b2 W{)5ZX~(m^Fi9 z5J^e=A6d(Kede}`5PhJA##k5JT`jkfS?j5GFLU_b6A=HNzmVV 8RS!;@`t^ zjOr^|km+-&an61MG*!;6G$g*NT|D4S!Tn48D|eG}XcGcFWx~&M$vAz-1$w}+JJKYm z@!}Tz2gasS1|GWMkMa?Js*EqE!67^hat#KyqvgL!-G(}%(9Wv;dMi0^G|S(%zQQSu zUB-?1Mj*x2D}gi%tBl}HKW3Bp^bR}n_0^SPU->L3c+RLSsRI9lt)PZCnKv;MEwFa5 zn$uuKJAv6Fi1;l92QGlDtRc=3E6uS;ZQO>vu>)ntS=1GAmj2IWF2g}dpn+3^GDBjd zI_wK?9rSw*Xvn9?-!nu!n$$!K`%h3{8Acfw4oxpT3jTQje-K*sFYG`9&S^dmlIt zj7;x0@l>7>w>|D{{`qerPidg^1Fa<|VkwzD`iWWmVfFPF84{wi=$NH14nhZpkonL5 z@9aPgO*7B%;qH-<#{P9XDPA&+(z~JjPnlJ*nDc*NZ-n!=f)tkWcVKgOl-TrH@M3Y+ zyM~)K{`!Er%)GqF=Z_!m@TBb_Ioxl|h-;(Rh}^LzC2KdAp9G1BdS8d}uXIdA&+Fr* zfFq5*quyqVVVSz2@bco)JHy}945wCD|C5v?UExM#jC}1PMuVFMd8T7ZERSDn4m5rM zzfW}@6|%nl$xiAp)UHU!_AS8u0Il4M#WMBipd~(PKeTJugk!*EVEX8~r*uzlPfeB9 z+nf1X;=c5tyQ|vw9VDbT6tIf63=s3`pH>G<%|AIk41%OlPxv?W$bWKMU7vhY_%n1eq$k*Y3vU4hr)7>vNGeZ&oaow#k7CHdJix}D;e zVwX95LC4mGc2`}09Its!Jd?lKJGZMYd1FQ;FVM^oI%#?LSicv&y>1omBlE^`^*JbC z0$qaV&%u2M`5LS)?6Y^{!*`%}C)aGlE}F1=%DkjHMEwp?G#4ksKq`_>K~}h4jRi6} z=#nyTt8P( T&n>j@v}3V7YomWe#$EwE$7CZ8{TZPfovr}E@U<9 zPr&Mc)x9(gjEd(7J}mMGuzKo!UTJtT=xqLdvcbBq9shf`Gg0;_P*hm2Ei>^cD2;N} zd23PpKbeqcYRBl`E&(yk*A^Sv-8X)6zWoBr_pc9j#t!B&kR+TcNw=RrRjnS6<$hCK zcbP0-?q-}%9vR`dzSN<`Z@!z1(y|KzIs^Kt{(iI-t=&1YST(`K#tcAX@4qOc|FeSq zw@UT@_9d(+=U cgPdZvz94I?WA3tR#;L*s$2=KtDE__w~ozg;e9K|nwQ_MQAx z6{G91Qmm?V%{pQBfKuOhTuQ;JE+6%KJhDN&lwuk^iuv@J=7zcF*po_q?yh7!9Yi{1 zP4*rU#jV?u;3`M6`wJmB!ETdI4yFLKkS3Z{H5N%d3n@5R&YyLMOoFQ;1%$B(368gz z5AZW7_=B$xpo%OiNx5Q*Qq^Dd=DIA-#OlS=Q&{Z^!u_CJU9nP}U1LWO}A%>jLAw zVJL|`nUx8qAdp#T8(eQT)pdRw6&ttx9cUBC?!^rIsM&~Nf8R}5ekLF@0oINKE5pEC z8Ex}gIg?;bW_;uztQ{K0s`4pUEKHwqxNSjeuJrdt;>iNCgbvS_nQgdo^DMDsH4+Oy ze`{8VS<2X%20;3rsZ1khhlPBo$hvf}(C&6+ZQI=Hr?IDO!|j`%)_a0AMp=DsVh1|z z!!V~j->Oc4pB0%O566va@e<^)jplS{&oh-TfP}U+$p*4~w7{)v<8l-T&=!a)Q@={> z-))N#SQjax$yHe>Fm5|Y+%m>`#x|U_xNz0JHbJerr@`gt`(_|vUO$00qB;Hfoy(gd zaC2Rr&)G*K(qAa4&89zO78OnUVYGA3Gj6Vcz75BQA8uCd?j&Z($e7ptC*3cD^+`1j zZ*pLKPMXVTc`#ltxZU# 9{x zfpB@BUPpmn)Gn!3ZcKaWd};?m6>a`WGz$n8A$*jhQLmdK?+nr8a7Wd?f`g?+!HWGT z`8YN}v_A(+JF@lfz(@?AH_9-1-ygL-=FL=FhSwP}i`x!t p`o_jrQ=NkCtSEZE+1ap$Tn(?u< zymtEfsG=gvI47?#qx_j+e5JED5fvjxR7LG6eTBI)Ou3RUFh`q$W-aBYkZ-csX+JfL zlBE16A*Z|fJf-H@` Gt%kd7mE>FMq1>yK&v5a-|zjuw)2aRwtsjlBp(PLVk zFoN1p_7Aa-hFSJNN2$klB0(3V(XLRr$8gASMxeDgJQF4W!tBDluia&4Txlrmm*nXI zHJ`u6aL6;f#`*Z2>^!{-3F~Uvvxzz3YhtK_PIB=1Ew?^ zzHwR#G^4Cggy zQ$Xn7`@eWyFgE^Xu@#&7tDJb1(X97~>-gqHYDj29-0K7+&6|mqWYoY%tOrGS_D5Mo z&m3W!%N474F)=tef#^vGpK-D1?~v3A`v&f{rUc$wlLsQci<5SE^=kO6&{6S5R R1k-sepuGO1ckw?^{Gw5I&5}Y@$b(1H1E&s-LcS8 z6yVL1`HxXMi(`=o4=6ybhO_wP$9Fs9vjtAuNJcMIh)Mfg!RmGtpbR8l^z4rjzK 6Yj9v4hW#CC&1qe00`V~*Xz{X;$zYEeRvzuXu?;ZS*Q$!o%3*u zvZp1ye-Fb4^EUGG*r{2h;qHg=21!MPao>7bUGBq9u)1XS?qAGWPIOU@gkn0q3MAAV z!e2>txCkYWjqmTWp#_nM*(SK$e=uPV)(9g<)650=%E)ek8v3MCCjv)kBFjj)TJ- zdC%s@8zMjM18a?M;>;fuH8UUO+8#1(&NeiSY8}TBJaSCGunDEa|8wvn|I;z(giCwr zJI|}`^TZDzr7s^yzsz@4IKfHD*T!t{9#~V-j4r)W$6mTk`Lt9EM%&zV?n$XE<>fNH z?+X0^ajlgbvJNhy+Y+UG`vuEaUSW6I1&oX2jv0Oojfu0Jexx<}pvA~rp-$nSemHGq zIbRE|hM<0ua{t&>;SA^DB@7HlRk~l^rhw!c^RRryEowmXILJ#?ESgK&33|co?tS30 zRaqsoJ#_Q*;p$`<{N70g8TXkF2og~=pQ0LrU3%ba;#SGu{-YvM!E-e0*9)e4`SpEE zOV3@oSQv=zx~;p>U~MFH4E1rjx2xB{vrMlSb#1jIj332R8dPmw%QevWH^DbaRi)sS zy}d2IDHxc)m%l8=(xokajuOSbz^vsC&GrXDjRYfXc8+?^>#SBe>gt5iozjZP$h)49 zugMV8bH@z}NtZV)x&DxSF4LP6M+qMsn0*7Uexm;2?8Ul!;G2yY#+1$c^u^dX+l(?f z`HXzyo~W}33ta}0#p$b)B;JRs n+iV|h7@raY8h!*dz3q^j{T65YHA+!&5nf=`Q|0qnl4JXm!2`jX!##d!P^%7# z87m=Sza$fLJ6>0SOurA?bbJ}x(x*4z?g6zb{*{E*&ligq1{>{&`FRY?xXqr=u?%d( z_qW7n1n+hVRfY|%-!=QbSH(o*$AWszgM-b2rU=zV`>O3-pRn%E9EqroqEOLcW_muI z<`WXo?q(yXzgP-nWVCvnjE>Q_UUv?xgQYbPk@%+;(?A3{1GKJowvtbVuimAwm=~$; zvcvZ*-~^UCp5*8wk7K!oK&@2Rx0jDx2iolD(yO2Ftl&N9gAh5q=7Z#}o9Ou|U#*Mf zBhvq3TMAlm-@ZgPD^V MpmQG?tIRpILp2zdhMo;c9#fOwOsLJhYc@a# zI}Xj`K$eYB_l<{fsbD u=9)3_I9MWb;*W#x>F+|2`oMTy);SRO7;G+x%p`PT#H!s&)&k$5$;@mg|o+9 zK>yX`9Va`I6oIxGZ+u>8s?^(Fxbyw{R=YGb?CFo_I9uOy`TO7-e`FNK&1A7&d2erL zSRE!-{|gF1U@OO$1{#WZskBV^E)?tO=N#!^^OzVG4S?GO-%3Hi57k8INMI;!@JwVE zk4j<5E?UdeocqNJ0pa@7o~y^9^lZZ)cNlXH;>PAVYMe|gl}^^ko~eA! z6-yx^ridtWkDkDxR_ae^dCHiRy&=s{1=In8Oo|FLJshkfvIr@;-^G$Y4Bkw up8!y+-`%IffPA(fL#pr!>!B!6A&lvdDzH+ro2S63GVX;VE4@SOS z^s``8>wWyN>0ITnz2Qekg6+ukM;^+3I-|3_h5bJt;p#%bTF-VL?GjN`2DUvaD&Q8m zD*p5}QYGHRJ6ZecKAnh2@o_CWmH}75t86=9Kqk>$`o_#mOlS{7U!0DTlH)H)Nr0hq zZOD_-*th~rt2YzMyO &v&4kCYpOFfs@mp8H$v=uY3I^{0^iG7tvtd`Bf}T!hJ}=j`T9~*kE=*XNWx5_ zBSQ;ddbB$fL|M}=II*^TecyAN`QCA{?>?#d@ByeR!z)lWAs*L|HFzV}*hjrurp@@I zajlqXyT?y9vOVcL^nbbpvOe|cPsq$91@r{$`|0b=DpZQ5ntEE2z}2J}qNq@d8*4z4 z2xRZp4C3s&gd`t6_)UW4W>UMq_=YG_i`6r;DlL7}dInH#-HVASD58C$Yl4spQ7aa& zSM-*9y++qAoemAl#)w6#m}tM*(4)k_Xea>~Gt%?9!2T-Sy83k`vl|+=b_q}@yX@`d z-%wZc+-9EuonsUN2vs;z R`R2RMT0*rj~q)O)$Mz7y41 Ot0(fa4@_$I?{O+`0=BzKI91&Gh6wSUkcsu7U|N7s7^t| zLu`7!;tvI9-l3!dPqEs3pSFY5Rof|NJp6bpV%6Z>=GcVC6tE|CE13#VEbZ7we`vXx z4k4R+1~@CG17;Q$1}A+~ip1Iub O*q||P{Mh?ghB1E_nmI(59Ul}I?8QA(^Ndei7iqUqR6pu~=N!SnT#V0ic z6PWRP6Mqhmf&(4#@Xr95!x-7hnbJN-*01t1Vo@*JiwFssCVjy{R1tyJ3pHrbTKzhI zN;_s~D1!b__~xSR(^_e63A)@LDT4wq$|DON&6P91)K1q!%=d&IE;hVil`}^(ssd~% zRW?QoEcO jo(I4m+Xom9opr? zn)I$i1n)rrA!X$3O(04%p9^ibH8I0~EMn++Drev}cC`d?X;4tK^^*+AOP@sY`M $aMx{Ib09s#LEp`;z0Qcb|VU2n6 zp0?SGD| EMvSIg+aM%hwS)*jM&2cVy zo+A11gK2Cwf=(xk-~rfZ*t)bH24xCVAIfN@CTlBGQC%^V+DvN `0 zvtzoaRYK*Xb8*L1FZQpmEmdf{>F6YWTpRkacSV~SAYA!}kx~1IV7JhdntA(wRs^MA z543m^o>=c5c44i9gcJNz{9PRz?dPzM;S`zLTcqijQH21pva!31&@eiS8ZM>@S%fC_ z``qT&b7YkS|G>Fo(hCc_G#`%~nAY1`wS!->YX(Ut>Tr8_wxH?npksacny+0`B3^$U zw`?B`2Yw8h*$T(@l-D+QTlf+=p~E&ax-`93C4}!CC@>20I9WLF(-hzFxmlQ_Otf00 zsA&G2hY^ix_=tJs(L#J&Vp|lARp-Usy{%HXtcRNc;7-|1)D*{b9v?o4Pk?iOU4bUF zDRobts}p>CX7JI5XT#6{@B4}4l(oQbZK`IR-p*W%v0B9HQ6XYJST?zc=9B-oI0Ic4 zMn;zvD(YOs3vV~P$cz~OqCd|pn9G@>Y)tf0IN1& _36NZieBP$qaH>X*549|u4FI|ycGN{Pcg)fEbdMM#`b8~XZ{vDAx|hb8Wwv(F?7 zVO j4=u z8&1cVDQxh1T0Ir|>>(Y!!i|4qXdJ%nYfSgqXu9jF+VcB@N3_A~$QYpxkQiDHA4f o ?z0BPTCXic?2a=)DS^ zcp0bY7)G1GFeR@u%1ZIrLzzol7o!c%3ftEi(sYN5zoaZ008)__6B{5vT^*xGt~-R; zEp4O7?~rlp`&MC&7c_MeIas#^k0fp^pBjK@Z{3 ;OfqSu-i}U@+6A@6wKjZL|IT;*Bff ziM9noct1S1`GXQZfuzD&G+~e5L*K5dbu!ZXt$2?Z$lIFehBD!Jlva45!iysCO_6Bx z4NqU_M?vlYWl9D%p1|&-qiXNa5MA~Fty;VJWxamEP3BsweP0k((@`Hs7guQom|C53 z+mOJIX&)SxsR;v@S~6{JZp(OITKmb!^pUl(n!Iz@3vr<+5DV~)G`oif6QQ-So;Z_Y zfipxTe<&ISLjQ<1*m~h2WNW6&^q<5ck)EPrViZ`k;l9g#s+WKIgg1}3N9e9W0gIAs zH?(Mfzf%m>0-t}MpB49Y9?P$Ow>OlL+uXd<**R`cw_l;*W?@=GuoGuG#rD M zhFv#}fV$P6aA$P5UG$s9O!am#QwwTzTw+u3YT)`4>M>n}u*%>Rz7Ptnn86mChCCK{ zdI?+8$~$N-E3TrX$ FUvaiL<8UtrgG_Pk$b_I)SKg*@xG zgFEUU6ljsa5Yfrz=}enOZX9B_PdsE~sJ-i#{8e9Imfp0{6!0e?4eiq1>TMp?S31;5 z$C}e_bO?r(tgdd`KY45{jgV3q?#fFFPWtIlF@K3cxMD+_cs1b|=FnX@(bVtU&^!pB znB!2`VZ+B@0(kwalCJt+C{V?m4?*FPze{hZ%P2Zq49FS^5+TYkqtrR#fD}Q7i$WSj zdp;qP@92dzUvW8s4y2%!RM$<@{v4O`u&6SOH0onmXA1-PPJM2`22Z{MvX!+^! ?n8Iaq*2KI`#BaXzQmhcJQ@|&=tPDH6N zqnK3lG}Mo{#N`NB1?ePmLp*QqyetiRS}k y8<_L8+MQA&RBEK@#b zmqN^_NXG{-0D@E&I2gb%ay@mHV#H$zsn>$Y_+}SU{h!zAp+I}`(KJr~Kx&P6BN _!ks~D)b9*G$Gu27>3F)=XIL nivv7kHE)nm_3}tcPAIz?ZAZ1<3H7a@xnNUm#@3Q^D>O{&oc|k=`*6wKs2_)5 zB_fb>J6TN+LL0y6H;6P|wjXGLV(Hc%I6s^`O>49-n{2&(2`oAilL)b*SFf{SwC*5~I^YB7zP&tXzWb{M+VGh{Zhg66F^f4wL|`=H^I z^A@V8txqksnKpNH_vxLoH++_7tQ&@Qd5KU(X(+>ZX;6D+0R?GpAG#L}PJ)#%1m=Vq zW60~;QuRL)dhEn`ZA~8%$An m zj|s3ceoZjcLcH>!ut^ZS^j>Fa_RBJzs>{N|b6`}0ussRefP{s+C5M7P 5+DP zWCI{|k3tDetXd&*I)b#u>=13+834>!m1eXwjkE>#9DU{*G&T?L9La2j`!-jy=h%ME z_^hel%~bD?v R?Qgv5AKMIDs TX)vzVV`m aEJ44Wn)MGob!5Hvy%gRS`%bn z)rE$AGtXr?AZp5N4tUqei1Oep-==YjY`FkyPCUo+5j&((0C)O8oaS9UilPc^bzWm6 zyF{VKXK?bp21m1z34(sVw~|0x(fWZ2xvtuVujYZiHPr~B)yB-nai?_c_e4=8JfJcXW84LzOwoltfNxw}*wYTQ_7am?k z&q)^^c5e;ZpYCjC0hP(nbM2)VM4*mEKTmQ0WYlJ(5!go~f8rOHWff@;S?|H+7CH2E zH{X+-d60-!Sk<&{*D(!CQAIK`m7Dvee}3zn^h}CzU6fh;wr8esnDNI4@H5?GT}X7S z^#j{s8~$=y*{JOs9s9VSYdW1REt660_uh2E2M0NxgteIgnpeLbvdgAD3T;RBf$;Hg zcax(>>)o7}Z?0}+3GvcR&ulO_C(TgJ`>ul$_2B1^B79TR>aq1}Sv~3$!*ZF8$7BAY z@{c&J3rFCT{%>n1qRFNoZR7d~dPmtwPjj*d$dhvS)BttQML(kZZDpCm@gu91D{slH zPQx0j3Jo%e`r9Axj`)=qo3EZ_wKx>fDB@JE8!xqzn3ONQ$X3(?`jtii7d~3MZSrde zZ&ze07HIV29Oll4igcb2fyX55>evo@cP+Rt#V6YG0dp&J$jF!ALdzx9%6Spi4|y%Q zkX=MQvNF~X%mNkumHFG#=asK#zcb|mS+OU%Afo@fZ@L}?^Ty+?bC&`2_PyS5-hJyI z&xR#`>XqVlZU>lGzyo(yckox=5}Giz2$SvWY(a|+&8NlB=+s?GJqZPKO~>_xhN;DK zOG-THyKKI)@$5G3#9^h|vDFzP-(IYnbZ!uRcwKmMv6=vOV=&MzuD!TDJY6a|+i&@n zewQb9*SB1@cp?|BYl*DoE^8-Nhhn`NUKqP?*&NA1BQw7PGo?lrt(1CFcUifx9rp1o zXOu|3(-Z*o;-S1Os#dIh`}*gP(fdnG !U2lDtDX`5vTnQEu}KAX)3%(naQw-4bG6DZ^l(DlqV=-N z&LlXblXi}lcqzI2VnIzTyWG01P6WZanP${ O+ z!Sle0^45#9xVe1J?MeJ%ZgUe=B6FkUrJOjxF`gtHGC&tWPA!Ev2{TJBrU}6>c6a%F zfAndN7D!n5&ts9V6Yk H_#y>G;U9$1zyCAG!M`=VGc-iV};8fmlgY`Pz!@b$42|^fm7_4o+;MH`99=Xdp z{S)JCaubCMa2x6R No+-WqIo&ejfCM?GV`*Pv-E5Vhix)^YxK@_VtaM ztPtJB_zCHQEhB^0hQrX{n}vO+pR^_#Fi7H^YN8gh!j8eu9p*}0W93R7&qM8Xq65KB z*`ye_pNWt-KRYUL@`8-Hh)S(X@G*J4q88Q9tDbu<91TATr}gwg=-c$+AI%fGK?}_m z6)XQ3FO{nfsaDIs@^=T$UwG11s0k2j=q9MRA3#4Y%#m%r*0_sx65dQRtfjKAW&M%U zrcVa|Ah_#K28Y=jrDU 5)UpLme#yFYbURk7HeF+vZYv*qqi(8seP+1ifd>?WE}F zuUU@EH0vv7P(p>)i{_wQhi#jIx#*E#O~|7rcPsm=%Gw(Nn?z^2Mg|w^-fulELIets z`TiW3U^23!P5eN@yZ#+2*H5mnV9`RF;Nas(iM`D{0D(&V_SlczY+DdHLSNPLn@dUp z8kqH(vz08~`R0brNeh!tJK)rz0VqEO6H>jtu=Hpm*P0~NF(0UVP$4O|J3n;hl>#hE zJw9#Q#J7+pq_kvd>GIG*{haq*A^y^Z(H$1b-ChYzsQ+BMKQwH`d$&%)wHJVQ$MhRw z^O8W37aiwe_Z1CsUOs~iiPB@5Cj5y6dU2{1vC~^prWOE3p^5L^k-NKv)Xlxx=m8dr z<%c9U?y}!BKb=ch`n}cKNiF3-cE<+1h{cue0$Up=ugU5C`X#S ?n(&qeVH$0vSoo+fQmOd^R<`$Tm|yJ`6)JPsO#$@aG?vq44X(6u92-E z&bhAg$(xhj7)&S&emZShBCy~r>NcNg_l9>vdsKleP@ndUJNmtzfn$@fIf51WTDIn& zL7Q1A%6GKa%&bR}w6&CrVHi`0n!d{FN$^u1!EZ=suG?UV;YnS{BVW>tHQN`G>R96n z+UD;Ct~1+ =MzsJ^)d%l4dz3R*c04N7hDS<)d|rPj7A1rB@Yb)vwx?0Q !@NiQobkhXT8cU6i`6cd$uwwtm)G{9y`Z&}k_slhbdGcKs3e`)Q06)cw z*I8Q1`$<=NF5>#AAgy^4+@2+{7Cy%?L(|4~`%@Z0U!^0oNn@^X;|9$@?QunT(!l1S z_Q?2jSm?G;sKvcLB-~L~4QAWg#6?ja!o)yBr5e95z=7N5=4Wj+oL-cSoHC7$G|(PW z>Ekf-;8>2%ioq+tBitef2FDZ7S!%5B&Y6%12#X1Mw4>jc+&kEu?VZVSNC~)2>}NKf zt-80tc`QcCF~;WhC##VFUwK6LLaj;w=-}< =&G`LZX;g =% zU@!W&W+uB(2!+#bdfZ*1WR&D|35^_PjrLMe205q8I=jf2kJj}@Uv1$W*w*UDob>mi zc;wTa1!;tp7n3dXX1r)a6;~B))@>}1PCaAKYmOiaDfZt1Z}QOs-g}grVDJtNnsF_U zAb+W=0wWR%rY!mUl#~R}`KmHk`HmQ7#iRna)1)%2E;rVoBR1w$o@&Yj@^hA~mr27< zJ(f**Q#%%(3pTB~X!FH9HJ~T^$j**2v357N*{*0KzQRPipTmPhe2jUUBq^oTbPm{} zQ$|xVu7W`G;{E-Wr~LHyVDp;YVviuVlb$l{6Tj|FJ TsVpJW3Ucm8IPW;jU?Z{LEjsPllunP`jDK;{COH zjTP{n^4HI?&q~Rxv#N5N*Zy>a&%*HZm^XjZ*(n3Z%8d#;JOFTT8I*A@ey}kCHvXX7 zS8(A0T$ed-dZq%o3~(!C{;fj46iH+)e{(qvbmA;(*Xu-A8D Lz#RXnZFz_1;*AW5%J7S;20SYe12%EqMHii*mFxND%oj_gX7gKFFHw*qmsNBfT zpXk{K{)$e{yTf@Ucs9Q*Q97Yv|4Iy4D8*I@J(cH18C378)jc`MOJI?cZg4XIyx)Rq z!l|v|`m=ArtKx25KNIf6u7cCj+;g|N!eyEoZe1|!I(sI$$wIhjOGyRT1)iPR*Kftm z49~cO1~mU=8CX7JZV$uzw_jQL!2Nw$5oH)NTnFIvJgeDsCIO_uU2-)D93TcxgBqJF zyO!lc1%TDvf8=<)s+{!hX+N+B{6FY*$WPKP0{?D+m9=Oy9-Hi-@bb@p{tCwht}6ac z1ku}993lSEWxdQYz`5TF0wmn%6L5l!@Vx!gyBb+n^j-Y~=Ko)ZuS9B1!X~4nuv6Ad zZ=b&P@H$M}n6J}e=eO6^Lv;RhuQYI8Zgo#lP}_Y1t*c%}gpZ`@LcAFqmF@GJ9SD*O z#OBp^ew@e5Rokws5sN-3((-tB-NH?4(8xNb;%xf*-^^5P9vjg@=}ORe734z)T>zx5 zUAakt`aykLwKwhP05`}uaxwxtk4Y49YOEU;a8_G;@*Fk^YFT^7fjQZC9BO0)#7ipme3;C#?@dF=z@wiD)K8G?8387Fr1GzP@fM>tnWH_Co*Eyw@J* z?Jg?fn=K<)+O0`orWOb!!)d$&QsimlXudoP&mfKs!U>EUyu)Uo)<`m)5&e3jh~;-* z2WxMTG(fbxu52H?b7))ki=0JU`gYuld}pD{LVvDGe|39xqG0`J@??8>d1$7au;Fcl z#C%#3-u7^YB+s^fI3Kh%bM!|MeD@qww`}5wew6xLrlH*XB ey_@YAV=bzd|b6BH+X1=O75oL}&8LxNJrQ|{nrf=Qu z>7&bg)nSDhq;tVa@l}rA7(x7c&o~NnnlG9r-@-*h?_}Sjm!G`+K>OR2?213rgo8pO zoKF=-g8JSczIn6GN9yc@Sq~YCZb*8-f@Tn=kUer;xNanPM)e|J(fZ||Ftl4%f0Gc_ zPIdM#DC@BAR_GrRo$r4U&)idm$fF Rnlgh>% zO74uFfKg0S50rib$@jY`Op~IQ0wXS!cr*ux>FDK>n%uZY#ulGy%U&=Xzm%;R4lgai za-Ew?o*)AyJVIAE`0?tVPc?v(==-z=qCT_&$6CL?2}Lu72K2%#$e8&3uZK%2a$Ov6 z?3E95EWfrEK^50O5XXj=3sRuQ%M?<|o RUF#5tzpC~bt)=#P-X6;E^kkGVHkDRB+i*FxTTtwAA%<(D=E`&v+y=x`qY*v` zL9;wVK3GWE*4*0~mI5bQXTqygV87?z=ey#Jutk`H9-*UN+o~@vAt|Js{(dlzsX0EE zESLG|EY18{15puLfo~m;Y!yOPi;MF#GkS-XiE@E~x;HmP 2V{3;`BdS zd#ku8+qUg{h9M;tC8R`Dy1PR{y1PZXyI~L%X_Ri1?rs J~ z4vNC-38zG;>RIkV;Gg+TExOa(XgD)9hhuNcnJZ1(=D%Z`6867CWbD}kDDCkf&|!6e zA3hwH1$Qt_adzw1#dW1~--sQcwHGCUEzsM5-9MBIc=h_0MN}gbpKayWd=<7SHu6z< zTVN2OGfR&LSIicKmI{hZCW)E2le7TmhrR7BW`lGcY_jmkJT5Qx??un_aM^la #z)J6YYhJ^*^Q|}}d1G3b{n?Bs6Qt^nQ$RhDbKFv4P6JOX5on9k zN1D-@^WS0i2j>Te@1|N8ne;wo?!d^PWG3(sJzt&_DvpUEUp$gA;l_t;;RWwTsh;w< z!11o)4*WuYOo_sZ!A!`g{}BP8qLf1--a2HR76pz6ZRx+8*$*hqzaXvhW>rSX_FvFp zgV;7%T!m*q>+J!47uG!|;aL~x@1&6`lxBir#uB0h+K-`(G*aFU19oM}ca)=(3m Q*zRs>q?L`Xnh@*&pB7WVuhh^# zQm-7}9Sd}h F$$G+Jm-S|nv)%KLE9_3NQT%2^ zx!9k_ZYoPFiRYI8y0N20oIgNu U7?a zEPJ5uEUpeMl2whEU}{Jdt1oU=&**Gh*2h#-eQaajR{w}a{#1pP-JxmzC-P;OaYKI? zkpOjZZ6?e1;FEaXITay-j4wQYC>IHcHQdlw UQxqQWC_7Rte51DMQi8h&D1dV%2 ziNv0EY$VqSt~Qrx3K}g`@xC3f)3;S7dc(5(0+F|qVScU-d+*==0F6Iu7M>U=^7?|M zYM||7nPEJQzcFNfuu47GaChxmXI4k=>0_R;JUP}c9a!|>L3XZAneZ-J)LUppE#pSS zCF+%(+I#`D;eEJabiIbQAYj+-6(Xo6Mj5}(jNr94;$=62;|lU;ip{u=rgHcla=+#2 z5p^xR_kq@KMrDo^QN)!o@ t5rHqn2#QyiDi}p3z5*};1_W<)$G&X)Sp8MZF7Zm-N zmsK)+;Gb-2-n~$C?VIT^^wbW#DxYa97dv^{CACw_Ql=k-+|2*T!~#ujxJ*uO*#S6S z#Szs9fA|oZay6L=df9!6m~ivcvXK(UGH#Tsb}BpAt8JJhxc*cCa0EjknKgS2K8QUS zcbjM_^0SN|Zb=&0!?l!{ZE!Q`qmk=b+gw(Zk5dTDc06w`^8oX_b|=c_T)ti$b50pY zV?ID8VjGIjfZz7H8Q0Rww2gr5A41cv?fq_OjTjQHkn=#2O1BC#rVqNXx1QcMJ?oWw zzQ0*wwHbhwB6wci?^EW4`CPkygg*|{Z{M}l)UbFxU2Jyb9PvMuOjG;zH?-j&;=FJ1 z!em?P3GLUpT>;SaG*R8Io(YqtUF@!0oJzx&*m>rkmf0<(;ChMV4ZcxEC7GJIKk7x- zxia}y-MAmet?amf<0rzkCRFb`eC6BrPV6v_0+edBTuYuzsPzOW*H8GGDy9lKcEJmf zZs=&3K}06V-*z1}9fD*&PvT7y-Nj-KvI*N>1iU_43U*q~$@l@!SO$#Vui&gri()CT z$3#ruV`xhQ|C_Lr&>6*xMD$3Cy91KV036b-`_oh=PoV5|T{URDn *2#l%{omy z@~%^gxu|OPx(-H%pN>#vPV? TCDDYWrsdzE;@Nd%DmoqZQn$;Orx6%(|Ldq(sZ@}mK0_#_uP z6`%BAHka{6uwE6(KzZ4JUNnPy^;csW8-T?|_sR@HEvDl@e@F
k=0$!~*r;VcEmP@4|F+DaZ=^ z79g8PkUOQ9IZ@e3WM)=xz!E@uy{lhzWzLtoTv0?JZmr924+|ke@Q?w?C;;k;x6{B+ zIFApj`mJO*3im%9@3CbPS2$s{owN62a=i^ZK*Q+JGnBK+l_-Z7JS-@Dnom^w+mLZP z!#N?&hM*<~lONt3WpW!RfOQ1)F}{jqL*yrC*;u<-s#m+s1&2=sx(IK(#`?%Yc|6zO zYm@yTJD7a8s3il{7^$-7Pg3+3cAY0lvd=qck#X5$`()CiCnnmy-u3q;AVP3HBo(2k z;LSgN^0}RZX2c}(a2UR8dKD;dJ-0CcWKqw#VQ?2*TK7^Hl!h+|01m$giel0gu)9`v zRESIhuL9isPzgSSxyp@H(fNM|Ee?>W)m-JRGw-D?4h(c3&QKO>-Km{i+z&mxh%lC0 zF%)nvYt?T1(Z1L}&_foZ#j-zgbupZ+Mz(hLu`{FDD1TEO=N7B*`wzEjHFZOWw1N!L zmC0Wmv0gn59zfC8o+T5#7WS{d`yx{}33pQJ;!&H)Kj{~HKt5i( 6|N6&2y8$5?$lM-4J}6KJqN71(b;!R(-uW47o5J-r zvtBt&B6(*pvy$Sex#daby8rF4o?jcm=Gs?Bye3N*YHX14{yec>o6b|C1;l1aPYV50 z-is|lhUvnoCe<*i_2`bRXV}+Y%>A wEB80GSa3pECPQ+- K9qi)C*bvb`{{c@F^*7N&j0;HO!ve5{ -v#mtMMA5LfzG8W*A ;RUsd+9@Jdu8y&s_cQerm zWyIiR`}KO=IZ;FKPoNLb%cCrSg*y7XO$HrxztWf*Y$ki*07R}oPX_jHvY#^_Di45l zV^!{Ca_{>TdH96C#nIs)Xgq2Aaeg^BFP^W2+M3t^oNZ^<`GOfjXC@`*t-T6IqXJ~< zUfb=sE&E?11>=LZ_7S|30=(UI7@sjvyjo+I^U?S| *)`u39q_>7)qDDokr)QxIcPjk1w7I{jil U{LmlsYOO;ObbiN0ij54>sD^JNw4jdP#Q?4gKQ~wsv%T4_$ zl|vJBHS=*O e>Lo%U$i5jIKBrqD=BoV zZ -Ou zG-Gt~VznvTV%?|0Ag2i@9 V$Zh+o{sLf2Slf$i=5#xP^wrl;-Y;G&sh zE}>gPqf4d-Vx@N$duOCLCt-7Vu00yT!Rp{DSXc!3Qcy3Rq6uqjVGmApBhkjvLjq_W zEWw3-)ShL--P-guvlRNOs!C~-C1XozgfWsCFziR2wZ=3QYMKy8zMkS73t;>y-y2tA zav5E2;x~`!AMEI76H=wTeucU$GIP=0nO`t12&_p0mj|}xisDErJ^>{aK!QAAo1Vb| zE9--8(ZYB}q8cGI@TJ%K-%AQW_znCu?B9nbAXNsgm(;?wZSCWbbGDue^XaTw0*_x- z^oLDsps%#|#{ObWF+3lCuVkFn@5L>yU?_{Yo1UywW%U{G*@;W(TnUtVzl5RlxQ7IQ z6o*nRR-m59$?DR~(VESodcd8vUP}XU>l(gxzQh7+ns|Sb odo_)1xo&o4$9BNmpf^>BHLiu+Md0GQ2Flwn#kHwx} z#bE3Vqpywa-NvwBoZXWqdxXXlXHU=~mBz~VCb%k(XI$FQLwk6wcfq8y52h`a0lS6$ z7nG}UKvo@^n=#-}ue9lcr#5X9=gj8?k4zeo{;e#wY0H!N6PA!K$dw^Z^$#}%bQBRl zDkkc+Xm2YRd0Aau`41Jv>Dj+=DG@_=U|n9BYA~9k&F{a3M zOU;B_dwkjY4Woo?5Whz(TfwW#y6VxECxDEE_)B6pW(+ycgSctYnL{ZyavD{9&iKVO z4$23h6UGM!3^yX4*Ozl}8_fy$2WHR$x@!ihAoyo3s@@G_vNFWQfckMocSWtK?X-g+ zS@<#94^uH1R?E+w0^J8!@xfD`#QNKBT$CxlOnr4#0jd;R%q_h0x!%$Bbn*$b1re1S z;$`umvb= !&8&Hs*cQYz8GLi&q;Xd>|tz=|oS-MsS78VHuGVy}s_FgyY1F2}ZSB ziV(V+=DS@l+8>1q8|TP-1pUSRkKAcn m~}o_e4^%(EsEK)PAzdcqrs|jOC`m3|q{7F<=`W_dC;#HeOD1 z!l3>f80|t*Nq+nrOXnv4X}o|_vGuW+SbH6Y*o%zsYq}B54u9@erqGql^IK6zHQ5zs zl;3o4 W&7NfEINWIAR=E{IVey>+UuqNLs?4-DuKtcSs@zkY zAs1YCKTv!D&1?xXWJhs;;5WZ(vMT}o;7>$Es#I_cW}%_h7kS&6*9#j(dSF;VlI#ql zBEe}=RYVC;+Z5X)@MAoE+CBzLh&!5`cR2)*P?YGe&` G+61sp2`ZT=?v-mU0X%M4KB?`!AA>&`r>H;tS8F6Ir1_ zmm%{UTQQm)0ByAagUkrZGMYG)Cn9>WjrRPVHB29%c=5xlFb}~(3BDHDkz#trJE jHBQ3p^mzVho5EIY8+b!6Sgzi-lBOa zVC-I`%`7T{^q^Gv*Y2dehb%#AWt_r?&+Pxq{ZvN&pSAHxHk2f1GFH1!kUP;A#@G8r zDOXW`*N;5=6tVVEF4vPl#5hA2qwJB?+lj~tfKK}ym-?Sn^|>&02(B72s4T)Q@v2xf zv+LdPHTwg?z)^fL9YoP;wSmQ&R^q+U^CVAIs4w=rOA%&s3^h_<{_t*8*&7-aw @c0gQ?!fb57}sKZpaTjJRSR^;tjm{!umtYu!ws!X5QUa)lXnq)T`6iNqf1jYeT zOc07DkN$M_ix&Pj9gGD*y}}){wyF{W1=AkkY4;7|>V9X`@IM6b7x7QdTV1o$fD0D+ z67!|V?J;0k=5=iuL54==aJoT%y}g$qC(6SJK!}Z4+P#9}yH`&cI4>hOCVpD`ZbK)! z=u-RRNBs6_U&0_*ioCJ{3K0|AkbPV4?h+OWZL6 TyX(s&mxN)i~*3%-)Db$iv&Oh!C%Ft(q4C>=TEJ0n<$ zYjSF<$>Eva0?cO)4Ua$vR%ENg!jAhI8i$g_)Cw{Ku+qT9WZ7&-VoX0 zIKzrCjI?fruvNLFnk(Dd@Lu&{UX?jvSP4?j*1!I4hK4K%Y<#*K4P?@?Ls`|PMR7Er zexsH(bds6MMRF|q%KHAK4a(0wVsa3G!bSpEQXUHTNYu0N5M)= ZyI6skmp*iO$6|$IR;iONB&j zEl&fY!mf(Lh#Wua0VnT~#}P8HM~M*^F??{pkO>%%QLy=-#t;PQs&5Ncyjfgi;k*`` z*|Q7_Pvo| )ouII-MV{CZK(C&g@XVXPjpBn^Bx)QoPd6I zj7<0gTYC=d%x>sEv p*Tvm9rqK?cWjV8V&fyW%> Nukd-rGB72^C)x7yQ^>V-#Gg+4|8Wak@!9`&db`t z5&;uRGTW(tbN;&s9i|JZJJ`aFdig29=wwA7k_nhOqim|H%J0r<*C{AMnA~mC61Kh6 zhn?_w7k}R_*_XbfXt!BkyR^kev?x0J2i64k;YT{=@W8xkU5@4Z78*R!HR%HAd92)T zW=nZP!f&7{<=&@u@&?#*oL9{e^t$KzF~<&xE1|_Nj_~u-8$7qu^M9=F#0if)zhKHE z5snWNVeNPk@nXscfN+gJ{E=tL?yzBLQnD`c&9aGTu6NMYCcZ4kxhv9gjiJvZyAzTi z*53L{*0=Qj 3b`2Wx*4dq*VaXhJRNT*xy%$J^p >m3^zd5B-!g zVg=*Nx6377dKCNA=Z8!=(>!HAFR&hS18T9i*=fR6wH5W6QyIA>gxrhBNMycf%4FpvxjSen* zZ-fw&R8=6K4Wtf=q)fdKT{6-*OF9gZD0xmI<+xk&50*0Tk1w&DMQ_$;cX r%{}Pnq>q`ICn8u+SO>2K)~@b*`MKJ?TDJ;laDnEh*`xi7!?koRDNs znRR~Ewl*mk1JPlRg>xVuvYOo`%L~wON5k3HG?Wz$$o_0hV+mf+uIP+91 %_pJPiJ>a6#6UhVMr3j)jLOC1igME9+BZ!sV^*)F3 z)875gWum?xJ9(qPduy>n?is-WTD {_zFxAVm^3FH$Wcys zz9^GT#&OQjYOg0D^?=UXrnm#@&XrvKyQ~r8Ktt~#{X;_?2s!6K7h<4?(Ghd$Hd=iH zrn`)>44hpWn>4p_ZP_zaUxkrpKW9G%mC9ub2qA|=b1@Qr2398|%3JL`S#BC}xex~6 zOi-#zUqY@sYx=>Eo1nv79mCiNH|VI0H+F)v^{41_?q)_B3l#ZliIgkQRtiGKHj(3$ z6ft?g@`oB}e8899Z#bL6-#{=DaG<|xI_&uGF;OrgxVwQC7$jc6Lx#a;d9ZKl;LHu6 zx`h@2#g2rBZ#_CEr{|i<{Lq8_KGt`ov**kFu1Nj*xoi)G?LV-WY%Ylw!dzr)3!C#0 zo!PTVA6j@F0?yw!wvrWjXM9gv#{8!U35(84u&{o%g{~PE`O|W^?5jNu`!E$->1&o| z8fXk# fa 6xC{yjPP2Bir`R1SpSs0xU=A))kxXD*4uN{SR2b!Sa zZx!^=p-QjDu> 10W4Um~yT~ILt*q4JgPcEFUe j!MGf& zQGyHLPAtTfv7I!y)9Uz2vwP=uCv{6@)EqwDOn_1!)s_5e*5A54w{n(@1 zg!tJz1p$@s+Q;oCw_L=Qvx2NWP2N?uqK~c DqWCB3>aMYiHB~F> Zp!u-qAr&pb zBsF+osv8|+Lz%2wGHzj+0A;^TYZ~FwQh6_+^ciRtqj&Jog<~Tz*Txc(1g&N~d1~@y z`|I7`Y)>tFT*GaatMz+;kl1a0;x76KhX1L$2?TfZ`O6Vi7p6ZG|Hk!{R_tTh+4VHQ zGyV`0rjHzi{M2fQ#K>g$9fU-E;&p16{we!e`Bfw)akPQ(HQR79`~5Zfd)`HF^wtf) zVp!-zUU~DhZRHXp5NKF9 $O$~;q d z-ff7e1 tDH+FUy8xJ13HKeh9wPR z o9MTNIqZ zW<88M90EYA>bI=WT%n)LL*PgG;N8TWZ|#J&BDkxo)etEbQ 9Y%Lo5W78qD6|SEt|8k$&?Z#dJ-F ? B0DlV;oGN{)OgB8VD{j8x9mEch1PXf5#0LBEVA{fR%49+|4dS#a@M3j z@1N;4cFK=T=vr?6S2AODdL-w8{?+H60 I=u%u$>=<_)rc&nipJ1cD$iqX0*gLWFCoTc!;-RkuQ1sqO-9z0y1nF4s{qMv=T2n zN$PS1|0DCI{J(~v861n7d`dp9h+O(79me~-acZQPmK(rSbmXLG4Rr@Z1`>i}7+AP7 zc!@4+o8jLz1%pbaOc{{%XWKuD^4=?&^Cq5ehUEXs~6GCfd8ps$? z;)9>$Ck&IOrHFFby8k-4 -ZnFX z%P*JTm$K4bE|u_yJ8LP;6BEXZ_yu>qce!qTn!Jp`uR)xAT#qvmLo{NzVT#tWN1hAX zY6^*@@;pd)x%i-Lysm))dMvRSKu}+|4OP!}mY*jyFzH?1)`b=)Tv+-cBYo-;-4wN$ ztRme8y=io4n&l6MnNub)TqtrfTQ-1V*u_=G(P}c=&nQn9J1UBovdjQH9)Va83_kG= zg&~rgnPr8Yi-SB9YutEO{0LbKgotv}1t ;Y_xU@1kM>PKJ5ejD@rHot!t&YR(RG0aR*!499mL2sqJ$dE<$nPAI*4PEcU-pTN ztAE)TIyHhDv Nn3)$4#ZkG3M4|z;u$^o_Qr<2VnFcMVSa2iq9(9U0 zhgIz~ka$w^&JL`(BplW@%V>lV(tE^^-{?xc^74Tw3fUS)HbNOAl#zYPrmOo@q~BA^ z__f;c03F-^v?}?3WY_;6{)JpCdPkY_9o&iVc5iZMABXp5DX#q7(-fm@+% Hm1xey#voqBImzR1$a$>eeYk?$`6F0U|dJ zqIKH0T!mXb(pRR^4-5WW3+fnNJ6|7{>FUhtvDynMz`?o&9sqO6HeYXSUUrICjRnqo z%yr7a;S6XJhj+XYsYCiKVpB;e B$FB z4z%$?(9+fg*8}eviz&pB7)E4=)m#OwE~ZAKbT}Z#piU3=FI*
4>iaHbytcp?aON #Tx?7(#2>Y^}F|al+juI>r&$ulh7#b}?hF zfy+sVyl-3@w=-~@@M71GEP*#`sDZO0;Fbk`9)Q3m4keIK{dZTcd$08pAY@Frh8o+v zJwXSUAI3$62WCy2hFaT3j=F00i2TzI1Kpv%ALJf{)#!+fDDHErN+dq4Ll%W7?zNtS zXUxp{8$y$eK(GEg51>FjT8TrNSxsNZEa4p;$sjgacu*dUuNdFjbFc2&GSsyVC!cA@ z&iB%X_%r R+4W35B9G3>X+*Yy*1GLe=2geo^0*A~yGkN`_Z4Yga1_}a;Rczc_WC!~2>(h;s5 z2$zAUMMDu$Y|ks)YvuZ9r7nH3Meg?5;m7zHDLh tAW{3W2p<5K{i@@Z(`P+DXlPN7YzEJZ yWTn?NOLnNN-V~%#m)+NwvGC5n*MVK2aYNxG|FaH@)c~fpF`Lw@}e-& z(-a#@dS(i^XWlgnU>)vtD&=oP$u%yYXN;CS?UzmbG6=(Q^+~Z%5*r%S)CA`e*<^*U z%KaOD3GHEl_$1=<8aE)>O!wa{_T*5nOgZi_X=)ngYEiO}9a5VCwLql?jA1~EW!p0+ zz5SdQ$Zw@XP*7Ifl~Cc2LW&U09jD^U L9> z-YPs_Sh7?gTmx?KTI{&8S?zI(0M1Z(c-HihO6CZxVN1`>Q9rpeu_8v7@ICs&$axv0 zIGw>m`x6zM&dFx|o-rX(rrKJQb6~#*bW@g}a!RKuNJxQq&3iZM3jKvQf^;V#1KRR6 zP-@+Nyvi^ZBi0-J@hoWYrRiIRnHGs}oeV0>hcGL!xNJ}sfNQu~3FA#y!cU*k^NXfB zZkCv8V`Mu5&SEl_Qcv!rk9^?l{;Rt|+<#v&gaazoJMVTf*>YKpE(;A1Su3dA>d;K4 zDxd=k>JDr3Pmn&Bc&-=puw&p4WKbXC-E2no7)T02W#bs%*ATnV=U(Q*-VFI-ga2|V zHT%E?^OnD^{Qe>>r9_3SrtCmM`faps z$9IBUbW>}-Y5w==Sz^#x8BnGt3o z1YflGuosZ=tidA6n&tX=q1EMEir%ifd$1aJt(S%Xsmwi@hriH?Dm+l^ORtH=vw)0I zVJu~^c1P%7@%xQ^6!T(_pvxB$I&>cW3s1OK9Ze)M7nohmn`sqPZ$^E(&IjFj`^Le$ zD#iZOcpn`>!9bEj)Epp*?$L^hjakZx!>>2u)RI46@FJG}R`MG^Ul$cE_PCV%tAG!v zOJMv+NQ0Mha$o?Ar|m9Bp=bpxsbo7FgM-jmi+B?2KFU0NCHNKp;x!^FMd**qMb4*J z7veO7&Yk!=Sh=k?SR^BxY7$uiNB!2|3zOE=syoztGE= ^4m*T%4uLt0_0C4W0eu@io+9PIP=xVWJW7$1%-1H~~ zjK6)P8~(EYuc|b7mso6XQ~n3Z98vz8_3F@>+sbX?SD1VbMyZtQ**{13hwAK27F*Gd zQqjQetoJX0a4sPF^IwJi!p!QhrzF`hLHUqMTPa2FX2X6$(jcT&4~pC34mSMp{4)aP zgqF^16Pse#FWvAZX&mZKK+eM|^nSQNkwOe%{FRQ7)q$5=CdQ=HdP&95q=&PHr9Y)# zNH(QF$ue^XbjvwS6@u~4i!WY%Si3Nv)usQ?5a+)ux %rm^S zXO@0!&5d`V(b{AGt@l!7Zo6F_Q+xCd^zAiW_Gjm@o%#05@RjC2ao7C1N;~AFBF+)` zkV>^xD`@06?;t#=cKbU%`bpGF-C?bERx^%lC$y;)kt9(C&&PmZU7n2NkV;dVwu4@4 zrJl-c*#*+IiVN>bcS0fdD4vY!XYIXHcruv2dGln$dcu7M=8>&4V{N}KtSh}84xjyO zow3sua?LxI`1V@uFlKW2c=i?)Q>2yMSd|vw9ZljI7kkiIFyspvNCRta zb1wKRiD{O=J72uGw4X;?qT9~Y-SB{tbfR~>{)Noz=zn1o>X7rx;xrLk<=p&TFL6ul zkDnI(gq?|zks~JiVTahVx|_?Kzqnf5w|Z@prto0z@>)X j`Hc6SX9e`H<@K z+xA>bkh#m79)6opvp7f;C;t8Z1)X4^mLT~TH%|gQhWo|uu8MleS+PyNLJvN5TKVKs zC+?d&CX0ddEh#ePXt^2uC&q6@jS zSnSuKJNVG;?cbaB8Fp?qE1L& zPwa3b-5ByxPilLX2Kcl? h%&B$oatJCwKCVh$b6`qytT<`1C->r|0 =8P6G2vO`h?GqQW^*7%mx}z1z1FdQQ zD?pm&34K9t(~FNxnaIbwx1qm&LZ?_kJ7U)}1w#}#b}xaagTWV9W#t%VhoNut3v{O| zv>%ob_-xy0+pNtJcR69LoUjBvR~p_9K}|)$tcdD6*9)|Oso$=v6ah!;6N^2v<7Jp% ztlJ2$?_SWFki}k)exV|v5h$S$Md~D@t?Hj@;i44^lo5+P`UeAjL@_WF7Q7yf@U2AY zHh1;nhYm3@k|d^jMiY zIHdXzj*PqR-tKi0fjPIj05^<7lWT1!^LeD%T*q&wBuQ_0T|e~6>D=z9AcqTAUiFlM z;GrUSmLYp 2Aq1cERUVUes2mUo{__z69<4!!r zuFM={q-4}2(N+KuoJM5{KKWc+N`I&T^k8*I7M+6GxGD1KDzL26%?(c;MMjc`Z-ne# zFp*I(Gy6|q%K5Ww($p5PYl2=R;E*_4o5XM2pv~rU G6f6(Gq{omG7F zGs$&KNlO$pSX)bj`xW+DJPi&HOs^^xhs+qu$`m_J?BDW%JSi9vOJulgbo57rf3DE! zKNzn@a{AB?;32>*HdN1%qFB7O8gGCXnAWN2XLs@c;%Y;4E+qdgmk3Un;tpCLoJ*st zBg0tT!B$DJ`QjrRktZPQ#JKi#leyX-zewtDJ@|l>I8_l$2u!h6BN7kILnAw%u*2HY z^0qWiwa6?~OpN!$ZGECvOd~ts7%U*>BHb@9&2L*Ar^L{?GKmpTo2)GNnfOW4@hn=5 z&!&z~pO7kHo{i GS*w8j)% C3u`}ME0Ey`}2OZgSEhd>;Y-UB`7a$?O!nz?#}H`6a-nC#CNNc(SniQ z!CPv_ZY%@6OrgC3-263fWBgmP&xqB?L59A_??TQDkdKGVflW^@*`XCj(X?;;PraFf zx=i-_KgS _q>yDa6dKK>P*#6@|&zaW0;|sr20@a-(rw%6Cy7 zi1$QApOr+DM_x!VM6b-5+WZsWhekm0{vI}*dw+Apw+oFf%h_KYh@9EJP;ysVRs@dX zE}Ty9I#Fi-<6?+DO8AV^L8H6FBs8#3*PE$j&i^P3&jdb*q(FG}lMW#>!w@AN+~;Hk+#@lVwG328NxPb_ 0ZHa0T;lT}W3x#Ot_YYjtv~xlzF1ZrYJ1t Ph;Jz6hn} zkdTh~QZpJebm&gfI>BQ@%AI4ue3=4Tksp8A5G0 G@ zVXKrGY0dLosvxMe^_N0 L5iGi*z#I8V`=W+0p$;{&z?ZO#&6m$iE7w- z*DqL}_WKScc5}{1m(vaKAq
9qHpPDunrNI6+S@`-jIY|4J>CC+_5Ffpx zvgY?oe5P=a*O#EUNxU9u+|1tt4MB{Y-UTJ|9m(;|{qo&H>75CsF~#J2FL95Kgvh+x zE6N&id(!3AVO~TgGoaol`k8e6{?l}A-_P+`8P+H4QdhXvxVv!SpO3pXr=q(Dr5Vx! z@ie~{SRWr$Dci4_C-LlG#HD=&Ty3@7e z!E-`{|^)FuZ~j7?B5e!Mym}4GhohscHz AQiT-ffm=Z^>ZJ^9l-y+Dq}u %)r~mN-nGlscKI{C?& aV7fm1njNC{=@Xmsm|oo|TygINPe=uY*zDIyB|NSt3#s^0E3f(hrX zP%lTzT1IJ8nD{rucSMez3CRNX-dL<79RLVz_OQU8`Q4*K#`;r@d^UuzdA0n~QN@-$ zhs+dU4_o>m@J!(*hcVfoRqLbQy#Ub;0#`)qB~#*v>w8R9u`eIISB^<(>{-)t?^-U8 z;sCAjKQN*FISmObHLC(LSHN^XY0?j|SHPIS vVwKa zE)v_ce3027h{%4C1V#={wp3*0Q}Xeg86jObNJgjFK*{y9Ja%Zyhf;wiMJ%ZIWWKZ5 zIVz)|1S{F|q<#$^d*9I0PAiVHMOoZ952&a>KZp)TTP{zCsR%txMND&ACLpfD6~(DG zUxALv4>7#HUS%wO`ePp#${XxBpuZyRWzP&9>r!(o001zhWF^HlGQrxGhdJM66^3W` zX4l~7@1?*_IX|`mbTcep>yW!AUFGY%)_?b8hq^kp0vtO++lA4E9)5C8eC?^+mr%SC zB7%AMke->DdDq08`?_uZ%J%L_XFV!G;vKbvs2{aS%a!!92Ht`EK(Hd*q^yO(i#Cc^ z{tRr#=TBm*cRKwy%F2a5hG@zuUJ*~os?|oWY?5*OiXcGK%q7yN>8Bgv7Uf$0yfBKg zHGy@v$^U+e6pF }Z&Xh5%7{ zEQpUR0(_f5xdtT*EML{3=%a1P{%Lb*rqS062+72Td<~>|NumFi#B3BwUTfD{Lg4ut zaGv*^{95=pqaf<+k39zds}~PwFb?K UaAH&C`xc-3bLbwZs~PQqRJ92*EX@UVH0*^+a0_UsIq$`qPIH zP3aTKI|AWy=#dR4q({>t v_|l>~qQwudpO;|?xu;X h5fJ#MAmf7YYPOtU!JsWv>ww{Iu&xh zVZ}H?W!ac5{-*|{?(lSyE#r0ErwJvAZz%L9ob}wxn2s1dtf%w&+)doNI>rAAizY=F z-{yQ7f0>cwE`7DKGI&UlLHovHx$yQ!^qMK;q?(Q*u>wp>T9|hc^u$y&oV`@+R1>=F zZ9n$x8UBWjPq&ciOOCvEx;xC$R^azmI8SA2n4Cdv9OyR9F2Bd%3%xE8^_2(G^)87` z97}}xxd1rs4Cl^DNPD3dYbf^ z-_ y$j=2RaU^%TL$-wS{NEuJsHCB%M@mQUc=vc@ogRgk%I ztGbRzfJI=lVx~hT`3^Q2RXeHyx3KI2rq?|~E|b3=QvZ222F;^Zm7~pM4`4fdL1U7x z{^({=^^ZIgI3Ij$({n dC+QP&!c`33}b1+XLaGBvO7oEdRt^jNPL(mOZ(rk+ddjJ@EWZ&or3v%7iVa zprA)tWtTzkF7WIC_Rcxt=_r*=*g&tp$yoR_gw~^zxQ25e T3W8 z(u){PD;Ik~7;L&^ls(hs?XXoZK=AFxLH!wt5=v_x2*>*912MP+;Ll8jJb}s>-oFzu zL;>G)>gm^_glpVQblP5rnaXk6PUu4GV`fNGa)Ud>;0(%a(tZtuS7X1JDlSbYSm}}m zdWYmE%(5HiL+L{(=+*jnTlok8BQc2r`WMe!hYPuP6x2n?Hhe%^0&SUae0Y;>$aZkM z?^LTk(#5 DnOTl0YC_u1iH SdX<|2USyhnUqpL`SAAkNK&Bw#EVyOU*1z@r~A~0Z;R{^WwH4&9yPLqXF#~Ds|%z zk%x{%?Kro`Rz;T@_ZQLgy*f5M7G)AI++TTJ=3k2n+x!~1fQdJ}Q&h+@Y=>|h9{>Wl z^IF?+aTq*$YThFJtLs=A&0Fj|9V~np$|NjG6wkAT @T5gE{r+AF%*1 zh>zvo*X2~Xmt}q`A1~Q-cdIC*h$8Ul=26T1&*1K&ZApqW&UVH}>x1Yg>L*=1YLx#g zY;(~RBwEm>FHNF^=Q_9+&R1cY8r!WJQ93Q7 x-^G$#EoT8`Ps@ccc3T zC`n;*&&u`Fpn_GA&`7zv6AA)|)8B%V`fX)Mr6A8=J`905QrLrZcSKf){tve&CI9!& zErlG=-pkZ=Rb!J);fZ0Y>ilc2QoR}3QKgnl`Hn=>{Qo$P^+zDV%jYr6I5Q;x Ftv7G2S+BdgWLxdCYj;(hed_%A@@EHtsURaS1Au`60AQeBz@K$MC;$lw8H5Z% zK|w-6MnOSA$3#U&LBk=y!^FkF$Hqp-$Hu_Lz`(`ECB(tUB?1$Z6A>~|l2YT4l5s#d z8F^_SY%mB=Ml^I3R8(|yR5VO Hz{f RwCq{6{K0I*mva9A*Zh5+0zD#E|0`tJ`691tD> z5f%gkg~GjL|Ng+jz#+f`5&x_KP~l(zu$XX|P}Jk|8;T{p*T`J24`}ZjL z3ne8>CjYu@saiPqk lC;#-N+koZjF;z z8DqwA6 h8Bha8!01WN^VF_j)qMs)Iyf>c-Qv6>AXvEO~ )wjFb6E3u zon`&{2hR7y*m&B =iA$2 zrR|#Wzr6ln@XO`27jdzk<~xB0N|6~3s#K8%5-^xUGV#VkfV<+Z7i>)ZGxAbPnV*wB zQ;u4}lv=7ZR0$${&?vAsTXLSyN&Rp~i!CKL6y7qF*F?B qw5p26<}LOXp1 oxtCIBTnAn;-VPdhzRM_cJ rhj0PgkRIQ&mp&a&HiIgbyV*L}l z6sEav0_=k9$rGlv0iyXewgON2 whCN3iMS;fR zB^Q=zYQOn9g lCFd-9*!84cKW8rPAQ$mGjN$8Q#y= zU7X<^*>g13bH3KdQ82R;r%r}Sg)KD>F|yQ2&$3|WhkCKm-P+-L`!Nk##*FshmR~+M zON>gj_qg_muZkOvEwh!q2@X+quV)(_!`F4voRuEYtT!8G!de!rYylZxzPT8iakhDK z*%OiE=+^A<5(;>an6YP)EgqZWV9Qam( ^RH@z1i|rBd-Y_^KmwF2DA&`o48}yZ&ppok*a= z=Hd36N2`E=$G40grO!MlwJK%Sw#9YcnXAXUHiw>72Fvc}Np%aE8_e9RmD8{7?HzcD zo6MOqm-I(A-_}fx3=4d1Y+N@@B@xt<`bHq&q13LoQgu3_(}o*+RD(kJg)Ps|Nbb=i z*b|-(>% +yH$L zNhno=9Ib>nrRK|Q)Ib9mFo_}xRPAXaFPSm$dt3}fmHRKgwez)E>kGL@26lR&0u7j! zXoV7-iA0OT&aO@wC}E}toyK4?lX3Wodkx3y=&!!7%)em>?OBQ0t)v9R?tB$i9?WvD zO1*LJT=OuVT)g28LW+{3Vdqa&Fw+1b4~1fQk4DtfC*{!6)L=)Qijt^qdZxc>5L(~i zd^P_Oq{x}nIdIUbEKUftM#MUGeE#kGQ0Go|d$Wy}7dG>YLUHaf85=1n6IezAy^PN= z7$UKrv1s{{d*+fK*RzNNNJ^?nF-E=jgh?HRu?PMD(i 84-M-AQ7i2`72e zmjpM#50gQ+K4K4TF!;KIxD$J-IIyFcx9x?^k-WJiHCq%a7Hnv?jN&hYh&1LNph I5`fLxefKWxqZL0OiU}KZFo|Y$Du< z{xN>}G^la>)9t{(_zBh$ITPu{rctP{0&R;Gj=x!tcZB}{qI|lp7TmWv{w)c6$KSX_ zL^%+;n5s38#~M726&Bv`t{RE2xT9xX(&uacmv{ADuPl2`sTc-t?f2Se_%Bw(5AMIL zXqng BZ-+jJmmv zoO-+vi2pgE=j}^s*z9Z^A?N-Fz#I;B;lxCh1wIPHN{kOC|A+uUm2u=?Gr1*CeS5nX zd7jI-_kAb e}HHX+cFD(Lnx@qy=GY%itIV{8YtCz@{ULra<> z(b;ikR0jeaJ0(Q31s(45spP@he-gt|dygFG+Xx()CMfE{|JdaI12B|j&K)(r4e;}w zdh#iuvn55WU5c1&fx{A;WvN3FOVMPkbszM1tBX{i{ eTRDk}gsjn$SHMbb|(f0m0HV6L)K`)h&Bgx4y3Wrfc{AuE7l@H(H+lU!(>9MK6j~ z*`LZA?=2}dd0n1T-n(y(-l;$R3;fOt&qcqQ+p1=ynYa_0>DW!{hZ*@*JfC#O-ws<< z=Z8TNQ%n)V2^R@2>sfUH+S69|E>DXTn%Xm8zAoWW6Pw*~0GS*s;wW#Pg@3uW`ITu! z=|SX4^@m)V4$R6*B#9a;68T(hu}Va80lsqJFP|mLE1R@HjY-W3uRE*ucA&~_tw&w3 zn7!ZNR%pZ_FN?81`5fy&qL4oyCe|w;oYD7 >!v z1|jlTF@I!h42$P=qKCMN=$pj~^3{CWJJm^1C^p0_zt^&n&ZfcCN;JiK=E_Xw9y6AW zbG44Ke7J%dpzW(ytr@d5wTgJMAQ7I6)cj0Adc`WaFoQd;i&vshr7h@p^*qx 7 zs(#TT0j;!=Mk}@42Wxs=9x4lm1oD(%Jk58&zONyP)#%0934^TyHM_4ZEp$Q{rrxkQ zF)P!2B3D !V46hshKv2Q zw=x?6U112&VF}wXQO|%{L4mDN@>@L x>7Z&&A@5>h z62`<*^w=Ez4queP*`zVGqS}FTyob8ix-0LZ-_o^}*{I%$?ZTLP2$H4k8}=AH2&*P5 zqdbB->Ilg}t<~H@MVXCuV6-I85$bRWhuTPQuX1#1v4xG5jU=G%bT$2l!P0%Y`^5ZL z4jDC*r# 0MMv zP#WFf2@^$5;)GzJ&RA*opJEO5%CU|e_A6$M^*B_08d1MKU~c%iP~`)oO-g^j 5<1|gJse%xlcdEHw>ED zPiwR`6+6$|99jtD0o{3>S IaLitMbje?_s^Y;c1u(QnUmRp{!#@reZ9jL*^sv>Is7U9ZCxIb+Xog*;lC72R-_ ztkBqcI&B|YYrjy;ORU8l8d#$ombFsHUG{Y~i=(Qg+Igfnf#cAjcBHSNn*Aj40HMaw z2Xs`LV9+Sc?C3KQu d>lwSh-OY0a ?X2N%< zN`EA3E-YvIBQ!JYN+%C#uz?B=HMHiE9DSzBIjTBtwC5OV1~octS5w2qb(O;FdKC_6 zhq4<58=e+_CG<#lo&N!JHU8@D(vCM;mq LIvmM)1 zOsneW-y&K9E<@twr>gVP;aLhwq)fy2=y7XaTH8JpjARH?G8A-mqOpA0aLx|z2>sYp zjk5Et-AOJ64 DI}$V=%shU;-w*Lm ze9*Xy1{0rjiJ4kuqmK`ZkmKN_-|z45(Trshq@bNrFdEOdl;3vq5Q xayg!Tyc7r zo<&UkU_Zr9+bB_D^vU#JoH`U|#Mn-l!I90|-{;A*8m^z?=KRsUw>U%dac!cG`Px+9 zd-#%#e11I^e~8?PU?#oAE!s&Q*VRitB3UHo9C9#Nx8e2aue5|f&Bt|WEO`w{X8(64 zRwnc)0G_?xtAB8zYTA+OwB&Rr)EuKLAA*$@jy6U}zVdgxT*MVKedP FJw9~b-O>q_$eYU7uU%wS}j#{1om?hk-R zSLHVs(Tvx|aGM;4Aj*;AnuwLUw6f(V&kOGFVDW!6neUtkoj043Kiu^@@s&NE7NXyr z4*dg|FU<70zI?g#o6qH8B%KW*{S7}@T*$os!fvItZXKv)i%s^)YH=r5++Jjh8ja(4 zIFQm6o8%7{ BKTc5^-OO-cSZji_QM4yD*V+xOeQELz`W;D`qAZX^MO79&c0f9sy^ $VgrnI##WmhO^~LZ>6oVQ>MQFworoJ%gI|p!o_;J5*m$0e|r4Y3gjYHBy(P{qt zfBCz}9`Fgemt??#?j_-1;h|Bz{|er{>?MI%nAkYby(9-bE;}ce7)0FU?-mjk1_lJs zdR=XZ-A3b}@Flg;-t6;mZ49)@;$ZNl^`B;xA^v|hV|4v#KOlY0Uwrp-T>f80*3M@p zM-v_Rf083!TZ6AxzF$hn?^3hatMD({A@ruoTz1Y%70A)@+E;Odl(rl68~Ul@R`TYq z5@~QmtT57xh0}QFTmIJ?-esZW9K@20^e7G&UKjG%!e@|?JuC4fT==a`KBb{>bw0kh z$`UUQ!qB==#+rj-Zo6xC$0HvixuDF{X6bj|MIIQ0G>z`?miw7zWNczx|B;#QG-0;x zAtGf;ovUeylKN%V_!u62>k@6%J`lO8XI`Ep%{Q pbdD9TIQvmS z6?blEn&(haqLPopP;L@Vtt|kzK$(Ou1`RIX(>{#Zl8g_B@DNxsKQ>D$FJ!a4k|4tJ zH3{Xz7b@bHo-wYoV9{+7MeM;IkS2kXBz>ZhY)rWY9RwG>^Q5>}f0dPyfseFV4Mtw2 z(}2aSL5f#Wk5@pVm8&B;svG_KwkWQn6_gkHHYZJ%I+4mRSnh~Q!1%A7vR7zqy3kuY zJZjI3q{!?c9WlvFt~&d*1F?}Ds#pTi8%!}2;xbx9bcOdE;69o;i`>D(82W<#25GFU zo?rVVSIVejhha@-p-j(V&bT@GP8`b2AP~4Ogf^@Lm1&)Y5C)!pokj?GIL_Cy*rC@( zj7_Jv>HW4t>bI3TC1h9n^;&9iy|(sVy5tYTTsDf>HvI|lFq9mWg9wEV&Nh;<$al-6 zz6gR+)>*%96rsK{Cd=~kIIYmbd#V0P)w8ilrbU+K1(3T7jejN6TYR5&POLL9T+NFZ zD{zIG4{zTtdJW0kH5o@e;W+Ts5c+)0LD}8G)!vSx^D~C`ffqZI+H)R3Uu-GX*8h=a zncCfC9DYrKCvW=T6CQ6}U@AC{*=(EMNrLO+6ZZA{d7YozNW503ll;jnV$2dT-avYS zl-T8;$LU!p?J=-LxwJ$oL!TQJm-81(-yp!tYo1( =V93}@gn2nuMOdO*A&p#hZ00IES3?u>z=#gPxGWZ0To>Urntt*f_ z-^^gcMQMoIvECz{2QzVm#OS 2{^!+D)Tl;p=`o^4`pO+BZ278 l(PCZpmH0G9L~#vW7Q)$^J3HVim8O0rJUPLCTstmSz> zT+GK!9+gQx7^h?a{G6V&FCP3c+h53Pslg7hucb&js^ud0@DSP}L&5Kmhi@(w|7LqB z!NMf3riDjtDG_h*BBz7_Kb0q6CJjxp(8fR_3`Qah8TV}}qgJJ+&kH(6-EN^!B8)r^ zs*>btX^5sA3(!ZrxhoA#>7A`uFtyuI!Mu4}8d}3UTk+iiSq6}^Mt?gngt8v}hTO!d zG{m#5d~j+HY6_ALp-_+zM=Od@Ui*B1_W|M`fVZr;=;0$DZzy(opgYdvwk*QcEZj@+ z$U@=p91g|g!7h5`3m)%mD>W2%#iQLS^Q72PgvFDs#iQM!82EDOWpK6d{vA94Oz4e2 z5Dth09YGlQzi|NQ;9*m;i>sSrg4x92ARH2E8ZJToIE9T=N%Nd$!Ml>K$xUCc{wp4U zBnnG=oT5O39VJzyPXB*Y$<4ga3!ux7I{NzV-<90a)-K$;Mfk}0qt4e<^5bf&G7bu{ z_sI<#7m;y!2kvonG!n0xFk5)MLRHpXJ9DS*_##^XSU=|pl-5VB-?w $vW zv7RRlGK_&g^mDf^^+#7tma}m93K z&E8wA$~7Lk31-%v_Eh)cbkC58bQjn`r5#D$SIh} zgl98sQW3hRz2p=L$J0ld1(>R;kdHPuauf4t6eCKiGPjz>@Q5BaHp_yU&7AsyABq=6 z?PhHLuyOJ2yQkM>SD&mC&t^y0MPzE2!mvqo(?)&9vlq}&T5S0FT$M|SpplJ3 z$P5Z5qU7}5m92w}?R2N#>Vs%A!tXxFXUJGujX2jxkexE|?0Tx2*mSqW+Z8VPaY|NF zYg5h70@-nJDL)5~m8Gjj|G=!&bIpVH%{HwSKU+7r+QeJM%`5X$OQvE4_pQ54g0^0< zJ(W*x_~}aUt<24xERugxYieB_maMk@HI(m4l>PSwk%6F!dO!ss2`;Mg2UVTZ%CdB2 z8m`Y{_@i8?oMH>7Y(E%>;S>vO-O(Jf&ga;s;ZPM2hzcZ4l(wRGf`F*f0|>Ckcyf_p zgjpx>a-fPpC0JniMu8d)Tovv#Y)~*rlUq7o@ENKk$4J5MMGnODtu}LAAaC})3T^YdC+HT3X6v-C0C6*OYn&3fQRAxi)9g*+8{d!WlLO9 zE_ws|G|5fwTdCb;7p@7U&n~PtQksv>y;o8)&7 3BWRT4WQArP7~ zQWGxef@JGIfMq`Qu;e}BaxWCqTFv_TNiy|>lgaP64)^&|50Xe3R`o=3&r2tc41A%E zL`irQ?x%`CDOoE5jp5EBMv>#F0&^7BsiL=*@js!X+PHbAwQ8!|yIv&AZSMb#016V+ z3NA%FMWrvqnvV=PrO;}5-wH5+R6R6Y7tEbLQ5Lm`oHnooJ>xdD4rrsV=*~;1KD=K` zKVDG1DZKegb0bM!+_FFpQ}lyk<{oin;0EefS1eGueu~nEqWOpoY`e!*qguy)#BswD zeVP$Pjd SHr#prWx0EBQ}52GsqT9@hVn)AkJ)7qxyIK*^WJl> z#>(B}rmZ{IHuM8Q^iMc*&NupRBf~yhZ>O}oY_KkVB2~sWA{Lws#uUmm3>w#Z`wQM} zXx?(*Bf7Q|`u=PiN`;qy@E-uy@Zy2xV8xre_s9_+TtJA7vS_($S1k|vE^iOD-)6XG zkY&X4 v~>oiC6}nFOuxX4$`7xE}Pq1;wR8X>Y{h z5%QT{AtUES4s%_cKuHe6@XKK{{1YMDOe~XOF=pG^F=h&Ga`VD1y_%~qK1DRMz&jaS zRSOqSq ISa1QZc49!yI9USNCa?wt{dNPf<^DV+bj?pp-H)DY<5Ae@V;qrB6@W z*gejEEOTn(RRsopMt%EiM+Wv=B=lH6EnMIV4k!^Al)Xo&X1PR|mx6^QaspstiFqSb zzrtR&{Ay64u28B`sa2)TnEHQKX?O$O%`ie2L^v2A%D--9UXD~?{ap?VU)DpHpvM0B z%c~@{-G2qdMJY!GHgva{zNh|NS%2f`-+K4ID{TEs@6s2bB!3HWfA|}Mr8m&x7FwwL zOaCtlA`a?>YL2rf)=`g4kLPsruIa8n0L8{ltIhYNUoM)RJ}sPk>9@cB5c8QfDxDR0 z&aFWf>@gW49+~r2IR1?1tY)E)%jxZg@m-(+SRuj#O8oORI($V~kWj~WFvu8$Y1`>3 zSeRg@&XYNc-VbEJ{GrBvmAzfDS)g5@6#NiKdf_fv3Rn`u-yf3c=f;xOSV FUd;6FvaDww2mWIuQx}qZ$ zQ+%gJ#$*|C#g5B(T(Vd?iw6{=>?DTQ>XeIxfm@;*HPJ=JoLvFZ>LL%_<0j|!lgZnP zYZhxn7NH|juS >)k9HRXsV2dhHsdiC%Uu`iLFQr!!Vqj^f AQ8%tCFl4ql&H(Ds?g@uok{vK)``%GX1kj!906Z@HR5{ zl9|D=tZDEH&3(k5j@Ry9x}I)bw^)aOd7MT)zSl2 F5QRbs z;`7E_1n~BL=-N);lOB`1)Uu70xw?iDJ64D^eU&6{MFkh--tjwROCL(+aAftU1JFUy zTU__Iu%KdtepKf Lf9rapWSf<;P_*ojZ5kYLyX{c^RyeM~C8 z;<%lZ51Tteyy)uES)1`^+ixn-fSAL`9Syki1o2~@5nNkA&1^~sW^uR%z>Z_q*yOjb zifqIuqLjIC!})6XtZrf1ZSe>w4U(k_A$>k;xM2ypW=?^tbcD*4Z!2WELn;zJoMvXL z>`mBv3KqdE-pS0U3&PPcdg-ouu!4& 6id-ZTi! zDyWM(@G->*fWwoZ6EkrxCd89CC@GYRQWQ=vTV&{&4ge#8k(2vjxG-VCWFT^-)iIr5 zTF@8^Eqyh-J}Ndf>;lXNa{`OXU%7<1!PKOhP+0zGRyl#F4zmN}Q6i=c0KZaf&p8Ek z?!8iIFqH|Nw2%Q)N|_$~;#gI3U(WdP;3&vEY+zN=e$e_f8}__4{sF9fE+dcC;OMPH zR>rFS0|c;^UgCh^?7GIJQ0hZyDy0NZVtZKO&-NoFW^j%y9p!mZlU#A|IIAGY(V@ax zl6mI#_l Z28X(KR|y*Wf}>7q0J{RSyXe4_HlV;j3Gx2we$pjiFw&tzLzoU~ zJR={hyEK`I7_7-Tj8r7^JZz4dU^{9#t{h+*p&mH6iYT34zCJd`o<$5xAbTt+55P;* zQ*p@KXyWO
+AXVdssWOP_7$n9n7I~)^PWJQgGzvZkt4GW-@ z!bS+tEf_JAG>R0b>L!k@)zLVzl@trs2SicAmN0oFhDG)z%1Qai0i1=J%oqtbJdk4a zx?c=k;p&38hEExENP^Zakxq$$$^sxBq7EUb3SWx$N(JQF*!_^@gP3TqT^@hOhC};G zmz8EVm{B=R4hT~VCdFysH1wek7Xbj`ODsee*tOV}d)GlJv_orlX-(jxV1z!*fkI*a zC?dT^M#3?9{7At !?Pev{eAJMeHBHE#6=Nl+Bpz z1Uj#b{5jaO4NCUlyo~SeY9KtA&f8x@;SvFEVpzfbkU|Nt73TGs1W-k)UM(nk<3d2{ z&dQI@cCGCYi4GJdG}0UhHVBz%Z_fJJ-bzHs8CG*W6HF8KnFQ;c;Z!MOU25yQ_3rNc z8jK^Ec2E_nZ)-!jQB+!c-V7*bkffkr3w=69s@Q!Vh=I)G*}^Lw*;b2<=lhlt^CM+F zK5eSn`P|xO9P`+)q7ezgF|4?A#`#kYblmDr?)f2)qgQn(ncG3&4l%-`raL#|yPwxE z)Vr97q<11S_FG%e@@VJKIV7p!FY0Q%F>sWO^->VSn%kdvOWsd34nATZGth>bp=?=^ z`zdFU7=RB@S8>&UPqB+TVz?Su7Ht0I<$NM+AlP~9H69XSt_-RjcW=&TIVKPXDyEZ^ z_nX{50Fn-@C6Xu@Nl38v7w6 &MH z!%|_afqH6|`XYd{->+`6u!VPOsJ4*bgV_9-c}D^(6V?MN*_~LUOLA0d(odZ&?0ora z5*HOH`IEHM5g1=bnlYlE9v9ylaL0{8CMARGpFKu#!R;7ar_pm(l*(2y#AK@0+{wg6 zCZHHX%$lGtzD{9<@zK88K`r+9C?vr_fkq_St(E5}UMwOrHaPaV+*zT~+Q{_^spu!q zui}0wW>G|bX&KU$ZO)qPVx^Ddwo8un39jxP4tqTV^OWeR;c)@t0Vf)1f#KrqSEnsE zxms&nt=1NU;bP&%H%{LOi(dz;#kpe8>joFRZl(&!Vlxs}nC!BHEseKpH-eX-n;`qi zyRVbQ{=*=kV2BSK%S{@gmTKuTPGU3JWsfIEAEHx&DF&;BXP6PZ6D+RgB|2-5Z H`;>tead!xqfQ4V114(`rNM>=N 8hwS|K#bo#k7V)pZGpxCbs%3NWO@OG1xi8WwKpgG~W zBJ0WT!gH!2M!hTzkylq%9ja32di~4H-Q_=mXZO1t#E+uO;IAcA=*wO&Y7Dr1(w;|$ z%r1Qc!dpcJYg2>9;Xu?O4PbL7kT?h51WSbGtTs*>EiVvNQLmUxMsEg$Aa0;;7UkBO zwy|76Q}726N$(j1yP=PZkSrNbsVm-q&DVYjP*1Q-cV7Y PGe2wM*5NBBVcnAYXo{nTruU(HRQE2JC_xLeyZbI1xJ8I_QiLwe$j~03|?`-B&;` zG60W05H>L~*?B22FcP2*R$!I`E=ODn=cK(}d^DbcTIuPPH8mkj!QhG>QBMu(mJY&O zCOF>IpzMjh=>rq1>jutu|9>OOj$=??p3*R4Lc_AK03ZVFzaq7NZ)`BZ;_7UsF3@|L zpd>N1!v4npzOlh%fHD-cq0XkiU%meR3*&iZ%fJ0UQt_7m|1O1W`TtE6Pl!Fg2>zAQ zdw%`939YyPEB*YB3bg*eOh^AS{HVvCaA0M-=l=OZ^TGPE?Ze)$PSt&nuin-o*M6d2 zKYXr);G$-G@-a3sP@s{2z*o2Lbb~)7AFL^NNLBpz?*qOgex_<<+Muh>t@z|{y*EZz zEX;pA%PQ1@p^e_#e+z5Nk4_ip!cQ&;Jz=+j&PXC5tUc84G^AVQGa=;MvO|KvB$Xu@ zwJTJ2kMmCCO?OBSxQ+cRnDM-s^eEExB=t7 1gdPdvWrv8akS&Q%uf#DEGOOu4>1=#H(8DIJlK^e;3)FaEZ=E2BV?8XEz1kTy z31fl~JRF=lR&Ko={U7>FktqSn=8 v_uua|NM2vbx8&1pj|~IR>w sHjslo__foad%@{Tq3z`B8zq`@dFnal-t^Q7iM+6BM-_w>-PwYC@^c*40xt46D+ z3ZTGPN<( i$%LsujoGe y#d{(kFrMksue0cb T9-*Vn~iPufyzY