satteri 0.10.5 → 0.11.3
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 +11 -0
- package/dist/arena-reader.d.ts +13 -0
- package/dist/arena-reader.js +104 -0
- package/dist/binding.browser.d.ts +1 -1
- package/dist/binding.browser.js +1 -1
- package/dist/binding.d.ts +1 -1
- package/dist/binding.js +1 -1
- package/dist/byte-writer.d.ts +0 -18
- package/dist/byte-writer.js +6 -30
- package/dist/child-stub.d.ts +0 -17
- package/dist/child-stub.js +6 -22
- package/dist/command-buffer.d.ts +5 -26
- package/dist/command-buffer.js +28 -39
- package/dist/compile-options.d.ts +11 -0
- package/dist/compile-options.js +101 -0
- package/dist/compile-types.d.ts +342 -0
- package/dist/compile-types.js +1 -0
- package/dist/compile.d.ts +22 -328
- package/dist/compile.js +133 -383
- package/dist/directive-types.d.ts +1 -0
- package/dist/directive-types.js +1 -6
- package/dist/generated/arena-layout.d.ts +6 -4
- package/dist/generated/arena-layout.js +6 -7
- package/dist/generated/fused-wire.d.ts +3 -0
- package/dist/generated/fused-wire.js +229 -0
- package/dist/generated/parse-options.d.ts +1 -0
- package/dist/generated/parse-options.js +1 -5
- package/dist/generated/wire-constants.d.ts +4 -0
- package/dist/generated/wire-constants.js +34 -42
- package/dist/handles.d.ts +0 -7
- package/dist/hast/child-stub.d.ts +1 -8
- package/dist/hast/child-stub.js +14 -13
- package/dist/hast/element-props.d.ts +13 -0
- package/dist/hast/element-props.js +52 -6
- package/dist/hast/generated/node-types.d.ts +1 -9
- package/dist/hast/generated/node-types.js +1 -9
- package/dist/hast/generated/walk-decode.d.ts +10 -0
- package/dist/hast/generated/walk-decode.js +61 -0
- package/dist/hast/hast-materializer.d.ts +3 -10
- package/dist/hast/hast-materializer.js +73 -47
- package/dist/hast/hast-reader.d.ts +9 -38
- package/dist/hast/hast-reader.js +82 -271
- package/dist/hast/hast-visitor.d.ts +29 -16
- package/dist/hast/hast-visitor.js +200 -508
- package/dist/hast/hast-walk.d.ts +18 -0
- package/dist/hast/hast-walk.js +264 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +4 -12
- package/dist/lazy-child-resolver.d.ts +1 -21
- package/dist/lazy-child-resolver.js +11 -32
- package/dist/materializer-cache.d.ts +5 -29
- package/dist/materializer-cache.js +29 -101
- package/dist/mdast/child-stub.d.ts +1 -12
- package/dist/mdast/child-stub.js +18 -28
- package/dist/mdast/column-align.d.ts +1 -1
- package/dist/mdast/column-align.js +0 -2
- package/dist/mdast/generated/layout.d.ts +0 -16
- package/dist/mdast/generated/layout.js +6 -47
- package/dist/mdast/generated/node-types.d.ts +1 -9
- package/dist/mdast/generated/node-types.js +3 -9
- package/dist/mdast/mdast-materializer.d.ts +3 -11
- package/dist/mdast/mdast-materializer.js +91 -63
- package/dist/mdast/mdast-reader.d.ts +15 -63
- package/dist/mdast/mdast-reader.js +132 -269
- package/dist/mdast/mdast-visitor.d.ts +23 -15
- package/dist/mdast/mdast-visitor.js +189 -294
- package/dist/mdast/mdast-walk.d.ts +13 -0
- package/dist/mdast/mdast-walk.js +144 -0
- package/dist/mdx-attr.js +0 -3
- package/dist/mdx-types.js +1 -6
- package/dist/op-stream.d.ts +4 -15
- package/dist/op-stream.js +31 -20
- package/dist/phantom.d.ts +0 -1
- package/dist/phantom.js +1 -9
- package/dist/plugin-pipeline.d.ts +32 -0
- package/dist/plugin-pipeline.js +177 -0
- package/dist/plugin.d.ts +14 -8
- package/dist/plugin.js +5 -10
- package/dist/types.d.ts +0 -1
- package/dist/visitor-node.d.ts +12 -0
- package/dist/visitor-node.js +23 -0
- package/dist/visitor-shared.d.ts +26 -30
- package/dist/visitor-shared.js +34 -36
- package/dist/wire-read.d.ts +0 -22
- package/dist/wire-read.js +3 -24
- package/index.d.ts +19 -10
- package/index.js +56 -53
- package/package.json +6 -12
- package/dist/string-pool.d.ts +0 -13
- package/dist/string-pool.js +0 -91
package/README.md
CHANGED
|
@@ -41,6 +41,17 @@ import { markdownToJs } from "satteri";
|
|
|
41
41
|
const { code } = markdownToJs("# Hello\n\n{not an expression}");
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
### HAST to HTML
|
|
45
|
+
|
|
46
|
+
`hastToHtml` serializes a HAST root, a single node, or an array of nodes without adding a trailing newline. Raw HTML nodes are emitted verbatim; MDX nodes are skipped.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { hastToHtml, markdownToHast } from "satteri";
|
|
50
|
+
|
|
51
|
+
const html = hastToHtml(markdownToHast("**Hello**"));
|
|
52
|
+
// <p><strong>Hello</strong></p>
|
|
53
|
+
```
|
|
54
|
+
|
|
44
55
|
### With plugins
|
|
45
56
|
|
|
46
57
|
All three functions accept `mdastPlugins` (operate on the Markdown AST) and `hastPlugins` (operate on the HTML AST). A plugin is an object with a `name` and a visitor per node type; `defineMdastPlugin` / `defineHastPlugin` add type inference.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ArenaWire, BufferHeader } from "./types.js";
|
|
2
|
+
export declare class ArenaReader {
|
|
3
|
+
#private;
|
|
4
|
+
readonly u8: Uint8Array;
|
|
5
|
+
readonly u32: Uint32Array;
|
|
6
|
+
readonly header: BufferHeader;
|
|
7
|
+
constructor(buffer: ArrayBuffer | Uint8Array, kind: number);
|
|
8
|
+
getWire(): ArenaWire;
|
|
9
|
+
getNodeData(nodeId: number): string | null;
|
|
10
|
+
getNodeDataTable(): ReadonlyMap<number, string> | null;
|
|
11
|
+
getStringPool(): string;
|
|
12
|
+
getString(offset: number, len: number): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { ARENA_MAGIC, HEADER, KIND_MDAST } from "./generated/arena-layout.js";
|
|
2
|
+
export class ArenaReader {
|
|
3
|
+
u8;
|
|
4
|
+
u32;
|
|
5
|
+
#view;
|
|
6
|
+
header;
|
|
7
|
+
#textDecoder = new TextDecoder("utf-8", { ignoreBOM: true });
|
|
8
|
+
#stringPoolCache = null;
|
|
9
|
+
constructor(buffer, kind) {
|
|
10
|
+
let u8 = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
11
|
+
// A foreign slice may not have the alignment required by a u32 view.
|
|
12
|
+
if ((u8.byteOffset & 3) !== 0)
|
|
13
|
+
u8 = u8.slice();
|
|
14
|
+
this.u8 = u8;
|
|
15
|
+
this.u32 = new Uint32Array(u8.buffer, u8.byteOffset, u8.byteLength >> 2);
|
|
16
|
+
this.#view = new DataView(u8.buffer, u8.byteOffset, u8.byteLength);
|
|
17
|
+
this.header = readHeader(this.#view, kind);
|
|
18
|
+
}
|
|
19
|
+
#nodeDataTable = null;
|
|
20
|
+
#wire = null;
|
|
21
|
+
// Memoize wire setup because the lazy materializer requests it for every node.
|
|
22
|
+
getWire() {
|
|
23
|
+
return (this.#wire ??= {
|
|
24
|
+
u8: this.u8,
|
|
25
|
+
u32: this.u32,
|
|
26
|
+
nodesB: this.header.nodesOffset,
|
|
27
|
+
nodesW: this.header.nodesOffset >> 2,
|
|
28
|
+
strideB: this.header.nodeStructSize,
|
|
29
|
+
strideW: this.header.nodeStructSize >> 2,
|
|
30
|
+
childrenW: this.header.childrenOffset >> 2,
|
|
31
|
+
typeDataB: this.header.typeDataOffset,
|
|
32
|
+
pool: this.getStringPool(),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
// Index data blobs once to keep materialization O(nodes), rather than O(nodes × entries).
|
|
36
|
+
getNodeData(nodeId) {
|
|
37
|
+
const table = this.getNodeDataTable();
|
|
38
|
+
if (table === null)
|
|
39
|
+
return null;
|
|
40
|
+
return table.get(nodeId) ?? null;
|
|
41
|
+
}
|
|
42
|
+
getNodeDataTable() {
|
|
43
|
+
if (this.header.nodeDataCount === 0)
|
|
44
|
+
return null;
|
|
45
|
+
if (this.#nodeDataTable === null) {
|
|
46
|
+
this.#nodeDataTable = new Map();
|
|
47
|
+
const v = this.#view;
|
|
48
|
+
let pos = this.header.nodeDataOffset;
|
|
49
|
+
for (let i = 0; i < this.header.nodeDataCount; i++) {
|
|
50
|
+
const id = v.getUint32(pos, true);
|
|
51
|
+
pos += 4;
|
|
52
|
+
const len = v.getUint32(pos, true);
|
|
53
|
+
pos += 4;
|
|
54
|
+
const slice = this.u8.subarray(pos, pos + len);
|
|
55
|
+
this.#nodeDataTable.set(id, this.#textDecoder.decode(slice));
|
|
56
|
+
pos += len;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return this.#nodeDataTable;
|
|
60
|
+
}
|
|
61
|
+
// The pool includes interned strings; it is not the original document source.
|
|
62
|
+
getStringPool() {
|
|
63
|
+
return this.#stringPoolCache ?? this.#initPool();
|
|
64
|
+
}
|
|
65
|
+
#initPool() {
|
|
66
|
+
const { stringPoolOffset, stringPoolLen } = this.header;
|
|
67
|
+
const pool = this.#textDecoder.decode(this.u8.subarray(stringPoolOffset, stringPoolOffset + stringPoolLen));
|
|
68
|
+
this.#stringPoolCache = pool;
|
|
69
|
+
return pool;
|
|
70
|
+
}
|
|
71
|
+
// The serializer remaps string refs to UTF-16 offsets, matching substring indices.
|
|
72
|
+
getString(offset, len) {
|
|
73
|
+
if (len === 0)
|
|
74
|
+
return "";
|
|
75
|
+
const pool = this.#stringPoolCache ?? this.#initPool();
|
|
76
|
+
return pool.substring(offset, offset + len);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function readHeader(view, expectedKind) {
|
|
80
|
+
const magic = view.getUint32(HEADER.magic, true);
|
|
81
|
+
if (magic !== ARENA_MAGIC) {
|
|
82
|
+
throw new Error(expectedKind === KIND_MDAST
|
|
83
|
+
? `Invalid buffer: bad magic 0x${magic.toString(16)}, expected 0x${ARENA_MAGIC.toString(16)}`
|
|
84
|
+
: `Invalid HAST buffer: bad magic 0x${magic.toString(16)}`);
|
|
85
|
+
}
|
|
86
|
+
const kind = view.getUint32(HEADER.kind, true);
|
|
87
|
+
if (kind !== expectedKind) {
|
|
88
|
+
throw new Error(`${expectedKind === KIND_MDAST ? "MdastReader" : "HastReader"} was handed a buffer of kind ${kind} (expected ${expectedKind}). ` +
|
|
89
|
+
`MDAST and HAST node types overlap; reading the wrong kind decodes garbage.`);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
nodeStructSize: view.getUint32(HEADER.node_struct_size, true),
|
|
93
|
+
nodeCount: view.getUint32(HEADER.node_count, true),
|
|
94
|
+
nodesOffset: view.getUint32(HEADER.nodes_offset, true),
|
|
95
|
+
childrenCount: view.getUint32(HEADER.children_count, true),
|
|
96
|
+
childrenOffset: view.getUint32(HEADER.children_offset, true),
|
|
97
|
+
typeDataLen: view.getUint32(HEADER.type_data_len, true),
|
|
98
|
+
typeDataOffset: view.getUint32(HEADER.type_data_offset, true),
|
|
99
|
+
stringPoolLen: view.getUint32(HEADER.string_pool_len, true),
|
|
100
|
+
stringPoolOffset: view.getUint32(HEADER.string_pool_offset, true),
|
|
101
|
+
nodeDataCount: view.getUint32(HEADER.node_data_count, true),
|
|
102
|
+
nodeDataOffset: view.getUint32(HEADER.node_data_offset, true),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { applyCommandsAndCompileHandle, applyCommandsAndConvertToHastHandle, applyCommandsAndRenderHandle, applyCommandsToHandle, applyCommandsToMdastHandle, applyMdastCommandsAndConvertAndCompile, applyMdastCommandsAndConvertAndRender, compileHandle, compileMdx, convertMdastToHastHandle, createHastHandle, createHastHandleFromHtml, createHastHandleWithFrontmatter, createMdastHandle, createMdxHastHandle, createMdxHastHandleWithFrontmatter, createMdxMdastHandle, dropHandle, getHandleSource, getMdastFrontmatter, getNodeData, markdownToHtmlFast, markdownToJsFast, mdastTextContentHandle, mdxToJsFast, parseEsm, parseExpression, parseToHtml, renderHandle, serializeHandle, setNodeData, textContentHandle, walkHandle, walkMdastHandle, } from "../browser.js";
|
|
1
|
+
export { applyCommandsAndCompileHandle, applyCommandsAndConvertToHastHandle, applyCommandsAndRenderHandle, applyCommandsToHandle, applyCommandsToMdastHandle, applyMdastCommandsAndConvertAndCompile, applyMdastCommandsAndConvertAndRender, compileHandle, compileMdx, convertMdastToHastHandle, createHastHandle, createHastHandleFromHtml, createHastHandleWithFrontmatter, createMdastHandle, createMdxHastHandle, createMdxHastHandleWithFrontmatter, createMdxMdastHandle, dropHandle, getHandleSource, getMdastFrontmatter, getNodeData, markdownToHtmlFast, markdownToJsFast, mdastTextContentHandle, mdxToJsFast, parseEsm, parseExpression, parseToHtml, renderHandle, renderHastOpstream, parseHastWire, parseMdastWire, serializeHandle, setNodeData, textContentHandle, walkHandle, walkMdastHandle, } from "../browser.js";
|
package/dist/binding.browser.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @ts-nocheck — WASM browser binding has no type declarations
|
|
2
|
-
export { applyCommandsAndCompileHandle, applyCommandsAndConvertToHastHandle, applyCommandsAndRenderHandle, applyCommandsToHandle, applyCommandsToMdastHandle, applyMdastCommandsAndConvertAndCompile, applyMdastCommandsAndConvertAndRender, compileHandle, compileMdx, convertMdastToHastHandle, createHastHandle, createHastHandleFromHtml, createHastHandleWithFrontmatter, createMdastHandle, createMdxHastHandle, createMdxHastHandleWithFrontmatter, createMdxMdastHandle, dropHandle, getHandleSource, getMdastFrontmatter, getNodeData, markdownToHtmlFast, markdownToJsFast, mdastTextContentHandle, mdxToJsFast, parseEsm, parseExpression, parseToHtml, renderHandle, serializeHandle, setNodeData, textContentHandle, walkHandle, walkMdastHandle, } from "../browser.js";
|
|
2
|
+
export { applyCommandsAndCompileHandle, applyCommandsAndConvertToHastHandle, applyCommandsAndRenderHandle, applyCommandsToHandle, applyCommandsToMdastHandle, applyMdastCommandsAndConvertAndCompile, applyMdastCommandsAndConvertAndRender, compileHandle, compileMdx, convertMdastToHastHandle, createHastHandle, createHastHandleFromHtml, createHastHandleWithFrontmatter, createMdastHandle, createMdxHastHandle, createMdxHastHandleWithFrontmatter, createMdxMdastHandle, dropHandle, getHandleSource, getMdastFrontmatter, getNodeData, markdownToHtmlFast, markdownToJsFast, mdastTextContentHandle, mdxToJsFast, parseEsm, parseExpression, parseToHtml, renderHandle, renderHastOpstream, parseHastWire, parseMdastWire, serializeHandle, setNodeData, textContentHandle, walkHandle, walkMdastHandle, } from "../browser.js";
|
package/dist/binding.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { applyCommandsAndCompileHandle, applyCommandsAndConvertToHastHandle, applyCommandsAndRenderHandle, applyCommandsToHandle, applyCommandsToMdastHandle, applyMdastCommandsAndConvertAndCompile, applyMdastCommandsAndConvertAndRender, compileHandle, compileMdx, convertMdastToHastHandle, createHastHandle, createHastHandleFromHtml, createHastHandleWithFrontmatter, createMdastHandle, createMdxHastHandle, createMdxHastHandleWithFrontmatter, createMdxMdastHandle, dropHandle, getHandleSource, getMdastFrontmatter, getNodeData, markdownToHtmlFast, markdownToJsFast, mdastTextContentHandle, mdxToJsFast, parseEsm, parseExpression, parseToHtml, renderHandle, serializeHandle, setNodeData, textContentHandle, walkHandle, walkMdastHandle, } from "../index.js";
|
|
1
|
+
export { applyCommandsAndCompileHandle, applyCommandsAndConvertToHastHandle, applyCommandsAndRenderHandle, applyCommandsToHandle, applyCommandsToMdastHandle, applyMdastCommandsAndConvertAndCompile, applyMdastCommandsAndConvertAndRender, compileHandle, compileMdx, convertMdastToHastHandle, createHastHandle, createHastHandleFromHtml, createHastHandleWithFrontmatter, createMdastHandle, createMdxHastHandle, createMdxHastHandleWithFrontmatter, createMdxMdastHandle, dropHandle, getHandleSource, getMdastFrontmatter, getNodeData, markdownToHtmlFast, markdownToJsFast, mdastTextContentHandle, mdxToJsFast, parseEsm, parseExpression, parseToHtml, renderHandle, renderHastOpstream, parseHastWire, parseMdastWire, serializeHandle, setNodeData, textContentHandle, walkHandle, walkMdastHandle, } from "../index.js";
|
package/dist/binding.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { applyCommandsAndCompileHandle, applyCommandsAndConvertToHastHandle, applyCommandsAndRenderHandle, applyCommandsToHandle, applyCommandsToMdastHandle, applyMdastCommandsAndConvertAndCompile, applyMdastCommandsAndConvertAndRender, compileHandle, compileMdx, convertMdastToHastHandle, createHastHandle, createHastHandleFromHtml, createHastHandleWithFrontmatter, createMdastHandle, createMdxHastHandle, createMdxHastHandleWithFrontmatter, createMdxMdastHandle, dropHandle, getHandleSource, getMdastFrontmatter, getNodeData, markdownToHtmlFast, markdownToJsFast, mdastTextContentHandle, mdxToJsFast, parseEsm, parseExpression, parseToHtml, renderHandle, serializeHandle, setNodeData, textContentHandle, walkHandle, walkMdastHandle, } from "../index.js";
|
|
1
|
+
export { applyCommandsAndCompileHandle, applyCommandsAndConvertToHastHandle, applyCommandsAndRenderHandle, applyCommandsToHandle, applyCommandsToMdastHandle, applyMdastCommandsAndConvertAndCompile, applyMdastCommandsAndConvertAndRender, compileHandle, compileMdx, convertMdastToHastHandle, createHastHandle, createHastHandleFromHtml, createHastHandleWithFrontmatter, createMdastHandle, createMdxHastHandle, createMdxHastHandleWithFrontmatter, createMdxMdastHandle, dropHandle, getHandleSource, getMdastFrontmatter, getNodeData, markdownToHtmlFast, markdownToJsFast, mdastTextContentHandle, mdxToJsFast, parseEsm, parseExpression, parseToHtml, renderHandle, renderHastOpstream, parseHastWire, parseMdastWire, serializeHandle, setNodeData, textContentHandle, walkHandle, walkMdastHandle, } from "../index.js";
|
package/dist/byte-writer.d.ts
CHANGED
|
@@ -1,35 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Growable little-endian byte buffer shared by the op-stream and command-buffer
|
|
3
|
-
* encoders — the two hottest write paths in the package.
|
|
4
|
-
*
|
|
5
|
-
* Subclasses write single bytes directly through the protected `buf`/`n`
|
|
6
|
-
* fields after an `ensure` for the whole record (one bounds check per record,
|
|
7
|
-
* not per byte, and no per-byte call in unoptimized tiers — CodSpeed's
|
|
8
|
-
* Simulation mode runs too few iterations for V8 to inline method calls).
|
|
9
|
-
* Only the non-trivial logic lives here: growth, u32 writes, and UTF-8
|
|
10
|
-
* string encoding.
|
|
11
|
-
*/
|
|
12
1
|
export declare class ByteWriter {
|
|
13
2
|
#private;
|
|
14
3
|
protected buf: Uint8Array;
|
|
15
4
|
protected n: number;
|
|
16
5
|
constructor(initialSize: number);
|
|
17
|
-
/** Number of bytes written so far. */
|
|
18
6
|
get length(): number;
|
|
19
7
|
get capacity(): number;
|
|
20
|
-
/** Reset for reuse; the grown buffer is retained so steady state is alloc-free. */
|
|
21
8
|
reset(): void;
|
|
22
9
|
/** View of the bytes written so far (no copy; valid until the next write or reset). */
|
|
23
10
|
take(): Uint8Array;
|
|
24
|
-
/** Release the backing (handed-out views stay intact); next write re-allocates. */
|
|
25
11
|
protected release(): void;
|
|
26
|
-
/** Grow (doubling) so `extra` more bytes fit; required before unchecked writes. */
|
|
27
12
|
ensure(extra: number): void;
|
|
28
13
|
/** Write a u32 (LE) at the cursor; caller must have `ensure`d 4 bytes. */
|
|
29
14
|
protected writeU32(v: number): void;
|
|
30
|
-
/** u32 byte length + UTF-8 bytes (self-ensuring). */
|
|
31
15
|
protected utf8WithU32Len(s: string): void;
|
|
32
|
-
/** Backpatch a u32 (LE) at `pos` in the already-written region; the cursor
|
|
33
|
-
* is left untouched. */
|
|
34
16
|
protected patchU32(pos: number, v: number): void;
|
|
35
17
|
}
|
package/dist/byte-writer.js
CHANGED
|
@@ -1,38 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
* Growable little-endian byte buffer shared by the op-stream and command-buffer
|
|
3
|
-
* encoders — the two hottest write paths in the package.
|
|
4
|
-
*
|
|
5
|
-
* Subclasses write single bytes directly through the protected `buf`/`n`
|
|
6
|
-
* fields after an `ensure` for the whole record (one bounds check per record,
|
|
7
|
-
* not per byte, and no per-byte call in unoptimized tiers — CodSpeed's
|
|
8
|
-
* Simulation mode runs too few iterations for V8 to inline method calls).
|
|
9
|
-
* Only the non-trivial logic lives here: growth, u32 writes, and UTF-8
|
|
10
|
-
* string encoding.
|
|
11
|
-
*/
|
|
1
|
+
// Write bytes inline after reserving each record to avoid per-byte calls and bounds checks.
|
|
12
2
|
const encoder = new TextEncoder();
|
|
13
3
|
const EMPTY = new Uint8Array(0);
|
|
14
|
-
|
|
15
|
-
* overhead; above it the native bulk path wins (and skips the ASCII scan).
|
|
16
|
-
* Measured crossover ~16 bytes (Node 24: 8B 15 vs 41 ns, 16B 37 vs 43,
|
|
17
|
-
* 32B 73 vs 52). */
|
|
4
|
+
// Below 16 bytes, inline ASCII writes beat encodeInto call overhead.
|
|
18
5
|
const INLINE_STR_MAX = 16;
|
|
19
6
|
export class ByteWriter {
|
|
20
|
-
//
|
|
21
|
-
// often never receive a byte (read-only plugins).
|
|
7
|
+
// Read-only plugin passes should allocate no backing buffer.
|
|
22
8
|
buf = EMPTY;
|
|
23
9
|
n = 0;
|
|
24
10
|
#initialSize;
|
|
25
11
|
constructor(initialSize) {
|
|
26
12
|
this.#initialSize = initialSize;
|
|
27
13
|
}
|
|
28
|
-
/** Number of bytes written so far. */
|
|
29
14
|
get length() {
|
|
30
15
|
return this.n;
|
|
31
16
|
}
|
|
32
17
|
get capacity() {
|
|
33
18
|
return this.buf.length;
|
|
34
19
|
}
|
|
35
|
-
|
|
20
|
+
// Retain capacity so repeated plugin passes can reuse the buffer without allocating.
|
|
36
21
|
reset() {
|
|
37
22
|
this.n = 0;
|
|
38
23
|
}
|
|
@@ -40,12 +25,11 @@ export class ByteWriter {
|
|
|
40
25
|
take() {
|
|
41
26
|
return this.n === 0 ? EMPTY : this.buf.subarray(0, this.n);
|
|
42
27
|
}
|
|
43
|
-
/** Release the backing (handed-out views stay intact); next write re-allocates. */
|
|
44
28
|
release() {
|
|
45
29
|
this.buf = EMPTY;
|
|
46
30
|
this.n = 0;
|
|
47
31
|
}
|
|
48
|
-
|
|
32
|
+
// Reserve capacity before unchecked writes.
|
|
49
33
|
ensure(extra) {
|
|
50
34
|
if (this.n + extra <= this.buf.length)
|
|
51
35
|
return;
|
|
@@ -66,12 +50,9 @@ export class ByteWriter {
|
|
|
66
50
|
buf[n++] = (v >>> 24) & 255;
|
|
67
51
|
this.n = n;
|
|
68
52
|
}
|
|
69
|
-
/** u32 byte length + UTF-8 bytes (self-ensuring). */
|
|
70
53
|
utf8WithU32Len(s) {
|
|
71
54
|
const len = s.length;
|
|
72
55
|
this.ensure(4 + len * 3); // worst-case UTF-8 is 3 bytes per UTF-16 unit
|
|
73
|
-
// Short strings: inline char copy (cheaper than a native call), guarded by a
|
|
74
|
-
// quick ASCII scan. Anything longer — or non-ASCII — goes to encodeInto.
|
|
75
56
|
if (len <= INLINE_STR_MAX) {
|
|
76
57
|
let ascii = true;
|
|
77
58
|
for (let i = 0; i < len; i++) {
|
|
@@ -81,8 +62,7 @@ export class ByteWriter {
|
|
|
81
62
|
}
|
|
82
63
|
}
|
|
83
64
|
if (ascii) {
|
|
84
|
-
// Inline stores
|
|
85
|
-
// unoptimized tier is exactly what this class's header rules out.
|
|
65
|
+
// Inline stores avoid per-string method calls before V8 has optimized this path.
|
|
86
66
|
const buf = this.buf;
|
|
87
67
|
let n = this.n;
|
|
88
68
|
buf[n++] = len & 255;
|
|
@@ -95,16 +75,12 @@ export class ByteWriter {
|
|
|
95
75
|
return;
|
|
96
76
|
}
|
|
97
77
|
}
|
|
98
|
-
// Bulk path: encodeInto writes UTF-8 straight into the buffer (no alloc, no
|
|
99
|
-
// per-char loop); backpatch the byte length once it's known.
|
|
100
78
|
const lenPos = this.n;
|
|
101
79
|
this.n += 4;
|
|
102
80
|
const written = encoder.encodeInto(s, this.buf.subarray(this.n)).written;
|
|
103
81
|
this.patchU32(lenPos, written);
|
|
104
82
|
this.n += written;
|
|
105
83
|
}
|
|
106
|
-
/** Backpatch a u32 (LE) at `pos` in the already-written region; the cursor
|
|
107
|
-
* is left untouched. */
|
|
108
84
|
patchU32(pos, v) {
|
|
109
85
|
const buf = this.buf;
|
|
110
86
|
buf[pos] = v & 255;
|
package/dist/child-stub.d.ts
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared machinery for walk-path child stubs (see `hast/child-stub.ts` and
|
|
3
|
-
* `mdast/child-stub.ts`): lightweight stand-ins that carry arena id + type
|
|
4
|
-
* eagerly and defer the full-arena snapshot until a plugin reads a real field.
|
|
5
|
-
* Passthrough children (the common replaceNode shape) thus compile to one-word
|
|
6
|
-
* refs without ever serializing the arena.
|
|
7
|
-
*/
|
|
8
1
|
export type StubDescriptorEntry = readonly [string, PropertyDescriptor];
|
|
9
|
-
/**
|
|
10
|
-
* Descriptor entries for one node type's stub fields. Own enumerable getters
|
|
11
|
-
* so a spread copy carries correct values. `position`/`data` ride on every
|
|
12
|
-
* stub; they may yield `undefined` where a materialized node omits the key —
|
|
13
|
-
* accepted drift, invisible to `toEqual`. Installed one `defineProperty` at a
|
|
14
|
-
* time: `Object.defineProperties` re-validates the whole map per call and
|
|
15
|
-
* costs nearly double.
|
|
16
|
-
*/
|
|
17
2
|
export declare function stubDescriptors(fields: readonly string[]): readonly StubDescriptorEntry[];
|
|
18
3
|
export declare function installStubDescriptors(host: object, entries: readonly StubDescriptorEntry[]): void;
|
|
19
|
-
/** Node tags are dense small ints, so the per-child stub loop indexes flat
|
|
20
|
-
* arrays instead of paying Map/dictionary lookups. */
|
|
21
4
|
export declare function flatByTag<T>(table: Readonly<Record<number, T>>): readonly (T | undefined)[];
|
package/dist/child-stub.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
* Shared machinery for walk-path child stubs (see `hast/child-stub.ts` and
|
|
3
|
-
* `mdast/child-stub.ts`): lightweight stand-ins that carry arena id + type
|
|
4
|
-
* eagerly and defer the full-arena snapshot until a plugin reads a real field.
|
|
5
|
-
* Passthrough children (the common replaceNode shape) thus compile to one-word
|
|
6
|
-
* refs without ever serializing the arena.
|
|
7
|
-
*/
|
|
8
|
-
/** Stub → materialized arena node, filled on the first real-field read. */
|
|
1
|
+
// Child stubs let unchanged children pass through as arena references without serializing the tree.
|
|
9
2
|
const REAL_NODES = new WeakMap();
|
|
10
|
-
|
|
11
|
-
* descriptor templates instead of allocating per-field closures per node. */
|
|
3
|
+
// Share getters across stubs to avoid allocating a closure for every field of every node.
|
|
12
4
|
const FIELD_GETTERS = new Map();
|
|
13
5
|
function fieldGetter(key) {
|
|
14
6
|
let getter = FIELD_GETTERS.get(key);
|
|
@@ -16,11 +8,11 @@ function fieldGetter(key) {
|
|
|
16
8
|
getter = function () {
|
|
17
9
|
let real = REAL_NODES.get(this);
|
|
18
10
|
if (real === undefined) {
|
|
19
|
-
real = this.
|
|
11
|
+
real = this._materialize();
|
|
20
12
|
REAL_NODES.set(this, real);
|
|
21
13
|
}
|
|
22
14
|
const value = real[key];
|
|
23
|
-
//
|
|
15
|
+
// Stub fields must remain as immutable as the frozen nodes they expose.
|
|
24
16
|
Object.defineProperty(this, key, {
|
|
25
17
|
value,
|
|
26
18
|
writable: false,
|
|
@@ -33,14 +25,7 @@ function fieldGetter(key) {
|
|
|
33
25
|
}
|
|
34
26
|
return getter;
|
|
35
27
|
}
|
|
36
|
-
|
|
37
|
-
* Descriptor entries for one node type's stub fields. Own enumerable getters
|
|
38
|
-
* so a spread copy carries correct values. `position`/`data` ride on every
|
|
39
|
-
* stub; they may yield `undefined` where a materialized node omits the key —
|
|
40
|
-
* accepted drift, invisible to `toEqual`. Installed one `defineProperty` at a
|
|
41
|
-
* time: `Object.defineProperties` re-validates the whole map per call and
|
|
42
|
-
* costs nearly double.
|
|
43
|
-
*/
|
|
28
|
+
// Individual defineProperty calls avoid the descriptor-map validation cost of defineProperties.
|
|
44
29
|
export function stubDescriptors(fields) {
|
|
45
30
|
const entries = [];
|
|
46
31
|
for (const key of [...fields, "position", "data"]) {
|
|
@@ -56,8 +41,7 @@ export function installStubDescriptors(host, entries) {
|
|
|
56
41
|
Object.defineProperty(host, e[0], e[1]);
|
|
57
42
|
}
|
|
58
43
|
}
|
|
59
|
-
|
|
60
|
-
* arrays instead of paying Map/dictionary lookups. */
|
|
44
|
+
// Dense node tags allow array indexing on the per-child hot path.
|
|
61
45
|
export function flatByTag(table) {
|
|
62
46
|
const flat = [];
|
|
63
47
|
for (const tag of Object.keys(table)) {
|
package/dist/command-buffer.d.ts
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Binary command buffer for efficient JS→Rust mutation serialization.
|
|
3
|
-
*
|
|
4
|
-
* Simple mutations (remove, setProperty) are encoded as compact binary commands.
|
|
5
|
-
* Structural mutations (insert, replace, …) carry one of two payload kinds:
|
|
6
|
-
* compiled op-streams (`PAYLOAD_OPSTREAM`, replayed straight into the arena —
|
|
7
|
-
* see op-stream.ts) for declarative content, or raw markdown/HTML strings
|
|
8
|
-
* (re-parsed by Rust) for the `{raw}`/`{rawHtml}` escape hatches.
|
|
9
|
-
*
|
|
10
|
-
* All multi-byte integers are little-endian to match native x86/ARM layout and
|
|
11
|
-
* avoid byte-swapping on the Rust side.
|
|
12
|
-
*/
|
|
13
1
|
import { OpWriter } from "./op-stream.js";
|
|
14
2
|
import type { MdastNode } from "./types.js";
|
|
15
3
|
type ReturnClass = "no_change" | "raw_markdown" | "raw_html" | "structured_node";
|
|
16
|
-
/** Input to the structural mutators (`replace`, `insertBefore`, …). */
|
|
17
4
|
type StructuralContent = MdastNode | {
|
|
18
5
|
raw: string;
|
|
19
6
|
mdxExpressions?: boolean;
|
|
@@ -25,36 +12,28 @@ export declare function classifyReturn(value: unknown): ReturnClass;
|
|
|
25
12
|
export declare const COMMAND_BUFFER_RETAIN_MAX: number;
|
|
26
13
|
export declare function acquireCommandBuffer(): CommandBuffer;
|
|
27
14
|
export declare function releaseCommandBuffer(buf: CommandBuffer): void;
|
|
28
|
-
/** Structural commands that carry a subtree payload emitted in place via `emitOpstreamCommand`. */
|
|
29
15
|
export type StructuralOp = "replace" | "insertBefore" | "insertAfter" | "prependChild" | "appendChild" | "wrapNode";
|
|
30
16
|
export declare const STRUCTURAL_CMD: Record<StructuralOp, number>;
|
|
31
17
|
export declare class CommandBuffer extends OpWriter {
|
|
32
18
|
#private;
|
|
33
19
|
constructor();
|
|
34
20
|
reset(): void;
|
|
35
|
-
/** Emit a structural command whose opstream payload is written by `emit`
|
|
36
|
-
* via the inherited op methods. If `emit` returns false or throws, the
|
|
37
|
-
* buffer is rolled back to the command start so the Rust decoder never
|
|
38
|
-
* sees a half-written command. Returns `emit`'s verdict. */
|
|
39
21
|
emitOpstreamCommand(cmd: number, nodeId: number, emit: () => boolean): boolean;
|
|
40
22
|
removeNode(nodeId: number): void;
|
|
41
|
-
/** Unified set-property for both MDAST and HAST nodes.
|
|
42
|
-
*
|
|
43
|
-
* Hot path: uses `encodeInto` to write UTF-8 straight into the buffer (no
|
|
44
|
-
* per-call `Uint8Array`), reserving the worst-case length up front and
|
|
45
|
-
* backfilling the length prefix once the byte count is known. */
|
|
46
23
|
setProperty(nodeId: number, key: string, value: unknown): void;
|
|
24
|
+
setField(nodeId: number, key: string, value: unknown): void;
|
|
25
|
+
setAttribute(nodeId: number, name: string, value: unknown): void;
|
|
26
|
+
/** Set a HAST element's list property from `encodeTokenList` bytes, whose
|
|
27
|
+
* separator the renderer picks from the element's schema. */
|
|
28
|
+
setTokenListProperty(nodeId: number, key: string, tokens: string): void;
|
|
47
29
|
insertBefore(nodeId: number, newNode: StructuralContent): void;
|
|
48
30
|
insertAfter(nodeId: number, newNode: StructuralContent): void;
|
|
49
31
|
prependChild(nodeId: number, newNode: StructuralContent): void;
|
|
50
32
|
appendChild(nodeId: number, newNode: StructuralContent): void;
|
|
51
33
|
wrapNode(nodeId: number, parentNode: StructuralContent): void;
|
|
52
34
|
replace(nodeId: number, newNode: StructuralContent): void;
|
|
53
|
-
/** Header (cmd + nodeId + PAYLOAD_RAW + flags) followed by a length-prefixed string. */
|
|
54
35
|
private writeRawCommand;
|
|
55
|
-
/** Return a Uint8Array view of the written bytes (no copy). */
|
|
56
36
|
getBuffer(): Uint8Array;
|
|
57
|
-
/** Encode the raw-string escape hatch; declarative nodes use `*Opstream` instead. */
|
|
58
37
|
private writeStructuralCommand;
|
|
59
38
|
}
|
|
60
39
|
export {};
|
package/dist/command-buffer.js
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
* Binary command buffer for efficient JS→Rust mutation serialization.
|
|
3
|
-
*
|
|
4
|
-
* Simple mutations (remove, setProperty) are encoded as compact binary commands.
|
|
5
|
-
* Structural mutations (insert, replace, …) carry one of two payload kinds:
|
|
6
|
-
* compiled op-streams (`PAYLOAD_OPSTREAM`, replayed straight into the arena —
|
|
7
|
-
* see op-stream.ts) for declarative content, or raw markdown/HTML strings
|
|
8
|
-
* (re-parsed by Rust) for the `{raw}`/`{rawHtml}` escape hatches.
|
|
9
|
-
*
|
|
10
|
-
* All multi-byte integers are little-endian to match native x86/ARM layout and
|
|
11
|
-
* avoid byte-swapping on the Rust side.
|
|
12
|
-
*/
|
|
1
|
+
// Little-endian fields match the Rust wire protocol without byte swapping on x86/ARM.
|
|
13
2
|
import { OpWriter } from "./op-stream.js";
|
|
14
|
-
import { PROP_STRING, PROP_BOOL_TRUE, PROP_BOOL_FALSE, PROP_SPACE_SEP, PROP_INT, PROP_NULL, } from "./op-stream.js";
|
|
15
|
-
import { CMD_REMOVE, CMD_INSERT_BEFORE, CMD_INSERT_AFTER, CMD_PREPEND_CHILD, CMD_APPEND_CHILD, CMD_WRAP, CMD_REPLACE, CMD_SET_PROPERTY,
|
|
3
|
+
import { PROP_STRING, PROP_BOOL_TRUE, PROP_BOOL_FALSE, PROP_SPACE_SEP, PROP_INT, PROP_NULL, PROP_TOKEN_LIST, } from "./op-stream.js";
|
|
4
|
+
import { CMD_REMOVE, CMD_INSERT_BEFORE, CMD_INSERT_AFTER, CMD_PREPEND_CHILD, CMD_APPEND_CHILD, CMD_WRAP, CMD_REPLACE, CMD_SET_PROPERTY, CMD_SET_FIELD, CMD_SET_ATTRIBUTE, PAYLOAD_RAW, RAW_LITERAL_BRACES, PAYLOAD_OPSTREAM, } from "./generated/wire-constants.js";
|
|
16
5
|
export function classifyReturn(value) {
|
|
17
6
|
if (value === undefined || value === null)
|
|
18
7
|
return "no_change";
|
|
@@ -26,10 +15,7 @@ export function classifyReturn(value) {
|
|
|
26
15
|
throw new Error("Invalid return value from visitor: must have raw, rawHtml, or type");
|
|
27
16
|
}
|
|
28
17
|
const INITIAL_SIZE = 4096;
|
|
29
|
-
|
|
30
|
-
* across plugin passes. Safe to retain the backing because `mergeAndReset`
|
|
31
|
-
* copies the bytes out before a buffer is released, so no view outlives a
|
|
32
|
-
* pass. Cap bounds the pool for processes that briefly burst high. */
|
|
18
|
+
// collectCommands copies bytes before release, so pooled buffers cannot invalidate returned commands.
|
|
33
19
|
const COMMAND_BUFFER_POOL_MAX = 8;
|
|
34
20
|
/** Backings above this are dropped on release so one huge compile does not retain megabytes forever. */
|
|
35
21
|
export const COMMAND_BUFFER_RETAIN_MAX = 1 << 20;
|
|
@@ -54,8 +40,7 @@ export const STRUCTURAL_CMD = {
|
|
|
54
40
|
wrapNode: CMD_WRAP,
|
|
55
41
|
};
|
|
56
42
|
export class CommandBuffer extends OpWriter {
|
|
57
|
-
|
|
58
|
-
* methods must not interleave bytes into it. */
|
|
43
|
+
// Commands must not interleave bytes while a structural payload is being emitted.
|
|
59
44
|
#inOpstream = false;
|
|
60
45
|
constructor() {
|
|
61
46
|
super(INITIAL_SIZE);
|
|
@@ -69,14 +54,10 @@ export class CommandBuffer extends OpWriter {
|
|
|
69
54
|
throw new Error("reentrant command emission: a node getter or toJSON invoked a context mutation while a structural payload was being encoded");
|
|
70
55
|
}
|
|
71
56
|
}
|
|
72
|
-
|
|
73
|
-
* via the inherited op methods. If `emit` returns false or throws, the
|
|
74
|
-
* buffer is rolled back to the command start so the Rust decoder never
|
|
75
|
-
* sees a half-written command. Returns `emit`'s verdict. */
|
|
57
|
+
// Roll back failed payloads so the Rust decoder never sees a partial command.
|
|
76
58
|
emitOpstreamCommand(cmd, nodeId, emit) {
|
|
77
59
|
const commandStart = this.n;
|
|
78
60
|
const lenPos = this.#beginOpstream(cmd, nodeId);
|
|
79
|
-
// ok starts false so a throwing emit still hits the abort in finally
|
|
80
61
|
let ok = false;
|
|
81
62
|
try {
|
|
82
63
|
ok = emit();
|
|
@@ -89,9 +70,6 @@ export class CommandBuffer extends OpWriter {
|
|
|
89
70
|
this.#endOpstream(lenPos);
|
|
90
71
|
return ok;
|
|
91
72
|
}
|
|
92
|
-
/** Open a structural command whose opstream payload is emitted in place via
|
|
93
|
-
* the inherited op methods; returns the backpatch position for
|
|
94
|
-
* `#endOpstream`. Pair with `#abortOpstream` on failure. */
|
|
95
73
|
#beginOpstream(cmd, nodeId) {
|
|
96
74
|
this.#assertNotEncoding();
|
|
97
75
|
this.#inOpstream = true;
|
|
@@ -107,7 +85,6 @@ export class CommandBuffer extends OpWriter {
|
|
|
107
85
|
this.#inOpstream = false;
|
|
108
86
|
this.patchU32(lenPos, this.n - (lenPos + 4));
|
|
109
87
|
}
|
|
110
|
-
/** Roll back an in-progress opstream command (unencodable content). */
|
|
111
88
|
#abortOpstream(commandStart) {
|
|
112
89
|
this.#inOpstream = false;
|
|
113
90
|
this.n = commandStart;
|
|
@@ -118,12 +95,16 @@ export class CommandBuffer extends OpWriter {
|
|
|
118
95
|
this.buf[this.n++] = CMD_REMOVE;
|
|
119
96
|
this.writeU32(nodeId);
|
|
120
97
|
}
|
|
121
|
-
/** Unified set-property for both MDAST and HAST nodes.
|
|
122
|
-
*
|
|
123
|
-
* Hot path: uses `encodeInto` to write UTF-8 straight into the buffer (no
|
|
124
|
-
* per-call `Uint8Array`), reserving the worst-case length up front and
|
|
125
|
-
* backfilling the length prefix once the byte count is known. */
|
|
126
98
|
setProperty(nodeId, key, value) {
|
|
99
|
+
this.#writeNamedValue(CMD_SET_PROPERTY, nodeId, key, value);
|
|
100
|
+
}
|
|
101
|
+
setField(nodeId, key, value) {
|
|
102
|
+
this.#writeNamedValue(CMD_SET_FIELD, nodeId, key, value);
|
|
103
|
+
}
|
|
104
|
+
setAttribute(nodeId, name, value) {
|
|
105
|
+
this.#writeNamedValue(CMD_SET_ATTRIBUTE, nodeId, name, value);
|
|
106
|
+
}
|
|
107
|
+
#writeNamedValue(cmd, nodeId, key, value) {
|
|
127
108
|
this.#assertNotEncoding();
|
|
128
109
|
let valueType;
|
|
129
110
|
let str;
|
|
@@ -151,14 +132,24 @@ export class CommandBuffer extends OpWriter {
|
|
|
151
132
|
valueType = PROP_STRING;
|
|
152
133
|
str = String(value);
|
|
153
134
|
}
|
|
154
|
-
// 1(cmd) + 4(nodeId) + 1(valueType); name and value are length-prefixed strings
|
|
155
135
|
this.ensure(6);
|
|
156
|
-
this.buf[this.n++] =
|
|
136
|
+
this.buf[this.n++] = cmd;
|
|
157
137
|
this.writeU32(nodeId);
|
|
158
138
|
this.buf[this.n++] = valueType;
|
|
159
139
|
this.utf8WithU32Len(key);
|
|
160
140
|
this.utf8WithU32Len(str);
|
|
161
141
|
}
|
|
142
|
+
/** Set a HAST element's list property from `encodeTokenList` bytes, whose
|
|
143
|
+
* separator the renderer picks from the element's schema. */
|
|
144
|
+
setTokenListProperty(nodeId, key, tokens) {
|
|
145
|
+
this.#assertNotEncoding();
|
|
146
|
+
this.ensure(6);
|
|
147
|
+
this.buf[this.n++] = CMD_SET_PROPERTY;
|
|
148
|
+
this.writeU32(nodeId);
|
|
149
|
+
this.buf[this.n++] = PROP_TOKEN_LIST;
|
|
150
|
+
this.utf8WithU32Len(key);
|
|
151
|
+
this.utf8WithU32Len(tokens);
|
|
152
|
+
}
|
|
162
153
|
insertBefore(nodeId, newNode) {
|
|
163
154
|
this.writeStructuralCommand(CMD_INSERT_BEFORE, nodeId, newNode);
|
|
164
155
|
}
|
|
@@ -177,7 +168,6 @@ export class CommandBuffer extends OpWriter {
|
|
|
177
168
|
replace(nodeId, newNode) {
|
|
178
169
|
this.writeStructuralCommand(CMD_REPLACE, nodeId, newNode);
|
|
179
170
|
}
|
|
180
|
-
/** Header (cmd + nodeId + PAYLOAD_RAW + flags) followed by a length-prefixed string. */
|
|
181
171
|
writeRawCommand(cmd, nodeId, flags, s) {
|
|
182
172
|
this.#assertNotEncoding();
|
|
183
173
|
this.ensure(7);
|
|
@@ -187,11 +177,10 @@ export class CommandBuffer extends OpWriter {
|
|
|
187
177
|
this.buf[this.n++] = flags;
|
|
188
178
|
this.utf8WithU32Len(s);
|
|
189
179
|
}
|
|
190
|
-
|
|
180
|
+
// This view aliases the buffer and must be copied before it is released to the pool.
|
|
191
181
|
getBuffer() {
|
|
192
182
|
return this.take();
|
|
193
183
|
}
|
|
194
|
-
/** Encode the raw-string escape hatch; declarative nodes use `*Opstream` instead. */
|
|
195
184
|
writeStructuralCommand(cmd, nodeId, node) {
|
|
196
185
|
const v = node;
|
|
197
186
|
if (typeof v.raw === "string") {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { markdownToHtmlFast } from "#binding";
|
|
2
|
+
import type { Features, MdxOnlyOptions } from "./compile-types.js";
|
|
3
|
+
export declare const DEFAULT_PARSE_OPTIONS: number;
|
|
4
|
+
export type NativeConvertOptions = NonNullable<Parameters<typeof markdownToHtmlFast>[2]>;
|
|
5
|
+
type NativeCompileOptions = {
|
|
6
|
+
parseOptions: number;
|
|
7
|
+
convertOptions: NativeConvertOptions | undefined;
|
|
8
|
+
};
|
|
9
|
+
export declare function featuresToNative(features: Features | undefined): NativeCompileOptions;
|
|
10
|
+
export declare function mdxOptionsToNative(opts: MdxOnlyOptions): MdxOnlyOptions | undefined;
|
|
11
|
+
export {};
|