satteri 0.1.1 → 0.2.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.
@@ -34,6 +34,12 @@ const MDX_ATTR_SPREAD = 3;
34
34
  // Total: 52 bytes
35
35
  const FIELD = {
36
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,
37
43
  children_start: 36,
38
44
  children_count: 40,
39
45
  data_offset: 44,
@@ -102,6 +108,27 @@ export class HastReader {
102
108
  const bytes = new Uint8Array(this.#view.buffer, this.#view.byteOffset + sourceOffset + offset, len);
103
109
  return this.#textDecoder.decode(bytes);
104
110
  }
111
+ /** Get position data for a node. */
112
+ getPosition(nodeId) {
113
+ const base = this.#header.nodesOffset + nodeId * this.#header.nodeStructSize;
114
+ const v = this.#view;
115
+ const startLine = v.getUint32(base + FIELD.start_line, true);
116
+ const startOffset = v.getUint32(base + FIELD.start_offset, true);
117
+ if (startLine === 0 && startOffset === 0)
118
+ return undefined;
119
+ return {
120
+ start: {
121
+ offset: startOffset,
122
+ line: startLine,
123
+ column: v.getUint32(base + FIELD.start_column, true),
124
+ },
125
+ end: {
126
+ offset: v.getUint32(base + FIELD.end_offset, true),
127
+ line: v.getUint32(base + FIELD.end_line, true),
128
+ column: v.getUint32(base + FIELD.end_column, true),
129
+ },
130
+ };
131
+ }
105
132
  /** Get the node_type byte for a given node ID. */
106
133
  getNodeType(nodeId) {
107
134
  const { nodesOffset, nodeStructSize } = this.#header;
@@ -15,19 +15,19 @@ export interface HastDiagnostic {
15
15
  export interface HastVisitorContext {
16
16
  readonly source: string;
17
17
  readonly filename: string;
18
- removeNode(node: HastNode): void;
19
- replaceNode(node: HastNode, newNode: HastNode): void;
20
- insertBefore(node: HastNode, newNode: HastNode): void;
21
- insertAfter(node: HastNode, newNode: HastNode): void;
22
- wrapNode(node: HastNode, parentNode: HastNode): void;
23
- prependChild(node: HastNode, childNode: HastNode): void;
24
- appendChild(node: HastNode, childNode: HastNode): void;
25
- setProperty(node: HastNode, key: string, value: unknown): void;
18
+ removeNode(node: Readonly<HastNode>): void;
19
+ replaceNode(node: Readonly<HastNode>, newNode: HastNode): void;
20
+ insertBefore(node: Readonly<HastNode>, newNode: HastNode): void;
21
+ insertAfter(node: Readonly<HastNode>, newNode: HastNode): void;
22
+ wrapNode(node: Readonly<HastNode>, parentNode: HastNode): void;
23
+ prependChild(node: Readonly<HastNode>, childNode: HastNode): void;
24
+ appendChild(node: Readonly<HastNode>, childNode: HastNode): void;
25
+ setProperty(node: Readonly<HastNode>, key: string, value: unknown): void;
26
26
  /** Collect the concatenated text of all descendant text nodes (like DOM textContent). */
27
- textContent(node: HastNode): string;
27
+ textContent(node: Readonly<HastNode>): string;
28
28
  report(opts: {
29
29
  message: string;
30
- node?: HastNode;
30
+ node?: Readonly<HastNode>;
31
31
  severity?: "error" | "warning" | "info";
32
32
  }): void;
33
33
  getDiagnostics(): HastDiagnostic[];
@@ -35,9 +35,9 @@ export interface HastVisitorContext {
35
35
  /** A filtered visitor: Rust filters by tag/component name, only matched nodes cross the boundary. */
36
36
  export interface HastFilteredVisitor<N extends HastNode = HastNode> {
37
37
  filter: string[];
38
- visit(node: N, ctx: HastVisitorContext): HastNode | void | Promise<HastNode | void>;
38
+ visit(node: Readonly<N>, ctx: HastVisitorContext): HastNode | void | Promise<HastNode | void>;
39
39
  }
40
- type HastVisitorFn<N extends HastNode = HastNode> = (node: N, ctx: HastVisitorContext) => HastNode | void | Promise<HastNode | void>;
40
+ type HastVisitorFn<N extends HastNode = HastNode> = (node: Readonly<N>, ctx: HastVisitorContext) => HastNode | void | Promise<HastNode | void>;
41
41
  export interface HastVisitorInstance {
42
42
  element?: HastFilteredVisitor<Element> | HastFilteredVisitor<Element>[];
43
43
  mdxJsxFlowElement?: HastFilteredVisitor<MdxJsxFlowElementHast> | HastFilteredVisitor<MdxJsxFlowElementHast>[];
@@ -1,7 +1,7 @@
1
1
  import { materializeHastNode } from "./hast-materializer.js";
2
2
  import { HastReader, 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";
3
3
  import { CommandBuffer } from "../command-buffer.js";
4
- import { walkHandle, applyCommandsToHandle, serializeHandle, textContentHandle, getNodeData as napiGetNodeData, parseExpression as napiParseExpression, } from "../../index.js";
4
+ import { walkHandle, applyCommandsToHandle, serializeHandle, textContentHandle, getNodeData as napiGetNodeData, parseExpression as napiParseExpression, } from "#binding";
5
5
  /** Maps HastNode objects to their arena node IDs without Object.defineProperty overhead. */
6
6
  const nodeIdMap = new WeakMap();
7
7
  /** Attach `parseExpression()` to an MDX expression node. */
@@ -374,7 +374,8 @@ function readMatchedNode(view, buf, offset, nodeId, nodeType, resolver) {
374
374
  nodeType === HAST_COMMENT ||
375
375
  nodeType === HAST_RAW ||
376
376
  nodeType === HAST_MDX_FLOW_EXPRESSION ||
377
- nodeType === HAST_MDX_TEXT_EXPRESSION) {
377
+ nodeType === HAST_MDX_TEXT_EXPRESSION ||
378
+ nodeType === HAST_MDX_ESM) {
378
379
  return readTextFromBinary(view, buf, offset, nodeId, nodeType);
379
380
  }
380
381
  else if (nodeType === HAST_MDX_JSX_ELEMENT || nodeType === HAST_MDX_JSX_TEXT_ELEMENT) {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,14 @@
1
- export { compileMarkdownToHtml, compileMdxToJs } from "./compile.js";
2
- export type { CompileOptions, OptimizeStaticConfig } from "./compile.js";
1
+ export { markdownToHtml, mdxToJs, markdownToMdast, mdxToMdast, markdownToHast, mdxToHast, } from "./compile.js";
2
+ export type { CompileOptions, MdxCompileOptions, OptimizeStaticConfig, Features, } from "./compile.js";
3
3
  export { defineMdastPlugin, defineHastPlugin } from "./plugin.js";
4
4
  export type { MdastPluginDefinition, HastPluginDefinition } from "./plugin.js";
5
5
  export type { HastVisitorInstance, HastVisitorContext, HastFilteredVisitor, EstreeProgram, } from "./hast/hast-visitor.js";
6
6
  export type { MdastNode, HastNode, Position, Point, MdxJsxAttributeNode, MdxJsxExpressionAttributeNode, MdxJsxAttributeValueExpressionNode, MdxJsxAttributeUnion, } from "./types.js";
7
+ export { visitMdastHandle, resolveMdastSubscriptions } from "./mdast/mdast-visitor.js";
8
+ export type { MdastPluginInstance } from "./mdast/mdast-visitor.js";
9
+ export { visitHastHandle, resolveSubscriptions as resolveHastSubscriptions, } from "./hast/hast-visitor.js";
10
+ export { MdastReader } from "./mdast/mdast-reader.js";
11
+ export { materializeMdastTree } from "./mdast/mdast-materializer.js";
12
+ export { HastReader } from "./hast/hast-reader.js";
13
+ export { materializeHastTree } from "./hast/hast-materializer.js";
14
+ export { createMdastHandle, createMdxMdastHandle, createHastHandle, createMdxHastHandle, convertMdastToHastHandle, serializeMdastHandle, serializeHandle, renderHandle, compileHandle, dropHandle, applyCommandsToMdastHandle, applyCommandsAndConvertToHastHandle, getHandleSource, } from "#binding";
package/dist/index.js CHANGED
@@ -1,4 +1,13 @@
1
1
  // Public API: compile functions
2
- export { compileMarkdownToHtml, compileMdxToJs } from "./compile.js";
2
+ export { markdownToHtml, mdxToJs, markdownToMdast, mdxToMdast, markdownToHast, mdxToHast, } from "./compile.js";
3
3
  // Plugin definitions
4
4
  export { defineMdastPlugin, defineHastPlugin } from "./plugin.js";
5
+ // Visitor pipeline (for manual plugin execution)
6
+ export { visitMdastHandle, resolveMdastSubscriptions } from "./mdast/mdast-visitor.js";
7
+ export { visitHastHandle, resolveSubscriptions as resolveHastSubscriptions, } from "./hast/hast-visitor.js";
8
+ // Step-by-step API: readers, materializers, and handle functions
9
+ export { MdastReader } from "./mdast/mdast-reader.js";
10
+ export { materializeMdastTree } from "./mdast/mdast-materializer.js";
11
+ export { HastReader } from "./hast/hast-reader.js";
12
+ export { materializeHastTree } from "./hast/hast-materializer.js";
13
+ export { createMdastHandle, createMdxMdastHandle, createHastHandle, createMdxHastHandle, convertMdastToHastHandle, serializeMdastHandle, serializeHandle, renderHandle, compileHandle, dropHandle, applyCommandsToMdastHandle, applyCommandsAndConvertToHastHandle, getHandleSource, } from "#binding";
@@ -1,9 +1,9 @@
1
1
  import type { MdastNode } from "../types.js";
2
- import type { ArenaReader } from "./mdast-reader.js";
2
+ import type { MdastReader } from "./mdast-reader.js";
3
3
  export declare const TYPE_NAMES: Record<number, string>;
4
4
  /**
5
5
  * Materialize a single MDAST node from a binary buffer as a lazy JS object.
6
6
  */
7
- export declare function materializeNode(reader: ArenaReader, nodeId: number): MdastNode;
7
+ export declare function materializeNode(reader: MdastReader, nodeId: number): MdastNode;
8
8
  /** Materialize the full tree from root (nodeId=0). */
9
- export declare function materializeTree(reader: ArenaReader): MdastNode;
9
+ export declare function materializeMdastTree(reader: MdastReader): MdastNode;
@@ -156,6 +156,6 @@ export function materializeNode(reader, nodeId) {
156
156
  return node;
157
157
  }
158
158
  /** Materialize the full tree from root (nodeId=0). */
159
- export function materializeTree(reader) {
159
+ export function materializeMdastTree(reader) {
160
160
  return materializeNode(reader, 0);
161
161
  }
@@ -36,7 +36,7 @@ export declare const NodeType: Readonly<{
36
36
  readonly MdxjsEsm: 104;
37
37
  }>;
38
38
  export declare const NodeTypeName: Record<number, string>;
39
- export declare class ArenaReader {
39
+ export declare class MdastReader {
40
40
  #private;
41
41
  constructor(buffer: ArrayBuffer | Uint8Array);
42
42
  get nodeCount(): number;
@@ -84,7 +84,7 @@ const FIELD = {
84
84
  // source_offset: u32 @ 40
85
85
  // Total: 44 bytes
86
86
  const MAGIC = 0x5241444d; // "MDAR" bytes [0x4d,0x44,0x41,0x52] read as little-endian u32
87
- export class ArenaReader {
87
+ export class MdastReader {
88
88
  #view;
89
89
  #header;
90
90
  #textDecoder;
@@ -15,22 +15,22 @@ export declare class MdastVisitorContext {
15
15
  readonly source: string;
16
16
  readonly filename: string;
17
17
  constructor(handle: MdastHandle, source: string, filename: string);
18
- removeNode(node: MdastNode): void;
19
- insertBefore(node: MdastNode, newNode: MdastNode): void;
20
- insertAfter(node: MdastNode, newNode: MdastNode): void;
21
- wrapNode(node: MdastNode, parentNode: MdastNode): void;
22
- prependChild(node: MdastNode, childNode: MdastNode): void;
23
- appendChild(node: MdastNode, childNode: MdastNode): void;
24
- replaceNode(node: MdastNode, newNode: MdastNode): void;
25
- setProperty(node: MdastNode, key: string, value: unknown): void;
18
+ removeNode(node: Readonly<MdastNode>): void;
19
+ insertBefore(node: Readonly<MdastNode>, newNode: MdastNode): void;
20
+ insertAfter(node: Readonly<MdastNode>, newNode: MdastNode): void;
21
+ wrapNode(node: Readonly<MdastNode>, parentNode: MdastNode): void;
22
+ prependChild(node: Readonly<MdastNode>, childNode: MdastNode): void;
23
+ appendChild(node: Readonly<MdastNode>, childNode: MdastNode): void;
24
+ replaceNode(node: Readonly<MdastNode>, newNode: MdastNode): void;
25
+ setProperty<N extends MdastNode, K extends keyof N & string>(node: Readonly<N>, key: K, value: N[K]): void;
26
26
  /** Collect the concatenated text of all descendant text nodes (like mdast-util-to-string). */
27
- textContent(node: MdastNode, options?: {
27
+ textContent(node: Readonly<MdastNode>, options?: {
28
28
  includeImageAlt?: boolean;
29
29
  includeHtml?: boolean;
30
30
  }): string;
31
31
  report({ message, node, severity, }: {
32
32
  message: string;
33
- node?: MdastNode;
33
+ node?: Readonly<MdastNode>;
34
34
  severity?: "error" | "warning" | "info";
35
35
  }): void;
36
36
  /** Get the binary command buffer for all mutations recorded via context methods. */
@@ -42,7 +42,7 @@ type MdastVisitorResult = MdastNode | {
42
42
  } | {
43
43
  rawHtml: string;
44
44
  } | undefined | null | void;
45
- type MdastVisitorFn<N extends MdastNode = MdastNode> = (node: N, context: MdastVisitorContext) => MdastVisitorResult | Promise<MdastVisitorResult>;
45
+ type MdastVisitorFn<N extends MdastNode = MdastNode> = (node: Readonly<N>, context: MdastVisitorContext) => MdastVisitorResult | Promise<MdastVisitorResult>;
46
46
  export interface MdastPluginInstance {
47
47
  root?: MdastVisitorFn<Root>;
48
48
  paragraph?: MdastVisitorFn<Paragraph>;
@@ -1,7 +1,7 @@
1
1
  import { materializeNode, TYPE_NAMES } from "./mdast-materializer.js";
2
- import { ArenaReader } from "./mdast-reader.js";
2
+ import { MdastReader } from "./mdast-reader.js";
3
3
  import { CommandBuffer, classifyReturn } from "../command-buffer.js";
4
- import { walkMdastHandle, serializeMdastHandle, getNodeData as napiGetNodeData, setNodeData, mdastTextContentHandle, } from "../../index.js";
4
+ import { walkMdastHandle, serializeMdastHandle, getNodeData as napiGetNodeData, mdastTextContentHandle, } from "#binding";
5
5
  const MutationType = {
6
6
  Replace: "replace",
7
7
  Remove: "remove",
@@ -86,6 +86,11 @@ export class MdastVisitorContext {
86
86
  this.#commandBuffer.replace(nid(node), newNode);
87
87
  }
88
88
  setProperty(node, key, value) {
89
+ if (key === "data") {
90
+ // data is stored as JSON in the arena, serialize it for the command buffer
91
+ this.#commandBuffer.setProperty(nid(node), key, value != null ? JSON.stringify(value) : null);
92
+ return;
93
+ }
89
94
  this.#commandBuffer.setProperty(nid(node), key, value);
90
95
  }
91
96
  /** Collect the concatenated text of all descendant text nodes (like mdast-util-to-string). */
@@ -164,7 +169,7 @@ function rstr(buf, off, len) {
164
169
  /**
165
170
  * Lazy child materializer for the MDAST handle walk path.
166
171
  * Serializes the handle once on first child access, then materializes
167
- * children via ArenaReader + materializeNode.
172
+ * children via MdastReader + materializeNode.
168
173
  */
169
174
  class MdastLazyChildResolver {
170
175
  #handle;
@@ -174,7 +179,7 @@ class MdastLazyChildResolver {
174
179
  }
175
180
  #ensure() {
176
181
  if (!this.#reader) {
177
- this.#reader = new ArenaReader(serializeMdastHandle(this.#handle));
182
+ this.#reader = new MdastReader(serializeMdastHandle(this.#handle));
178
183
  }
179
184
  return this.#reader;
180
185
  }
@@ -209,7 +214,7 @@ class MdastLazyChildResolver {
209
214
  * [node_data: u32+bytes][position: 6×u32 = 24B][child_count: u16][child_ids: N×u32][type-specific data]
210
215
  */
211
216
  const encoder = new TextEncoder();
212
- function readMdastMatchedNode(view, buf, dataOffset, nodeId, nodeType, dirtyData, resolver) {
217
+ function readMdastMatchedNode(view, buf, dataOffset, nodeId, nodeType, resolver) {
213
218
  let pos = dataOffset;
214
219
  // Node data (JSON bytes), always first
215
220
  const dataJsonLen = ru32(view, pos);
@@ -452,26 +457,9 @@ function readMdastMatchedNode(view, buf, dataOffset, nodeId, nodeType, dirtyData
452
457
  // strong(12), break(14), tableRow(22), tableCell(23), delete(24): no extra data
453
458
  }
454
459
  mdastNodeIdMap.set(node, nodeId);
455
- // Read inline node_data JSON from the end of the data section.
456
- // The Rust serializer always appends [json_len: u32][json_bytes...] at the end.
457
- // We need to find it by reading from dataEnd backwards.
458
- // Actually, we read it at `dataOffset + dataLen - (4 + jsonDataLen)` but we don't
459
- // know jsonDataLen yet. Instead, the data section ends with [len: u32][bytes...],
460
- // so we scan from the current end of type-specific data.
461
- // For simplicity, we'll handle this in the caller which knows the full data_len.
462
- // Set up data getter/setter that tracks dirty entries
463
- let currentData = initialData;
464
- Object.defineProperty(node, "data", {
465
- get() {
466
- return currentData;
467
- },
468
- set(value) {
469
- currentData = value;
470
- dirtyData.set(nodeId, value);
471
- },
472
- configurable: true,
473
- enumerable: true,
474
- });
460
+ if (initialData) {
461
+ node.data = initialData;
462
+ }
475
463
  return node;
476
464
  }
477
465
  /** Apply a sync visitor result to the return buffer.
@@ -505,7 +493,6 @@ function applyMdastVisitResult(result, nodeId, returnBuffer, originalNode) {
505
493
  export function visitMdastHandle(handle, plugin, subs, source, filename) {
506
494
  const context = new MdastVisitorContext(handle, source, filename);
507
495
  const returnBuffer = new CommandBuffer();
508
- const dirtyData = new Map();
509
496
  const resolver = new MdastLazyChildResolver(handle);
510
497
  const rustSubs = subs.map((s) => ({ nodeType: s.nodeType, tagFilter: [] }));
511
498
  const matchBuf = walkMdastHandle(handle, rustSubs);
@@ -518,7 +505,7 @@ export function visitMdastHandle(handle, plugin, subs, source, filename) {
518
505
  const subIndex = matchBuf[indexBase + 4];
519
506
  const dataOffset = ru32(matchView, indexBase + 6);
520
507
  const sub = subs[subIndex];
521
- const node = readMdastMatchedNode(matchView, matchBuf, dataOffset, nodeId, sub.nodeType, dirtyData, resolver);
508
+ const node = readMdastMatchedNode(matchView, matchBuf, dataOffset, nodeId, sub.nodeType, resolver);
522
509
  const result = sub.visitFn.call(plugin, node, context);
523
510
  if (result instanceof Promise) {
524
511
  deferred ??= [];
@@ -533,16 +520,12 @@ export function visitMdastHandle(handle, plugin, subs, source, filename) {
533
520
  for (const { nodeId, result, originalNode } of results) {
534
521
  applyMdastVisitResult(result, nodeId, returnBuffer, originalNode);
535
522
  }
536
- return finalizeMdastVisit(handle, context, returnBuffer, dirtyData);
523
+ return finalizeMdastVisit(handle, context, returnBuffer);
537
524
  });
538
525
  }
539
- return finalizeMdastVisit(handle, context, returnBuffer, dirtyData);
526
+ return finalizeMdastVisit(handle, context, returnBuffer);
540
527
  }
541
- function finalizeMdastVisit(handle, context, returnBuffer, dirtyData) {
542
- for (const [id, value] of dirtyData) {
543
- const json = value ? JSON.stringify(value) : "";
544
- setNodeData(handle, id, encoder.encode(json));
545
- }
528
+ function finalizeMdastVisit(handle, context, returnBuffer) {
546
529
  const { merged, hasMutations } = mergeAndReset(returnBuffer, context);
547
530
  return { commandBuffer: merged, diagnostics: context.getDiagnostics(), hasMutations };
548
531
  }
package/dist/plugin.d.ts CHANGED
@@ -1,12 +1,10 @@
1
1
  import type { MdastPluginInstance } from "./mdast/mdast-visitor.js";
2
2
  import type { HastVisitorInstance } from "./hast/hast-visitor.js";
3
- export interface MdastPluginDefinition {
3
+ export type MdastPluginDefinition = MdastPluginInstance & {
4
4
  name: string;
5
- createOnce(): MdastPluginInstance;
6
- }
7
- export interface HastPluginDefinition {
5
+ };
6
+ export type HastPluginDefinition = HastVisitorInstance & {
8
7
  name: string;
9
- createOnce(): HastVisitorInstance;
10
- }
8
+ };
11
9
  export declare function defineMdastPlugin(definition: MdastPluginDefinition): MdastPluginDefinition;
12
10
  export declare function defineHastPlugin(definition: HastPluginDefinition): HastPluginDefinition;
package/dist/plugin.js CHANGED
@@ -2,17 +2,11 @@ export function defineMdastPlugin(definition) {
2
2
  if (!definition.name) {
3
3
  throw new Error("Plugin definition must have a name");
4
4
  }
5
- if (typeof definition.createOnce !== "function") {
6
- throw new Error("Plugin definition must have a createOnce function");
7
- }
8
5
  return definition;
9
6
  }
10
7
  export function defineHastPlugin(definition) {
11
8
  if (!definition.name) {
12
9
  throw new Error("Plugin definition must have a name");
13
10
  }
14
- if (typeof definition.createOnce !== "function") {
15
- throw new Error("Plugin definition must have a createOnce function");
16
- }
17
11
  return definition;
18
12
  }
package/dist/types.js CHANGED
@@ -1,5 +1 @@
1
- // Shared types for the satteri JS layer.
2
- //
3
- // Uses standard @types/mdast, @types/hast, and mdast-util-mdx-* packages
4
- // for AST node types. Extension types (toml, math, raw) are augmented here.
5
1
  export {};
package/index.d.ts CHANGED
@@ -16,7 +16,7 @@ export declare function applyCommandsToMdastHandle(handle: ArenaHandle, commandB
16
16
  export declare function compileHandle(handle: ArenaHandle, options?: JsMdxOptions | undefined | null): string
17
17
 
18
18
  /** Compile MDX source directly to JavaScript. */
19
- export declare function compileMdx(source: string, options?: JsMdxOptions | undefined | null): string
19
+ export declare function compileMdx(source: string, options?: JsMdxOptions | undefined | null, features?: JsFeatures | undefined | null): string
20
20
 
21
21
  /** Convert an MDAST handle to a HAST handle. The MDAST handle is consumed (emptied). */
22
22
  export declare function convertMdastToHastHandle(handle: ArenaHandle): ArenaHandle
@@ -25,16 +25,16 @@ export declare function convertMdastToHastHandle(handle: ArenaHandle): ArenaHand
25
25
  * Parse markdown source and convert to HAST. Returns an opaque handle.
26
26
  * The arena stays in Rust memory, no buffer is copied to JS.
27
27
  */
28
- export declare function createHastHandle(source: string): ArenaHandle
28
+ export declare function createHastHandle(source: string, features?: JsFeatures | undefined | null): ArenaHandle
29
29
 
30
30
  /** Parse markdown source into an MDAST arena handle. */
31
- export declare function createMdastHandle(source: string): ArenaHandle
31
+ export declare function createMdastHandle(source: string, features?: JsFeatures | undefined | null): ArenaHandle
32
32
 
33
33
  /** Parse MDX source and convert to HAST. Returns an opaque handle. */
34
- export declare function createMdxHastHandle(source: string): ArenaHandle
34
+ export declare function createMdxHastHandle(source: string, features?: JsFeatures | undefined | null): ArenaHandle
35
35
 
36
36
  /** Parse MDX source into an MDAST arena handle. */
37
- export declare function createMdxMdastHandle(source: string): ArenaHandle
37
+ export declare function createMdxMdastHandle(source: string, features?: JsFeatures | undefined | null): ArenaHandle
38
38
 
39
39
  /**
40
40
  * Release the arena memory held by a handle. The handle becomes empty
@@ -48,6 +48,33 @@ export declare function getHandleSource(handle: ArenaHandle): string
48
48
  /** Read the node_data JSON blob for a node. Returns null if none is set. */
49
49
  export declare function getNodeData(handle: ArenaHandle, nodeId: number): string | null
50
50
 
51
+ /** Feature toggles for the Markdown/MDX parser, passed from JavaScript. */
52
+ export interface JsFeatures {
53
+ /**
54
+ * GFM: tables, footnotes, strikethrough, task lists, blockquote tags.
55
+ * Default: true.
56
+ */
57
+ gfm?: boolean
58
+ /** Frontmatter: YAML (`--- ... ---`) and TOML (`+++ ... +++`). Default: true. */
59
+ frontmatter?: boolean
60
+ /** Math blocks and inline math (`$$ ... $$`, `$ ... $`). Default: true. */
61
+ math?: boolean
62
+ /** Heading attributes (`# text { #id .class }`). Default: true. */
63
+ headingAttributes?: boolean
64
+ /** Colon-delimited container directive blocks (`:::`). Default: false. */
65
+ directive?: boolean
66
+ /** Superscript (`^super^`). Default: false. */
67
+ superscript?: boolean
68
+ /** Subscript (`~sub~`). Default: false. */
69
+ subscript?: boolean
70
+ /** Obsidian-style wikilinks (`[[link]]`). Default: false. */
71
+ wikilinks?: boolean
72
+ /** Smart punctuation (ligatures, smart quotes). Default: false. */
73
+ smartPunctuation?: boolean
74
+ /** Definition lists. Default: false. */
75
+ definitionList?: boolean
76
+ }
77
+
51
78
  /** MDX compile options passed from JavaScript. */
52
79
  export interface JsMdxOptions {
53
80
  /**
@@ -55,6 +82,28 @@ export interface JsMdxOptions {
55
82
  * into raw HTML strings using the specified component and prop.
56
83
  */
57
84
  optimizeStatic?: JsOptimizeStaticConfig
85
+ /**
86
+ * Place to import automatic JSX runtimes from (e.g. "react", "preact").
87
+ * Default: "react".
88
+ */
89
+ jsxImportSource?: string
90
+ /** Whether to keep JSX instead of compiling it away. Default: false. */
91
+ jsx?: boolean
92
+ /** JSX runtime: "automatic" (default) or "classic". */
93
+ jsxRuntime?: string
94
+ /**
95
+ * Whether to add extra info to error messages and use the development
96
+ * JSX runtime. Default: false.
97
+ */
98
+ development?: boolean
99
+ /** Place to import a provider from (e.g. "@mdx-js/react"). */
100
+ providerImportSource?: string
101
+ /** Pragma for JSX in classic runtime (default: "React.createElement"). */
102
+ pragma?: string
103
+ /** Pragma for JSX fragments in classic runtime (default: "React.Fragment"). */
104
+ pragmaFrag?: string
105
+ /** Where to import the pragma from in classic runtime (default: "react"). */
106
+ pragmaImportSource?: string
58
107
  }
59
108
 
60
109
  /** Static optimization config passed from JavaScript. */
@@ -99,7 +148,7 @@ export declare function parseExpression(source: string): string | null
99
148
  * Parse Markdown source and return HTML string directly.
100
149
  * Uses pulldown-cmark's streaming renderer, skipping the arena entirely.
101
150
  */
102
- export declare function parseToHtml(source: string): string
151
+ export declare function parseToHtml(source: string, features?: JsFeatures | undefined | null): string
103
152
 
104
153
  /** Render a handle's HAST arena to HTML. Does not consume the handle. */
105
154
  export declare function renderHandle(handle: ArenaHandle): string