mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-10 01:29:49 +02:00
Merge branch 'develop' into sidv/fixTripleParsing
* develop: (59 commits) fix!(deps): fix zenuml style leakage. update @zenuml/core to ^3.0.6 to fix the style leakage. Update selectSvgElement.ts create `Group` type Add specialChars in textNoTagsToken, alphaNumToken Return Unicode Text to idStringToken definition Add underscore to unit test on special Chars Revert to old docs concerning quotations marks in string Refactor unit tests and remove repetition Correct idStringToken definition to include all individual special tokens Add unit tests for node ids with special Chars Create lychee.toml create `selectSvgElement` change `svgElem` to `SVG` in `configureSvgSize` add `configureSvgSize` in infoRenderer run docs:build remove info sandbox test case Remove replaceAll method in addLink Modify HREF token regex to contain space Add unit tests for stange node names Remove escaped quotes with backslash feature ...
This commit is contained in:
44
.github/lychee.toml
vendored
Normal file
44
.github/lychee.toml
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
############################# Display #############################
|
||||||
|
|
||||||
|
# Verbose program output
|
||||||
|
# Accepts log level: "error", "warn", "info", "debug", "trace"
|
||||||
|
verbose = "debug"
|
||||||
|
|
||||||
|
# Don't show interactive progress bar while checking links.
|
||||||
|
no_progress = true
|
||||||
|
|
||||||
|
############################# Cache ###############################
|
||||||
|
|
||||||
|
# Enable link caching. This can be helpful to avoid checking the same links on
|
||||||
|
# multiple runs.
|
||||||
|
cache = true
|
||||||
|
|
||||||
|
# Discard all cached requests older than this duration.
|
||||||
|
max_cache_age = "1d"
|
||||||
|
|
||||||
|
############################# Requests ############################
|
||||||
|
|
||||||
|
# Comma-separated list of accepted status codes for valid links.
|
||||||
|
accept = [200, 429]
|
||||||
|
|
||||||
|
############################# Exclusions ##########################
|
||||||
|
|
||||||
|
# Exclude URLs and mail addresses from checking (supports regex).
|
||||||
|
exclude = [
|
||||||
|
# Network error: Forbidden
|
||||||
|
"https://codepen.io",
|
||||||
|
|
||||||
|
# Timeout error, maybe Twitter has anti-bot defenses against GitHub's CI servers?
|
||||||
|
"https://twitter.com/mermaidjs_",
|
||||||
|
|
||||||
|
# Don't check files that are generated during the build via `pnpm docs:code`
|
||||||
|
'packages/mermaid/src/docs/config/setup/*',
|
||||||
|
|
||||||
|
# Ignore slack invite
|
||||||
|
"https://join.slack.com/"
|
||||||
|
]
|
||||||
|
|
||||||
|
# Exclude all private IPs from checking.
|
||||||
|
# Equivalent to setting `exclude_private`, `exclude_link_local`, and
|
||||||
|
# `exclude_loopback` to true.
|
||||||
|
exclude_all_private = true
|
7
.github/workflows/link-checker.yml
vendored
7
.github/workflows/link-checker.yml
vendored
@@ -20,7 +20,7 @@ on:
|
|||||||
- cron: '30 8 * * *'
|
- cron: '30 8 * * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
linkChecker:
|
link-checker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
|
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
|
||||||
@@ -39,10 +39,7 @@ jobs:
|
|||||||
uses: lycheeverse/lychee-action@v1.8.0
|
uses: lycheeverse/lychee-action@v1.8.0
|
||||||
with:
|
with:
|
||||||
args: >-
|
args: >-
|
||||||
--verbose
|
--config .github/lychee.toml
|
||||||
--no-progress
|
|
||||||
--cache
|
|
||||||
--max-cache-age 1d
|
|
||||||
packages/mermaid/src/docs/**/*.md
|
packages/mermaid/src/docs/**/*.md
|
||||||
README.md
|
README.md
|
||||||
README.zh-CN.md
|
README.zh-CN.md
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
# These links are ignored by our link checker https://github.com/lycheeverse/lychee
|
|
||||||
# The file allows you to list multiple regular expressions for exclusion (one pattern per line).
|
|
||||||
|
|
||||||
# Network error: Forbidden
|
|
||||||
https://codepen.io
|
|
||||||
|
|
||||||
# Timeout error, maybe Twitter has anti-bot defenses against GitHub's CI servers?
|
|
||||||
https://twitter.com/mermaidjs_
|
|
||||||
|
|
||||||
# Don't check files that are generated during the build via `pnpm docs:code`
|
|
||||||
packages/mermaid/src/docs/config/setup/*
|
|
||||||
|
|
||||||
# Ignore localhost
|
|
||||||
http://localhost:3333/
|
|
||||||
|
|
||||||
# Ignore slack invite
|
|
||||||
https://join.slack.com/
|
|
@@ -891,4 +891,27 @@ graph TD
|
|||||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('66: apply class called default on node called default', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
graph TD
|
||||||
|
classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff
|
||||||
|
hello --> default
|
||||||
|
`,
|
||||||
|
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('67: should be able to style default node independently', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
flowchart TD
|
||||||
|
classDef default fill:#a34
|
||||||
|
hello --> default
|
||||||
|
|
||||||
|
style default stroke:#000,stroke-width:4px
|
||||||
|
`,
|
||||||
|
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -96,7 +96,7 @@ mermaid.initialize(config);
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:666](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L666)
|
[mermaidAPI.ts:668](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L668)
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ Return the last node appended
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:307](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L307)
|
[mermaidAPI.ts:309](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L309)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -320,4 +320,4 @@ Remove any existing elements from the given document
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:357](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L357)
|
[mermaidAPI.ts:359](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L359)
|
||||||
|
@@ -608,12 +608,12 @@ It is possible to escape characters using the syntax exemplified here.
|
|||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
flowchart LR
|
flowchart LR
|
||||||
A["A double quote:#quot;"] -->B["A dec char:#9829;"]
|
A["A double quote:#quot;"] --> B["A dec char:#9829;"]
|
||||||
```
|
```
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart LR
|
||||||
A["A double quote:#quot;"] -->B["A dec char:#9829;"]
|
A["A double quote:#quot;"] --> B["A dec char:#9829;"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names.
|
Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names.
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zenuml/core": "^3.0.3"
|
"@zenuml/core": "^3.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mermaid": "workspace:^"
|
"mermaid": "workspace:^"
|
||||||
|
@@ -79,8 +79,10 @@ export type DrawDefinition = (
|
|||||||
*/
|
*/
|
||||||
export type ParseDirectiveDefinition = (statement: string, context: string, type: string) => void;
|
export type ParseDirectiveDefinition = (statement: string, context: string, type: string) => void;
|
||||||
|
|
||||||
export type HTML = d3.Selection<HTMLIFrameElement, unknown, Element, unknown>;
|
export type HTML = d3.Selection<HTMLIFrameElement, unknown, Element | null, unknown>;
|
||||||
|
|
||||||
export type SVG = d3.Selection<SVGSVGElement, unknown, Element, unknown>;
|
export type SVG = d3.Selection<SVGSVGElement, unknown, Element | null, unknown>;
|
||||||
|
|
||||||
|
export type Group = d3.Selection<SVGGElement, unknown, Element | null, unknown>;
|
||||||
|
|
||||||
export type DiagramStylesProvider = (options?: any) => string;
|
export type DiagramStylesProvider = (options?: any) => string;
|
||||||
|
@@ -49,7 +49,7 @@ describe('diagram detection', () => {
|
|||||||
"Parse error on line 2:
|
"Parse error on line 2:
|
||||||
graph TD; A-->
|
graph TD; A-->
|
||||||
--------------^
|
--------------^
|
||||||
Expecting 'AMP', 'ALPHA', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'MINUS', 'BRKT', 'DOT', 'PUNCTUATION', 'UNICODE_TEXT', 'PLUS', 'EQUALS', 'MULT', 'UNDERSCORE', got 'EOF'"
|
Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'EOF'"
|
||||||
`);
|
`);
|
||||||
await expect(getDiagramFromText('sequenceDiagram; A-->B')).rejects
|
await expect(getDiagramFromText('sequenceDiagram; A-->B')).rejects
|
||||||
.toThrowErrorMatchingInlineSnapshot(`
|
.toThrowErrorMatchingInlineSnapshot(`
|
||||||
|
@@ -6,6 +6,40 @@ setConfig({
|
|||||||
securityLevel: 'strict',
|
securityLevel: 'strict',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const keywords = [
|
||||||
|
'graph',
|
||||||
|
'flowchart',
|
||||||
|
'flowchart-elk',
|
||||||
|
'style',
|
||||||
|
'default',
|
||||||
|
'linkStyle',
|
||||||
|
'interpolate',
|
||||||
|
'classDef',
|
||||||
|
'class',
|
||||||
|
'href',
|
||||||
|
'call',
|
||||||
|
'click',
|
||||||
|
'_self',
|
||||||
|
'_blank',
|
||||||
|
'_parent',
|
||||||
|
'_top',
|
||||||
|
'end',
|
||||||
|
'subgraph',
|
||||||
|
'kitty',
|
||||||
|
];
|
||||||
|
|
||||||
|
const doubleEndedEdges = [
|
||||||
|
{ edgeStart: 'x--', edgeEnd: '--x', stroke: 'normal', type: 'double_arrow_cross' },
|
||||||
|
{ edgeStart: 'x==', edgeEnd: '==x', stroke: 'thick', type: 'double_arrow_cross' },
|
||||||
|
{ edgeStart: 'x-.', edgeEnd: '.-x', stroke: 'dotted', type: 'double_arrow_cross' },
|
||||||
|
{ edgeStart: 'o--', edgeEnd: '--o', stroke: 'normal', type: 'double_arrow_circle' },
|
||||||
|
{ edgeStart: 'o==', edgeEnd: '==o', stroke: 'thick', type: 'double_arrow_circle' },
|
||||||
|
{ edgeStart: 'o-.', edgeEnd: '.-o', stroke: 'dotted', type: 'double_arrow_circle' },
|
||||||
|
{ edgeStart: '<--', edgeEnd: '-->', stroke: 'normal', type: 'double_arrow_point' },
|
||||||
|
{ edgeStart: '<==', edgeEnd: '==>', stroke: 'thick', type: 'double_arrow_point' },
|
||||||
|
{ edgeStart: '<-.', edgeEnd: '.->', stroke: 'dotted', type: 'double_arrow_point' },
|
||||||
|
];
|
||||||
|
|
||||||
describe('[Edges] when parsing', () => {
|
describe('[Edges] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = flowDb;
|
||||||
@@ -39,211 +73,62 @@ describe('[Edges] when parsing', () => {
|
|||||||
expect(edges[0].type).toBe('arrow_circle');
|
expect(edges[0].type).toBe('arrow_circle');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('cross', function () {
|
describe('edges', function () {
|
||||||
it('should handle double edged nodes and edges', function () {
|
doubleEndedEdges.forEach((edgeType) => {
|
||||||
const res = flow.parser.parse('graph TD;\nA x--x B;');
|
it(`should handle ${edgeType.stroke} ${edgeType.type} with no text`, function () {
|
||||||
|
const res = flow.parser.parse(`graph TD;\nA ${edgeType.edgeStart}${edgeType.edgeEnd} B;`);
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
const vert = flow.parser.yy.getVertices();
|
||||||
const edges = flow.parser.yy.getEdges();
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
expect(vert['A'].id).toBe('A');
|
||||||
expect(vert['B'].id).toBe('B');
|
expect(vert['B'].id).toBe('B');
|
||||||
expect(edges.length).toBe(1);
|
expect(edges.length).toBe(1);
|
||||||
expect(edges[0].start).toBe('A');
|
expect(edges[0].start).toBe('A');
|
||||||
expect(edges[0].end).toBe('B');
|
expect(edges[0].end).toBe('B');
|
||||||
expect(edges[0].type).toBe('double_arrow_cross');
|
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||||
expect(edges[0].text).toBe('');
|
expect(edges[0].text).toBe('');
|
||||||
expect(edges[0].stroke).toBe('normal');
|
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||||
expect(edges[0].length).toBe(1);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes with text', function () {
|
it(`should handle ${edgeType.stroke} ${edgeType.type} with text`, function () {
|
||||||
const res = flow.parser.parse('graph TD;\nA x-- text --x B;');
|
const res = flow.parser.parse(
|
||||||
|
`graph TD;\nA ${edgeType.edgeStart} text ${edgeType.edgeEnd} B;`
|
||||||
|
);
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
const vert = flow.parser.yy.getVertices();
|
||||||
const edges = flow.parser.yy.getEdges();
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
expect(vert['A'].id).toBe('A');
|
||||||
expect(vert['B'].id).toBe('B');
|
expect(vert['B'].id).toBe('B');
|
||||||
expect(edges.length).toBe(1);
|
expect(edges.length).toBe(1);
|
||||||
expect(edges[0].start).toBe('A');
|
expect(edges[0].start).toBe('A');
|
||||||
expect(edges[0].end).toBe('B');
|
expect(edges[0].end).toBe('B');
|
||||||
expect(edges[0].type).toBe('double_arrow_cross');
|
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||||
expect(edges[0].text).toBe('text');
|
expect(edges[0].text).toBe('text');
|
||||||
expect(edges[0].stroke).toBe('normal');
|
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||||
expect(edges[0].length).toBe(1);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes and edges on thick arrows', function () {
|
it.each(keywords)(
|
||||||
const res = flow.parser.parse('graph TD;\nA x==x B;');
|
`should handle ${edgeType.stroke} ${edgeType.type} with %s text`,
|
||||||
|
function (keyword) {
|
||||||
|
const res = flow.parser.parse(
|
||||||
|
`graph TD;\nA ${edgeType.edgeStart} ${keyword} ${edgeType.edgeEnd} B;`
|
||||||
|
);
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
const vert = flow.parser.yy.getVertices();
|
||||||
const edges = flow.parser.yy.getEdges();
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
expect(vert['A'].id).toBe('A');
|
||||||
expect(vert['B'].id).toBe('B');
|
expect(vert['B'].id).toBe('B');
|
||||||
expect(edges.length).toBe(1);
|
expect(edges.length).toBe(1);
|
||||||
expect(edges[0].start).toBe('A');
|
expect(edges[0].start).toBe('A');
|
||||||
expect(edges[0].end).toBe('B');
|
expect(edges[0].end).toBe('B');
|
||||||
expect(edges[0].type).toBe('double_arrow_cross');
|
expect(edges[0].type).toBe(`${edgeType.type}`);
|
||||||
expect(edges[0].text).toBe('');
|
expect(edges[0].text).toBe(`${keyword}`);
|
||||||
expect(edges[0].stroke).toBe('thick');
|
expect(edges[0].stroke).toBe(`${edgeType.stroke}`);
|
||||||
expect(edges[0].length).toBe(1);
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
it('should handle double edged nodes with text on thick arrows', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA x== text ==x B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_cross');
|
|
||||||
expect(edges[0].text).toBe('text');
|
|
||||||
expect(edges[0].stroke).toBe('thick');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes and edges on dotted arrows', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA x-.-x B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_cross');
|
|
||||||
expect(edges[0].text).toBe('');
|
|
||||||
expect(edges[0].stroke).toBe('dotted');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes with text on dotted arrows', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA x-. text .-x B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_cross');
|
|
||||||
expect(edges[0].text).toBe('text');
|
|
||||||
expect(edges[0].stroke).toBe('dotted');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('circle', function () {
|
|
||||||
it('should handle double edged nodes and edges', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA o--o B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_circle');
|
|
||||||
expect(edges[0].text).toBe('');
|
|
||||||
expect(edges[0].stroke).toBe('normal');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes with text', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA o-- text --o B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_circle');
|
|
||||||
expect(edges[0].text).toBe('text');
|
|
||||||
expect(edges[0].stroke).toBe('normal');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes and edges on thick arrows', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA o==o B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_circle');
|
|
||||||
expect(edges[0].text).toBe('');
|
|
||||||
expect(edges[0].stroke).toBe('thick');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes with text on thick arrows', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA o== text ==o B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_circle');
|
|
||||||
expect(edges[0].text).toBe('text');
|
|
||||||
expect(edges[0].stroke).toBe('thick');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes and edges on dotted arrows', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA o-.-o B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_circle');
|
|
||||||
expect(edges[0].text).toBe('');
|
|
||||||
expect(edges[0].stroke).toBe('dotted');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle double edged nodes with text on dotted arrows', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;\nA o-. text .-o B;');
|
|
||||||
|
|
||||||
const vert = flow.parser.yy.getVertices();
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(vert['A'].id).toBe('A');
|
|
||||||
expect(vert['B'].id).toBe('B');
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
expect(edges[0].start).toBe('A');
|
|
||||||
expect(edges[0].end).toBe('B');
|
|
||||||
expect(edges[0].type).toBe('double_arrow_circle');
|
|
||||||
expect(edges[0].text).toBe('text');
|
|
||||||
expect(edges[0].stroke).toBe('dotted');
|
|
||||||
expect(edges[0].length).toBe(1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ A["\`The cat in **the** hat\`"]-- "\`The *bat* in the chat\`" -->B["The dog in t
|
|||||||
expect(vert['A'].labelType).toBe('markdown');
|
expect(vert['A'].labelType).toBe('markdown');
|
||||||
expect(vert['B'].id).toBe('B');
|
expect(vert['B'].id).toBe('B');
|
||||||
expect(vert['B'].text).toBe('The dog in the hog');
|
expect(vert['B'].text).toBe('The dog in the hog');
|
||||||
expect(vert['B'].labelType).toBe('text');
|
expect(vert['B'].labelType).toBe('string');
|
||||||
expect(edges.length).toBe(2);
|
expect(edges.length).toBe(2);
|
||||||
expect(edges[0].start).toBe('A');
|
expect(edges[0].start).toBe('A');
|
||||||
expect(edges[0].end).toBe('B');
|
expect(edges[0].end).toBe('B');
|
||||||
@@ -35,7 +35,7 @@ A["\`The cat in **the** hat\`"]-- "\`The *bat* in the chat\`" -->B["The dog in t
|
|||||||
expect(edges[1].end).toBe('C');
|
expect(edges[1].end).toBe('C');
|
||||||
expect(edges[1].type).toBe('arrow_point');
|
expect(edges[1].type).toBe('arrow_point');
|
||||||
expect(edges[1].text).toBe('The rat in the mat');
|
expect(edges[1].text).toBe('The rat in the mat');
|
||||||
expect(edges[1].labelType).toBe('text');
|
expect(edges[1].labelType).toBe('string');
|
||||||
});
|
});
|
||||||
it('mardown formatting in subgraphs', function () {
|
it('mardown formatting in subgraphs', function () {
|
||||||
const res = flow.parser.parse(`flowchart LR
|
const res = flow.parser.parse(`flowchart LR
|
||||||
|
@@ -6,6 +6,29 @@ setConfig({
|
|||||||
securityLevel: 'strict',
|
securityLevel: 'strict',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const keywords = [
|
||||||
|
'graph',
|
||||||
|
'flowchart',
|
||||||
|
'flowchart-elk',
|
||||||
|
'style',
|
||||||
|
'default',
|
||||||
|
'linkStyle',
|
||||||
|
'interpolate',
|
||||||
|
'classDef',
|
||||||
|
'class',
|
||||||
|
'href',
|
||||||
|
'call',
|
||||||
|
'click',
|
||||||
|
'_self',
|
||||||
|
'_blank',
|
||||||
|
'_parent',
|
||||||
|
'_top',
|
||||||
|
'end',
|
||||||
|
'subgraph',
|
||||||
|
];
|
||||||
|
|
||||||
|
const specialChars = ['#', ':', '0', '&', ',', '*', '.', '\\', 'v', '-', '/', '_'];
|
||||||
|
|
||||||
describe('[Singlenodes] when parsing', () => {
|
describe('[Singlenodes] when parsing', () => {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
flow.parser.yy = flowDb;
|
flow.parser.yy = flowDb;
|
||||||
@@ -259,4 +282,90 @@ describe('[Singlenodes] when parsing', () => {
|
|||||||
expect(edges.length).toBe(0);
|
expect(edges.length).toBe(0);
|
||||||
expect(vert['i_d'].styles.length).toBe(0);
|
expect(vert['i_d'].styles.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each(keywords)('should handle keywords between dashes "-"', function (keyword) {
|
||||||
|
const res = flow.parser.parse(`graph TD;a-${keyword}-node;`);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
expect(vert[`a-${keyword}-node`].text).toBe(`a-${keyword}-node`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(keywords)('should handle keywords between periods "."', function (keyword) {
|
||||||
|
const res = flow.parser.parse(`graph TD;a.${keyword}.node;`);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
expect(vert[`a.${keyword}.node`].text).toBe(`a.${keyword}.node`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(keywords)('should handle keywords between underscores "_"', function (keyword) {
|
||||||
|
const res = flow.parser.parse(`graph TD;a_${keyword}_node;`);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
expect(vert[`a_${keyword}_node`].text).toBe(`a_${keyword}_node`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(keywords)('should handle nodes ending in %s', function (keyword) {
|
||||||
|
const res = flow.parser.parse(`graph TD;node_${keyword};node.${keyword};node-${keyword};`);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
expect(vert[`node_${keyword}`].text).toBe(`node_${keyword}`);
|
||||||
|
expect(vert[`node.${keyword}`].text).toBe(`node.${keyword}`);
|
||||||
|
expect(vert[`node-${keyword}`].text).toBe(`node-${keyword}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const errorKeywords = [
|
||||||
|
'graph',
|
||||||
|
'flowchart',
|
||||||
|
'flowchart-elk',
|
||||||
|
'style',
|
||||||
|
'linkStyle',
|
||||||
|
'interpolate',
|
||||||
|
'classDef',
|
||||||
|
'class',
|
||||||
|
'_self',
|
||||||
|
'_blank',
|
||||||
|
'_parent',
|
||||||
|
'_top',
|
||||||
|
'end',
|
||||||
|
'subgraph',
|
||||||
|
];
|
||||||
|
it.each(errorKeywords)('should throw error at nodes beginning with %s', function (keyword) {
|
||||||
|
const str = `graph TD;${keyword}.node;${keyword}-node;${keyword}/node`;
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
|
||||||
|
expect(() => flow.parser.parse(str)).toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
const workingKeywords = ['default', 'href', 'click', 'call'];
|
||||||
|
|
||||||
|
it.each(workingKeywords)('should parse node beginning with %s', function (keyword) {
|
||||||
|
flow.parser.parse(`graph TD; ${keyword}.node;${keyword}-node;${keyword}/node;`);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
expect(vert[`${keyword}.node`].text).toBe(`${keyword}.node`);
|
||||||
|
expect(vert[`${keyword}-node`].text).toBe(`${keyword}-node`);
|
||||||
|
expect(vert[`${keyword}/node`].text).toBe(`${keyword}/node`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(specialChars)(
|
||||||
|
'should allow node ids of single special characters',
|
||||||
|
function (specialChar) {
|
||||||
|
flow.parser.parse(`graph TD; ${specialChar} --> A`);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
expect(vert[`${specialChar}`].text).toBe(`${specialChar}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each(specialChars)(
|
||||||
|
'should allow node ids with special characters at start of id',
|
||||||
|
function (specialChar) {
|
||||||
|
flow.parser.parse(`graph TD; ${specialChar}node --> A`);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
expect(vert[`${specialChar}node`].text).toBe(`${specialChar}node`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
it.each(specialChars)(
|
||||||
|
'should allow node ids with special characters at end of id',
|
||||||
|
function (specialChar) {
|
||||||
|
flow.parser.parse(`graph TD; node${specialChar} --> A`);
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
expect(vert[`node${specialChar}`].text).toBe(`node${specialChar}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
@@ -26,15 +26,6 @@ describe('[Style] when parsing', () => {
|
|||||||
expect(vert['Q'].styles[0]).toBe('background:#fff');
|
expect(vert['Q'].styles[0]).toBe('background:#fff');
|
||||||
});
|
});
|
||||||
|
|
||||||
// log.debug(flow.parser.parse('graph TD;style Q background:#fff;'));
|
|
||||||
it('should handle styles for edges', function () {
|
|
||||||
const res = flow.parser.parse('graph TD;a-->b;\nstyle #0 stroke: #f66;');
|
|
||||||
|
|
||||||
const edges = flow.parser.yy.getEdges();
|
|
||||||
|
|
||||||
expect(edges.length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle multiple styles for a vortex', function () {
|
it('should handle multiple styles for a vortex', function () {
|
||||||
const res = flow.parser.parse('graph TD;style R background:#fff,border:1px solid red;');
|
const res = flow.parser.parse('graph TD;style R background:#fff,border:1px solid red;');
|
||||||
|
|
||||||
|
@@ -305,6 +305,95 @@ describe('[Text] when parsing', () => {
|
|||||||
expect(vert['C'].type).toBe('round');
|
expect(vert['C'].type).toBe('round');
|
||||||
expect(vert['C'].text).toBe('Chimpansen hoppar');
|
expect(vert['C'].text).toBe('Chimpansen hoppar');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const keywords = [
|
||||||
|
'graph',
|
||||||
|
'flowchart',
|
||||||
|
'flowchart-elk',
|
||||||
|
'style',
|
||||||
|
'default',
|
||||||
|
'linkStyle',
|
||||||
|
'interpolate',
|
||||||
|
'classDef',
|
||||||
|
'class',
|
||||||
|
'href',
|
||||||
|
'call',
|
||||||
|
'click',
|
||||||
|
'_self',
|
||||||
|
'_blank',
|
||||||
|
'_parent',
|
||||||
|
'_top',
|
||||||
|
'end',
|
||||||
|
'subgraph',
|
||||||
|
'kitty',
|
||||||
|
];
|
||||||
|
|
||||||
|
const shapes = [
|
||||||
|
{ start: '[', end: ']', name: 'square' },
|
||||||
|
{ start: '(', end: ')', name: 'round' },
|
||||||
|
{ start: '{', end: '}', name: 'diamond' },
|
||||||
|
{ start: '(-', end: '-)', name: 'ellipse' },
|
||||||
|
{ start: '([', end: '])', name: 'stadium' },
|
||||||
|
{ start: '>', end: ']', name: 'odd' },
|
||||||
|
{ start: '[(', end: ')]', name: 'cylinder' },
|
||||||
|
{ start: '(((', end: ')))', name: 'doublecircle' },
|
||||||
|
{ start: '[/', end: '\\]', name: 'trapezoid' },
|
||||||
|
{ start: '[\\', end: '/]', name: 'inv_trapezoid' },
|
||||||
|
{ start: '[/', end: '/]', name: 'lean_right' },
|
||||||
|
{ start: '[\\', end: '\\]', name: 'lean_left' },
|
||||||
|
{ start: '[[', end: ']]', name: 'subroutine' },
|
||||||
|
{ start: '{{', end: '}}', name: 'hexagon' },
|
||||||
|
];
|
||||||
|
|
||||||
|
shapes.forEach((shape) => {
|
||||||
|
it.each(keywords)(`should handle %s keyword in ${shape.name} vertex`, function (keyword) {
|
||||||
|
const rest = flow.parser.parse(
|
||||||
|
`graph TD;A_${keyword}_node-->B${shape.start}This node has a ${keyword} as text${shape.end};`
|
||||||
|
);
|
||||||
|
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
expect(vert['B'].type).toBe(`${shape.name}`);
|
||||||
|
expect(vert['B'].text).toBe(`This node has a ${keyword} as text`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each(keywords)('should handle %s keyword in rect vertex', function (keyword) {
|
||||||
|
const rest = flow.parser.parse(
|
||||||
|
`graph TD;A_${keyword}_node-->B[|borders:lt|This node has a ${keyword} as text];`
|
||||||
|
);
|
||||||
|
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
expect(vert['B'].type).toBe('rect');
|
||||||
|
expect(vert['B'].text).toBe(`This node has a ${keyword} as text`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle edge case for odd vertex with node id ending with minus', function () {
|
||||||
|
const res = flow.parser.parse('graph TD;A_node-->odd->Vertex Text];');
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
|
||||||
|
expect(vert['odd-'].type).toBe('odd');
|
||||||
|
expect(vert['odd-'].text).toBe('Vertex Text');
|
||||||
|
});
|
||||||
|
it('should allow forward slashes in lean_right vertices', function () {
|
||||||
|
const rest = flow.parser.parse(`graph TD;A_node-->B[/This node has a / as text/];`);
|
||||||
|
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
expect(vert['B'].type).toBe('lean_right');
|
||||||
|
expect(vert['B'].text).toBe(`This node has a / as text`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow back slashes in lean_left vertices', function () {
|
||||||
|
const rest = flow.parser.parse(`graph TD;A_node-->B[\\This node has a \\ as text\\];`);
|
||||||
|
|
||||||
|
const vert = flow.parser.yy.getVertices();
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
expect(vert['B'].type).toBe('lean_left');
|
||||||
|
expect(vert['B'].text).toBe(`This node has a \\ as text`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle åäö and minus', function () {
|
it('should handle åäö and minus', function () {
|
||||||
const res = flow.parser.parse('graph TD;A-->C{Chimpansen hoppar åäö-ÅÄÖ};');
|
const res = flow.parser.parse('graph TD;A-->C{Chimpansen hoppar åäö-ÅÄÖ};');
|
||||||
|
|
||||||
@@ -484,4 +573,33 @@ describe('[Text] when parsing', () => {
|
|||||||
expect(vert['A'].text).toBe(',.?!+-*');
|
expect(vert['A'].text).toBe(',.?!+-*');
|
||||||
expect(edges[0].text).toBe(',.?!+-*');
|
expect(edges[0].text).toBe(',.?!+-*');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw error at nested set of brackets', function () {
|
||||||
|
const str = 'graph TD; A[This is a () in text];';
|
||||||
|
expect(() => flow.parser.parse(str)).toThrowError("got 'PS'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for strings and text at the same time', function () {
|
||||||
|
const str = 'graph TD;A(this node has "string" and text)-->|this link has "string" and text|C;';
|
||||||
|
|
||||||
|
expect(() => flow.parser.parse(str)).toThrowError("got 'STR'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for escaping quotes in text state', function () {
|
||||||
|
//prettier-ignore
|
||||||
|
const str = 'graph TD; A[This is a \"()\" in text];'; //eslint-disable-line no-useless-escape
|
||||||
|
|
||||||
|
expect(() => flow.parser.parse(str)).toThrowError("got 'STR'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for nested quoatation marks', function () {
|
||||||
|
const str = 'graph TD; A["This is a "()" in text"];';
|
||||||
|
|
||||||
|
expect(() => flow.parser.parse(str)).toThrowError("Expecting 'SQE'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error', function () {
|
||||||
|
const str = `graph TD; node[hello ) world] --> works`;
|
||||||
|
expect(() => flow.parser.parse(str)).toThrowError("got 'PE'");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -13,6 +13,12 @@
|
|||||||
%x acc_descr_multiline
|
%x acc_descr_multiline
|
||||||
%x dir
|
%x dir
|
||||||
%x vertex
|
%x vertex
|
||||||
|
%x text
|
||||||
|
%x ellipseText
|
||||||
|
%x trapText
|
||||||
|
%x edgeText
|
||||||
|
%x thickEdgeText
|
||||||
|
%x dottedEdgeText
|
||||||
%x click
|
%x click
|
||||||
%x href
|
%x href
|
||||||
%x callbackname
|
%x callbackname
|
||||||
@@ -23,41 +29,19 @@
|
|||||||
%x close_directive
|
%x close_directive
|
||||||
|
|
||||||
%%
|
%%
|
||||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||||
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; }
|
||||||
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
|
||||||
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';
|
||||||
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
|
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
|
||||||
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
|
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
|
||||||
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
|
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
|
||||||
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
|
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
|
||||||
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
||||||
<acc_descr_multiline>[\}] { this.popState(); }
|
<acc_descr_multiline>[\}] { this.popState(); }
|
||||||
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
||||||
// <acc_descr_multiline>.*[^\n]* { return "acc_descr_line"}
|
// <acc_descr_multiline>.*[^\n]* { return "acc_descr_line"}
|
||||||
["][`] { this.begin("md_string");}
|
|
||||||
<md_string>[^`"]+ { return "MD_STR";}
|
|
||||||
<md_string>[`]["] { this.popState();}
|
|
||||||
["] this.begin("string");
|
|
||||||
<string>["] this.popState();
|
|
||||||
<string>[^"]* return "STR";
|
|
||||||
"style" return 'STYLE';
|
|
||||||
"default" return 'DEFAULT';
|
|
||||||
"linkStyle" return 'LINKSTYLE';
|
|
||||||
"interpolate" return 'INTERPOLATE';
|
|
||||||
"classDef" return 'CLASSDEF';
|
|
||||||
"class" return 'CLASS';
|
|
||||||
|
|
||||||
/*
|
|
||||||
---interactivity command---
|
|
||||||
'href' adds a link to the specified node. 'href' can only be specified when the
|
|
||||||
line was introduced with 'click'.
|
|
||||||
'href "<link>"' attaches the specified link to the node that was specified by 'click'.
|
|
||||||
*/
|
|
||||||
"href"[\s]+["] this.begin("href");
|
|
||||||
<href>["] this.popState();
|
|
||||||
<href>[^"]* return 'HREF';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
---interactivity command---
|
---interactivity command---
|
||||||
@@ -74,88 +58,128 @@ Function arguments are optional: 'call <callbackname>()' simply executes 'callba
|
|||||||
<callbackargs>\) this.popState();
|
<callbackargs>\) this.popState();
|
||||||
<callbackargs>[^)]* return 'CALLBACKARGS';
|
<callbackargs>[^)]* return 'CALLBACKARGS';
|
||||||
|
|
||||||
|
<md_string>[^`"]+ { return "MD_STR";}
|
||||||
|
<md_string>[`]["] { this.popState();}
|
||||||
|
<*>["][`] { this.begin("md_string");}
|
||||||
|
<string>[^"]+ return "STR";
|
||||||
|
<string>["] this.popState();
|
||||||
|
<*>["] this.pushState("string");
|
||||||
|
"style" return 'STYLE';
|
||||||
|
"default" return 'DEFAULT';
|
||||||
|
"linkStyle" return 'LINKSTYLE';
|
||||||
|
"interpolate" return 'INTERPOLATE';
|
||||||
|
"classDef" return 'CLASSDEF';
|
||||||
|
"class" return 'CLASS';
|
||||||
|
|
||||||
|
/*
|
||||||
|
---interactivity command---
|
||||||
|
'href' adds a link to the specified node. 'href' can only be specified when the
|
||||||
|
line was introduced with 'click'.
|
||||||
|
'href "<link>"' attaches the specified link to the node that was specified by 'click'.
|
||||||
|
*/
|
||||||
|
"href"[\s] return 'HREF';
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
'click' is the keyword to introduce a line that contains interactivity commands.
|
'click' is the keyword to introduce a line that contains interactivity commands.
|
||||||
'click' must be followed by an existing node-id. All commands are attached to
|
'click' must be followed by an existing node-id. All commands are attached to
|
||||||
that id.
|
that id.
|
||||||
'click <id>' can be followed by href or call commands in any desired order
|
'click <id>' can be followed by href or call commands in any desired order
|
||||||
*/
|
*/
|
||||||
"click"[\s]+ this.begin("click");
|
"click"[\s]+ this.begin("click");
|
||||||
<click>[\s\n] this.popState();
|
<click>[\s\n] this.popState();
|
||||||
<click>[^\s\n]* return 'CLICK';
|
<click>[^\s\n]* return 'CLICK';
|
||||||
|
|
||||||
"flowchart-elk" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
|
"flowchart-elk" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
|
||||||
"graph" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
|
"graph" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
|
||||||
"flowchart" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
|
"flowchart" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';}
|
||||||
"subgraph" return 'subgraph';
|
"subgraph" return 'subgraph';
|
||||||
"end"\b\s* return 'end';
|
"end"\b\s* return 'end';
|
||||||
|
|
||||||
"_self" return 'LINK_TARGET';
|
"_self" return 'LINK_TARGET';
|
||||||
"_blank" return 'LINK_TARGET';
|
"_blank" return 'LINK_TARGET';
|
||||||
"_parent" return 'LINK_TARGET';
|
"_parent" return 'LINK_TARGET';
|
||||||
"_top" return 'LINK_TARGET';
|
"_top" return 'LINK_TARGET';
|
||||||
|
|
||||||
<dir>(\r?\n)*\s*\n { this.popState(); return 'NODIR'; }
|
<dir>(\r?\n)*\s*\n { this.popState(); return 'NODIR'; }
|
||||||
<dir>\s*"LR" { this.popState(); return 'DIR'; }
|
<dir>\s*"LR" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*"RL" { this.popState(); return 'DIR'; }
|
<dir>\s*"RL" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*"TB" { this.popState(); return 'DIR'; }
|
<dir>\s*"TB" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*"BT" { this.popState(); return 'DIR'; }
|
<dir>\s*"BT" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*"TD" { this.popState(); return 'DIR'; }
|
<dir>\s*"TD" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*"BR" { this.popState(); return 'DIR'; }
|
<dir>\s*"BR" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*"<" { this.popState(); return 'DIR'; }
|
<dir>\s*"<" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*">" { this.popState(); return 'DIR'; }
|
<dir>\s*">" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*"^" { this.popState(); return 'DIR'; }
|
<dir>\s*"^" { this.popState(); return 'DIR'; }
|
||||||
<dir>\s*"v" { this.popState(); return 'DIR'; }
|
<dir>\s*"v" { this.popState(); return 'DIR'; }
|
||||||
|
|
||||||
|
.*direction\s+TB[^\n]* return 'direction_tb';
|
||||||
|
.*direction\s+BT[^\n]* return 'direction_bt';
|
||||||
|
.*direction\s+RL[^\n]* return 'direction_rl';
|
||||||
|
.*direction\s+LR[^\n]* return 'direction_lr';
|
||||||
|
|
||||||
|
[0-9]+ return 'NUM';
|
||||||
|
\# return 'BRKT';
|
||||||
|
":::" return 'STYLE_SEPARATOR';
|
||||||
|
":" return 'COLON';
|
||||||
|
"&" return 'AMP';
|
||||||
|
";" return 'SEMI';
|
||||||
|
"," return 'COMMA';
|
||||||
|
"*" return 'MULT';
|
||||||
|
|
||||||
|
<INITIAL,edgeText>\s*[xo<]?\-\-+[-xo>]\s* { this.popState(); return 'LINK'; }
|
||||||
|
<INITIAL>\s*[xo<]?\-\-\s* { this.pushState("edgeText"); return 'START_LINK'; }
|
||||||
|
<edgeText>[^-]|\-(?!\-)+ return 'EDGE_TEXT';
|
||||||
|
|
||||||
|
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[=xo>]\s* { this.popState(); return 'LINK'; }
|
||||||
|
<INITIAL>\s*[xo<]?\=\=\s* { this.pushState("thickEdgeText"); return 'START_LINK'; }
|
||||||
|
<thickEdgeText>[^=]|\=(?!=) return 'EDGE_TEXT';
|
||||||
|
|
||||||
|
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-[xo>]?\s* { this.popState(); return 'LINK'; }
|
||||||
|
<INITIAL>\s*[xo<]?\-\.\s* { this.pushState("dottedEdgeText"); return 'START_LINK'; }
|
||||||
|
<dottedEdgeText>[^\.]|\.(?!-) return 'EDGE_TEXT';
|
||||||
|
|
||||||
|
|
||||||
|
<*>\s*\~\~[\~]+\s* return 'LINK';
|
||||||
|
|
||||||
|
<ellipseText>[-/\)][\)] { this.popState(); return '-)'; }
|
||||||
|
<ellipseText>[^\(\)\[\]\{\}]|-/!\)+ return "TEXT"
|
||||||
|
<*>"(-" { this.pushState("ellipseText"); return '(-'; }
|
||||||
|
|
||||||
|
<text>"])" { this.popState(); return 'STADIUMEND'; }
|
||||||
|
<*>"([" { this.pushState("text"); return 'STADIUMSTART'; }
|
||||||
|
|
||||||
|
<text>"]]" { this.popState(); return 'SUBROUTINEEND'; }
|
||||||
|
<*>"[[" { this.pushState("text"); return 'SUBROUTINESTART'; }
|
||||||
|
|
||||||
|
"[|" { return 'VERTEX_WITH_PROPS_START'; }
|
||||||
|
|
||||||
|
\> { this.pushState("text"); return 'TAGEND'; }
|
||||||
|
|
||||||
|
<text>")]" { this.popState(); return 'CYLINDEREND'; }
|
||||||
|
<*>"[(" { this.pushState("text") ;return 'CYLINDERSTART'; }
|
||||||
|
|
||||||
|
<text>")))" { this.popState(); return 'DOUBLECIRCLEEND'; }
|
||||||
|
<*>"(((" { this.pushState("text"); return 'DOUBLECIRCLESTART'; }
|
||||||
|
|
||||||
|
<trapText>[\\(?=\])][\]] { this.popState(); return 'TRAPEND'; }
|
||||||
|
<trapText>\/(?=\])\] { this.popState(); return 'INVTRAPEND'; }
|
||||||
|
<trapText>\/(?!\])|\\(?!\])|[^\\\[\]\(\)\{\}\/]+ return 'TEXT';
|
||||||
|
<*>"[/" { this.pushState("trapText"); return 'TRAPSTART'; }
|
||||||
|
|
||||||
|
<*>"[\\" { this.pushState("trapText"); return 'INVTRAPSTART'; }
|
||||||
|
|
||||||
.*direction\s+TB[^\n]* return 'direction_tb';
|
|
||||||
.*direction\s+BT[^\n]* return 'direction_bt';
|
|
||||||
.*direction\s+RL[^\n]* return 'direction_rl';
|
|
||||||
.*direction\s+LR[^\n]* return 'direction_lr';
|
|
||||||
|
|
||||||
[0-9]+ { return 'NUM';}
|
|
||||||
\# return 'BRKT';
|
|
||||||
":::" return 'STYLE_SEPARATOR';
|
|
||||||
":" return 'COLON';
|
|
||||||
"&" return 'AMP';
|
|
||||||
";" return 'SEMI';
|
|
||||||
"," return 'COMMA';
|
|
||||||
"*" return 'MULT';
|
|
||||||
\s*[xo<]?\-\-+[-xo>]\s* return 'LINK';
|
|
||||||
\s*[xo<]?\=\=+[=xo>]\s* return 'LINK';
|
|
||||||
\s*[xo<]?\-?\.+\-[xo>]?\s* return 'LINK';
|
|
||||||
\s*\~\~[\~]+\s* return 'LINK';
|
|
||||||
\s*[xo<]?\-\-\s* return 'START_LINK';
|
|
||||||
\s*[xo<]?\=\=\s* return 'START_LINK';
|
|
||||||
\s*[xo<]?\-\.\s* return 'START_LINK';
|
|
||||||
"(-" return '(-';
|
|
||||||
"-)" return '-)';
|
|
||||||
"([" return 'STADIUMSTART';
|
|
||||||
"])" return 'STADIUMEND';
|
|
||||||
"[[" return 'SUBROUTINESTART';
|
|
||||||
"]]" return 'SUBROUTINEEND';
|
|
||||||
"[|" return 'VERTEX_WITH_PROPS_START';
|
|
||||||
"[(" return 'CYLINDERSTART';
|
|
||||||
")]" return 'CYLINDEREND';
|
|
||||||
"(((" return 'DOUBLECIRCLESTART';
|
|
||||||
")))" return 'DOUBLECIRCLEEND';
|
|
||||||
\- return 'MINUS';
|
|
||||||
"." return 'DOT';
|
|
||||||
[\_] return 'UNDERSCORE';
|
|
||||||
\+ return 'PLUS';
|
|
||||||
\% return 'PCT';
|
|
||||||
"=" return 'EQUALS';
|
|
||||||
\= return 'EQUALS';
|
|
||||||
"<" return 'TAGSTART';
|
"<" return 'TAGSTART';
|
||||||
">" return 'TAGEND';
|
">" return 'TAGEND';
|
||||||
"^" return 'UP';
|
"^" return 'UP';
|
||||||
"\|" return 'SEP';
|
"\|" return 'SEP';
|
||||||
"v" return 'DOWN';
|
"v" return 'DOWN';
|
||||||
[A-Za-z]+ return 'ALPHA';
|
"*" return 'MULT';
|
||||||
"\\]" return 'TRAPEND';
|
"#" return 'BRKT';
|
||||||
"[/" return 'TRAPSTART';
|
"&" return 'AMP';
|
||||||
"/]" return 'INVTRAPEND';
|
([A-Za-z0-9!"\#$%&'*+\.`?\\_\/]|\-(?=[^\>\-\.])|=(?!=))+ return 'NODE_STRING';
|
||||||
"[\\" return 'INVTRAPSTART';
|
"-" return 'MINUS'
|
||||||
[!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION';
|
|
||||||
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
|
[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|
|
||||||
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
|
[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|
|
||||||
[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|
|
[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|
|
||||||
@@ -218,13 +242,20 @@ that id.
|
|||||||
[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|
|
[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|
|
||||||
[\uFFD2-\uFFD7\uFFDA-\uFFDC]
|
[\uFFD2-\uFFD7\uFFDA-\uFFDC]
|
||||||
return 'UNICODE_TEXT';
|
return 'UNICODE_TEXT';
|
||||||
"|" return 'PIPE';
|
|
||||||
"(" return 'PS';
|
<text>"|" { this.popState(); return 'PIPE'; }
|
||||||
")" return 'PE';
|
<*>"|" { this.pushState("text"); return 'PIPE'; }
|
||||||
"[" return 'SQS';
|
|
||||||
"]" return 'SQE';
|
<text>")" { this.popState(); return 'PE'; }
|
||||||
"{" return 'DIAMOND_START'
|
<*>"(" { this.pushState("text"); return 'PS'; }
|
||||||
"}" return 'DIAMOND_STOP'
|
|
||||||
|
<text>"]" { this.popState(); return 'SQE'; }
|
||||||
|
<*>"[" { this.pushState("text"); return 'SQS'; }
|
||||||
|
|
||||||
|
<text>(\}) { this.popState(); return 'DIAMOND_STOP' }
|
||||||
|
<*>"{" { this.pushState("text"); return 'DIAMOND_START' }
|
||||||
|
<text>[^\[\]\(\)\{\}\|\"]+ return "TEXT";
|
||||||
|
|
||||||
"\"" return 'QUOTE';
|
"\"" return 'QUOTE';
|
||||||
(\r?\n)+ return 'NEWLINE';
|
(\r?\n)+ return 'NEWLINE';
|
||||||
\s return 'SPACE';
|
\s return 'SPACE';
|
||||||
@@ -255,11 +286,11 @@ openDirective
|
|||||||
;
|
;
|
||||||
|
|
||||||
typeDirective
|
typeDirective
|
||||||
: type_directive { yy.parseDirective($1, 'type_directive'); }
|
: type_directive { yy.parseDirective($type_directive, 'type_directive'); }
|
||||||
;
|
;
|
||||||
|
|
||||||
argDirective
|
argDirective
|
||||||
: arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); }
|
: arg_directive { $arg_directive = $arg_directive.trim().replace(/'/g, '"'); yy.parseDirective($arg_directive, 'arg_directive'); }
|
||||||
;
|
;
|
||||||
|
|
||||||
closeDirective
|
closeDirective
|
||||||
@@ -275,15 +306,15 @@ document
|
|||||||
{ $$ = [];}
|
{ $$ = [];}
|
||||||
| document line
|
| document line
|
||||||
{
|
{
|
||||||
if(!Array.isArray($2) || $2.length > 0){
|
if(!Array.isArray($line) || $line.length > 0){
|
||||||
$1.push($2);
|
$document.push($line);
|
||||||
}
|
}
|
||||||
$$=$1;}
|
$$=$document;}
|
||||||
;
|
;
|
||||||
|
|
||||||
line
|
line
|
||||||
: statement
|
: statement
|
||||||
{$$=$1;}
|
{$$=$statement;}
|
||||||
| SEMI
|
| SEMI
|
||||||
| NEWLINE
|
| NEWLINE
|
||||||
| SPACE
|
| SPACE
|
||||||
@@ -296,15 +327,15 @@ graphConfig
|
|||||||
| GRAPH NODIR
|
| GRAPH NODIR
|
||||||
{ yy.setDirection('TB');$$ = 'TB';}
|
{ yy.setDirection('TB');$$ = 'TB';}
|
||||||
| GRAPH DIR FirstStmtSeperator
|
| GRAPH DIR FirstStmtSeperator
|
||||||
{ yy.setDirection($2);$$ = $2;}
|
{ yy.setDirection($DIR);$$ = $DIR;}
|
||||||
// | GRAPH SPACE TAGEND FirstStmtSeperator
|
// | GRAPH SPACE TAGEND FirstStmtSeperator
|
||||||
// { yy.setDirection("LR");$$ = $3;}
|
// { yy.setDirection("LR");$$ = $TAGEND;}
|
||||||
// | GRAPH SPACE TAGSTART FirstStmtSeperator
|
// | GRAPH SPACE TAGSTART FirstStmtSeperator
|
||||||
// { yy.setDirection("RL");$$ = $3;}
|
// { yy.setDirection("RL");$$ = $TAGSTART;}
|
||||||
// | GRAPH SPACE UP FirstStmtSeperator
|
// | GRAPH SPACE UP FirstStmtSeperator
|
||||||
// { yy.setDirection("BT");$$ = $3;}
|
// { yy.setDirection("BT");$$ = $UP;}
|
||||||
// | GRAPH SPACE DOWN FirstStmtSeperator
|
// | GRAPH SPACE DOWN FirstStmtSeperator
|
||||||
// { yy.setDirection("TB");$$ = $3;}
|
// { yy.setDirection("TB");$$ = $DOWN;}
|
||||||
;
|
;
|
||||||
|
|
||||||
ending: endToken ending
|
ending: endToken ending
|
||||||
@@ -332,7 +363,7 @@ spaceList
|
|||||||
|
|
||||||
statement
|
statement
|
||||||
: verticeStatement separator
|
: verticeStatement separator
|
||||||
{ /* console.warn('finat vs', $1.nodes); */ $$=$1.nodes}
|
{ /* console.warn('finat vs', $verticeStatement.nodes); */ $$=$verticeStatement.nodes}
|
||||||
| styleStatement separator
|
| styleStatement separator
|
||||||
{$$=[];}
|
{$$=[];}
|
||||||
| linkStyleStatement separator
|
| linkStyleStatement separator
|
||||||
@@ -343,110 +374,121 @@ statement
|
|||||||
{$$=[];}
|
{$$=[];}
|
||||||
| clickStatement separator
|
| clickStatement separator
|
||||||
{$$=[];}
|
{$$=[];}
|
||||||
| subgraph SPACE text SQS text SQE separator document end
|
| subgraph SPACE textNoTags SQS text SQE separator document end
|
||||||
{$$=yy.addSubGraph($3,$8,$5);}
|
{$$=yy.addSubGraph($textNoTags,$document,$text);}
|
||||||
| subgraph SPACE text separator document end
|
| subgraph SPACE textNoTags separator document end
|
||||||
{$$=yy.addSubGraph($3,$5,$3);}
|
{$$=yy.addSubGraph($textNoTags,$document,$textNoTags);}
|
||||||
// | subgraph SPACE text separator document end
|
// | subgraph SPACE textNoTags separator document end
|
||||||
// {$$=yy.addSubGraph($3,$5,$3);}
|
// {$$=yy.addSubGraph($textNoTags,$document,$textNoTags);}
|
||||||
| subgraph separator document end
|
| subgraph separator document end
|
||||||
{$$=yy.addSubGraph(undefined,$3,undefined);}
|
{$$=yy.addSubGraph(undefined,$document,undefined);}
|
||||||
| direction
|
| direction
|
||||||
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
|
| acc_title acc_title_value { $$=$acc_title_value.trim();yy.setAccTitle($$); }
|
||||||
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
|
| acc_descr acc_descr_value { $$=$acc_descr_value.trim();yy.setAccDescription($$); }
|
||||||
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); }
|
| acc_descr_multiline_value { $$=$acc_descr_multiline_value.trim();yy.setAccDescription($$); }
|
||||||
;
|
;
|
||||||
|
|
||||||
separator: NEWLINE | SEMI | EOF ;
|
separator: NEWLINE | SEMI | EOF ;
|
||||||
|
|
||||||
|
|
||||||
verticeStatement: verticeStatement link node
|
verticeStatement: verticeStatement link node
|
||||||
{ /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
|
{ /* console.warn('vs',$verticeStatement.stmt,$node); */ yy.addLink($verticeStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($verticeStatement.nodes) } }
|
||||||
| verticeStatement link node spaceList
|
| verticeStatement link node spaceList
|
||||||
{ /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
|
{ /* console.warn('vs',$verticeStatement.stmt,$node); */ yy.addLink($verticeStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($verticeStatement.nodes) } }
|
||||||
|node spaceList {/*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }}
|
|node spaceList {/*console.warn('noda', $node);*/ $$ = {stmt: $node, nodes:$node }}
|
||||||
|node { /*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }}
|
|node { /*console.warn('noda', $node);*/ $$ = {stmt: $node, nodes:$node }}
|
||||||
;
|
;
|
||||||
|
|
||||||
node: styledVertex
|
node: styledVertex
|
||||||
{ /* console.warn('nod', $1); */ $$ = [$1];}
|
{ /* console.warn('nod', $styledVertex); */ $$ = [$styledVertex];}
|
||||||
| node spaceList AMP spaceList styledVertex
|
| node spaceList AMP spaceList styledVertex
|
||||||
{ $$ = $1.concat($5); /* console.warn('pip', $1[0], $5, $$); */ }
|
{ $$ = $node.concat($styledVertex); /* console.warn('pip', $node[0], $styledVertex, $$); */ }
|
||||||
;
|
;
|
||||||
|
|
||||||
styledVertex: vertex
|
styledVertex: vertex
|
||||||
{ /* console.warn('nod', $1); */ $$ = $1;}
|
{ /* console.warn('nod', $vertex); */ $$ = $vertex;}
|
||||||
| vertex STYLE_SEPARATOR idString
|
| vertex STYLE_SEPARATOR idString
|
||||||
{$$ = $1;yy.setClass($1,$3)}
|
{$$ = $vertex;yy.setClass($vertex,$idString)}
|
||||||
;
|
;
|
||||||
|
|
||||||
vertex: idString SQS text SQE
|
vertex: idString SQS text SQE
|
||||||
{$$ = $1;yy.addVertex($1,$3,'square');}
|
{$$ = $idString;yy.addVertex($idString,$text,'square');}
|
||||||
| idString DOUBLECIRCLESTART text DOUBLECIRCLEEND
|
| idString DOUBLECIRCLESTART text DOUBLECIRCLEEND
|
||||||
{$$ = $1;yy.addVertex($1,$3,'doublecircle');}
|
{$$ = $idString;yy.addVertex($idString,$text,'doublecircle');}
|
||||||
| idString PS PS text PE PE
|
| idString PS PS text PE PE
|
||||||
{$$ = $1;yy.addVertex($1,$4,'circle');}
|
{$$ = $idString;yy.addVertex($idString,$text,'circle');}
|
||||||
| idString '(-' text '-)'
|
| idString '(-' text '-)'
|
||||||
{$$ = $1;yy.addVertex($1,$3,'ellipse');}
|
{$$ = $idString;yy.addVertex($idString,$text,'ellipse');}
|
||||||
| idString STADIUMSTART text STADIUMEND
|
| idString STADIUMSTART text STADIUMEND
|
||||||
{$$ = $1;yy.addVertex($1,$3,'stadium');}
|
{$$ = $idString;yy.addVertex($idString,$text,'stadium');}
|
||||||
| idString SUBROUTINESTART text SUBROUTINEEND
|
| idString SUBROUTINESTART text SUBROUTINEEND
|
||||||
{$$ = $1;yy.addVertex($1,$3,'subroutine');}
|
{$$ = $idString;yy.addVertex($idString,$text,'subroutine');}
|
||||||
| idString VERTEX_WITH_PROPS_START ALPHA COLON ALPHA PIPE text SQE
|
| idString VERTEX_WITH_PROPS_START NODE_STRING\[field] COLON NODE_STRING\[value] PIPE text SQE
|
||||||
{$$ = $1;yy.addVertex($1,$7,'rect',undefined,undefined,undefined, Object.fromEntries([[$3, $5]]));}
|
{$$ = $idString;yy.addVertex($idString,$text,'rect',undefined,undefined,undefined, Object.fromEntries([[$field, $value]]));}
|
||||||
| idString CYLINDERSTART text CYLINDEREND
|
| idString CYLINDERSTART text CYLINDEREND
|
||||||
{$$ = $1;yy.addVertex($1,$3,'cylinder');}
|
{$$ = $idString;yy.addVertex($idString,$text,'cylinder');}
|
||||||
| idString PS text PE
|
| idString PS text PE
|
||||||
{$$ = $1;yy.addVertex($1,$3,'round');}
|
{$$ = $idString;yy.addVertex($idString,$text,'round');}
|
||||||
| idString DIAMOND_START text DIAMOND_STOP
|
| idString DIAMOND_START text DIAMOND_STOP
|
||||||
{$$ = $1;yy.addVertex($1,$3,'diamond');}
|
{$$ = $idString;yy.addVertex($idString,$text,'diamond');}
|
||||||
| idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP
|
| idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP
|
||||||
{$$ = $1;yy.addVertex($1,$4,'hexagon');}
|
{$$ = $idString;yy.addVertex($idString,$text,'hexagon');}
|
||||||
| idString TAGEND text SQE
|
| idString TAGEND text SQE
|
||||||
{$$ = $1;yy.addVertex($1,$3,'odd');}
|
{$$ = $idString;yy.addVertex($idString,$text,'odd');}
|
||||||
| idString TRAPSTART text TRAPEND
|
| idString TRAPSTART text TRAPEND
|
||||||
{$$ = $1;yy.addVertex($1,$3,'trapezoid');}
|
{$$ = $idString;yy.addVertex($idString,$text,'trapezoid');}
|
||||||
| idString INVTRAPSTART text INVTRAPEND
|
| idString INVTRAPSTART text INVTRAPEND
|
||||||
{$$ = $1;yy.addVertex($1,$3,'inv_trapezoid');}
|
{$$ = $idString;yy.addVertex($idString,$text,'inv_trapezoid');}
|
||||||
| idString TRAPSTART text INVTRAPEND
|
| idString TRAPSTART text INVTRAPEND
|
||||||
{$$ = $1;yy.addVertex($1,$3,'lean_right');}
|
{$$ = $idString;yy.addVertex($idString,$text,'lean_right');}
|
||||||
| idString INVTRAPSTART text TRAPEND
|
| idString INVTRAPSTART text TRAPEND
|
||||||
{$$ = $1;yy.addVertex($1,$3,'lean_left');}
|
{$$ = $idString;yy.addVertex($idString,$text,'lean_left');}
|
||||||
| idString
|
| idString
|
||||||
{ /*console.warn('h: ', $1);*/$$ = $1;yy.addVertex($1);}
|
{ /*console.warn('h: ', $idString);*/$$ = $idString;yy.addVertex($idString);}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
link: linkStatement arrowText
|
link: linkStatement arrowText
|
||||||
{$1.text = $2;$$ = $1;}
|
{$linkStatement.text = $arrowText;$$ = $linkStatement;}
|
||||||
| linkStatement TESTSTR SPACE
|
| linkStatement TESTSTR SPACE
|
||||||
{$1.text = $2;$$ = $1;}
|
{$linkStatement.text = $TESTSTR;$$ = $linkStatement;}
|
||||||
| linkStatement arrowText SPACE
|
| linkStatement arrowText SPACE
|
||||||
{$1.text = $2;$$ = $1;}
|
{$linkStatement.text = $arrowText;$$ = $linkStatement;}
|
||||||
| linkStatement
|
| linkStatement
|
||||||
{$$ = $1;}
|
{$$ = $linkStatement;}
|
||||||
| START_LINK text LINK
|
| START_LINK edgeText LINK
|
||||||
{var inf = yy.destructLink($3, $1); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$2};}
|
{var inf = yy.destructLink($LINK, $START_LINK); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$edgeText};}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
edgeText: edgeTextToken
|
||||||
|
{$$={text:$edgeTextToken, type:'text'};}
|
||||||
|
| edgeText edgeTextToken
|
||||||
|
{$$={text:$edgeText.text+''+$edgeTextToken, type:$edgeText.type};}
|
||||||
|
|STR
|
||||||
|
{$$={text: $STR, type: 'string'};}
|
||||||
|
| MD_STR
|
||||||
|
{$$={text:$MD_STR, type:'markdown'};}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
linkStatement: LINK
|
linkStatement: LINK
|
||||||
{var inf = yy.destructLink($1);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};}
|
{var inf = yy.destructLink($LINK);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};}
|
||||||
;
|
;
|
||||||
|
|
||||||
arrowText:
|
arrowText:
|
||||||
PIPE text PIPE
|
PIPE text PIPE
|
||||||
{$$ = $2;}
|
{$$ = $text;}
|
||||||
;
|
;
|
||||||
|
|
||||||
text: textToken
|
text: textToken
|
||||||
{ $$={text:$1, type: 'text'};}
|
{ $$={text:$textToken, type: 'text'};}
|
||||||
| text textToken
|
| text textToken
|
||||||
{ $$={text:$1.text+''+$2, type: $1.type};}
|
{ $$={text:$text.text+''+$textToken, type: $text.type};}
|
||||||
| STR
|
| STR
|
||||||
{ $$={text: $1, type: 'text'};}
|
{ $$ = {text: $STR, type: 'string'};}
|
||||||
| MD_STR
|
| MD_STR
|
||||||
{ $$={text: $1, type: 'markdown'};}
|
{ $$={text: $MD_STR, type: 'markdown'};}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@@ -456,109 +498,104 @@ keywords
|
|||||||
|
|
||||||
|
|
||||||
textNoTags: textNoTagsToken
|
textNoTags: textNoTagsToken
|
||||||
{$$=$1;}
|
{$$={text:$textNoTagsToken, type: 'text'};}
|
||||||
| textNoTags textNoTagsToken
|
| textNoTags textNoTagsToken
|
||||||
{$$=$1+''+$2;}
|
{$$={text:$textNoTags.text+''+$textNoTagsToken, type: $textNoTags.type};}
|
||||||
|
| STR
|
||||||
|
{ $$={text: $STR, type: 'text'};}
|
||||||
|
| MD_STR
|
||||||
|
{ $$={text: $MD_STR, type: 'markdown'};}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
classDefStatement:CLASSDEF SPACE DEFAULT SPACE stylesOpt
|
classDefStatement:CLASSDEF SPACE idString SPACE stylesOpt
|
||||||
{$$ = $1;yy.addClass($3,$5);}
|
{$$ = $CLASSDEF;yy.addClass($idString,$stylesOpt);}
|
||||||
| CLASSDEF SPACE alphaNum SPACE stylesOpt
|
|
||||||
{$$ = $1;yy.addClass($3,$5);}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
classStatement:CLASS SPACE alphaNum SPACE alphaNum
|
classStatement:CLASS SPACE idString\[vertex] SPACE idString\[class]
|
||||||
{$$ = $1;yy.setClass($3, $5);}
|
{$$ = $CLASS;yy.setClass($vertex, $class);}
|
||||||
;
|
;
|
||||||
|
|
||||||
clickStatement
|
clickStatement
|
||||||
: CLICK CALLBACKNAME {$$ = $1;yy.setClickEvent($1, $2);}
|
: CLICK CALLBACKNAME {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME);}
|
||||||
| CLICK CALLBACKNAME SPACE STR {$$ = $1;yy.setClickEvent($1, $2);yy.setTooltip($1, $4);}
|
| CLICK CALLBACKNAME SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME);yy.setTooltip($CLICK, $STR);}
|
||||||
| CLICK CALLBACKNAME CALLBACKARGS {$$ = $1;yy.setClickEvent($1, $2, $3);}
|
| CLICK CALLBACKNAME CALLBACKARGS {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME, $CALLBACKARGS);}
|
||||||
| CLICK CALLBACKNAME CALLBACKARGS SPACE STR {$$ = $1;yy.setClickEvent($1, $2, $3);yy.setTooltip($1, $5);}
|
| CLICK CALLBACKNAME CALLBACKARGS SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME, $CALLBACKARGS);yy.setTooltip($CLICK, $STR);}
|
||||||
| CLICK HREF {$$ = $1;yy.setLink($1, $2);}
|
| CLICK HREF STR {$$ = $CLICK;yy.setLink($CLICK, $STR);}
|
||||||
| CLICK HREF SPACE STR {$$ = $1;yy.setLink($1, $2);yy.setTooltip($1, $4);}
|
| CLICK HREF STR SPACE STR {$$ = $CLICK;yy.setLink($CLICK, $STR1);yy.setTooltip($CLICK, $STR2);}
|
||||||
| CLICK HREF SPACE LINK_TARGET {$$ = $1;yy.setLink($1, $2, $4);}
|
| CLICK HREF STR SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $STR, $LINK_TARGET);}
|
||||||
| CLICK HREF SPACE STR SPACE LINK_TARGET {$$ = $1;yy.setLink($1, $2, $6);yy.setTooltip($1, $4);}
|
| CLICK HREF STR\[link] SPACE STR\[tooltip] SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $link, $LINK_TARGET);yy.setTooltip($CLICK, $tooltip);}
|
||||||
| CLICK alphaNum {$$ = $1;yy.setClickEvent($1, $2);}
|
| CLICK alphaNum {$$ = $CLICK;yy.setClickEvent($CLICK, $alphaNum);}
|
||||||
| CLICK alphaNum SPACE STR {$$ = $1;yy.setClickEvent($1, $2);yy.setTooltip($1, $4);}
|
| CLICK alphaNum SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $alphaNum);yy.setTooltip($CLICK, $STR);}
|
||||||
| CLICK STR {$$ = $1;yy.setLink($1, $2);}
|
| CLICK STR {$$ = $CLICK;yy.setLink($CLICK, $STR);}
|
||||||
| CLICK STR SPACE STR {$$ = $1;yy.setLink($1, $2);yy.setTooltip($1, $4);}
|
| CLICK STR\[link] SPACE STR\[tooltip] {$$ = $CLICK;yy.setLink($CLICK, $link);yy.setTooltip($CLICK, $tooltip);}
|
||||||
| CLICK STR SPACE LINK_TARGET {$$ = $1;yy.setLink($1, $2, $4);}
|
| CLICK STR SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $STR, $LINK_TARGET);}
|
||||||
| CLICK STR SPACE STR SPACE LINK_TARGET {$$ = $1;yy.setLink($1, $2, $6);yy.setTooltip($1, $4);}
|
| CLICK STR\[link] SPACE STR\[tooltip] SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $link, $LINK_TARGET);yy.setTooltip($CLICK, $tooltip);}
|
||||||
;
|
;
|
||||||
|
|
||||||
styleStatement:STYLE SPACE alphaNum SPACE stylesOpt
|
styleStatement:STYLE SPACE idString SPACE stylesOpt
|
||||||
{$$ = $1;yy.addVertex($3,undefined,undefined,$5);}
|
{$$ = $STYLE;yy.addVertex($idString,undefined,undefined,$stylesOpt);}
|
||||||
| STYLE SPACE HEX SPACE stylesOpt
|
|
||||||
{$$ = $1;yy.updateLink($3,$5);}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
linkStyleStatement
|
linkStyleStatement
|
||||||
: LINKSTYLE SPACE DEFAULT SPACE stylesOpt
|
: LINKSTYLE SPACE DEFAULT SPACE stylesOpt
|
||||||
{$$ = $1;yy.updateLink([$3],$5);}
|
{$$ = $LINKSTYLE;yy.updateLink([$DEFAULT],$stylesOpt);}
|
||||||
| LINKSTYLE SPACE numList SPACE stylesOpt
|
| LINKSTYLE SPACE numList SPACE stylesOpt
|
||||||
{$$ = $1;yy.updateLink($3,$5);}
|
{$$ = $LINKSTYLE;yy.updateLink($numList,$stylesOpt);}
|
||||||
| LINKSTYLE SPACE DEFAULT SPACE INTERPOLATE SPACE alphaNum SPACE stylesOpt
|
| LINKSTYLE SPACE DEFAULT SPACE INTERPOLATE SPACE alphaNum SPACE stylesOpt
|
||||||
{$$ = $1;yy.updateLinkInterpolate([$3],$7);yy.updateLink([$3],$9);}
|
{$$ = $LINKSTYLE;yy.updateLinkInterpolate([$DEFAULT],$alphaNum);yy.updateLink([$DEFAULT],$stylesOpt);}
|
||||||
| LINKSTYLE SPACE numList SPACE INTERPOLATE SPACE alphaNum SPACE stylesOpt
|
| LINKSTYLE SPACE numList SPACE INTERPOLATE SPACE alphaNum SPACE stylesOpt
|
||||||
{$$ = $1;yy.updateLinkInterpolate($3,$7);yy.updateLink($3,$9);}
|
{$$ = $LINKSTYLE;yy.updateLinkInterpolate($numList,$alphaNum);yy.updateLink($numList,$stylesOpt);}
|
||||||
| LINKSTYLE SPACE DEFAULT SPACE INTERPOLATE SPACE alphaNum
|
| LINKSTYLE SPACE DEFAULT SPACE INTERPOLATE SPACE alphaNum
|
||||||
{$$ = $1;yy.updateLinkInterpolate([$3],$7);}
|
{$$ = $LINKSTYLE;yy.updateLinkInterpolate([$DEFAULT],$alphaNum);}
|
||||||
| LINKSTYLE SPACE numList SPACE INTERPOLATE SPACE alphaNum
|
| LINKSTYLE SPACE numList SPACE INTERPOLATE SPACE alphaNum
|
||||||
{$$ = $1;yy.updateLinkInterpolate($3,$7);}
|
{$$ = $LINKSTYLE;yy.updateLinkInterpolate($numList,$alphaNum);}
|
||||||
;
|
;
|
||||||
|
|
||||||
numList: NUM
|
numList: NUM
|
||||||
{$$ = [$1]}
|
{$$ = [$NUM]}
|
||||||
| numList COMMA NUM
|
| numList COMMA NUM
|
||||||
{$1.push($3);$$ = $1;}
|
{$numList.push($NUM);$$ = $numList;}
|
||||||
;
|
;
|
||||||
|
|
||||||
stylesOpt: style
|
stylesOpt: style
|
||||||
{$$ = [$1]}
|
{$$ = [$style]}
|
||||||
| stylesOpt COMMA style
|
| stylesOpt COMMA style
|
||||||
{$1.push($3);$$ = $1;}
|
{$stylesOpt.push($style);$$ = $stylesOpt;}
|
||||||
;
|
;
|
||||||
|
|
||||||
style: styleComponent
|
style: styleComponent
|
||||||
|style styleComponent
|
|style styleComponent
|
||||||
{$$ = $1 + $2;}
|
{$$ = $style + $styleComponent;}
|
||||||
;
|
;
|
||||||
|
|
||||||
styleComponent: ALPHA | COLON | MINUS | NUM | UNIT | SPACE | HEX | BRKT | DOT | STYLE | PCT ;
|
styleComponent: NUM | NODE_STRING| COLON | UNIT | SPACE | BRKT | STYLE | PCT ;
|
||||||
|
|
||||||
/* Token lists */
|
/* Token lists */
|
||||||
|
idStringToken : NUM | NODE_STRING | DOWN | MINUS | DEFAULT | COMMA | COLON | AMP | BRKT | MULT | UNICODE_TEXT;
|
||||||
|
|
||||||
textToken : textNoTagsToken | TAGSTART | TAGEND | START_LINK | PCT | DEFAULT;
|
textToken : TEXT | TAGSTART | TAGEND | UNICODE_TEXT;
|
||||||
|
|
||||||
textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ;
|
textNoTagsToken: NUM | NODE_STRING | SPACE | MINUS | AMP | UNICODE_TEXT | COLON | MULT | BRKT | keywords | START_LINK ;
|
||||||
|
|
||||||
|
edgeTextToken : EDGE_TEXT | UNICODE_TEXT ;
|
||||||
|
|
||||||
|
alphaNumToken : NUM | UNICODE_TEXT | NODE_STRING | DIR | DOWN | MINUS | COMMA | COLON | AMP | BRKT | MULT;
|
||||||
|
|
||||||
idString
|
idString
|
||||||
:idStringToken
|
:idStringToken
|
||||||
{$$=$1}
|
{$$=$idStringToken}
|
||||||
| idString idStringToken
|
| idString idStringToken
|
||||||
{$$=$1+''+$2}
|
{$$=$idString+''+$idStringToken}
|
||||||
;
|
;
|
||||||
|
|
||||||
alphaNum
|
alphaNum
|
||||||
: alphaNumStatement
|
: alphaNumToken
|
||||||
{$$=$1;}
|
{$$=$alphaNumToken;}
|
||||||
| alphaNum alphaNumStatement
|
| alphaNum alphaNumToken
|
||||||
{$$=$1+''+$2;}
|
{$$=$alphaNum+''+$alphaNumToken;}
|
||||||
;
|
;
|
||||||
|
|
||||||
alphaNumStatement
|
|
||||||
: DIR
|
|
||||||
{$$=$1;}
|
|
||||||
| alphaNumToken
|
|
||||||
{$$=$1;}
|
|
||||||
| DOWN
|
|
||||||
{$$='v';}
|
|
||||||
| MINUS
|
|
||||||
{$$='-';}
|
|
||||||
;
|
|
||||||
|
|
||||||
direction
|
direction
|
||||||
: direction_tb
|
: direction_tb
|
||||||
@@ -571,9 +608,4 @@ direction
|
|||||||
{ $$={stmt:'dir', value:'LR'};}
|
{ $$={stmt:'dir', value:'LR'};}
|
||||||
;
|
;
|
||||||
|
|
||||||
alphaNumToken : PUNCTUATION | AMP | UNICODE_TEXT | NUM| ALPHA | COLON | COMMA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ;
|
|
||||||
|
|
||||||
idStringToken : ALPHA|UNDERSCORE |UNICODE_TEXT | NUM| COLON | COMMA | PLUS | MINUS | DOWN |EQUALS | MULT | BRKT | DOT | PUNCTUATION | AMP | DEFAULT;
|
|
||||||
|
|
||||||
graphCodeTokens: STADIUMSTART | STADIUMEND | SUBROUTINESTART | SUBROUTINEEND | VERTEX_WITH_PROPS_START | CYLINDERSTART | CYLINDEREND | TRAPSTART | TRAPEND | INVTRAPSTART | INVTRAPEND | PIPE | PS | PE | SQS | SQE | DIAMOND_START | DIAMOND_STOP | TAGSTART | TAGEND | ARROW_CROSS | ARROW_POINT | ARROW_CIRCLE | ARROW_OPEN | QUOTE | SEMI;
|
|
||||||
%%
|
%%
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { select } from 'd3';
|
|
||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
import { getConfig } from '../../config.js';
|
import { configureSvgSize } from '../../setupGraphViewbox.js';
|
||||||
import type { DrawDefinition, HTML, SVG } from '../../diagram-api/types.js';
|
import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js';
|
||||||
|
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a an info picture in the tag with id: id based on the graph definition in text.
|
* Draws a an info picture in the tag with id: id based on the graph definition in text.
|
||||||
@@ -11,40 +11,20 @@ import type { DrawDefinition, HTML, SVG } from '../../diagram-api/types.js';
|
|||||||
* @param version - MermaidJS version.
|
* @param version - MermaidJS version.
|
||||||
*/
|
*/
|
||||||
const draw: DrawDefinition = (text, id, version) => {
|
const draw: DrawDefinition = (text, id, version) => {
|
||||||
try {
|
log.debug('rendering info diagram\n' + text);
|
||||||
log.debug('rendering info diagram\n' + text);
|
|
||||||
|
|
||||||
const { securityLevel } = getConfig();
|
const svg: SVG = selectSvgElement(id);
|
||||||
// handle root and document for when rendering in sandbox mode
|
configureSvgSize(svg, 100, 400, true);
|
||||||
let sandboxElement: HTML | undefined;
|
|
||||||
let document: Document | null | undefined;
|
|
||||||
if (securityLevel === 'sandbox') {
|
|
||||||
sandboxElement = select('#i' + id);
|
|
||||||
document = sandboxElement.nodes()[0].contentDocument;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-ignore - figure out how to assign HTML to document type
|
const group: Group = svg.append('g');
|
||||||
const root: HTML =
|
group
|
||||||
sandboxElement !== undefined && document !== undefined && document !== null
|
.append('text')
|
||||||
? select(document)
|
.attr('x', 100)
|
||||||
: select('body');
|
.attr('y', 40)
|
||||||
|
.attr('class', 'version')
|
||||||
const svg: SVG = root.select('#' + id);
|
.attr('font-size', 32)
|
||||||
svg.attr('height', 100);
|
.style('text-anchor', 'middle')
|
||||||
svg.attr('width', 400);
|
.text(`v${version}`);
|
||||||
|
|
||||||
const g = svg.append('g');
|
|
||||||
|
|
||||||
g.append('text') // text label for the x axis
|
|
||||||
.attr('x', 100)
|
|
||||||
.attr('y', 40)
|
|
||||||
.attr('class', 'version')
|
|
||||||
.attr('font-size', '32px')
|
|
||||||
.style('text-anchor', 'middle')
|
|
||||||
.text('v ' + version);
|
|
||||||
} catch (e) {
|
|
||||||
log.error('error while rendering info diagram', e);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const renderer = { draw };
|
export const renderer = { draw };
|
||||||
|
@@ -390,7 +390,7 @@ It is possible to escape characters using the syntax exemplified here.
|
|||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
flowchart LR
|
flowchart LR
|
||||||
A["A double quote:#quot;"] -->B["A dec char:#9829;"]
|
A["A double quote:#quot;"] --> B["A dec char:#9829;"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names.
|
Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names.
|
||||||
|
@@ -284,7 +284,9 @@ export const cleanUpSvgCode = (
|
|||||||
* TODO replace btoa(). Replace with buf.toString('base64')?
|
* TODO replace btoa(). Replace with buf.toString('base64')?
|
||||||
*/
|
*/
|
||||||
export const putIntoIFrame = (svgCode = '', svgElement?: D3Element): string => {
|
export const putIntoIFrame = (svgCode = '', svgElement?: D3Element): string => {
|
||||||
const height = svgElement ? svgElement.viewBox.baseVal.height + 'px' : IFRAME_HEIGHT;
|
const height = svgElement?.viewBox?.baseVal?.height
|
||||||
|
? svgElement.viewBox.baseVal.height + 'px'
|
||||||
|
: IFRAME_HEIGHT;
|
||||||
const base64encodedSrc = btoa('<body style="' + IFRAME_BODY_STYLE + '">' + svgCode + '</body>');
|
const base64encodedSrc = btoa('<body style="' + IFRAME_BODY_STYLE + '">' + svgCode + '</body>');
|
||||||
return `<iframe style="width:${IFRAME_WIDTH};height:${height};${IFRAME_STYLES}" src="data:text/html;base64,${base64encodedSrc}" sandbox="${IFRAME_SANDBOX_OPTS}">
|
return `<iframe style="width:${IFRAME_WIDTH};height:${height};${IFRAME_STYLES}" src="data:text/html;base64,${base64encodedSrc}" sandbox="${IFRAME_SANDBOX_OPTS}">
|
||||||
${IFRAME_NOT_SUPPORTED_MSG}
|
${IFRAME_NOT_SUPPORTED_MSG}
|
||||||
|
22
packages/mermaid/src/rendering-util/selectSvgElement.ts
Normal file
22
packages/mermaid/src/rendering-util/selectSvgElement.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { select } from 'd3';
|
||||||
|
import { getConfig } from '../config.js';
|
||||||
|
import type { HTML, SVG } from '../diagram-api/types.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the SVG element using {@link id}.
|
||||||
|
*
|
||||||
|
* @param id - The diagram ID.
|
||||||
|
* @returns The selected {@link SVG} element using {@link id}.
|
||||||
|
*/
|
||||||
|
export const selectSvgElement = (id: string): SVG => {
|
||||||
|
const { securityLevel } = getConfig();
|
||||||
|
// handle root and document for when rendering in sandbox mode
|
||||||
|
let root: HTML = select('body');
|
||||||
|
if (securityLevel === 'sandbox') {
|
||||||
|
const sandboxElement: HTML = select(`#i${id}`);
|
||||||
|
const doc: Document = sandboxElement.node()?.contentDocument ?? document;
|
||||||
|
root = select(doc.body as HTMLIFrameElement);
|
||||||
|
}
|
||||||
|
const svg: SVG = root.select(`#${id}`);
|
||||||
|
return svg;
|
||||||
|
};
|
@@ -1,4 +1,5 @@
|
|||||||
import { log } from './logger.js';
|
import { log } from './logger.js';
|
||||||
|
import { SVG } from './diagram-api/types.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies d3 attributes
|
* Applies d3 attributes
|
||||||
@@ -35,7 +36,7 @@ export const calculateSvgSizeAttrs = function (height, width, useMaxWidth) {
|
|||||||
/**
|
/**
|
||||||
* Applies attributes from `calculateSvgSizeAttrs`
|
* Applies attributes from `calculateSvgSizeAttrs`
|
||||||
*
|
*
|
||||||
* @param {SVGSVGElement} svgElem The SVG Element to configure
|
* @param {SVG} svgElem The SVG Element to configure
|
||||||
* @param {number} height The height of the SVG
|
* @param {number} height The height of the SVG
|
||||||
* @param {number} width The width of the SVG
|
* @param {number} width The width of the SVG
|
||||||
* @param {boolean} useMaxWidth Whether or not to use max-width and set width to 100%
|
* @param {boolean} useMaxWidth Whether or not to use max-width and set width to 100%
|
||||||
|
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -413,8 +413,8 @@ importers:
|
|||||||
packages/mermaid-zenuml:
|
packages/mermaid-zenuml:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@zenuml/core':
|
'@zenuml/core':
|
||||||
specifier: ^3.0.3
|
specifier: ^3.0.6
|
||||||
version: 3.0.3(ts-node@10.9.1)
|
version: 3.0.6(ts-node@10.9.1)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
mermaid:
|
mermaid:
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@@ -5738,14 +5738,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
|
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@zenuml/core@3.0.3(ts-node@10.9.1):
|
/@zenuml/core@3.0.6(ts-node@10.9.1):
|
||||||
resolution: {integrity: sha512-Wp6yF5iERvGXrR3z/mNhQYP2uI54Bd7RQ2ZwA26Lca+tufj4X8pfqGVSORLqbUl4wjjdcwHc2RNT8AU+cz2NCg==}
|
resolution: {integrity: sha512-azEBVrl+ClCPhII92TbzBUFcWhIjlOPdEHVzF6eZXs5Oy4JlrfldS5pAZBHCFL4riOBsjZ5sHHmQLQg9V07T4Q==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/assert': 1.5.6
|
'@types/assert': 1.5.6
|
||||||
'@types/ramda': 0.28.25
|
'@types/ramda': 0.28.25
|
||||||
'@vue/compat': 3.3.4(vue@3.3.4)
|
'@vue/compat': 3.3.4(vue@3.3.4)
|
||||||
antlr4: 4.13.0
|
antlr4: 4.11.0
|
||||||
color-string: 1.9.1
|
color-string: 1.9.1
|
||||||
dom-to-image-more: 2.16.0
|
dom-to-image-more: 2.16.0
|
||||||
file-saver: 2.0.5
|
file-saver: 2.0.5
|
||||||
@@ -6026,9 +6026,9 @@ packages:
|
|||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/antlr4@4.13.0:
|
/antlr4@4.11.0:
|
||||||
resolution: {integrity: sha512-zooUbt+UscjnWyOrsuY/tVFL4rwrAGwOivpQmvmUDE22hy/lUA467Rc1rcixyRwcRUIXFYBwv7+dClDSHdmmew==}
|
resolution: {integrity: sha512-GUGlpE2JUjAN+G8G5vY+nOoeyNhHsXoIJwP1XF1oRw89vifA1K46T6SEkwLwr7drihN7I/lf0DIjKc4OZvBX8w==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=14'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/any-promise@1.3.0:
|
/any-promise@1.3.0:
|
||||||
|
Reference in New Issue
Block a user