/
Diagram.ts
112 lines (105 loc) · 3.19 KB
/
Diagram.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import * as configApi from './config';
import { log } from './logger';
import { getDiagram, registerDiagram } from './diagram-api/diagramAPI';
import { detectType, getDiagramLoader } from './diagram-api/detectType';
import { isDetailedError } from './utils';
export class Diagram {
type = 'graph';
parser;
renderer;
db;
private detectTypeFailed = false;
// eslint-disable-next-line @typescript-eslint/ban-types
constructor(public txt: string, parseError?: Function) {
const cnf = configApi.getConfig();
this.txt = txt;
try {
this.type = detectType(txt, cnf);
} catch (e) {
this.handleError(e, parseError);
this.type = 'error';
this.detectTypeFailed = true;
}
const diagram = getDiagram(this.type);
log.debug('Type ' + this.type);
// Setup diagram
this.db = diagram.db;
this.db.clear?.();
this.renderer = diagram.renderer;
this.parser = diagram.parser;
this.parser.parser.yy = this.db;
if (diagram.init) {
diagram.init(cnf);
log.debug('Initialized diagram ' + this.type, cnf);
}
this.txt += '\n';
this.parse(this.txt, parseError);
}
// eslint-disable-next-line @typescript-eslint/ban-types
parse(text: string, parseError?: Function): boolean {
if (this.detectTypeFailed) {
return false;
}
try {
text = text + '\n';
this.db.clear();
this.parser.parse(text);
return true;
} catch (error) {
this.handleError(error, parseError);
}
return false;
}
// eslint-disable-next-line @typescript-eslint/ban-types
handleError(error: unknown, parseError?: Function) {
// Is this the correct way to access mermiad's parseError()
// method ? (or global.mermaid.parseError()) ?
if (parseError) {
if (isDetailedError(error)) {
// handle case where error string and hash were
// wrapped in object like`const error = { str, hash };`
parseError(error.str, error.hash);
} else {
// assume it is just error string and pass it on
parseError(error);
}
} else {
// No mermaid.parseError() handler defined, so re-throw it
throw error;
}
}
getParser() {
return this.parser;
}
getType() {
return this.type;
}
}
export const getDiagramFromText = (
txt: string,
// eslint-disable-next-line @typescript-eslint/ban-types
parseError?: Function
): Diagram | Promise<Diagram> => {
const type = detectType(txt, configApi.getConfig());
try {
// Trying to find the diagram
getDiagram(type);
return new Diagram(txt, parseError);
} catch (error) {
const loader = getDiagramLoader(type);
if (!loader) {
throw new Error(`Diagram ${type} not found.`);
}
// TODO: Uncomment for v10
// // Diagram not available, loading it
// const { diagram } = await loader();
// registerDiagram(type, diagram, undefined, diagram.injectUtils);
// // new diagram will try getDiagram again and if fails then it is a valid throw
return loader().then(({ diagram }) => {
registerDiagram(type, diagram, undefined, diagram.injectUtils);
return new Diagram(txt, parseError);
});
}
// return new Diagram(txt, parseError);
};
export default Diagram;