@nielspeter/eess-mermaid 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mermaid-js/create-mermaid-parser.d.ts +48 -0
- package/dist/mermaid-js/create-mermaid-parser.d.ts.map +1 -0
- package/dist/mermaid-js/create-mermaid-parser.js +438 -0
- package/dist/mermaid-js/create-mermaid-parser.js.map +1 -0
- package/dist/mermaid-js/mermaid-parser.d.ts +17 -0
- package/dist/mermaid-js/mermaid-parser.d.ts.map +1 -0
- package/dist/mermaid-js/mermaid-parser.js +19 -0
- package/dist/mermaid-js/mermaid-parser.js.map +1 -0
- package/dist/mermaid-js/mermaid-worker.mjs +144 -0
- package/dist/parser/diagram-kind.d.ts +16 -0
- package/dist/parser/diagram-kind.d.ts.map +1 -1
- package/dist/parser/diagram-kind.js +43 -14
- package/dist/parser/diagram-kind.js.map +1 -1
- package/dist/parser/mermaid-line-map.d.ts +36 -0
- package/dist/parser/mermaid-line-map.d.ts.map +1 -0
- package/dist/parser/mermaid-line-map.js +101 -0
- package/dist/parser/mermaid-line-map.js.map +1 -0
- package/package.json +19 -3
package/README.md
CHANGED
|
@@ -24,6 +24,34 @@ classes(d).that().haveStereotype('repository').should().haveNameEndingWith('Repo
|
|
|
24
24
|
|
|
25
25
|
The diagram is validated for internal consistency (valid class references, stereotypes, relationships) via the Langium grammar. Cross-validation against TypeScript code — binding a diagram to its implementation so either side drifting fails the build — ships as `diagramMatchesCode()` in [`@nielspeter/eess-crossvalidate`](https://www.npmjs.com/package/@nielspeter/eess-crossvalidate) (design history: [plan 0059](https://github.com/nielspeter/eess/blob/main/work/plans/completed/0059-cross-validation-eess-crossvalidate.md)).
|
|
26
26
|
|
|
27
|
+
## Does every Mermaid block parse?
|
|
28
|
+
|
|
29
|
+
`mermaidParser()` is Mermaid's own parser (the `mermaid` package GitHub renders with) for
|
|
30
|
+
[`@nielspeter/eess-md`](https://www.npmjs.com/package/@nielspeter/eess-md)'s `parseCodeBlocks`. It
|
|
31
|
+
says whether a block parses; `parseClassDiagram` above is eess's own grammar, used to bind a
|
|
32
|
+
diagram to code.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm i -D @nielspeter/eess-md mermaid@11 jsdom
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { corpus, parseCodeBlocks, codeBlocks } from '@nielspeter/eess-md'
|
|
40
|
+
import { mermaidParser } from '@nielspeter/eess-mermaid'
|
|
41
|
+
|
|
42
|
+
const parsed = await parseCodeBlocks(corpus({ roots: ['docs/**'] }), {
|
|
43
|
+
language: 'mermaid',
|
|
44
|
+
parser: mermaidParser(),
|
|
45
|
+
})
|
|
46
|
+
codeBlocks(parsed).should().parse().check()
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`mermaid` and `jsdom` are optional peers, about 179 MB installed (`mermaid` 83 MB, `jsdom`
|
|
50
|
+
8.3 MB), and load only inside a worker thread, so your process never gets a DOM. What it reports,
|
|
51
|
+
and its limits (a block with a trailing `%%` comment claims no line; `parse` is not `render`; the
|
|
52
|
+
canaries cover one kind per error shape), are in the
|
|
53
|
+
[guide](https://github.com/nielspeter/eess/blob/main/docs/mermaid.md#does-every-mermaid-block-parse).
|
|
54
|
+
|
|
27
55
|
## License
|
|
28
56
|
|
|
29
57
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export { defineConfig } from './cli/config.js';
|
|
|
27
27
|
export type { CliConfig } from './cli/config.js';
|
|
28
28
|
export { fromDiagram } from './bridge/from-diagram.js';
|
|
29
29
|
export type { BridgeOptions, BridgeRule, BridgeRuleAllowedEdge, BridgeRuleForbiddenEdge, BridgeRuleInheritance, BridgeOutput, } from './bridge/from-diagram.js';
|
|
30
|
+
export { mermaidParser } from './mermaid-js/mermaid-parser.js';
|
|
31
|
+
export type { MermaidParser, MermaidVerdict, MermaidCanary, } from './mermaid-js/create-mermaid-parser.js';
|
|
30
32
|
export { parseErDiagram } from './parser/parse-er-diagram.js';
|
|
31
33
|
export { diagramKind } from './parser/diagram-kind.js';
|
|
32
34
|
export { collectEntities, collectErRelationships } from './models/er-entity.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAA;AAC/B,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAClG,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC9E,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKlD,OAAO,EACL,eAAe,EACf,aAAa,EAMb,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACtE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAG/C,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAG3C,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAG1F,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAC5E,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAI7E,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC7E,YAAY,EACV,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAGvE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,YAAY,EACV,aAAa,EACb,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,YAAY,GACb,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC/E,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAA;AAC/B,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAClG,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAC9E,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKlD,OAAO,EACL,eAAe,EACf,aAAa,EAMb,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACtE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAG/C,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAG3C,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAG1F,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAC5E,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAI7E,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC7E,YAAY,EACV,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,8BAA8B,CAAA;AAGrC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAGvE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,YAAY,EACV,aAAa,EACb,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,YAAY,GACb,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,YAAY,EACV,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,uCAAuC,CAAA;AAG9C,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC/E,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,8 @@ export { validateReferences } from './parser/validate-diagram.js';
|
|
|
32
32
|
export { defineConfig } from './cli/config.js';
|
|
33
33
|
// Bridge to eess-ts
|
|
34
34
|
export { fromDiagram } from './bridge/from-diagram.js';
|
|
35
|
+
// Mermaid's own parser, for eess-md's parseCodeBlocks (plan 0413)
|
|
36
|
+
export { mermaidParser } from './mermaid-js/mermaid-parser.js';
|
|
35
37
|
// ER diagrams (plan 0069 Phase 3)
|
|
36
38
|
export { parseErDiagram } from './parser/parse-er-diagram.js';
|
|
37
39
|
// Plan 0214: the one lexer for a diagram's declared kind.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,cAAc,iBAAiB,CAAA;AAE/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAE9E,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAElD,iFAAiF;AACjF,8EAA8E;AAC9E,iEAAiE;AACjE,OAAO,EACL,eAAe,EACf,aAAa;AACb,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,uEAAuE;AACvE,WAAW;AACX,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAI/C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAE3C,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAE1F,oBAAoB;AACpB,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAE5E,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAE7E,aAAa;AACb,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAW7E,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AAGjE,oDAAoD;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAG9C,oBAAoB;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAUtD,kCAAkC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,0DAA0D;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,cAAc,iBAAiB,CAAA;AAE/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAE9E,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAElD,iFAAiF;AACjF,8EAA8E;AAC9E,iEAAiE;AACjE,OAAO,EACL,eAAe,EACf,aAAa;AACb,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,uEAAuE;AACvE,WAAW;AACX,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAI/C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAE3C,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAE1F,oBAAoB;AACpB,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAE5E,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAE7E,aAAa;AACb,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAW7E,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AAGjE,oDAAoD;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAG9C,oBAAoB;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAUtD,kEAAkE;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAO9D,kCAAkC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,0DAA0D;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan 0413: Mermaid's own parser, in a worker, in the shape of eess-md's code-block parser port
|
|
3
|
+
* (plan 0412). eess-mermaid matches that port by shape and imports nothing from eess-md.
|
|
4
|
+
*
|
|
5
|
+
* Internal: `mermaidParser()` is this with the worker beside it. Tests pass a copy of the worker in a
|
|
6
|
+
* scratch directory whose `node_modules` holds a stub `mermaid`, nothing, or the real packages. The
|
|
7
|
+
* package's `exports` has no deep path, so no rule file can name a module for it to run.
|
|
8
|
+
*
|
|
9
|
+
* The three types below mirror eess-md's `CodeBlockVerdict`, `CodeBlockCanary` and `CodeBlockParser`
|
|
10
|
+
* (`packages/md/src/model/code-block-parse.ts`): a change to the port changes both packages' API.
|
|
11
|
+
* eess-crossvalidate's port test assigns one to the other, so a drift fails its typecheck.
|
|
12
|
+
*/
|
|
13
|
+
/** What Mermaid says about one block, in eess-md's `CodeBlockVerdict` shape. */
|
|
14
|
+
export type MermaidVerdict = {
|
|
15
|
+
readonly outcome: 'valid';
|
|
16
|
+
} | {
|
|
17
|
+
readonly outcome: 'invalid';
|
|
18
|
+
readonly message: string;
|
|
19
|
+
/** 1-based, from the block's first body line; `null` when Mermaid's line cannot be trusted. */
|
|
20
|
+
readonly line: number | null;
|
|
21
|
+
readonly remedy: string;
|
|
22
|
+
} | {
|
|
23
|
+
readonly outcome: 'unrecognised';
|
|
24
|
+
readonly message: string;
|
|
25
|
+
readonly remedy: string;
|
|
26
|
+
};
|
|
27
|
+
/** A block Mermaid must reject, in eess-md's `CodeBlockCanary` shape. */
|
|
28
|
+
export interface MermaidCanary {
|
|
29
|
+
readonly text: string;
|
|
30
|
+
readonly expect: 'invalid' | 'unrecognised';
|
|
31
|
+
}
|
|
32
|
+
/** eess-md's `CodeBlockParser` shape, filled by Mermaid. */
|
|
33
|
+
export interface MermaidParser {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
/** The installed `mermaid`'s version, `'not installed'`, or `'unreadable'`. */
|
|
36
|
+
readonly version: string;
|
|
37
|
+
readonly canaries: readonly MermaidCanary[];
|
|
38
|
+
parse(texts: readonly string[], options: {
|
|
39
|
+
readonly signal: AbortSignal;
|
|
40
|
+
readonly budgetMs: number;
|
|
41
|
+
}): Promise<readonly MermaidVerdict[]>;
|
|
42
|
+
}
|
|
43
|
+
/** The parser, run from `workerUrl`. Never throws: a missing peer is reported by `parse`. */
|
|
44
|
+
export declare function createMermaidParser(options: {
|
|
45
|
+
/** The worker module to run: `mermaid-worker.mjs`, or a copy of it. */
|
|
46
|
+
readonly workerUrl: URL;
|
|
47
|
+
}): MermaidParser;
|
|
48
|
+
//# sourceMappingURL=create-mermaid-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-mermaid-parser.d.ts","sourceRoot":"","sources":["../../src/mermaid-js/create-mermaid-parser.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;GAWG;AAEH,gFAAgF;AAChF,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC7B;IACE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,+FAA+F;IAC/F,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,GACD;IAAE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3F,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,cAAc,CAAA;CAC5C;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;IAC3C,KAAK,CACH,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACnE,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAA;CACtC;AAkaD,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAC3C,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAA;CACxB,GAAG,aAAa,CAYhB"}
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { Worker } from 'node:worker_threads';
|
|
5
|
+
import { diagramPreamble } from '../parser/diagram-kind.js';
|
|
6
|
+
import { frontmatterYaml, hasTrailingComment, mermaidLineMap } from '../parser/mermaid-line-map.js';
|
|
7
|
+
/**
|
|
8
|
+
* Why the parser could not answer for the batch. eess-md reads `remedy` and `blockIndex` by shape
|
|
9
|
+
* (an index into `texts`, or `null`) and reports the instrument, naming the block when there is one.
|
|
10
|
+
*/
|
|
11
|
+
class MermaidParserFailure extends Error {
|
|
12
|
+
remedy;
|
|
13
|
+
blockIndex;
|
|
14
|
+
constructor(message, remedy, blockIndex) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.remedy = remedy;
|
|
17
|
+
this.blockIndex = blockIndex;
|
|
18
|
+
this.name = 'MermaidParserFailure';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** The version the line map's regexes were read from; the line canary checks they still hold. */
|
|
22
|
+
const LINE_MAP_MERMAID = '11.17.2';
|
|
23
|
+
const INSTALL = 'Install both peers: `npm i -D mermaid@11 jsdom`.';
|
|
24
|
+
/**
|
|
25
|
+
* One known-broken block per error shape. eess-md runs them before the corpus's blocks, so a
|
|
26
|
+
* `mermaid` that stopped throwing (a new major, a changed error shape, `suppressErrors`) is caught.
|
|
27
|
+
*/
|
|
28
|
+
const CANARIES = Object.freeze([
|
|
29
|
+
Object.freeze({ text: 'sequenceDiagram\n A->>B: hi\n A->>', expect: 'invalid' }),
|
|
30
|
+
Object.freeze({ text: 'packet-beta\n0-10: "a"\n1x-2: "b"', expect: 'invalid' }),
|
|
31
|
+
Object.freeze({ text: 'flowchrt TD\n A --> B', expect: 'unrecognised' }),
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* The line canary: blocks whose true error line is known. Between them they hold frontmatter
|
|
35
|
+
* followed by a blank line, a one-line and a three-line directive, a bare `%%` line (which Mermaid
|
|
36
|
+
* keeps), a blank line before a mid-body comment, two mid-body comments, a blank line left at the
|
|
37
|
+
* front once a leading comment goes, `\r\n` line ends, and one error of each line shape: a jison
|
|
38
|
+
* parse error, a jison lexical error, a Langium error. Not held: a Langium block with errors on
|
|
39
|
+
* several lines (which one is reported is the line map's "smallest line" rule, pinned only by the
|
|
40
|
+
* unit tests). Parsed privately, before eess-md's texts.
|
|
41
|
+
*/
|
|
42
|
+
const LINE_CANARIES = Object.freeze([
|
|
43
|
+
{
|
|
44
|
+
text: [
|
|
45
|
+
'---',
|
|
46
|
+
'title: x',
|
|
47
|
+
'---',
|
|
48
|
+
'',
|
|
49
|
+
'flowchart TD',
|
|
50
|
+
' A --> B',
|
|
51
|
+
'%%{init: {"theme":"dark"}}%%',
|
|
52
|
+
' B --> C',
|
|
53
|
+
'%%',
|
|
54
|
+
'',
|
|
55
|
+
' %% c',
|
|
56
|
+
' %% d',
|
|
57
|
+
'%%{init: {',
|
|
58
|
+
'"theme":"dark"',
|
|
59
|
+
'}}%%',
|
|
60
|
+
' C --> --> D',
|
|
61
|
+
' E --> F',
|
|
62
|
+
].join('\n'),
|
|
63
|
+
line: 16,
|
|
64
|
+
},
|
|
65
|
+
// A comment and a blank line before the kind: only Mermaid's final `trimStart` drops the blank.
|
|
66
|
+
{
|
|
67
|
+
text: '%% a\r\n\r\nflowchart TD\r\n A --> B\r\n %% c\r\n C --> D ]]] x\r\n E --> F',
|
|
68
|
+
line: 6,
|
|
69
|
+
},
|
|
70
|
+
{ text: 'packet-beta\n0-10: "a"\n%% c\n%% c\n11-x: "b"', line: 5 },
|
|
71
|
+
]);
|
|
72
|
+
const SHAPES = [
|
|
73
|
+
'ok',
|
|
74
|
+
'jison',
|
|
75
|
+
'langium',
|
|
76
|
+
'unknown-diagram',
|
|
77
|
+
'yaml',
|
|
78
|
+
'other',
|
|
79
|
+
'non-result',
|
|
80
|
+
];
|
|
81
|
+
function isShape(value) {
|
|
82
|
+
return typeof value === 'string' && SHAPES.includes(value);
|
|
83
|
+
}
|
|
84
|
+
function isRecord(value) {
|
|
85
|
+
return typeof value === 'object' && value !== null;
|
|
86
|
+
}
|
|
87
|
+
function lineOrNull(value) {
|
|
88
|
+
if (value === null)
|
|
89
|
+
return null;
|
|
90
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
91
|
+
}
|
|
92
|
+
/** The worker is code eess-mermaid runs but cannot type: every message is narrowed (ADR-005). */
|
|
93
|
+
function readFact(value) {
|
|
94
|
+
if (!isRecord(value))
|
|
95
|
+
return null;
|
|
96
|
+
const { shape, message } = value;
|
|
97
|
+
const locFirstLine = lineOrNull(value.locFirstLine);
|
|
98
|
+
const hashLine = lineOrNull(value.hashLine);
|
|
99
|
+
const yamlLine = lineOrNull(value.yamlLine);
|
|
100
|
+
const yamlText = value.yamlText;
|
|
101
|
+
const lines = value.langiumLines;
|
|
102
|
+
if (!isShape(shape) || typeof message !== 'string')
|
|
103
|
+
return null;
|
|
104
|
+
if (locFirstLine === undefined || hashLine === undefined || yamlLine === undefined)
|
|
105
|
+
return null;
|
|
106
|
+
if (!Array.isArray(lines))
|
|
107
|
+
return null;
|
|
108
|
+
if (yamlText !== null && typeof yamlText !== 'string')
|
|
109
|
+
return null;
|
|
110
|
+
const langiumLines = [];
|
|
111
|
+
for (const line of lines) {
|
|
112
|
+
if (typeof line !== 'number')
|
|
113
|
+
return null;
|
|
114
|
+
langiumLines.push(line);
|
|
115
|
+
}
|
|
116
|
+
return { shape, locFirstLine, hashLine, langiumLines, yamlLine, yamlText, message };
|
|
117
|
+
}
|
|
118
|
+
function readFacts(value, count) {
|
|
119
|
+
if (!Array.isArray(value) || value.length !== count)
|
|
120
|
+
return null;
|
|
121
|
+
const facts = [];
|
|
122
|
+
for (const item of value) {
|
|
123
|
+
const fact = readFact(item);
|
|
124
|
+
if (fact === null)
|
|
125
|
+
return null;
|
|
126
|
+
facts.push(fact);
|
|
127
|
+
}
|
|
128
|
+
return facts;
|
|
129
|
+
}
|
|
130
|
+
/** Mermaid's own line for an error, by shape; never read from the message. */
|
|
131
|
+
function mermaidLine(fact) {
|
|
132
|
+
if (fact.shape === 'jison') {
|
|
133
|
+
if (fact.locFirstLine !== null)
|
|
134
|
+
return fact.locFirstLine;
|
|
135
|
+
// A lexical error carries no `hash.loc`, and its `hash.line` counts from 0 (spike 0425).
|
|
136
|
+
return fact.hashLine === null ? null : fact.hashLine + 1;
|
|
137
|
+
}
|
|
138
|
+
if (fact.shape === 'langium' && fact.langiumLines.length > 0) {
|
|
139
|
+
return Math.min(...fact.langiumLines);
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
/** The block line of a syntax error, and Mermaid's own, before the trailing-comment rule. */
|
|
144
|
+
function blockLine(text, fact) {
|
|
145
|
+
const reported = mermaidLine(fact);
|
|
146
|
+
return { line: reported === null ? null : mermaidLineMap(text)(reported), reported };
|
|
147
|
+
}
|
|
148
|
+
const SUPPRESSED = (index) => new MermaidParserFailure('`mermaid.parse` resolved without a result; is `suppressErrors` set?', "Check that nothing sets Mermaid's `suppressErrors`: eess-mermaid needs `mermaid.parse` to throw on a broken block.", index);
|
|
149
|
+
/**
|
|
150
|
+
* The outcome table (plan 0413): Mermaid's acceptance always wins, and so does a syntax error it can
|
|
151
|
+
* place, since Mermaid found a diagram to parse. Any other failure is read with the block's preamble.
|
|
152
|
+
* A throw eess-mermaid cannot place is the instrument, never the author's error.
|
|
153
|
+
*/
|
|
154
|
+
function verdictFor(text, fact, index) {
|
|
155
|
+
const message = fact.message;
|
|
156
|
+
switch (fact.shape) {
|
|
157
|
+
case 'ok':
|
|
158
|
+
return { outcome: 'valid' };
|
|
159
|
+
case 'non-result':
|
|
160
|
+
throw SUPPRESSED(index);
|
|
161
|
+
case 'jison':
|
|
162
|
+
case 'langium':
|
|
163
|
+
return syntaxError(text, fact);
|
|
164
|
+
case 'yaml':
|
|
165
|
+
return yamlError(text, fact);
|
|
166
|
+
case 'unknown-diagram':
|
|
167
|
+
case 'other':
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
switch (diagramPreamble(text).reason) {
|
|
171
|
+
case 'unclosed-frontmatter':
|
|
172
|
+
return {
|
|
173
|
+
outcome: 'invalid',
|
|
174
|
+
message,
|
|
175
|
+
line: 1,
|
|
176
|
+
remedy: 'Close the frontmatter with an un-indented `---` line, followed by a newline and the diagram.',
|
|
177
|
+
};
|
|
178
|
+
case 'unclosed-directive':
|
|
179
|
+
return {
|
|
180
|
+
outcome: 'unrecognised',
|
|
181
|
+
message,
|
|
182
|
+
remedy: 'A `%%{` directive is never closed with `}%%`: close it.',
|
|
183
|
+
};
|
|
184
|
+
case 'empty':
|
|
185
|
+
return {
|
|
186
|
+
outcome: 'unrecognised',
|
|
187
|
+
message,
|
|
188
|
+
remedy: 'The block is empty: write the diagram, or remove the block.',
|
|
189
|
+
};
|
|
190
|
+
case 'no-kind-after-preamble':
|
|
191
|
+
return {
|
|
192
|
+
outcome: 'unrecognised',
|
|
193
|
+
message,
|
|
194
|
+
remedy: 'The block declares no diagram after its directives, comments or frontmatter: add the diagram.',
|
|
195
|
+
};
|
|
196
|
+
case 'declared':
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
if (fact.shape === 'unknown-diagram') {
|
|
200
|
+
return {
|
|
201
|
+
outcome: 'unrecognised',
|
|
202
|
+
message,
|
|
203
|
+
remedy: 'Check the spelling of the diagram kind, or this kind needs a newer `mermaid` or a plugin.',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
throw new MermaidParserFailure(`Mermaid threw something eess-mermaid does not recognise as a syntax error: ${message}`, 'If this block is wrong, fix it; otherwise report it to eess.', index);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* A YAML error claims a line only when the YAML js-yaml was given is the block's frontmatter as the
|
|
210
|
+
* line map reads it, which starts on the block's second line. Mermaid also reads a node's `@{ … }`
|
|
211
|
+
* data as YAML, counted on a snippet of its own; that error claims no line (PR review, architect N1).
|
|
212
|
+
*/
|
|
213
|
+
function yamlError(text, fact) {
|
|
214
|
+
const frontmatter = frontmatterYaml(text);
|
|
215
|
+
const given = fact.yamlText?.replace(/\n$/, '');
|
|
216
|
+
if (frontmatter !== null && given === frontmatter && fact.yamlLine !== null) {
|
|
217
|
+
return {
|
|
218
|
+
outcome: 'invalid',
|
|
219
|
+
message: fact.message,
|
|
220
|
+
line: fact.yamlLine + 2,
|
|
221
|
+
remedy: "Fix the frontmatter's YAML at this line; Mermaid's message is above.",
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
outcome: 'invalid',
|
|
226
|
+
message: fact.message,
|
|
227
|
+
line: null,
|
|
228
|
+
remedy: "Mermaid could not read a YAML part of this block, its frontmatter or a node's `@{ … }` data; " +
|
|
229
|
+
'its message is above.',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function syntaxError(text, fact) {
|
|
233
|
+
const { line, reported } = blockLine(text, fact);
|
|
234
|
+
const remedy = "Fix the syntax at this line; Mermaid's message is above.";
|
|
235
|
+
const said = reported === null ? 'no line' : `line ${String(reported)}`;
|
|
236
|
+
// Mermaid reads frontmatter after a blank line or a comment, which the line map does not mirror
|
|
237
|
+
// (bug 0435): the walk then calls it unclosed, and the mapped line would be wrong.
|
|
238
|
+
if (diagramPreamble(text).reason === 'unclosed-frontmatter') {
|
|
239
|
+
return {
|
|
240
|
+
outcome: 'invalid',
|
|
241
|
+
message: `${fact.message}\nMermaid read frontmatter here that eess-mermaid's line map does not ` +
|
|
242
|
+
`(after a blank line or a comment); it reported ${said}.`,
|
|
243
|
+
line: null,
|
|
244
|
+
remedy,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
if (hasTrailingComment(text)) {
|
|
248
|
+
return {
|
|
249
|
+
outcome: 'invalid',
|
|
250
|
+
message: `${fact.message}\nMermaid's line count is unreliable in a block with a trailing \`%%\` comment; ` +
|
|
251
|
+
`it reported ${said}.`,
|
|
252
|
+
line: null,
|
|
253
|
+
remedy,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
return { outcome: 'invalid', message: fact.message, line, remedy };
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The line canary: each block's syntax error must be on its known line. A block Mermaid accepts, or
|
|
260
|
+
* rejects with anything but a syntax error, checks nothing, so it is the instrument too. The one
|
|
261
|
+
* exception: when Mermaid also accepted one of this parser's own canaries, it has stopped throwing
|
|
262
|
+
* altogether, and eess-md's canaries report that under their own cause.
|
|
263
|
+
*/
|
|
264
|
+
function checkLineCanaries(facts, loaded, stoppedThrowing) {
|
|
265
|
+
for (const [i, canary] of LINE_CANARIES.entries()) {
|
|
266
|
+
const fact = facts[i];
|
|
267
|
+
if (fact === undefined)
|
|
268
|
+
continue;
|
|
269
|
+
const which = `line-canary block ${String(i + 1)}`;
|
|
270
|
+
if (fact.shape === 'non-result')
|
|
271
|
+
throw SUPPRESSED(null);
|
|
272
|
+
if (fact.shape === 'ok') {
|
|
273
|
+
if (stoppedThrowing)
|
|
274
|
+
continue;
|
|
275
|
+
throw new MermaidParserFailure(`mermaid ${loaded} accepted ${which}, which must fail on line ${String(canary.line)}, so ` +
|
|
276
|
+
"eess-mermaid's line map cannot be checked against it", `Install \`mermaid@${LINE_MAP_MERMAID}\`, and report the version to eess.`, null);
|
|
277
|
+
}
|
|
278
|
+
if (fact.shape !== 'jison' && fact.shape !== 'langium') {
|
|
279
|
+
throw new MermaidParserFailure(`mermaid ${loaded} rejected ${which} with something that is not a syntax error: ${fact.message}`, "Check that `mermaid` and `jsdom` load cleanly; if they do, report it to eess with Mermaid's message.", null);
|
|
280
|
+
}
|
|
281
|
+
if (blockLine(canary.text, fact).line === canary.line)
|
|
282
|
+
continue;
|
|
283
|
+
throw new MermaidParserFailure(`eess-mermaid's line map, written for mermaid ${LINE_MAP_MERMAID}, disagrees with mermaid ` +
|
|
284
|
+
`${loaded}: ${which} should fail on line ${String(canary.line)}`, `Install \`mermaid@${LINE_MAP_MERMAID}\`, and report the version to eess.`, null);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const CANARY_TEXTS = new Set(CANARIES.map((c) => c.text));
|
|
288
|
+
/** "Major 11", prereleases included: `11.0.0-alpha.1` is in, `12.0.0-rc.1` is out. */
|
|
289
|
+
function inMermaidRange(version) {
|
|
290
|
+
return /^11\.\d+\.\d+(?:[-+].*)?$/.test(version);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* The installed `mermaid`'s version, read without loading it and without its `exports`: the first
|
|
294
|
+
* `<dir>/mermaid/package.json` among the directories Node would search from the worker.
|
|
295
|
+
*/
|
|
296
|
+
function declaredMermaid(workerUrl) {
|
|
297
|
+
for (const dir of createRequire(workerUrl).resolve.paths('mermaid') ?? []) {
|
|
298
|
+
const file = join(dir, 'mermaid', 'package.json');
|
|
299
|
+
if (!existsSync(file))
|
|
300
|
+
continue;
|
|
301
|
+
let pkg;
|
|
302
|
+
try {
|
|
303
|
+
pkg = JSON.parse(readFileSync(file, 'utf8'));
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
// Not JSON: an installed mermaid is never reported as missing (ADR-009 rule 2).
|
|
307
|
+
return {
|
|
308
|
+
version: 'unreadable',
|
|
309
|
+
file,
|
|
310
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
const version = isRecord(pkg) ? pkg.version : undefined;
|
|
314
|
+
return typeof version === 'string' && version !== ''
|
|
315
|
+
? { version, file }
|
|
316
|
+
: { version: 'unreadable', file };
|
|
317
|
+
}
|
|
318
|
+
return { version: 'not installed', file: null };
|
|
319
|
+
}
|
|
320
|
+
function before(declared) {
|
|
321
|
+
if (declared.version === 'not installed') {
|
|
322
|
+
return new MermaidParserFailure('mermaid is not installed where eess-mermaid can resolve it.', INSTALL, null);
|
|
323
|
+
}
|
|
324
|
+
if (declared.version === 'unreadable') {
|
|
325
|
+
return new MermaidParserFailure(`mermaid's package.json at ${declared.file ?? 'an unknown path'} has no readable version` +
|
|
326
|
+
`${declared.reason === undefined ? '' : ` (${declared.reason})`}.`, 'Reinstall `mermaid`.', null);
|
|
327
|
+
}
|
|
328
|
+
if (!inMermaidRange(declared.version)) {
|
|
329
|
+
return new MermaidParserFailure(`mermaid ${declared.version} is installed.`, 'eess-mermaid reads mermaid 11; install `mermaid@11`.', null);
|
|
330
|
+
}
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
function loadFailure(message) {
|
|
334
|
+
const said = typeof message.message === 'string' ? message.message : 'no message';
|
|
335
|
+
const missing = typeof message.missing === 'string' ? message.missing : '';
|
|
336
|
+
if (missing === 'mermaid' || missing === 'jsdom') {
|
|
337
|
+
return new MermaidParserFailure(`the Mermaid worker could not load ${missing}: ${said}`, INSTALL, null);
|
|
338
|
+
}
|
|
339
|
+
if (missing !== '') {
|
|
340
|
+
return new MermaidParserFailure(`the Mermaid worker could not load: ${said}`, `\`${missing}\`, a dependency of mermaid or jsdom, is missing; reinstall them.`, null);
|
|
341
|
+
}
|
|
342
|
+
return new MermaidParserFailure(`the Mermaid worker could not load: ${said}`, `${INSTALL} Node said: ${said}`, null);
|
|
343
|
+
}
|
|
344
|
+
/** The parser, run from `workerUrl`. Never throws: a missing peer is reported by `parse`. */
|
|
345
|
+
export function createMermaidParser(options) {
|
|
346
|
+
const { workerUrl } = options;
|
|
347
|
+
const declared = declaredMermaid(workerUrl);
|
|
348
|
+
return Object.freeze({
|
|
349
|
+
name: 'mermaid',
|
|
350
|
+
version: declared.version,
|
|
351
|
+
canaries: CANARIES,
|
|
352
|
+
parse: (texts, run) => parseInWorker(workerUrl, declared, texts, run),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
function parseInWorker(workerUrl, declared, texts, run) {
|
|
356
|
+
const refused = before(declared);
|
|
357
|
+
if (refused !== null)
|
|
358
|
+
return Promise.reject(refused);
|
|
359
|
+
const { signal, budgetMs } = run;
|
|
360
|
+
return new Promise((resolve, reject) => {
|
|
361
|
+
const worker = new Worker(workerUrl, {
|
|
362
|
+
workerData: { texts: [...texts], privateTexts: LINE_CANARIES.map((c) => c.text) },
|
|
363
|
+
});
|
|
364
|
+
let inFlight = null;
|
|
365
|
+
let loaded = false;
|
|
366
|
+
let settled = false;
|
|
367
|
+
// The worker is terminated on every path: success, failure, exit and abort.
|
|
368
|
+
const finish = (settle) => {
|
|
369
|
+
if (settled)
|
|
370
|
+
return;
|
|
371
|
+
settled = true;
|
|
372
|
+
signal.removeEventListener('abort', onAbort);
|
|
373
|
+
void worker.terminate();
|
|
374
|
+
settle();
|
|
375
|
+
};
|
|
376
|
+
const fail = (failure) => finish(() => reject(failure));
|
|
377
|
+
const onAbort = () => {
|
|
378
|
+
fail(inFlight === null
|
|
379
|
+
? new MermaidParserFailure(`the Mermaid worker did not start parsing within the budget of ${String(budgetMs)} ms`, 'Raise `budget.startUpMs`.', null)
|
|
380
|
+
: new MermaidParserFailure(`Mermaid was still parsing text ${String(inFlight + 1)} when the budget of ` +
|
|
381
|
+
`${String(budgetMs)} ms ran out`, 'Raise `budget.perBlockMs`, or leave that document out of the corpus by its `ignore` glob.', inFlight));
|
|
382
|
+
};
|
|
383
|
+
if (signal.aborted)
|
|
384
|
+
onAbort();
|
|
385
|
+
else
|
|
386
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
387
|
+
worker.on('message', (message) => {
|
|
388
|
+
if (!isRecord(message))
|
|
389
|
+
return;
|
|
390
|
+
if (message.type === 'progress') {
|
|
391
|
+
if (typeof message.index === 'number')
|
|
392
|
+
inFlight = message.index;
|
|
393
|
+
}
|
|
394
|
+
else if (message.type === 'load-error') {
|
|
395
|
+
fail(loadFailure(message));
|
|
396
|
+
}
|
|
397
|
+
else if (message.type === 'loaded') {
|
|
398
|
+
loaded = true;
|
|
399
|
+
const version = typeof message.version === 'string' ? message.version : 'unreadable';
|
|
400
|
+
if (version !== declared.version) {
|
|
401
|
+
fail(new MermaidParserFailure(`the Mermaid worker loaded mermaid ${version}, but mermaid ${declared.version} is ` +
|
|
402
|
+
`installed at ${declared.file ?? 'an unknown path'}`, 'Reinstall `mermaid`, and check for a loader hook that redirects it.', null));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
else if (message.type === 'verdicts') {
|
|
406
|
+
const facts = readFacts(message.results, texts.length);
|
|
407
|
+
const lineFacts = readFacts(message.privateResults, LINE_CANARIES.length);
|
|
408
|
+
if (!loaded || facts === null || lineFacts === null) {
|
|
409
|
+
fail(new MermaidParserFailure('the Mermaid worker posted verdicts eess-mermaid cannot read', 'Report it to eess, with the versions of mermaid and jsdom.', null));
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
// Every error settles the parse: a throw from a message listener would be uncaught in the
|
|
413
|
+
// caller's process, with no finding to report.
|
|
414
|
+
try {
|
|
415
|
+
const verdicts = facts.map((fact, i) => verdictFor(texts[i] ?? '', fact, i));
|
|
416
|
+
const stoppedThrowing = facts.some((fact, i) => fact.shape === 'ok' && CANARY_TEXTS.has(texts[i] ?? ''));
|
|
417
|
+
checkLineCanaries(lineFacts, declared.version, stoppedThrowing);
|
|
418
|
+
finish(() => resolve(Object.freeze(verdicts)));
|
|
419
|
+
}
|
|
420
|
+
catch (error) {
|
|
421
|
+
fail(error instanceof MermaidParserFailure
|
|
422
|
+
? error
|
|
423
|
+
: new MermaidParserFailure(`eess-mermaid could not classify Mermaid's answer: ${error instanceof Error ? error.message : String(error)}`, 'Report it to eess, with the block.', null));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
worker.on('error', (error) => {
|
|
428
|
+
fail(exitFailure(`the Mermaid worker threw: ${error.message}`, inFlight));
|
|
429
|
+
});
|
|
430
|
+
worker.on('exit', (code) => {
|
|
431
|
+
fail(exitFailure(`the Mermaid worker exited (code ${String(code)}) without a result`, inFlight));
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
function exitFailure(what, inFlight) {
|
|
436
|
+
return new MermaidParserFailure(inFlight === null ? what : `${what}, while parsing text ${String(inFlight + 1)}`, 'Leave that document out of the corpus by its `ignore` glob, and report the block to eess.', inFlight);
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=create-mermaid-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-mermaid-parser.js","sourceRoot":"","sources":["../../src/mermaid-js/create-mermaid-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type MermaidParser } from './create-mermaid-parser.js';
|
|
2
|
+
/**
|
|
3
|
+
* Mermaid's own parser, for eess-md's `parseCodeBlocks` (plan 0413): it says whether a block
|
|
4
|
+
* parses with the `mermaid` package GitHub renders with. It is not `parseClassDiagram`, which is
|
|
5
|
+
* eess's own grammar, used to bind a diagram to code.
|
|
6
|
+
*
|
|
7
|
+
* `mermaid` (11) and `jsdom` are optional peers, loaded only inside a worker thread, so the DOM
|
|
8
|
+
* globals Mermaid needs never reach the caller's process. Never throws: a missing peer is reported
|
|
9
|
+
* by `parse`, as the instrument.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const parsed = await parseCodeBlocks(corpus, { language: 'mermaid', parser: mermaidParser() })
|
|
13
|
+
* codeBlocks(parsed).should().parse().check()
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function mermaidParser(): MermaidParser;
|
|
17
|
+
//# sourceMappingURL=mermaid-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid-parser.d.ts","sourceRoot":"","sources":["../../src/mermaid-js/mermaid-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAEpF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,IAAI,aAAa,CAE7C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createMermaidParser } from './create-mermaid-parser.js';
|
|
2
|
+
/**
|
|
3
|
+
* Mermaid's own parser, for eess-md's `parseCodeBlocks` (plan 0413): it says whether a block
|
|
4
|
+
* parses with the `mermaid` package GitHub renders with. It is not `parseClassDiagram`, which is
|
|
5
|
+
* eess's own grammar, used to bind a diagram to code.
|
|
6
|
+
*
|
|
7
|
+
* `mermaid` (11) and `jsdom` are optional peers, loaded only inside a worker thread, so the DOM
|
|
8
|
+
* globals Mermaid needs never reach the caller's process. Never throws: a missing peer is reported
|
|
9
|
+
* by `parse`, as the instrument.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const parsed = await parseCodeBlocks(corpus, { language: 'mermaid', parser: mermaidParser() })
|
|
13
|
+
* codeBlocks(parsed).should().parse().check()
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function mermaidParser() {
|
|
17
|
+
return createMermaidParser({ workerUrl: new URL('./mermaid-worker.mjs', import.meta.url) });
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=mermaid-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid-parser.js","sourceRoot":"","sources":["../../src/mermaid-js/mermaid-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAsB,MAAM,4BAA4B,CAAA;AAEpF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,mBAAmB,CAAC,EAAE,SAAS,EAAE,IAAI,GAAG,CAAC,sBAAsB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AAC7F,CAAC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// eess-mermaid's Mermaid worker (plan 0413). It runs `mermaid.parse` under a `jsdom` window on its
|
|
2
|
+
// own thread, so the DOM globals Mermaid needs never reach the host's.
|
|
3
|
+
//
|
|
4
|
+
// Self-contained on purpose: it imports only Node built-ins, `mermaid` and `jsdom`, with no relative
|
|
5
|
+
// import, so a copy of this one file runs wherever those two resolve. It is plain JavaScript because
|
|
6
|
+
// no loader transforms a worker's own imports: the resolve hook ADR-015 allows is in-thread and
|
|
7
|
+
// does not reach a worker.
|
|
8
|
+
//
|
|
9
|
+
// It posts facts and decides nothing. An error loses its `hash` and `result` crossing `postMessage`,
|
|
10
|
+
// so each one is read here, where it was thrown, and only plain data is posted. Which outcome a fact
|
|
11
|
+
// is, and on which line, is the host's (`create-mermaid-parser.ts`). The messages:
|
|
12
|
+
// { type: 'loaded', version } once, after `mermaid` and `jsdom` load
|
|
13
|
+
// { type: 'load-error', code, missing, message } when they do not
|
|
14
|
+
// { type: 'progress', index } before each of `workerData.texts`
|
|
15
|
+
// { type: 'verdicts', results, privateResults } one fact per text, at the end
|
|
16
|
+
// A fact is { shape, locFirstLine, hashLine, langiumLines, yamlLine, yamlText, message }.
|
|
17
|
+
// `workerData.privateTexts` are parsed first and post no `progress`, so the indexes stay the caller's.
|
|
18
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
19
|
+
import { dirname, join } from 'node:path'
|
|
20
|
+
import { fileURLToPath } from 'node:url'
|
|
21
|
+
import { parentPort, workerData } from 'node:worker_threads'
|
|
22
|
+
|
|
23
|
+
/** The version of the `mermaid` this worker imports: up from its resolved entry to its package.json. */
|
|
24
|
+
function loadedVersion() {
|
|
25
|
+
let dir = dirname(fileURLToPath(import.meta.resolve('mermaid')))
|
|
26
|
+
for (;;) {
|
|
27
|
+
const file = join(dir, 'package.json')
|
|
28
|
+
if (existsSync(file)) {
|
|
29
|
+
const pkg = JSON.parse(readFileSync(file, 'utf8'))
|
|
30
|
+
if (pkg?.name === 'mermaid')
|
|
31
|
+
return typeof pkg.version === 'string' ? pkg.version : 'unreadable'
|
|
32
|
+
}
|
|
33
|
+
const up = dirname(dir)
|
|
34
|
+
if (up === dir) return 'unreadable'
|
|
35
|
+
dir = up
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const finite = (value) => (typeof value === 'number' && Number.isFinite(value) ? value : null)
|
|
40
|
+
|
|
41
|
+
/** One error, read by property, never by class name or message. */
|
|
42
|
+
function errorFact(error) {
|
|
43
|
+
const message = String(error?.message ?? error)
|
|
44
|
+
const fact = {
|
|
45
|
+
shape: 'other',
|
|
46
|
+
locFirstLine: null,
|
|
47
|
+
hashLine: null,
|
|
48
|
+
langiumLines: [],
|
|
49
|
+
yamlLine: null,
|
|
50
|
+
yamlText: null,
|
|
51
|
+
message,
|
|
52
|
+
}
|
|
53
|
+
if (typeof error?.hash === 'object' && error.hash !== null) {
|
|
54
|
+
return {
|
|
55
|
+
...fact,
|
|
56
|
+
shape: 'jison',
|
|
57
|
+
locFirstLine: finite(error.hash.loc?.first_line),
|
|
58
|
+
hashLine: finite(error.hash.line),
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const result = error?.result
|
|
62
|
+
if (Array.isArray(result?.lexerErrors) && Array.isArray(result?.parserErrors)) {
|
|
63
|
+
const lines = [
|
|
64
|
+
...result.lexerErrors.map((e) => finite(e?.line)),
|
|
65
|
+
...result.parserErrors.map((e) => finite(e?.token?.startLine)),
|
|
66
|
+
].filter((line) => line !== null)
|
|
67
|
+
return { ...fact, shape: 'langium', langiumLines: lines }
|
|
68
|
+
}
|
|
69
|
+
if (error?.name === 'UnknownDiagramError') return { ...fact, shape: 'unknown-diagram' }
|
|
70
|
+
// YAML Mermaid could not read: js-yaml's error, with its 0-based line and the YAML it was given,
|
|
71
|
+
// which may be the frontmatter or a node's `@{ … }` data.
|
|
72
|
+
if (error?.name === 'YAMLException') {
|
|
73
|
+
const buffer = error.mark?.buffer
|
|
74
|
+
return {
|
|
75
|
+
...fact,
|
|
76
|
+
shape: 'yaml',
|
|
77
|
+
yamlLine: finite(error.mark?.line),
|
|
78
|
+
yamlText: typeof buffer === 'string' ? buffer : null,
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return fact
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function parseOne(mermaid, text) {
|
|
85
|
+
try {
|
|
86
|
+
const result = await mermaid.parse(text)
|
|
87
|
+
if (typeof result !== 'object' || result === null) {
|
|
88
|
+
return {
|
|
89
|
+
shape: 'non-result',
|
|
90
|
+
locFirstLine: null,
|
|
91
|
+
hashLine: null,
|
|
92
|
+
langiumLines: [],
|
|
93
|
+
yamlLine: null,
|
|
94
|
+
yamlText: null,
|
|
95
|
+
message: String(result),
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
shape: 'ok',
|
|
100
|
+
locFirstLine: null,
|
|
101
|
+
hashLine: null,
|
|
102
|
+
langiumLines: [],
|
|
103
|
+
yamlLine: null,
|
|
104
|
+
yamlText: null,
|
|
105
|
+
message: '',
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return errorFact(error)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function main() {
|
|
113
|
+
let mermaid
|
|
114
|
+
let version
|
|
115
|
+
try {
|
|
116
|
+
const { JSDOM } = await import('jsdom')
|
|
117
|
+
const dom = new JSDOM('<!doctype html><html><body></body></html>')
|
|
118
|
+
for (const key of ['window', 'document', 'DOMParser', 'Element', 'HTMLElement', 'Node']) {
|
|
119
|
+
if (!(key in globalThis)) globalThis[key] = key === 'window' ? dom.window : dom.window[key]
|
|
120
|
+
}
|
|
121
|
+
mermaid = (await import('mermaid')).default
|
|
122
|
+
version = loadedVersion()
|
|
123
|
+
} catch (error) {
|
|
124
|
+
const message = String(error?.message ?? error)
|
|
125
|
+
parentPort.postMessage({
|
|
126
|
+
type: 'load-error',
|
|
127
|
+
code: typeof error?.code === 'string' ? error.code : '',
|
|
128
|
+
missing: /Cannot find package '([^']+)'/.exec(message)?.[1] ?? '',
|
|
129
|
+
message,
|
|
130
|
+
})
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
parentPort.postMessage({ type: 'loaded', version })
|
|
134
|
+
const privateResults = []
|
|
135
|
+
for (const text of workerData.privateTexts) privateResults.push(await parseOne(mermaid, text))
|
|
136
|
+
const results = []
|
|
137
|
+
for (const [index, text] of workerData.texts.entries()) {
|
|
138
|
+
parentPort.postMessage({ type: 'progress', index })
|
|
139
|
+
results.push(await parseOne(mermaid, text))
|
|
140
|
+
}
|
|
141
|
+
parentPort.postMessage({ type: 'verdicts', results, privateResults })
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
await main()
|
|
@@ -8,4 +8,20 @@
|
|
|
8
8
|
* binding tested the raw text and missed a themed diagram entirely (bug 0210).
|
|
9
9
|
*/
|
|
10
10
|
export declare function diagramKind(text: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Why a block declares the kind it does (plan 0413). `declared` when the walk finds a kind; otherwise
|
|
13
|
+
* the first that holds of: Mermaid sees frontmatter it cannot close (`unclosed-frontmatter`), a `%%{`
|
|
14
|
+
* directive never closes (`unclosed-directive`), the block is blank (`empty`), or something precedes
|
|
15
|
+
* no kind (`no-kind-after-preamble`). Internal to eess-mermaid: no adopter needs the reason.
|
|
16
|
+
*/
|
|
17
|
+
type PreambleReason = 'declared' | 'empty' | 'no-kind-after-preamble' | 'unclosed-directive' | 'unclosed-frontmatter';
|
|
18
|
+
interface DiagramPreamble {
|
|
19
|
+
/** As `diagramKind` returns it: the kind token, or `''`. */
|
|
20
|
+
readonly kind: string;
|
|
21
|
+
/** The 1-based block line the kind is declared on, or `null` when none is. */
|
|
22
|
+
readonly kindLine: number | null;
|
|
23
|
+
readonly reason: PreambleReason;
|
|
24
|
+
}
|
|
25
|
+
export declare function diagramPreamble(text: string): DiagramPreamble;
|
|
26
|
+
export {};
|
|
11
27
|
//# sourceMappingURL=diagram-kind.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagram-kind.d.ts","sourceRoot":"","sources":["../../src/parser/diagram-kind.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"diagram-kind.d.ts","sourceRoot":"","sources":["../../src/parser/diagram-kind.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD;AAMD;;;;;GAKG;AACH,KAAK,cAAc,GACf,UAAU,GACV,OAAO,GACP,wBAAwB,GACxB,oBAAoB,GACpB,sBAAsB,CAAA;AAE1B,UAAU,eAAe;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;CAChC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAa7D"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { mermaidPreprocessed } from './mermaid-line-map.js';
|
|
1
2
|
/**
|
|
2
3
|
* The declared kind of a Mermaid diagram (plan 0214): the first token of the line that declares it,
|
|
3
4
|
* such as `erDiagram`, `graph` or `stateDiagram-v2`, or `''` when the text declares none.
|
|
@@ -8,7 +9,29 @@
|
|
|
8
9
|
* binding tested the raw text and missed a themed diagram entirely (bug 0210).
|
|
9
10
|
*/
|
|
10
11
|
export function diagramKind(text) {
|
|
11
|
-
|
|
12
|
+
// The walk alone: the reason below needs Mermaid's preprocessing, and the bindings that select
|
|
13
|
+
// blocks by kind need neither its cost nor its dependence on one Mermaid version.
|
|
14
|
+
return kindOf(declaredLine(text).line);
|
|
15
|
+
}
|
|
16
|
+
function kindOf(line) {
|
|
17
|
+
return (line.split(/[\s{]/)[0] ?? '').trim();
|
|
18
|
+
}
|
|
19
|
+
export function diagramPreamble(text) {
|
|
20
|
+
const walked = declaredLine(text);
|
|
21
|
+
const kind = kindOf(walked.line);
|
|
22
|
+
// Mermaid's own test for frontmatter it could not read: what is left after its preprocessing
|
|
23
|
+
// still begins with `---` (its `---` diagram detector). The same steps as the line map, so the
|
|
24
|
+
// two cannot disagree about it.
|
|
25
|
+
if (/^---/.test(mermaidPreprocessed(text).text.toLowerCase())) {
|
|
26
|
+
return { kind, kindLine: walked.at, reason: 'unclosed-frontmatter' };
|
|
27
|
+
}
|
|
28
|
+
if (kind !== '')
|
|
29
|
+
return { kind, kindLine: walked.at, reason: 'declared' };
|
|
30
|
+
if (walked.inDirective)
|
|
31
|
+
return { kind, kindLine: null, reason: 'unclosed-directive' };
|
|
32
|
+
if (text.trim() === '')
|
|
33
|
+
return { kind, kindLine: null, reason: 'empty' };
|
|
34
|
+
return { kind, kindLine: null, reason: 'no-kind-after-preamble' };
|
|
12
35
|
}
|
|
13
36
|
function declaredLine(text) {
|
|
14
37
|
const lines = text.split(/\r?\n/);
|
|
@@ -21,24 +44,30 @@ function declaredLine(text) {
|
|
|
21
44
|
}
|
|
22
45
|
let inDirective = false;
|
|
23
46
|
for (; i < lines.length; i += 1) {
|
|
24
|
-
|
|
25
|
-
if (line === '')
|
|
26
|
-
continue;
|
|
47
|
+
let line = lines[i]?.trim() ?? '';
|
|
27
48
|
// `%%{ … }%%` may span lines. Track it, or the continuation line gets read as the declared kind:
|
|
28
|
-
// measured, a multi-line init block ahead of a sequenceDiagram made it selected.
|
|
49
|
+
// measured, a multi-line init block ahead of a sequenceDiagram made it selected. A directive
|
|
50
|
+
// closes at its FIRST `}%%`, wherever it is on the line, as Mermaid's own pattern does; what
|
|
51
|
+
// follows is read as the rest of the line (bug 0429: `%%{init}%% %% note` stayed open).
|
|
29
52
|
if (inDirective) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
53
|
+
const close = line.indexOf('}%%');
|
|
54
|
+
if (close === -1)
|
|
55
|
+
continue;
|
|
56
|
+
inDirective = false;
|
|
57
|
+
line = line.slice(close + 3).trim();
|
|
33
58
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
while (line.startsWith('%%{')) {
|
|
60
|
+
const close = line.indexOf('}%%');
|
|
61
|
+
if (close === -1) {
|
|
62
|
+
inDirective = true;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
line = line.slice(close + 3).trim();
|
|
37
66
|
}
|
|
38
|
-
if (line.startsWith('%%'))
|
|
67
|
+
if (inDirective || line === '' || line.startsWith('%%'))
|
|
39
68
|
continue;
|
|
40
|
-
return line;
|
|
69
|
+
return { line, at: i + 1, inDirective: false };
|
|
41
70
|
}
|
|
42
|
-
return '';
|
|
71
|
+
return { line: '', at: null, inDirective };
|
|
43
72
|
}
|
|
44
73
|
//# sourceMappingURL=diagram-kind.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagram-kind.js","sourceRoot":"","sources":["../../src/parser/diagram-kind.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"diagram-kind.js","sourceRoot":"","sources":["../../src/parser/diagram-kind.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where Mermaid's line is in the block (plan 0413, spike 0428). Mermaid counts an error's line on the
|
|
3
|
+
* text it has preprocessed, not on the block: it drops frontmatter with the blank lines after it,
|
|
4
|
+
* collapses a multi-line directive, and removes every whole-line `%%` comment with the blank lines
|
|
5
|
+
* before it. This mirrors those steps on the block while carrying each UTF-16 unit's origin line.
|
|
6
|
+
*
|
|
7
|
+
* The regexes are mermaid 11.17.2's, from `preprocessDiagram` in `dist/mermaid.core.mjs`: the CRLF
|
|
8
|
+
* rewrite and the comment removal are its own, the frontmatter regex is `frontMatterRegex` and the
|
|
9
|
+
* directive regex is `directiveRegex`. The line canary (`create-mermaid-parser.ts`) reds when an
|
|
10
|
+
* installed `mermaid` stops agreeing with them.
|
|
11
|
+
*/
|
|
12
|
+
interface Traced {
|
|
13
|
+
readonly text: string;
|
|
14
|
+
/** The block line (1-based) each UTF-16 unit of `text` came from. */
|
|
15
|
+
readonly origin: readonly number[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The YAML of the block's frontmatter as Mermaid hands it to js-yaml (its indent removed from each
|
|
19
|
+
* line, as `extractFrontMatter` does), or `null` when the line map reads no frontmatter.
|
|
20
|
+
*/
|
|
21
|
+
export declare function frontmatterYaml(text: string): string | null;
|
|
22
|
+
/** The text Mermaid parses, as its four line-moving steps leave it, with each unit's origin line. */
|
|
23
|
+
export declare function mermaidPreprocessed(text: string): Traced;
|
|
24
|
+
/**
|
|
25
|
+
* A function from Mermaid's 1-based line to the block's, or `null` when Mermaid's text has no such
|
|
26
|
+
* line.
|
|
27
|
+
*/
|
|
28
|
+
export declare function mermaidLineMap(text: string): (mermaidLine: number) => number | null;
|
|
29
|
+
/**
|
|
30
|
+
* Does any line of the block carry a `%%` comment after other text? Two of Mermaid's lexers lose
|
|
31
|
+
* lines after one (spike 0428 Q2), so a verdict for such a block claims no line. Read after the
|
|
32
|
+
* frontmatter and directive steps, so a directive's own closing `}%%` is not a comment.
|
|
33
|
+
*/
|
|
34
|
+
export declare function hasTrailingComment(text: string): boolean;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=mermaid-line-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid-line-map.d.ts","sourceRoot":"","sources":["../../src/parser/mermaid-line-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,UAAU,MAAM;IACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CACnC;AAkCD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU3D;AAOD,qGAAqG;AACrG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CASnF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where Mermaid's line is in the block (plan 0413, spike 0428). Mermaid counts an error's line on the
|
|
3
|
+
* text it has preprocessed, not on the block: it drops frontmatter with the blank lines after it,
|
|
4
|
+
* collapses a multi-line directive, and removes every whole-line `%%` comment with the blank lines
|
|
5
|
+
* before it. This mirrors those steps on the block while carrying each UTF-16 unit's origin line.
|
|
6
|
+
*
|
|
7
|
+
* The regexes are mermaid 11.17.2's, from `preprocessDiagram` in `dist/mermaid.core.mjs`: the CRLF
|
|
8
|
+
* rewrite and the comment removal are its own, the frontmatter regex is `frontMatterRegex` and the
|
|
9
|
+
* directive regex is `directiveRegex`. The line canary (`create-mermaid-parser.ts`) reds when an
|
|
10
|
+
* installed `mermaid` stops agreeing with them.
|
|
11
|
+
*/
|
|
12
|
+
const FRONTMATTER = /^([^\S\n\r]*)-{3}\s*[\n\r](.*?)[\n\r]\1-{3}\s*[\n\r]+/s;
|
|
13
|
+
const DIRECTIVE = /%{2}{\s*(?:(\w+)\s*:|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi;
|
|
14
|
+
const COMMENT = /^\s*%%(?!{)[^\n]+\n?/gm;
|
|
15
|
+
/** A line whose first non-blank text is not `%%` and that holds `%%` later: a trailing comment. */
|
|
16
|
+
const TRAILING_COMMENT = /^[^\S\n]*(?!%%)\S[^\n]*%%/m;
|
|
17
|
+
function cut(traced, pattern) {
|
|
18
|
+
const global = pattern.global ? pattern : new RegExp(pattern.source, `${pattern.flags}g`);
|
|
19
|
+
let text = '';
|
|
20
|
+
const origin = [];
|
|
21
|
+
let last = 0;
|
|
22
|
+
for (const match of traced.text.matchAll(global)) {
|
|
23
|
+
text += traced.text.slice(last, match.index);
|
|
24
|
+
// A loop, not a spread: a spread of a block-sized array overflows the stack (PR review, 300 KB).
|
|
25
|
+
for (let i = last; i < match.index; i += 1) {
|
|
26
|
+
const line = traced.origin[i];
|
|
27
|
+
if (line !== undefined)
|
|
28
|
+
origin.push(line);
|
|
29
|
+
}
|
|
30
|
+
last = match.index + match[0].length;
|
|
31
|
+
if (!pattern.global)
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
text: text + traced.text.slice(last),
|
|
36
|
+
origin: origin.concat(traced.origin.slice(last)),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function trace(text) {
|
|
40
|
+
const normalised = text.replace(/\r\n?/g, '\n');
|
|
41
|
+
const origin = [];
|
|
42
|
+
let line = 1;
|
|
43
|
+
for (let i = 0; i < normalised.length; i += 1) {
|
|
44
|
+
origin.push(line);
|
|
45
|
+
if (normalised[i] === '\n')
|
|
46
|
+
line += 1;
|
|
47
|
+
}
|
|
48
|
+
return { text: normalised, origin };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The YAML of the block's frontmatter as Mermaid hands it to js-yaml (its indent removed from each
|
|
52
|
+
* line, as `extractFrontMatter` does), or `null` when the line map reads no frontmatter.
|
|
53
|
+
*/
|
|
54
|
+
export function frontmatterYaml(text) {
|
|
55
|
+
const match = FRONTMATTER.exec(trace(text).text);
|
|
56
|
+
if (match === null)
|
|
57
|
+
return null;
|
|
58
|
+
const indent = match[1] ?? '';
|
|
59
|
+
const body = match[2] ?? '';
|
|
60
|
+
if (indent === '')
|
|
61
|
+
return body;
|
|
62
|
+
return body
|
|
63
|
+
.split('\n')
|
|
64
|
+
.map((line) => (line.startsWith(indent) ? line.slice(indent.length) : line))
|
|
65
|
+
.join('\n');
|
|
66
|
+
}
|
|
67
|
+
/** The text after Mermaid's frontmatter and directive steps, before its comment removal. */
|
|
68
|
+
function withoutPreamble(text) {
|
|
69
|
+
return cut(cut(trace(text), FRONTMATTER), DIRECTIVE);
|
|
70
|
+
}
|
|
71
|
+
/** The text Mermaid parses, as its four line-moving steps leave it, with each unit's origin line. */
|
|
72
|
+
export function mermaidPreprocessed(text) {
|
|
73
|
+
const uncommented = cut(withoutPreamble(text), COMMENT);
|
|
74
|
+
const lead = uncommented.text.length - uncommented.text.trimStart().length;
|
|
75
|
+
return { text: uncommented.text.slice(lead), origin: uncommented.origin.slice(lead) };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A function from Mermaid's 1-based line to the block's, or `null` when Mermaid's text has no such
|
|
79
|
+
* line.
|
|
80
|
+
*/
|
|
81
|
+
export function mermaidLineMap(text) {
|
|
82
|
+
const { text: parsed, origin } = mermaidPreprocessed(text);
|
|
83
|
+
const starts = [];
|
|
84
|
+
if (origin[0] !== undefined)
|
|
85
|
+
starts.push(origin[0]);
|
|
86
|
+
for (let i = 0; i < parsed.length - 1; i += 1) {
|
|
87
|
+
const next = origin[i + 1];
|
|
88
|
+
if (parsed[i] === '\n' && next !== undefined)
|
|
89
|
+
starts.push(next);
|
|
90
|
+
}
|
|
91
|
+
return (mermaidLine) => starts[mermaidLine - 1] ?? null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Does any line of the block carry a `%%` comment after other text? Two of Mermaid's lexers lose
|
|
95
|
+
* lines after one (spike 0428 Q2), so a verdict for such a block claims no line. Read after the
|
|
96
|
+
* frontmatter and directive steps, so a directive's own closing `}%%` is not a comment.
|
|
97
|
+
*/
|
|
98
|
+
export function hasTrailingComment(text) {
|
|
99
|
+
return TRAILING_COMMENT.test(withoutPreamble(text).text);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=mermaid-line-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid-line-map.js","sourceRoot":"","sources":["../../src/parser/mermaid-line-map.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nielspeter/eess-mermaid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Architecture testing for Mermaid class diagrams — the Mermaid dialect of the eess family (formerly mermaidunit)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -27,11 +27,23 @@
|
|
|
27
27
|
},
|
|
28
28
|
"author": "Niels Peter",
|
|
29
29
|
"license": "MIT",
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"jsdom": ">=29.1.1",
|
|
32
|
+
"mermaid": "^11.0.0"
|
|
33
|
+
},
|
|
34
|
+
"peerDependenciesMeta": {
|
|
35
|
+
"jsdom": {
|
|
36
|
+
"optional": true
|
|
37
|
+
},
|
|
38
|
+
"mermaid": {
|
|
39
|
+
"optional": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
30
42
|
"scripts": {
|
|
31
43
|
"prepublishOnly": "npm run build",
|
|
32
44
|
"langium:gen": "langium generate --file langium-config.json",
|
|
33
45
|
"prebuild": "rm -rf dist",
|
|
34
|
-
"build": "npm run langium:gen && tsc -p tsconfig.build.json && chmod +x dist/cli/bin.js",
|
|
46
|
+
"build": "npm run langium:gen && tsc -p tsconfig.build.json && node -e \"require('node:fs').cpSync('src/mermaid-js/mermaid-worker.mjs', 'dist/mermaid-js/mermaid-worker.mjs')\" && chmod +x dist/cli/bin.js",
|
|
35
47
|
"test": "vitest run",
|
|
36
48
|
"test:watch": "vitest",
|
|
37
49
|
"typecheck": "tsc --noEmit"
|
|
@@ -44,8 +56,12 @@
|
|
|
44
56
|
"eess"
|
|
45
57
|
],
|
|
46
58
|
"dependencies": {
|
|
47
|
-
"@nielspeter/eess": "^0.7.
|
|
59
|
+
"@nielspeter/eess": "^0.7.1",
|
|
48
60
|
"jiti": "^2.7.0",
|
|
49
61
|
"langium": "^4.2.3"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"jsdom": "29.1.1",
|
|
65
|
+
"mermaid": "11.17.2"
|
|
50
66
|
}
|
|
51
67
|
}
|