mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-02-04 07:13:25 +08:00
fix: Optimize diagram loading
This commit is contained in:
parent
069437842b
commit
3698b30809
@ -11,17 +11,13 @@ import Diagram from '../Diagram';
|
|||||||
// Normally, we could just do the following to get the original `parse()`
|
// Normally, we could just do the following to get the original `parse()`
|
||||||
// implementation, however, requireActual returns a promise and it's not documented how to use withing mock file.
|
// implementation, however, requireActual returns a promise and it's not documented how to use withing mock file.
|
||||||
|
|
||||||
let hasLoadedDiagrams = false;
|
|
||||||
/**
|
/**
|
||||||
* @param text
|
* @param text
|
||||||
* @param parseError
|
* @param parseError
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
function parse(text: string, parseError?: Function): boolean {
|
function parse(text: string, parseError?: Function): boolean {
|
||||||
if (!hasLoadedDiagrams) {
|
addDiagrams();
|
||||||
addDiagrams();
|
|
||||||
hasLoadedDiagrams = true;
|
|
||||||
}
|
|
||||||
const diagram = new Diagram(text, parseError);
|
const diagram = new Diagram(text, parseError);
|
||||||
return diagram.parse(text, parseError);
|
return diagram.parse(text, parseError);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { MermaidConfig } from '../config.type';
|
import { MermaidConfig } from '../config.type';
|
||||||
|
import { log } from '../logger';
|
||||||
import { DetectorRecord, DiagramDetector, DiagramLoader } from './types';
|
import { DetectorRecord, DiagramDetector, DiagramLoader } from './types';
|
||||||
|
|
||||||
const directive =
|
const directive =
|
||||||
@ -47,6 +48,7 @@ export const addDetector = (key: string, detector: DiagramDetector, loader?: Dia
|
|||||||
throw new Error(`Detector with key ${key} already exists`);
|
throw new Error(`Detector with key ${key} already exists`);
|
||||||
}
|
}
|
||||||
detectors[key] = { detector, loader };
|
detectors[key] = { detector, loader };
|
||||||
|
log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDiagramLoader = (key: string) => detectors[key].loader;
|
export const getDiagramLoader = (key: string) => detectors[key].loader;
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
import { registerDiagram, registerDetector } from './diagramAPI';
|
import { registerDiagram } from './diagramAPI';
|
||||||
import { DiagramDefinition, DiagramDetector } from './types';
|
|
||||||
|
|
||||||
// // @ts-ignore: TODO Fix ts errors
|
|
||||||
// import mindmapParser from '../diagrams/mindmap/parser/mindmap';
|
|
||||||
// import * as mindmapDb from '../diagrams/mindmap/mindmapDb';
|
|
||||||
// import { mindmapDetector } from '../diagrams/mindmap/mindmapDetector';
|
|
||||||
// import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer';
|
|
||||||
// import mindmapStyles from '../diagrams/mindmap/styles';
|
|
||||||
|
|
||||||
// @ts-ignore: TODO Fix ts errors
|
// @ts-ignore: TODO Fix ts errors
|
||||||
import gitGraphParser from '../diagrams/git/parser/gitGraph';
|
import gitGraphParser from '../diagrams/git/parser/gitGraph';
|
||||||
@ -102,17 +94,15 @@ import { setConfig } from '../config';
|
|||||||
import errorRenderer from '../diagrams/error/errorRenderer';
|
import errorRenderer from '../diagrams/error/errorRenderer';
|
||||||
import errorStyles from '../diagrams/error/styles';
|
import errorStyles from '../diagrams/error/styles';
|
||||||
|
|
||||||
const registerDiagramAndDetector = (
|
let hasLoadedDiagrams = false;
|
||||||
id: string,
|
|
||||||
diagram: DiagramDefinition,
|
|
||||||
detector: DiagramDetector
|
|
||||||
) => {
|
|
||||||
registerDiagram(id, diagram);
|
|
||||||
registerDetector(id, detector);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const addDiagrams = () => {
|
export const addDiagrams = () => {
|
||||||
registerDiagramAndDetector(
|
if (hasLoadedDiagrams) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// This is added here to avoid race-conditions.
|
||||||
|
// We could optimize the loading logic somehow.
|
||||||
|
hasLoadedDiagrams = true;
|
||||||
|
registerDiagram(
|
||||||
'error',
|
'error',
|
||||||
// Special diagram with error messages but setup as a regular diagram
|
// Special diagram with error messages but setup as a regular diagram
|
||||||
{
|
{
|
||||||
@ -136,7 +126,7 @@ export const addDiagrams = () => {
|
|||||||
(text) => text.toLowerCase().trim() === 'error'
|
(text) => text.toLowerCase().trim() === 'error'
|
||||||
);
|
);
|
||||||
|
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'c4',
|
'c4',
|
||||||
{
|
{
|
||||||
parser: c4Parser,
|
parser: c4Parser,
|
||||||
@ -149,7 +139,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
c4Detector
|
c4Detector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'class',
|
'class',
|
||||||
{
|
{
|
||||||
parser: classParser,
|
parser: classParser,
|
||||||
@ -166,7 +156,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
classDetector
|
classDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'classDiagram',
|
'classDiagram',
|
||||||
{
|
{
|
||||||
parser: classParser,
|
parser: classParser,
|
||||||
@ -183,7 +173,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
classDetectorV2
|
classDetectorV2
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'er',
|
'er',
|
||||||
{
|
{
|
||||||
parser: erParser,
|
parser: erParser,
|
||||||
@ -193,7 +183,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
erDetector
|
erDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'gantt',
|
'gantt',
|
||||||
{
|
{
|
||||||
parser: ganttParser,
|
parser: ganttParser,
|
||||||
@ -203,7 +193,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
ganttDetector
|
ganttDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'info',
|
'info',
|
||||||
{
|
{
|
||||||
parser: infoParser,
|
parser: infoParser,
|
||||||
@ -213,7 +203,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
infoDetector
|
infoDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'pie',
|
'pie',
|
||||||
{
|
{
|
||||||
parser: pieParser,
|
parser: pieParser,
|
||||||
@ -223,7 +213,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
pieDetector
|
pieDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'requirement',
|
'requirement',
|
||||||
{
|
{
|
||||||
parser: requirementParser,
|
parser: requirementParser,
|
||||||
@ -233,7 +223,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
requirementDetector
|
requirementDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'sequence',
|
'sequence',
|
||||||
{
|
{
|
||||||
parser: sequenceParser,
|
parser: sequenceParser,
|
||||||
@ -256,7 +246,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
sequenceDetector
|
sequenceDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'state',
|
'state',
|
||||||
{
|
{
|
||||||
parser: stateParser,
|
parser: stateParser,
|
||||||
@ -273,7 +263,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
stateDetector
|
stateDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'stateDiagram',
|
'stateDiagram',
|
||||||
{
|
{
|
||||||
parser: stateParser,
|
parser: stateParser,
|
||||||
@ -290,7 +280,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
stateDetectorV2
|
stateDetectorV2
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'journey',
|
'journey',
|
||||||
{
|
{
|
||||||
parser: journeyParser,
|
parser: journeyParser,
|
||||||
@ -305,7 +295,7 @@ export const addDiagrams = () => {
|
|||||||
journeyDetector
|
journeyDetector
|
||||||
);
|
);
|
||||||
|
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'flowchart',
|
'flowchart',
|
||||||
{
|
{
|
||||||
parser: flowParser,
|
parser: flowParser,
|
||||||
@ -325,7 +315,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
flowDetector
|
flowDetector
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'flowchart-v2',
|
'flowchart-v2',
|
||||||
{
|
{
|
||||||
parser: flowParser,
|
parser: flowParser,
|
||||||
@ -346,14 +336,9 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
flowDetectorV2
|
flowDetectorV2
|
||||||
);
|
);
|
||||||
registerDiagramAndDetector(
|
registerDiagram(
|
||||||
'gitGraph',
|
'gitGraph',
|
||||||
{ parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles },
|
{ parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles },
|
||||||
gitGraphDetector
|
gitGraphDetector
|
||||||
);
|
);
|
||||||
// registerDiagram(
|
|
||||||
// 'mindmap',
|
|
||||||
// { parser: mindmapParser, db: mindmapDb, renderer: mindmapRenderer, styles: mindmapStyles },
|
|
||||||
// mindmapDetector
|
|
||||||
// );
|
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { detectType } from './detectType';
|
import { detectType } from './detectType';
|
||||||
import { getDiagram, registerDiagram, registerDetector } from './diagramAPI';
|
import { getDiagram, registerDiagram } from './diagramAPI';
|
||||||
import { addDiagrams } from './diagram-orchestration';
|
import { addDiagrams } from './diagram-orchestration';
|
||||||
import { DiagramDetector } from './types';
|
import { DiagramDetector } from './types';
|
||||||
|
|
||||||
@ -22,13 +22,16 @@ describe('DiagramAPI', () => {
|
|||||||
const detector: DiagramDetector = (str: string) => {
|
const detector: DiagramDetector = (str: string) => {
|
||||||
return str.match('loki') !== null;
|
return str.match('loki') !== null;
|
||||||
};
|
};
|
||||||
registerDetector('loki', detector);
|
registerDiagram(
|
||||||
registerDiagram('loki', {
|
'loki',
|
||||||
db: {},
|
{
|
||||||
parser: {},
|
db: {},
|
||||||
renderer: {},
|
parser: {},
|
||||||
styles: {},
|
renderer: {},
|
||||||
});
|
styles: {},
|
||||||
|
},
|
||||||
|
detector
|
||||||
|
);
|
||||||
expect(getDiagram('loki')).not.toBeNull();
|
expect(getDiagram('loki')).not.toBeNull();
|
||||||
expect(detectType('loki diagram')).toBe('loki');
|
expect(detectType('loki diagram')).toBe('loki');
|
||||||
});
|
});
|
||||||
|
@ -23,13 +23,10 @@ export interface Detectors {
|
|||||||
[key: string]: DiagramDetector;
|
[key: string]: DiagramDetector;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const registerDetector = (id: string, detector: DiagramDetector) => {
|
|
||||||
addDetector(id, detector, null);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const registerDiagram = (
|
export const registerDiagram = (
|
||||||
id: string,
|
id: string,
|
||||||
diagram: DiagramDefinition,
|
diagram: DiagramDefinition,
|
||||||
|
detector: DiagramDetector,
|
||||||
callback?: (
|
callback?: (
|
||||||
_log: any,
|
_log: any,
|
||||||
_setLogLevel: any,
|
_setLogLevel: any,
|
||||||
@ -39,9 +36,10 @@ export const registerDiagram = (
|
|||||||
) => void
|
) => void
|
||||||
) => {
|
) => {
|
||||||
if (diagrams[id]) {
|
if (diagrams[id]) {
|
||||||
log.warn(`Diagram ${id} already registered.`);
|
throw new Error(`Diagram ${id} already registered.`);
|
||||||
}
|
}
|
||||||
diagrams[id] = diagram;
|
diagrams[id] = diagram;
|
||||||
|
addDetector(id, detector);
|
||||||
addStylesForDiagram(id, diagram.styles);
|
addStylesForDiagram(id, diagram.styles);
|
||||||
if (typeof callback !== 'undefined') {
|
if (typeof callback !== 'undefined') {
|
||||||
callback(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox);
|
callback(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox);
|
||||||
|
@ -53,7 +53,6 @@ const init = async function (
|
|||||||
callback?: Function
|
callback?: Function
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
log.info('Detectors in init', mermaid.detectors); // eslint-disable-line
|
|
||||||
const conf = mermaidAPI.getConfig();
|
const conf = mermaidAPI.getConfig();
|
||||||
if (conf?.lazyLoadedDiagrams && conf.lazyLoadedDiagrams.length > 0) {
|
if (conf?.lazyLoadedDiagrams && conf.lazyLoadedDiagrams.length > 0) {
|
||||||
// Load all lazy loaded diagrams in parallel
|
// Load all lazy loaded diagrams in parallel
|
||||||
@ -64,9 +63,6 @@ const init = async function (
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
mermaid.detectors.forEach(({ id, detector, path }) => {
|
|
||||||
addDetector(id, detector, path);
|
|
||||||
});
|
|
||||||
await initThrowsErrors(config, nodes, callback);
|
await initThrowsErrors(config, nodes, callback);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.warn('Syntax Error rendering');
|
log.warn('Syntax Error rendering');
|
||||||
@ -251,7 +247,6 @@ const mermaid: {
|
|||||||
contentLoaded: typeof contentLoaded;
|
contentLoaded: typeof contentLoaded;
|
||||||
setParseErrorHandler: typeof setParseErrorHandler;
|
setParseErrorHandler: typeof setParseErrorHandler;
|
||||||
// Array of functions to use for detecting diagram types
|
// Array of functions to use for detecting diagram types
|
||||||
detectors: Array<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
||||||
connectDiagram: (id: string, diagram: DiagramDefinition, callback: (id: string) => void) => void;
|
connectDiagram: (id: string, diagram: DiagramDefinition, callback: (id: string) => void) => void;
|
||||||
} = {
|
} = {
|
||||||
startOnLoad: true,
|
startOnLoad: true,
|
||||||
@ -265,7 +260,6 @@ const mermaid: {
|
|||||||
parseError: undefined,
|
parseError: undefined,
|
||||||
contentLoaded,
|
contentLoaded,
|
||||||
setParseErrorHandler,
|
setParseErrorHandler,
|
||||||
detectors: [],
|
|
||||||
connectDiagram: connectDiagram,
|
connectDiagram: connectDiagram,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ import { compile, serialize, stringify } from 'stylis';
|
|||||||
import pkg from '../package.json';
|
import pkg from '../package.json';
|
||||||
import * as configApi from './config';
|
import * as configApi from './config';
|
||||||
import { addDiagrams } from './diagram-api/diagram-orchestration';
|
import { addDiagrams } from './diagram-api/diagram-orchestration';
|
||||||
import { addDetector } from './diagram-api/detectType';
|
|
||||||
import classDb from './diagrams/class/classDb';
|
import classDb from './diagrams/class/classDb';
|
||||||
import flowDb from './diagrams/flowchart/flowDb';
|
import flowDb from './diagrams/flowchart/flowDb';
|
||||||
import flowRenderer from './diagrams/flowchart/flowRenderer';
|
import flowRenderer from './diagrams/flowchart/flowRenderer';
|
||||||
@ -34,18 +33,13 @@ import DOMPurify from 'dompurify';
|
|||||||
import { MermaidConfig } from './config.type';
|
import { MermaidConfig } from './config.type';
|
||||||
import { evaluate } from './diagrams/common/common';
|
import { evaluate } from './diagrams/common/common';
|
||||||
|
|
||||||
let hasLoadedDiagrams = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param text
|
* @param text
|
||||||
* @param parseError
|
* @param parseError
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
function parse(text: string, parseError?: Function): boolean {
|
function parse(text: string, parseError?: Function): boolean {
|
||||||
if (!hasLoadedDiagrams) {
|
addDiagrams();
|
||||||
addDiagrams();
|
|
||||||
hasLoadedDiagrams = true;
|
|
||||||
}
|
|
||||||
const diagram = new Diagram(text, parseError);
|
const diagram = new Diagram(text, parseError);
|
||||||
return diagram.parse(text, parseError);
|
return diagram.parse(text, parseError);
|
||||||
}
|
}
|
||||||
@ -122,10 +116,7 @@ const render = async function (
|
|||||||
cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
|
cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
|
||||||
container?: Element
|
container?: Element
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!hasLoadedDiagrams) {
|
addDiagrams();
|
||||||
addDiagrams();
|
|
||||||
hasLoadedDiagrams = true;
|
|
||||||
}
|
|
||||||
configApi.reset();
|
configApi.reset();
|
||||||
text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;;
|
text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;;
|
||||||
const graphInit = utils.detectInit(text);
|
const graphInit = utils.detectInit(text);
|
||||||
@ -486,11 +477,7 @@ async function initialize(options: MermaidConfig) {
|
|||||||
typeof options === 'object' ? configApi.setSiteConfig(options) : configApi.getSiteConfig();
|
typeof options === 'object' ? configApi.setSiteConfig(options) : configApi.getSiteConfig();
|
||||||
|
|
||||||
setLogLevel(config.logLevel);
|
setLogLevel(config.logLevel);
|
||||||
|
addDiagrams();
|
||||||
if (!hasLoadedDiagrams) {
|
|
||||||
addDiagrams();
|
|
||||||
hasLoadedDiagrams = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mermaidAPI = Object.freeze({
|
export const mermaidAPI = Object.freeze({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user