mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
Merge pull request #4751 from Yokozuna59/add-pie-langium-parser
feat: add `pie` langium parser
This commit is contained in:
commit
d11bfaa6c4
9
.build/langium-cli.d.ts
vendored
9
.build/langium-cli.d.ts
vendored
@ -1,9 +0,0 @@
|
|||||||
declare module 'langium-cli' {
|
|
||||||
export interface GenerateOptions {
|
|
||||||
file?: string;
|
|
||||||
mode?: 'development' | 'production';
|
|
||||||
watch?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generate(options: GenerateOptions): Promise<boolean>;
|
|
||||||
}
|
|
@ -246,18 +246,18 @@ In this example, the `mermaidAPI` is being called through the `CDN`:
|
|||||||
<body>
|
<body>
|
||||||
Here is one mermaid diagram:
|
Here is one mermaid diagram:
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
graph TD
|
graph TD
|
||||||
A[Client] --> B[Load Balancer]
|
A[Client] --> B[Load Balancer]
|
||||||
B --> C[Server1]
|
B --> C[Server1]
|
||||||
B --> D[Server2]
|
B --> D[Server2]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
And here is another:
|
And here is another:
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
graph TD
|
graph TD
|
||||||
A[Client] -->|tcp_123| B
|
A[Client] -->|tcp_123| B
|
||||||
B(Load Balancer)
|
B(Load Balancer)
|
||||||
B -->|tcp_456| C[Server1]
|
B -->|tcp_456| C[Server1]
|
||||||
B -->|tcp_456| D[Server2]
|
B -->|tcp_456| D[Server2]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -278,15 +278,15 @@ In this example, `mermaid.js` is referenced in `src` as a separate JavaScript fi
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
graph LR
|
graph LR
|
||||||
A --- B
|
A --- B
|
||||||
B-->C[fa:fa-ban forbidden]
|
B-->C[fa:fa-ban forbidden]
|
||||||
B-->D(fa:fa-spinner);
|
B-->D(fa:fa-spinner);
|
||||||
</pre>
|
</pre>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
graph TD
|
graph TD
|
||||||
A[Client] --> B[Load Balancer]
|
A[Client] --> B[Load Balancer]
|
||||||
B --> C[Server1]
|
B --> C[Server1]
|
||||||
B --> D[Server2]
|
B --> D[Server2]
|
||||||
</pre>
|
</pre>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
base = ""
|
base = ""
|
||||||
|
|
||||||
# Directory that contains the deploy-ready HTML files and
|
# Directory that contains the deploy-ready HTML files and
|
||||||
# assets generated by the build. This is an absolute path relative
|
# assets generated by the build. This is an absolute path relative
|
||||||
# to the base directory, which is the root by default (/).
|
# to the base directory, which is the root by default (/).
|
||||||
# This sample publishes the directory located at the absolute
|
# This sample publishes the directory located at the absolute
|
||||||
# path "root/project/build-output"
|
# path "root/project/build-output"
|
||||||
|
|
||||||
publish = "mermaid-live-editor/docs"
|
publish = "mermaid-live-editor/docs"
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
/** mermaid
|
|
||||||
* https://knsv.github.io/mermaid
|
|
||||||
* (c) 2015 Knut Sveidqvist
|
|
||||||
* MIT license.
|
|
||||||
*/
|
|
||||||
%lex
|
|
||||||
%options case-insensitive
|
|
||||||
|
|
||||||
%x string
|
|
||||||
%x title
|
|
||||||
%x acc_title
|
|
||||||
%x acc_descr
|
|
||||||
%x acc_descr_multiline
|
|
||||||
%%
|
|
||||||
\%\%(?!\{)[^\n]* /* skip comments */
|
|
||||||
[^\}]\%\%[^\n]* /* skip comments */{ /*console.log('');*/ }
|
|
||||||
[\n\r]+ return 'NEWLINE';
|
|
||||||
\%\%[^\n]* /* do nothing */
|
|
||||||
[\s]+ /* ignore */
|
|
||||||
title { this.begin("title");return 'title'; }
|
|
||||||
<title>(?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; }
|
|
||||||
|
|
||||||
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
|
|
||||||
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
|
|
||||||
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
|
|
||||||
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
|
|
||||||
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
|
||||||
<acc_descr_multiline>[\}] { this.popState(); }
|
|
||||||
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
|
||||||
["] { this.begin("string"); }
|
|
||||||
<string>["] { this.popState(); }
|
|
||||||
<string>[^"]* { return "txt"; }
|
|
||||||
"pie" return 'PIE';
|
|
||||||
"showData" return 'showData';
|
|
||||||
":"[\s]*[\d]+(?:\.[\d]+)? return "value";
|
|
||||||
<<EOF>> return 'EOF';
|
|
||||||
|
|
||||||
/lex
|
|
||||||
|
|
||||||
%start start
|
|
||||||
|
|
||||||
%% /* language grammar */
|
|
||||||
|
|
||||||
start
|
|
||||||
: eol start
|
|
||||||
| PIE document
|
|
||||||
| PIE showData document {yy.setShowData(true);}
|
|
||||||
;
|
|
||||||
|
|
||||||
document
|
|
||||||
: /* empty */
|
|
||||||
| document line
|
|
||||||
;
|
|
||||||
|
|
||||||
line
|
|
||||||
: statement eol { $$ = $1 }
|
|
||||||
;
|
|
||||||
|
|
||||||
statement
|
|
||||||
:
|
|
||||||
| txt value { yy.addSection($1,yy.cleanupValue($2)); }
|
|
||||||
| title title_value { $$=$2.trim();yy.setDiagramTitle($$); }
|
|
||||||
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
|
|
||||||
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
|
|
||||||
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } | section {yy.addSection($1.substr(8));$$=$1.substr(8);}
|
|
||||||
;
|
|
||||||
|
|
||||||
eol
|
|
||||||
: NEWLINE
|
|
||||||
| ';'
|
|
||||||
| EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
%%
|
|
@ -1,5 +1,4 @@
|
|||||||
// @ts-ignore: JISON doesn't support types
|
import { parser } from './pieParser.js';
|
||||||
import { parser } from './parser/pie.jison';
|
|
||||||
import { DEFAULT_PIE_DB, db } from './pieDb.js';
|
import { DEFAULT_PIE_DB, db } from './pieDb.js';
|
||||||
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
import { setConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
|
|
||||||
@ -8,17 +7,11 @@ setConfig({
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('pie', () => {
|
describe('pie', () => {
|
||||||
beforeAll(() => {
|
beforeEach(() => db.clear());
|
||||||
parser.yy = db;
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
parser.yy.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('parse', () => {
|
describe('parse', () => {
|
||||||
it('should handle very simple pie', () => {
|
it('should handle very simple pie', async () => {
|
||||||
parser.parse(`pie
|
await parser.parse(`pie
|
||||||
"ash": 100
|
"ash": 100
|
||||||
`);
|
`);
|
||||||
|
|
||||||
@ -26,8 +19,8 @@ describe('pie', () => {
|
|||||||
expect(sections['ash']).toBe(100);
|
expect(sections['ash']).toBe(100);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie', () => {
|
it('should handle simple pie', async () => {
|
||||||
parser.parse(`pie
|
await parser.parse(`pie
|
||||||
"ash" : 60
|
"ash" : 60
|
||||||
"bat" : 40
|
"bat" : 40
|
||||||
`);
|
`);
|
||||||
@ -37,8 +30,8 @@ describe('pie', () => {
|
|||||||
expect(sections['bat']).toBe(40);
|
expect(sections['bat']).toBe(40);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie with showData', () => {
|
it('should handle simple pie with showData', async () => {
|
||||||
parser.parse(`pie showData
|
await parser.parse(`pie showData
|
||||||
"ash" : 60
|
"ash" : 60
|
||||||
"bat" : 40
|
"bat" : 40
|
||||||
`);
|
`);
|
||||||
@ -50,8 +43,8 @@ describe('pie', () => {
|
|||||||
expect(sections['bat']).toBe(40);
|
expect(sections['bat']).toBe(40);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie with comments', () => {
|
it('should handle simple pie with comments', async () => {
|
||||||
parser.parse(`pie
|
await parser.parse(`pie
|
||||||
%% comments
|
%% comments
|
||||||
"ash" : 60
|
"ash" : 60
|
||||||
"bat" : 40
|
"bat" : 40
|
||||||
@ -62,8 +55,8 @@ describe('pie', () => {
|
|||||||
expect(sections['bat']).toBe(40);
|
expect(sections['bat']).toBe(40);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie with a title', () => {
|
it('should handle simple pie with a title', async () => {
|
||||||
parser.parse(`pie title a 60/40 pie
|
await parser.parse(`pie title a 60/40 pie
|
||||||
"ash" : 60
|
"ash" : 60
|
||||||
"bat" : 40
|
"bat" : 40
|
||||||
`);
|
`);
|
||||||
@ -75,8 +68,8 @@ describe('pie', () => {
|
|||||||
expect(sections['bat']).toBe(40);
|
expect(sections['bat']).toBe(40);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie with an acc title (accTitle)', () => {
|
it('should handle simple pie with an acc title (accTitle)', async () => {
|
||||||
parser.parse(`pie title a neat chart
|
await parser.parse(`pie title a neat chart
|
||||||
accTitle: a neat acc title
|
accTitle: a neat acc title
|
||||||
"ash" : 60
|
"ash" : 60
|
||||||
"bat" : 40
|
"bat" : 40
|
||||||
@ -91,8 +84,8 @@ describe('pie', () => {
|
|||||||
expect(sections['bat']).toBe(40);
|
expect(sections['bat']).toBe(40);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie with an acc description (accDescr)', () => {
|
it('should handle simple pie with an acc description (accDescr)', async () => {
|
||||||
parser.parse(`pie title a neat chart
|
await parser.parse(`pie title a neat chart
|
||||||
accDescr: a neat description
|
accDescr: a neat description
|
||||||
"ash" : 60
|
"ash" : 60
|
||||||
"bat" : 40
|
"bat" : 40
|
||||||
@ -107,8 +100,8 @@ describe('pie', () => {
|
|||||||
expect(sections['bat']).toBe(40);
|
expect(sections['bat']).toBe(40);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie with a multiline acc description (accDescr)', () => {
|
it('should handle simple pie with a multiline acc description (accDescr)', async () => {
|
||||||
parser.parse(`pie title a neat chart
|
await parser.parse(`pie title a neat chart
|
||||||
accDescr {
|
accDescr {
|
||||||
a neat description
|
a neat description
|
||||||
on multiple lines
|
on multiple lines
|
||||||
@ -126,8 +119,8 @@ describe('pie', () => {
|
|||||||
expect(sections['bat']).toBe(40);
|
expect(sections['bat']).toBe(40);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie with positive decimal', () => {
|
it('should handle simple pie with positive decimal', async () => {
|
||||||
parser.parse(`pie
|
await parser.parse(`pie
|
||||||
"ash" : 60.67
|
"ash" : 60.67
|
||||||
"bat" : 40
|
"bat" : 40
|
||||||
`);
|
`);
|
||||||
@ -138,12 +131,12 @@ describe('pie', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle simple pie with negative decimal', () => {
|
it('should handle simple pie with negative decimal', () => {
|
||||||
expect(() => {
|
expect(async () => {
|
||||||
parser.parse(`pie
|
await parser.parse(`pie
|
||||||
"ash" : -60.67
|
"ash" : -60.67
|
||||||
"bat" : 40.12
|
"bat" : 40.12
|
||||||
`);
|
`);
|
||||||
}).toThrowError();
|
}).rejects.toThrowError();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
import { getConfig as commonGetConfig } from '../../diagram-api/diagramAPI.js';
|
|
||||||
import { sanitizeText } from '../common/common.js';
|
|
||||||
import {
|
import {
|
||||||
setAccTitle,
|
setAccTitle,
|
||||||
getAccTitle,
|
getAccTitle,
|
||||||
@ -10,7 +8,7 @@ import {
|
|||||||
setAccDescription,
|
setAccDescription,
|
||||||
clear as commonClear,
|
clear as commonClear,
|
||||||
} from '../common/commonDb.js';
|
} from '../common/commonDb.js';
|
||||||
import type { PieFields, PieDB, Sections } from './pieTypes.js';
|
import type { PieFields, PieDB, Sections, D3Section } from './pieTypes.js';
|
||||||
import type { RequiredDeep } from 'type-fest';
|
import type { RequiredDeep } from 'type-fest';
|
||||||
import type { PieDiagramConfig } from '../../config.type.js';
|
import type { PieDiagramConfig } from '../../config.type.js';
|
||||||
import DEFAULT_CONFIG from '../../defaultConfig.js';
|
import DEFAULT_CONFIG from '../../defaultConfig.js';
|
||||||
@ -35,8 +33,7 @@ const clear = (): void => {
|
|||||||
commonClear();
|
commonClear();
|
||||||
};
|
};
|
||||||
|
|
||||||
const addSection = (label: string, value: number): void => {
|
const addSection = ({ label, value }: D3Section): void => {
|
||||||
label = sanitizeText(label, commonGetConfig());
|
|
||||||
if (sections[label] === undefined) {
|
if (sections[label] === undefined) {
|
||||||
sections[label] = value;
|
sections[label] = value;
|
||||||
log.debug(`added new section: ${label}, with value: ${value}`);
|
log.debug(`added new section: ${label}, with value: ${value}`);
|
||||||
@ -45,13 +42,6 @@ const addSection = (label: string, value: number): void => {
|
|||||||
|
|
||||||
const getSections = (): Sections => sections;
|
const getSections = (): Sections => sections;
|
||||||
|
|
||||||
const cleanupValue = (value: string): number => {
|
|
||||||
if (value.substring(0, 1) === ':') {
|
|
||||||
value = value.substring(1).trim();
|
|
||||||
}
|
|
||||||
return Number(value.trim());
|
|
||||||
};
|
|
||||||
|
|
||||||
const setShowData = (toggle: boolean): void => {
|
const setShowData = (toggle: boolean): void => {
|
||||||
showData = toggle;
|
showData = toggle;
|
||||||
};
|
};
|
||||||
@ -71,7 +61,6 @@ export const db: PieDB = {
|
|||||||
|
|
||||||
addSection,
|
addSection,
|
||||||
getSections,
|
getSections,
|
||||||
cleanupValue,
|
|
||||||
setShowData,
|
setShowData,
|
||||||
getShowData,
|
getShowData,
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
||||||
// @ts-ignore: JISON doesn't support types
|
import { parser } from './pieParser.js';
|
||||||
import parser from './parser/pie.jison';
|
|
||||||
import { db } from './pieDb.js';
|
import { db } from './pieDb.js';
|
||||||
import styles from './pieStyles.js';
|
import styles from './pieStyles.js';
|
||||||
import { renderer } from './pieRenderer.js';
|
import { renderer } from './pieRenderer.js';
|
||||||
|
21
packages/mermaid/src/diagrams/pie/pieParser.ts
Normal file
21
packages/mermaid/src/diagrams/pie/pieParser.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import type { Pie } from '@mermaid-js/parser';
|
||||||
|
import { parse } from '@mermaid-js/parser';
|
||||||
|
import { log } from '../../logger.js';
|
||||||
|
import type { ParserDefinition } from '../../diagram-api/types.js';
|
||||||
|
import { populateCommonDb } from '../common/populateCommonDb.js';
|
||||||
|
import type { PieDB } from './pieTypes.js';
|
||||||
|
import { db } from './pieDb.js';
|
||||||
|
|
||||||
|
const populateDb = (ast: Pie, db: PieDB) => {
|
||||||
|
populateCommonDb(ast, db);
|
||||||
|
db.setShowData(ast.showData);
|
||||||
|
ast.sections.map(db.addSection);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const parser: ParserDefinition = {
|
||||||
|
parse: async (input: string): Promise<void> => {
|
||||||
|
const ast: Pie = await parse('pie', input);
|
||||||
|
log.debug(ast);
|
||||||
|
populateDb(ast, db);
|
||||||
|
},
|
||||||
|
};
|
@ -5,24 +5,24 @@ import { configureSvgSize } from '../../setupGraphViewbox.js';
|
|||||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
import { cleanAndMerge, parseFontSize } from '../../utils.js';
|
import { cleanAndMerge, parseFontSize } from '../../utils.js';
|
||||||
import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js';
|
import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js';
|
||||||
import type { D3Sections, PieDB, Sections } from './pieTypes.js';
|
import type { D3Section, PieDB, Sections } from './pieTypes.js';
|
||||||
import type { MermaidConfig, PieDiagramConfig } from '../../config.type.js';
|
import type { MermaidConfig, PieDiagramConfig } from '../../config.type.js';
|
||||||
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
|
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
|
||||||
|
|
||||||
const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Sections>[] => {
|
const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Section>[] => {
|
||||||
// Compute the position of each group on the pie:
|
// Compute the position of each group on the pie:
|
||||||
const pieData: D3Sections[] = Object.entries(sections)
|
const pieData: D3Section[] = Object.entries(sections)
|
||||||
.map((element: [string, number]): D3Sections => {
|
.map((element: [string, number]): D3Section => {
|
||||||
return {
|
return {
|
||||||
label: element[0],
|
label: element[0],
|
||||||
value: element[1],
|
value: element[1],
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort((a: D3Sections, b: D3Sections): number => {
|
.sort((a: D3Section, b: D3Section): number => {
|
||||||
return b.value - a.value;
|
return b.value - a.value;
|
||||||
});
|
});
|
||||||
const pie: d3.Pie<unknown, D3Sections> = d3pie<D3Sections>().value(
|
const pie: d3.Pie<unknown, D3Section> = d3pie<D3Section>().value(
|
||||||
(d3Section: D3Sections): number => d3Section.value
|
(d3Section: D3Section): number => d3Section.value
|
||||||
);
|
);
|
||||||
return pie(pieData);
|
return pie(pieData);
|
||||||
};
|
};
|
||||||
@ -47,7 +47,6 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
|||||||
const pieWidth: number = height;
|
const pieWidth: number = height;
|
||||||
const svg: SVG = selectSvgElement(id);
|
const svg: SVG = selectSvgElement(id);
|
||||||
const group: Group = svg.append('g');
|
const group: Group = svg.append('g');
|
||||||
const sections: Sections = db.getSections();
|
|
||||||
group.attr('transform', 'translate(' + pieWidth / 2 + ',' + height / 2 + ')');
|
group.attr('transform', 'translate(' + pieWidth / 2 + ',' + height / 2 + ')');
|
||||||
|
|
||||||
const { themeVariables } = globalConfig;
|
const { themeVariables } = globalConfig;
|
||||||
@ -57,13 +56,11 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
|||||||
const textPosition: number = pieConfig.textPosition;
|
const textPosition: number = pieConfig.textPosition;
|
||||||
const radius: number = Math.min(pieWidth, height) / 2 - MARGIN;
|
const radius: number = Math.min(pieWidth, height) / 2 - MARGIN;
|
||||||
// Shape helper to build arcs:
|
// Shape helper to build arcs:
|
||||||
const arcGenerator: d3.Arc<unknown, d3.PieArcDatum<D3Sections>> = arc<
|
const arcGenerator: d3.Arc<unknown, d3.PieArcDatum<D3Section>> = arc<d3.PieArcDatum<D3Section>>()
|
||||||
d3.PieArcDatum<D3Sections>
|
|
||||||
>()
|
|
||||||
.innerRadius(0)
|
.innerRadius(0)
|
||||||
.outerRadius(radius);
|
.outerRadius(radius);
|
||||||
const labelArcGenerator: d3.Arc<unknown, d3.PieArcDatum<D3Sections>> = arc<
|
const labelArcGenerator: d3.Arc<unknown, d3.PieArcDatum<D3Section>> = arc<
|
||||||
d3.PieArcDatum<D3Sections>
|
d3.PieArcDatum<D3Section>
|
||||||
>()
|
>()
|
||||||
.innerRadius(radius * textPosition)
|
.innerRadius(radius * textPosition)
|
||||||
.outerRadius(radius * textPosition);
|
.outerRadius(radius * textPosition);
|
||||||
@ -75,7 +72,8 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
|||||||
.attr('r', radius + outerStrokeWidth / 2)
|
.attr('r', radius + outerStrokeWidth / 2)
|
||||||
.attr('class', 'pieOuterCircle');
|
.attr('class', 'pieOuterCircle');
|
||||||
|
|
||||||
const arcs: d3.PieArcDatum<D3Sections>[] = createPieArcs(sections);
|
const sections: Sections = db.getSections();
|
||||||
|
const arcs: d3.PieArcDatum<D3Section>[] = createPieArcs(sections);
|
||||||
|
|
||||||
const myGeneratedColors = [
|
const myGeneratedColors = [
|
||||||
themeVariables.pie1,
|
themeVariables.pie1,
|
||||||
@ -101,7 +99,7 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
|||||||
.enter()
|
.enter()
|
||||||
.append('path')
|
.append('path')
|
||||||
.attr('d', arcGenerator)
|
.attr('d', arcGenerator)
|
||||||
.attr('fill', (datum: d3.PieArcDatum<D3Sections>) => {
|
.attr('fill', (datum: d3.PieArcDatum<D3Section>) => {
|
||||||
return color(datum.data.label);
|
return color(datum.data.label);
|
||||||
})
|
})
|
||||||
.attr('class', 'pieCircle');
|
.attr('class', 'pieCircle');
|
||||||
@ -117,10 +115,10 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
|||||||
.data(arcs)
|
.data(arcs)
|
||||||
.enter()
|
.enter()
|
||||||
.append('text')
|
.append('text')
|
||||||
.text((datum: d3.PieArcDatum<D3Sections>): string => {
|
.text((datum: d3.PieArcDatum<D3Section>): string => {
|
||||||
return ((datum.data.value / sum) * 100).toFixed(0) + '%';
|
return ((datum.data.value / sum) * 100).toFixed(0) + '%';
|
||||||
})
|
})
|
||||||
.attr('transform', (datum: d3.PieArcDatum<D3Sections>): string => {
|
.attr('transform', (datum: d3.PieArcDatum<D3Section>): string => {
|
||||||
return 'translate(' + labelArcGenerator.centroid(datum) + ')';
|
return 'translate(' + labelArcGenerator.centroid(datum) + ')';
|
||||||
})
|
})
|
||||||
.style('text-anchor', 'middle')
|
.style('text-anchor', 'middle')
|
||||||
@ -160,7 +158,7 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
|||||||
.append('text')
|
.append('text')
|
||||||
.attr('x', LEGEND_RECT_SIZE + LEGEND_SPACING)
|
.attr('x', LEGEND_RECT_SIZE + LEGEND_SPACING)
|
||||||
.attr('y', LEGEND_RECT_SIZE - LEGEND_SPACING)
|
.attr('y', LEGEND_RECT_SIZE - LEGEND_SPACING)
|
||||||
.text((datum: d3.PieArcDatum<D3Sections>): string => {
|
.text((datum: d3.PieArcDatum<D3Section>): string => {
|
||||||
const { label, value } = datum.data;
|
const { label, value } = datum.data;
|
||||||
if (db.getShowData()) {
|
if (db.getShowData()) {
|
||||||
return `${label} [${value}]`;
|
return `${label} [${value}]`;
|
||||||
|
@ -36,7 +36,7 @@ export interface PieStyleOptions {
|
|||||||
|
|
||||||
export type Sections = Record<string, number>;
|
export type Sections = Record<string, number>;
|
||||||
|
|
||||||
export interface D3Sections {
|
export interface D3Section {
|
||||||
label: string;
|
label: string;
|
||||||
value: number;
|
value: number;
|
||||||
}
|
}
|
||||||
@ -55,9 +55,8 @@ export interface PieDB extends DiagramDB {
|
|||||||
getAccDescription: () => string;
|
getAccDescription: () => string;
|
||||||
|
|
||||||
// diagram db
|
// diagram db
|
||||||
addSection: (label: string, value: number) => void;
|
addSection: ({ label, value }: D3Section) => void;
|
||||||
getSections: () => Sections;
|
getSections: () => Sections;
|
||||||
cleanupValue: (value: string) => number;
|
|
||||||
setShowData: (toggle: boolean) => void;
|
setShowData: (toggle: boolean) => void;
|
||||||
getShowData: () => boolean;
|
getShowData: () => boolean;
|
||||||
}
|
}
|
||||||
|
@ -239,18 +239,18 @@ In this example, the `mermaidAPI` is being called through the `CDN`:
|
|||||||
<body>
|
<body>
|
||||||
Here is one mermaid diagram:
|
Here is one mermaid diagram:
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
graph TD
|
graph TD
|
||||||
A[Client] --> B[Load Balancer]
|
A[Client] --> B[Load Balancer]
|
||||||
B --> C[Server1]
|
B --> C[Server1]
|
||||||
B --> D[Server2]
|
B --> D[Server2]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
And here is another:
|
And here is another:
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
graph TD
|
graph TD
|
||||||
A[Client] -->|tcp_123| B
|
A[Client] -->|tcp_123| B
|
||||||
B(Load Balancer)
|
B(Load Balancer)
|
||||||
B -->|tcp_456| C[Server1]
|
B -->|tcp_456| C[Server1]
|
||||||
B -->|tcp_456| D[Server2]
|
B -->|tcp_456| D[Server2]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -271,15 +271,15 @@ In this example, `mermaid.js` is referenced in `src` as a separate JavaScript fi
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
graph LR
|
graph LR
|
||||||
A --- B
|
A --- B
|
||||||
B-->C[fa:fa-ban forbidden]
|
B-->C[fa:fa-ban forbidden]
|
||||||
B-->D(fa:fa-spinner);
|
B-->D(fa:fa-spinner);
|
||||||
</pre>
|
</pre>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
graph TD
|
graph TD
|
||||||
A[Client] --> B[Load Balancer]
|
A[Client] --> B[Load Balancer]
|
||||||
B --> C[Server1]
|
B --> C[Server1]
|
||||||
B --> D[Server2]
|
B --> D[Server2]
|
||||||
</pre>
|
</pre>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
@ -10,6 +10,11 @@
|
|||||||
"id": "packet",
|
"id": "packet",
|
||||||
"grammar": "src/language/packet/packet.langium",
|
"grammar": "src/language/packet/packet.langium",
|
||||||
"fileExtensions": [".mmd", ".mermaid"]
|
"fileExtensions": [".mmd", ".mermaid"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pie",
|
||||||
|
"grammar": "src/language/pie/pie.langium",
|
||||||
|
"fileExtensions": [".mmd", ".mermaid"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"mode": "production",
|
"mode": "production",
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/mermaid-parser.esm.mjs",
|
"import": "./dist/mermaid-parser.core.mjs",
|
||||||
"types": "./dist/src/index.d.ts"
|
"types": "./dist/src/index.d.ts"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -34,10 +34,10 @@
|
|||||||
"ast"
|
"ast"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"langium": "2.0.1"
|
"langium": "2.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"langium-cli": "2.0.1"
|
"chevrotain": "^11.0.3"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist/"
|
"dist/"
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import type { AstNode } from 'langium';
|
import type { AstNode } from 'langium';
|
||||||
|
|
||||||
export type { Info, Packet } from './language/index.js';
|
export * from './language/index.js';
|
||||||
export { MermaidParseError, parse } from './parse.js';
|
export * from './parse.js';
|
||||||
export type { DiagramAST } from './parse.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exclude/omit all `AstNode` attributes recursively.
|
* Exclude/omit all `AstNode` attributes recursively.
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
|
|
||||||
type CustomPatternMatcherReturn = [string] & { payload?: any };
|
|
||||||
|
|
||||||
export type CustomPatternMatcherFunc = (
|
|
||||||
text: string,
|
|
||||||
offset: number,
|
|
||||||
tokens: IToken[],
|
|
||||||
groups: {
|
|
||||||
[groupName: string]: IToken[];
|
|
||||||
}
|
|
||||||
) => CustomPatternMatcherReturn | RegExpExecArray | null;
|
|
||||||
|
|
||||||
interface ICustomPattern {
|
|
||||||
exec: CustomPatternMatcherFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
type TokenPattern = RegExp | string | CustomPatternMatcherFunc | ICustomPattern;
|
|
||||||
|
|
||||||
export interface IToken {
|
|
||||||
image: string;
|
|
||||||
startOffset: number;
|
|
||||||
startLine?: number;
|
|
||||||
startColumn?: number;
|
|
||||||
endOffset?: number;
|
|
||||||
endLine?: number;
|
|
||||||
endColumn?: number;
|
|
||||||
isInsertedInRecovery?: boolean;
|
|
||||||
tokenTypeIdx: number;
|
|
||||||
tokenType: TokenType;
|
|
||||||
payload?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TokenType {
|
|
||||||
name: string;
|
|
||||||
GROUP?: string;
|
|
||||||
PATTERN?: TokenPattern;
|
|
||||||
LABEL?: string;
|
|
||||||
LONGER_ALT?: TokenType | TokenType[];
|
|
||||||
POP_MODE?: boolean;
|
|
||||||
PUSH_MODE?: string;
|
|
||||||
LINE_BREAKS?: boolean;
|
|
||||||
CATEGORIES?: TokenType[];
|
|
||||||
tokenTypeIdx?: number;
|
|
||||||
categoryMatches?: number[];
|
|
||||||
categoryMatchesMap?: {
|
|
||||||
[tokType: number]: boolean;
|
|
||||||
};
|
|
||||||
isParent?: boolean;
|
|
||||||
START_CHARS_HINT?: (string | number)[];
|
|
||||||
}
|
|
@ -5,15 +5,19 @@ interface Common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fragment TitleAndAccessibilities:
|
fragment TitleAndAccessibilities:
|
||||||
((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) NEWLINE+)+
|
((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) EOL)+
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment EOL returns string:
|
||||||
|
NEWLINE+ | EOF
|
||||||
;
|
;
|
||||||
|
|
||||||
terminal NEWLINE: /\r?\n/;
|
terminal NEWLINE: /\r?\n/;
|
||||||
terminal ACC_DESCR: /accDescr([\t ]*:[^\n\r]*(?=%%)|\s*{[^}]*})|accDescr([\t ]*:[^\n\r]*|\s*{[^}]*})/;
|
terminal ACC_DESCR: /[\t ]*accDescr(?:[\t ]*:([^\n\r]*?(?=%%)|[^\n\r]*)|\s*{([^}]*)})/;
|
||||||
terminal ACC_TITLE: /accTitle[\t ]*:[^\n\r]*(?=%%)|accTitle[\t ]*:[^\n\r]*/;
|
terminal ACC_TITLE: /[\t ]*accTitle[\t ]*:(?:[^\n\r]*?(?=%%)|[^\n\r]*)/;
|
||||||
terminal TITLE: /title([\t ][^\n\r]*|)(?=%%)|title([\t ][^\n\r]*|)/;
|
terminal TITLE: /[\t ]*title(?:[\t ][^\n\r]*?(?=%%)|[\t ][^\n\r]*|)/;
|
||||||
|
|
||||||
hidden terminal WHITESPACE: /[\t ]+/;
|
hidden terminal WHITESPACE: /[\t ]+/;
|
||||||
hidden terminal YAML: /---[\t ]*\r?\n[\S\s]*?---[\t ]*(?!.)/;
|
hidden terminal YAML: /---[\t ]*\r?\n(?:[\S\s]*?\r?\n)?---(?:\r?\n|(?!\S))/;
|
||||||
hidden terminal DIRECTIVE: /[\t ]*%%{[\S\s]*?}%%\s*/;
|
hidden terminal DIRECTIVE: /[\t ]*%%{[\S\s]*?}%%(?:\r?\n|(?!\S))/;
|
||||||
hidden terminal SINGLE_LINE_COMMENT: /[\t ]*%%[^\n\r]*/;
|
hidden terminal SINGLE_LINE_COMMENT: /[\t ]*%%[^\n\r]*/;
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
export * from './lexer.js';
|
|
||||||
export * from './tokenBuilder.js';
|
export * from './tokenBuilder.js';
|
||||||
export { MermaidValueConverter } from './valueConverter.js';
|
export * from './valueConverter.js';
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
import type { LexerResult } from 'langium';
|
|
||||||
import { DefaultLexer } from 'langium';
|
|
||||||
|
|
||||||
export class CommonLexer extends DefaultLexer {
|
|
||||||
public override tokenize(text: string): LexerResult {
|
|
||||||
return super.tokenize(text + '\n');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* Matches single and multiline accessible description
|
* Matches single and multi line accessible description
|
||||||
*/
|
*/
|
||||||
export const accessibilityDescrRegex = /accDescr(?:[\t ]*:[\t ]*([^\n\r]*)|\s*{([^}]*)})/;
|
export const accessibilityDescrRegex = /accDescr(?:[\t ]*:([^\n\r]*)|\s*{([^}]*)})/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches single line accessible title
|
* Matches single line accessible title
|
||||||
*/
|
*/
|
||||||
export const accessibilityTitleRegex = /accTitle[\t ]*:[\t ]*([^\n\r]*)/;
|
export const accessibilityTitleRegex = /accTitle[\t ]*:([^\n\r]*)/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches a single line title
|
* Matches a single line title
|
||||||
*/
|
*/
|
||||||
export const titleRegex = /title([\t ]+([^\n\r]*)|)/;
|
export const titleRegex = /title([\t ][^\n\r]*|)/;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import type { GrammarAST, Stream, TokenBuilderOptions } from 'langium';
|
import type { GrammarAST, Stream, TokenBuilderOptions } from 'langium';
|
||||||
import type { TokenType } from '../chevrotainWrapper.js';
|
import type { TokenType } from 'chevrotain';
|
||||||
|
|
||||||
import { DefaultTokenBuilder } from 'langium';
|
import { DefaultTokenBuilder } from 'langium';
|
||||||
|
|
||||||
export abstract class MermaidTokenBuilder extends DefaultTokenBuilder {
|
export abstract class AbstractMermaidTokenBuilder extends DefaultTokenBuilder {
|
||||||
private keywords: Set<string>;
|
private keywords: Set<string>;
|
||||||
|
|
||||||
public constructor(keywords: string[]) {
|
public constructor(keywords: string[]) {
|
||||||
@ -20,9 +20,11 @@ export abstract class MermaidTokenBuilder extends DefaultTokenBuilder {
|
|||||||
// to restrict users, they mustn't have any non-whitespace characters after the keyword.
|
// to restrict users, they mustn't have any non-whitespace characters after the keyword.
|
||||||
tokenTypes.forEach((tokenType: TokenType): void => {
|
tokenTypes.forEach((tokenType: TokenType): void => {
|
||||||
if (this.keywords.has(tokenType.name) && tokenType.PATTERN !== undefined) {
|
if (this.keywords.has(tokenType.name) && tokenType.PATTERN !== undefined) {
|
||||||
tokenType.PATTERN = new RegExp(tokenType.PATTERN.toString() + '(?!\\S)');
|
tokenType.PATTERN = new RegExp(tokenType.PATTERN.toString() + '(?:(?=%%)|(?!\\S))');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return tokenTypes;
|
return tokenTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class CommonTokenBuilder extends AbstractMermaidTokenBuilder {}
|
||||||
|
@ -10,7 +10,7 @@ const rulesRegexes: Record<string, RegExp> = {
|
|||||||
TITLE: titleRegex,
|
TITLE: titleRegex,
|
||||||
};
|
};
|
||||||
|
|
||||||
export abstract class MermaidValueConverter extends DefaultValueConverter {
|
export abstract class AbstractMermaidValueConverter extends DefaultValueConverter {
|
||||||
/**
|
/**
|
||||||
* A method contains convert logic to be used by class.
|
* A method contains convert logic to be used by class.
|
||||||
*
|
*
|
||||||
@ -71,8 +71,8 @@ export abstract class MermaidValueConverter extends DefaultValueConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CommonValueConverter extends MermaidValueConverter {
|
export class CommonValueConverter extends AbstractMermaidValueConverter {
|
||||||
protected runCustomConverter(
|
protected override runCustomConverter(
|
||||||
_rule: GrammarAST.AbstractRule,
|
_rule: GrammarAST.AbstractRule,
|
||||||
_input: string,
|
_input: string,
|
||||||
_cstNode: CstNode
|
_cstNode: CstNode
|
||||||
|
@ -1,7 +1,25 @@
|
|||||||
export * from './generated/ast.js';
|
export {
|
||||||
export * from './generated/grammar.js';
|
Info,
|
||||||
export * from './generated/module.js';
|
MermaidAstType,
|
||||||
|
Packet,
|
||||||
|
PacketBlock,
|
||||||
|
Pie,
|
||||||
|
PieSection,
|
||||||
|
isCommon,
|
||||||
|
isInfo,
|
||||||
|
isPacket,
|
||||||
|
isPacketBlock,
|
||||||
|
isPie,
|
||||||
|
isPieSection,
|
||||||
|
} from './generated/ast.js';
|
||||||
|
export {
|
||||||
|
InfoGeneratedModule,
|
||||||
|
MermaidGeneratedSharedModule,
|
||||||
|
PacketGeneratedModule,
|
||||||
|
PieGeneratedModule,
|
||||||
|
} from './generated/module.js';
|
||||||
|
|
||||||
export * from './common/index.js';
|
export * from './common/index.js';
|
||||||
export * from './info/index.js';
|
export * from './info/index.js';
|
||||||
export * from './packet/index.js';
|
export * from './packet/index.js';
|
||||||
|
export * from './pie/index.js';
|
||||||
|
@ -7,8 +7,7 @@ import type {
|
|||||||
} from 'langium';
|
} from 'langium';
|
||||||
import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject } from 'langium';
|
import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject } from 'langium';
|
||||||
|
|
||||||
import { CommonLexer } from '../common/lexer.js';
|
import { CommonValueConverter } from '../common/index.js';
|
||||||
import { CommonValueConverter } from '../common/valueConverter.js';
|
|
||||||
import { InfoGeneratedModule, MermaidGeneratedSharedModule } from '../generated/module.js';
|
import { InfoGeneratedModule, MermaidGeneratedSharedModule } from '../generated/module.js';
|
||||||
import { InfoTokenBuilder } from './tokenBuilder.js';
|
import { InfoTokenBuilder } from './tokenBuilder.js';
|
||||||
|
|
||||||
@ -17,7 +16,6 @@ import { InfoTokenBuilder } from './tokenBuilder.js';
|
|||||||
*/
|
*/
|
||||||
type InfoAddedServices = {
|
type InfoAddedServices = {
|
||||||
parser: {
|
parser: {
|
||||||
Lexer: CommonLexer;
|
|
||||||
TokenBuilder: InfoTokenBuilder;
|
TokenBuilder: InfoTokenBuilder;
|
||||||
ValueConverter: CommonValueConverter;
|
ValueConverter: CommonValueConverter;
|
||||||
};
|
};
|
||||||
@ -34,7 +32,6 @@ export type InfoServices = LangiumServices & InfoAddedServices;
|
|||||||
*/
|
*/
|
||||||
export const InfoModule: Module<InfoServices, PartialLangiumServices & InfoAddedServices> = {
|
export const InfoModule: Module<InfoServices, PartialLangiumServices & InfoAddedServices> = {
|
||||||
parser: {
|
parser: {
|
||||||
Lexer: (services: InfoServices) => new CommonLexer(services),
|
|
||||||
TokenBuilder: () => new InfoTokenBuilder(),
|
TokenBuilder: () => new InfoTokenBuilder(),
|
||||||
ValueConverter: () => new CommonValueConverter(),
|
ValueConverter: () => new CommonValueConverter(),
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { MermaidTokenBuilder } from '../common/index.js';
|
import { AbstractMermaidTokenBuilder } from '../common/index.js';
|
||||||
|
|
||||||
export class InfoTokenBuilder extends MermaidTokenBuilder {
|
export class InfoTokenBuilder extends AbstractMermaidTokenBuilder {
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super(['info', 'showInfo']);
|
super(['info', 'showInfo']);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import type {
|
|||||||
PartialLangiumServices,
|
PartialLangiumServices,
|
||||||
} from 'langium';
|
} from 'langium';
|
||||||
import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject } from 'langium';
|
import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject } from 'langium';
|
||||||
import { CommonLexer } from '../common/lexer.js';
|
|
||||||
import { CommonValueConverter } from '../common/valueConverter.js';
|
import { CommonValueConverter } from '../common/valueConverter.js';
|
||||||
import { MermaidGeneratedSharedModule, PacketGeneratedModule } from '../generated/module.js';
|
import { MermaidGeneratedSharedModule, PacketGeneratedModule } from '../generated/module.js';
|
||||||
import { PacketTokenBuilder } from './tokenBuilder.js';
|
import { PacketTokenBuilder } from './tokenBuilder.js';
|
||||||
@ -16,7 +15,6 @@ import { PacketTokenBuilder } from './tokenBuilder.js';
|
|||||||
*/
|
*/
|
||||||
type PacketAddedServices = {
|
type PacketAddedServices = {
|
||||||
parser: {
|
parser: {
|
||||||
Lexer: CommonLexer;
|
|
||||||
TokenBuilder: PacketTokenBuilder;
|
TokenBuilder: PacketTokenBuilder;
|
||||||
ValueConverter: CommonValueConverter;
|
ValueConverter: CommonValueConverter;
|
||||||
};
|
};
|
||||||
@ -33,7 +31,6 @@ export type PacketServices = LangiumServices & PacketAddedServices;
|
|||||||
*/
|
*/
|
||||||
export const PacketModule: Module<PacketServices, PartialLangiumServices & PacketAddedServices> = {
|
export const PacketModule: Module<PacketServices, PartialLangiumServices & PacketAddedServices> = {
|
||||||
parser: {
|
parser: {
|
||||||
Lexer: (services: PacketServices) => new CommonLexer(services),
|
|
||||||
TokenBuilder: () => new PacketTokenBuilder(),
|
TokenBuilder: () => new PacketTokenBuilder(),
|
||||||
ValueConverter: () => new CommonValueConverter(),
|
ValueConverter: () => new CommonValueConverter(),
|
||||||
},
|
},
|
||||||
|
@ -4,15 +4,15 @@ import "../common/common";
|
|||||||
entry Packet:
|
entry Packet:
|
||||||
NEWLINE*
|
NEWLINE*
|
||||||
"packet-beta"
|
"packet-beta"
|
||||||
(
|
(
|
||||||
NEWLINE* TitleAndAccessibilities blocks+=PacketBlock*
|
NEWLINE* TitleAndAccessibilities blocks+=PacketBlock*
|
||||||
| NEWLINE+ blocks+=PacketBlock+
|
| NEWLINE+ blocks+=PacketBlock+
|
||||||
| NEWLINE*
|
| NEWLINE*
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
||||||
PacketBlock:
|
PacketBlock:
|
||||||
start=INT('-' end=INT)? ':' label=STRING NEWLINE+
|
start=INT('-' end=INT)? ':' label=STRING EOL
|
||||||
;
|
;
|
||||||
|
|
||||||
terminal INT returns number: /0|[1-9][0-9]*/;
|
terminal INT returns number: /0|[1-9][0-9]*/;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { MermaidTokenBuilder } from '../common/index.js';
|
import { AbstractMermaidTokenBuilder } from '../common/index.js';
|
||||||
|
|
||||||
export class PacketTokenBuilder extends MermaidTokenBuilder {
|
export class PacketTokenBuilder extends AbstractMermaidTokenBuilder {
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super(['packet-beta']);
|
super(['packet-beta']);
|
||||||
}
|
}
|
||||||
|
1
packages/parser/src/language/pie/index.ts
Normal file
1
packages/parser/src/language/pie/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './module.js';
|
65
packages/parser/src/language/pie/module.ts
Normal file
65
packages/parser/src/language/pie/module.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import type {
|
||||||
|
DefaultSharedModuleContext,
|
||||||
|
LangiumServices,
|
||||||
|
LangiumSharedServices,
|
||||||
|
Module,
|
||||||
|
PartialLangiumServices,
|
||||||
|
} from 'langium';
|
||||||
|
import { EmptyFileSystem, createDefaultModule, createDefaultSharedModule, inject } from 'langium';
|
||||||
|
|
||||||
|
import { MermaidGeneratedSharedModule, PieGeneratedModule } from '../generated/module.js';
|
||||||
|
import { PieTokenBuilder } from './tokenBuilder.js';
|
||||||
|
import { PieValueConverter } from './valueConverter.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declaration of `Pie` services.
|
||||||
|
*/
|
||||||
|
type PieAddedServices = {
|
||||||
|
parser: {
|
||||||
|
TokenBuilder: PieTokenBuilder;
|
||||||
|
ValueConverter: PieValueConverter;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Union of Langium default services and `Pie` services.
|
||||||
|
*/
|
||||||
|
export type PieServices = LangiumServices & PieAddedServices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dependency injection module that overrides Langium default services and
|
||||||
|
* contributes the declared `Pie` services.
|
||||||
|
*/
|
||||||
|
export const PieModule: Module<PieServices, PartialLangiumServices & PieAddedServices> = {
|
||||||
|
parser: {
|
||||||
|
TokenBuilder: () => new PieTokenBuilder(),
|
||||||
|
ValueConverter: () => new PieValueConverter(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the full set of services required by Langium.
|
||||||
|
*
|
||||||
|
* First inject the shared services by merging two modules:
|
||||||
|
* - Langium default shared services
|
||||||
|
* - Services generated by langium-cli
|
||||||
|
*
|
||||||
|
* Then inject the language-specific services by merging three modules:
|
||||||
|
* - Langium default language-specific services
|
||||||
|
* - Services generated by langium-cli
|
||||||
|
* - Services specified in this file
|
||||||
|
* @param context - Optional module context with the LSP connection
|
||||||
|
* @returns An object wrapping the shared services and the language-specific services
|
||||||
|
*/
|
||||||
|
export function createPieServices(context: DefaultSharedModuleContext = EmptyFileSystem): {
|
||||||
|
shared: LangiumSharedServices;
|
||||||
|
Pie: PieServices;
|
||||||
|
} {
|
||||||
|
const shared: LangiumSharedServices = inject(
|
||||||
|
createDefaultSharedModule(context),
|
||||||
|
MermaidGeneratedSharedModule
|
||||||
|
);
|
||||||
|
const Pie: PieServices = inject(createDefaultModule({ shared }), PieGeneratedModule, PieModule);
|
||||||
|
shared.ServiceRegistry.register(Pie);
|
||||||
|
return { shared, Pie };
|
||||||
|
}
|
19
packages/parser/src/language/pie/pie.langium
Normal file
19
packages/parser/src/language/pie/pie.langium
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
grammar Pie
|
||||||
|
import "../common/common";
|
||||||
|
|
||||||
|
entry Pie:
|
||||||
|
NEWLINE*
|
||||||
|
"pie" showData?="showData"?
|
||||||
|
(
|
||||||
|
NEWLINE* TitleAndAccessibilities sections+=PieSection*
|
||||||
|
| NEWLINE+ sections+=PieSection+
|
||||||
|
| NEWLINE*
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
PieSection:
|
||||||
|
label=PIE_SECTION_LABEL ":" value=PIE_SECTION_VALUE EOL
|
||||||
|
;
|
||||||
|
|
||||||
|
terminal PIE_SECTION_LABEL: /"[^"]+"/;
|
||||||
|
terminal PIE_SECTION_VALUE returns number: /(0|[1-9][0-9]*)(\.[0-9]+)?/;
|
7
packages/parser/src/language/pie/tokenBuilder.ts
Normal file
7
packages/parser/src/language/pie/tokenBuilder.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { AbstractMermaidTokenBuilder } from '../common/index.js';
|
||||||
|
|
||||||
|
export class PieTokenBuilder extends AbstractMermaidTokenBuilder {
|
||||||
|
public constructor() {
|
||||||
|
super(['pie', 'showData']);
|
||||||
|
}
|
||||||
|
}
|
17
packages/parser/src/language/pie/valueConverter.ts
Normal file
17
packages/parser/src/language/pie/valueConverter.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import type { CstNode, GrammarAST, ValueType } from 'langium';
|
||||||
|
|
||||||
|
import { AbstractMermaidValueConverter } from '../common/index.js';
|
||||||
|
|
||||||
|
export class PieValueConverter extends AbstractMermaidValueConverter {
|
||||||
|
protected runCustomConverter(
|
||||||
|
rule: GrammarAST.AbstractRule,
|
||||||
|
input: string,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
_cstNode: CstNode
|
||||||
|
): ValueType | undefined {
|
||||||
|
if (rule.name !== 'PIE_SECTION_LABEL') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return input.replace(/"/g, '').trim();
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
import type { LangiumParser, ParseResult } from 'langium';
|
import type { LangiumParser, ParseResult } from 'langium';
|
||||||
import type { Info, Packet } from './index.js';
|
|
||||||
|
|
||||||
export type DiagramAST = Info | Packet;
|
import type { Info, Packet, Pie } from './index.js';
|
||||||
|
|
||||||
|
export type DiagramAST = Info | Packet | Pie;
|
||||||
|
|
||||||
const parsers: Record<string, LangiumParser> = {};
|
const parsers: Record<string, LangiumParser> = {};
|
||||||
|
|
||||||
const initializers = {
|
const initializers = {
|
||||||
info: async () => {
|
info: async () => {
|
||||||
const { createInfoServices } = await import('./language/info/index.js');
|
const { createInfoServices } = await import('./language/info/index.js');
|
||||||
@ -16,9 +16,16 @@ const initializers = {
|
|||||||
const parser = createPacketServices().Packet.parser.LangiumParser;
|
const parser = createPacketServices().Packet.parser.LangiumParser;
|
||||||
parsers['packet'] = parser;
|
parsers['packet'] = parser;
|
||||||
},
|
},
|
||||||
|
pie: async () => {
|
||||||
|
const { createPieServices } = await import('./language/pie/index.js');
|
||||||
|
const parser = createPieServices().Pie.parser.LangiumParser;
|
||||||
|
parsers['pie'] = parser;
|
||||||
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export async function parse(diagramType: 'info', text: string): Promise<Info>;
|
export async function parse(diagramType: 'info', text: string): Promise<Info>;
|
||||||
export async function parse(diagramType: 'packet', text: string): Promise<Packet>;
|
export async function parse(diagramType: 'packet', text: string): Promise<Packet>;
|
||||||
|
export async function parse(diagramType: 'pie', text: string): Promise<Pie>;
|
||||||
export async function parse<T extends DiagramAST>(
|
export async function parse<T extends DiagramAST>(
|
||||||
diagramType: keyof typeof initializers,
|
diagramType: keyof typeof initializers,
|
||||||
text: string
|
text: string
|
||||||
|
@ -1,26 +1,9 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import type { LangiumParser, ParseResult } from 'langium';
|
|
||||||
|
|
||||||
import type { InfoServices } from '../src/language/index.js';
|
import { Info } from '../src/language/index.js';
|
||||||
import { Info, createInfoServices } from '../src/language/index.js';
|
import { expectNoErrorsOrAlternatives, infoParse as parse } from './test-util.js';
|
||||||
import { noErrorsOrAlternatives } from './test-util.js';
|
|
||||||
|
|
||||||
const services: InfoServices = createInfoServices().Info;
|
|
||||||
const parser: LangiumParser = services.parser.LangiumParser;
|
|
||||||
function createInfoTestServices(): {
|
|
||||||
services: InfoServices;
|
|
||||||
parse: (input: string) => ParseResult<Info>;
|
|
||||||
} {
|
|
||||||
const parse = (input: string) => {
|
|
||||||
return parser.parse<Info>(input);
|
|
||||||
};
|
|
||||||
|
|
||||||
return { services, parse };
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('info', () => {
|
describe('info', () => {
|
||||||
const { parse } = createInfoTestServices();
|
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
`info`,
|
`info`,
|
||||||
`
|
`
|
||||||
@ -32,26 +15,34 @@ describe('info', () => {
|
|||||||
`,
|
`,
|
||||||
])('should handle empty info', (context: string) => {
|
])('should handle empty info', (context: string) => {
|
||||||
const result = parse(context);
|
const result = parse(context);
|
||||||
noErrorsOrAlternatives(result);
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
|
||||||
expect(result.value.$type).toBe(Info);
|
expect(result.value.$type).toBe(Info);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
`info showInfo`,
|
`info showInfo`,
|
||||||
|
`info showInfo
|
||||||
|
`,
|
||||||
`
|
`
|
||||||
info showInfo`,
|
info showInfo`,
|
||||||
`info
|
`info
|
||||||
|
showInfo`,
|
||||||
|
`info
|
||||||
showInfo
|
showInfo
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
info
|
info
|
||||||
showInfo
|
showInfo
|
||||||
`,
|
`,
|
||||||
|
`
|
||||||
|
info
|
||||||
|
showInfo`,
|
||||||
|
`
|
||||||
|
info showInfo
|
||||||
|
`,
|
||||||
])('should handle showInfo', (context: string) => {
|
])('should handle showInfo', (context: string) => {
|
||||||
const result = parse(context);
|
const result = parse(context);
|
||||||
noErrorsOrAlternatives(result);
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
|
||||||
expect(result.value.$type).toBe(Info);
|
expect(result.value.$type).toBe(Info);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
229
packages/parser/tests/pie.test.ts
Normal file
229
packages/parser/tests/pie.test.ts
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { Pie } from '../src/language/index.js';
|
||||||
|
import { expectNoErrorsOrAlternatives, pieParse as parse } from './test-util.js';
|
||||||
|
|
||||||
|
describe('pie', () => {
|
||||||
|
it.each([
|
||||||
|
`pie`,
|
||||||
|
` pie `,
|
||||||
|
`\tpie\t`,
|
||||||
|
`
|
||||||
|
\tpie
|
||||||
|
`,
|
||||||
|
])('should handle regular pie', (context: string) => {
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
`pie showData`,
|
||||||
|
` pie showData `,
|
||||||
|
`\tpie\tshowData\t`,
|
||||||
|
`
|
||||||
|
pie\tshowData
|
||||||
|
`,
|
||||||
|
])('should handle regular showData', (context: string) => {
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { showData } = result.value;
|
||||||
|
expect(showData).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
`pie title sample title`,
|
||||||
|
` pie title sample title `,
|
||||||
|
`\tpie\ttitle sample title\t`,
|
||||||
|
`pie
|
||||||
|
\ttitle sample title
|
||||||
|
`,
|
||||||
|
])('should handle regular pie + title in same line', (context: string) => {
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { title } = result.value;
|
||||||
|
expect(title).toBe('sample title');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
`pie
|
||||||
|
title sample title`,
|
||||||
|
`pie
|
||||||
|
title sample title
|
||||||
|
`,
|
||||||
|
`pie
|
||||||
|
title sample title`,
|
||||||
|
`pie
|
||||||
|
title sample title
|
||||||
|
`,
|
||||||
|
])('should handle regular pie + title in different line', (context: string) => {
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { title } = result.value;
|
||||||
|
expect(title).toBe('sample title');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
`pie showData title sample title`,
|
||||||
|
`pie showData title sample title
|
||||||
|
`,
|
||||||
|
])('should handle regular pie + showData + title', (context: string) => {
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { showData, title } = result.value;
|
||||||
|
expect(showData).toBeTruthy();
|
||||||
|
expect(title).toBe('sample title');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
`pie showData
|
||||||
|
title sample title`,
|
||||||
|
`pie showData
|
||||||
|
title sample title
|
||||||
|
`,
|
||||||
|
`pie showData
|
||||||
|
title sample title`,
|
||||||
|
`pie showData
|
||||||
|
title sample title
|
||||||
|
`,
|
||||||
|
])('should handle regular showData + title in different line', (context: string) => {
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { showData, title } = result.value;
|
||||||
|
expect(showData).toBeTruthy();
|
||||||
|
expect(title).toBe('sample title');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sections', () => {
|
||||||
|
describe('normal', () => {
|
||||||
|
it.each([
|
||||||
|
`pie
|
||||||
|
"GitHub":100
|
||||||
|
"GitLab":50`,
|
||||||
|
`pie
|
||||||
|
"GitHub" : 100
|
||||||
|
"GitLab" : 50`,
|
||||||
|
`pie
|
||||||
|
"GitHub"\t:\t100
|
||||||
|
"GitLab"\t:\t50`,
|
||||||
|
`pie
|
||||||
|
\t"GitHub" \t : \t 100
|
||||||
|
\t"GitLab" \t : \t 50
|
||||||
|
`,
|
||||||
|
])('should handle regular secions', (context: string) => {
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { sections } = result.value;
|
||||||
|
expect(sections[0].label).toBe('GitHub');
|
||||||
|
expect(sections[0].value).toBe(100);
|
||||||
|
|
||||||
|
expect(sections[1].label).toBe('GitLab');
|
||||||
|
expect(sections[1].value).toBe(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle sections with showData', () => {
|
||||||
|
const context = `pie showData
|
||||||
|
"GitHub": 100
|
||||||
|
"GitLab": 50`;
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { showData, sections } = result.value;
|
||||||
|
expect(showData).toBeTruthy();
|
||||||
|
|
||||||
|
expect(sections[0].label).toBe('GitHub');
|
||||||
|
expect(sections[0].value).toBe(100);
|
||||||
|
|
||||||
|
expect(sections[1].label).toBe('GitLab');
|
||||||
|
expect(sections[1].value).toBe(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle sections with title', () => {
|
||||||
|
const context = `pie title sample wow
|
||||||
|
"GitHub": 100
|
||||||
|
"GitLab": 50`;
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { title, sections } = result.value;
|
||||||
|
expect(title).toBe('sample wow');
|
||||||
|
|
||||||
|
expect(sections[0].label).toBe('GitHub');
|
||||||
|
expect(sections[0].value).toBe(100);
|
||||||
|
|
||||||
|
expect(sections[1].label).toBe('GitLab');
|
||||||
|
expect(sections[1].value).toBe(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle sections with accTitle', () => {
|
||||||
|
const context = `pie accTitle: sample wow
|
||||||
|
"GitHub": 100
|
||||||
|
"GitLab": 50`;
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { accTitle, sections } = result.value;
|
||||||
|
expect(accTitle).toBe('sample wow');
|
||||||
|
|
||||||
|
expect(sections[0].label).toBe('GitHub');
|
||||||
|
expect(sections[0].value).toBe(100);
|
||||||
|
|
||||||
|
expect(sections[1].label).toBe('GitLab');
|
||||||
|
expect(sections[1].value).toBe(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle sections with single line accDescr', () => {
|
||||||
|
const context = `pie accDescr: sample wow
|
||||||
|
"GitHub": 100
|
||||||
|
"GitLab": 50`;
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { accDescr, sections } = result.value;
|
||||||
|
expect(accDescr).toBe('sample wow');
|
||||||
|
|
||||||
|
expect(sections[0].label).toBe('GitHub');
|
||||||
|
expect(sections[0].value).toBe(100);
|
||||||
|
|
||||||
|
expect(sections[1].label).toBe('GitLab');
|
||||||
|
expect(sections[1].value).toBe(50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle sections with multi line accDescr', () => {
|
||||||
|
const context = `pie accDescr {
|
||||||
|
sample wow
|
||||||
|
}
|
||||||
|
"GitHub": 100
|
||||||
|
"GitLab": 50`;
|
||||||
|
const result = parse(context);
|
||||||
|
expectNoErrorsOrAlternatives(result);
|
||||||
|
expect(result.value.$type).toBe(Pie);
|
||||||
|
|
||||||
|
const { accDescr, sections } = result.value;
|
||||||
|
expect(accDescr).toBe('sample wow');
|
||||||
|
|
||||||
|
expect(sections[0].label).toBe('GitHub');
|
||||||
|
expect(sections[0].value).toBe(100);
|
||||||
|
|
||||||
|
expect(sections[1].label).toBe('GitLab');
|
||||||
|
expect(sections[1].value).toBe(50);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,5 +1,7 @@
|
|||||||
|
import type { LangiumParser, ParseResult } from 'langium';
|
||||||
import { expect, vi } from 'vitest';
|
import { expect, vi } from 'vitest';
|
||||||
import type { ParseResult } from 'langium';
|
import type { Info, InfoServices, Pie, PieServices } from '../src/language/index.js';
|
||||||
|
import { createInfoServices, createPieServices } from '../src/language/index.js';
|
||||||
|
|
||||||
const consoleMock = vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
const consoleMock = vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
||||||
|
|
||||||
@ -9,10 +11,32 @@ const consoleMock = vi.spyOn(console, 'log').mockImplementation(() => undefined)
|
|||||||
*
|
*
|
||||||
* @param result - the result `parse` function.
|
* @param result - the result `parse` function.
|
||||||
*/
|
*/
|
||||||
export function noErrorsOrAlternatives(result: ParseResult) {
|
export function expectNoErrorsOrAlternatives(result: ParseResult) {
|
||||||
expect(result.lexerErrors).toHaveLength(0);
|
expect(result.lexerErrors).toHaveLength(0);
|
||||||
expect(result.parserErrors).toHaveLength(0);
|
expect(result.parserErrors).toHaveLength(0);
|
||||||
|
|
||||||
expect(consoleMock).not.toHaveBeenCalled();
|
expect(consoleMock).not.toHaveBeenCalled();
|
||||||
consoleMock.mockReset();
|
consoleMock.mockReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const infoServices: InfoServices = createInfoServices().Info;
|
||||||
|
const infoParser: LangiumParser = infoServices.parser.LangiumParser;
|
||||||
|
export function createInfoTestServices() {
|
||||||
|
const parse = (input: string) => {
|
||||||
|
return infoParser.parse<Info>(input);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { services: infoServices, parse };
|
||||||
|
}
|
||||||
|
export const infoParse = createInfoTestServices().parse;
|
||||||
|
|
||||||
|
const pieServices: PieServices = createPieServices().Pie;
|
||||||
|
const pieParser: LangiumParser = pieServices.parser.LangiumParser;
|
||||||
|
export function createPieTestServices() {
|
||||||
|
const parse = (input: string) => {
|
||||||
|
return pieParser.parse<Pie>(input);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { services: pieServices, parse };
|
||||||
|
}
|
||||||
|
export const pieParse = createPieTestServices().parse;
|
||||||
|
77
pnpm-lock.yaml
generated
77
pnpm-lock.yaml
generated
@ -496,12 +496,12 @@ importers:
|
|||||||
packages/parser:
|
packages/parser:
|
||||||
dependencies:
|
dependencies:
|
||||||
langium:
|
langium:
|
||||||
specifier: 2.0.1
|
specifier: 2.1.2
|
||||||
version: 2.0.1
|
version: 2.1.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
langium-cli:
|
chevrotain:
|
||||||
specifier: 2.0.1
|
specifier: ^11.0.3
|
||||||
version: 2.0.1
|
version: 11.0.3
|
||||||
|
|
||||||
tests/webpack:
|
tests/webpack:
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -11968,20 +11968,6 @@ packages:
|
|||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/langium-cli@2.0.1:
|
|
||||||
resolution: {integrity: sha512-dPPaHimIoCgELED4tvRGdU3i26tjWuyVwexXgPtTtTzp1MBdGCBLppLADXHkL8yFVdWM/PWlCq06YyqAT4eV3A==}
|
|
||||||
engines: {node: '>=16.0.0'}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
chalk: 5.3.0
|
|
||||||
commander: 10.0.1
|
|
||||||
fs-extra: 11.1.1
|
|
||||||
jsonschema: 1.4.1
|
|
||||||
langium: 2.0.1
|
|
||||||
langium-railroad: 2.0.0
|
|
||||||
lodash: 4.17.21
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/langium-cli@2.1.0:
|
/langium-cli@2.1.0:
|
||||||
resolution: {integrity: sha512-Gbj4CvfAc1gP/6ihxikd2Je95j1FWjXZu8bbji2/t2vQ6kEP+vs9Fx7kSGOM0AbU/hjZfy6E35bJPOdwsiyqTA==}
|
resolution: {integrity: sha512-Gbj4CvfAc1gP/6ihxikd2Je95j1FWjXZu8bbji2/t2vQ6kEP+vs9Fx7kSGOM0AbU/hjZfy6E35bJPOdwsiyqTA==}
|
||||||
engines: {node: '>=16.0.0'}
|
engines: {node: '>=16.0.0'}
|
||||||
@ -11991,37 +11977,20 @@ packages:
|
|||||||
commander: 11.0.0
|
commander: 11.0.0
|
||||||
fs-extra: 11.1.1
|
fs-extra: 11.1.1
|
||||||
jsonschema: 1.4.1
|
jsonschema: 1.4.1
|
||||||
langium: 2.1.3
|
langium: 2.1.2
|
||||||
langium-railroad: 2.1.0
|
langium-railroad: 2.1.0
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/langium-railroad@2.0.0:
|
|
||||||
resolution: {integrity: sha512-g6y8vPh4i7ll/Q4D9aFrjk4UgtkuzkE6WGfiTHJHTFlDwHoiKrPSIIBZO4wjEb3XUF9P5vIt7aRjerTy7Jgm0g==}
|
|
||||||
dependencies:
|
|
||||||
langium: 2.0.1
|
|
||||||
railroad-diagrams: 1.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/langium-railroad@2.1.0:
|
/langium-railroad@2.1.0:
|
||||||
resolution: {integrity: sha512-2IeAIUSTQzbDjNnJA+0ql8tyN/mhCSN4FS50Mo9LOtLj523qUEBwHflDmCiOGZzW9iZdni6NXJgh8nLqjhTlDw==}
|
resolution: {integrity: sha512-2IeAIUSTQzbDjNnJA+0ql8tyN/mhCSN4FS50Mo9LOtLj523qUEBwHflDmCiOGZzW9iZdni6NXJgh8nLqjhTlDw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
langium: 2.1.3
|
langium: 2.1.2
|
||||||
railroad-diagrams: 1.0.0
|
railroad-diagrams: 1.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/langium@2.0.1:
|
/langium@2.1.2:
|
||||||
resolution: {integrity: sha512-EGi8NNN/5zxcUL//sA4kqpV9YVOZfDngwkkSxsZ/zfx4Wjdg9von71rWIMCV6kW1M40kPOKF6e8oMTyWeX92fg==}
|
resolution: {integrity: sha512-1NDUmhm111xs6NLh1DzQ9YPrOhL6JqJryY9igPIGrG0AbKKGmGf3fahAiY1MUChwIYSec6Fvoj+igwKzvGXQog==}
|
||||||
engines: {node: '>=16.0.0'}
|
|
||||||
dependencies:
|
|
||||||
chevrotain: 11.0.3
|
|
||||||
chevrotain-allstar: 0.3.1(chevrotain@11.0.3)
|
|
||||||
vscode-languageserver: 8.0.2
|
|
||||||
vscode-languageserver-textdocument: 1.0.8
|
|
||||||
vscode-uri: 3.0.7
|
|
||||||
|
|
||||||
/langium@2.1.3:
|
|
||||||
resolution: {integrity: sha512-/WN1xHoNBg0mi1Jp9ydMFSHIv8Jhq7K+0stNVURdoG4NgZx4/06AfNeeixmmU8X842wBl9gFZJP5O93Ge5Oasw==}
|
|
||||||
engines: {node: '>=16.0.0'}
|
engines: {node: '>=16.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
chevrotain: 11.0.3
|
chevrotain: 11.0.3
|
||||||
@ -12029,7 +11998,6 @@ packages:
|
|||||||
vscode-languageserver: 9.0.1
|
vscode-languageserver: 9.0.1
|
||||||
vscode-languageserver-textdocument: 1.0.11
|
vscode-languageserver-textdocument: 1.0.11
|
||||||
vscode-uri: 3.0.8
|
vscode-uri: 3.0.8
|
||||||
dev: true
|
|
||||||
|
|
||||||
/layout-base@1.0.2:
|
/layout-base@1.0.2:
|
||||||
resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==}
|
resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==}
|
||||||
@ -16502,37 +16470,22 @@ packages:
|
|||||||
vscode-uri: 3.0.7
|
vscode-uri: 3.0.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vscode-jsonrpc@8.0.2:
|
|
||||||
resolution: {integrity: sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==}
|
|
||||||
engines: {node: '>=14.0.0'}
|
|
||||||
|
|
||||||
/vscode-jsonrpc@8.2.0:
|
/vscode-jsonrpc@8.2.0:
|
||||||
resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
|
resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vscode-languageserver-protocol@3.17.2:
|
|
||||||
resolution: {integrity: sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==}
|
|
||||||
dependencies:
|
|
||||||
vscode-jsonrpc: 8.0.2
|
|
||||||
vscode-languageserver-types: 3.17.2
|
|
||||||
|
|
||||||
/vscode-languageserver-protocol@3.17.5:
|
/vscode-languageserver-protocol@3.17.5:
|
||||||
resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}
|
resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
vscode-jsonrpc: 8.2.0
|
vscode-jsonrpc: 8.2.0
|
||||||
vscode-languageserver-types: 3.17.5
|
vscode-languageserver-types: 3.17.5
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vscode-languageserver-textdocument@1.0.11:
|
/vscode-languageserver-textdocument@1.0.11:
|
||||||
resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==}
|
resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vscode-languageserver-textdocument@1.0.8:
|
/vscode-languageserver-textdocument@1.0.8:
|
||||||
resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==}
|
resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==}
|
||||||
|
dev: true
|
||||||
/vscode-languageserver-types@3.17.2:
|
|
||||||
resolution: {integrity: sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==}
|
|
||||||
|
|
||||||
/vscode-languageserver-types@3.17.3:
|
/vscode-languageserver-types@3.17.3:
|
||||||
resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==}
|
resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==}
|
||||||
@ -16540,20 +16493,12 @@ packages:
|
|||||||
|
|
||||||
/vscode-languageserver-types@3.17.5:
|
/vscode-languageserver-types@3.17.5:
|
||||||
resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}
|
resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vscode-languageserver@8.0.2:
|
|
||||||
resolution: {integrity: sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
vscode-languageserver-protocol: 3.17.2
|
|
||||||
|
|
||||||
/vscode-languageserver@9.0.1:
|
/vscode-languageserver@9.0.1:
|
||||||
resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
|
resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
vscode-languageserver-protocol: 3.17.5
|
vscode-languageserver-protocol: 3.17.5
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vscode-nls@5.2.0:
|
/vscode-nls@5.2.0:
|
||||||
resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==}
|
resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==}
|
||||||
@ -16569,10 +16514,10 @@ packages:
|
|||||||
|
|
||||||
/vscode-uri@3.0.7:
|
/vscode-uri@3.0.7:
|
||||||
resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==}
|
resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vscode-uri@3.0.8:
|
/vscode-uri@3.0.8:
|
||||||
resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
|
resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/vue-demi@0.13.11(vue@3.4.15):
|
/vue-demi@0.13.11(vue@3.4.15):
|
||||||
resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==}
|
resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user