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.
Files changed (90) hide show
  1. package/README.md +11 -0
  2. package/dist/arena-reader.d.ts +13 -0
  3. package/dist/arena-reader.js +104 -0
  4. package/dist/binding.browser.d.ts +1 -1
  5. package/dist/binding.browser.js +1 -1
  6. package/dist/binding.d.ts +1 -1
  7. package/dist/binding.js +1 -1
  8. package/dist/byte-writer.d.ts +0 -18
  9. package/dist/byte-writer.js +6 -30
  10. package/dist/child-stub.d.ts +0 -17
  11. package/dist/child-stub.js +6 -22
  12. package/dist/command-buffer.d.ts +5 -26
  13. package/dist/command-buffer.js +28 -39
  14. package/dist/compile-options.d.ts +11 -0
  15. package/dist/compile-options.js +101 -0
  16. package/dist/compile-types.d.ts +342 -0
  17. package/dist/compile-types.js +1 -0
  18. package/dist/compile.d.ts +22 -328
  19. package/dist/compile.js +133 -383
  20. package/dist/directive-types.d.ts +1 -0
  21. package/dist/directive-types.js +1 -6
  22. package/dist/generated/arena-layout.d.ts +6 -4
  23. package/dist/generated/arena-layout.js +6 -7
  24. package/dist/generated/fused-wire.d.ts +3 -0
  25. package/dist/generated/fused-wire.js +229 -0
  26. package/dist/generated/parse-options.d.ts +1 -0
  27. package/dist/generated/parse-options.js +1 -5
  28. package/dist/generated/wire-constants.d.ts +4 -0
  29. package/dist/generated/wire-constants.js +34 -42
  30. package/dist/handles.d.ts +0 -7
  31. package/dist/hast/child-stub.d.ts +1 -8
  32. package/dist/hast/child-stub.js +14 -13
  33. package/dist/hast/element-props.d.ts +13 -0
  34. package/dist/hast/element-props.js +52 -6
  35. package/dist/hast/generated/node-types.d.ts +1 -9
  36. package/dist/hast/generated/node-types.js +1 -9
  37. package/dist/hast/generated/walk-decode.d.ts +10 -0
  38. package/dist/hast/generated/walk-decode.js +61 -0
  39. package/dist/hast/hast-materializer.d.ts +3 -10
  40. package/dist/hast/hast-materializer.js +73 -47
  41. package/dist/hast/hast-reader.d.ts +9 -38
  42. package/dist/hast/hast-reader.js +82 -271
  43. package/dist/hast/hast-visitor.d.ts +29 -16
  44. package/dist/hast/hast-visitor.js +200 -508
  45. package/dist/hast/hast-walk.d.ts +18 -0
  46. package/dist/hast/hast-walk.js +264 -0
  47. package/dist/index.d.ts +5 -5
  48. package/dist/index.js +4 -12
  49. package/dist/lazy-child-resolver.d.ts +1 -21
  50. package/dist/lazy-child-resolver.js +11 -32
  51. package/dist/materializer-cache.d.ts +5 -29
  52. package/dist/materializer-cache.js +29 -101
  53. package/dist/mdast/child-stub.d.ts +1 -12
  54. package/dist/mdast/child-stub.js +18 -28
  55. package/dist/mdast/column-align.d.ts +1 -1
  56. package/dist/mdast/column-align.js +0 -2
  57. package/dist/mdast/generated/layout.d.ts +0 -16
  58. package/dist/mdast/generated/layout.js +6 -47
  59. package/dist/mdast/generated/node-types.d.ts +1 -9
  60. package/dist/mdast/generated/node-types.js +3 -9
  61. package/dist/mdast/mdast-materializer.d.ts +3 -11
  62. package/dist/mdast/mdast-materializer.js +91 -63
  63. package/dist/mdast/mdast-reader.d.ts +15 -63
  64. package/dist/mdast/mdast-reader.js +132 -269
  65. package/dist/mdast/mdast-visitor.d.ts +23 -15
  66. package/dist/mdast/mdast-visitor.js +189 -294
  67. package/dist/mdast/mdast-walk.d.ts +13 -0
  68. package/dist/mdast/mdast-walk.js +144 -0
  69. package/dist/mdx-attr.js +0 -3
  70. package/dist/mdx-types.js +1 -6
  71. package/dist/op-stream.d.ts +4 -15
  72. package/dist/op-stream.js +31 -20
  73. package/dist/phantom.d.ts +0 -1
  74. package/dist/phantom.js +1 -9
  75. package/dist/plugin-pipeline.d.ts +32 -0
  76. package/dist/plugin-pipeline.js +177 -0
  77. package/dist/plugin.d.ts +14 -8
  78. package/dist/plugin.js +5 -10
  79. package/dist/types.d.ts +0 -1
  80. package/dist/visitor-node.d.ts +12 -0
  81. package/dist/visitor-node.js +23 -0
  82. package/dist/visitor-shared.d.ts +26 -30
  83. package/dist/visitor-shared.js +34 -36
  84. package/dist/wire-read.d.ts +0 -22
  85. package/dist/wire-read.js +3 -24
  86. package/index.d.ts +19 -10
  87. package/index.js +56 -53
  88. package/package.json +6 -12
  89. package/dist/string-pool.d.ts +0 -13
  90. package/dist/string-pool.js +0 -91
@@ -0,0 +1,61 @@
1
+ // @generated by `cargo run -p satteri-layout-codegen`. Do not edit by hand.
2
+ import { rstr } from "../../wire-read.js";
3
+ import { restorePhantomSpaces } from "../../phantom.js";
4
+ import { decodeElementProp } from "../element-props.js";
5
+ import { decodeMdxJsxAttr } from "../../mdx-attr.js";
6
+ export function readWalkElementTag(view, buf, pos) {
7
+ return rstr(buf, pos + 2, view.getUint16(pos, true));
8
+ }
9
+ export function walkElementPropsAt(view, pos) {
10
+ return pos + 2 + view.getUint16(pos, true);
11
+ }
12
+ export function walkElementPropCount(view, propsAt) {
13
+ return view.getUint16(propsAt, true);
14
+ }
15
+ export function decodeWalkElementProps(view, buf, pos) {
16
+ const count = view.getUint16(pos, true);
17
+ pos += 2;
18
+ const properties = {};
19
+ for (let i = 0; i < count; i++) {
20
+ const nameLen = view.getUint16(pos, true);
21
+ pos += 2;
22
+ const name = rstr(buf, pos, nameLen);
23
+ pos += nameLen;
24
+ const kind = buf[pos] ?? 0;
25
+ pos += 1;
26
+ const valueLen = view.getUint16(pos, true);
27
+ pos += 2;
28
+ const value = rstr(buf, pos, valueLen);
29
+ pos += valueLen;
30
+ properties[name] = decodeElementProp(kind, value);
31
+ }
32
+ return properties;
33
+ }
34
+ export function readWalkHastValue(view, buf, offset, nodeType) {
35
+ const value = rstr(buf, offset + 4, view.getUint32(offset, true));
36
+ return nodeType === 12 || nodeType === 14 ? restorePhantomSpaces(value) : value;
37
+ }
38
+ // A zero-length name represents an MDX fragment.
39
+ export function readWalkMdxJsx(view, buf, pos) {
40
+ const headLen = view.getUint16(pos, true);
41
+ pos += 2;
42
+ const headName = headLen > 0 ? rstr(buf, pos, headLen) : null;
43
+ pos += headLen;
44
+ const count = view.getUint16(pos, true);
45
+ pos += 2;
46
+ const attributes = [];
47
+ for (let i = 0; i < count; i++) {
48
+ const kind = buf[pos] ?? 0;
49
+ pos += 1;
50
+ const nameLen = view.getUint16(pos, true);
51
+ pos += 2;
52
+ const name = rstr(buf, pos, nameLen);
53
+ pos += nameLen;
54
+ const valueLen = view.getUint32(pos, true);
55
+ pos += 4;
56
+ const value = rstr(buf, pos, valueLen);
57
+ pos += valueLen;
58
+ attributes.push(decodeMdxJsxAttr(kind, name, value));
59
+ }
60
+ return { name: headName, attributes };
61
+ }
@@ -1,16 +1,9 @@
1
1
  import { HastReader } from "./hast-reader.js";
2
2
  import type { Root } from "hast";
3
3
  import type { HastNode } from "../types.js";
4
+ import { CONTAINER_TYPES } from "./generated/node-types.js";
4
5
  export type { HastNode };
5
- /** Container node types (the ones that carry `children`); everything else is a leaf. */
6
- export declare const HAST_CONTAINER_TYPES: ReadonlySet<number>;
7
- /**
8
- * Materialize a single HAST node; scalars eager, `children` lazy, memoized per
9
- * `(reader, id)`; `frozen` (the plugin walk path) deep-freezes so plugins
10
- * cannot corrupt the shared cache.
11
- */
6
+ export { CONTAINER_TYPES as HAST_CONTAINER_TYPES };
12
7
  export declare const materializeHastNode: (reader: HastReader, nodeId: number, frozen?: boolean, refs?: import("../visitor-shared.js").NodeRefs) => import("hast").Nodes;
13
- /**
14
- * Materialize the full HAST tree from root (nodeId=0).
15
- */
8
+ /** Materialize the full HAST tree from root (nodeId=0) in one eager pass, breadth-first over the parents still to fill. */
16
9
  export declare function materializeHastTree(reader: HastReader): Root;
@@ -1,57 +1,83 @@
1
- import { HastReader, HAST_ROOT, HAST_ELEMENT, HAST_TEXT, HAST_COMMENT, HAST_RAW, HAST_MDX_JSX_ELEMENT, HAST_MDX_JSX_TEXT_ELEMENT, HAST_MDX_FLOW_EXPRESSION, HAST_MDX_TEXT_EXPRESSION, HAST_MDX_ESM, } from "./hast-reader.js";
2
- import { TYPE_NAMES } from "./generated/node-types.js";
3
- import { restorePhantomSpaces } from "../phantom.js";
4
- import { createMaterializer } from "../materializer-cache.js";
5
- /** Container node types (the ones that carry `children`); everything else is a leaf. */
6
- export const HAST_CONTAINER_TYPES = new Set([
7
- HAST_ROOT,
8
- HAST_ELEMENT,
9
- HAST_MDX_JSX_ELEMENT,
10
- HAST_MDX_JSX_TEXT_ELEMENT,
11
- ]);
1
+ import { HastReader, HAST_MDX_JSX_ELEMENT, HAST_MDX_JSX_TEXT_ELEMENT } from "./hast-reader.js";
2
+ import { CONTAINER_TYPES, TYPE_NAMES } from "./generated/node-types.js";
3
+ import { createMaterializer, installNodeData } from "../materializer-cache.js";
4
+ import { FIELD, W_CHILDREN_COUNT, W_CHILDREN_START } from "../generated/arena-layout.js";
5
+ import { readHastWireNode } from "../generated/fused-wire.js";
6
+ export { CONTAINER_TYPES as HAST_CONTAINER_TYPES };
7
+ const IS_CONTAINER = new Uint8Array(256);
8
+ for (const t of CONTAINER_TYPES)
9
+ IS_CONTAINER[t] = 1;
12
10
  const hastMaterializer = createMaterializer({
13
11
  label: "materializeHastNode",
14
12
  typeNames: TYPE_NAMES,
15
- hasChildren: (nodeType) => HAST_CONTAINER_TYPES.has(nodeType),
13
+ hasChildren: (nodeType) => IS_CONTAINER[nodeType] === 1,
16
14
  populate(node, reader, nodeId, nodeType) {
17
- switch (nodeType) {
18
- case HAST_ELEMENT:
19
- reader.readElementInto(nodeId, node);
20
- break;
21
- case HAST_TEXT:
22
- case HAST_COMMENT:
23
- case HAST_RAW:
24
- node.value = reader.getTextValue(nodeId);
25
- break;
26
- case HAST_MDX_JSX_ELEMENT:
27
- case HAST_MDX_JSX_TEXT_ELEMENT: {
28
- const { name, attributes } = reader.getMdxJsxElementData(nodeId);
29
- node.name = name;
30
- node.attributes = attributes;
31
- break;
32
- }
33
- case HAST_MDX_FLOW_EXPRESSION:
34
- case HAST_MDX_TEXT_EXPRESSION:
35
- node.value = restorePhantomSpaces(reader.getTextValue(nodeId));
36
- break;
37
- case HAST_MDX_ESM:
38
- node.value = reader.getTextValue(nodeId);
39
- break;
40
- // HAST_ROOT / HAST_DOCTYPE: no extra properties
41
- default:
42
- break;
15
+ if (!readHastWireNode(reader.getWire(), nodeId, nodeType, node)) {
16
+ addHastTypeProperties(node, reader, nodeId, nodeType);
43
17
  }
44
18
  },
45
19
  });
46
- /**
47
- * Materialize a single HAST node; scalars eager, `children` lazy, memoized per
48
- * `(reader, id)`; `frozen` (the plugin walk path) deep-freezes so plugins
49
- * cannot corrupt the shared cache.
50
- */
51
20
  export const materializeHastNode = hastMaterializer.node;
52
- /**
53
- * Materialize the full HAST tree from root (nodeId=0).
54
- */
21
+ function addHastTypeProperties(node, reader, nodeId, nodeType) {
22
+ if (nodeType === HAST_MDX_JSX_ELEMENT || nodeType === HAST_MDX_JSX_TEXT_ELEMENT) {
23
+ const { name, attributes } = reader.getMdxJsxElementData(nodeId);
24
+ const element = node;
25
+ element.name = name;
26
+ element.attributes = attributes;
27
+ }
28
+ }
29
+ // Not a per-call closure: fresh closures restart type feedback per tree, pinning small-tree calls to the slow tiers.
30
+ function buildHastFused(reader, wire, nodeId, nodeType) {
31
+ const typeName = TYPE_NAMES[nodeType] ?? `unknown(${nodeType})`;
32
+ // Unified's assertNode requires a plain-object prototype.
33
+ const node = { type: typeName };
34
+ if (!readHastWireNode(wire, nodeId, nodeType, node)) {
35
+ addHastTypeProperties(node, reader, nodeId, nodeType);
36
+ }
37
+ return node;
38
+ }
39
+ /** Materialize the full HAST tree from root (nodeId=0) in one eager pass, breadth-first over the parents still to fill. */
55
40
  export function materializeHastTree(reader) {
56
- return hastMaterializer.tree(reader, 0);
41
+ const wire = reader.getWire();
42
+ const { u8, u32, nodesB, nodesW, strideB, strideW, childrenW } = wire;
43
+ const dataTable = reader.getNodeDataTable();
44
+ const rootType = u8[nodesB + FIELD.node_type] ?? 0;
45
+ const root = buildHastFused(reader, wire, 0, rootType);
46
+ if (dataTable !== null) {
47
+ const raw = dataTable.get(0);
48
+ if (raw !== undefined)
49
+ installNodeData(root, raw, "materializeHastTree", 0);
50
+ }
51
+ if (IS_CONTAINER[rootType] !== 1)
52
+ return root;
53
+ const parents = [root];
54
+ const parentIds = [0];
55
+ for (let p = 0; p < parentIds.length; p++) {
56
+ const parent = parents[p];
57
+ const parentId = parentIds[p];
58
+ if (parent === undefined || parentId === undefined) {
59
+ throw new Error(`materializeHastTree: parent queue hole at ${p}`);
60
+ }
61
+ const w = nodesW + parentId * strideW;
62
+ const count = u32[w + W_CHILDREN_COUNT] ?? 0;
63
+ const cbase = childrenW + (u32[w + W_CHILDREN_START] ?? 0);
64
+ const kids = new Array(count);
65
+ for (let i = 0; i < count; i++) {
66
+ const childId = u32[cbase + i] ?? 0;
67
+ const childType = u8[nodesB + childId * strideB + FIELD.node_type] ?? 0;
68
+ const child = buildHastFused(reader, wire, childId, childType);
69
+ kids[i] = child;
70
+ if (dataTable !== null) {
71
+ const raw = dataTable.get(childId);
72
+ if (raw !== undefined)
73
+ installNodeData(child, raw, "materializeHastTree", childId);
74
+ }
75
+ if (IS_CONTAINER[childType] === 1) {
76
+ parents.push(child);
77
+ parentIds.push(childId);
78
+ }
79
+ }
80
+ parent.children = kids;
81
+ }
82
+ return root;
57
83
  }
@@ -1,6 +1,6 @@
1
- import type { BufferHeader } from "../types.js";
2
- import type { MdxJsxAttribute, MdxJsxExpressionAttribute } from "../mdx-types.js";
3
1
  import type { Position } from "unist";
2
+ import type { MdxJsxAttribute, MdxJsxExpressionAttribute } from "../mdx-types.js";
3
+ import type { BufferHeader } from "../types.js";
4
4
  export type { MdxJsxAttribute, MdxJsxExpressionAttribute };
5
5
  export declare const HAST_ROOT: number;
6
6
  export declare const HAST_ELEMENT: number;
@@ -19,57 +19,28 @@ export interface HastProperty {
19
19
  export declare class HastReader {
20
20
  #private;
21
21
  constructor(buffer: ArrayBuffer | Uint8Array);
22
- /**
23
- * Per-node JSON `data` blob (set via `Arena::set_node_data` on the Rust
24
- * side). Returns `null` when the node has no entry. Lazy-builds a
25
- * `Map<id, string>` on first call so a materialization pass on a
26
- * data-heavy tree stays O(nodes) rather than O(nodes × entries).
27
- */
22
+ /** Per-node JSON data, or null when absent. */
28
23
  getNodeData(nodeId: number): string | null;
29
24
  get nodeCount(): number;
30
25
  get header(): BufferHeader;
31
- /** The full string pool (original input + interning heap). Not the document
32
- * source as written; for that, read `ctx.source` from a plugin. */
26
+ /** Full string pool, including interned strings; use ctx.source for the original document. */
33
27
  getStringPool(): string;
34
- /** Read a substring from the string pool by byte offset and length. */
28
+ /** Wire string refs use UTF-16 units, so substring preserves their offsets. */
35
29
  getString(offset: number, len: number): string;
36
- /** Get position data for a node. */
30
+ /** A zero start line marks a synthesized node with no source range (unist
31
+ * lines are 1-based), surfaced as `undefined`. */
37
32
  getPosition(nodeId: number): Position | undefined;
38
33
  /** Get the node_type byte for a given node ID. */
39
34
  getNodeType(nodeId: number): number;
40
35
  /** Get the parent id for a given node (0xffffffff at the root). */
41
36
  getParentId(nodeId: number): number;
42
- /** Get child node IDs for a given node. */
37
+ getChildrenCount(nodeId: number): number;
43
38
  getChildIds(nodeId: number): number[];
44
- /** Push child node IDs directly onto a stack array (reverse order for depth-first). */
45
- pushChildIds(nodeId: number, stack: number[]): void;
46
39
  /** Get the raw type_data bytes for a node. */
47
40
  getTypeData(nodeId: number): Uint8Array;
48
- /** Element `tagName`, `properties` count, and the i-th property, read without
49
- * building the intermediate views and records `getElementData` allocates. */
50
- getElementTagName(nodeId: number): string;
51
- getElementPropCount(nodeId: number): number;
52
- getElementPropName(nodeId: number, index: number): string;
53
- getElementPropValue(nodeId: number, index: number): HastProperty["value"];
54
- getElementData(nodeId: number): {
55
- tagName: string;
56
- properties: HastProperty[];
57
- };
58
- /**
59
- * Get MDX JSX element data: name and attributes.
60
- *
61
- * MDX JSX element type_data layout:
62
- * [name: StringRef(8B)][attr_count: u32(4B)][_pad: u32(4B)] = 16-byte header
63
- * then attr_count * 20 bytes:
64
- * [kind: u8(1B)][_pad: [u8;3](3B)][name: StringRef(8B)][value: StringRef(8B)]
65
- */
41
+ /** A zero-length element name represents an MDX fragment. */
66
42
  getMdxJsxElementData(nodeId: number): {
67
43
  name: string | null;
68
44
  attributes: (MdxJsxAttribute | MdxJsxExpressionAttribute)[];
69
45
  };
70
- /**
71
- * Get the string value for HAST_TEXT, HAST_COMMENT, or HAST_RAW nodes.
72
- * These store a single StringRef (8 bytes) as their type_data.
73
- */
74
- getTextValue(nodeId: number): string;
75
46
  }