🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

satteri

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

satteri - npm Package Compare versions

Comparing version
0.6.3
to
0.7.0
+86
-5
dist/compile.d.ts

@@ -19,10 +19,86 @@ import type { MdastPluginInput, HastPluginInput } from "./plugin.js";

}
/**
* Per-backref callback. Invoked once per anchor in the footnotes section
* with 1-based `referenceNumber` and `rerunIndex` (1 on the first backref
* to that definition, 2 on the second, and so on). Must return the final
* string used as the backref content or `aria-label`.
*/
export type FootnoteBackrefCallback = (referenceNumber: number, rerunIndex: number) => string;
/**
* i18n strings for the GFM footnotes section. Mirrors `footnoteLabel`,
* `footnoteBackLabel`, and `footnoteBackContent` from remark-rehype.
*
* `backContent` and `backLabel` each accept either a template string with
* the `{reference}` placeholder (substituted with `1` or `1-2` to match
* remark-rehype's default suffix), or a callback receiving the raw
* `(referenceNumber, rerunIndex)` pair.
*
* Passing this object enables footnotes. To turn them off, use
* `gfm: { footnotes: false }`.
*/
export interface FootnoteOptions {
/** `<h2>` label opening the footnotes section. Default: `"Footnotes"`. */
label?: string;
/**
* Backref `<a>` content. Default: `"↩"`.
*
* Template form: the string is used as-is, and a `<sup>K</sup>` marker
* is auto-appended on reruns (k > 1). Callback form: returns the full
* content for each backref; no auto-sup is added.
*/
backContent?: string | FootnoteBackrefCallback;
/**
* Backref `aria-label`. Default: `"Back to reference {reference}"`.
*
* Template form: `{reference}` becomes `n` for the first backref, `n-K`
* for subsequent ones. Callback form: returns the `aria-label` string
* for each backref.
*/
backLabel?: string | FootnoteBackrefCallback;
}
/** Granular GFM toggles, nested under {@link Features.gfm}. */
export interface GfmOptions {
/**
* Enable GFM footnotes (`[^id]`). Default: true.
*
* Pass `false` to drop footnote parsing while keeping the rest of GFM;
* pass an object to enable footnotes with custom i18n strings (see
* {@link FootnoteOptions}).
*/
footnotes?: boolean | FootnoteOptions;
}
/** Granular math toggles, nested under {@link Features.math}. */
export interface MathOptions {
/**
* Treat single-dollar runs (`$ ... $`) as inline math. Default: true.
*
* Set `false` to keep single `$` as literal text while still parsing
* `$$ ... $$` display math. Mirrors `singleDollarTextMath` from
* remark-math.
*/
singleDollarTextMath?: boolean;
}
/** Parser feature toggles. All default to their documented value when omitted. */
export interface Features {
/** GFM: tables, footnotes, strikethrough, task lists. Default: true. */
gfm?: boolean;
/**
* GFM: tables, footnotes, strikethrough, task lists. Default: true.
*
* Pass an options object for granular control:
* ```ts
* gfm: { footnotes: false } // skip footnotes only
* gfm: { footnotes: { label: "Notes" } } // localize footnotes
* ```
*/
gfm?: boolean | GfmOptions;
/** Frontmatter: YAML (`--- ... ---`) and TOML (`+++ ... +++`). Default: true. */
frontmatter?: boolean;
/** Math blocks and inline math. Default: true. */
math?: boolean;
/**
* Math blocks and inline math. Default: true.
*
* Pass an options object for granular control:
* ```ts
* math: { singleDollarTextMath: false } // $$..$$ only, $..$ literal
* ```
*/
math?: boolean | MathOptions;
/** Heading attributes (`# text { #id .class }`). Default: true. */

@@ -52,3 +128,8 @@ headingAttributes?: boolean;

features?: Features;
filename?: string;
/**
* The document being processed, surfaced to plugins as `ctx.fileURL`. Must
* be a `URL` (e.g. Astro's `fileURL`); convert a filesystem path with Node's
* `pathToFileURL` before passing it.
*/
fileURL?: URL;
}

@@ -55,0 +136,0 @@ /**

+97
-52

@@ -8,12 +8,51 @@ import { visitHastHandle, resolveSubscriptions } from "./hast/hast-visitor.js";

import { materializeHastTree } from "./hast/hast-materializer.js";
/**
* Split the user-facing `Features` (with nested unions) into the flat napi
* `JsFeatures` shape plus the conversion-side `JsConvertOptions` carrying
* the footnote i18n strings. The public API only exposes `features`; the
* footnote strings are routed to napi internally.
*/
function featuresToNative(features) {
if (!features)
return undefined;
return { features: undefined, convertOptions: undefined };
const result = {};
if (features.gfm !== undefined)
result.gfm = features.gfm;
let convertOptions;
if (features.gfm !== undefined) {
if (typeof features.gfm === "object") {
const g = features.gfm;
const gfmOpts = {};
if (g.footnotes !== undefined) {
if (typeof g.footnotes === "object") {
gfmOpts.footnotes = true;
convertOptions = convertOptions ?? {};
if (g.footnotes.label !== undefined)
convertOptions.footnoteLabel = g.footnotes.label;
if (g.footnotes.backContent !== undefined)
convertOptions.footnoteBackContent = g.footnotes.backContent;
if (g.footnotes.backLabel !== undefined)
convertOptions.footnoteBackLabel = g.footnotes.backLabel;
}
else {
gfmOpts.footnotes = g.footnotes;
}
}
result.gfmOptions = gfmOpts;
}
else {
result.gfm = features.gfm;
}
}
if (features.frontmatter !== undefined)
result.frontmatter = features.frontmatter;
if (features.math !== undefined)
result.math = features.math;
if (features.math !== undefined) {
if (typeof features.math === "object") {
const mathOpts = {};
if (features.math.singleDollarTextMath !== undefined)
mathOpts.singleDollarTextMath = features.math.singleDollarTextMath;
result.mathOptions = mathOpts;
}
else {
result.math = features.math;
}
}
if (features.headingAttributes !== undefined)

@@ -37,37 +76,42 @@ result.headingAttributes = features.headingAttributes;

}
return result;
return { features: result, convertOptions };
}
function runMdastPluginsOnHandle(handle, plugins, filename) {
let pendingCommands = null;
function warnDroppedTransforms(plugin, dropped) {
const name = plugin.name ?? "<anonymous>";
const noun = dropped === 1 ? "transform" : "transforms";
console.warn(`satteri: plugin "${name}" queued ${dropped} mdast ${noun} on node(s) that were removed or ` +
`replaced earlier in the same pass; ${dropped === 1 ? "it was" : "they were"} dropped.`);
}
function runMdastPluginsOnHandle(handle, plugins, fileURL) {
// Each plugin runs once over the tree. A transform that passes a child
// through (returning it inside the replacement) keeps that child's identity,
// so a patch the same pass queued on it still applies — nesting composes in
// one pass. A plugin's own freshly-built nodes are not re-walked; transform
// them up front, or hand off to a later plugin that sees the materialized tree.
const runPlugin = (plugin) => {
const subs = resolveMdastSubscriptions(plugin);
const result = visitMdastHandle(handle, plugin, subs, () => getHandleSource(handle), fileURL);
const apply = (r) => {
if (!r.hasMutations)
return;
const dropped = applyCommandsToMdastHandle(handle, r.commandBuffer);
if (dropped)
warnDroppedTransforms(plugin, dropped);
};
return result instanceof Promise ? result.then(apply) : apply(result);
};
let i = 0;
const runNext = () => {
while (i < plugins.length) {
const idx = i++;
const raw = plugins[idx];
const raw = plugins[i++];
const plugin = typeof raw === "function" ? raw() : raw;
const subs = resolveMdastSubscriptions(plugin);
const result = visitMdastHandle(handle, plugin, subs, () => getHandleSource(handle), filename);
if (result instanceof Promise) {
return result.then((r) => {
applyMdastResult(r, idx, plugins.length, handle);
return runNext();
});
}
applyMdastResult(result, idx, plugins.length, handle);
const r = runPlugin(plugin);
if (r instanceof Promise)
return r.then(runNext);
}
return { handle, pendingCommands };
return { handle };
};
function applyMdastResult(result, idx, total, h) {
if (result.hasMutations) {
if (idx === total - 1) {
pendingCommands = result.commandBuffer;
}
else {
applyCommandsToMdastHandle(h, result.commandBuffer);
}
}
}
return runNext();
}
function runHastPluginsOnHandle(handle, plugins, source, filename) {
function runHastPluginsOnHandle(handle, plugins, source, fileURL) {
if (plugins.length === 0)

@@ -82,3 +126,3 @@ return;

const subs = resolveSubscriptions(plugin);
const result = visitHastHandle(handle, plugin, subs, source, filename);
const result = visitHastHandle(handle, plugin, subs, source, fileURL);
if (result instanceof Promise) {

@@ -135,5 +179,5 @@ return result.then(runNext);

export function markdownToHtml(source, options = {}) {
const { mdastPlugins = [], hastPlugins = [], features, filename = "<unknown>" } = options;
const nativeFeatures = featuresToNative(features);
const result = createHastHandleFromMdast(source, mdastPlugins, false, filename, nativeFeatures);
const { mdastPlugins = [], hastPlugins = [], features, fileURL } = options;
const { features: nativeFeatures, convertOptions: nativeConvertOptions } = featuresToNative(features);
const result = createHastHandleFromMdast(source, mdastPlugins, false, fileURL, nativeFeatures, nativeConvertOptions);
const renderAndDrop = (h, frontmatter) => {

@@ -151,3 +195,3 @@ try {

try {
hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, filename);
hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL);
}

@@ -171,6 +215,6 @@ catch (err) {

export function mdxToJs(source, options = {}) {
const { mdastPlugins = [], hastPlugins = [], features, filename = "<unknown>", ...mdxFields } = options;
const { mdastPlugins = [], hastPlugins = [], features, fileURL, ...mdxFields } = options;
const mdxOptions = mdxOptionsToNative(mdxFields);
const nativeFeatures = featuresToNative(features);
const result = createHastHandleFromMdast(source, mdastPlugins, true, filename, nativeFeatures);
const { features: nativeFeatures, convertOptions: nativeConvertOptions } = featuresToNative(features);
const result = createHastHandleFromMdast(source, mdastPlugins, true, fileURL, nativeFeatures, nativeConvertOptions);
const compileAndDrop = (h, frontmatter) => {

@@ -188,3 +232,3 @@ try {

try {
hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, filename);
hastResult = runHastPluginsOnHandle(r.hastHandle, hastPlugins, source, fileURL);
}

@@ -234,5 +278,7 @@ catch (err) {

* the yaml/toml node are reflected in the returned value. */
function createHastHandleFromMdast(source, mdastPlugins, mdx, filename,
function createHastHandleFromMdast(source, mdastPlugins, mdx, fileURL,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
nativeFeatures) {
nativeFeatures,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
nativeConvertOptions) {
const mdastHandle = mdx

@@ -245,7 +291,4 @@ ? createMdxMdastHandle(source, nativeFeatures)

try {
if (r.pendingCommands) {
applyCommandsToMdastHandle(r.handle, r.pendingCommands);
}
const frontmatter = readFrontmatter(r.handle);
const hastHandle = convertMdastToHastHandle(r.handle);
const hastHandle = convertMdastToHastHandle(r.handle, nativeConvertOptions);
return { hastHandle, frontmatter };

@@ -259,5 +302,5 @@ }

if (mdastPlugins.length === 0) {
return finalize({ handle: mdastHandle, pendingCommands: null });
return finalize({ handle: mdastHandle });
}
const mdastResult = runMdastPluginsOnHandle(mdastHandle, mdastPlugins, filename);
const mdastResult = runMdastPluginsOnHandle(mdastHandle, mdastPlugins, fileURL);
if (mdastResult instanceof Promise) {

@@ -279,3 +322,3 @@ return mdastResult.then(finalize, (err) => {

export function markdownToMdast(source, options = {}) {
const handle = createMdastHandle(source, featuresToNative(options.features));
const handle = createMdastHandle(source, featuresToNative(options.features).features);
try {

@@ -290,3 +333,3 @@ return materializeMdastTree(new MdastReader(serializeHandle(handle)));

export function mdxToMdast(source, options = {}) {
const handle = createMdxMdastHandle(source, featuresToNative(options.features));
const handle = createMdxMdastHandle(source, featuresToNative(options.features).features);
try {

@@ -301,3 +344,4 @@ return materializeMdastTree(new MdastReader(serializeHandle(handle)));

export function markdownToHast(source, options = {}) {
const handle = createHastHandle(source, featuresToNative(options.features));
const { features: nativeFeatures, convertOptions } = featuresToNative(options.features);
const handle = createHastHandle(source, nativeFeatures, convertOptions);
try {

@@ -312,3 +356,4 @@ return materializeHastTree(new HastReader(serializeHandle(handle)));

export function mdxToHast(source, options = {}) {
const handle = createMdxHastHandle(source, featuresToNative(options.features));
const { features: nativeFeatures, convertOptions } = featuresToNative(options.features);
const handle = createMdxHastHandle(source, nativeFeatures, convertOptions);
try {

@@ -315,0 +360,0 @@ return materializeHastTree(new HastReader(serializeHandle(handle)));

@@ -18,3 +18,8 @@ import { type HastNode } from "./hast-materializer.js";

readonly source: string;
readonly filename: string;
/**
* The URL of the document being processed (the compile `fileURL` option),
* or `undefined` when none was given. Use `fileURLToPath(ctx.fileURL)` for a
* decoded filesystem path.
*/
readonly fileURL: URL | undefined;
removeNode(node: Readonly<HastNode>): void;

@@ -74,3 +79,3 @@ replaceNode(node: Readonly<HastNode>, newNode: HastNode): void;

*/
export declare function visitHastHandle(handle: HastHandle, plugin: HastVisitorInstance, subs: ResolvedSubscription[], source: string | (() => string), filename: string): void | Promise<void>;
export declare function visitHastHandle(handle: HastHandle, plugin: HastVisitorInstance, subs: ResolvedSubscription[], source: string | (() => string), fileURL: URL | undefined): void | Promise<void>;
export {};

@@ -24,20 +24,33 @@ import { materializeHastNode } from "./hast-materializer.js";

}
/** Inject `_hast: true` marker on a HastNode and all its children for JSON serialization. */
/**
* Serialize a HastNode for the command buffer. Marks each node `_hast: true`,
* and — except at the root, which is the new replacement content — emits a
* reused (materialized) node as a `{ _ref: id }` placeholder so the rebuild
* splices the original in place (preserving its id, applying any pending patch
* on it) instead of rebuilding it fresh.
*/
function markHast(node) {
const n = node;
return markHastNode(node, true);
}
function markHastNode(node, isRoot) {
if (!isRoot) {
const id = nodeIdMap.get(node) ?? node._nodeId;
if (typeof id === "number")
return { _ref: id };
}
const obj = { _hast: true, type: node.type };
if ("tagName" in node)
obj.tagName = n.tagName;
obj.tagName = node.tagName;
if ("properties" in node)
obj.properties = n.properties;
obj.properties = node.properties;
if ("value" in node)
obj.value = n.value;
obj.value = node.value;
if ("name" in node)
obj.name = n.name;
obj.name = node.name;
if ("attributes" in node)
obj.attributes = n.attributes;
if ("data" in node && n.data != null)
obj.data = n.data;
obj.attributes = node.attributes;
if ("data" in node && node.data != null)
obj.data = node.data;
if ("children" in node) {
obj.children = n.children.map(markHast);
obj.children = node.children.map((c) => markHastNode(c, false));
}

@@ -56,7 +69,7 @@ return obj;

#getSource;
filename;
constructor(handle, getSource, filename) {
fileURL;
constructor(handle, getSource, fileURL) {
this.#handle = handle;
this.#getSource = getSource;
this.filename = filename;
this.fileURL = fileURL;
}

@@ -104,3 +117,4 @@ get source() {

// MDX JSX nodes use `attributes`, not `properties`, keep replaceNode path
const current = this.#pendingNodes.get(id) ?? node;
const pending = this.#pendingNodes.get(id);
const current = (pending ?? node);
const updated = { ...current };

@@ -115,3 +129,3 @@ const attrs = [...(updated.attributes ?? [])];

? value
: `${value}`;
: String(value);
attrs.push({ type: "mdxJsxAttribute", name: key, value: attrValue });

@@ -220,2 +234,17 @@ updated.attributes = attrs;

}
/** Decode the 24-byte position block written by `serialize_hast_node_inline`. */
function readPositionPrefix(view, offset) {
const startOffset = view.getUint32(offset, true);
const endOffset = view.getUint32(offset + 4, true);
const startLine = view.getUint32(offset + 8, true);
const startColumn = view.getUint32(offset + 12, true);
const endLine = view.getUint32(offset + 16, true);
const endColumn = view.getUint32(offset + 20, true);
if (startLine === 0 && startOffset === 0)
return undefined;
return {
start: { offset: startOffset, line: startLine, column: startColumn },
end: { offset: endOffset, line: endLine, column: endColumn },
};
}
/**

@@ -236,4 +265,2 @@ * Walk-path element node: uses prototype getters instead of per-instance

/** @internal */ _resolver;
/** @internal */ _dataPos;
/** @internal */ _dataLen;
get properties() {

@@ -259,18 +286,6 @@ const val = decodeProperties(this._view, this._buf, this._propsPos);

}
get data() {
if (this._dataPos < 0)
return undefined;
const val = JSON.parse(textDecoder.decode(this._buf.subarray(this._dataPos, this._dataPos + this._dataLen)));
Object.defineProperty(this, "data", {
value: val,
writable: true,
enumerable: true,
configurable: true,
});
return val;
}
}
/** Read a matched element node from the binary data section into a HastNode.
* Only tagName is decoded eagerly; properties, children, and data are lazy. */
function readElementFromBinary(view, buf, offset, nodeId, resolver) {
/** Read the tail of a matched element node (tag + properties).
* Common prelude (data/position/children) is already consumed by `readMatchedNode`. */
function readElementFromBinary(view, buf, offset, nodeId, resolver, position, childIds, data) {
let pos = offset;

@@ -282,33 +297,15 @@ // Eager: tagName (almost always accessed by visitors)

pos += tagLen;
// Pre-scan: find section byte offsets without decoding strings
const propsPos = pos;
const propCount = view.getUint16(pos, true);
pos += 2;
for (let i = 0; i < propCount; i++) {
const nLen = view.getUint16(pos, true);
pos += 2 + nLen + 1; // name + kind byte
const vLen = view.getUint16(pos, true);
pos += 2 + vLen; // value
}
const childCount = view.getUint16(pos, true);
pos += 2;
const childIdsPos = pos;
pos += childCount * 4;
const nodeDataLen = view.getUint32(pos, true);
pos += 4;
const nodeDataPos = nodeDataLen > 0 ? pos : -1;
// Collect child IDs for lazy materialization
const ids = [];
for (let i = 0; i < childCount; i++)
ids.push(view.getUint32(childIdsPos + i * 4, true));
// Build node using class (prototype getters, no per-instance defineProperty)
const node = new WalkElement();
node.tagName = tagName;
if (position !== undefined)
node.position = position;
if (data !== null)
node.data = data;
node._view = view;
node._buf = buf;
node._propsPos = propsPos;
node._childIds = ids;
node._childIds = childIds;
node._resolver = resolver;
node._dataPos = nodeDataPos;
node._dataLen = nodeDataLen;
nodeIdMap.set(node, nodeId);

@@ -326,6 +323,11 @@ return node;

};
function readTextFromBinary(view, buf, offset, nodeId, nodeType) {
function readTextFromBinary(view, buf, offset, nodeId, nodeType, position, data) {
const valLen = view.getUint32(offset, true);
const value = textDecoder.decode(buf.subarray(offset + 4, offset + 4 + valLen));
const node = { type: TEXT_NODE_TYPES[nodeType], value };
const base = { type: TEXT_NODE_TYPES[nodeType], value };
if (position !== undefined)
base.position = position;
if (data !== null)
base.data = data;
const node = base;
nodeIdMap.set(node, nodeId);

@@ -341,3 +343,3 @@ if (nodeType === HAST_MDX_FLOW_EXPRESSION || nodeType === HAST_MDX_TEXT_EXPRESSION) {

/** Read an MDX JSX element from the binary data section. */
function readMdxJsxFromBinary(view, buf, offset, nodeId, nodeType, resolver) {
function readMdxJsxFromBinary(view, buf, offset, nodeId, nodeType, resolver, position, childIds, data) {
let pos = offset;

@@ -349,3 +351,3 @@ // Name

pos += nameLen;
// Attributes: [kind: u8][nameLen: u16][name][valLen: u16][val]
// Attributes: [kind: u8][nameLen: u16][name][valLen: u32][val]
const attrCount = view.getUint16(pos, true);

@@ -384,3 +386,32 @@ pos += 2;

}
// Child IDs
const typeName = nodeType === HAST_MDX_JSX_ELEMENT ? "mdxJsxFlowElement" : "mdxJsxTextElement";
const base = { type: typeName, name, attributes };
if (position !== undefined)
base.position = position;
if (data !== null)
base.data = data;
nodeIdMap.set(base, nodeId);
makeLazyChildren(base, childIds, resolver);
return base;
}
function readMatchedNode(view, buf, offset, nodeId, nodeType, resolver) {
let pos = offset;
// Shared prelude (matches serialize_hast_node_inline / serialize_mdast_node_inline):
// [data_len: u32][data_bytes][position: 24B][child_count: u16][child_ids: N×u32]
// Data (JSON), eagerly parsed
const dataLen = view.getUint32(pos, true);
pos += 4;
let data = null;
if (dataLen > 0) {
const jsonStr = textDecoder.decode(buf.subarray(pos, pos + dataLen));
try {
data = JSON.parse(jsonStr);
}
catch {
/* ignore malformed JSON */
}
pos += dataLen;
}
const position = readPositionPrefix(view, pos);
pos += 24;
const childCount = view.getUint16(pos, true);

@@ -393,12 +424,5 @@ pos += 2;

}
const typeName = nodeType === HAST_MDX_JSX_ELEMENT ? "mdxJsxFlowElement" : "mdxJsxTextElement";
const node = { type: typeName, name, attributes };
nodeIdMap.set(node, nodeId);
makeLazyChildren(node, childIds, resolver);
resolver.attachLazyData(node, nodeId);
return node;
}
function readMatchedNode(view, buf, offset, nodeId, nodeType, resolver) {
// Dispatch to type-specific tail (pos now sits at the type-specific section)
if (nodeType === HAST_ELEMENT) {
return readElementFromBinary(view, buf, offset, nodeId, resolver);
return readElementFromBinary(view, buf, pos, nodeId, resolver, position, childIds, data);
}

@@ -411,9 +435,14 @@ else if (nodeType === HAST_TEXT ||

nodeType === HAST_MDX_ESM) {
return readTextFromBinary(view, buf, offset, nodeId, nodeType);
return readTextFromBinary(view, buf, pos, nodeId, nodeType, position, data);
}
else if (nodeType === HAST_MDX_JSX_ELEMENT || nodeType === HAST_MDX_JSX_TEXT_ELEMENT) {
return readMdxJsxFromBinary(view, buf, offset, nodeId, nodeType, resolver);
return readMdxJsxFromBinary(view, buf, pos, nodeId, nodeType, resolver, position, childIds, data);
}
// Fallback: minimal node
const node = { type: `unknown(${nodeType})` };
// Fallback: minimal node carrying whatever prelude data we found
const base = { type: `unknown(${nodeType})` };
if (position !== undefined)
base.position = position;
if (data !== null)
base.data = data;
const node = base;
nodeIdMap.set(node, nodeId);

@@ -546,5 +575,5 @@ return node;

*/
export function visitHastHandle(handle, plugin, subs, source, filename) {
export function visitHastHandle(handle, plugin, subs, source, fileURL) {
const getSource = typeof source === "function" ? source : () => source;
const ctx = new HastVisitorContextImpl(handle, getSource, filename);
const ctx = new HastVisitorContextImpl(handle, getSource, fileURL);
const returnBuffer = new CommandBuffer();

@@ -551,0 +580,0 @@ const resolver = new LazyChildResolver(handle);

@@ -16,4 +16,9 @@ import { CommandBuffer } from "../command-buffer.js";

#private;
readonly filename: string;
constructor(handle: MdastHandle, getSource: () => string, filename: string);
/**
* The URL of the document being processed (the compile `fileURL` option),
* or `undefined` when none was given. Use `fileURLToPath(ctx.fileURL)` for a
* decoded filesystem path.
*/
readonly fileURL: URL | undefined;
constructor(handle: MdastHandle, getSource: () => string, fileURL: URL | undefined);
get source(): string;

@@ -106,3 +111,3 @@ removeNode(node: Readonly<MdastNode>): void;

*/
export declare function visitMdastHandle(handle: MdastHandle, plugin: MdastPluginInstance, subs: MdastSubscription[], source: string | (() => string), filename: string): MdastVisitResult | Promise<MdastVisitResult>;
export declare function visitMdastHandle(handle: MdastHandle, plugin: MdastPluginInstance, subs: MdastSubscription[], source: string | (() => string), fileURL: URL | undefined): MdastVisitResult | Promise<MdastVisitResult>;
export {};

@@ -63,7 +63,12 @@ import { materializeNode, TYPE_NAMES } from "./mdast-materializer.js";

#getSource;
filename;
constructor(handle, getSource, filename) {
/**
* The URL of the document being processed (the compile `fileURL` option),
* or `undefined` when none was given. Use `fileURLToPath(ctx.fileURL)` for a
* decoded filesystem path.
*/
fileURL;
constructor(handle, getSource, fileURL) {
this.#handle = handle;
this.#getSource = getSource;
this.filename = filename;
this.fileURL = fileURL;
}

@@ -505,2 +510,32 @@ get source() {

* so that context mutations (e.g. setProperty) are not clobbered. */
/** The arena id of a node if it is an existing (materialized) node, else
* undefined for a freshly-built one. */
function reusedId(node) {
if (node === null || typeof node !== "object")
return undefined;
const id = nid(node);
return typeof id === "number" ? id : undefined;
}
/**
* Rewrite a returned replacement tree so every *reused* node (one that came
* from the arena, at any depth) becomes a `{ _ref: id }` placeholder. The
* rebuild splices those originals back in place, preserving their ids — so a
* patch a nested visitor queued on a passed-through child still lands, in the
* same pass. Freshly-built nodes serialize as before. The root is never reffed:
* it is the new shape replacing the visited node.
*/
function refifyReusedNodes(node, isRoot) {
if (node === null || typeof node !== "object")
return node;
if (!isRoot) {
const id = reusedId(node);
if (id !== undefined)
return { _ref: id };
}
const children = node.children;
if (Array.isArray(children)) {
return { ...node, children: children.map((c) => refifyReusedNodes(c, false)) };
}
return node;
}
function applyMdastVisitResult(result, nodeId, returnBuffer, originalNode) {

@@ -520,3 +555,3 @@ if (result === undefined || result === null)

case "structured_node":
returnBuffer.replace(nodeId, result);
returnBuffer.replace(nodeId, refifyReusedNodes(result, true));
break;

@@ -532,5 +567,5 @@ }

*/
export function visitMdastHandle(handle, plugin, subs, source, filename) {
export function visitMdastHandle(handle, plugin, subs, source, fileURL) {
const getSource = typeof source === "function" ? source : () => source;
const context = new MdastVisitorContext(handle, getSource, filename);
const context = new MdastVisitorContext(handle, getSource, fileURL);
const returnBuffer = new CommandBuffer();

@@ -537,0 +572,0 @@ const resolver = new MdastLazyChildResolver(handle);

@@ -7,3 +7,3 @@ /* auto-generated by NAPI-RS */

*/
export declare function applyCommandsAndConvertToHastHandle(handle: MdastHandle, commandBuf: Uint8Array): HastHandle
export declare function applyCommandsAndConvertToHastHandle(handle: MdastHandle, commandBuf: Uint8Array, convertOptions?: JsConvertOptions | undefined | null): HastHandle

@@ -13,4 +13,8 @@ /** Apply a command buffer to a HAST handle's arena in-place. */

/** Apply a command buffer to an MDAST handle in-place. */
export declare function applyCommandsToMdastHandle(handle: MdastHandle, commandBuf: Uint8Array): void
/**
* Apply a command buffer to an MDAST handle in-place. Returns how many patches
* were dropped because their target lived inside a subtree this pass removed or
* replaced (see the lenient note below); the JS pipeline warns when non-zero.
*/
export declare function applyCommandsToMdastHandle(handle: MdastHandle, commandBuf: Uint8Array): number

@@ -21,6 +25,6 @@ /** Compile a HAST handle's arena to MDX JavaScript. Does not consume the handle. */

/** Compile MDX source directly to JavaScript. */
export declare function compileMdx(source: string, options?: JsMdxOptions | undefined | null, features?: JsFeatures | undefined | null): string
export declare function compileMdx(source: string, options?: JsMdxOptions | undefined | null, features?: JsFeatures | undefined | null, convertOptions?: JsConvertOptions | undefined | null): string
/** Convert an MDAST handle to a HAST handle. The MDAST handle is consumed (emptied). */
export declare function convertMdastToHastHandle(handle: MdastHandle): HastHandle
export declare function convertMdastToHastHandle(handle: MdastHandle, convertOptions?: JsConvertOptions | undefined | null): HastHandle

@@ -31,3 +35,3 @@ /**

*/
export declare function createHastHandle(source: string, features?: JsFeatures | undefined | null): HastHandle
export declare function createHastHandle(source: string, features?: JsFeatures | undefined | null, convertOptions?: JsConvertOptions | undefined | null): HastHandle

@@ -38,3 +42,3 @@ /** Parse markdown source into an MDAST arena handle. */

/** Parse MDX source and convert to HAST. Returns an opaque handle. */
export declare function createMdxHastHandle(source: string, features?: JsFeatures | undefined | null): HastHandle
export declare function createMdxHastHandle(source: string, features?: JsFeatures | undefined | null, convertOptions?: JsConvertOptions | undefined | null): HastHandle

@@ -68,2 +72,21 @@ /** Parse MDX source into an MDAST arena handle. */

/**
* MDAST→HAST conversion options passed from JavaScript.
*
* Input-only: `object_to_js = false` because `FunctionRef` only crosses
* JS → Rust. A `JsConvertOptions` never gets serialized back to JS.
*/
export interface JsConvertOptions {
/** `<h2>` label opening the footnotes section. Default: `"Footnotes"`. */
footnoteLabel?: string
/** Backref `<a>` content. Default: `"\u{21a9}"` (↩). */
footnoteBackContent?: string | ((arg0: number, arg1: number) => string)
/**
* Backref `aria-label`. The token `{reference}` is replaced with the
* footnote number (`1`) or `number-K` (`1-2`) for repeated references.
* Default: `"Back to reference {reference}"`.
*/
footnoteBackLabel?: string | ((arg0: number, arg1: number) => string)
}
/** Feature toggles for the Markdown/MDX parser, passed from JavaScript. */

@@ -73,2 +96,4 @@ export interface JsFeatures {

gfm?: boolean
/** Granular GFM control (overrides `gfm`). */
gfmOptions?: JsGfmOptions
/** Frontmatter: YAML (`--- ... ---`) and TOML (`+++ ... +++`). Default: true. */

@@ -78,2 +103,4 @@ frontmatter?: boolean

math?: boolean
/** Granular math control (overrides `math`). */
mathOptions?: JsMathOptions
/** Heading attributes (`# text { #id .class }`). Default: true. */

@@ -103,2 +130,26 @@ headingAttributes?: boolean

/**
* Granular GFM toggles, nested under `features.gfm`. The footnote i18n
* strings (label, back-content, back-label) travel separately via the
* `JsConvertOptions` argument on conversion entry points; the JS package
* extracts them from `features.gfm.footnotes` before calling in.
*/
export interface JsGfmOptions {
/**
* Enable GFM footnotes (`[^id]`). Default: true. Set `false` to drop
* footnote parsing while keeping the rest of the GFM bundle.
*/
footnotes?: boolean
}
/** Granular math toggles, nested under `features.math`. */
export interface JsMathOptions {
/**
* Treat single-dollar runs (`$ ... $`) as inline math. Default: true.
* Set `false` to keep single `$` as literal text (prose with currency)
* while still parsing double-dollar (`$$ ... $$`) display math.
*/
singleDollarTextMath?: boolean
}
/** MDX compile options passed from JavaScript. */

@@ -201,3 +252,3 @@ export interface JsMdxOptions {

/** Parse Markdown source and return HTML string directly. */
export declare function parseToHtml(source: string, features?: JsFeatures | undefined | null): string
export declare function parseToHtml(source: string, features?: JsFeatures | undefined | null, convertOptions?: JsConvertOptions | undefined | null): string

@@ -204,0 +255,0 @@ /** Render a HAST handle's arena to HTML. Does not consume the handle. */

+52
-52

@@ -84,4 +84,4 @@ // prettier-ignore

const bindingPackageVersion = require('@bruits/satteri-android-arm64/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -101,4 +101,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-android-arm-eabi/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -123,4 +123,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-win32-x64-gnu/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -140,4 +140,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-win32-x64-msvc/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -158,4 +158,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-win32-ia32-msvc/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -175,4 +175,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-win32-arm64-msvc/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -195,4 +195,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-darwin-universal/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -212,4 +212,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-darwin-x64/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -229,4 +229,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-darwin-arm64/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -250,4 +250,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-freebsd-x64/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -267,4 +267,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-freebsd-arm64/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -289,4 +289,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-x64-musl/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -306,4 +306,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-x64-gnu/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -325,4 +325,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-arm64-musl/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -342,4 +342,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-arm64-gnu/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -361,4 +361,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-arm-musleabihf/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -378,4 +378,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-arm-gnueabihf/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -397,4 +397,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-loong64-musl/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -414,4 +414,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-loong64-gnu/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -433,4 +433,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-riscv64-musl/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -450,4 +450,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-riscv64-gnu/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -468,4 +468,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-ppc64-gnu/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -485,4 +485,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-linux-s390x-gnu/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -506,4 +506,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-openharmony-arm64/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -523,4 +523,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-openharmony-x64/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -540,4 +540,4 @@ return binding

const bindingPackageVersion = require('@bruits/satteri-openharmony-arm/package.json').version
if (bindingPackageVersion !== '0.6.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
if (bindingPackageVersion !== '0.6.3' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
throw new Error(`Native binding package version mismatch, expected 0.6.3 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
}

@@ -544,0 +544,0 @@ return binding

{
"name": "satteri",
"version": "0.6.3",
"version": "0.7.0",
"description": "High-performance Markdown and MDX processing",

@@ -83,7 +83,7 @@ "repository": {

"optionalDependencies": {
"@bruits/satteri-linux-x64-gnu": "0.6.3",
"@bruits/satteri-darwin-x64": "0.6.3",
"@bruits/satteri-darwin-arm64": "0.6.3",
"@bruits/satteri-win32-x64-msvc": "0.6.3",
"@bruits/satteri-wasm32-wasi": "0.6.3"
"@bruits/satteri-linux-x64-gnu": "0.7.0",
"@bruits/satteri-darwin-x64": "0.7.0",
"@bruits/satteri-darwin-arm64": "0.7.0",
"@bruits/satteri-win32-x64-msvc": "0.7.0",
"@bruits/satteri-wasm32-wasi": "0.7.0"
},

@@ -95,2 +95,4 @@ "scripts": {

"postbuild:binary:native": "node patch-binding.js",
"build:binary:native:lite": "napi build --manifest-path ../../crates/satteri-napi-binding/Cargo.toml --output-dir . --platform --release --esm --strip -- --no-default-features",
"postbuild:binary:native:lite": "node patch-binding.js",
"build:binary:native:cross": "napi build --manifest-path ../../crates/satteri-napi-binding/Cargo.toml --output-dir . --platform --release --esm --strip --cross-compile",

@@ -97,0 +99,0 @@ "postbuild:binary:native:cross": "node patch-binding.js",

@@ -166,2 +166,10 @@ # satteri

### How transforms compose
Unlike remark and rehype, which re-walk the tree until it stops changing, each Sätteri plugin walks the tree **once**. Within that single pass:
- **Passed-through children keep their identity.** When a visitor returns a replacement that reuses the original node's children (e.g. `{ ...node, children: [...node.children] }`), those children are spliced back unchanged — so a transform the same pass queues on a nested one still applies. This is what lets a `containerDirective` visitor turn both an outer `:::note` and a nested `:::tip` into asides in one go.
- **A plugin's own freshly-built nodes are not re-walked by that plugin.** If a visitor returns a brand-new node (one that didn't come from the tree), the same plugin won't visit it. Produce its final shape directly, or hand it off to a later plugin — every plugin runs over the fully materialized output of the ones before it.
- **Dropping a subtree drops transforms queued inside it.** If one visitor removes or replaces a node while another (in the same pass) had queued a transform on something inside that subtree, the orphaned transform is dropped and a warning is logged. This is usually intentional — you discarded that subtree on purpose — but the warning helps catch the cases where it isn't.
### Async plugins

@@ -293,3 +301,4 @@

hastPlugins?: HastPluginDefinition[];
filename?: string;
features?: Features;
fileURL?: URL;
}

@@ -303,4 +312,8 @@

`fileURL` is the `URL` of the document being processed, surfaced to plugins as `ctx.fileURL` (a `URL`, or `undefined` when omitted). Pass a file URL such as Astro's `fileURL`, or convert a filesystem path with Node's `pathToFileURL`; read it back with `fileURLToPath(ctx.fileURL)`.
`Features` controls the Markdown extensions Sätteri's parser recognizes: `gfm`, `frontmatter`, `math`, `directive`, `smartPunctuation`, etc. `gfm`, `math`, and `smartPunctuation` also accept granular options. For example, `math: { singleDollarTextMath: false }` keeps single `$` as literal text. See the [Features reference](https://satteri.dev/docs/features/) for the full list.
## License
MIT