@jarenjs/md 0.49.2 → 0.56.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 +14 -14
- package/dist/types/directives.d.ts +6 -4
- package/docs/MD-FORMAT.md +1 -1
- package/package.json +4 -4
- package/src/directives.js +6 -4
package/README.md
CHANGED
|
@@ -365,7 +365,7 @@ an editable data pane.
|
|
|
365
365
|
### Directives — a number a machine derives and a human reads
|
|
366
366
|
|
|
367
367
|
```markdown
|
|
368
|
-
Jaren is <!--
|
|
368
|
+
Jaren is <!--fact:jsonpath.ctsRatio-->8.8<!--/fact-->x faster across the CTS queries.
|
|
369
369
|
```
|
|
370
370
|
|
|
371
371
|
Every markdown renderer on earth drops HTML comments, so GitHub, an editor
|
|
@@ -389,7 +389,7 @@ being true. It splices only the spans between markers — a document with
|
|
|
389
389
|
no directives comes back byte-identical — because `toMarkdown` is a
|
|
390
390
|
canonicalizing printer and re-printing a hand-written README would reflow
|
|
391
391
|
every list for no reason. This repository's own figures work exactly this
|
|
392
|
-
way (`npm run docs:
|
|
392
|
+
way (`npm run docs:derive`, `npm run docs:check`).
|
|
393
393
|
|
|
394
394
|
The layer never interprets the payload: `bm` puts a derivation key there,
|
|
395
395
|
`mdx` puts a query expression, and the vocabulary belongs to the
|
|
@@ -451,25 +451,25 @@ active policy ([PLUGINS.md](docs/PLUGINS.md) §5, [MD-FORMAT.md](docs/MD-FORMAT.
|
|
|
451
451
|
|
|
452
452
|
## Performance contract
|
|
453
453
|
|
|
454
|
-
Measured, not claimed — `npm run benchmark:markdown`, <!--
|
|
454
|
+
Measured, not claimed — `npm run benchmark:markdown`, <!--fact:md.measured-->2026-08-11, Node v24.19.0<!--/fact-->
|
|
455
455
|
(run it yourself; micro-timings vary ±15%):
|
|
456
456
|
|
|
457
|
-
- **Parse to AST**: <!--
|
|
457
|
+
- **Parse to AST**: <!--fact:md.parseTimes-->~0.099 ms for a typical ~2 kB document, ~0.51 ms for ~10 kB, ~4.8 ms for ~100 kB<!--/fact--> — linear in input. A CPU profile puts the
|
|
458
458
|
inline phase at ~36% of that and the source hash for `meta.hash` at
|
|
459
459
|
~10%; the block scan, the obvious suspect, is ~14%. (Replacing one
|
|
460
460
|
`/\s+$/` regex at paragraph close with a scan was worth 4–17%
|
|
461
461
|
depending on how paragraph-dense the document is — measured as an A/B
|
|
462
462
|
on this corpus, because the same change looked like noise on a
|
|
463
463
|
differently shaped one.)
|
|
464
|
-
- **Parse + render to HTML** (the cross-engine row, `toHtml`): takes <!--
|
|
464
|
+
- **Parse + render to HTML** (the cross-engine row, `toHtml`): takes <!--fact:md.vsPeers-->0.6–1.1<!--/fact-->x the time `marked` and `markdown-it` take — <!--fact:md.vsPeersDetail-->faster than both at every size measured except one — `markdown-it` is ahead at ~10 kB (1.1x)<!--/fact--> — and is <!--fact:md.vsMicromark-->12.9–21.4<!--/fact-->x faster than `micromark`, on the same GFM documents.
|
|
465
465
|
Through the **vnode** path the same documents cost roughly twice that
|
|
466
466
|
— keys, memoization and a tree the patcher can reconcile are not free,
|
|
467
467
|
and the benchmark publishes that row beside this one rather than
|
|
468
468
|
quoting only the flattering half.
|
|
469
469
|
- **Where the time goes** (~100 kB, the phase split the benchmark now
|
|
470
|
-
prints and publishes): <!--
|
|
471
|
-
the parse, is the expensive half — and <!--
|
|
472
|
-
computing the content-hash **keys** (<!--
|
|
470
|
+
prints and publishes): <!--fact:md.phaseSplit-->parse 35%, AST→vnode 50%, vnode→HTML 16%<!--/fact-->. The projection, not
|
|
471
|
+
the parse, is the expensive half — and <!--fact:md.keyCost-->53%<!--/fact--> of the projection is
|
|
472
|
+
computing the content-hash **keys** (<!--fact:md.unkeyedMs-->3.3 ms against 6.9 ms<!--/fact--> without them).
|
|
473
473
|
Keys are what let the patcher reorder blocks instead of rebuilding
|
|
474
474
|
them, so they are worth it for a tree that will be patched — and worth
|
|
475
475
|
nothing to a caller that renders once and throws the tree away. That
|
|
@@ -483,7 +483,7 @@ Measured, not claimed — `npm run benchmark:markdown`, <!--bm:md.measured-->202
|
|
|
483
483
|
output will be patched, and guessing wrong turns O(1) reconciliation
|
|
484
484
|
into a rebuild with no error to show for it.
|
|
485
485
|
- **The compiled fast path**: `compileMarkdown(...).toVnode()` returns
|
|
486
|
-
the cached projection in <!--
|
|
486
|
+
the cached projection in <!--fact:md.cachedNs-->39–82<!--/fact--> ns — and because block vnodes carry
|
|
487
487
|
content-hash keys and unchanged AST nodes emit reference-equal
|
|
488
488
|
vnodes, the view patcher skips unchanged blocks in O(1). A JSLT
|
|
489
489
|
identity transform returns the document by reference; a partial
|
|
@@ -491,12 +491,12 @@ Measured, not claimed — `npm run benchmark:markdown`, <!--bm:md.measured-->202
|
|
|
491
491
|
the one-shot HTML render — is what this package is optimized for.
|
|
492
492
|
- **CommonMark scorecard**, both paths, because the difference between
|
|
493
493
|
them *is* the safety boundary:
|
|
494
|
-
- `toHtml` (`html: 'raw'`, the like-for-like row): <!--
|
|
494
|
+
- `toHtml` (`html: 'raw'`, the like-for-like row): <!--fact:md.scorecard-->655 of 655 (100.0%)<!--/fact-->; for scale, <!--fact:md.scorecardPeers-->marked 620, markdown-it 655, micromark 650<!--/fact-->.
|
|
495
495
|
**No dialect gap remains on this path**: every example the spec
|
|
496
496
|
contains passes, and the round-trip suite additionally asserts that
|
|
497
497
|
all 655 survive `parseMarkdown → toMarkdown → parseMarkdown` with an
|
|
498
498
|
identical AST and an unchanged canonical form.
|
|
499
|
-
- `mdToVnode` + SSR: <!--
|
|
499
|
+
- `mdToVnode` + SSR: <!--fact:md.scorecardVnode-->593 of 655 (90.5%)<!--/fact-->. **Every** example the two
|
|
500
500
|
paths disagree on contains raw HTML — asserted, not asserted-at:
|
|
501
501
|
[`test/md/to-html.test.js`](../../test/md/to-html.test.js) checks that no
|
|
502
502
|
vnode-path failure is free of an `html` node. The spec renders raw
|
|
@@ -508,9 +508,9 @@ Measured, not claimed — `npm run benchmark:markdown`, <!--bm:md.measured-->202
|
|
|
508
508
|
- **GFM extension scorecard**, the five extension sections of the GFM
|
|
509
509
|
specification with every engine's extensions switched on — because the
|
|
510
510
|
CommonMark corpus says nothing about any of them, and the part of the
|
|
511
|
-
dialect every engine advertises was the only part nobody measured: <!--
|
|
512
|
-
path; for scale, <!--
|
|
513
|
-
Autolink literals are <!--
|
|
511
|
+
dialect every engine advertises was the only part nobody measured: <!--fact:md.gfmScorecard-->22 of 24 (91.7%)<!--/fact--> through `toHtml`, and <!--fact:md.gfmScorecardVnode-->22 of 24 (91.7%)<!--/fact--> through the vnode
|
|
512
|
+
path; for scale, <!--fact:md.gfmPeers-->marked 22, markdown-it 14, micromark 23<!--/fact-->.
|
|
513
|
+
Autolink literals are <!--fact:md.gfmAutolinks-->11 of 11<!--/fact-->, ahead of every rival here. The two
|
|
514
514
|
this package does not pass are **stated boundaries, not to-do items**:
|
|
515
515
|
- **table alignment is written as `style="text-align:center"`, not the
|
|
516
516
|
deprecated `align` attribute** (1 example). Both render identically;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* human reads.
|
|
4
4
|
*
|
|
5
5
|
* ```markdown
|
|
6
|
-
* Jaren is <!--
|
|
6
|
+
* Jaren is <!--fact:jsonpath.ctsRatio-->23.1<!--/fact-->x faster on the CTS mean.
|
|
7
7
|
* ```
|
|
8
8
|
*
|
|
9
9
|
* Every markdown renderer on earth drops HTML comments, so GitHub, an
|
|
@@ -18,11 +18,13 @@
|
|
|
18
18
|
* as literal gibberish anywhere the transform has not run — usable only
|
|
19
19
|
* in documents nobody reads raw.
|
|
20
20
|
*
|
|
21
|
-
* **The layer never interprets the payload.** `
|
|
22
|
-
* there, `mdx` puts a query expression; the vocabulary belongs to the
|
|
21
|
+
* **The layer never interprets the payload.** `fact` puts a derivation
|
|
22
|
+
* key there, `mdx` puts a query expression; the vocabulary belongs to the
|
|
23
23
|
* consumer, and this module owns exactly one thing — the marker grammar
|
|
24
24
|
* and the pairing — so two consumers cannot disagree about what a
|
|
25
|
-
* directive is.
|
|
25
|
+
* directive is. The namespace is the consumer's too, and one consumer
|
|
26
|
+
* SHOULD claim one: pairing and the orphan report are per-namespace, so a
|
|
27
|
+
* repository that spells the same idea two ways has two blind spots.
|
|
26
28
|
*
|
|
27
29
|
* There are two ways in, because there are two questions:
|
|
28
30
|
*
|
package/docs/MD-FORMAT.md
CHANGED
|
@@ -411,7 +411,7 @@ A **directive** is a value in a document that a machine derives and a
|
|
|
411
411
|
human reads:
|
|
412
412
|
|
|
413
413
|
```markdown
|
|
414
|
-
Jaren is <!--
|
|
414
|
+
Jaren is <!--fact:jsonpath.ctsRatio-->23.1<!--/fact-->x faster on the CTS mean.
|
|
415
415
|
```
|
|
416
416
|
|
|
417
417
|
The carrier is an HTML comment, and the choice is the whole design:
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarenjs/md",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.56.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"types": "./dist/types/index.d.ts",
|
|
@@ -73,8 +73,8 @@
|
|
|
73
73
|
"prepack": "npm run build:types"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@jarenjs/core": "^0.
|
|
77
|
-
"@jarenjs/mermaid": "^0.
|
|
78
|
-
"@jarenjs/view": "^0.
|
|
76
|
+
"@jarenjs/core": "^0.56.0",
|
|
77
|
+
"@jarenjs/mermaid": "^0.56.0",
|
|
78
|
+
"@jarenjs/view": "^0.56.0"
|
|
79
79
|
}
|
|
80
80
|
}
|
package/src/directives.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* human reads.
|
|
5
5
|
*
|
|
6
6
|
* ```markdown
|
|
7
|
-
* Jaren is <!--
|
|
7
|
+
* Jaren is <!--fact:jsonpath.ctsRatio-->23.1<!--/fact-->x faster on the CTS mean.
|
|
8
8
|
* ```
|
|
9
9
|
*
|
|
10
10
|
* Every markdown renderer on earth drops HTML comments, so GitHub, an
|
|
@@ -19,11 +19,13 @@
|
|
|
19
19
|
* as literal gibberish anywhere the transform has not run — usable only
|
|
20
20
|
* in documents nobody reads raw.
|
|
21
21
|
*
|
|
22
|
-
* **The layer never interprets the payload.** `
|
|
23
|
-
* there, `mdx` puts a query expression; the vocabulary belongs to the
|
|
22
|
+
* **The layer never interprets the payload.** `fact` puts a derivation
|
|
23
|
+
* key there, `mdx` puts a query expression; the vocabulary belongs to the
|
|
24
24
|
* consumer, and this module owns exactly one thing — the marker grammar
|
|
25
25
|
* and the pairing — so two consumers cannot disagree about what a
|
|
26
|
-
* directive is.
|
|
26
|
+
* directive is. The namespace is the consumer's too, and one consumer
|
|
27
|
+
* SHOULD claim one: pairing and the orphan report are per-namespace, so a
|
|
28
|
+
* repository that spells the same idea two ways has two blind spots.
|
|
27
29
|
*
|
|
28
30
|
* There are two ways in, because there are two questions:
|
|
29
31
|
*
|