@ai-markdown/core 3.0.2 → 3.1.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/dist/index.d.cts CHANGED
@@ -50,9 +50,9 @@ interface BlockInfo {
50
50
  * smaller than the container's end — maxEnd alone misses that case);
51
51
  * - the explicit dataFootnotes bit closes the degenerate corner where a
52
52
  * swallowed section and later real children tie on both numbers;
53
- * - a hash of the swallowed extent's SOURCE (`[ownEnd, maxEnd)`) catches
54
- * an equal-length, equal-shape single-frame replacement of the
55
- * swallowed siblings, which leaves every count unchanged.
53
+ * - a hash of the swallowed extent's SOURCE (`[ownEnd, maxEnd)`) quickly
54
+ * rejects most equal-length, equal-shape replacements. A matching hash
55
+ * still requires an exact {@link BlockInfo.swallowedSource} comparison.
56
56
  *
57
57
  * Markdown-native blocks (paragraph/list/math/code/…) never receive
58
58
  * reparented content — every hast descendant derives from their own mdast
@@ -60,6 +60,14 @@ interface BlockInfo {
60
60
  * per-frame cost away from huge deterministic subtrees like KaTeX output.
61
61
  */
62
62
  hastDigest?: string;
63
+ /**
64
+ * Exact source in the swallowed interval `[ownEnd, maxEnd)` of a raw-HTML
65
+ * block. The FNV-1a 32-bit hash in `hastDigest` can collide for different
66
+ * equal-length contents, so a cache hit must compare this string too.
67
+ * Empty when the block swallowed no source; absent for markdown-native
68
+ * blocks. Optional to keep existing public block-plan producers compatible.
69
+ */
70
+ swallowedSource?: string;
63
71
  /** A raw-HTML container that swallowed the synthesized
64
72
  * `<section data-footnotes>` (rehype-raw reparents the following siblings
65
73
  * into an unclosed `<details>` / `<div>` mid-stream). The footer is then
@@ -474,6 +482,23 @@ interface PipelineFrameOptions {
474
482
  /** False for a one-shot server render; no browser-global probe is needed. */
475
483
  incrementalParse: boolean;
476
484
  defListEnabled: boolean;
485
+ /** Whether `remarkPlugins` parses GFM task-list items. Default `false`
486
+ * (the boundary scanner keeps every `[x]` as reference taint). The
487
+ * adapters pass `true` because they build the chain with
488
+ * `buildCoreRemarkPlugins`, which always includes remark-gfm. A box
489
+ * whose paragraph a `$$` opener closed is released only when
490
+ * `mathFlow` is `true` as well. */
491
+ gfmTaskListItems?: boolean;
492
+ /** Whether `remarkPlugins` parses `$$` flow math (remark-math). Passed
493
+ * through to the engine in all three states: `true` declares it (a
494
+ * `$$` region is verbatim math), `false` declares its absence (`$$`
495
+ * lines are paragraph text), and omitted leaves it unknown — the
496
+ * scanner then takes the union of both grammars, which is correct for
497
+ * either chain and freezes less around `$$`. The adapters pass `true`
498
+ * because `buildCoreRemarkPlugins` always includes remark-math; a
499
+ * caller with its own chain should declare the real value and may
500
+ * leave it out when unsure. */
501
+ mathFlow?: boolean;
477
502
  measure?: AdvanceOptions['measure'];
478
503
  }
479
504
  declare function createPipelineSession(): PipelineSession;
package/dist/index.d.ts CHANGED
@@ -50,9 +50,9 @@ interface BlockInfo {
50
50
  * smaller than the container's end — maxEnd alone misses that case);
51
51
  * - the explicit dataFootnotes bit closes the degenerate corner where a
52
52
  * swallowed section and later real children tie on both numbers;
53
- * - a hash of the swallowed extent's SOURCE (`[ownEnd, maxEnd)`) catches
54
- * an equal-length, equal-shape single-frame replacement of the
55
- * swallowed siblings, which leaves every count unchanged.
53
+ * - a hash of the swallowed extent's SOURCE (`[ownEnd, maxEnd)`) quickly
54
+ * rejects most equal-length, equal-shape replacements. A matching hash
55
+ * still requires an exact {@link BlockInfo.swallowedSource} comparison.
56
56
  *
57
57
  * Markdown-native blocks (paragraph/list/math/code/…) never receive
58
58
  * reparented content — every hast descendant derives from their own mdast
@@ -60,6 +60,14 @@ interface BlockInfo {
60
60
  * per-frame cost away from huge deterministic subtrees like KaTeX output.
61
61
  */
62
62
  hastDigest?: string;
63
+ /**
64
+ * Exact source in the swallowed interval `[ownEnd, maxEnd)` of a raw-HTML
65
+ * block. The FNV-1a 32-bit hash in `hastDigest` can collide for different
66
+ * equal-length contents, so a cache hit must compare this string too.
67
+ * Empty when the block swallowed no source; absent for markdown-native
68
+ * blocks. Optional to keep existing public block-plan producers compatible.
69
+ */
70
+ swallowedSource?: string;
63
71
  /** A raw-HTML container that swallowed the synthesized
64
72
  * `<section data-footnotes>` (rehype-raw reparents the following siblings
65
73
  * into an unclosed `<details>` / `<div>` mid-stream). The footer is then
@@ -474,6 +482,23 @@ interface PipelineFrameOptions {
474
482
  /** False for a one-shot server render; no browser-global probe is needed. */
475
483
  incrementalParse: boolean;
476
484
  defListEnabled: boolean;
485
+ /** Whether `remarkPlugins` parses GFM task-list items. Default `false`
486
+ * (the boundary scanner keeps every `[x]` as reference taint). The
487
+ * adapters pass `true` because they build the chain with
488
+ * `buildCoreRemarkPlugins`, which always includes remark-gfm. A box
489
+ * whose paragraph a `$$` opener closed is released only when
490
+ * `mathFlow` is `true` as well. */
491
+ gfmTaskListItems?: boolean;
492
+ /** Whether `remarkPlugins` parses `$$` flow math (remark-math). Passed
493
+ * through to the engine in all three states: `true` declares it (a
494
+ * `$$` region is verbatim math), `false` declares its absence (`$$`
495
+ * lines are paragraph text), and omitted leaves it unknown — the
496
+ * scanner then takes the union of both grammars, which is correct for
497
+ * either chain and freezes less around `$$`. The adapters pass `true`
498
+ * because `buildCoreRemarkPlugins` always includes remark-math; a
499
+ * caller with its own chain should declare the real value and may
500
+ * leave it out when unsure. */
501
+ mathFlow?: boolean;
477
502
  measure?: AdvanceOptions['measure'];
478
503
  }
479
504
  declare function createPipelineSession(): PipelineSession;
@@ -266,10 +266,12 @@ function buildBlocks(mdast, hast, source, options = {}) {
266
266
  continue;
267
267
  }
268
268
  let hastDigest;
269
+ let swallowedSource;
269
270
  let swallowedTaint = false;
270
271
  if (isRawHtmlBlock) {
271
272
  const d = computeHtmlBlockDigestWithExtent(el, source, mdastPos.end.offset);
272
273
  hastDigest = d.digest;
274
+ swallowedSource = source.slice(mdastPos.end.offset, d.maxEnd);
273
275
  const first = firstTaintAtOrAfter(mdastPos.end.offset);
274
276
  swallowedTaint = first < taintOffsets.length && taintOffsets[first] < d.maxEnd;
275
277
  }
@@ -282,6 +284,7 @@ function buildBlocks(mdast, hast, source, options = {}) {
282
284
  startColumn: mdastPos.start.column,
283
285
  hasReference,
284
286
  ...hastDigest !== void 0 ? { hastDigest } : {},
287
+ ...swallowedSource !== void 0 ? { swallowedSource } : {},
285
288
  ...swallowed?.hasFootnoteSection ? { containsFootnoteSection: true } : {},
286
289
  ...hasReference ? {
287
290
  taintLabels: {
@@ -856,6 +859,9 @@ function createPipelineSession() {
856
859
  provenance,
857
860
  incrementalParse,
858
861
  defListEnabled,
862
+ gfmTaskListItems = false,
863
+ // No default: omitted is its own (undeclared) state at the engine.
864
+ mathFlow,
859
865
  measure: measureHere = unmeasured
860
866
  }) {
861
867
  const phantomDefs = (0, import_engine4.buildPhantomSuffix)(targetPhantoms);
@@ -933,9 +939,13 @@ function createPipelineSession() {
933
939
  // already refuses to resume under a different profile, but the
934
940
  // retained TREES were still spliced against — a prefix frozen
935
941
  // under one profile must not survive into frames under the other.
936
- defListEnabled
942
+ defListEnabled,
943
+ gfmTaskListItems,
944
+ mathFlow
937
945
  ],
938
946
  defListEnabled,
947
+ gfmTaskListItems,
948
+ mathFlow,
939
949
  phantomSuffix,
940
950
  measure: measureHere
941
951
  });