@takazudo/zfb-md-wasm 2.7.0 → 2.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 +153 -49
- package/dist/parse-browser.d.ts +12 -0
- package/dist/parse-browser.js +17 -0
- package/dist/parse-browser.js.map +1 -0
- package/dist/parse.d.ts +12 -0
- package/dist/parse.js +23 -0
- package/dist/parse.js.map +1 -0
- package/dist/render-browser.d.ts +11 -0
- package/dist/render-browser.js +16 -0
- package/dist/render-browser.js.map +1 -0
- package/dist/render.d.ts +11 -0
- package/dist/render.js +22 -0
- package/dist/render.js.map +1 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +9 -12
- package/dist/runtime.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.js.map +1 -1
- package/dist/wasm/zfb_md_wasm_bg.wasm +0 -0
- package/dist/wasm/zfb_md_wasm_glue.zfb-resource.d.mts +3 -1
- package/dist/wasm/zfb_md_wasm_glue.zfb-resource.mjs +3 -1
- package/dist/wasm-highlight/zfb_md_wasm_highlight_bg.wasm +0 -0
- package/dist/wasm-parse/zfb_md_wasm_parse_bg.wasm +0 -0
- package/dist/wasm-parse/zfb_md_wasm_parse_bg.wasm.d.ts +10 -0
- package/dist/wasm-parse/zfb_md_wasm_parse_glue.zfb-resource.d.mts +108 -0
- package/dist/wasm-parse/zfb_md_wasm_parse_glue.zfb-resource.mjs +300 -0
- package/dist/wasm-render/zfb_md_wasm_render_bg.wasm +0 -0
- package/dist/wasm-render/zfb_md_wasm_render_bg.wasm.d.ts +10 -0
- package/dist/wasm-render/zfb_md_wasm_render_glue.zfb-resource.d.mts +68 -0
- package/dist/wasm-render/zfb_md_wasm_render_glue.zfb-resource.mjs +260 -0
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -22,7 +22,69 @@ binary directly.
|
|
|
22
22
|
pnpm add @takazudo/zfb-md-wasm
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## Choose an entry
|
|
26
|
+
|
|
27
|
+
The package has four additive entries. Keep using `.` for the complete current
|
|
28
|
+
API (`compile` plus render, parse, and highlight); root imports do not need a
|
|
29
|
+
migration. `./highlight` is also backward-compatible. New `./render` and
|
|
30
|
+
`./parse` entries are isolated **SWC-free** graphs: they omit `swc_core` and
|
|
31
|
+
`zfb-render` but intentionally retain `zfb-content` and `syntect-fancy`.
|
|
32
|
+
`./parse` is not syntect-free.
|
|
33
|
+
|
|
34
|
+
| Entry | Exact runtime values | Exact exported types |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| `.` | `init`, `compile`, `renderHtml`, `parseToAst`, `highlightCode`, `version`, `__forceTrapForTests`, `__getTrapRecoveryStateForTests`, `toMdastRoot`, `ZfbMdWasmTrapError`, `ZfbMdWasmTrapRecoveryLimitError`, `MdastAdapterError` | Full current compile/render/parse/raw-mdast/highlight surface |
|
|
37
|
+
| `./highlight` | `init`, `highlightCode`, `version`, `__forceTrapForTests`, `__getTrapRecoveryStateForTests`, `ZfbMdWasmTrapError`, `ZfbMdWasmTrapRecoveryLimitError` | `HighlightRole`, `HighlightCodeOptions`, `HighlightCodeResult`, `HighlightDiagnostic`, `HighlightDiagnosticSource` |
|
|
38
|
+
| `./render` | `init`, `renderHtml`, `version`, `ZfbMdWasmTrapError`, `ZfbMdWasmTrapRecoveryLimitError`, `__forceTrapForTests`, `__getTrapRecoveryStateForTests` | `RenderHtmlResult`, `Diagnostic`, `DiagnosticSource`, `ZfbMdWasmOptions`, `ParseDialect`, `PipelineOptions`, `GfmOptions`, `CodeHighlightMode`, `CodeHighlightOptions`, `MarkdownFeaturesConfig`, `JsxRuntime`, `HighlightRole` |
|
|
39
|
+
| `./parse` | `init`, `parseToAst`, `toMdastRoot`, `MdastAdapterError`, `version`, `ZfbMdWasmTrapError`, `ZfbMdWasmTrapRecoveryLimitError`, `__forceTrapForTests`, `__getTrapRecoveryStateForTests` | `ParseToAstResult`, `ParseToAstOptions`, `ParseDialect`, `FrontmatterPolicy`, `ParsePipelineOptions`, `Diagnostic`, `DiagnosticSource`, `AstPoint`, `AstPosition`, `RawMdastData`, `MarkdownRsStop`, `MdastNode`, `MdastRoot`, `UnknownMdastNode`, `Root`, `Paragraph`, `Heading`, `ThematicBreak`, `Blockquote`, `List`, `ListItem`, `Html`, `Code`, `Definition`, `Text`, `DirectiveNodeBase`, `ContainerDirective`, `LeafDirective`, `TextDirective`, `Emphasis`, `Strong`, `InlineCode`, `Break`, `Link`, `Image`, `ReferenceKind`, `LinkReference`, `ImageReference`, `FootnoteDefinition`, `FootnoteReference`, `TableAlign`, `Table`, `TableRow`, `TableCell`, `Delete`, `Yaml`, `MdxFlowExpression`, `MdxTextExpression`, `MdxJsxFlowElement`, `MdxJsxTextElement`, `MdxJsxAttributeContent`, `MdxJsxAttribute`, `MdxJsxAttributeValueExpression`, `MdxJsxExpressionAttribute` |
|
|
40
|
+
|
|
41
|
+
The focused entries own private resource pairs:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
wasm-render/zfb_md_wasm_render_glue.zfb-resource.mjs
|
|
45
|
+
wasm-render/zfb_md_wasm_render_bg.wasm
|
|
46
|
+
wasm-parse/zfb_md_wasm_parse_glue.zfb-resource.mjs
|
|
47
|
+
wasm-parse/zfb_md_wasm_parse_bg.wasm
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Each also has only its matching declaration sidecars. Every entry creates its
|
|
51
|
+
own compiled-module, wasm-instance, generation, retry, and terminal state.
|
|
52
|
+
Importing multiple entries intentionally loads independent pairs and instances;
|
|
53
|
+
it does not deduplicate their resources.
|
|
54
|
+
|
|
55
|
+
Migration is only needed when a root consumer calls one focused function:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// Direct Node import and browser-aware bundler import.
|
|
59
|
+
import { renderHtml } from "@takazudo/zfb-md-wasm/render";
|
|
60
|
+
import { parseToAst, toMdastRoot } from "@takazudo/zfb-md-wasm/parse";
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For browser lazy loading, import from the user action. The conditional browser
|
|
64
|
+
entry uses static URL edges for only that entry's own resource pair:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
button.addEventListener("click", async () => {
|
|
68
|
+
const { renderHtml } = await import("@takazudo/zfb-md-wasm/render");
|
|
69
|
+
const { html } = await renderHtml(source, { filename: "preview.md" });
|
|
70
|
+
preview.innerHTML = html ?? "";
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
parseButton.addEventListener("click", async () => {
|
|
74
|
+
const { parseToAst, toMdastRoot } = await import("@takazudo/zfb-md-wasm/parse");
|
|
75
|
+
const parsed = await parseToAst(source, { filename: "preview.md" });
|
|
76
|
+
const root = parsed.ast === null ? null : toMdastRoot(parsed.ast);
|
|
77
|
+
inspect(root);
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`compile()` remains root-only. It returns module source, not an evaluated
|
|
82
|
+
module; host evaluation must supply the JSX runtime and components. Controlled
|
|
83
|
+
consumer code may interpret an already-parsed AST in a controlled AST-to-React
|
|
84
|
+
renderer, but no slim entry evaluates author JavaScript. `renderHtml` is not a sanitizer and raw HTML remains
|
|
85
|
+
untrusted; MDX JSX, expression, and ESM-shaped AST nodes are inert data.
|
|
86
|
+
|
|
87
|
+
## Root API
|
|
26
88
|
|
|
27
89
|
Both functions take the markdown/MDX `source` and an options object (every
|
|
28
90
|
field optional; `{}` selects all defaults). Both return a result object plus a
|
|
@@ -72,14 +134,17 @@ plain-markdown preview when you don't need to evaluate a component module.
|
|
|
72
134
|
```ts
|
|
73
135
|
import { renderHtml } from "@takazudo/zfb-md-wasm";
|
|
74
136
|
|
|
75
|
-
const { html, frontmatter, diagnostics } = await renderHtml("
|
|
137
|
+
const { html, frontmatter, diagnostics } = await renderHtml("Budget <8 ms\n", {
|
|
76
138
|
filename: "post.md",
|
|
77
139
|
});
|
|
78
|
-
// html -> "<
|
|
140
|
+
// html -> "<p>Budget <8 ms</p>"
|
|
79
141
|
```
|
|
80
142
|
|
|
81
|
-
`renderHtml`
|
|
82
|
-
|
|
143
|
+
`renderHtml` infers CommonMark for `.md` and MDX for `.mdx`; an explicit
|
|
144
|
+
`dialect: "markdown" | "mdx"` overrides either valid extension. Omitting the
|
|
145
|
+
filename uses `<anonymous>.md`, hence CommonMark. `compile` remains MDX-only
|
|
146
|
+
and accepts/ignores `dialect`, while `renderHtml` accepts/ignores
|
|
147
|
+
`jsxRuntime` / `development`, so one options object can serve both tiers.
|
|
83
148
|
|
|
84
149
|
### `version()` / `init()`
|
|
85
150
|
|
|
@@ -99,7 +164,7 @@ Shiki classes.
|
|
|
99
164
|
|
|
100
165
|
If `highlightCode` is the only thing you use, import it from
|
|
101
166
|
`@takazudo/zfb-md-wasm/highlight` instead of the package root — that entry
|
|
102
|
-
ships a separate
|
|
167
|
+
ships a separate highlight-only wasm artifact with no `compile`/`renderHtml`
|
|
103
168
|
(and no md/MDX/JSX pipeline behind them at all). Same function, same result
|
|
104
169
|
shape, same `init()`/`version()`; see "Artifact size" below for the byte
|
|
105
170
|
savings.
|
|
@@ -110,7 +175,7 @@ import {
|
|
|
110
175
|
type HighlightCodeOptions,
|
|
111
176
|
type HighlightCodeResult,
|
|
112
177
|
} from "@takazudo/zfb-md-wasm";
|
|
113
|
-
// or, for the
|
|
178
|
+
// or, for the highlight-only artifact:
|
|
114
179
|
// } from "@takazudo/zfb-md-wasm/highlight";
|
|
115
180
|
|
|
116
181
|
const output: HighlightCodeResult = await highlightCode("const answer = 42;", {
|
|
@@ -403,25 +468,37 @@ for your own environment.
|
|
|
403
468
|
|
|
404
469
|
## Browser loading and emitted resources
|
|
405
470
|
|
|
406
|
-
|
|
407
|
-
|
|
471
|
+
Every entry has a `browser` export condition. Its browser entry imports the
|
|
472
|
+
generated glue and Wasm binary through an explicit bundler `?url` asset
|
|
408
473
|
contract. Vite and zfb's pinned esbuild setup therefore keep separate resource
|
|
409
|
-
edges for exactly
|
|
410
|
-
`zfb_md_wasm_bg.wasm`; a zfb production build emits them under hashed names:
|
|
474
|
+
edges for exactly its own pair. The focused pairs are:
|
|
411
475
|
|
|
412
476
|
```text
|
|
413
|
-
|
|
414
|
-
|
|
477
|
+
wasm-render/zfb_md_wasm_render_glue.zfb-resource.mjs
|
|
478
|
+
wasm-render/zfb_md_wasm_render_bg.wasm
|
|
479
|
+
wasm-parse/zfb_md_wasm_parse_glue.zfb-resource.mjs
|
|
480
|
+
wasm-parse/zfb_md_wasm_parse_bg.wasm
|
|
415
481
|
```
|
|
416
482
|
|
|
483
|
+
Root and highlight retain their existing `wasm/` and `wasm-highlight/` pairs;
|
|
484
|
+
each directory is closed with its matching glue/wasm declaration sidecars. A
|
|
485
|
+
zfb production build emits each selected pair under hashed names.
|
|
486
|
+
|
|
417
487
|
Keep the package import in a user action when first-load cost matters:
|
|
418
488
|
|
|
419
489
|
```ts
|
|
420
490
|
button.addEventListener("click", async () => {
|
|
421
|
-
const {
|
|
422
|
-
const result = await
|
|
491
|
+
const { renderHtml } = await import("@takazudo/zfb-md-wasm/render");
|
|
492
|
+
const result = await renderHtml(editor.value, { filename: "preview.md" });
|
|
423
493
|
preview.innerHTML = result.html ?? "";
|
|
424
494
|
});
|
|
495
|
+
|
|
496
|
+
parseButton.addEventListener("click", async () => {
|
|
497
|
+
const { parseToAst, toMdastRoot } = await import("@takazudo/zfb-md-wasm/parse");
|
|
498
|
+
const parsed = await parseToAst(editor.value, { filename: "preview.md" });
|
|
499
|
+
const root = parsed.ast === null ? null : toMdastRoot(parsed.ast);
|
|
500
|
+
inspect(root);
|
|
501
|
+
});
|
|
425
502
|
```
|
|
426
503
|
|
|
427
504
|
That import/call boundary keeps both resources unloaded before the action;
|
|
@@ -432,18 +509,17 @@ replace the static imports with source paths or manually copied resource
|
|
|
432
509
|
files, which breaks the emitted URL graph. No Vite plugin, alias, or
|
|
433
510
|
package-specific consumer configuration is required.
|
|
434
511
|
|
|
435
|
-
The `./highlight` subpath
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
`@takazudo/zfb-md-wasm/highlight` in the same bundle loads BOTH wasm
|
|
440
|
-
artifacts — pick one entry per bundle.
|
|
512
|
+
The `./highlight` subpath has the identical `browser` export condition and
|
|
513
|
+
resource-loading contract, pointed at its own separate resources. Importing
|
|
514
|
+
multiple entries in the same bundle intentionally loads each private pair and
|
|
515
|
+
creates independent wasm state; no entry evicts or shares another's instance.
|
|
441
516
|
|
|
442
517
|
## Options shape
|
|
443
518
|
|
|
444
519
|
```ts
|
|
445
520
|
interface ZfbMdWasmOptions {
|
|
446
521
|
filename?: string; // must end .md/.mdx; drives frontmatter dispatch + diagnostics
|
|
522
|
+
dialect?: "markdown" | "mdx"; // renderHtml only; inferred from filename when absent
|
|
447
523
|
jsxRuntime?: "preact" | "react"; // compile only; default "preact"
|
|
448
524
|
development?: boolean; // compile only; default false
|
|
449
525
|
pipeline?: {
|
|
@@ -574,9 +650,20 @@ alias.
|
|
|
574
650
|
## Node usage
|
|
575
651
|
|
|
576
652
|
For tests and tooling, the package loads and runs under Node ≥ 20 with no extra
|
|
577
|
-
setup
|
|
578
|
-
|
|
579
|
-
|
|
653
|
+
setup. Direct imports select the resource pair that matches the operation:
|
|
654
|
+
|
|
655
|
+
```ts
|
|
656
|
+
import { renderHtml } from "@takazudo/zfb-md-wasm/render";
|
|
657
|
+
import { parseToAst, toMdastRoot } from "@takazudo/zfb-md-wasm/parse";
|
|
658
|
+
|
|
659
|
+
const { html } = await renderHtml("# Hello from Node\n");
|
|
660
|
+
const parsed = await parseToAst("# Hello from Node\n", { filename: "post.md" });
|
|
661
|
+
const root = parsed.ast === null ? null : toMdastRoot(parsed.ast);
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
The root import remains the compatibility choice for code that also calls
|
|
665
|
+
`compile`, and the existing highlight import remains compatible. This is also
|
|
666
|
+
how the package's vitest suite and parse benchmark exercise the built wasm.
|
|
580
667
|
|
|
581
668
|
## Parity guarantee & limitations
|
|
582
669
|
|
|
@@ -593,37 +680,54 @@ suite gates exact-match). Deliberate limitations of the browser build:
|
|
|
593
680
|
- **No cross-file features.** Route-table link resolution and cross-file anchor
|
|
594
681
|
resolution need the whole project graph, which a single-document browser call
|
|
595
682
|
doesn't have.
|
|
596
|
-
- **
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
683
|
+
- **Choose a focused artifact for non-compile calls.** The root remains the
|
|
684
|
+
compatibility entry and carries the complete compiler graph. `./highlight`
|
|
685
|
+
keeps its public API and resources while the post-#2449/#2450 graph is
|
|
686
|
+
proven SWC-free. `./render` and `./parse` are also SWC-free and omit `zfb-render`;
|
|
687
|
+
parse intentionally retains `zfb-content`/`syntect-fancy`, so it is not
|
|
688
|
+
syntect-free. Use `./render` or `./parse` when a consumer does not need
|
|
689
|
+
`compile`; root and highlight callers otherwise require no migration.
|
|
690
|
+
- **`compile` is the execution boundary.** It returns ES-module source and
|
|
691
|
+
only the root entry exposes it. Host code must explicitly evaluate that
|
|
692
|
+
source and provide the JSX runtime/components. Controlled consumer code may
|
|
693
|
+
interpret an already-parsed AST; no slim entry evaluates author JavaScript.
|
|
694
|
+
- **`renderHtml` is not a sanitizer.** Raw HTML remains untrusted, and JSX,
|
|
695
|
+
expression, or ESM-shaped AST nodes from MDX remain inert data.
|
|
696
|
+
- **`renderHtml` selects syntax from the filename.** `.md` uses CommonMark,
|
|
697
|
+
`.mdx` uses MDX, and an explicit `dialect` overrides either valid extension.
|
|
698
|
+
`compile` remains MDX-only.
|
|
699
|
+
- **Grammar subsetting is not built.** All four artifacts ship every bundled
|
|
603
700
|
syntect grammar; there is no per-language allowlist knob.
|
|
604
701
|
- **Syntax highlighting uses syntect's `fancy-regex` backend** (native zfb uses
|
|
605
702
|
`oniguruma`, which can't compile to wasm). The two are byte-identical on
|
|
606
703
|
zfb's fixture corpus; any grammar-level divergences are tracked in the
|
|
607
704
|
crate's informational backend-divergence test.
|
|
608
705
|
|
|
609
|
-
## Artifact size
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
|
617
|
-
|
|
|
618
|
-
|
|
|
619
|
-
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
706
|
+
## Artifact size and locked ceilings
|
|
707
|
+
|
|
708
|
+
The decision snapshot uses the optimized final wasm after wasm-bindgen and
|
|
709
|
+
wasm-opt, Node `gzipSync(..., { level: 9 })`, and glue bytes/gzip. These exact
|
|
710
|
+
#2447 rows are measurements, not permanent promises:
|
|
711
|
+
|
|
712
|
+
| Entry/graph | final wasm | gzip-9 | glue | glue gzip-9 |
|
|
713
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
714
|
+
| root (full) | 3,336,933 B | 1,491,970 B | 14,881 B | 4,151 B |
|
|
715
|
+
| highlight (historical current SWC-retaining baseline) | 1,484,705 B | 767,009 B | 8,758 B | 2,637 B |
|
|
716
|
+
| render (selected SWC-free candidate) | 2,123,309 B | 1,032,557 B | 8,637 B | 2,597 B |
|
|
717
|
+
| parse (selected SWC-free candidate) | 650,458 B | 289,523 B | 11,141 B | 3,795 B |
|
|
718
|
+
|
|
719
|
+
The measured split package was 3,638,607 B versus 2,314,818 B for the current
|
|
720
|
+
root-plus-highlight package. Locked gzip-9 ceilings are root 1,600,000 B,
|
|
721
|
+
highlight 820,000 B, render 1,100,000 B, and parse 325,000 B; the complete
|
|
722
|
+
packed tarball ceiling is 3,900,000 B. The clean four-step production ceiling
|
|
723
|
+
is 210 seconds; the selected #2447 median was 155.015 s [153.496, 165.977].
|
|
724
|
+
|
|
725
|
+
The highlight row is explicitly historical: #2447's current
|
|
726
|
+
`highlight,compiler-surface` baseline retained `swc_core` because the content
|
|
727
|
+
edge was unconditional. The shipped post-#2449 highlight graph is proven
|
|
728
|
+
SWC-free by #2450's exact parity and no-`swc_core` assertion, with its public API
|
|
729
|
+
and resources unchanged, but its post-gating size was not measured. Do not
|
|
730
|
+
invent or project a highlight byte value.
|
|
627
731
|
|
|
628
732
|
## Error / trap / re-init contract
|
|
629
733
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const init: () => Promise<void>, parseToAst: (source: string, options?: import("./types.js").ParseToAstOptions) => Promise<import("./types.js").ParseToAstResult>, version: () => Promise<string>, __forceTrapForTests: () => Promise<void>, __getTrapRecoveryStateForTests: () => {
|
|
2
|
+
compiledModuleLoads: number;
|
|
3
|
+
currentGeneration: number;
|
|
4
|
+
freshInstanceStarts: number;
|
|
5
|
+
glueImportAttempts: number;
|
|
6
|
+
maxTrapRecoveries: number;
|
|
7
|
+
trapRecoveriesStarted: number;
|
|
8
|
+
terminal: boolean;
|
|
9
|
+
};
|
|
10
|
+
export { MdastAdapterError, toMdastRoot } from "./mdast.js";
|
|
11
|
+
export { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from "./runtime.js";
|
|
12
|
+
export type { ParseToAstResult, ParseToAstOptions, ParseDialect, FrontmatterPolicy, ParsePipelineOptions, Diagnostic, DiagnosticSource, AstPoint, AstPosition, RawMdastData, MarkdownRsStop, MdastNode, MdastRoot, UnknownMdastNode, Root, Paragraph, Heading, ThematicBreak, Blockquote, List, ListItem, Html, Code, Definition, Text, DirectiveNodeBase, ContainerDirective, LeafDirective, TextDirective, Emphasis, Strong, InlineCode, Break, Link, Image, ReferenceKind, LinkReference, ImageReference, FootnoteDefinition, FootnoteReference, TableAlign, Table, TableRow, TableCell, Delete, Yaml, MdxFlowExpression, MdxTextExpression, MdxJsxFlowElement, MdxJsxTextElement, MdxJsxAttributeContent, MdxJsxAttribute, MdxJsxAttributeValueExpression, MdxJsxExpressionAttribute, } from "./types.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import glueHref from "./wasm-parse/zfb_md_wasm_parse_glue.zfb-resource.mjs?url";
|
|
2
|
+
import wasmHref from "./wasm-parse/zfb_md_wasm_parse_bg.wasm?url";
|
|
3
|
+
import { createWasmApi } from "./runtime.js";
|
|
4
|
+
const GLUE_URL = new URL(glueHref, import.meta.url);
|
|
5
|
+
const WASM_URL = new URL(wasmHref, import.meta.url);
|
|
6
|
+
async function loadBrowserWasmBytes() {
|
|
7
|
+
const response = await fetch(WASM_URL);
|
|
8
|
+
if (!response.ok) {
|
|
9
|
+
throw new Error(`zfb-md-wasm: failed to fetch wasm binary: ${response.status} ${response.statusText}`);
|
|
10
|
+
}
|
|
11
|
+
return response.arrayBuffer();
|
|
12
|
+
}
|
|
13
|
+
const api = createWasmApi({ glueUrl: GLUE_URL, loadWasmBytes: loadBrowserWasmBytes });
|
|
14
|
+
export const { init, parseToAst, version, __forceTrapForTests, __getTrapRecoveryStateForTests } = api;
|
|
15
|
+
export { MdastAdapterError, toMdastRoot } from "./mdast.js";
|
|
16
|
+
export { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from "./runtime.js";
|
|
17
|
+
//# sourceMappingURL=parse-browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-browser.js","sourceRoot":"","sources":["../src/parse-browser.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,0DAA0D,CAAC;AAChF,OAAO,QAAQ,MAAM,4CAA4C,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEpD,KAAK,UAAU,oBAAoB;IACjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,6CAA6C,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC,CAAC;AAEtF,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,8BAA8B,EAAE,GAC7F,GAAG,CAAC;AAEN,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC","sourcesContent":["import glueHref from \"./wasm-parse/zfb_md_wasm_parse_glue.zfb-resource.mjs?url\";\nimport wasmHref from \"./wasm-parse/zfb_md_wasm_parse_bg.wasm?url\";\nimport { createWasmApi } from \"./runtime.js\";\n\nconst GLUE_URL = new URL(glueHref, import.meta.url);\nconst WASM_URL = new URL(wasmHref, import.meta.url);\n\nasync function loadBrowserWasmBytes(): Promise<ArrayBuffer> {\n const response = await fetch(WASM_URL);\n if (!response.ok) {\n throw new Error(\n `zfb-md-wasm: failed to fetch wasm binary: ${response.status} ${response.statusText}`,\n );\n }\n return response.arrayBuffer();\n}\n\nconst api = createWasmApi({ glueUrl: GLUE_URL, loadWasmBytes: loadBrowserWasmBytes });\n\nexport const { init, parseToAst, version, __forceTrapForTests, __getTrapRecoveryStateForTests } =\n api;\n\nexport { MdastAdapterError, toMdastRoot } from \"./mdast.js\";\nexport { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from \"./runtime.js\";\nexport type {\n ParseToAstResult,\n ParseToAstOptions,\n ParseDialect,\n FrontmatterPolicy,\n ParsePipelineOptions,\n Diagnostic,\n DiagnosticSource,\n AstPoint,\n AstPosition,\n RawMdastData,\n MarkdownRsStop,\n MdastNode,\n MdastRoot,\n UnknownMdastNode,\n Root,\n Paragraph,\n Heading,\n ThematicBreak,\n Blockquote,\n List,\n ListItem,\n Html,\n Code,\n Definition,\n Text,\n DirectiveNodeBase,\n ContainerDirective,\n LeafDirective,\n TextDirective,\n Emphasis,\n Strong,\n InlineCode,\n Break,\n Link,\n Image,\n ReferenceKind,\n LinkReference,\n ImageReference,\n FootnoteDefinition,\n FootnoteReference,\n TableAlign,\n Table,\n TableRow,\n TableCell,\n Delete,\n Yaml,\n MdxFlowExpression,\n MdxTextExpression,\n MdxJsxFlowElement,\n MdxJsxTextElement,\n MdxJsxAttributeContent,\n MdxJsxAttribute,\n MdxJsxAttributeValueExpression,\n MdxJsxExpressionAttribute,\n} from \"./types.js\";\n"]}
|
package/dist/parse.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const init: () => Promise<void>, parseToAst: (source: string, options?: import("./types.js").ParseToAstOptions) => Promise<import("./types.js").ParseToAstResult>, version: () => Promise<string>, __forceTrapForTests: () => Promise<void>, __getTrapRecoveryStateForTests: () => {
|
|
2
|
+
compiledModuleLoads: number;
|
|
3
|
+
currentGeneration: number;
|
|
4
|
+
freshInstanceStarts: number;
|
|
5
|
+
glueImportAttempts: number;
|
|
6
|
+
maxTrapRecoveries: number;
|
|
7
|
+
trapRecoveriesStarted: number;
|
|
8
|
+
terminal: boolean;
|
|
9
|
+
};
|
|
10
|
+
export { MdastAdapterError, toMdastRoot } from "./mdast.js";
|
|
11
|
+
export { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from "./runtime.js";
|
|
12
|
+
export type { ParseToAstResult, ParseToAstOptions, ParseDialect, FrontmatterPolicy, ParsePipelineOptions, Diagnostic, DiagnosticSource, AstPoint, AstPosition, RawMdastData, MarkdownRsStop, MdastNode, MdastRoot, UnknownMdastNode, Root, Paragraph, Heading, ThematicBreak, Blockquote, List, ListItem, Html, Code, Definition, Text, DirectiveNodeBase, ContainerDirective, LeafDirective, TextDirective, Emphasis, Strong, InlineCode, Break, Link, Image, ReferenceKind, LinkReference, ImageReference, FootnoteDefinition, FootnoteReference, TableAlign, Table, TableRow, TableCell, Delete, Yaml, MdxFlowExpression, MdxTextExpression, MdxJsxFlowElement, MdxJsxTextElement, MdxJsxAttributeContent, MdxJsxAttribute, MdxJsxAttributeValueExpression, MdxJsxExpressionAttribute, } from "./types.js";
|
package/dist/parse.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createWasmApi } from "./runtime.js";
|
|
2
|
+
const GLUE_URL = new URL("./wasm-parse/zfb_md_wasm_parse_glue.zfb-resource.mjs", import.meta.url);
|
|
3
|
+
const WASM_URL = new URL("./wasm-parse/zfb_md_wasm_parse_bg.wasm", import.meta.url);
|
|
4
|
+
async function loadDirectWasmBytes() {
|
|
5
|
+
if (typeof process !== "undefined" && process.versions?.node) {
|
|
6
|
+
const [{ readFile }, { fileURLToPath }] = await Promise.all([
|
|
7
|
+
import("node:fs/promises"),
|
|
8
|
+
import("node:url"),
|
|
9
|
+
]);
|
|
10
|
+
const bytes = await readFile(fileURLToPath(WASM_URL));
|
|
11
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
12
|
+
}
|
|
13
|
+
const response = await fetch(WASM_URL);
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
throw new Error(`zfb-md-wasm: failed to fetch wasm binary: ${response.status} ${response.statusText}`);
|
|
16
|
+
}
|
|
17
|
+
return response.arrayBuffer();
|
|
18
|
+
}
|
|
19
|
+
const api = createWasmApi({ glueUrl: GLUE_URL, loadWasmBytes: loadDirectWasmBytes });
|
|
20
|
+
export const { init, parseToAst, version, __forceTrapForTests, __getTrapRecoveryStateForTests } = api;
|
|
21
|
+
export { MdastAdapterError, toMdastRoot } from "./mdast.js";
|
|
22
|
+
export { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from "./runtime.js";
|
|
23
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,sDAAsD,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClG,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,wCAAwC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEpF,KAAK,UAAU,mBAAmB;IAChC,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC7D,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC1D,MAAM,CAAC,kBAAkB,CAAC;YAC1B,MAAM,CAAC,UAAU,CAAC;SACnB,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAgB,CAAC;IAClG,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,6CAA6C,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAErF,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,8BAA8B,EAAE,GAC7F,GAAG,CAAC;AAEN,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC","sourcesContent":["import { createWasmApi } from \"./runtime.js\";\n\nconst GLUE_URL = new URL(\"./wasm-parse/zfb_md_wasm_parse_glue.zfb-resource.mjs\", import.meta.url);\nconst WASM_URL = new URL(\"./wasm-parse/zfb_md_wasm_parse_bg.wasm\", import.meta.url);\n\nasync function loadDirectWasmBytes(): Promise<ArrayBuffer> {\n if (typeof process !== \"undefined\" && process.versions?.node) {\n const [{ readFile }, { fileURLToPath }] = await Promise.all([\n import(\"node:fs/promises\"),\n import(\"node:url\"),\n ]);\n const bytes = await readFile(fileURLToPath(WASM_URL));\n return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;\n }\n const response = await fetch(WASM_URL);\n if (!response.ok) {\n throw new Error(\n `zfb-md-wasm: failed to fetch wasm binary: ${response.status} ${response.statusText}`,\n );\n }\n return response.arrayBuffer();\n}\n\nconst api = createWasmApi({ glueUrl: GLUE_URL, loadWasmBytes: loadDirectWasmBytes });\n\nexport const { init, parseToAst, version, __forceTrapForTests, __getTrapRecoveryStateForTests } =\n api;\n\nexport { MdastAdapterError, toMdastRoot } from \"./mdast.js\";\nexport { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from \"./runtime.js\";\nexport type {\n ParseToAstResult,\n ParseToAstOptions,\n ParseDialect,\n FrontmatterPolicy,\n ParsePipelineOptions,\n Diagnostic,\n DiagnosticSource,\n AstPoint,\n AstPosition,\n RawMdastData,\n MarkdownRsStop,\n MdastNode,\n MdastRoot,\n UnknownMdastNode,\n Root,\n Paragraph,\n Heading,\n ThematicBreak,\n Blockquote,\n List,\n ListItem,\n Html,\n Code,\n Definition,\n Text,\n DirectiveNodeBase,\n ContainerDirective,\n LeafDirective,\n TextDirective,\n Emphasis,\n Strong,\n InlineCode,\n Break,\n Link,\n Image,\n ReferenceKind,\n LinkReference,\n ImageReference,\n FootnoteDefinition,\n FootnoteReference,\n TableAlign,\n Table,\n TableRow,\n TableCell,\n Delete,\n Yaml,\n MdxFlowExpression,\n MdxTextExpression,\n MdxJsxFlowElement,\n MdxJsxTextElement,\n MdxJsxAttributeContent,\n MdxJsxAttribute,\n MdxJsxAttributeValueExpression,\n MdxJsxExpressionAttribute,\n} from \"./types.js\";\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const init: () => Promise<void>, renderHtml: (source: string, options?: import("./types.js").ZfbMdWasmOptions) => Promise<import("./types.js").RenderHtmlResult>, version: () => Promise<string>, __forceTrapForTests: () => Promise<void>, __getTrapRecoveryStateForTests: () => {
|
|
2
|
+
compiledModuleLoads: number;
|
|
3
|
+
currentGeneration: number;
|
|
4
|
+
freshInstanceStarts: number;
|
|
5
|
+
glueImportAttempts: number;
|
|
6
|
+
maxTrapRecoveries: number;
|
|
7
|
+
trapRecoveriesStarted: number;
|
|
8
|
+
terminal: boolean;
|
|
9
|
+
};
|
|
10
|
+
export { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from "./runtime.js";
|
|
11
|
+
export type { RenderHtmlResult, Diagnostic, DiagnosticSource, ZfbMdWasmOptions, ParseDialect, PipelineOptions, GfmOptions, CodeHighlightMode, CodeHighlightOptions, MarkdownFeaturesConfig, JsxRuntime, HighlightRole, } from "./types.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import glueHref from "./wasm-render/zfb_md_wasm_render_glue.zfb-resource.mjs?url";
|
|
2
|
+
import wasmHref from "./wasm-render/zfb_md_wasm_render_bg.wasm?url";
|
|
3
|
+
import { createWasmApi } from "./runtime.js";
|
|
4
|
+
const GLUE_URL = new URL(glueHref, import.meta.url);
|
|
5
|
+
const WASM_URL = new URL(wasmHref, import.meta.url);
|
|
6
|
+
async function loadBrowserWasmBytes() {
|
|
7
|
+
const response = await fetch(WASM_URL);
|
|
8
|
+
if (!response.ok) {
|
|
9
|
+
throw new Error(`zfb-md-wasm: failed to fetch wasm binary: ${response.status} ${response.statusText}`);
|
|
10
|
+
}
|
|
11
|
+
return response.arrayBuffer();
|
|
12
|
+
}
|
|
13
|
+
const api = createWasmApi({ glueUrl: GLUE_URL, loadWasmBytes: loadBrowserWasmBytes });
|
|
14
|
+
export const { init, renderHtml, version, __forceTrapForTests, __getTrapRecoveryStateForTests } = api;
|
|
15
|
+
export { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from "./runtime.js";
|
|
16
|
+
//# sourceMappingURL=render-browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-browser.js","sourceRoot":"","sources":["../src/render-browser.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,4DAA4D,CAAC;AAClF,OAAO,QAAQ,MAAM,8CAA8C,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEpD,KAAK,UAAU,oBAAoB;IACjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,6CAA6C,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC,CAAC;AAEtF,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,8BAA8B,EAAE,GAC7F,GAAG,CAAC;AAEN,OAAO,EAAE,kBAAkB,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC","sourcesContent":["import glueHref from \"./wasm-render/zfb_md_wasm_render_glue.zfb-resource.mjs?url\";\nimport wasmHref from \"./wasm-render/zfb_md_wasm_render_bg.wasm?url\";\nimport { createWasmApi } from \"./runtime.js\";\n\nconst GLUE_URL = new URL(glueHref, import.meta.url);\nconst WASM_URL = new URL(wasmHref, import.meta.url);\n\nasync function loadBrowserWasmBytes(): Promise<ArrayBuffer> {\n const response = await fetch(WASM_URL);\n if (!response.ok) {\n throw new Error(\n `zfb-md-wasm: failed to fetch wasm binary: ${response.status} ${response.statusText}`,\n );\n }\n return response.arrayBuffer();\n}\n\nconst api = createWasmApi({ glueUrl: GLUE_URL, loadWasmBytes: loadBrowserWasmBytes });\n\nexport const { init, renderHtml, version, __forceTrapForTests, __getTrapRecoveryStateForTests } =\n api;\n\nexport { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from \"./runtime.js\";\nexport type {\n RenderHtmlResult,\n Diagnostic,\n DiagnosticSource,\n ZfbMdWasmOptions,\n ParseDialect,\n PipelineOptions,\n GfmOptions,\n CodeHighlightMode,\n CodeHighlightOptions,\n MarkdownFeaturesConfig,\n JsxRuntime,\n HighlightRole,\n} from \"./types.js\";\n"]}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const init: () => Promise<void>, renderHtml: (source: string, options?: import("./types.js").ZfbMdWasmOptions) => Promise<import("./types.js").RenderHtmlResult>, version: () => Promise<string>, __forceTrapForTests: () => Promise<void>, __getTrapRecoveryStateForTests: () => {
|
|
2
|
+
compiledModuleLoads: number;
|
|
3
|
+
currentGeneration: number;
|
|
4
|
+
freshInstanceStarts: number;
|
|
5
|
+
glueImportAttempts: number;
|
|
6
|
+
maxTrapRecoveries: number;
|
|
7
|
+
trapRecoveriesStarted: number;
|
|
8
|
+
terminal: boolean;
|
|
9
|
+
};
|
|
10
|
+
export { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from "./runtime.js";
|
|
11
|
+
export type { RenderHtmlResult, Diagnostic, DiagnosticSource, ZfbMdWasmOptions, ParseDialect, PipelineOptions, GfmOptions, CodeHighlightMode, CodeHighlightOptions, MarkdownFeaturesConfig, JsxRuntime, HighlightRole, } from "./types.js";
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createWasmApi } from "./runtime.js";
|
|
2
|
+
const GLUE_URL = new URL("./wasm-render/zfb_md_wasm_render_glue.zfb-resource.mjs", import.meta.url);
|
|
3
|
+
const WASM_URL = new URL("./wasm-render/zfb_md_wasm_render_bg.wasm", import.meta.url);
|
|
4
|
+
async function loadDirectWasmBytes() {
|
|
5
|
+
if (typeof process !== "undefined" && process.versions?.node) {
|
|
6
|
+
const [{ readFile }, { fileURLToPath }] = await Promise.all([
|
|
7
|
+
import("node:fs/promises"),
|
|
8
|
+
import("node:url"),
|
|
9
|
+
]);
|
|
10
|
+
const bytes = await readFile(fileURLToPath(WASM_URL));
|
|
11
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
12
|
+
}
|
|
13
|
+
const response = await fetch(WASM_URL);
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
throw new Error(`zfb-md-wasm: failed to fetch wasm binary: ${response.status} ${response.statusText}`);
|
|
16
|
+
}
|
|
17
|
+
return response.arrayBuffer();
|
|
18
|
+
}
|
|
19
|
+
const api = createWasmApi({ glueUrl: GLUE_URL, loadWasmBytes: loadDirectWasmBytes });
|
|
20
|
+
export const { init, renderHtml, version, __forceTrapForTests, __getTrapRecoveryStateForTests } = api;
|
|
21
|
+
export { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from "./runtime.js";
|
|
22
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,wDAAwD,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpG,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,0CAA0C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEtF,KAAK,UAAU,mBAAmB;IAChC,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC7D,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC1D,MAAM,CAAC,kBAAkB,CAAC;YAC1B,MAAM,CAAC,UAAU,CAAC;SACnB,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAgB,CAAC;IAClG,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,6CAA6C,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAErF,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE,8BAA8B,EAAE,GAC7F,GAAG,CAAC;AAEN,OAAO,EAAE,kBAAkB,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC","sourcesContent":["import { createWasmApi } from \"./runtime.js\";\n\nconst GLUE_URL = new URL(\"./wasm-render/zfb_md_wasm_render_glue.zfb-resource.mjs\", import.meta.url);\nconst WASM_URL = new URL(\"./wasm-render/zfb_md_wasm_render_bg.wasm\", import.meta.url);\n\nasync function loadDirectWasmBytes(): Promise<ArrayBuffer> {\n if (typeof process !== \"undefined\" && process.versions?.node) {\n const [{ readFile }, { fileURLToPath }] = await Promise.all([\n import(\"node:fs/promises\"),\n import(\"node:url\"),\n ]);\n const bytes = await readFile(fileURLToPath(WASM_URL));\n return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;\n }\n const response = await fetch(WASM_URL);\n if (!response.ok) {\n throw new Error(\n `zfb-md-wasm: failed to fetch wasm binary: ${response.status} ${response.statusText}`,\n );\n }\n return response.arrayBuffer();\n}\n\nconst api = createWasmApi({ glueUrl: GLUE_URL, loadWasmBytes: loadDirectWasmBytes });\n\nexport const { init, renderHtml, version, __forceTrapForTests, __getTrapRecoveryStateForTests } =\n api;\n\nexport { ZfbMdWasmTrapError, ZfbMdWasmTrapRecoveryLimitError } from \"./runtime.js\";\nexport type {\n RenderHtmlResult,\n Diagnostic,\n DiagnosticSource,\n ZfbMdWasmOptions,\n ParseDialect,\n PipelineOptions,\n GfmOptions,\n CodeHighlightMode,\n CodeHighlightOptions,\n MarkdownFeaturesConfig,\n JsxRuntime,\n HighlightRole,\n} from \"./types.js\";\n"]}
|
package/dist/runtime.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ interface WasmGlueModule {
|
|
|
6
6
|
compile?(source: string, optionsJson: string): string;
|
|
7
7
|
renderHtml?(source: string, optionsJson: string): string;
|
|
8
8
|
parseToAst?(source: string, optionsJson: string): string;
|
|
9
|
-
highlightCode(code: string, optionsJson: string): string;
|
|
9
|
+
highlightCode?(code: string, optionsJson: string): string;
|
|
10
10
|
version(): string;
|
|
11
11
|
__forceTrapForTests(): void;
|
|
12
12
|
}
|
package/dist/runtime.js
CHANGED
|
@@ -122,26 +122,23 @@ export function createWasmApi({ glueUrl, loadWasmBytes, compileWasm = (bytes) =>
|
|
|
122
122
|
async function init() {
|
|
123
123
|
await getInstance();
|
|
124
124
|
}
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
// never re-export these two functions. Kept as a clear runtime error
|
|
129
|
-
// rather than a silent `undefined()` crash.
|
|
130
|
-
function requirePipelineExport(fn, name) {
|
|
125
|
+
// Public entry surfaces make missing calls unreachable. This guard keeps
|
|
126
|
+
// structural glue mismatches artifact-neutral and actionable.
|
|
127
|
+
function requireCapability(fn, name) {
|
|
131
128
|
if (!fn) {
|
|
132
|
-
throw new Error(`zfb-md-wasm: ${name}() is not available in
|
|
133
|
-
`
|
|
129
|
+
throw new Error(`zfb-md-wasm: ${name}() is not available in this wasm artifact. ` +
|
|
130
|
+
`Import an entry whose artifact provides that capability.`);
|
|
134
131
|
}
|
|
135
132
|
return fn;
|
|
136
133
|
}
|
|
137
134
|
async function compile(source, options = {}) {
|
|
138
135
|
const optionsJson = JSON.stringify(options);
|
|
139
|
-
const json = await callWasm(({ glue }) =>
|
|
136
|
+
const json = await callWasm(({ glue }) => requireCapability(glue.compile, "compile").call(glue, source, optionsJson));
|
|
140
137
|
return JSON.parse(json);
|
|
141
138
|
}
|
|
142
139
|
async function renderHtml(source, options = {}) {
|
|
143
140
|
const optionsJson = JSON.stringify(options);
|
|
144
|
-
const json = await callWasm(({ glue }) =>
|
|
141
|
+
const json = await callWasm(({ glue }) => requireCapability(glue.renderHtml, "renderHtml").call(glue, source, optionsJson));
|
|
145
142
|
return JSON.parse(json);
|
|
146
143
|
}
|
|
147
144
|
/**
|
|
@@ -153,12 +150,12 @@ export function createWasmApi({ glueUrl, loadWasmBytes, compileWasm = (bytes) =>
|
|
|
153
150
|
*/
|
|
154
151
|
async function parseToAst(source, options = {}) {
|
|
155
152
|
const optionsJson = JSON.stringify(options);
|
|
156
|
-
const json = await callWasm(({ glue }) =>
|
|
153
|
+
const json = await callWasm(({ glue }) => requireCapability(glue.parseToAst, "parseToAst").call(glue, source, optionsJson));
|
|
157
154
|
return JSON.parse(json);
|
|
158
155
|
}
|
|
159
156
|
async function highlightCode(code, options) {
|
|
160
157
|
const optionsJson = JSON.stringify(options);
|
|
161
|
-
const json = await callWasm(({ glue }) => glue.highlightCode(code, optionsJson));
|
|
158
|
+
const json = await callWasm(({ glue }) => requireCapability(glue.highlightCode, "highlightCode").call(glue, code, optionsJson));
|
|
162
159
|
return JSON.parse(json);
|
|
163
160
|
}
|
|
164
161
|
async function version() {
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CompileResult,\n HighlightCodeOptions,\n HighlightCodeResult,\n ParseToAstOptions,\n ParseToAstResult,\n RenderHtmlResult,\n ZfbMdWasmOptions,\n} from \"./types.js\";\n\ninterface WasmGlueModule {\n // Keep this deliberately structural instead of importing the generated\n // glue's declaration file. The browser entry imports that file as a *URL\n // resource*, while the direct entry imports it dynamically. Both paths\n // nevertheless use the same wasm-bindgen surface and recovery\n // implementation below.\n //\n // `compile`/`renderHtml` are optional: the highlight-only wasm artifact\n // (`./highlight` entry, zfb#1849, epic zfb#1845) is compiled with the\n // `pipeline` Cargo feature off (see crates/zfb-md-wasm/Cargo.toml), so its\n // wasm-bindgen glue never generates these exports at all. `createWasmApi`\n // below is shared by both entries; only `src/index.ts`/`src/browser.ts`\n // re-export the functions that call them.\n initSync(input?: { module: WebAssembly.Module }): unknown;\n compile?(source: string, optionsJson: string): string;\n renderHtml?(source: string, optionsJson: string): string;\n // Raw-mdast export (zfb#1857, epic zfb#1854); pipeline-gated like\n // compile/renderHtml -- the highlight-only artifact never generates it.\n parseToAst?(source: string, optionsJson: string): string;\n highlightCode(code: string, optionsJson: string): string;\n version(): string;\n __forceTrapForTests(): void;\n}\n\nexport interface WasmResourceConfig {\n glueUrl: URL;\n loadWasmBytes(): Promise<ArrayBuffer>;\n /** @internal Deterministic test seam; production uses WebAssembly.compile. */\n compileWasm?(bytes: ArrayBuffer): Promise<WebAssembly.Module>;\n /** @internal Deterministic test seam; production dynamically imports the glue URL. */\n importGlue?(specifier: string): Promise<WasmGlueModule>;\n}\n\nexport class ZfbMdWasmTrapError extends Error {\n constructor(cause: unknown) {\n super(\n \"zfb-md-wasm: the wasm instance trapped (a Rust panic or internal fault) and has been \" +\n \"automatically re-instantiated. This is always a bug in zfb-md-wasm -- please report it \" +\n \"with the input that triggered it.\",\n );\n this.name = \"ZfbMdWasmTrapError\";\n this.cause = cause;\n }\n}\n\nexport class ZfbMdWasmTrapRecoveryLimitError extends Error {\n constructor(maxRecoveries: number, cause: unknown) {\n super(\n `zfb-md-wasm: wasm trap recovery limit reached after ${maxRecoveries} ` +\n `successful re-instantiations. Further automatic recovery is disabled to avoid ` +\n `unbounded ES module record growth. Reload the JS realm before using zfb-md-wasm ` +\n `again, and please report the input that triggered the repeated traps.`,\n );\n this.name = \"ZfbMdWasmTrapRecoveryLimitError\";\n this.cause = cause;\n }\n}\n\nexport function createWasmApi({\n glueUrl,\n loadWasmBytes,\n compileWasm = (bytes) => WebAssembly.compile(bytes),\n importGlue = (specifier) => import(/* @vite-ignore */ specifier) as Promise<WasmGlueModule>,\n}: WasmResourceConfig) {\n let compiledModulePromise: Promise<WebAssembly.Module> | undefined;\n let compiledModuleLoads = 0;\n\n function getCompiledModule(): Promise<WebAssembly.Module> {\n if (!compiledModulePromise) {\n compiledModuleLoads += 1;\n const attempt = Promise.resolve().then(loadWasmBytes).then(compileWasm);\n compiledModulePromise = attempt;\n void attempt.catch(() => {\n // A rejected attempt must be retryable, but it must not erase a newer\n // attempt if its rejection cleanup runs late.\n if (compiledModulePromise === attempt) {\n compiledModulePromise = undefined;\n }\n });\n }\n return compiledModulePromise;\n }\n\n const MAX_TRAP_RECOVERIES = 16;\n\n let currentGeneration = 0;\n let trapRecoveriesStarted = 0;\n let freshInstanceStarts = 0;\n let glueImportAttempts = 0;\n let terminalTrapRecoveryError: ZfbMdWasmTrapRecoveryLimitError | undefined;\n\n interface Instance {\n generation: number;\n glue: WasmGlueModule;\n }\n\n /**\n * Every fresh instance attempt creates a new wasm-bindgen glue module\n * record. The import-attempt nonce is deliberately independent of the trap\n * generation: transient import/initSync failures need a new module record\n * without consuming the bounded trap-recovery budget.\n */\n async function freshInstance(generation: number): Promise<Instance> {\n freshInstanceStarts += 1;\n glueImportAttempts += 1;\n const glueSpecifier = new URL(glueUrl.href);\n glueSpecifier.searchParams.set(\"zfbMdWasmGen\", String(generation));\n glueSpecifier.searchParams.set(\"zfbMdWasmAttempt\", String(glueImportAttempts));\n const [module, glue] = await Promise.all([\n getCompiledModule(),\n // Deferring the injected function also converts a synchronous test-seam\n // throw into the rejection handled by the retryable instance cache.\n Promise.resolve().then(() => importGlue(glueSpecifier.href)),\n ]);\n glue.initSync({ module });\n return { generation, glue };\n }\n\n let instancePromise: Promise<Instance> | undefined;\n\n function startInstance(generation: number): Promise<Instance> {\n const attempt = freshInstance(generation);\n instancePromise = attempt;\n void attempt.catch(() => {\n // Trap recovery can replace the installed instance promise. Never let a\n // stale initialization rejection clear that newer attempt.\n if (instancePromise === attempt) {\n instancePromise = undefined;\n }\n });\n return attempt;\n }\n\n function getInstance(): Promise<Instance> {\n if (terminalTrapRecoveryError) {\n return Promise.reject(terminalTrapRecoveryError);\n }\n if (!instancePromise) {\n return startInstance(currentGeneration);\n }\n return instancePromise;\n }\n\n function isTrap(err: unknown): boolean {\n return typeof WebAssembly !== \"undefined\" && err instanceof WebAssembly.RuntimeError;\n }\n\n async function recoverAfterTrap(observedGeneration: number, cause: unknown): Promise<void> {\n if (terminalTrapRecoveryError) {\n throw terminalTrapRecoveryError;\n }\n\n // CAS-style single-flight: reporters for an already-replaced generation\n // await its replacement instead of creating another glue module record.\n if (observedGeneration !== currentGeneration) {\n await getInstance();\n return;\n }\n\n if (trapRecoveriesStarted >= MAX_TRAP_RECOVERIES) {\n terminalTrapRecoveryError = new ZfbMdWasmTrapRecoveryLimitError(MAX_TRAP_RECOVERIES, cause);\n instancePromise = undefined;\n throw terminalTrapRecoveryError;\n }\n\n trapRecoveriesStarted += 1;\n currentGeneration += 1;\n await startInstance(currentGeneration);\n }\n\n async function callWasm<T>(fn: (instance: Instance) => T): Promise<T> {\n const instance = await getInstance();\n try {\n return fn(instance);\n } catch (err) {\n if (!isTrap(err)) {\n throw err;\n }\n await recoverAfterTrap(instance.generation, err);\n throw new ZfbMdWasmTrapError(err);\n }\n }\n\n async function init(): Promise<void> {\n await getInstance();\n }\n\n // Both throw helpers below fire only if `compile`/`renderHtml` were\n // somehow invoked against the highlight-only glue -- unreachable through\n // the public API surface, since `src/highlight.ts`/`src/highlight-browser.ts`\n // never re-export these two functions. Kept as a clear runtime error\n // rather than a silent `undefined()` crash.\n function requirePipelineExport<T>(fn: T | undefined, name: string): T {\n if (!fn) {\n throw new Error(\n `zfb-md-wasm: ${name}() is not available in the highlight-only wasm artifact ` +\n `(built with the \\`pipeline\\` Cargo feature off) -- use the default \\`.\\` entry instead.`,\n );\n }\n return fn;\n }\n\n async function compile(source: string, options: ZfbMdWasmOptions = {}): Promise<CompileResult> {\n const optionsJson = JSON.stringify(options);\n const json = await callWasm(({ glue }) =>\n requirePipelineExport(glue.compile, \"compile\").call(glue, source, optionsJson),\n );\n return JSON.parse(json) as CompileResult;\n }\n\n async function renderHtml(\n source: string,\n options: ZfbMdWasmOptions = {},\n ): Promise<RenderHtmlResult> {\n const optionsJson = JSON.stringify(options);\n const json = await callWasm(({ glue }) =>\n requirePipelineExport(glue.renderHtml, \"renderHtml\").call(glue, source, optionsJson),\n );\n return JSON.parse(json) as RenderHtmlResult;\n }\n\n /**\n * Parse markdown/MDX into a raw mdast tree (zfb#1857, epic zfb#1854).\n * The `parseToAst + JSON.parse` round trip here IS the product cost the\n * epic's benchmark measures against remark-parse. See `types.ts`'s\n * `ParseToAstResult`/`MdastNode` docs for the result shape and the\n * UTF-16 position contract.\n */\n async function parseToAst(\n source: string,\n options: ParseToAstOptions = {},\n ): Promise<ParseToAstResult> {\n const optionsJson = JSON.stringify(options);\n const json = await callWasm(({ glue }) =>\n requirePipelineExport(glue.parseToAst, \"parseToAst\").call(glue, source, optionsJson),\n );\n return JSON.parse(json) as ParseToAstResult;\n }\n\n async function highlightCode(\n code: string,\n options: HighlightCodeOptions,\n ): Promise<HighlightCodeResult> {\n const optionsJson = JSON.stringify(options);\n const json = await callWasm(({ glue }) => glue.highlightCode(code, optionsJson));\n return JSON.parse(json) as HighlightCodeResult;\n }\n\n async function version(): Promise<string> {\n return callWasm(({ glue }) => glue.version());\n }\n\n /** @internal Test-only hook that forces the current instance to trap. */\n async function __forceTrapForTests(): Promise<void> {\n await callWasm(({ glue }) => glue.__forceTrapForTests());\n }\n\n /** @internal Test-only observability for the bounded recovery contract. */\n function __getTrapRecoveryStateForTests(): {\n compiledModuleLoads: number;\n currentGeneration: number;\n freshInstanceStarts: number;\n glueImportAttempts: number;\n maxTrapRecoveries: number;\n trapRecoveriesStarted: number;\n terminal: boolean;\n } {\n return {\n compiledModuleLoads,\n currentGeneration,\n freshInstanceStarts,\n glueImportAttempts,\n maxTrapRecoveries: MAX_TRAP_RECOVERIES,\n trapRecoveriesStarted,\n terminal: !!terminalTrapRecoveryError,\n };\n }\n\n return {\n init,\n compile,\n renderHtml,\n parseToAst,\n highlightCode,\n version,\n __forceTrapForTests,\n __getTrapRecoveryStateForTests,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CompileResult,\n HighlightCodeOptions,\n HighlightCodeResult,\n ParseToAstOptions,\n ParseToAstResult,\n RenderHtmlResult,\n ZfbMdWasmOptions,\n} from \"./types.js\";\n\ninterface WasmGlueModule {\n // Keep this deliberately structural instead of importing the generated\n // glue's declaration file. The browser entry imports that file as a *URL\n // resource*, while the direct entry imports it dynamically. Both paths\n // nevertheless use the same wasm-bindgen surface and recovery\n // implementation below.\n //\n // Capability functions are structural and optional because each singleton\n // artifact's wasm-bindgen glue contains only its selected Rust export.\n // Public entries expose only the matching calls from `createWasmApi`.\n initSync(input?: { module: WebAssembly.Module }): unknown;\n compile?(source: string, optionsJson: string): string;\n renderHtml?(source: string, optionsJson: string): string;\n // Raw-mdast export (zfb#1857, epic zfb#1854).\n parseToAst?(source: string, optionsJson: string): string;\n highlightCode?(code: string, optionsJson: string): string;\n version(): string;\n __forceTrapForTests(): void;\n}\n\nexport interface WasmResourceConfig {\n glueUrl: URL;\n loadWasmBytes(): Promise<ArrayBuffer>;\n /** @internal Deterministic test seam; production uses WebAssembly.compile. */\n compileWasm?(bytes: ArrayBuffer): Promise<WebAssembly.Module>;\n /** @internal Deterministic test seam; production dynamically imports the glue URL. */\n importGlue?(specifier: string): Promise<WasmGlueModule>;\n}\n\nexport class ZfbMdWasmTrapError extends Error {\n constructor(cause: unknown) {\n super(\n \"zfb-md-wasm: the wasm instance trapped (a Rust panic or internal fault) and has been \" +\n \"automatically re-instantiated. This is always a bug in zfb-md-wasm -- please report it \" +\n \"with the input that triggered it.\",\n );\n this.name = \"ZfbMdWasmTrapError\";\n this.cause = cause;\n }\n}\n\nexport class ZfbMdWasmTrapRecoveryLimitError extends Error {\n constructor(maxRecoveries: number, cause: unknown) {\n super(\n `zfb-md-wasm: wasm trap recovery limit reached after ${maxRecoveries} ` +\n `successful re-instantiations. Further automatic recovery is disabled to avoid ` +\n `unbounded ES module record growth. Reload the JS realm before using zfb-md-wasm ` +\n `again, and please report the input that triggered the repeated traps.`,\n );\n this.name = \"ZfbMdWasmTrapRecoveryLimitError\";\n this.cause = cause;\n }\n}\n\nexport function createWasmApi({\n glueUrl,\n loadWasmBytes,\n compileWasm = (bytes) => WebAssembly.compile(bytes),\n importGlue = (specifier) => import(/* @vite-ignore */ specifier) as Promise<WasmGlueModule>,\n}: WasmResourceConfig) {\n let compiledModulePromise: Promise<WebAssembly.Module> | undefined;\n let compiledModuleLoads = 0;\n\n function getCompiledModule(): Promise<WebAssembly.Module> {\n if (!compiledModulePromise) {\n compiledModuleLoads += 1;\n const attempt = Promise.resolve().then(loadWasmBytes).then(compileWasm);\n compiledModulePromise = attempt;\n void attempt.catch(() => {\n // A rejected attempt must be retryable, but it must not erase a newer\n // attempt if its rejection cleanup runs late.\n if (compiledModulePromise === attempt) {\n compiledModulePromise = undefined;\n }\n });\n }\n return compiledModulePromise;\n }\n\n const MAX_TRAP_RECOVERIES = 16;\n\n let currentGeneration = 0;\n let trapRecoveriesStarted = 0;\n let freshInstanceStarts = 0;\n let glueImportAttempts = 0;\n let terminalTrapRecoveryError: ZfbMdWasmTrapRecoveryLimitError | undefined;\n\n interface Instance {\n generation: number;\n glue: WasmGlueModule;\n }\n\n /**\n * Every fresh instance attempt creates a new wasm-bindgen glue module\n * record. The import-attempt nonce is deliberately independent of the trap\n * generation: transient import/initSync failures need a new module record\n * without consuming the bounded trap-recovery budget.\n */\n async function freshInstance(generation: number): Promise<Instance> {\n freshInstanceStarts += 1;\n glueImportAttempts += 1;\n const glueSpecifier = new URL(glueUrl.href);\n glueSpecifier.searchParams.set(\"zfbMdWasmGen\", String(generation));\n glueSpecifier.searchParams.set(\"zfbMdWasmAttempt\", String(glueImportAttempts));\n const [module, glue] = await Promise.all([\n getCompiledModule(),\n // Deferring the injected function also converts a synchronous test-seam\n // throw into the rejection handled by the retryable instance cache.\n Promise.resolve().then(() => importGlue(glueSpecifier.href)),\n ]);\n glue.initSync({ module });\n return { generation, glue };\n }\n\n let instancePromise: Promise<Instance> | undefined;\n\n function startInstance(generation: number): Promise<Instance> {\n const attempt = freshInstance(generation);\n instancePromise = attempt;\n void attempt.catch(() => {\n // Trap recovery can replace the installed instance promise. Never let a\n // stale initialization rejection clear that newer attempt.\n if (instancePromise === attempt) {\n instancePromise = undefined;\n }\n });\n return attempt;\n }\n\n function getInstance(): Promise<Instance> {\n if (terminalTrapRecoveryError) {\n return Promise.reject(terminalTrapRecoveryError);\n }\n if (!instancePromise) {\n return startInstance(currentGeneration);\n }\n return instancePromise;\n }\n\n function isTrap(err: unknown): boolean {\n return typeof WebAssembly !== \"undefined\" && err instanceof WebAssembly.RuntimeError;\n }\n\n async function recoverAfterTrap(observedGeneration: number, cause: unknown): Promise<void> {\n if (terminalTrapRecoveryError) {\n throw terminalTrapRecoveryError;\n }\n\n // CAS-style single-flight: reporters for an already-replaced generation\n // await its replacement instead of creating another glue module record.\n if (observedGeneration !== currentGeneration) {\n await getInstance();\n return;\n }\n\n if (trapRecoveriesStarted >= MAX_TRAP_RECOVERIES) {\n terminalTrapRecoveryError = new ZfbMdWasmTrapRecoveryLimitError(MAX_TRAP_RECOVERIES, cause);\n instancePromise = undefined;\n throw terminalTrapRecoveryError;\n }\n\n trapRecoveriesStarted += 1;\n currentGeneration += 1;\n await startInstance(currentGeneration);\n }\n\n async function callWasm<T>(fn: (instance: Instance) => T): Promise<T> {\n const instance = await getInstance();\n try {\n return fn(instance);\n } catch (err) {\n if (!isTrap(err)) {\n throw err;\n }\n await recoverAfterTrap(instance.generation, err);\n throw new ZfbMdWasmTrapError(err);\n }\n }\n\n async function init(): Promise<void> {\n await getInstance();\n }\n\n // Public entry surfaces make missing calls unreachable. This guard keeps\n // structural glue mismatches artifact-neutral and actionable.\n function requireCapability<T>(fn: T | undefined, name: string): T {\n if (!fn) {\n throw new Error(\n `zfb-md-wasm: ${name}() is not available in this wasm artifact. ` +\n `Import an entry whose artifact provides that capability.`,\n );\n }\n return fn;\n }\n\n async function compile(source: string, options: ZfbMdWasmOptions = {}): Promise<CompileResult> {\n const optionsJson = JSON.stringify(options);\n const json = await callWasm(({ glue }) =>\n requireCapability(glue.compile, \"compile\").call(glue, source, optionsJson),\n );\n return JSON.parse(json) as CompileResult;\n }\n\n async function renderHtml(\n source: string,\n options: ZfbMdWasmOptions = {},\n ): Promise<RenderHtmlResult> {\n const optionsJson = JSON.stringify(options);\n const json = await callWasm(({ glue }) =>\n requireCapability(glue.renderHtml, \"renderHtml\").call(glue, source, optionsJson),\n );\n return JSON.parse(json) as RenderHtmlResult;\n }\n\n /**\n * Parse markdown/MDX into a raw mdast tree (zfb#1857, epic zfb#1854).\n * The `parseToAst + JSON.parse` round trip here IS the product cost the\n * epic's benchmark measures against remark-parse. See `types.ts`'s\n * `ParseToAstResult`/`MdastNode` docs for the result shape and the\n * UTF-16 position contract.\n */\n async function parseToAst(\n source: string,\n options: ParseToAstOptions = {},\n ): Promise<ParseToAstResult> {\n const optionsJson = JSON.stringify(options);\n const json = await callWasm(({ glue }) =>\n requireCapability(glue.parseToAst, \"parseToAst\").call(glue, source, optionsJson),\n );\n return JSON.parse(json) as ParseToAstResult;\n }\n\n async function highlightCode(\n code: string,\n options: HighlightCodeOptions,\n ): Promise<HighlightCodeResult> {\n const optionsJson = JSON.stringify(options);\n const json = await callWasm(({ glue }) =>\n requireCapability(glue.highlightCode, \"highlightCode\").call(glue, code, optionsJson),\n );\n return JSON.parse(json) as HighlightCodeResult;\n }\n\n async function version(): Promise<string> {\n return callWasm(({ glue }) => glue.version());\n }\n\n /** @internal Test-only hook that forces the current instance to trap. */\n async function __forceTrapForTests(): Promise<void> {\n await callWasm(({ glue }) => glue.__forceTrapForTests());\n }\n\n /** @internal Test-only observability for the bounded recovery contract. */\n function __getTrapRecoveryStateForTests(): {\n compiledModuleLoads: number;\n currentGeneration: number;\n freshInstanceStarts: number;\n glueImportAttempts: number;\n maxTrapRecoveries: number;\n trapRecoveriesStarted: number;\n terminal: boolean;\n } {\n return {\n compiledModuleLoads,\n currentGeneration,\n freshInstanceStarts,\n glueImportAttempts,\n maxTrapRecoveries: MAX_TRAP_RECOVERIES,\n trapRecoveriesStarted,\n terminal: !!terminalTrapRecoveryError,\n };\n }\n\n return {\n init,\n compile,\n renderHtml,\n parseToAst,\n highlightCode,\n version,\n __forceTrapForTests,\n __getTrapRecoveryStateForTests,\n };\n}\n"]}
|