satteri 0.8.0 → 0.9.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 +35 -0
- package/dist/byte-writer.d.ts +31 -0
- package/dist/byte-writer.js +106 -0
- package/dist/child-stub.d.ts +17 -0
- package/dist/child-stub.js +57 -0
- package/dist/command-buffer.d.ts +23 -24
- package/dist/command-buffer.js +65 -128
- package/dist/compile.d.ts +5 -1
- package/dist/compile.js +40 -26
- package/dist/directive-types.d.ts +4 -2
- package/dist/generated/arena-layout.d.ts +37 -0
- package/dist/generated/arena-layout.js +41 -0
- package/dist/generated/wire-constants.d.ts +51 -0
- package/dist/generated/wire-constants.js +63 -0
- package/dist/handles.d.ts +21 -0
- package/dist/handles.js +1 -0
- package/dist/hast/child-stub.d.ts +18 -0
- package/dist/hast/child-stub.js +43 -0
- package/dist/hast/element-props.d.ts +2 -0
- package/dist/hast/element-props.js +23 -0
- package/dist/hast/generated/node-types.d.ts +14 -0
- package/dist/hast/generated/node-types.js +64 -0
- package/dist/hast/hast-materializer.d.ts +2 -1
- package/dist/hast/hast-materializer.js +9 -45
- package/dist/hast/hast-reader.d.ts +18 -23
- package/dist/hast/hast-reader.js +48 -115
- package/dist/hast/hast-visitor.d.ts +38 -12
- package/dist/hast/hast-visitor.js +417 -281
- package/dist/index.d.ts +10 -4
- package/dist/index.js +23 -1
- package/dist/lazy-child-resolver.d.ts +36 -0
- package/dist/lazy-child-resolver.js +95 -0
- package/dist/lazy-props.d.ts +1 -1
- package/dist/mdast/child-stub.d.ts +18 -0
- package/dist/mdast/child-stub.js +46 -0
- package/dist/mdast/column-align.d.ts +1 -0
- package/dist/mdast/column-align.js +6 -0
- package/dist/mdast/generated/layout.d.ts +19 -0
- package/dist/mdast/generated/layout.js +272 -0
- package/dist/mdast/generated/node-types.d.ts +58 -0
- package/dist/mdast/generated/node-types.js +266 -0
- package/dist/mdast/mdast-materializer.d.ts +3 -2
- package/dist/mdast/mdast-materializer.js +9 -93
- package/dist/mdast/mdast-reader.d.ts +4 -120
- package/dist/mdast/mdast-reader.js +45 -272
- package/dist/mdast/mdast-visitor.d.ts +55 -13
- package/dist/mdast/mdast-visitor.js +375 -410
- package/dist/mdx-attr.d.ts +2 -0
- package/dist/mdx-attr.js +20 -0
- package/dist/op-stream.d.ts +38 -0
- package/dist/op-stream.js +125 -0
- package/dist/phantom.d.ts +2 -0
- package/dist/phantom.js +13 -0
- package/dist/types.d.ts +34 -4
- package/dist/visitor-shared.d.ts +28 -0
- package/dist/visitor-shared.js +52 -0
- package/dist/wire-read.d.ts +27 -0
- package/dist/wire-read.js +59 -0
- package/index.js +52 -52
- package/package.json +6 -6
package/dist/compile.js
CHANGED
|
@@ -3,6 +3,7 @@ import { visitMdastHandle, resolveMdastSubscriptions, } from "./mdast/mdast-visi
|
|
|
3
3
|
import { createHastHandle, createMdxHastHandle, renderHandle, compileHandle, dropHandle, createMdastHandle, createMdxMdastHandle, applyCommandsToMdastHandle, convertMdastToHastHandle, getHandleSource, getMdastFrontmatter, serializeHandle, } from "#binding";
|
|
4
4
|
import { MdastReader } from "./mdast/mdast-reader.js";
|
|
5
5
|
import { materializeMdastTree } from "./mdast/mdast-materializer.js";
|
|
6
|
+
import { markHandleMutated } from "./lazy-child-resolver.js";
|
|
6
7
|
import { HastReader } from "./hast/hast-reader.js";
|
|
7
8
|
import { materializeHastTree } from "./hast/hast-materializer.js";
|
|
8
9
|
/**
|
|
@@ -74,13 +75,20 @@ function featuresToNative(features) {
|
|
|
74
75
|
}
|
|
75
76
|
return { features: result, convertOptions };
|
|
76
77
|
}
|
|
78
|
+
/** Drop a handle after bumping its epoch: the arena dies with the handle, so a
|
|
79
|
+
* child stub retained past the pipeline must hit the designed retention error,
|
|
80
|
+
* not a cryptic RangeError from snapshotting the freed arena. */
|
|
81
|
+
function disposeHandle(handle) {
|
|
82
|
+
markHandleMutated(handle);
|
|
83
|
+
dropHandle(handle);
|
|
84
|
+
}
|
|
77
85
|
function warnDroppedTransforms(plugin, dropped, kind) {
|
|
78
86
|
const name = plugin.name ?? "<anonymous>";
|
|
79
87
|
const noun = dropped === 1 ? "transform" : "transforms";
|
|
80
88
|
console.warn(`satteri: plugin "${name}" queued ${dropped} ${kind} ${noun} on node(s) that were removed or ` +
|
|
81
89
|
`replaced earlier in the same pass; ${dropped === 1 ? "it was" : "they were"} dropped.`);
|
|
82
90
|
}
|
|
83
|
-
function runMdastPluginsOnHandle(handle, plugins, fileURL) {
|
|
91
|
+
function runMdastPluginsOnHandle(handle, plugins, fileURL, data) {
|
|
84
92
|
// Each plugin runs once over the tree. A transform that passes a child
|
|
85
93
|
// through (returning it inside the replacement) keeps that child's identity,
|
|
86
94
|
// so a patch the same pass queued on it still applies — nesting composes in
|
|
@@ -88,10 +96,11 @@ function runMdastPluginsOnHandle(handle, plugins, fileURL) {
|
|
|
88
96
|
// them up front, or hand off to a later plugin that sees the materialized tree.
|
|
89
97
|
const runPlugin = (plugin) => {
|
|
90
98
|
const subs = resolveMdastSubscriptions(plugin);
|
|
91
|
-
const result = visitMdastHandle(handle, plugin, subs, () => getHandleSource(handle), fileURL);
|
|
99
|
+
const result = visitMdastHandle(handle, plugin, subs, () => getHandleSource(handle), fileURL, data);
|
|
92
100
|
const apply = (r) => {
|
|
93
101
|
if (!r.hasMutations)
|
|
94
102
|
return;
|
|
103
|
+
markHandleMutated(handle);
|
|
95
104
|
const dropped = applyCommandsToMdastHandle(handle, r.commandBuffer);
|
|
96
105
|
if (dropped)
|
|
97
106
|
warnDroppedTransforms(plugin, dropped, "mdast");
|
|
@@ -111,7 +120,7 @@ function runMdastPluginsOnHandle(handle, plugins, fileURL) {
|
|
|
111
120
|
};
|
|
112
121
|
return runNext();
|
|
113
122
|
}
|
|
114
|
-
function runHastPluginsOnHandle(handle, plugins, source, fileURL) {
|
|
123
|
+
function runHastPluginsOnHandle(handle, plugins, source, fileURL, data) {
|
|
115
124
|
if (plugins.length === 0)
|
|
116
125
|
return;
|
|
117
126
|
let i = 0;
|
|
@@ -121,7 +130,7 @@ function runHastPluginsOnHandle(handle, plugins, source, fileURL) {
|
|
|
121
130
|
i++;
|
|
122
131
|
const plugin = typeof raw === "function" ? raw() : raw;
|
|
123
132
|
const subs = resolveSubscriptions(plugin);
|
|
124
|
-
const result = visitHastHandle(handle, plugin, subs, source, fileURL);
|
|
133
|
+
const result = visitHastHandle(handle, plugin, subs, source, fileURL, data);
|
|
125
134
|
const warnIfDropped = (dropped) => {
|
|
126
135
|
if (dropped)
|
|
127
136
|
warnDroppedTransforms(plugin, dropped, "hast");
|
|
@@ -183,28 +192,29 @@ function mdxOptionsToNative(opts) {
|
|
|
183
192
|
export function markdownToHtml(source, options = {}) {
|
|
184
193
|
const { mdastPlugins = [], hastPlugins = [], features, fileURL } = options;
|
|
185
194
|
const { features: nativeFeatures, convertOptions: nativeConvertOptions } = featuresToNative(features);
|
|
186
|
-
const
|
|
195
|
+
const data = {};
|
|
196
|
+
const result = createHastHandleFromMdast(source, mdastPlugins, false, fileURL, nativeFeatures, nativeConvertOptions, data);
|
|
187
197
|
const renderAndDrop = (h, frontmatter) => {
|
|
188
198
|
try {
|
|
189
199
|
const html = renderHandle(h);
|
|
190
|
-
return { html, frontmatter };
|
|
200
|
+
return { html, frontmatter, data };
|
|
191
201
|
}
|
|
192
202
|
finally {
|
|
193
|
-
|
|
203
|
+
disposeHandle(h);
|
|
194
204
|
}
|
|
195
205
|
};
|
|
196
206
|
const runHastThenRender = (r) => {
|
|
197
207
|
let hastResult;
|
|
198
208
|
try {
|
|
199
|
-
hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL);
|
|
209
|
+
hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL, data);
|
|
200
210
|
}
|
|
201
211
|
catch (err) {
|
|
202
|
-
|
|
212
|
+
disposeHandle(r.hastHandle);
|
|
203
213
|
throw err;
|
|
204
214
|
}
|
|
205
215
|
if (hastResult instanceof Promise) {
|
|
206
216
|
return hastResult.then(() => renderAndDrop(r.hastHandle, r.frontmatter), (err) => {
|
|
207
|
-
|
|
217
|
+
disposeHandle(r.hastHandle);
|
|
208
218
|
throw err;
|
|
209
219
|
});
|
|
210
220
|
}
|
|
@@ -218,28 +228,29 @@ export function mdxToJs(source, options = {}) {
|
|
|
218
228
|
const { mdastPlugins = [], hastPlugins = [], features, fileURL, ...mdxFields } = options;
|
|
219
229
|
const mdxOptions = mdxOptionsToNative(mdxFields);
|
|
220
230
|
const { features: nativeFeatures, convertOptions: nativeConvertOptions } = featuresToNative(features);
|
|
221
|
-
const
|
|
231
|
+
const data = {};
|
|
232
|
+
const result = createHastHandleFromMdast(source, mdastPlugins, true, fileURL, nativeFeatures, nativeConvertOptions, data);
|
|
222
233
|
const compileAndDrop = (h, frontmatter) => {
|
|
223
234
|
try {
|
|
224
235
|
const code = compileHandle(h, mdxOptions);
|
|
225
|
-
return { code, frontmatter };
|
|
236
|
+
return { code, frontmatter, data };
|
|
226
237
|
}
|
|
227
238
|
finally {
|
|
228
|
-
|
|
239
|
+
disposeHandle(h);
|
|
229
240
|
}
|
|
230
241
|
};
|
|
231
242
|
const runHastThenCompile = (r) => {
|
|
232
243
|
let hastResult;
|
|
233
244
|
try {
|
|
234
|
-
hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL);
|
|
245
|
+
hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL, data);
|
|
235
246
|
}
|
|
236
247
|
catch (err) {
|
|
237
|
-
|
|
248
|
+
disposeHandle(r.hastHandle);
|
|
238
249
|
throw err;
|
|
239
250
|
}
|
|
240
251
|
if (hastResult instanceof Promise) {
|
|
241
252
|
return hastResult.then(() => compileAndDrop(r.hastHandle, r.frontmatter), (err) => {
|
|
242
|
-
|
|
253
|
+
disposeHandle(r.hastHandle);
|
|
243
254
|
throw err;
|
|
244
255
|
});
|
|
245
256
|
}
|
|
@@ -280,37 +291,40 @@ function createHastHandleFromMdast(source, mdastPlugins, mdx, fileURL,
|
|
|
280
291
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
281
292
|
nativeFeatures,
|
|
282
293
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
283
|
-
nativeConvertOptions) {
|
|
294
|
+
nativeConvertOptions, data) {
|
|
284
295
|
const mdastHandle = mdx
|
|
285
296
|
? createMdxMdastHandle(source, nativeFeatures)
|
|
286
297
|
: createMdastHandle(source, nativeFeatures);
|
|
287
|
-
// finally{
|
|
298
|
+
// finally{dispose} is intentional: convertMdastToHastHandle empties the arena
|
|
288
299
|
// on success, but if any step here throws the handle would otherwise leak.
|
|
289
300
|
const finalize = (r) => {
|
|
290
301
|
try {
|
|
291
302
|
const frontmatter = readFrontmatter(r.handle);
|
|
303
|
+
// The conversion empties the mdast arena; bump the epoch so a stub
|
|
304
|
+
// retained past the mdast pass fails with the retention error.
|
|
305
|
+
markHandleMutated(r.handle);
|
|
292
306
|
const hastHandle = convertMdastToHastHandle(r.handle, nativeConvertOptions);
|
|
293
307
|
return { hastHandle, frontmatter };
|
|
294
308
|
}
|
|
295
309
|
finally {
|
|
296
|
-
|
|
310
|
+
disposeHandle(r.handle);
|
|
297
311
|
}
|
|
298
312
|
};
|
|
299
313
|
try {
|
|
300
314
|
if (mdastPlugins.length === 0) {
|
|
301
315
|
return finalize({ handle: mdastHandle });
|
|
302
316
|
}
|
|
303
|
-
const mdastResult = runMdastPluginsOnHandle(mdastHandle, mdastPlugins, fileURL);
|
|
317
|
+
const mdastResult = runMdastPluginsOnHandle(mdastHandle, mdastPlugins, fileURL, data);
|
|
304
318
|
if (mdastResult instanceof Promise) {
|
|
305
319
|
return mdastResult.then(finalize, (err) => {
|
|
306
|
-
|
|
320
|
+
disposeHandle(mdastHandle);
|
|
307
321
|
throw err;
|
|
308
322
|
});
|
|
309
323
|
}
|
|
310
324
|
return finalize(mdastResult);
|
|
311
325
|
}
|
|
312
326
|
catch (err) {
|
|
313
|
-
|
|
327
|
+
disposeHandle(mdastHandle);
|
|
314
328
|
throw err;
|
|
315
329
|
}
|
|
316
330
|
}
|
|
@@ -322,7 +336,7 @@ export function markdownToMdast(source, options = {}) {
|
|
|
322
336
|
return materializeMdastTree(new MdastReader(serializeHandle(handle)));
|
|
323
337
|
}
|
|
324
338
|
finally {
|
|
325
|
-
|
|
339
|
+
disposeHandle(handle);
|
|
326
340
|
}
|
|
327
341
|
}
|
|
328
342
|
/** Parse MDX source into a materialized mdast tree. */
|
|
@@ -332,7 +346,7 @@ export function mdxToMdast(source, options = {}) {
|
|
|
332
346
|
return materializeMdastTree(new MdastReader(serializeHandle(handle)));
|
|
333
347
|
}
|
|
334
348
|
finally {
|
|
335
|
-
|
|
349
|
+
disposeHandle(handle);
|
|
336
350
|
}
|
|
337
351
|
}
|
|
338
352
|
/** Convert Markdown source to a materialized hast tree. */
|
|
@@ -343,7 +357,7 @@ export function markdownToHast(source, options = {}) {
|
|
|
343
357
|
return materializeHastTree(new HastReader(serializeHandle(handle)));
|
|
344
358
|
}
|
|
345
359
|
finally {
|
|
346
|
-
|
|
360
|
+
disposeHandle(handle);
|
|
347
361
|
}
|
|
348
362
|
}
|
|
349
363
|
/** Convert MDX source to a materialized hast tree. */
|
|
@@ -354,6 +368,6 @@ export function mdxToHast(source, options = {}) {
|
|
|
354
368
|
return materializeHastTree(new HastReader(serializeHandle(handle)));
|
|
355
369
|
}
|
|
356
370
|
finally {
|
|
357
|
-
|
|
371
|
+
disposeHandle(handle);
|
|
358
372
|
}
|
|
359
373
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BlockContent, Data as MdastData, DefinitionContent, Parent as MdastParent, PhrasingContent } from "mdast";
|
|
2
|
-
export type DirectiveAttributes = Record<string, string>;
|
|
2
|
+
export type DirectiveAttributes = Record<string, string | null | undefined>;
|
|
3
3
|
export interface ContainerDirective extends MdastParent {
|
|
4
4
|
type: "containerDirective";
|
|
5
5
|
name: string;
|
|
@@ -8,7 +8,6 @@ export interface ContainerDirective extends MdastParent {
|
|
|
8
8
|
data?: ContainerDirectiveData | undefined;
|
|
9
9
|
}
|
|
10
10
|
export interface ContainerDirectiveData extends MdastData {
|
|
11
|
-
directiveLabel?: boolean | undefined;
|
|
12
11
|
}
|
|
13
12
|
export interface LeafDirective extends MdastParent {
|
|
14
13
|
type: "leafDirective";
|
|
@@ -33,6 +32,9 @@ declare module "mdast" {
|
|
|
33
32
|
containerDirective: ContainerDirective;
|
|
34
33
|
leafDirective: LeafDirective;
|
|
35
34
|
}
|
|
35
|
+
interface ParagraphData {
|
|
36
|
+
directiveLabel?: boolean | null | undefined;
|
|
37
|
+
}
|
|
36
38
|
interface PhrasingContentMap {
|
|
37
39
|
textDirective: TextDirective;
|
|
38
40
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** `b"MDAR"` magic, read as a little-endian u32. */
|
|
2
|
+
export declare const ARENA_MAGIC = 1380009037;
|
|
3
|
+
/** `Arena<K>` kind tags carried in the header's `kind` field. */
|
|
4
|
+
export declare const KIND_MDAST = 1;
|
|
5
|
+
export declare const KIND_HAST = 2;
|
|
6
|
+
/** `ArenaNode` `#[repr(C)]` field byte offsets (u32 fields; `node_type` is a u8). */
|
|
7
|
+
export declare const FIELD: {
|
|
8
|
+
readonly id: 0;
|
|
9
|
+
readonly node_type: 4;
|
|
10
|
+
readonly parent: 8;
|
|
11
|
+
readonly start_offset: 12;
|
|
12
|
+
readonly end_offset: 16;
|
|
13
|
+
readonly start_line: 20;
|
|
14
|
+
readonly start_column: 24;
|
|
15
|
+
readonly end_line: 28;
|
|
16
|
+
readonly end_column: 32;
|
|
17
|
+
readonly children_start: 36;
|
|
18
|
+
readonly children_count: 40;
|
|
19
|
+
readonly data_offset: 44;
|
|
20
|
+
readonly data_len: 48;
|
|
21
|
+
};
|
|
22
|
+
/** Raw-buffer header byte offsets (4-byte fields, u32 LE). */
|
|
23
|
+
export declare const HEADER: {
|
|
24
|
+
readonly magic: 0;
|
|
25
|
+
readonly kind: 4;
|
|
26
|
+
readonly node_struct_size: 8;
|
|
27
|
+
readonly node_count: 12;
|
|
28
|
+
readonly nodes_offset: 16;
|
|
29
|
+
readonly children_count: 20;
|
|
30
|
+
readonly children_offset: 24;
|
|
31
|
+
readonly type_data_len: 28;
|
|
32
|
+
readonly type_data_offset: 32;
|
|
33
|
+
readonly source_len: 36;
|
|
34
|
+
readonly source_offset: 40;
|
|
35
|
+
readonly node_data_count: 44;
|
|
36
|
+
readonly node_data_offset: 48;
|
|
37
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// @generated by `cargo run -p satteri-layout-codegen`. Do not edit by hand.
|
|
2
|
+
// Arena raw-buffer layout, declared once in `satteri-layout-codegen/src/schema.rs`.
|
|
3
|
+
// The Rust side is pinned to these offsets by the compile-time asserts in
|
|
4
|
+
// `satteri-arena/src/generated/layout.rs`.
|
|
5
|
+
/** `b"MDAR"` magic, read as a little-endian u32. */
|
|
6
|
+
export const ARENA_MAGIC = 0x5241444d;
|
|
7
|
+
/** `Arena<K>` kind tags carried in the header's `kind` field. */
|
|
8
|
+
export const KIND_MDAST = 1;
|
|
9
|
+
export const KIND_HAST = 2;
|
|
10
|
+
/** `ArenaNode` `#[repr(C)]` field byte offsets (u32 fields; `node_type` is a u8). */
|
|
11
|
+
export const FIELD = {
|
|
12
|
+
id: 0,
|
|
13
|
+
node_type: 4,
|
|
14
|
+
parent: 8,
|
|
15
|
+
start_offset: 12,
|
|
16
|
+
end_offset: 16,
|
|
17
|
+
start_line: 20,
|
|
18
|
+
start_column: 24,
|
|
19
|
+
end_line: 28,
|
|
20
|
+
end_column: 32,
|
|
21
|
+
children_start: 36,
|
|
22
|
+
children_count: 40,
|
|
23
|
+
data_offset: 44,
|
|
24
|
+
data_len: 48,
|
|
25
|
+
};
|
|
26
|
+
/** Raw-buffer header byte offsets (4-byte fields, u32 LE). */
|
|
27
|
+
export const HEADER = {
|
|
28
|
+
magic: 0,
|
|
29
|
+
kind: 4,
|
|
30
|
+
node_struct_size: 8,
|
|
31
|
+
node_count: 12,
|
|
32
|
+
nodes_offset: 16,
|
|
33
|
+
children_count: 20,
|
|
34
|
+
children_offset: 24,
|
|
35
|
+
type_data_len: 28,
|
|
36
|
+
type_data_offset: 32,
|
|
37
|
+
source_len: 36,
|
|
38
|
+
source_offset: 40,
|
|
39
|
+
node_data_count: 44,
|
|
40
|
+
node_data_offset: 48,
|
|
41
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export declare const OP_OPEN = 1;
|
|
2
|
+
export declare const OP_CLOSE = 2;
|
|
3
|
+
export declare const OP_REF = 3;
|
|
4
|
+
export declare const OP_KEEP_CHILDREN = 4;
|
|
5
|
+
export declare const OP_STR = 5;
|
|
6
|
+
export declare const OP_U8 = 6;
|
|
7
|
+
export declare const OP_U32 = 7;
|
|
8
|
+
export declare const OP_BOOL = 8;
|
|
9
|
+
export declare const OP_DATA = 9;
|
|
10
|
+
export declare const OP_PROP = 10;
|
|
11
|
+
export declare const OP_ALIGN = 11;
|
|
12
|
+
export declare const OF_VALUE = 0;
|
|
13
|
+
export declare const OF_URL = 1;
|
|
14
|
+
export declare const OF_TITLE = 2;
|
|
15
|
+
export declare const OF_ALT = 3;
|
|
16
|
+
export declare const OF_LANG = 4;
|
|
17
|
+
export declare const OF_META = 5;
|
|
18
|
+
export declare const OF_IDENTIFIER = 6;
|
|
19
|
+
export declare const OF_LABEL = 7;
|
|
20
|
+
export declare const OF_NAME = 8;
|
|
21
|
+
export declare const OF_REFERENCE_TYPE = 9;
|
|
22
|
+
export declare const OF_DEPTH = 10;
|
|
23
|
+
export declare const OF_CHECKED = 11;
|
|
24
|
+
export declare const OF_START = 12;
|
|
25
|
+
export declare const OF_ORDERED = 13;
|
|
26
|
+
export declare const OF_SPREAD = 14;
|
|
27
|
+
export declare const OF_TAGNAME = 15;
|
|
28
|
+
export declare const OF_EXPLICIT = 16;
|
|
29
|
+
export declare const CMD_REMOVE = 1;
|
|
30
|
+
export declare const CMD_INSERT_BEFORE = 5;
|
|
31
|
+
export declare const CMD_INSERT_AFTER = 6;
|
|
32
|
+
export declare const CMD_PREPEND_CHILD = 7;
|
|
33
|
+
export declare const CMD_APPEND_CHILD = 8;
|
|
34
|
+
export declare const CMD_WRAP = 9;
|
|
35
|
+
export declare const CMD_REPLACE = 11;
|
|
36
|
+
export declare const CMD_SET_PROPERTY = 12;
|
|
37
|
+
export declare const CMD_SET_CHILDREN = 13;
|
|
38
|
+
export declare const PAYLOAD_RAW_MARKDOWN = 16;
|
|
39
|
+
export declare const PAYLOAD_RAW_HTML = 17;
|
|
40
|
+
export declare const PAYLOAD_OPSTREAM = 20;
|
|
41
|
+
export declare const PROP_STRING = 0;
|
|
42
|
+
export declare const PROP_BOOL_TRUE = 1;
|
|
43
|
+
export declare const PROP_BOOL_FALSE = 2;
|
|
44
|
+
export declare const PROP_SPACE_SEP = 3;
|
|
45
|
+
export declare const PROP_COMMA_SEP = 4;
|
|
46
|
+
export declare const PROP_INT = 5;
|
|
47
|
+
export declare const PROP_NULL = 6;
|
|
48
|
+
export declare const MDX_ATTR_BOOLEAN_PROP = 0;
|
|
49
|
+
export declare const MDX_ATTR_LITERAL_PROP = 1;
|
|
50
|
+
export declare const MDX_ATTR_EXPRESSION_PROP = 2;
|
|
51
|
+
export declare const MDX_ATTR_SPREAD = 3;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @generated by `cargo run -p satteri-layout-codegen`. Do not edit by hand.
|
|
2
|
+
// JS<->Rust wire-protocol byte values, declared once in
|
|
3
|
+
// `satteri-layout-codegen/src/schema.rs`. Rust twins live in
|
|
4
|
+
// `satteri-plugin-api/src/generated/wire_constants.rs` and
|
|
5
|
+
// `satteri-ast/src/generated/wire_constants.rs`.
|
|
6
|
+
// Op-stream op codes (JS `OpWriter` -> Rust `replay_opstream`).
|
|
7
|
+
export const OP_OPEN = 0x01; // [type: u8]
|
|
8
|
+
export const OP_CLOSE = 0x02;
|
|
9
|
+
export const OP_REF = 0x03; // [id: u32 LE] — splice an existing node
|
|
10
|
+
export const OP_KEEP_CHILDREN = 0x04; // splice the anchor node's original children
|
|
11
|
+
export const OP_STR = 0x05; // [field: u8][len: u32 LE][utf8]
|
|
12
|
+
export const OP_U8 = 0x06; // [field: u8][value: u8]
|
|
13
|
+
export const OP_U32 = 0x07; // [field: u8][value: u32 LE]
|
|
14
|
+
export const OP_BOOL = 0x08; // [field: u8][0|1]
|
|
15
|
+
export const OP_DATA = 0x09; // [len: u32 LE][json utf8]
|
|
16
|
+
export const OP_PROP = 0x0a; // [name str][kind: u8][value str] — HAST element property
|
|
17
|
+
export const OP_ALIGN = 0x0b; // [len: u32 LE][ColumnAlign bytes] — table column alignment
|
|
18
|
+
// Op-stream field ids (single namespace across OP_STR/OP_U8/OP_U32/OP_BOOL).
|
|
19
|
+
export const OF_VALUE = 0;
|
|
20
|
+
export const OF_URL = 1;
|
|
21
|
+
export const OF_TITLE = 2;
|
|
22
|
+
export const OF_ALT = 3;
|
|
23
|
+
export const OF_LANG = 4;
|
|
24
|
+
export const OF_META = 5;
|
|
25
|
+
export const OF_IDENTIFIER = 6;
|
|
26
|
+
export const OF_LABEL = 7;
|
|
27
|
+
export const OF_NAME = 8; // directive / MDX JSX element name
|
|
28
|
+
export const OF_REFERENCE_TYPE = 9;
|
|
29
|
+
export const OF_DEPTH = 10;
|
|
30
|
+
export const OF_CHECKED = 11;
|
|
31
|
+
export const OF_START = 12;
|
|
32
|
+
export const OF_ORDERED = 13;
|
|
33
|
+
export const OF_SPREAD = 14;
|
|
34
|
+
export const OF_TAGNAME = 15; // HAST element tag name
|
|
35
|
+
export const OF_EXPLICIT = 16; // MDX JSX `_mdxExplicitJsx` flag
|
|
36
|
+
// Command bytes (0x01–0x0F range). Each is followed by [nodeId: u32 LE];
|
|
37
|
+
// structural commands then carry [payloadType: u8][payload…].
|
|
38
|
+
export const CMD_REMOVE = 0x01;
|
|
39
|
+
export const CMD_INSERT_BEFORE = 0x05;
|
|
40
|
+
export const CMD_INSERT_AFTER = 0x06;
|
|
41
|
+
export const CMD_PREPEND_CHILD = 0x07;
|
|
42
|
+
export const CMD_APPEND_CHILD = 0x08;
|
|
43
|
+
export const CMD_WRAP = 0x09;
|
|
44
|
+
export const CMD_REPLACE = 0x0b;
|
|
45
|
+
export const CMD_SET_PROPERTY = 0x0c; // [valueType: u8][name str][value str], PROP_* value kinds
|
|
46
|
+
export const CMD_SET_CHILDREN = 0x0d; // payload is a Root-wrapped child list
|
|
47
|
+
// Structural-command payload types (0x10+, a range distinct from commands).
|
|
48
|
+
export const PAYLOAD_RAW_MARKDOWN = 0x10; // [len: u32 LE][utf8] — re-parsed as markdown
|
|
49
|
+
export const PAYLOAD_RAW_HTML = 0x11; // [len: u32 LE][utf8] — re-parsed as HTML/MDX
|
|
50
|
+
export const PAYLOAD_OPSTREAM = 0x14; // [len: u32 LE][op bytes] — replayed straight into the arena
|
|
51
|
+
// Property value kinds (HAST element properties and SET_PROPERTY commands).
|
|
52
|
+
export const PROP_STRING = 0; // UTF-8 value
|
|
53
|
+
export const PROP_BOOL_TRUE = 1; // no value bytes
|
|
54
|
+
export const PROP_BOOL_FALSE = 2; // no value bytes
|
|
55
|
+
export const PROP_SPACE_SEP = 3; // space-separated list (UTF-8)
|
|
56
|
+
export const PROP_COMMA_SEP = 4; // comma-separated list (UTF-8)
|
|
57
|
+
export const PROP_INT = 5; // decimal string, parsed to i64
|
|
58
|
+
export const PROP_NULL = 6; // no value bytes
|
|
59
|
+
// MDX JSX attribute kinds (MDAST and HAST MDX JSX element type_data).
|
|
60
|
+
export const MDX_ATTR_BOOLEAN_PROP = 0; // name only, no value
|
|
61
|
+
export const MDX_ATTR_LITERAL_PROP = 1; // name="literal"
|
|
62
|
+
export const MDX_ATTR_EXPRESSION_PROP = 2; // name={expr}
|
|
63
|
+
export const MDX_ATTR_SPREAD = 3; // {...expr}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque handles to Rust-owned arenas. The napi-generated `index.d.ts` refers
|
|
3
|
+
* to `MdastHandle`/`HastHandle`/`AnyHandle` as bare, undeclared names; these
|
|
4
|
+
* global declarations give those signatures real types. The kind brand makes
|
|
5
|
+
* passing a hast handle to an mdast entry point (a runtime error in Rust) a
|
|
6
|
+
* compile error in TS.
|
|
7
|
+
*/
|
|
8
|
+
declare global {
|
|
9
|
+
interface MdastHandle {
|
|
10
|
+
readonly __satteriHandleKind: "mdast";
|
|
11
|
+
}
|
|
12
|
+
interface HastHandle {
|
|
13
|
+
readonly __satteriHandleKind: "hast";
|
|
14
|
+
}
|
|
15
|
+
/** Handle accepted by kind-agnostic entry points (drop, serialize, …). */
|
|
16
|
+
type AnyHandle = MdastHandle | HastHandle;
|
|
17
|
+
}
|
|
18
|
+
type MdastHandleAlias = MdastHandle;
|
|
19
|
+
type HastHandleAlias = HastHandle;
|
|
20
|
+
type AnyHandleAlias = AnyHandle;
|
|
21
|
+
export type { MdastHandleAlias as MdastHandle, HastHandleAlias as HastHandle, AnyHandleAlias as AnyHandle, };
|
package/dist/handles.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LazyChildResolver } from "../lazy-child-resolver.js";
|
|
2
|
+
import type { HastNode } from "../types.js";
|
|
3
|
+
import type { HastReader } from "./hast-reader.js";
|
|
4
|
+
type HastResolver = LazyChildResolver<HastReader, HastNode>;
|
|
5
|
+
/**
|
|
6
|
+
* Walk-path child stub: arena id + `type` eagerly, every other field a lazy
|
|
7
|
+
* forward to the materialized node (first read snapshots the arena via
|
|
8
|
+
* `materializeOne`, which enforces the handle epoch — the pass seal is checked
|
|
9
|
+
* where the stubs are built). Spread/identity rules are enforced by `nid()`
|
|
10
|
+
* in hast-visitor.ts.
|
|
11
|
+
*/
|
|
12
|
+
export declare class HastChildStub {
|
|
13
|
+
_resolver: HastResolver;
|
|
14
|
+
_id: number;
|
|
15
|
+
type: string;
|
|
16
|
+
constructor(resolver: HastResolver, id: number, nodeType: number);
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { flatByTag, stubDescriptors } from "../child-stub.js";
|
|
2
|
+
import { NAME_TO_TYPE, TYPE_NAMES } from "./generated/node-types.js";
|
|
3
|
+
const N = NAME_TO_TYPE;
|
|
4
|
+
/** Per-type stub fields, mirroring `materializeHastNode`'s switch. */
|
|
5
|
+
const HAST_STUB_FIELDS = {
|
|
6
|
+
[N.root]: ["children"],
|
|
7
|
+
[N.element]: ["tagName", "properties", "children"],
|
|
8
|
+
[N.text]: ["value"],
|
|
9
|
+
[N.comment]: ["value"],
|
|
10
|
+
[N.doctype]: [],
|
|
11
|
+
[N.raw]: ["value"],
|
|
12
|
+
[N.mdxJsxFlowElement]: ["name", "attributes", "children"],
|
|
13
|
+
[N.mdxJsxTextElement]: ["name", "attributes", "children"],
|
|
14
|
+
[N.mdxFlowExpression]: ["value"],
|
|
15
|
+
[N.mdxTextExpression]: ["value"],
|
|
16
|
+
[N.mdxjsEsm]: ["value"],
|
|
17
|
+
};
|
|
18
|
+
const TYPE_NAME_BY_TAG = flatByTag(TYPE_NAMES);
|
|
19
|
+
const HAST_STUB_DESCRIPTORS = [];
|
|
20
|
+
for (const tag of Object.keys(HAST_STUB_FIELDS)) {
|
|
21
|
+
const nodeType = Number(tag);
|
|
22
|
+
HAST_STUB_DESCRIPTORS[nodeType] = stubDescriptors(HAST_STUB_FIELDS[nodeType]);
|
|
23
|
+
}
|
|
24
|
+
/** Unknown node types still expose the prelude-backed lazy fields. */
|
|
25
|
+
const FALLBACK_DESCRIPTORS = stubDescriptors([]);
|
|
26
|
+
/**
|
|
27
|
+
* Walk-path child stub: arena id + `type` eagerly, every other field a lazy
|
|
28
|
+
* forward to the materialized node (first read snapshots the arena via
|
|
29
|
+
* `materializeOne`, which enforces the handle epoch — the pass seal is checked
|
|
30
|
+
* where the stubs are built). Spread/identity rules are enforced by `nid()`
|
|
31
|
+
* in hast-visitor.ts.
|
|
32
|
+
*/
|
|
33
|
+
export class HastChildStub {
|
|
34
|
+
_resolver;
|
|
35
|
+
_id;
|
|
36
|
+
type;
|
|
37
|
+
constructor(resolver, id, nodeType) {
|
|
38
|
+
this._resolver = resolver;
|
|
39
|
+
this._id = id;
|
|
40
|
+
this.type = TYPE_NAME_BY_TAG[nodeType] ?? `unknown(${nodeType})`;
|
|
41
|
+
Object.defineProperties(this, HAST_STUB_DESCRIPTORS[nodeType] ?? FALLBACK_DESCRIPTORS);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Decode a HAST element property value from its wire `(kind, value)` — shared
|
|
2
|
+
* by the walk decoder and the snapshot reader so the kind dispatch lives once.
|
|
3
|
+
* The bool kinds carry no value string (callers pass `""`). */
|
|
4
|
+
import { PROP_BOOL_TRUE, PROP_BOOL_FALSE, PROP_SPACE_SEP, PROP_COMMA_SEP, PROP_INT, } from "../generated/wire-constants.js";
|
|
5
|
+
export function decodeElementProp(kind, value) {
|
|
6
|
+
switch (kind) {
|
|
7
|
+
case PROP_BOOL_TRUE:
|
|
8
|
+
return true;
|
|
9
|
+
case PROP_BOOL_FALSE:
|
|
10
|
+
return false;
|
|
11
|
+
case PROP_SPACE_SEP:
|
|
12
|
+
return value.split(" ").filter((s) => s.length > 0);
|
|
13
|
+
case PROP_COMMA_SEP:
|
|
14
|
+
return value
|
|
15
|
+
.split(",")
|
|
16
|
+
.map((s) => s.trim())
|
|
17
|
+
.filter((s) => s.length > 0);
|
|
18
|
+
case PROP_INT:
|
|
19
|
+
return Number(value);
|
|
20
|
+
default:
|
|
21
|
+
return value; // PROP_STRING
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Node-type tag -> canonical AST name. */
|
|
2
|
+
export declare const TYPE_NAMES: Readonly<Record<number, string>>;
|
|
3
|
+
/** Canonical AST name -> node-type tag. */
|
|
4
|
+
export declare const NAME_TO_TYPE: Readonly<Record<string, number>>;
|
|
5
|
+
/** Names a plugin can subscribe to (every node except `root`). */
|
|
6
|
+
export declare const VISITOR_KEYS: ReadonlySet<string>;
|
|
7
|
+
/** Name -> tag for the types the op-stream can encode; one lookup gates AND
|
|
8
|
+
* resolves the emit-path tag. Excluded names (see `*_OPSTREAM_EXCLUDED` in
|
|
9
|
+
* schema.rs) have no encoding — the visitor throws for them. */
|
|
10
|
+
export declare const HAST_OPSTREAM_TYPES: Readonly<Record<string, number>>;
|
|
11
|
+
/** Names of the variable-length `custom` node types (hand-written or
|
|
12
|
+
* `Tail`-generated codec). The op-stream round-trip oracle asserts it covers
|
|
13
|
+
* every one, so a forgotten or drifted encode/decode arm fails loudly. */
|
|
14
|
+
export declare const HAST_CUSTOM_TYPES: readonly string[];
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// @generated by `cargo run -p satteri-layout-codegen`. Do not edit by hand.
|
|
2
|
+
/** Node-type tag -> canonical AST name. */
|
|
3
|
+
export const TYPE_NAMES = {
|
|
4
|
+
0: "root",
|
|
5
|
+
1: "element",
|
|
6
|
+
2: "text",
|
|
7
|
+
3: "comment",
|
|
8
|
+
4: "doctype",
|
|
9
|
+
5: "raw",
|
|
10
|
+
10: "mdxJsxFlowElement",
|
|
11
|
+
11: "mdxJsxTextElement",
|
|
12
|
+
12: "mdxFlowExpression",
|
|
13
|
+
13: "mdxjsEsm",
|
|
14
|
+
14: "mdxTextExpression",
|
|
15
|
+
};
|
|
16
|
+
/** Canonical AST name -> node-type tag. */
|
|
17
|
+
export const NAME_TO_TYPE = {
|
|
18
|
+
root: 0,
|
|
19
|
+
element: 1,
|
|
20
|
+
text: 2,
|
|
21
|
+
comment: 3,
|
|
22
|
+
doctype: 4,
|
|
23
|
+
raw: 5,
|
|
24
|
+
mdxJsxFlowElement: 10,
|
|
25
|
+
mdxJsxTextElement: 11,
|
|
26
|
+
mdxFlowExpression: 12,
|
|
27
|
+
mdxjsEsm: 13,
|
|
28
|
+
mdxTextExpression: 14,
|
|
29
|
+
};
|
|
30
|
+
/** Names a plugin can subscribe to (every node except `root`). */
|
|
31
|
+
export const VISITOR_KEYS = new Set([
|
|
32
|
+
"element",
|
|
33
|
+
"text",
|
|
34
|
+
"comment",
|
|
35
|
+
"doctype",
|
|
36
|
+
"raw",
|
|
37
|
+
"mdxJsxFlowElement",
|
|
38
|
+
"mdxJsxTextElement",
|
|
39
|
+
"mdxFlowExpression",
|
|
40
|
+
"mdxjsEsm",
|
|
41
|
+
"mdxTextExpression",
|
|
42
|
+
]);
|
|
43
|
+
/** Name -> tag for the types the op-stream can encode; one lookup gates AND
|
|
44
|
+
* resolves the emit-path tag. Excluded names (see `*_OPSTREAM_EXCLUDED` in
|
|
45
|
+
* schema.rs) have no encoding — the visitor throws for them. */
|
|
46
|
+
export const HAST_OPSTREAM_TYPES = {
|
|
47
|
+
element: 1,
|
|
48
|
+
text: 2,
|
|
49
|
+
comment: 3,
|
|
50
|
+
raw: 5,
|
|
51
|
+
mdxJsxFlowElement: 10,
|
|
52
|
+
mdxJsxTextElement: 11,
|
|
53
|
+
mdxFlowExpression: 12,
|
|
54
|
+
mdxjsEsm: 13,
|
|
55
|
+
mdxTextExpression: 14,
|
|
56
|
+
};
|
|
57
|
+
/** Names of the variable-length `custom` node types (hand-written or
|
|
58
|
+
* `Tail`-generated codec). The op-stream round-trip oracle asserts it covers
|
|
59
|
+
* every one, so a forgotten or drifted encode/decode arm fails loudly. */
|
|
60
|
+
export const HAST_CUSTOM_TYPES = [
|
|
61
|
+
"element",
|
|
62
|
+
"mdxJsxFlowElement",
|
|
63
|
+
"mdxJsxTextElement",
|
|
64
|
+
];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HastReader } from "./hast-reader.js";
|
|
2
|
+
import type { Root } from "hast";
|
|
2
3
|
import type { HastNode } from "../types.js";
|
|
3
4
|
export type { HastNode };
|
|
4
5
|
/**
|
|
@@ -8,4 +9,4 @@ export declare function materializeHastNode(reader: HastReader, nodeId: number):
|
|
|
8
9
|
/**
|
|
9
10
|
* Materialize the full HAST tree from root (nodeId=0).
|
|
10
11
|
*/
|
|
11
|
-
export declare function materializeHastTree(reader: HastReader):
|
|
12
|
+
export declare function materializeHastTree(reader: HastReader): Root;
|