diff --git a/packages/mermaid/src/Diagram.ts b/packages/mermaid/src/Diagram.ts index 13fd3232b..1d4793bf0 100644 --- a/packages/mermaid/src/Diagram.ts +++ b/packages/mermaid/src/Diagram.ts @@ -50,7 +50,9 @@ export class Diagram { this.parser.parse = (text: string) => originalParse(cleanupComments(extractFrontMatter(text, this.db))); - this.parser.parser.yy = this.db; + if (this.parser.parser?.yy) { + this.parser.parser.yy = this.db; + } this.init = diagram.init; this.parse(); } diff --git a/packages/mermaid/src/diagram-api/types.ts b/packages/mermaid/src/diagram-api/types.ts index 100b92e87..6da97147a 100644 --- a/packages/mermaid/src/diagram-api/types.ts +++ b/packages/mermaid/src/diagram-api/types.ts @@ -72,7 +72,7 @@ export type DrawDefinition = ( export interface ParserDefinition { parse: (text: string) => void; - parser: { yy: DiagramDB }; + parser?: { yy: DiagramDB }; } /** diff --git a/packages/mermaid/src/diagrams/info/info.spec.ts b/packages/mermaid/src/diagrams/info/info.spec.ts index 22fb5afdc..c3d1f60e7 100644 --- a/packages/mermaid/src/diagrams/info/info.spec.ts +++ b/packages/mermaid/src/diagrams/info/info.spec.ts @@ -1,11 +1,10 @@ -import { parse } from './infoParser.js'; -import { db } from './infoDb.js'; +import { parser } from './infoParser.js'; describe('info', () => { it('should handle an info definition', () => { const str = `info`; expect(() => { - parse(str); + parser.parse(str); }).not.toThrow(); }); }); diff --git a/packages/mermaid/src/diagrams/info/infoDiagram.ts b/packages/mermaid/src/diagrams/info/infoDiagram.ts index f65fa3d7f..442616490 100644 --- a/packages/mermaid/src/diagrams/info/infoDiagram.ts +++ b/packages/mermaid/src/diagrams/info/infoDiagram.ts @@ -1,10 +1,10 @@ import type { DiagramDefinition } from '../../diagram-api/types.js'; -import { parse } from './infoParser.js'; +import { parser } from './infoParser.js'; import { db } from './infoDb.js'; import { renderer } from './infoRenderer.js'; export const diagram: DiagramDefinition = { - parser: { parse, parser: { yy: {} } }, + parser, db, renderer, }; diff --git a/packages/mermaid/src/diagrams/info/infoParser.ts b/packages/mermaid/src/diagrams/info/infoParser.ts index e73b044df..09b63001e 100644 --- a/packages/mermaid/src/diagrams/info/infoParser.ts +++ b/packages/mermaid/src/diagrams/info/infoParser.ts @@ -1,20 +1,10 @@ -import type { Info, InfoServices } from 'mermaid-parser'; -import { createInfoServices } from 'mermaid-parser'; - +import { parse, Info } from 'mermaid-parser'; import { log } from '../../logger.js'; +import { ParserDefinition } from '../../diagram-api/types.js'; -const services: InfoServices = createInfoServices().Info; -const langiumParser = services.parser.LangiumParser; - -export function parse(input: string): void { - const result = langiumParser.parse(input); - if (result.parserErrors.length > 0 || result.lexerErrors.length > 0) { - const parserErrors = result.parserErrors.map((parseError) => parseError); - const lexerErrors = result.lexerErrors.map((lexerError) => lexerError); - log.error( - { parserErrors: parserErrors, lexerErrors: lexerErrors }, - 'Error parsing info diagram' - ); - throw new Error(`Parser errors: ${parserErrors}\nLex errors: ${lexerErrors}`); - } -} +export const parser: ParserDefinition = { + parse: (input: string): void => { + const result = parse('info', input); + log.debug({ result }); + }, +}; diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts index 949d67519..67ab30aae 100644 --- a/packages/parser/src/index.ts +++ b/packages/parser/src/index.ts @@ -1 +1,43 @@ -export * from './language/index.js'; +import type { AstNode, LangiumParser, LangiumServices, ParseResult } from 'langium'; +import { createInfoServices } from './language/info/index.js'; +// Cache for services, can remove if not required. +const services: Record = {}; + +const initializers = { + info: () => { + // Will have to make parse async to use this. Can try later... + // const { createInfoServices } = await import('./language/info/index.js'); + const service = createInfoServices().Info; + services['info'] = { + service, + parser: service.parser.LangiumParser, + }; + }, +} as const; + +export const parse = ( + diagramType: keyof typeof initializers, + text: string +) => { + const initializer = initializers[diagramType]; + if (!initializer) { + throw new Error(`Unknown diagram type: ${diagramType}`); + } + if (!services[diagramType]) { + initializer(); + } + const { parser } = services[diagramType]; + const result = parser.parse(text); + if (result.lexerErrors.length > 0 || result.parserErrors.length > 0) { + throw new MermaidParseError(result); + } + return result; +}; + +export class MermaidParseError extends Error { + constructor({ lexerErrors, parserErrors }: ParseResult) { + super(`Parsing failed: ${lexerErrors} ${parserErrors}`); + } +} + +export { Info } from './language/index.js';