satteri 0.8.1 → 0.9.1

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.
Files changed (60) hide show
  1. package/README.md +54 -0
  2. package/dist/byte-writer.d.ts +31 -0
  3. package/dist/byte-writer.js +106 -0
  4. package/dist/child-stub.d.ts +17 -0
  5. package/dist/child-stub.js +57 -0
  6. package/dist/command-buffer.d.ts +23 -26
  7. package/dist/command-buffer.js +64 -132
  8. package/dist/compile.d.ts +13 -1
  9. package/dist/compile.js +44 -28
  10. package/dist/directive-types.d.ts +4 -2
  11. package/dist/generated/arena-layout.d.ts +37 -0
  12. package/dist/generated/arena-layout.js +41 -0
  13. package/dist/generated/wire-constants.d.ts +51 -0
  14. package/dist/generated/wire-constants.js +63 -0
  15. package/dist/handles.d.ts +21 -0
  16. package/dist/handles.js +1 -0
  17. package/dist/hast/child-stub.d.ts +18 -0
  18. package/dist/hast/child-stub.js +43 -0
  19. package/dist/hast/element-props.d.ts +2 -0
  20. package/dist/hast/element-props.js +23 -0
  21. package/dist/hast/generated/node-types.d.ts +14 -0
  22. package/dist/hast/generated/node-types.js +64 -0
  23. package/dist/hast/hast-materializer.d.ts +2 -1
  24. package/dist/hast/hast-materializer.js +9 -45
  25. package/dist/hast/hast-reader.d.ts +18 -23
  26. package/dist/hast/hast-reader.js +48 -115
  27. package/dist/hast/hast-visitor.d.ts +35 -13
  28. package/dist/hast/hast-visitor.js +395 -302
  29. package/dist/index.d.ts +10 -4
  30. package/dist/index.js +23 -1
  31. package/dist/lazy-child-resolver.d.ts +36 -0
  32. package/dist/lazy-child-resolver.js +95 -0
  33. package/dist/lazy-props.d.ts +1 -1
  34. package/dist/mdast/child-stub.d.ts +18 -0
  35. package/dist/mdast/child-stub.js +46 -0
  36. package/dist/mdast/column-align.d.ts +1 -0
  37. package/dist/mdast/column-align.js +6 -0
  38. package/dist/mdast/generated/layout.d.ts +19 -0
  39. package/dist/mdast/generated/layout.js +272 -0
  40. package/dist/mdast/generated/node-types.d.ts +58 -0
  41. package/dist/mdast/generated/node-types.js +266 -0
  42. package/dist/mdast/mdast-materializer.d.ts +3 -2
  43. package/dist/mdast/mdast-materializer.js +9 -93
  44. package/dist/mdast/mdast-reader.d.ts +4 -120
  45. package/dist/mdast/mdast-reader.js +45 -272
  46. package/dist/mdast/mdast-visitor.d.ts +52 -14
  47. package/dist/mdast/mdast-visitor.js +348 -427
  48. package/dist/mdx-attr.d.ts +2 -0
  49. package/dist/mdx-attr.js +20 -0
  50. package/dist/op-stream.d.ts +38 -0
  51. package/dist/op-stream.js +125 -0
  52. package/dist/phantom.d.ts +2 -0
  53. package/dist/phantom.js +13 -0
  54. package/dist/types.d.ts +34 -4
  55. package/dist/visitor-shared.d.ts +28 -0
  56. package/dist/visitor-shared.js +52 -0
  57. package/dist/wire-read.d.ts +27 -0
  58. package/dist/wire-read.js +59 -0
  59. package/index.js +52 -52
  60. package/package.json +6 -6
package/dist/compile.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { MdastPluginInput, HastPluginInput } from "./plugin.js";
2
- import type { MdastNode, HastNode } from "./types.js";
2
+ import type { MdastNode, HastNode, Data } from "./types.js";
3
3
  /** Configuration for static subtree collapsing during MDX compilation. */
4
4
  export interface OptimizeStaticConfig {
5
5
  component: string;
@@ -130,6 +130,14 @@ export interface CompileOptions {
130
130
  * `pathToFileURL` before passing it.
131
131
  */
132
132
  fileURL?: URL;
133
+ /**
134
+ * Initial document-level data bag, seeding `ctx.data` before any plugin runs.
135
+ * It is the same object plugins mutate and the caller reads back as
136
+ * `result.data`, so values flow both into and out of a compile. Defaults to a
137
+ * fresh empty object. Used by reference and mutated in place, so pass a
138
+ * throwaway object per compile rather than a shared one.
139
+ */
140
+ data?: Data;
133
141
  }
134
142
  /**
135
143
  * MDX-only compile options.
@@ -200,6 +208,8 @@ export interface MarkdownToHtmlResult {
200
208
  html: string;
201
209
  /** Frontmatter block at the start of the document, or `null` if none. */
202
210
  frontmatter: Frontmatter | null;
211
+ /** Document-level data bag shared with plugins via `ctx.data`; the seeded `data` option if provided, else a fresh `{}`. */
212
+ data: Data;
203
213
  }
204
214
  /** Result of {@link mdxToJs}. */
205
215
  export interface MdxToJsResult {
@@ -207,6 +217,8 @@ export interface MdxToJsResult {
207
217
  code: string;
208
218
  /** Frontmatter block at the start of the document, or `null` if none. */
209
219
  frontmatter: Frontmatter | null;
220
+ /** Document-level data bag shared with plugins via `ctx.data`; the seeded `data` option if provided, else a fresh `{}`. */
221
+ data: Data;
210
222
  }
211
223
  type AnyFn = (...args: any[]) => unknown;
212
224
  type ReturnsPromise<F> = F extends AnyFn ? Extract<ReturnType<F>, Promise<unknown>> extends never ? false : true : false;
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,21 @@ function featuresToNative(features) {
74
75
  }
75
76
  return { features: result, convertOptions };
76
77
  }
78
+ /** Free a handle's arena. A plugin's visitor can hand child stubs to user code;
79
+ * pass `invalidateStubs` so the epoch bump makes any stub retained past this
80
+ * point hit the designed retention error instead of snapshotting the freed arena. */
81
+ function releaseHandle(handle, invalidateStubs) {
82
+ if (invalidateStubs)
83
+ markHandleMutated(handle);
84
+ dropHandle(handle);
85
+ }
77
86
  function warnDroppedTransforms(plugin, dropped, kind) {
78
87
  const name = plugin.name ?? "<anonymous>";
79
88
  const noun = dropped === 1 ? "transform" : "transforms";
80
89
  console.warn(`satteri: plugin "${name}" queued ${dropped} ${kind} ${noun} on node(s) that were removed or ` +
81
90
  `replaced earlier in the same pass; ${dropped === 1 ? "it was" : "they were"} dropped.`);
82
91
  }
83
- function runMdastPluginsOnHandle(handle, plugins, fileURL) {
92
+ function runMdastPluginsOnHandle(handle, plugins, fileURL, data) {
84
93
  // Each plugin runs once over the tree. A transform that passes a child
85
94
  // through (returning it inside the replacement) keeps that child's identity,
86
95
  // so a patch the same pass queued on it still applies — nesting composes in
@@ -88,10 +97,11 @@ function runMdastPluginsOnHandle(handle, plugins, fileURL) {
88
97
  // them up front, or hand off to a later plugin that sees the materialized tree.
89
98
  const runPlugin = (plugin) => {
90
99
  const subs = resolveMdastSubscriptions(plugin);
91
- const result = visitMdastHandle(handle, plugin, subs, () => getHandleSource(handle), fileURL);
100
+ const result = visitMdastHandle(handle, plugin, subs, () => getHandleSource(handle), fileURL, data);
92
101
  const apply = (r) => {
93
102
  if (!r.hasMutations)
94
103
  return;
104
+ markHandleMutated(handle);
95
105
  const dropped = applyCommandsToMdastHandle(handle, r.commandBuffer);
96
106
  if (dropped)
97
107
  warnDroppedTransforms(plugin, dropped, "mdast");
@@ -111,7 +121,7 @@ function runMdastPluginsOnHandle(handle, plugins, fileURL) {
111
121
  };
112
122
  return runNext();
113
123
  }
114
- function runHastPluginsOnHandle(handle, plugins, source, fileURL) {
124
+ function runHastPluginsOnHandle(handle, plugins, source, fileURL, data) {
115
125
  if (plugins.length === 0)
116
126
  return;
117
127
  let i = 0;
@@ -121,7 +131,7 @@ function runHastPluginsOnHandle(handle, plugins, source, fileURL) {
121
131
  i++;
122
132
  const plugin = typeof raw === "function" ? raw() : raw;
123
133
  const subs = resolveSubscriptions(plugin);
124
- const result = visitHastHandle(handle, plugin, subs, source, fileURL);
134
+ const result = visitHastHandle(handle, plugin, subs, source, fileURL, data);
125
135
  const warnIfDropped = (dropped) => {
126
136
  if (dropped)
127
137
  warnDroppedTransforms(plugin, dropped, "hast");
@@ -181,30 +191,31 @@ function mdxOptionsToNative(opts) {
181
191
  return result;
182
192
  }
183
193
  export function markdownToHtml(source, options = {}) {
184
- const { mdastPlugins = [], hastPlugins = [], features, fileURL } = options;
194
+ const { mdastPlugins = [], hastPlugins = [], features, fileURL, data = {} } = options;
195
+ const hastMayHaveStubs = hastPlugins.length > 0;
185
196
  const { features: nativeFeatures, convertOptions: nativeConvertOptions } = featuresToNative(features);
186
- const result = createHastHandleFromMdast(source, mdastPlugins, false, fileURL, nativeFeatures, nativeConvertOptions);
197
+ const result = createHastHandleFromMdast(source, mdastPlugins, false, fileURL, nativeFeatures, nativeConvertOptions, data);
187
198
  const renderAndDrop = (h, frontmatter) => {
188
199
  try {
189
200
  const html = renderHandle(h);
190
- return { html, frontmatter };
201
+ return { html, frontmatter, data };
191
202
  }
192
203
  finally {
193
- dropHandle(h);
204
+ releaseHandle(h, hastMayHaveStubs);
194
205
  }
195
206
  };
196
207
  const runHastThenRender = (r) => {
197
208
  let hastResult;
198
209
  try {
199
- hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL);
210
+ hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL, data);
200
211
  }
201
212
  catch (err) {
202
- dropHandle(r.hastHandle);
213
+ releaseHandle(r.hastHandle, hastMayHaveStubs);
203
214
  throw err;
204
215
  }
205
216
  if (hastResult instanceof Promise) {
206
217
  return hastResult.then(() => renderAndDrop(r.hastHandle, r.frontmatter), (err) => {
207
- dropHandle(r.hastHandle);
218
+ releaseHandle(r.hastHandle, hastMayHaveStubs);
208
219
  throw err;
209
220
  });
210
221
  }
@@ -215,31 +226,32 @@ export function markdownToHtml(source, options = {}) {
215
226
  return runHastThenRender(result);
216
227
  }
217
228
  export function mdxToJs(source, options = {}) {
218
- const { mdastPlugins = [], hastPlugins = [], features, fileURL, ...mdxFields } = options;
229
+ const { mdastPlugins = [], hastPlugins = [], features, fileURL, data = {}, ...mdxFields } = options;
230
+ const hastMayHaveStubs = hastPlugins.length > 0;
219
231
  const mdxOptions = mdxOptionsToNative(mdxFields);
220
232
  const { features: nativeFeatures, convertOptions: nativeConvertOptions } = featuresToNative(features);
221
- const result = createHastHandleFromMdast(source, mdastPlugins, true, fileURL, nativeFeatures, nativeConvertOptions);
233
+ const result = createHastHandleFromMdast(source, mdastPlugins, true, fileURL, nativeFeatures, nativeConvertOptions, data);
222
234
  const compileAndDrop = (h, frontmatter) => {
223
235
  try {
224
236
  const code = compileHandle(h, mdxOptions);
225
- return { code, frontmatter };
237
+ return { code, frontmatter, data };
226
238
  }
227
239
  finally {
228
- dropHandle(h);
240
+ releaseHandle(h, hastMayHaveStubs);
229
241
  }
230
242
  };
231
243
  const runHastThenCompile = (r) => {
232
244
  let hastResult;
233
245
  try {
234
- hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL);
246
+ hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL, data);
235
247
  }
236
248
  catch (err) {
237
- dropHandle(r.hastHandle);
249
+ releaseHandle(r.hastHandle, hastMayHaveStubs);
238
250
  throw err;
239
251
  }
240
252
  if (hastResult instanceof Promise) {
241
253
  return hastResult.then(() => compileAndDrop(r.hastHandle, r.frontmatter), (err) => {
242
- dropHandle(r.hastHandle);
254
+ releaseHandle(r.hastHandle, hastMayHaveStubs);
243
255
  throw err;
244
256
  });
245
257
  }
@@ -280,37 +292,41 @@ function createHastHandleFromMdast(source, mdastPlugins, mdx, fileURL,
280
292
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
281
293
  nativeFeatures,
282
294
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
283
- nativeConvertOptions) {
295
+ nativeConvertOptions, data) {
284
296
  const mdastHandle = mdx
285
297
  ? createMdxMdastHandle(source, nativeFeatures)
286
298
  : createMdastHandle(source, nativeFeatures);
287
- // finally{drop} is intentional: convertMdastToHastHandle empties the arena
299
+ const mdastMayHaveStubs = mdastPlugins.length > 0;
300
+ // finally{release} is intentional: convertMdastToHastHandle empties the arena
288
301
  // on success, but if any step here throws the handle would otherwise leak.
289
302
  const finalize = (r) => {
290
303
  try {
291
304
  const frontmatter = readFrontmatter(r.handle);
305
+ // convert empties the mdast arena, so invalidate any stub held past this point.
306
+ if (mdastMayHaveStubs)
307
+ markHandleMutated(r.handle);
292
308
  const hastHandle = convertMdastToHastHandle(r.handle, nativeConvertOptions);
293
309
  return { hastHandle, frontmatter };
294
310
  }
295
311
  finally {
296
- dropHandle(r.handle);
312
+ releaseHandle(r.handle, mdastMayHaveStubs);
297
313
  }
298
314
  };
299
315
  try {
300
316
  if (mdastPlugins.length === 0) {
301
317
  return finalize({ handle: mdastHandle });
302
318
  }
303
- const mdastResult = runMdastPluginsOnHandle(mdastHandle, mdastPlugins, fileURL);
319
+ const mdastResult = runMdastPluginsOnHandle(mdastHandle, mdastPlugins, fileURL, data);
304
320
  if (mdastResult instanceof Promise) {
305
321
  return mdastResult.then(finalize, (err) => {
306
- dropHandle(mdastHandle);
322
+ releaseHandle(mdastHandle, mdastMayHaveStubs);
307
323
  throw err;
308
324
  });
309
325
  }
310
326
  return finalize(mdastResult);
311
327
  }
312
328
  catch (err) {
313
- dropHandle(mdastHandle);
329
+ releaseHandle(mdastHandle, mdastMayHaveStubs);
314
330
  throw err;
315
331
  }
316
332
  }
@@ -322,7 +338,7 @@ export function markdownToMdast(source, options = {}) {
322
338
  return materializeMdastTree(new MdastReader(serializeHandle(handle)));
323
339
  }
324
340
  finally {
325
- dropHandle(handle);
341
+ releaseHandle(handle, true);
326
342
  }
327
343
  }
328
344
  /** Parse MDX source into a materialized mdast tree. */
@@ -332,7 +348,7 @@ export function mdxToMdast(source, options = {}) {
332
348
  return materializeMdastTree(new MdastReader(serializeHandle(handle)));
333
349
  }
334
350
  finally {
335
- dropHandle(handle);
351
+ releaseHandle(handle, true);
336
352
  }
337
353
  }
338
354
  /** Convert Markdown source to a materialized hast tree. */
@@ -343,7 +359,7 @@ export function markdownToHast(source, options = {}) {
343
359
  return materializeHastTree(new HastReader(serializeHandle(handle)));
344
360
  }
345
361
  finally {
346
- dropHandle(handle);
362
+ releaseHandle(handle, true);
347
363
  }
348
364
  }
349
365
  /** Convert MDX source to a materialized hast tree. */
@@ -354,6 +370,6 @@ export function mdxToHast(source, options = {}) {
354
370
  return materializeHastTree(new HastReader(serializeHandle(handle)));
355
371
  }
356
372
  finally {
357
- dropHandle(handle);
373
+ releaseHandle(handle, true);
358
374
  }
359
375
  }
@@ -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, };
@@ -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,2 @@
1
+ export type HastPropertyValue = string | number | boolean | string[];
2
+ export declare function decodeElementProp(kind: number, value: string): HastPropertyValue;
@@ -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[];