@@ -55,2 +55,4 @@ /** | ||
| replaceRawJson(nodeId: number, json: string): void; | ||
| /** Replace a node's child list (Root-wrapped `json`) while keeping the node. */ | ||
| setChildren(nodeId: number, json: string): void; | ||
| /** Write any structural command with a pre-serialized JSON payload. */ | ||
@@ -57,0 +59,0 @@ insertBeforeRawJson(nodeId: number, json: string): void; |
@@ -20,2 +20,3 @@ /** | ||
| const CMD_SET_PROPERTY = 0x0c; | ||
| const CMD_SET_CHILDREN = 0x0d; | ||
| // Payload types (0x10+, distinct range from commands) | ||
@@ -123,2 +124,6 @@ const PAYLOAD_RAW_MARKDOWN = 0x10; | ||
| } | ||
| /** Replace a node's child list (Root-wrapped `json`) while keeping the node. */ | ||
| setChildren(nodeId, json) { | ||
| this.writeRawJsonCommand(CMD_SET_CHILDREN, nodeId, json); | ||
| } | ||
| /** Write any structural command with a pre-serialized JSON payload. */ | ||
@@ -125,0 +130,0 @@ insertBeforeRawJson(nodeId, json) { |
@@ -26,4 +26,4 @@ import { type HastNode } from "./hast-materializer.js"; | ||
| replaceNode(node: Readonly<HastNode>, newNode: HastNode): void; | ||
| insertBefore(node: Readonly<HastNode>, newNode: HastNode): void; | ||
| insertAfter(node: Readonly<HastNode>, newNode: HastNode): void; | ||
| insertBefore(node: Readonly<HastNode>, newNode: HastNode | HastNode[]): void; | ||
| insertAfter(node: Readonly<HastNode>, newNode: HastNode | HastNode[]): void; | ||
| /** | ||
@@ -35,4 +35,8 @@ * Wrap `node` in `parentNode`, making it `parentNode`'s first child. Any | ||
| wrapNode(node: Readonly<HastNode>, parentNode: HastNode): void; | ||
| prependChild(node: Readonly<HastNode>, childNode: HastNode): void; | ||
| appendChild(node: Readonly<HastNode>, childNode: HastNode): void; | ||
| prependChild(node: Readonly<HastNode>, childNode: HastNode | HastNode[]): void; | ||
| appendChild(node: Readonly<HastNode>, childNode: HastNode | HastNode[]): void; | ||
| /** Insert one node or an array at `index`; clamps (`0` or less prepends, past the end appends). */ | ||
| insertChildAt(node: Readonly<HastNode>, index: number, childNode: HastNode | HastNode[]): void; | ||
| /** Remove the `index`-th child of `node`; a no-op when there is no such child. */ | ||
| removeChildAt(node: Readonly<HastNode>, index: number): void; | ||
| setProperty(node: Readonly<HastNode>, key: string, value: unknown): void; | ||
@@ -39,0 +43,0 @@ /** Collect the concatenated text of all descendant text nodes (like DOM textContent). */ |
@@ -61,2 +61,5 @@ import { materializeHastNode } from "./hast-materializer.js"; | ||
| } | ||
| function asArray(value) { | ||
| return Array.isArray(value) ? value : [value]; | ||
| } | ||
| class HastVisitorContextImpl { | ||
@@ -89,6 +92,12 @@ #commandBuffer = new CommandBuffer(); | ||
| insertBefore(node, newNode) { | ||
| this.#commandBuffer.insertBeforeRawJson(nid(node), JSON.stringify(markHast(newNode))); | ||
| const id = nid(node); | ||
| for (const n of asArray(newNode)) { | ||
| this.#commandBuffer.insertBeforeRawJson(id, JSON.stringify(markHast(n))); | ||
| } | ||
| } | ||
| insertAfter(node, newNode) { | ||
| this.#commandBuffer.insertAfterRawJson(nid(node), JSON.stringify(markHast(newNode))); | ||
| const id = nid(node); | ||
| for (const n of asArray(newNode)) { | ||
| this.#commandBuffer.insertAfterRawJson(id, JSON.stringify(markHast(n))); | ||
| } | ||
| } | ||
@@ -99,9 +108,43 @@ wrapNode(node, parentNode) { | ||
| prependChild(node, childNode) { | ||
| this.#commandBuffer.prependChildRawJson(nid(node), JSON.stringify(markHast(childNode))); | ||
| const id = nid(node); | ||
| for (const n of asArray(childNode)) { | ||
| this.#commandBuffer.prependChildRawJson(id, JSON.stringify(markHast(n))); | ||
| } | ||
| } | ||
| appendChild(node, childNode) { | ||
| this.#commandBuffer.appendChildRawJson(nid(node), JSON.stringify(markHast(childNode))); | ||
| const id = nid(node); | ||
| for (const n of asArray(childNode)) { | ||
| this.#commandBuffer.appendChildRawJson(id, JSON.stringify(markHast(n))); | ||
| } | ||
| } | ||
| insertChildAt(node, index, childNode) { | ||
| const children = "children" in node ? node.children : []; | ||
| if (index <= 0 || children.length === 0) { | ||
| this.prependChild(node, childNode); | ||
| } | ||
| else if (index >= children.length) { | ||
| this.appendChild(node, childNode); | ||
| } | ||
| else { | ||
| this.insertBefore(children[index], childNode); | ||
| } | ||
| } | ||
| removeChildAt(node, index) { | ||
| const child = "children" in node ? node.children[index] : undefined; | ||
| if (child) | ||
| this.removeNode(child); | ||
| } | ||
| setProperty(node, key, value) { | ||
| const id = nid(node); | ||
| if (key === "children") { | ||
| // children is structural: set-children keeps the node and swaps only its | ||
| // child list (reused children keep their id). | ||
| const wrapper = { | ||
| _hast: true, | ||
| type: "root", | ||
| children: value.map((child) => markHastNode(child, false)), | ||
| }; | ||
| this.#commandBuffer.setChildren(id, JSON.stringify(wrapper)); | ||
| return; | ||
| } | ||
| if (key === "data") { | ||
@@ -108,0 +151,0 @@ this.#commandBuffer.setProperty(id, key, value != null ? JSON.stringify(value) : null); |
@@ -25,4 +25,4 @@ import { CommandBuffer } from "../command-buffer.js"; | ||
| removeNode(node: Readonly<MdastNode>): void; | ||
| insertBefore(node: Readonly<MdastNode>, newNode: MdastNode): void; | ||
| insertAfter(node: Readonly<MdastNode>, newNode: MdastNode): void; | ||
| insertBefore(node: Readonly<MdastNode>, newNode: MdastNode | MdastNode[]): void; | ||
| insertAfter(node: Readonly<MdastNode>, newNode: MdastNode | MdastNode[]): void; | ||
| /** | ||
@@ -33,4 +33,8 @@ * Wrap `node` in `parentNode`, making it `parentNode`'s first child. Any | ||
| wrapNode(node: Readonly<MdastNode>, parentNode: MdastNode): void; | ||
| prependChild(node: Readonly<MdastNode>, childNode: MdastNode): void; | ||
| appendChild(node: Readonly<MdastNode>, childNode: MdastNode): void; | ||
| prependChild(node: Readonly<MdastNode>, childNode: MdastNode | MdastNode[]): void; | ||
| appendChild(node: Readonly<MdastNode>, childNode: MdastNode | MdastNode[]): void; | ||
| /** Insert one node or an array at `index`; clamps (`0` or less prepends, past the end appends). */ | ||
| insertChildAt(node: Readonly<MdastNode>, index: number, childNode: MdastNode | MdastNode[]): void; | ||
| /** Remove the `index`-th child of `node`; a no-op when there is no such child. */ | ||
| removeChildAt(node: Readonly<MdastNode>, index: number): void; | ||
| replaceNode(node: Readonly<MdastNode>, newNode: MdastNode): void; | ||
@@ -37,0 +41,0 @@ setProperty<N extends MdastNode, K extends keyof N & string>(node: Readonly<N>, key: K, value: N[K]): void; |
@@ -58,2 +58,5 @@ import { materializeNode, TYPE_NAMES } from "./mdast-materializer.js"; | ||
| } | ||
| function asArray(value) { | ||
| return Array.isArray(value) ? value : [value]; | ||
| } | ||
| export class MdastVisitorContext { | ||
@@ -84,6 +87,10 @@ #commandBuffer = new CommandBuffer(); | ||
| insertBefore(node, newNode) { | ||
| this.#commandBuffer.insertBefore(nid(node), newNode); | ||
| const id = nid(node); | ||
| for (const n of asArray(newNode)) | ||
| this.#commandBuffer.insertBefore(id, n); | ||
| } | ||
| insertAfter(node, newNode) { | ||
| this.#commandBuffer.insertAfter(nid(node), newNode); | ||
| const id = nid(node); | ||
| for (const n of asArray(newNode)) | ||
| this.#commandBuffer.insertAfter(id, n); | ||
| } | ||
@@ -98,7 +105,30 @@ /** | ||
| prependChild(node, childNode) { | ||
| this.#commandBuffer.prependChild(nid(node), childNode); | ||
| const id = nid(node); | ||
| for (const n of asArray(childNode)) | ||
| this.#commandBuffer.prependChild(id, n); | ||
| } | ||
| appendChild(node, childNode) { | ||
| this.#commandBuffer.appendChild(nid(node), childNode); | ||
| const id = nid(node); | ||
| for (const n of asArray(childNode)) | ||
| this.#commandBuffer.appendChild(id, n); | ||
| } | ||
| /** Insert one node or an array at `index`; clamps (`0` or less prepends, past the end appends). */ | ||
| insertChildAt(node, index, childNode) { | ||
| const children = "children" in node ? node.children : []; | ||
| if (index <= 0 || children.length === 0) { | ||
| this.prependChild(node, childNode); | ||
| } | ||
| else if (index >= children.length) { | ||
| this.appendChild(node, childNode); | ||
| } | ||
| else { | ||
| this.insertBefore(children[index], childNode); | ||
| } | ||
| } | ||
| /** Remove the `index`-th child of `node`; a no-op when there is no such child. */ | ||
| removeChildAt(node, index) { | ||
| const child = "children" in node ? node.children[index] : undefined; | ||
| if (child) | ||
| this.removeNode(child); | ||
| } | ||
| replaceNode(node, newNode) { | ||
@@ -108,2 +138,9 @@ this.#commandBuffer.replace(nid(node), newNode); | ||
| setProperty(node, key, value) { | ||
| if (key === "children") { | ||
| // children is structural: set-children keeps the node and swaps only its | ||
| // child list (reused children keep their id). | ||
| const wrapper = refifyReusedNodes({ type: "root", children: value }, true); | ||
| this.#commandBuffer.setChildren(nid(node), JSON.stringify(wrapper)); | ||
| return; | ||
| } | ||
| if (key === "data") { | ||
@@ -403,2 +440,3 @@ // data is stored as JSON in the arena, serialize it for the command buffer | ||
| const kind = buf[pos]; | ||
| pos += 1; | ||
| // Only link/image references carry `referenceType`; the mdast spec | ||
@@ -409,2 +447,8 @@ // defines it for those two, not for `footnoteReference`. | ||
| } | ||
| // imageReference also carries `alt` (the serializer appends it). | ||
| if (nodeType === 18) { | ||
| const altLen = ru16(view, pos); | ||
| pos += 2; | ||
| node.alt = rstr(buf, pos, altLen); | ||
| } | ||
| break; | ||
@@ -411,0 +455,0 @@ } |
+6
-6
| { | ||
| "name": "satteri", | ||
| "version": "0.8.0", | ||
| "version": "0.8.1", | ||
| "description": "High-performance Markdown and MDX processing", | ||
@@ -83,7 +83,7 @@ "repository": { | ||
| "optionalDependencies": { | ||
| "@bruits/satteri-linux-x64-gnu": "0.8.0", | ||
| "@bruits/satteri-darwin-x64": "0.8.0", | ||
| "@bruits/satteri-darwin-arm64": "0.8.0", | ||
| "@bruits/satteri-win32-x64-msvc": "0.8.0", | ||
| "@bruits/satteri-wasm32-wasi": "0.8.0" | ||
| "@bruits/satteri-linux-x64-gnu": "0.8.1", | ||
| "@bruits/satteri-darwin-x64": "0.8.1", | ||
| "@bruits/satteri-darwin-arm64": "0.8.1", | ||
| "@bruits/satteri-win32-x64-msvc": "0.8.1", | ||
| "@bruits/satteri-wasm32-wasi": "0.8.1" | ||
| }, | ||
@@ -90,0 +90,0 @@ "scripts": { |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 3 instances
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 3 instances
237634
1.87%5561
1.87%