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
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { HastReader, HAST_ROOT, HAST_ELEMENT, HAST_TEXT, HAST_COMMENT, HAST_DOCTYPE, 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";
|
|
2
3
|
import { lazyProp, lazyGroup } from "../lazy-props.js";
|
|
4
|
+
import { restorePhantomSpaces } from "../phantom.js";
|
|
3
5
|
function propsToRecord(props) {
|
|
4
6
|
const result = {};
|
|
5
7
|
for (const p of props) {
|
|
@@ -12,47 +14,13 @@ function propsToRecord(props) {
|
|
|
12
14
|
*/
|
|
13
15
|
export function materializeHastNode(reader, nodeId) {
|
|
14
16
|
const nodeType = reader.getNodeType(nodeId);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
typeName = "element";
|
|
22
|
-
break;
|
|
23
|
-
case HAST_TEXT:
|
|
24
|
-
typeName = "text";
|
|
25
|
-
break;
|
|
26
|
-
case HAST_COMMENT:
|
|
27
|
-
typeName = "comment";
|
|
28
|
-
break;
|
|
29
|
-
case HAST_DOCTYPE:
|
|
30
|
-
typeName = "doctype";
|
|
31
|
-
break;
|
|
32
|
-
case HAST_RAW:
|
|
33
|
-
typeName = "raw";
|
|
34
|
-
break;
|
|
35
|
-
case HAST_MDX_JSX_ELEMENT:
|
|
36
|
-
typeName = "mdxJsxFlowElement";
|
|
37
|
-
break;
|
|
38
|
-
case HAST_MDX_JSX_TEXT_ELEMENT:
|
|
39
|
-
typeName = "mdxJsxTextElement";
|
|
40
|
-
break;
|
|
41
|
-
case HAST_MDX_FLOW_EXPRESSION:
|
|
42
|
-
typeName = "mdxFlowExpression";
|
|
43
|
-
break;
|
|
44
|
-
case HAST_MDX_TEXT_EXPRESSION:
|
|
45
|
-
typeName = "mdxTextExpression";
|
|
46
|
-
break;
|
|
47
|
-
case HAST_MDX_ESM:
|
|
48
|
-
typeName = "mdxjsEsm";
|
|
49
|
-
break;
|
|
50
|
-
default:
|
|
51
|
-
typeName = `unknown(${nodeType})`;
|
|
52
|
-
break;
|
|
17
|
+
const typeName = TYPE_NAMES[nodeType] ?? `unknown(${nodeType})`;
|
|
18
|
+
const node = { type: typeName };
|
|
19
|
+
// Position decodes to three objects; defer it — passthrough children (e.g.
|
|
20
|
+
// replaceNode keeping `node.children`) never read it.
|
|
21
|
+
if (reader.hasPosition(nodeId)) {
|
|
22
|
+
Object.defineProperty(node, "position", lazyProp("position", () => reader.getPosition(nodeId)));
|
|
53
23
|
}
|
|
54
|
-
const position = reader.getPosition(nodeId);
|
|
55
|
-
const node = (position ? { type: typeName, position } : { type: typeName });
|
|
56
24
|
// _nodeId: non-enumerable internal reference
|
|
57
25
|
Object.defineProperty(node, "_nodeId", {
|
|
58
26
|
value: nodeId,
|
|
@@ -135,11 +103,7 @@ export function materializeHastNode(reader, nodeId) {
|
|
|
135
103
|
case HAST_MDX_FLOW_EXPRESSION:
|
|
136
104
|
case HAST_MDX_TEXT_EXPRESSION:
|
|
137
105
|
Object.defineProperties(node, {
|
|
138
|
-
|
|
139
|
-
// satteri-pulldown-cmark/src/mdx.rs) back to regular spaces — mdast
|
|
140
|
-
// and hast keep phantoms in the value field; only the compile path
|
|
141
|
-
// drops them.
|
|
142
|
-
value: lazyProp("value", () => reader.getTextValue(nodeId).replaceAll("", " ")),
|
|
106
|
+
value: lazyProp("value", () => restorePhantomSpaces(reader.getTextValue(nodeId))),
|
|
143
107
|
});
|
|
144
108
|
break;
|
|
145
109
|
case HAST_MDX_ESM:
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import type { BufferHeader } from "../types.js";
|
|
2
2
|
import type { MdxJsxAttribute, MdxJsxExpressionAttribute } from "../mdx-types.js";
|
|
3
|
+
import type { Position } from "unist";
|
|
3
4
|
export type { MdxJsxAttribute, MdxJsxExpressionAttribute };
|
|
4
|
-
export declare const HAST_ROOT
|
|
5
|
-
export declare const HAST_ELEMENT
|
|
6
|
-
export declare const HAST_TEXT
|
|
7
|
-
export declare const HAST_COMMENT
|
|
8
|
-
export declare const HAST_DOCTYPE
|
|
9
|
-
export declare const HAST_RAW
|
|
10
|
-
export declare const HAST_MDX_JSX_ELEMENT
|
|
11
|
-
export declare const HAST_MDX_JSX_TEXT_ELEMENT
|
|
12
|
-
export declare const HAST_MDX_FLOW_EXPRESSION
|
|
13
|
-
export declare const HAST_MDX_ESM
|
|
14
|
-
export declare const HAST_MDX_TEXT_EXPRESSION
|
|
5
|
+
export declare const HAST_ROOT: number;
|
|
6
|
+
export declare const HAST_ELEMENT: number;
|
|
7
|
+
export declare const HAST_TEXT: number;
|
|
8
|
+
export declare const HAST_COMMENT: number;
|
|
9
|
+
export declare const HAST_DOCTYPE: number;
|
|
10
|
+
export declare const HAST_RAW: number;
|
|
11
|
+
export declare const HAST_MDX_JSX_ELEMENT: number;
|
|
12
|
+
export declare const HAST_MDX_JSX_TEXT_ELEMENT: number;
|
|
13
|
+
export declare const HAST_MDX_FLOW_EXPRESSION: number;
|
|
14
|
+
export declare const HAST_MDX_ESM: number;
|
|
15
|
+
export declare const HAST_MDX_TEXT_EXPRESSION: number;
|
|
15
16
|
export interface HastProperty {
|
|
16
17
|
name: string;
|
|
17
18
|
value: string | number | boolean | string[];
|
|
@@ -33,20 +34,14 @@ export declare class HastReader {
|
|
|
33
34
|
/** Read a substring from the string pool by byte offset and length. */
|
|
34
35
|
getString(offset: number, len: number): string;
|
|
35
36
|
/** Get position data for a node. */
|
|
36
|
-
getPosition(nodeId: number):
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
column: number;
|
|
41
|
-
};
|
|
42
|
-
end: {
|
|
43
|
-
offset: number;
|
|
44
|
-
line: number;
|
|
45
|
-
column: number;
|
|
46
|
-
};
|
|
47
|
-
} | undefined;
|
|
37
|
+
getPosition(nodeId: number): Position | undefined;
|
|
38
|
+
/** Whether the node carries a source position (line 0 + offset 0 is the
|
|
39
|
+
* synthesized-node sentinel), without decoding the three position objects. */
|
|
40
|
+
hasPosition(nodeId: number): boolean;
|
|
48
41
|
/** Get the node_type byte for a given node ID. */
|
|
49
42
|
getNodeType(nodeId: number): number;
|
|
43
|
+
/** Get the parent id for a given node (0xffffffff at the root). */
|
|
44
|
+
getParentId(nodeId: number): number;
|
|
50
45
|
/** Get child node IDs for a given node. */
|
|
51
46
|
getChildIds(nodeId: number): number[];
|
|
52
47
|
/** Push child node IDs directly onto a stack array (reverse order for depth-first). */
|
package/dist/hast/hast-reader.js
CHANGED
|
@@ -1,53 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export const
|
|
8
|
-
|
|
9
|
-
export const
|
|
10
|
-
export const
|
|
11
|
-
export const
|
|
12
|
-
export const
|
|
13
|
-
export const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const PROP_COMMA_SEP = 4;
|
|
19
|
-
// MDX JSX attribute kinds (must match node_types.rs)
|
|
20
|
-
const MDX_ATTR_BOOLEAN_PROP = 0;
|
|
21
|
-
const MDX_ATTR_LITERAL_PROP = 1;
|
|
22
|
-
const MDX_ATTR_EXPRESSION_PROP = 2;
|
|
23
|
-
const MDX_ATTR_SPREAD = 3;
|
|
24
|
-
// HastNode field offsets (same layout as MDAST, shared binary format)
|
|
25
|
-
// id: u32 @ 0
|
|
26
|
-
// node_type: u8 @ 4
|
|
27
|
-
// _pad: [u8; 3] @ 5
|
|
28
|
-
// parent: u32 @ 8
|
|
29
|
-
// ...
|
|
30
|
-
// children_start: u32 @ 36
|
|
31
|
-
// children_count: u32 @ 40
|
|
32
|
-
// data_offset: u32 @ 44
|
|
33
|
-
// data_len: u32 @ 48
|
|
34
|
-
// Total: 52 bytes
|
|
35
|
-
const FIELD = {
|
|
36
|
-
node_type: 4,
|
|
37
|
-
start_offset: 12,
|
|
38
|
-
end_offset: 16,
|
|
39
|
-
start_line: 20,
|
|
40
|
-
start_column: 24,
|
|
41
|
-
end_line: 28,
|
|
42
|
-
end_column: 32,
|
|
43
|
-
children_start: 36,
|
|
44
|
-
children_count: 40,
|
|
45
|
-
data_offset: 44,
|
|
46
|
-
data_len: 48,
|
|
47
|
-
};
|
|
48
|
-
// "MDAR" bytes: 4d 44 41 52; read as LE u32 = 0x5241444d
|
|
49
|
-
const MAGIC = 0x5241444d;
|
|
50
|
-
const KIND_HAST = 2;
|
|
1
|
+
import { restorePhantomSpaces } from "../phantom.js";
|
|
2
|
+
import { readPosition } from "../wire-read.js";
|
|
3
|
+
import { MDX_ATTR_BOOLEAN_PROP, MDX_ATTR_LITERAL_PROP, MDX_ATTR_EXPRESSION_PROP, MDX_ATTR_SPREAD, } from "../op-stream.js";
|
|
4
|
+
import { decodeElementProp } from "./element-props.js";
|
|
5
|
+
import { NAME_TO_TYPE } from "./generated/node-types.js";
|
|
6
|
+
import { ARENA_MAGIC, KIND_HAST, FIELD, HEADER } from "../generated/arena-layout.js";
|
|
7
|
+
export const HAST_ROOT = NAME_TO_TYPE.root;
|
|
8
|
+
export const HAST_ELEMENT = NAME_TO_TYPE.element;
|
|
9
|
+
export const HAST_TEXT = NAME_TO_TYPE.text;
|
|
10
|
+
export const HAST_COMMENT = NAME_TO_TYPE.comment;
|
|
11
|
+
export const HAST_DOCTYPE = NAME_TO_TYPE.doctype;
|
|
12
|
+
export const HAST_RAW = NAME_TO_TYPE.raw;
|
|
13
|
+
export const HAST_MDX_JSX_ELEMENT = NAME_TO_TYPE.mdxJsxFlowElement;
|
|
14
|
+
export const HAST_MDX_JSX_TEXT_ELEMENT = NAME_TO_TYPE.mdxJsxTextElement;
|
|
15
|
+
export const HAST_MDX_FLOW_EXPRESSION = NAME_TO_TYPE.mdxFlowExpression;
|
|
16
|
+
export const HAST_MDX_ESM = NAME_TO_TYPE.mdxjsEsm;
|
|
17
|
+
export const HAST_MDX_TEXT_EXPRESSION = NAME_TO_TYPE.mdxTextExpression;
|
|
51
18
|
export class HastReader {
|
|
52
19
|
#view;
|
|
53
20
|
#header;
|
|
@@ -65,27 +32,27 @@ export class HastReader {
|
|
|
65
32
|
}
|
|
66
33
|
#readHeader() {
|
|
67
34
|
const v = this.#view;
|
|
68
|
-
const magic = v.getUint32(
|
|
69
|
-
if (magic !==
|
|
35
|
+
const magic = v.getUint32(HEADER.magic, true);
|
|
36
|
+
if (magic !== ARENA_MAGIC) {
|
|
70
37
|
throw new Error(`Invalid HAST buffer: bad magic 0x${magic.toString(16)}`);
|
|
71
38
|
}
|
|
72
|
-
const kind = v.getUint32(
|
|
39
|
+
const kind = v.getUint32(HEADER.kind, true);
|
|
73
40
|
if (kind !== KIND_HAST) {
|
|
74
41
|
throw new Error(`HastReader was handed a buffer of kind ${kind} (expected ${KIND_HAST}). ` +
|
|
75
42
|
`MDAST and HAST node types overlap; reading the wrong kind decodes garbage.`);
|
|
76
43
|
}
|
|
77
44
|
return {
|
|
78
|
-
nodeStructSize: v.getUint32(
|
|
79
|
-
nodeCount: v.getUint32(
|
|
80
|
-
nodesOffset: v.getUint32(
|
|
81
|
-
childrenCount: v.getUint32(
|
|
82
|
-
childrenOffset: v.getUint32(
|
|
83
|
-
typeDataLen: v.getUint32(
|
|
84
|
-
typeDataOffset: v.getUint32(
|
|
85
|
-
sourceLen: v.getUint32(
|
|
86
|
-
sourceOffset: v.getUint32(
|
|
87
|
-
nodeDataCount: v.getUint32(
|
|
88
|
-
nodeDataOffset: v.getUint32(
|
|
45
|
+
nodeStructSize: v.getUint32(HEADER.node_struct_size, true),
|
|
46
|
+
nodeCount: v.getUint32(HEADER.node_count, true),
|
|
47
|
+
nodesOffset: v.getUint32(HEADER.nodes_offset, true),
|
|
48
|
+
childrenCount: v.getUint32(HEADER.children_count, true),
|
|
49
|
+
childrenOffset: v.getUint32(HEADER.children_offset, true),
|
|
50
|
+
typeDataLen: v.getUint32(HEADER.type_data_len, true),
|
|
51
|
+
typeDataOffset: v.getUint32(HEADER.type_data_offset, true),
|
|
52
|
+
sourceLen: v.getUint32(HEADER.source_len, true),
|
|
53
|
+
sourceOffset: v.getUint32(HEADER.source_offset, true),
|
|
54
|
+
nodeDataCount: v.getUint32(HEADER.node_data_count, true),
|
|
55
|
+
nodeDataOffset: v.getUint32(HEADER.node_data_offset, true),
|
|
89
56
|
};
|
|
90
57
|
}
|
|
91
58
|
#nodeDataTable = null;
|
|
@@ -139,30 +106,27 @@ export class HastReader {
|
|
|
139
106
|
}
|
|
140
107
|
/** Get position data for a node. */
|
|
141
108
|
getPosition(nodeId) {
|
|
109
|
+
const base = this.#header.nodesOffset + nodeId * this.#header.nodeStructSize;
|
|
110
|
+
return readPosition(this.#view, base + FIELD.start_offset);
|
|
111
|
+
}
|
|
112
|
+
/** Whether the node carries a source position (line 0 + offset 0 is the
|
|
113
|
+
* synthesized-node sentinel), without decoding the three position objects. */
|
|
114
|
+
hasPosition(nodeId) {
|
|
142
115
|
const base = this.#header.nodesOffset + nodeId * this.#header.nodeStructSize;
|
|
143
116
|
const v = this.#view;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (startLine === 0 && startOffset === 0)
|
|
147
|
-
return undefined;
|
|
148
|
-
return {
|
|
149
|
-
start: {
|
|
150
|
-
offset: startOffset,
|
|
151
|
-
line: startLine,
|
|
152
|
-
column: v.getUint32(base + FIELD.start_column, true),
|
|
153
|
-
},
|
|
154
|
-
end: {
|
|
155
|
-
offset: v.getUint32(base + FIELD.end_offset, true),
|
|
156
|
-
line: v.getUint32(base + FIELD.end_line, true),
|
|
157
|
-
column: v.getUint32(base + FIELD.end_column, true),
|
|
158
|
-
},
|
|
159
|
-
};
|
|
117
|
+
return (v.getUint32(base + FIELD.start_line, true) !== 0 ||
|
|
118
|
+
v.getUint32(base + FIELD.start_offset, true) !== 0);
|
|
160
119
|
}
|
|
161
120
|
/** Get the node_type byte for a given node ID. */
|
|
162
121
|
getNodeType(nodeId) {
|
|
163
122
|
const { nodesOffset, nodeStructSize } = this.#header;
|
|
164
123
|
return this.#view.getUint8(nodesOffset + nodeId * nodeStructSize + FIELD.node_type);
|
|
165
124
|
}
|
|
125
|
+
/** Get the parent id for a given node (0xffffffff at the root). */
|
|
126
|
+
getParentId(nodeId) {
|
|
127
|
+
const { nodesOffset, nodeStructSize } = this.#header;
|
|
128
|
+
return this.#view.getUint32(nodesOffset + nodeId * nodeStructSize + FIELD.parent, true);
|
|
129
|
+
}
|
|
166
130
|
/** Get child node IDs for a given node. */
|
|
167
131
|
getChildIds(nodeId) {
|
|
168
132
|
const base = this.#header.nodesOffset + nodeId * this.#header.nodeStructSize;
|
|
@@ -233,39 +197,8 @@ export class HastReader {
|
|
|
233
197
|
const name = this.getString(nameRef.offset, nameRef.len);
|
|
234
198
|
const valueType = data[base + 8];
|
|
235
199
|
const valueRef = this.#readStringRef(data, base + 12);
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
properties.push({ name, value: true });
|
|
239
|
-
break;
|
|
240
|
-
case PROP_BOOL_FALSE:
|
|
241
|
-
properties.push({ name, value: false });
|
|
242
|
-
break;
|
|
243
|
-
case PROP_STRING:
|
|
244
|
-
properties.push({ name, value: this.getString(valueRef.offset, valueRef.len) });
|
|
245
|
-
break;
|
|
246
|
-
case PROP_SPACE_SEP: {
|
|
247
|
-
const raw = this.getString(valueRef.offset, valueRef.len);
|
|
248
|
-
properties.push({ name, value: raw.split(" ").filter((s) => s.length > 0) });
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
case PROP_COMMA_SEP: {
|
|
252
|
-
const raw = this.getString(valueRef.offset, valueRef.len);
|
|
253
|
-
properties.push({
|
|
254
|
-
name,
|
|
255
|
-
value: raw
|
|
256
|
-
.split(",")
|
|
257
|
-
.map((s) => s.trim())
|
|
258
|
-
.filter((s) => s.length > 0),
|
|
259
|
-
});
|
|
260
|
-
break;
|
|
261
|
-
}
|
|
262
|
-
case 5: {
|
|
263
|
-
// PROP_INT
|
|
264
|
-
const raw = this.getString(valueRef.offset, valueRef.len);
|
|
265
|
-
properties.push({ name, value: Number(raw) });
|
|
266
|
-
break;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
200
|
+
const valueStr = this.getString(valueRef.offset, valueRef.len);
|
|
201
|
+
properties.push({ name, value: decodeElementProp(valueType, valueStr) });
|
|
269
202
|
}
|
|
270
203
|
return { tagName, properties };
|
|
271
204
|
}
|
|
@@ -313,14 +246,14 @@ export class HastReader {
|
|
|
313
246
|
name: this.getString(attrNameRef.offset, attrNameRef.len),
|
|
314
247
|
value: {
|
|
315
248
|
type: "mdxJsxAttributeValueExpression",
|
|
316
|
-
value: this.getString(attrValueRef.offset, attrValueRef.len)
|
|
249
|
+
value: restorePhantomSpaces(this.getString(attrValueRef.offset, attrValueRef.len)),
|
|
317
250
|
},
|
|
318
251
|
});
|
|
319
252
|
break;
|
|
320
253
|
case MDX_ATTR_SPREAD:
|
|
321
254
|
attributes.push({
|
|
322
255
|
type: "mdxJsxExpressionAttribute",
|
|
323
|
-
value: this.getString(attrValueRef.offset, attrValueRef.len)
|
|
256
|
+
value: restorePhantomSpaces(this.getString(attrValueRef.offset, attrValueRef.len)),
|
|
324
257
|
});
|
|
325
258
|
break;
|
|
326
259
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { type HastNode } from "./hast-materializer.js";
|
|
2
|
-
import type { HastRaw } from "../types.js";
|
|
3
|
-
import type { Element, Text, Comment, Doctype } from "hast";
|
|
2
|
+
import type { HastRaw, Data } from "../types.js";
|
|
3
|
+
import type { Element, Text, Comment, Doctype, Parents as HastParents, Root as HastRoot } from "hast";
|
|
4
4
|
import type { Program } from "estree-jsx";
|
|
5
5
|
import type { MdxJsxFlowElementHast, MdxJsxTextElementHast } from "../mdx-types.js";
|
|
6
6
|
import type { MdxFlowExpressionHast, MdxTextExpressionHast } from "../mdx-types.js";
|
|
7
7
|
import type { MdxjsEsmHast } from "../mdx-types.js";
|
|
8
|
-
|
|
8
|
+
import type { HastHandle } from "../handles.js";
|
|
9
|
+
export type { HastHandle };
|
|
9
10
|
/** ESTree-compatible Program node returned by `parseExpression()`. */
|
|
10
11
|
export type EstreeProgram = Program;
|
|
11
12
|
export interface HastDiagnostic {
|
|
@@ -21,21 +22,45 @@ export interface HastVisitorContext {
|
|
|
21
22
|
* decoded filesystem path.
|
|
22
23
|
*/
|
|
23
24
|
readonly fileURL: URL | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Document-level data bag, shared across every plugin in the compile and
|
|
27
|
+
* across the mdast→hast phase boundary. Mutate keys directly
|
|
28
|
+
* (`ctx.data.foo = x`); the bag itself isn't reassignable. Values are kept
|
|
29
|
+
* on the JS side, so any value is allowed, including functions and class
|
|
30
|
+
* instances. Returned to the caller as `result.data`.
|
|
31
|
+
*/
|
|
32
|
+
readonly data: Data;
|
|
24
33
|
removeNode(node: Readonly<HastNode>): void;
|
|
25
|
-
replaceNode(node: Readonly<HastNode>, newNode:
|
|
26
|
-
insertBefore(node: Readonly<HastNode>, newNode:
|
|
27
|
-
insertAfter(node: Readonly<HastNode>, newNode:
|
|
34
|
+
replaceNode(node: Readonly<HastNode>, newNode: HastContent): void;
|
|
35
|
+
insertBefore(node: Readonly<HastNode>, newNode: HastContent | HastContent[]): void;
|
|
36
|
+
insertAfter(node: Readonly<HastNode>, newNode: HastContent | HastContent[]): void;
|
|
28
37
|
/**
|
|
29
38
|
* Wrap `node` in `parentNode`, making it `parentNode`'s first child. Any
|
|
30
39
|
* children `parentNode` declares are kept after it, so a `div` with an anchor
|
|
31
40
|
* child wraps a heading as `div > [heading, anchor]`.
|
|
32
41
|
*/
|
|
33
|
-
wrapNode(node: Readonly<HastNode>, parentNode:
|
|
34
|
-
prependChild(node: Readonly<HastNode>, childNode:
|
|
35
|
-
appendChild(node: Readonly<HastNode>, childNode:
|
|
42
|
+
wrapNode(node: Readonly<HastNode>, parentNode: HastContent): void;
|
|
43
|
+
prependChild(node: Readonly<HastNode>, childNode: HastContent | HastContent[]): void;
|
|
44
|
+
appendChild(node: Readonly<HastNode>, childNode: HastContent | HastContent[]): void;
|
|
45
|
+
/** Insert one node or an array at `index`; clamps (`0` or less prepends, past the end appends). */
|
|
46
|
+
insertChildAt(node: Readonly<HastNode>, index: number, childNode: HastContent | HastContent[]): void;
|
|
47
|
+
/** Remove the `index`-th child of `node`; a no-op when there is no such child. */
|
|
48
|
+
removeChildAt(node: Readonly<HastNode>, index: number): void;
|
|
36
49
|
setProperty(node: Readonly<HastNode>, key: string, value: unknown): void;
|
|
37
50
|
/** Collect the concatenated text of all descendant text nodes (like DOM textContent). */
|
|
38
51
|
textContent(node: Readonly<HastNode>): string;
|
|
52
|
+
/**
|
|
53
|
+
* The parent of a node, or `undefined` at the root. Within a pass the same
|
|
54
|
+
* parent is always the same object, so visitors on sibling nodes can dedupe
|
|
55
|
+
* by identity.
|
|
56
|
+
*/
|
|
57
|
+
parent<N extends Exclude<HastNode, HastRoot>>(node: Readonly<N>): Readonly<HastParents>;
|
|
58
|
+
parent(node: Readonly<HastNode>): Readonly<HastParents> | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Index of `node` within its parent's children, or `undefined` at the root.
|
|
61
|
+
* Use this rather than `parent.children.indexOf(node)`, which won't find it.
|
|
62
|
+
*/
|
|
63
|
+
indexOf(node: Readonly<HastNode>): number | undefined;
|
|
39
64
|
report(opts: {
|
|
40
65
|
message: string;
|
|
41
66
|
node?: Readonly<HastNode>;
|
|
@@ -43,6 +68,9 @@ export interface HastVisitorContext {
|
|
|
43
68
|
}): void;
|
|
44
69
|
getDiagnostics(): HastDiagnostic[];
|
|
45
70
|
}
|
|
71
|
+
/** New content for a HAST structural mutation. Unlike [`MdastContent`], HAST has
|
|
72
|
+
* a `raw` node type, so it needs no raw/rawHtml escape hatch. */
|
|
73
|
+
export type HastContent = HastNode;
|
|
46
74
|
/** A filtered visitor: Rust filters by tag/component name, only matched nodes cross the boundary. */
|
|
47
75
|
export interface HastFilteredVisitor<N extends HastNode = HastNode> {
|
|
48
76
|
filter: string[];
|
|
@@ -72,7 +100,6 @@ interface ResolvedSubscription {
|
|
|
72
100
|
tagFilter: string[];
|
|
73
101
|
visitFn: (node: HastNode, ctx: HastVisitorContext) => HastNode | void;
|
|
74
102
|
}
|
|
75
|
-
/** Resolve subscriptions from a plugin instance. */
|
|
76
103
|
export declare function resolveSubscriptions(plugin: HastVisitorInstance): ResolvedSubscription[];
|
|
77
104
|
/**
|
|
78
105
|
* Walk a handle's arena in Rust, dispatch matched nodes to JS visitor functions,
|
|
@@ -82,5 +109,4 @@ export declare function resolveSubscriptions(plugin: HastVisitorInstance): Resol
|
|
|
82
109
|
* replaced earlier in the same pass (the caller warns when non-zero), or a
|
|
83
110
|
* Promise of that count if any visitor is async.
|
|
84
111
|
*/
|
|
85
|
-
export declare function visitHastHandle(handle: HastHandle, plugin: HastVisitorInstance, subs: ResolvedSubscription[], source: string | (() => string), fileURL: URL | undefined): number | Promise<number>;
|
|
86
|
-
export {};
|
|
112
|
+
export declare function visitHastHandle(handle: HastHandle, plugin: HastVisitorInstance, subs: ResolvedSubscription[], source: string | (() => string), fileURL: URL | undefined, data?: Data): number | Promise<number>;
|