fix: Optimize diagram loading

This commit is contained in:
Sidharth Vinod 2022-10-08 13:14:16 +08:00
parent 069437842b
commit 3698b30809
No known key found for this signature in database
GPG Key ID: FB5CCD378D3907CD
7 changed files with 44 additions and 79 deletions

View File

@ -11,17 +11,13 @@ import Diagram from '../Diagram';
// 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.
let hasLoadedDiagrams = false;
/**
* @param text
* @param parseError
*/
// eslint-disable-next-line @typescript-eslint/ban-types
function parse(text: string, parseError?: Function): boolean {
if (!hasLoadedDiagrams) {
addDiagrams();
hasLoadedDiagrams = true;
}
addDiagrams();
const diagram = new Diagram(text, parseError);
return diagram.parse(text, parseError);
}

View File

@ -1,4 +1,5 @@
import { MermaidConfig } from '../config.type';
import { log } from '../logger';
import { DetectorRecord, DiagramDetector, DiagramLoader } from './types';
const directive =
@ -47,6 +48,7 @@ export const addDetector = (key: string, detector: DiagramDetector, loader?: Dia
throw new Error(`Detector with key ${key} already exists`);
}
detectors[key] = { detector, loader };
log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`);
};
export const getDiagramLoader = (key: string) => detectors[key].loader;

View File

@ -1,12 +1,4 @@
import { registerDiagram, registerDetector } 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';
import { registerDiagram } from './diagramAPI';
// @ts-ignore: TODO Fix ts errors
import gitGraphParser from '../diagrams/git/parser/gitGraph';
@ -102,17 +94,15 @@ import { setConfig } from '../config';
import errorRenderer from '../diagrams/error/errorRenderer';
import errorStyles from '../diagrams/error/styles';
const registerDiagramAndDetector = (
id: string,
diagram: DiagramDefinition,
detector: DiagramDetector
) => {
registerDiagram(id, diagram);
registerDetector(id, detector);
};
let hasLoadedDiagrams = false;
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',
// Special diagram with error messages but setup as a regular diagram
{
@ -136,7 +126,7 @@ export const addDiagrams = () => {
(text) => text.toLowerCase().trim() === 'error'
);
registerDiagramAndDetector(
registerDiagram(
'c4',
{
parser: c4Parser,
@ -149,7 +139,7 @@ export const addDiagrams = () => {
},
c4Detector
);
registerDiagramAndDetector(
registerDiagram(
'class',
{
parser: classParser,
@ -166,7 +156,7 @@ export const addDiagrams = () => {
},
classDetector
);
registerDiagramAndDetector(
registerDiagram(
'classDiagram',
{
parser: classParser,
@ -183,7 +173,7 @@ export const addDiagrams = () => {
},
classDetectorV2
);
registerDiagramAndDetector(
registerDiagram(
'er',
{
parser: erParser,
@ -193,7 +183,7 @@ export const addDiagrams = () => {
},
erDetector
);
registerDiagramAndDetector(
registerDiagram(
'gantt',
{
parser: ganttParser,
@ -203,7 +193,7 @@ export const addDiagrams = () => {
},
ganttDetector
);
registerDiagramAndDetector(
registerDiagram(
'info',
{
parser: infoParser,
@ -213,7 +203,7 @@ export const addDiagrams = () => {
},
infoDetector
);
registerDiagramAndDetector(
registerDiagram(
'pie',
{
parser: pieParser,
@ -223,7 +213,7 @@ export const addDiagrams = () => {
},
pieDetector
);
registerDiagramAndDetector(
registerDiagram(
'requirement',
{
parser: requirementParser,
@ -233,7 +223,7 @@ export const addDiagrams = () => {
},
requirementDetector
);
registerDiagramAndDetector(
registerDiagram(
'sequence',
{
parser: sequenceParser,
@ -256,7 +246,7 @@ export const addDiagrams = () => {
},
sequenceDetector
);
registerDiagramAndDetector(
registerDiagram(
'state',
{
parser: stateParser,
@ -273,7 +263,7 @@ export const addDiagrams = () => {
},
stateDetector
);
registerDiagramAndDetector(
registerDiagram(
'stateDiagram',
{
parser: stateParser,
@ -290,7 +280,7 @@ export const addDiagrams = () => {
},
stateDetectorV2
);
registerDiagramAndDetector(
registerDiagram(
'journey',
{
parser: journeyParser,
@ -305,7 +295,7 @@ export const addDiagrams = () => {
journeyDetector
);
registerDiagramAndDetector(
registerDiagram(
'flowchart',
{
parser: flowParser,
@ -325,7 +315,7 @@ export const addDiagrams = () => {
},
flowDetector
);
registerDiagramAndDetector(
registerDiagram(
'flowchart-v2',
{
parser: flowParser,
@ -346,14 +336,9 @@ export const addDiagrams = () => {
},
flowDetectorV2
);
registerDiagramAndDetector(
registerDiagram(
'gitGraph',
{ parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles },
gitGraphDetector
);
// registerDiagram(
// 'mindmap',
// { parser: mindmapParser, db: mindmapDb, renderer: mindmapRenderer, styles: mindmapStyles },
// mindmapDetector
// );
};

View File

@ -1,5 +1,5 @@
import { detectType } from './detectType';
import { getDiagram, registerDiagram, registerDetector } from './diagramAPI';
import { getDiagram, registerDiagram } from './diagramAPI';
import { addDiagrams } from './diagram-orchestration';
import { DiagramDetector } from './types';
@ -22,13 +22,16 @@ describe('DiagramAPI', () => {
const detector: DiagramDetector = (str: string) => {
return str.match('loki') !== null;
};
registerDetector('loki', detector);
registerDiagram('loki', {
db: {},
parser: {},
renderer: {},
styles: {},
});
registerDiagram(
'loki',
{
db: {},
parser: {},
renderer: {},
styles: {},
},
detector
);
expect(getDiagram('loki')).not.toBeNull();
expect(detectType('loki diagram')).toBe('loki');
});

View File

@ -23,13 +23,10 @@ export interface Detectors {
[key: string]: DiagramDetector;
}
export const registerDetector = (id: string, detector: DiagramDetector) => {
addDetector(id, detector, null);
};
export const registerDiagram = (
id: string,
diagram: DiagramDefinition,
detector: DiagramDetector,
callback?: (
_log: any,
_setLogLevel: any,
@ -39,9 +36,10 @@ export const registerDiagram = (
) => void
) => {
if (diagrams[id]) {
log.warn(`Diagram ${id} already registered.`);
throw new Error(`Diagram ${id} already registered.`);
}
diagrams[id] = diagram;
addDetector(id, detector);
addStylesForDiagram(id, diagram.styles);
if (typeof callback !== 'undefined') {
callback(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox);

View File

@ -53,7 +53,6 @@ const init = async function (
callback?: Function
) {
try {
log.info('Detectors in init', mermaid.detectors); // eslint-disable-line
const conf = mermaidAPI.getConfig();
if (conf?.lazyLoadedDiagrams && conf.lazyLoadedDiagrams.length > 0) {
// 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);
} catch (e) {
log.warn('Syntax Error rendering');
@ -251,7 +247,6 @@ const mermaid: {
contentLoaded: typeof contentLoaded;
setParseErrorHandler: typeof setParseErrorHandler;
// 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;
} = {
startOnLoad: true,
@ -265,7 +260,6 @@ const mermaid: {
parseError: undefined,
contentLoaded,
setParseErrorHandler,
detectors: [],
connectDiagram: connectDiagram,
};

View File

@ -18,7 +18,6 @@ import { compile, serialize, stringify } from 'stylis';
import pkg from '../package.json';
import * as configApi from './config';
import { addDiagrams } from './diagram-api/diagram-orchestration';
import { addDetector } from './diagram-api/detectType';
import classDb from './diagrams/class/classDb';
import flowDb from './diagrams/flowchart/flowDb';
import flowRenderer from './diagrams/flowchart/flowRenderer';
@ -34,18 +33,13 @@ import DOMPurify from 'dompurify';
import { MermaidConfig } from './config.type';
import { evaluate } from './diagrams/common/common';
let hasLoadedDiagrams = false;
/**
* @param text
* @param parseError
*/
// eslint-disable-next-line @typescript-eslint/ban-types
function parse(text: string, parseError?: Function): boolean {
if (!hasLoadedDiagrams) {
addDiagrams();
hasLoadedDiagrams = true;
}
addDiagrams();
const diagram = new Diagram(text, parseError);
return diagram.parse(text, parseError);
}
@ -122,10 +116,7 @@ const render = async function (
cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
container?: Element
): Promise<void> {
if (!hasLoadedDiagrams) {
addDiagrams();
hasLoadedDiagrams = true;
}
addDiagrams();
configApi.reset();
text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;;
const graphInit = utils.detectInit(text);
@ -486,11 +477,7 @@ async function initialize(options: MermaidConfig) {
typeof options === 'object' ? configApi.setSiteConfig(options) : configApi.getSiteConfig();
setLogLevel(config.logLevel);
if (!hasLoadedDiagrams) {
addDiagrams();
hasLoadedDiagrams = true;
}
addDiagrams();
}
export const mermaidAPI = Object.freeze({