mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-06 17:16:43 +02:00
Merge branch next into add-pie-langium-parser
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
import * as configApi from './config.js';
|
||||
import { log } from './logger.js';
|
||||
import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js';
|
||||
import { detectType, getDiagramLoader } from './diagram-api/detectType.js';
|
||||
import { UnknownDiagramError } from './errors.js';
|
||||
import { encodeEntities } from './utils.js';
|
||||
|
||||
import type { DetailedError } from './utils.js';
|
||||
import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js';
|
||||
|
||||
@@ -15,51 +13,45 @@ export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?:
|
||||
* @privateRemarks This is exported as part of the public mermaidAPI.
|
||||
*/
|
||||
export class Diagram {
|
||||
type = 'graph';
|
||||
parser: DiagramDefinition['parser'];
|
||||
renderer: DiagramDefinition['renderer'];
|
||||
db: DiagramDefinition['db'];
|
||||
private init?: DiagramDefinition['init'];
|
||||
|
||||
private detectError?: UnknownDiagramError;
|
||||
constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) {
|
||||
this.text = encodeEntities(text);
|
||||
this.text += '\n';
|
||||
const cnf = configApi.getConfig();
|
||||
try {
|
||||
this.type = detectType(text, cnf);
|
||||
} catch (e) {
|
||||
this.type = 'error';
|
||||
this.detectError = e as UnknownDiagramError;
|
||||
}
|
||||
const diagram = getDiagram(this.type);
|
||||
log.debug('Type ' + this.type);
|
||||
// Setup diagram
|
||||
this.db = diagram.db;
|
||||
this.renderer = diagram.renderer;
|
||||
this.parser = diagram.parser;
|
||||
if (this.parser.parser) {
|
||||
// The parser.parser.yy is only present in JISON parsers. So, we'll only set if required.
|
||||
this.parser.parser.yy = this.db;
|
||||
}
|
||||
this.init = diagram.init;
|
||||
this.parse();
|
||||
}
|
||||
|
||||
parse() {
|
||||
if (this.detectError) {
|
||||
throw this.detectError;
|
||||
}
|
||||
this.db.clear?.();
|
||||
public static async fromText(text: string, metadata: Pick<DiagramMetadata, 'title'> = {}) {
|
||||
const config = configApi.getConfig();
|
||||
this.init?.(config);
|
||||
const type = detectType(text, config);
|
||||
text = encodeEntities(text) + '\n';
|
||||
try {
|
||||
getDiagram(type);
|
||||
} catch (e) {
|
||||
const loader = getDiagramLoader(type);
|
||||
if (!loader) {
|
||||
throw new UnknownDiagramError(`Diagram ${type} not found.`);
|
||||
}
|
||||
// Diagram not available, loading it.
|
||||
// new diagram will try getDiagram again and if fails then it is a valid throw
|
||||
const { id, diagram } = await loader();
|
||||
registerDiagram(id, diagram);
|
||||
}
|
||||
const { db, parser, renderer, init } = getDiagram(type);
|
||||
if (parser.parser) {
|
||||
// The parser.parser.yy is only present in JISON parsers. So, we'll only set if required.
|
||||
parser.parser.yy = db;
|
||||
}
|
||||
db.clear?.();
|
||||
init?.(config);
|
||||
// This block was added for legacy compatibility. Use frontmatter instead of adding more special cases.
|
||||
if (this.metadata.title) {
|
||||
this.db.setDiagramTitle?.(this.metadata.title);
|
||||
if (metadata.title) {
|
||||
db.setDiagramTitle?.(metadata.title);
|
||||
}
|
||||
this.parser.parse(this.text);
|
||||
await parser.parse(text);
|
||||
return new Diagram(type, text, db, parser, renderer);
|
||||
}
|
||||
|
||||
private constructor(
|
||||
public type: string,
|
||||
public text: string,
|
||||
public db: DiagramDefinition['db'],
|
||||
public parser: DiagramDefinition['parser'],
|
||||
public renderer: DiagramDefinition['renderer']
|
||||
) {}
|
||||
|
||||
async render(id: string, version: string) {
|
||||
await this.renderer.draw(this.text, id, version, this);
|
||||
}
|
||||
@@ -72,34 +64,3 @@ export class Diagram {
|
||||
return this.type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the text asynchronously and generate a Diagram object asynchronously.
|
||||
* **Warning:** This function may be changed in the future.
|
||||
* @alpha
|
||||
* @param text - The mermaid diagram definition.
|
||||
* @param metadata - Diagram metadata, defined in YAML.
|
||||
* @returns A the Promise of a Diagram object.
|
||||
* @throws {@link UnknownDiagramError} if the diagram type can not be found.
|
||||
* @privateRemarks This is exported as part of the public mermaidAPI.
|
||||
*/
|
||||
export const getDiagramFromText = async (
|
||||
text: string,
|
||||
metadata: Pick<DiagramMetadata, 'title'> = {}
|
||||
): Promise<Diagram> => {
|
||||
const type = detectType(text, configApi.getConfig());
|
||||
try {
|
||||
// Trying to find the diagram
|
||||
getDiagram(type);
|
||||
} catch (error) {
|
||||
const loader = getDiagramLoader(type);
|
||||
if (!loader) {
|
||||
throw new UnknownDiagramError(`Diagram ${type} not found.`);
|
||||
}
|
||||
// Diagram not available, loading it.
|
||||
// new diagram will try getDiagram again and if fails then it is a valid throw
|
||||
const { id, diagram } = await loader();
|
||||
registerDiagram(id, diagram);
|
||||
}
|
||||
return new Diagram(text, metadata);
|
||||
};
|
||||
|
@@ -2,12 +2,12 @@ import { detectType } from './detectType.js';
|
||||
import { getDiagram, registerDiagram } from './diagramAPI.js';
|
||||
import { addDiagrams } from './diagram-orchestration.js';
|
||||
import type { DiagramDetector } from './types.js';
|
||||
import { getDiagramFromText } from '../Diagram.js';
|
||||
import { Diagram } from '../Diagram.js';
|
||||
import { it, describe, expect, beforeAll } from 'vitest';
|
||||
|
||||
addDiagrams();
|
||||
beforeAll(async () => {
|
||||
await getDiagramFromText('sequenceDiagram');
|
||||
await Diagram.fromText('sequenceDiagram');
|
||||
});
|
||||
|
||||
describe('DiagramAPI', () => {
|
||||
|
@@ -121,7 +121,7 @@ export type DrawDefinition = (
|
||||
) => void | Promise<void>;
|
||||
|
||||
export interface ParserDefinition {
|
||||
parse: (text: string) => void;
|
||||
parse: (text: string) => void | Promise<void>;
|
||||
parser?: { yy: DiagramDB };
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { Diagram, getDiagramFromText } from './Diagram.js';
|
||||
import { Diagram } from './Diagram.js';
|
||||
import { addDetector } from './diagram-api/detectType.js';
|
||||
import { addDiagrams } from './diagram-api/diagram-orchestration.js';
|
||||
import type { DiagramLoader } from './diagram-api/types.js';
|
||||
@@ -30,10 +30,10 @@ const getDummyDiagram = (id: string, title?: string): Awaited<ReturnType<Diagram
|
||||
|
||||
describe('diagram detection', () => {
|
||||
test('should detect inbuilt diagrams', async () => {
|
||||
const graph = (await getDiagramFromText('graph TD; A-->B')) as Diagram;
|
||||
const graph = (await Diagram.fromText('graph TD; A-->B')) as Diagram;
|
||||
expect(graph).toBeInstanceOf(Diagram);
|
||||
expect(graph.type).toBe('flowchart-v2');
|
||||
const sequence = (await getDiagramFromText(
|
||||
const sequence = (await Diagram.fromText(
|
||||
'sequenceDiagram; Alice->>+John: Hello John, how are you?'
|
||||
)) as Diagram;
|
||||
expect(sequence).toBeInstanceOf(Diagram);
|
||||
@@ -46,7 +46,7 @@ describe('diagram detection', () => {
|
||||
(str) => str.startsWith('loki'),
|
||||
() => Promise.resolve(getDummyDiagram('loki'))
|
||||
);
|
||||
const diagram = await getDiagramFromText('loki TD; A-->B');
|
||||
const diagram = await Diagram.fromText('loki TD; A-->B');
|
||||
expect(diagram).toBeInstanceOf(Diagram);
|
||||
expect(diagram.type).toBe('loki');
|
||||
});
|
||||
@@ -58,19 +58,19 @@ describe('diagram detection', () => {
|
||||
(str) => str.startsWith('flowchart-elk'),
|
||||
() => Promise.resolve(getDummyDiagram('flowchart-elk', title))
|
||||
);
|
||||
const diagram = await getDiagramFromText('flowchart-elk TD; A-->B');
|
||||
const diagram = await Diagram.fromText('flowchart-elk TD; A-->B');
|
||||
expect(diagram).toBeInstanceOf(Diagram);
|
||||
expect(diagram.db.getDiagramTitle?.()).toBe(title);
|
||||
});
|
||||
|
||||
test('should throw the right error for incorrect diagram', async () => {
|
||||
await expect(getDiagramFromText('graph TD; A-->')).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
await expect(Diagram.fromText('graph TD; A-->')).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Parse error on line 2:
|
||||
graph TD; A-->
|
||||
--------------^
|
||||
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(Diagram.fromText('sequenceDiagram; A-->B')).rejects
|
||||
.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Parse error on line 1:
|
||||
...quenceDiagram; A-->B
|
||||
@@ -80,13 +80,13 @@ Expecting 'TXT', got 'NEWLINE'"
|
||||
});
|
||||
|
||||
test('should throw the right error for unregistered diagrams', async () => {
|
||||
await expect(getDiagramFromText('thor TD; A-->B')).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
await expect(Diagram.fromText('thor TD; A-->B')).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
'"No diagram type detected matching given configuration for text: thor TD; A-->B"'
|
||||
);
|
||||
});
|
||||
|
||||
test('should consider entity codes when present in diagram defination', async () => {
|
||||
const diagram = await getDiagramFromText(`sequenceDiagram
|
||||
const diagram = await Diagram.fromText(`sequenceDiagram
|
||||
A->>B: I #9829; you!
|
||||
B->>A: I #9829; you #infin; times more!`);
|
||||
// @ts-ignore: we need to add types for sequenceDb which will be done in separate PR
|
||||
|
@@ -1,31 +1,27 @@
|
||||
import { parser } from './infoParser.js';
|
||||
|
||||
describe('info', () => {
|
||||
it('should handle an info definition', () => {
|
||||
it('should handle an info definition', async () => {
|
||||
const str = `info`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).not.toThrow();
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
it('should handle an info definition with showInfo', () => {
|
||||
it('should handle an info definition with showInfo', async () => {
|
||||
const str = `info showInfo`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).not.toThrow();
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw because of unsupported info grammar', () => {
|
||||
it('should throw because of unsupported info grammar', async () => {
|
||||
const str = `info unsupported`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).toThrow('Parsing failed: unexpected character: ->u<- at offset: 5, skipped 11 characters.');
|
||||
await expect(parser.parse(str)).rejects.toThrow(
|
||||
'Parsing failed: unexpected character: ->u<- at offset: 5, skipped 11 characters.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw because of unsupported info grammar', () => {
|
||||
it('should throw because of unsupported info grammar', async () => {
|
||||
const str = `info unsupported`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).toThrow('Parsing failed: unexpected character: ->u<- at offset: 5, skipped 11 characters.');
|
||||
await expect(parser.parse(str)).rejects.toThrow(
|
||||
'Parsing failed: unexpected character: ->u<- at offset: 5, skipped 11 characters.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -1,12 +1,11 @@
|
||||
import type { Info } from '@mermaid-js/parser';
|
||||
import { parse } from '@mermaid-js/parser';
|
||||
|
||||
import { log } from '../../logger.js';
|
||||
import type { ParserDefinition } from '../../diagram-api/types.js';
|
||||
import { log } from '../../logger.js';
|
||||
|
||||
export const parser: ParserDefinition = {
|
||||
parse: (input: string): void => {
|
||||
const ast: Info = parse('info', input);
|
||||
parse: async (input: string): Promise<void> => {
|
||||
const ast: Info = await parse('info', input);
|
||||
log.debug(ast);
|
||||
},
|
||||
};
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { it, describe, expect } from 'vitest';
|
||||
import { db } from './db.js';
|
||||
import { parser } from './parser.js';
|
||||
|
||||
@@ -8,24 +9,20 @@ describe('packet diagrams', () => {
|
||||
clear();
|
||||
});
|
||||
|
||||
it('should handle a packet-beta definition', () => {
|
||||
it('should handle a packet-beta definition', async () => {
|
||||
const str = `packet-beta`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).not.toThrow();
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
expect(getPacket()).toMatchInlineSnapshot('[]');
|
||||
});
|
||||
|
||||
it('should handle diagram with data and title', () => {
|
||||
it('should handle diagram with data and title', async () => {
|
||||
const str = `packet-beta
|
||||
title Packet diagram
|
||||
accTitle: Packet accTitle
|
||||
accDescr: Packet accDescription
|
||||
0-10: "test"
|
||||
`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).not.toThrow();
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
expect(getDiagramTitle()).toMatchInlineSnapshot('"Packet diagram"');
|
||||
expect(getAccTitle()).toMatchInlineSnapshot('"Packet accTitle"');
|
||||
expect(getAccDescription()).toMatchInlineSnapshot('"Packet accDescription"');
|
||||
@@ -42,14 +39,12 @@ describe('packet diagrams', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle single bits', () => {
|
||||
it('should handle single bits', async () => {
|
||||
const str = `packet-beta
|
||||
0-10: "test"
|
||||
11: "single"
|
||||
`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).not.toThrow();
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
expect(getPacket()).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
@@ -68,14 +63,12 @@ describe('packet diagrams', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it('should split into multiple rows', () => {
|
||||
it('should split into multiple rows', async () => {
|
||||
const str = `packet-beta
|
||||
0-10: "test"
|
||||
11-90: "multiple"
|
||||
`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).not.toThrow();
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
expect(getPacket()).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
@@ -108,14 +101,12 @@ describe('packet diagrams', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it('should split into multiple rows when cut at exact length', () => {
|
||||
it('should split into multiple rows when cut at exact length', async () => {
|
||||
const str = `packet-beta
|
||||
0-16: "test"
|
||||
17-63: "multiple"
|
||||
`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).not.toThrow();
|
||||
await expect(parser.parse(str)).resolves.not.toThrow();
|
||||
expect(getPacket()).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
@@ -141,51 +132,43 @@ describe('packet diagrams', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it('should throw error if numbers are not continuous', () => {
|
||||
it('should throw error if numbers are not continuous', async () => {
|
||||
const str = `packet-beta
|
||||
0-16: "test"
|
||||
18-20: "error"
|
||||
`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
'"Packet block 18 - 20 is not contiguous. It should start from 17."'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if numbers are not continuous for single packets', () => {
|
||||
it('should throw error if numbers are not continuous for single packets', async () => {
|
||||
const str = `packet-beta
|
||||
0-16: "test"
|
||||
18: "error"
|
||||
`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
'"Packet block 18 - 18 is not contiguous. It should start from 17."'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if numbers are not continuous for single packets - 2', () => {
|
||||
it('should throw error if numbers are not continuous for single packets - 2', async () => {
|
||||
const str = `packet-beta
|
||||
0-16: "test"
|
||||
17: "good"
|
||||
19: "error"
|
||||
`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
'"Packet block 19 - 19 is not contiguous. It should start from 18."'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if end is less than start', () => {
|
||||
it('should throw error if end is less than start', async () => {
|
||||
const str = `packet-beta
|
||||
0-16: "test"
|
||||
25-20: "error"
|
||||
`;
|
||||
expect(() => {
|
||||
parser.parse(str);
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
'"Packet block 25 - 20 is invalid. End must be greater than start."'
|
||||
);
|
||||
});
|
||||
|
@@ -77,8 +77,8 @@ const getNextFittingBlock = (
|
||||
};
|
||||
|
||||
export const parser: ParserDefinition = {
|
||||
parse: (input: string): void => {
|
||||
const ast: Packet = parse('packet', input);
|
||||
parse: async (input: string): Promise<void> => {
|
||||
const ast: Packet = await parse('packet', input);
|
||||
log.debug(ast);
|
||||
populate(ast);
|
||||
},
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import { vi } from 'vitest';
|
||||
import { setSiteConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import mermaidAPI from '../../mermaidAPI.js';
|
||||
import { Diagram, getDiagramFromText } from '../../Diagram.js';
|
||||
import { Diagram } from '../../Diagram.js';
|
||||
import { addDiagrams } from '../../diagram-api/diagram-orchestration.js';
|
||||
|
||||
beforeAll(async () => {
|
||||
// Is required to load the sequence diagram
|
||||
await getDiagramFromText('sequenceDiagram');
|
||||
await Diagram.fromText('sequenceDiagram');
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -95,8 +95,8 @@ function addConf(conf, key, value) {
|
||||
let diagram;
|
||||
|
||||
describe('more than one sequence diagram', () => {
|
||||
it('should not have duplicated messages', () => {
|
||||
const diagram1 = new Diagram(`
|
||||
it('should not have duplicated messages', async () => {
|
||||
const diagram1 = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Bob-->Alice: I am good thanks!`);
|
||||
@@ -120,7 +120,7 @@ describe('more than one sequence diagram', () => {
|
||||
},
|
||||
]
|
||||
`);
|
||||
const diagram2 = new Diagram(`
|
||||
const diagram2 = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Bob-->Alice: I am good thanks!`);
|
||||
@@ -147,7 +147,7 @@ describe('more than one sequence diagram', () => {
|
||||
`);
|
||||
|
||||
// Add John actor
|
||||
const diagram3 = new Diagram(`
|
||||
const diagram3 = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
Alice->John:Hello John, how are you?
|
||||
John-->Alice: I am good thanks!`);
|
||||
@@ -176,8 +176,8 @@ describe('more than one sequence diagram', () => {
|
||||
});
|
||||
|
||||
describe('when parsing a sequenceDiagram', function () {
|
||||
beforeEach(function () {
|
||||
diagram = new Diagram(`
|
||||
beforeEach(async function () {
|
||||
diagram = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Note right of Bob: Bob thinks
|
||||
@@ -1613,7 +1613,7 @@ describe('when rendering a sequenceDiagram APA', function () {
|
||||
setSiteConfig({ logLevel: 5, sequence: conf });
|
||||
});
|
||||
let conf;
|
||||
beforeEach(function () {
|
||||
beforeEach(async function () {
|
||||
mermaidAPI.reset();
|
||||
|
||||
// });
|
||||
@@ -1632,7 +1632,7 @@ describe('when rendering a sequenceDiagram APA', function () {
|
||||
mirrorActors: false,
|
||||
};
|
||||
setSiteConfig({ logLevel: 5, sequence: conf });
|
||||
diagram = new Diagram(`
|
||||
diagram = await Diagram.fromText(`
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Note right of Bob: Bob thinks
|
||||
|
@@ -17,7 +17,7 @@ import { compile, serialize, stringify } from 'stylis';
|
||||
import { version } from '../package.json';
|
||||
import * as configApi from './config.js';
|
||||
import { addDiagrams } from './diagram-api/diagram-orchestration.js';
|
||||
import { Diagram, getDiagramFromText as getDiagramFromTextInternal } from './Diagram.js';
|
||||
import { Diagram } from './Diagram.js';
|
||||
import errorRenderer from './diagrams/error/errorRenderer.js';
|
||||
import { attachFunctions } from './interactionDb.js';
|
||||
import { log, setLogLevel } from './logger.js';
|
||||
@@ -422,9 +422,9 @@ const render = async function (
|
||||
let parseEncounteredException;
|
||||
|
||||
try {
|
||||
diag = await getDiagramFromText(text, { title: processed.title });
|
||||
diag = await Diagram.fromText(text, { title: processed.title });
|
||||
} catch (error) {
|
||||
diag = new Diagram('error');
|
||||
diag = await Diagram.fromText('error');
|
||||
parseEncounteredException = error;
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ function initialize(options: MermaidConfig = {}) {
|
||||
|
||||
const getDiagramFromText = (text: string, metadata: Pick<DiagramMetadata, 'title'> = {}) => {
|
||||
const { code } = preprocessDiagram(text);
|
||||
return getDiagramFromTextInternal(code, metadata);
|
||||
return Diagram.fromText(code, metadata);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1,38 +1,41 @@
|
||||
import type { LangiumParser, ParseResult } from 'langium';
|
||||
|
||||
import type { Info, Packet, Pie } from './index.js';
|
||||
import { createInfoServices, createPacketServices, createPieServices } from './language/index.js';
|
||||
|
||||
export type DiagramAST = Info | Packet | Pie;
|
||||
|
||||
const parsers: Record<string, LangiumParser> = {};
|
||||
const initializers = {
|
||||
info: () => {
|
||||
// Will have to make parse async to use this. Can try later...
|
||||
// const { createInfoServices } = await import('./language/info/index.js');
|
||||
parsers['info'] = createInfoServices().Info.parser.LangiumParser;
|
||||
info: async () => {
|
||||
const { createInfoServices } = await import('./language/info/index.js');
|
||||
const parser = createInfoServices().Info.parser.LangiumParser;
|
||||
parsers['info'] = parser;
|
||||
},
|
||||
packet: () => {
|
||||
parsers['packet'] = createPacketServices().Packet.parser.LangiumParser;
|
||||
packet: async () => {
|
||||
const { createPacketServices } = await import('./language/packet/index.js');
|
||||
const parser = createPacketServices().Packet.parser.LangiumParser;
|
||||
parsers['packet'] = parser;
|
||||
},
|
||||
pie: () => {
|
||||
parsers['pie'] = createPieServices().Pie.parser.LangiumParser;
|
||||
pie: async () => {
|
||||
const { createPieServices } = await import('./language/pie/index.js');
|
||||
const parser = createPieServices().Pie.parser.LangiumParser;
|
||||
parsers['pie'] = parser;
|
||||
},
|
||||
} as const;
|
||||
|
||||
export function parse(diagramType: 'info', text: string): Info;
|
||||
export function parse(diagramType: 'packet', text: string): Packet;
|
||||
export function parse(diagramType: 'pie', text: string): Pie;
|
||||
export function parse<T extends DiagramAST>(
|
||||
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: 'pie', text: string): Promise<Pie>;
|
||||
export async function parse<T extends DiagramAST>(
|
||||
diagramType: keyof typeof initializers,
|
||||
text: string
|
||||
): T {
|
||||
): Promise<T> {
|
||||
const initializer = initializers[diagramType];
|
||||
if (!initializer) {
|
||||
throw new Error(`Unknown diagram type: ${diagramType}`);
|
||||
}
|
||||
if (!parsers[diagramType]) {
|
||||
initializer();
|
||||
await initializer();
|
||||
}
|
||||
const parser: LangiumParser = parsers[diagramType];
|
||||
const result: ParseResult<T> = parser.parse<T>(text);
|
||||
|
Reference in New Issue
Block a user