@ai-react-markdown/engine 2.11.0 → 2.13.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
@@ -156,6 +156,53 @@ declare function buildTransform(ctx: TransformContext): BuildVisitor<Root$1>;
156
156
  */
157
157
  declare const defaultUrlTransform: UrlTransform;
158
158
 
159
+ /** Checkpoint representation and initialization. Only confirmed lines mutate this state. */
160
+
161
+ interface FreezeBoundaryOptions {
162
+ /** Whether remark-definition-list is in the active plugin chain (the
163
+ * `enginePlugins` selection includes `definitionList`). Enables blockers 3b/4. */
164
+ defListEnabled: boolean;
165
+ /**
166
+ * Whether `$$` flow math is in the grammar (remark-math). Default `true`
167
+ * (the engine's own profile). The def-label scanner runs a PINNED
168
+ * remark-parse+gfm subset where `$$` is ordinary paragraph text — under
169
+ * that grammar the math branch is a MASKING hole: `inMath` returns early
170
+ * without comment/fence scanning, so `$$\n<!--\n$$` reads as a closed
171
+ * math block here while the subset grammar sees an OPEN type-2 HTML
172
+ * comment running to `-->`/EOF (a candidate after it would let a
173
+ * standalone tail parse invent ghost defs). With `false`, `$$` lines take
174
+ * the ordinary text path and comments/fences inside are scanned.
175
+ */
176
+ mathFlow?: boolean;
177
+ /**
178
+ * Whether blocker 5 (reference taint) applies. Default `true`: the
179
+ * engine must reject candidates past an unresolved `[label]` because a
180
+ * later definition retargets the reference's PARSE. The def-label
181
+ * scanner only extracts definition IDENTITIES — a pure block-level fact
182
+ * unaffected by how inline references resolve — and under taint a
183
+ * streaming citation footer (defs with no settling blank line yet)
184
+ * collapses the boundary to the body's first reference, zeroing the
185
+ * caching this profile exists for. `false` skips ref tracking entirely.
186
+ */
187
+ referenceTaint?: boolean;
188
+ }
189
+ interface FreezeScanResult {
190
+ /** Largest freeze-safe boundary, or 0 when nothing can be frozen. */
191
+ boundary: number;
192
+ /** Opaque resume state — pass back on the next APPEND-ONLY call to skip
193
+ * re-lexing the confirmed prefix. Single-consumer; see module docs. */
194
+ checkpoint: FreezeScanCheckpoint;
195
+ }
196
+ /** Opaque resume token. Produced by one `computeFreezeBoundary` call and
197
+ * passed back on the next APPEND-ONLY call; the only supported operations
198
+ * are storing it and passing it back. The field set is an implementation
199
+ * detail of the scanner and changes between minor versions — the brand key
200
+ * (a structural string literal, safe across dual d.ts entries) is all that
201
+ * ships in the public type. */
202
+ interface FreezeScanCheckpoint {
203
+ readonly '~freezeScanCheckpoint'?: never;
204
+ }
205
+
159
206
  /**
160
207
  * Freeze-boundary detector for incremental (prefix-freeze) parsing.
161
208
  *
@@ -275,88 +322,12 @@ declare const defaultUrlTransform: UrlTransform;
275
322
  * via injection replay (v2).
276
323
  */
277
324
 
278
- interface FreezeBoundaryOptions {
279
- /** Whether remark-definition-list is in the active plugin chain (the
280
- * `enginePlugins` selection includes `definitionList`). Enables blockers 3b/4. */
281
- defListEnabled: boolean;
282
- /**
283
- * Whether `$$` flow math is in the grammar (remark-math). Default `true`
284
- * (the engine's own profile). The def-label scanner runs a PINNED
285
- * remark-parse+gfm subset where `$$` is ordinary paragraph text — under
286
- * that grammar the math branch is a MASKING hole: `inMath` returns early
287
- * without comment/fence scanning, so `$$\n<!--\n$$` reads as a closed
288
- * math block here while the subset grammar sees an OPEN type-2 HTML
289
- * comment running to `-->`/EOF (a candidate after it would let a
290
- * standalone tail parse invent ghost defs). With `false`, `$$` lines take
291
- * the ordinary text path and comments/fences inside are scanned.
292
- */
293
- mathFlow?: boolean;
294
- /**
295
- * Whether blocker 5 (reference taint) applies. Default `true`: the
296
- * engine must reject candidates past an unresolved `[label]` because a
297
- * later definition retargets the reference's PARSE. The def-label
298
- * scanner only extracts definition IDENTITIES — a pure block-level fact
299
- * unaffected by how inline references resolve — and under taint a
300
- * streaming citation footer (defs with no settling blank line yet)
301
- * collapses the boundary to the body's first reference, zeroing the
302
- * caching this profile exists for. `false` skips ref tracking entirely.
303
- */
304
- referenceTaint?: boolean;
305
- }
306
- interface FreezeScanResult {
307
- /** Largest freeze-safe boundary, or 0 when nothing can be frozen. */
308
- boundary: number;
309
- /** Opaque resume state — pass back on the next APPEND-ONLY call to skip
310
- * re-lexing the confirmed prefix. Single-consumer; see module docs. */
311
- checkpoint: FreezeScanCheckpoint;
312
- }
313
- /** Opaque resume token. Produced by one `computeFreezeBoundary` call and
314
- * passed back on the next APPEND-ONLY call; the only supported operations
315
- * are storing it and passing it back. The field set is an implementation
316
- * detail of the scanner and changes between minor versions — the brand key
317
- * (a structural string literal, safe across dual d.ts entries) is all that
318
- * ships in the public type. */
319
- interface FreezeScanCheckpoint {
320
- readonly '~freezeScanCheckpoint'?: never;
321
- }
322
325
  /**
323
326
  * @soak-entry freeze-scanner-resume
324
327
  * @soak-entry freeze-direction
325
328
  */
326
329
  declare function computeFreezeBoundary(text: string, options: FreezeBoundaryOptions, resume?: FreezeScanCheckpoint | null): FreezeScanResult;
327
330
 
328
- /**
329
- * Pure splice helpers for incremental (prefix-freeze) parsing: cut the
330
- * frozen prefix out of the previous frame's trees, re-base a tail-only
331
- * parse into document coordinates, and join the two into fresh roots.
332
- *
333
- * Invariant these helpers exist to uphold (enforced by the
334
- * splice-equivalence arbiter test, NOT asserted at runtime): the spliced
335
- * `{mdast, hast}` is deep-equal — positions included — to a full pipeline
336
- * run over the whole content. Defined on UNRENDERED trees; after a render,
337
- * `renderHastSubtree` mutates hast in place (convergent `data.originalUrls`
338
- * stash, raw→text rewrite — see Markdown.tsx), so no in-component
339
- * deep-equal check is possible or attempted.
340
- *
341
- * Prefix link/image definitions are PREPENDED to the tail source (not
342
- * appended: a streaming tail routinely ends inside an unclosed fence or
343
- * `$$` block that would swallow appended lines, and appended defs would
344
- * invert CommonMark first-def-wins against a same-label tail def).
345
- * Definitions emit zero hast (mdast-util-to-hast has no `definition`
346
- * handler), so their only trace is `definition` mdast nodes inside the
347
- * injected region, which are dropped before the join. Definition text is
348
- * sliced verbatim from the previous content via node positions — exact
349
- * source roundtrip preserves escapes and multi-line titles.
350
- *
351
- * Sanitize-STRIPPED prefix nodes (HTML comments, `<?…?>` bogus comments,
352
- * `<script>`) are modeled explicitly: their wrap separators survive as
353
- * orphans, and `alignPrefixCut` re-derives the mdast↔hast pairing from
354
- * separator-run lengths (B0-probe-verified: one orphan '\n' per stripped
355
- * child's gap slot; separators MERGED into raw trailing literals count via
356
- * their trailing newlines — `literalCredit`). Layouts outside the model
357
- * return null → full-parse fallback for the frame.
358
- */
359
-
360
331
  /** Prefix footnote/definition events in DOCUMENT ORDER. Order is the whole
361
332
  * point: mdast-util-to-hast's footnoteOrder/footnoteCounts are built from
362
333
  * encounter order, and the replay must reproduce it exactly. */
@@ -726,6 +697,12 @@ interface Registry {
726
697
  * consumers should observe via `subscribe`, not by writing. */
727
698
  readonly version: number;
728
699
  subscribe(cb: () => void): () => void;
700
+ /** Observe one normalized label's indexed selectors. Links/images share
701
+ * the 'link' channel (canonical owner, URL, title). Footnotes observe
702
+ * canonical owner, numbering, counts and per-chunk occurrence ranges.
703
+ * Raw chunk payload/body changes still require the global subscription.
704
+ * Notifications are microtask-coalesced and may skip net-zero changes. */
705
+ subscribeLabel(kind: 'link' | 'footnote', label: string, cb: () => void): () => void;
729
706
  canonicalFootnoteFor(label: string): symbol | null;
730
707
  canonicalLinkFor(label: string): symbol | null;
731
708
  globalNumber(label: string): number | null;
@@ -1106,6 +1083,9 @@ interface RehypeVerifyEngineTagsOptions {
1106
1083
  /** The credential the handlers were given. The empty string accepts
1107
1084
  * nothing (fail closed); it is never a valid credential. */
1108
1085
  provenance: string;
1086
+ /** Capture ancestry only when the final a/img schema needs it. Data is
1087
+ * recorded after verification, never taken from authored attributes. */
1088
+ referenceAncestors?: boolean;
1109
1089
  }
1110
1090
  /**
1111
1091
  * rehype plugin: strip the provenance credential from genuine engine
@@ -1315,6 +1295,21 @@ type UrlAttrTag = 'a' | 'img';
1315
1295
  */
1316
1296
  declare function sanitizeCrossChunkUrl(rawUrl: string, key: UrlAttrKey, tagName: UrlAttrTag, urlTransform: UrlTransform, schema: SanitizeSchema): string | null;
1317
1297
 
1298
+ /** Resolve the final element, not just its URL: placeholders reach React
1299
+ * after the normal rehype passes, so their a/img must apply those passes too.
1300
+ * The marker represents already-rendered link children and distinguishes
1301
+ * sanitizer unwrapping from stripping the element with its contents. */
1302
+ declare function resolveCrossChunkReference(input: {
1303
+ tagName: 'a' | 'img';
1304
+ url: string;
1305
+ title?: string;
1306
+ alt?: string;
1307
+ node?: Pick<Element, 'children' | 'position' | 'data'>;
1308
+ }, schema: SanitizeSchema, urlTransform: UrlTransform, clobberPrefix: string): {
1309
+ element: Element | null;
1310
+ keepChildren: boolean;
1311
+ };
1312
+
1318
1313
  /**
1319
1314
  * The five shipped engine plugins and the default set.
1320
1315
  *
@@ -1930,4 +1925,4 @@ type RemendPreprocessorOptions = Omit<RemendOptions, 'katex' | 'inlineKatex'>;
1930
1925
  */
1931
1926
  declare function createRemendPreprocessor(options?: RemendPreprocessorOptions): AIMDContentPreprocessor;
1932
1927
 
1933
- export { type AIMDContentPreprocessor, type AIMarkdownEnginePlugin, type AIMarkdownEnginePluginName, type AdvanceOptions, type AdvanceResult, type AllowElement, type ChunkData, type Contribution, type CoreRehypePluginsOptions, type CrossChunkHandlerOptions, DEFAULT_PAYLOAD, type DefLabelScanner, type DefLabels, type Deprecation, ENGINE_PLACEHOLDER_TAGS, ENGINE_PROVENANCE_PROPERTY, type EnginePluginInternals, type EnginePluginStage, type ExtractContributionsOptions, type FootnoteDef, type FreezeBoundaryOptions, type IncrementalParseState, type IncrementalStage, type LinkDef, PIPELINE_STAGES, type ParsedMarkdown, type PhantomLabels, type PipelineOptions, type PipelineStage, type RefKind, type RefRecord, type Registry, type RegistryInternal, type RehypePlugins, type RehypeRebaseHashLinksOptions, type RehypeVerifyEngineTagsOptions, type RemarkPlugins, type RemarkRehypeOptions, type RemendPreprocessorOptions, SENTINEL_FN_CONTENT, SENTINEL_LINK_URL, SMOOTH_STREAM_PACING_PRESETS, STAGE_MEASURE_PREFIX, type SanitizeSchema, type SmoothStreamController, type SmoothStreamOptions, type SmoothStreamPacing, type SmoothStreamPacingParams, type TransformContext, type UrlAttrKey, type UrlAttrTag, type UrlTransform, advanceIncrementalParse, attributeHastChildren, buildCoreRehypePlugins, buildCoreRemarkPlugins, buildCoreRemarkRehypeOptions, buildCrossChunkHandlers, buildPhantomSuffix, buildTransform, codePointSnapshots, collectDefLabels, computeFreezeBoundary, createDefLabelScanner, createIncrementalLatexPreprocessor, createProcessor, createRegistry, createRemendPreprocessor, createSmoothStreamController, defaultEnginePlugins, defaultUrlTransform, definitionList, extendSanitizeSchema, extractContributions, extractDefBodiesFromHast, footnoteSafeId, getEnginePluginInternals, hasLoneSurrogate, highlight, isFootnoteSection, lastMeaningfulIdx, measureStage, normalizeForMatch, normalizeId, pangu, parseStage, phantomSuffixCloser, preprocessAIMDContent, preprocessLaTeX, rehypeFooterAdorn, rehypeRebaseHashLinks, rehypeVerifyEngineTags, removeComments, sanitizeCrossChunkUrl, sanitizeSchema, shortenDocumentId, smartypants, sourceIdFromFootnoteLiId, subscribeStageTimings, transformStage, withDefs };
1928
+ export { type AIMDContentPreprocessor, type AIMarkdownEnginePlugin, type AIMarkdownEnginePluginName, type AdvanceOptions, type AdvanceResult, type AllowElement, type ChunkData, type Contribution, type CoreRehypePluginsOptions, type CrossChunkHandlerOptions, DEFAULT_PAYLOAD, type DefLabelScanner, type DefLabels, type Deprecation, ENGINE_PLACEHOLDER_TAGS, ENGINE_PROVENANCE_PROPERTY, type EnginePluginInternals, type EnginePluginStage, type ExtractContributionsOptions, type FootnoteDef, type FreezeBoundaryOptions, type IncrementalParseState, type IncrementalStage, type LinkDef, PIPELINE_STAGES, type ParsedMarkdown, type PhantomLabels, type PipelineOptions, type PipelineStage, type RefKind, type RefRecord, type Registry, type RegistryInternal, type RehypePlugins, type RehypeRebaseHashLinksOptions, type RehypeVerifyEngineTagsOptions, type RemarkPlugins, type RemarkRehypeOptions, type RemendPreprocessorOptions, SENTINEL_FN_CONTENT, SENTINEL_LINK_URL, SMOOTH_STREAM_PACING_PRESETS, STAGE_MEASURE_PREFIX, type SanitizeSchema, type SmoothStreamController, type SmoothStreamOptions, type SmoothStreamPacing, type SmoothStreamPacingParams, type TransformContext, type UrlAttrKey, type UrlAttrTag, type UrlTransform, advanceIncrementalParse, attributeHastChildren, buildCoreRehypePlugins, buildCoreRemarkPlugins, buildCoreRemarkRehypeOptions, buildCrossChunkHandlers, buildPhantomSuffix, buildTransform, codePointSnapshots, collectDefLabels, computeFreezeBoundary, createDefLabelScanner, createIncrementalLatexPreprocessor, createProcessor, createRegistry, createRemendPreprocessor, createSmoothStreamController, defaultEnginePlugins, defaultUrlTransform, definitionList, extendSanitizeSchema, extractContributions, extractDefBodiesFromHast, footnoteSafeId, getEnginePluginInternals, hasLoneSurrogate, highlight, isFootnoteSection, lastMeaningfulIdx, measureStage, normalizeForMatch, normalizeId, pangu, parseStage, phantomSuffixCloser, preprocessAIMDContent, preprocessLaTeX, rehypeFooterAdorn, rehypeRebaseHashLinks, rehypeVerifyEngineTags, removeComments, resolveCrossChunkReference, sanitizeCrossChunkUrl, sanitizeSchema, shortenDocumentId, smartypants, sourceIdFromFootnoteLiId, subscribeStageTimings, transformStage, withDefs };
package/dist/index.d.ts CHANGED
@@ -156,6 +156,53 @@ declare function buildTransform(ctx: TransformContext): BuildVisitor<Root$1>;
156
156
  */
157
157
  declare const defaultUrlTransform: UrlTransform;
158
158
 
159
+ /** Checkpoint representation and initialization. Only confirmed lines mutate this state. */
160
+
161
+ interface FreezeBoundaryOptions {
162
+ /** Whether remark-definition-list is in the active plugin chain (the
163
+ * `enginePlugins` selection includes `definitionList`). Enables blockers 3b/4. */
164
+ defListEnabled: boolean;
165
+ /**
166
+ * Whether `$$` flow math is in the grammar (remark-math). Default `true`
167
+ * (the engine's own profile). The def-label scanner runs a PINNED
168
+ * remark-parse+gfm subset where `$$` is ordinary paragraph text — under
169
+ * that grammar the math branch is a MASKING hole: `inMath` returns early
170
+ * without comment/fence scanning, so `$$\n<!--\n$$` reads as a closed
171
+ * math block here while the subset grammar sees an OPEN type-2 HTML
172
+ * comment running to `-->`/EOF (a candidate after it would let a
173
+ * standalone tail parse invent ghost defs). With `false`, `$$` lines take
174
+ * the ordinary text path and comments/fences inside are scanned.
175
+ */
176
+ mathFlow?: boolean;
177
+ /**
178
+ * Whether blocker 5 (reference taint) applies. Default `true`: the
179
+ * engine must reject candidates past an unresolved `[label]` because a
180
+ * later definition retargets the reference's PARSE. The def-label
181
+ * scanner only extracts definition IDENTITIES — a pure block-level fact
182
+ * unaffected by how inline references resolve — and under taint a
183
+ * streaming citation footer (defs with no settling blank line yet)
184
+ * collapses the boundary to the body's first reference, zeroing the
185
+ * caching this profile exists for. `false` skips ref tracking entirely.
186
+ */
187
+ referenceTaint?: boolean;
188
+ }
189
+ interface FreezeScanResult {
190
+ /** Largest freeze-safe boundary, or 0 when nothing can be frozen. */
191
+ boundary: number;
192
+ /** Opaque resume state — pass back on the next APPEND-ONLY call to skip
193
+ * re-lexing the confirmed prefix. Single-consumer; see module docs. */
194
+ checkpoint: FreezeScanCheckpoint;
195
+ }
196
+ /** Opaque resume token. Produced by one `computeFreezeBoundary` call and
197
+ * passed back on the next APPEND-ONLY call; the only supported operations
198
+ * are storing it and passing it back. The field set is an implementation
199
+ * detail of the scanner and changes between minor versions — the brand key
200
+ * (a structural string literal, safe across dual d.ts entries) is all that
201
+ * ships in the public type. */
202
+ interface FreezeScanCheckpoint {
203
+ readonly '~freezeScanCheckpoint'?: never;
204
+ }
205
+
159
206
  /**
160
207
  * Freeze-boundary detector for incremental (prefix-freeze) parsing.
161
208
  *
@@ -275,88 +322,12 @@ declare const defaultUrlTransform: UrlTransform;
275
322
  * via injection replay (v2).
276
323
  */
277
324
 
278
- interface FreezeBoundaryOptions {
279
- /** Whether remark-definition-list is in the active plugin chain (the
280
- * `enginePlugins` selection includes `definitionList`). Enables blockers 3b/4. */
281
- defListEnabled: boolean;
282
- /**
283
- * Whether `$$` flow math is in the grammar (remark-math). Default `true`
284
- * (the engine's own profile). The def-label scanner runs a PINNED
285
- * remark-parse+gfm subset where `$$` is ordinary paragraph text — under
286
- * that grammar the math branch is a MASKING hole: `inMath` returns early
287
- * without comment/fence scanning, so `$$\n<!--\n$$` reads as a closed
288
- * math block here while the subset grammar sees an OPEN type-2 HTML
289
- * comment running to `-->`/EOF (a candidate after it would let a
290
- * standalone tail parse invent ghost defs). With `false`, `$$` lines take
291
- * the ordinary text path and comments/fences inside are scanned.
292
- */
293
- mathFlow?: boolean;
294
- /**
295
- * Whether blocker 5 (reference taint) applies. Default `true`: the
296
- * engine must reject candidates past an unresolved `[label]` because a
297
- * later definition retargets the reference's PARSE. The def-label
298
- * scanner only extracts definition IDENTITIES — a pure block-level fact
299
- * unaffected by how inline references resolve — and under taint a
300
- * streaming citation footer (defs with no settling blank line yet)
301
- * collapses the boundary to the body's first reference, zeroing the
302
- * caching this profile exists for. `false` skips ref tracking entirely.
303
- */
304
- referenceTaint?: boolean;
305
- }
306
- interface FreezeScanResult {
307
- /** Largest freeze-safe boundary, or 0 when nothing can be frozen. */
308
- boundary: number;
309
- /** Opaque resume state — pass back on the next APPEND-ONLY call to skip
310
- * re-lexing the confirmed prefix. Single-consumer; see module docs. */
311
- checkpoint: FreezeScanCheckpoint;
312
- }
313
- /** Opaque resume token. Produced by one `computeFreezeBoundary` call and
314
- * passed back on the next APPEND-ONLY call; the only supported operations
315
- * are storing it and passing it back. The field set is an implementation
316
- * detail of the scanner and changes between minor versions — the brand key
317
- * (a structural string literal, safe across dual d.ts entries) is all that
318
- * ships in the public type. */
319
- interface FreezeScanCheckpoint {
320
- readonly '~freezeScanCheckpoint'?: never;
321
- }
322
325
  /**
323
326
  * @soak-entry freeze-scanner-resume
324
327
  * @soak-entry freeze-direction
325
328
  */
326
329
  declare function computeFreezeBoundary(text: string, options: FreezeBoundaryOptions, resume?: FreezeScanCheckpoint | null): FreezeScanResult;
327
330
 
328
- /**
329
- * Pure splice helpers for incremental (prefix-freeze) parsing: cut the
330
- * frozen prefix out of the previous frame's trees, re-base a tail-only
331
- * parse into document coordinates, and join the two into fresh roots.
332
- *
333
- * Invariant these helpers exist to uphold (enforced by the
334
- * splice-equivalence arbiter test, NOT asserted at runtime): the spliced
335
- * `{mdast, hast}` is deep-equal — positions included — to a full pipeline
336
- * run over the whole content. Defined on UNRENDERED trees; after a render,
337
- * `renderHastSubtree` mutates hast in place (convergent `data.originalUrls`
338
- * stash, raw→text rewrite — see Markdown.tsx), so no in-component
339
- * deep-equal check is possible or attempted.
340
- *
341
- * Prefix link/image definitions are PREPENDED to the tail source (not
342
- * appended: a streaming tail routinely ends inside an unclosed fence or
343
- * `$$` block that would swallow appended lines, and appended defs would
344
- * invert CommonMark first-def-wins against a same-label tail def).
345
- * Definitions emit zero hast (mdast-util-to-hast has no `definition`
346
- * handler), so their only trace is `definition` mdast nodes inside the
347
- * injected region, which are dropped before the join. Definition text is
348
- * sliced verbatim from the previous content via node positions — exact
349
- * source roundtrip preserves escapes and multi-line titles.
350
- *
351
- * Sanitize-STRIPPED prefix nodes (HTML comments, `<?…?>` bogus comments,
352
- * `<script>`) are modeled explicitly: their wrap separators survive as
353
- * orphans, and `alignPrefixCut` re-derives the mdast↔hast pairing from
354
- * separator-run lengths (B0-probe-verified: one orphan '\n' per stripped
355
- * child's gap slot; separators MERGED into raw trailing literals count via
356
- * their trailing newlines — `literalCredit`). Layouts outside the model
357
- * return null → full-parse fallback for the frame.
358
- */
359
-
360
331
  /** Prefix footnote/definition events in DOCUMENT ORDER. Order is the whole
361
332
  * point: mdast-util-to-hast's footnoteOrder/footnoteCounts are built from
362
333
  * encounter order, and the replay must reproduce it exactly. */
@@ -726,6 +697,12 @@ interface Registry {
726
697
  * consumers should observe via `subscribe`, not by writing. */
727
698
  readonly version: number;
728
699
  subscribe(cb: () => void): () => void;
700
+ /** Observe one normalized label's indexed selectors. Links/images share
701
+ * the 'link' channel (canonical owner, URL, title). Footnotes observe
702
+ * canonical owner, numbering, counts and per-chunk occurrence ranges.
703
+ * Raw chunk payload/body changes still require the global subscription.
704
+ * Notifications are microtask-coalesced and may skip net-zero changes. */
705
+ subscribeLabel(kind: 'link' | 'footnote', label: string, cb: () => void): () => void;
729
706
  canonicalFootnoteFor(label: string): symbol | null;
730
707
  canonicalLinkFor(label: string): symbol | null;
731
708
  globalNumber(label: string): number | null;
@@ -1106,6 +1083,9 @@ interface RehypeVerifyEngineTagsOptions {
1106
1083
  /** The credential the handlers were given. The empty string accepts
1107
1084
  * nothing (fail closed); it is never a valid credential. */
1108
1085
  provenance: string;
1086
+ /** Capture ancestry only when the final a/img schema needs it. Data is
1087
+ * recorded after verification, never taken from authored attributes. */
1088
+ referenceAncestors?: boolean;
1109
1089
  }
1110
1090
  /**
1111
1091
  * rehype plugin: strip the provenance credential from genuine engine
@@ -1315,6 +1295,21 @@ type UrlAttrTag = 'a' | 'img';
1315
1295
  */
1316
1296
  declare function sanitizeCrossChunkUrl(rawUrl: string, key: UrlAttrKey, tagName: UrlAttrTag, urlTransform: UrlTransform, schema: SanitizeSchema): string | null;
1317
1297
 
1298
+ /** Resolve the final element, not just its URL: placeholders reach React
1299
+ * after the normal rehype passes, so their a/img must apply those passes too.
1300
+ * The marker represents already-rendered link children and distinguishes
1301
+ * sanitizer unwrapping from stripping the element with its contents. */
1302
+ declare function resolveCrossChunkReference(input: {
1303
+ tagName: 'a' | 'img';
1304
+ url: string;
1305
+ title?: string;
1306
+ alt?: string;
1307
+ node?: Pick<Element, 'children' | 'position' | 'data'>;
1308
+ }, schema: SanitizeSchema, urlTransform: UrlTransform, clobberPrefix: string): {
1309
+ element: Element | null;
1310
+ keepChildren: boolean;
1311
+ };
1312
+
1318
1313
  /**
1319
1314
  * The five shipped engine plugins and the default set.
1320
1315
  *
@@ -1930,4 +1925,4 @@ type RemendPreprocessorOptions = Omit<RemendOptions, 'katex' | 'inlineKatex'>;
1930
1925
  */
1931
1926
  declare function createRemendPreprocessor(options?: RemendPreprocessorOptions): AIMDContentPreprocessor;
1932
1927
 
1933
- export { type AIMDContentPreprocessor, type AIMarkdownEnginePlugin, type AIMarkdownEnginePluginName, type AdvanceOptions, type AdvanceResult, type AllowElement, type ChunkData, type Contribution, type CoreRehypePluginsOptions, type CrossChunkHandlerOptions, DEFAULT_PAYLOAD, type DefLabelScanner, type DefLabels, type Deprecation, ENGINE_PLACEHOLDER_TAGS, ENGINE_PROVENANCE_PROPERTY, type EnginePluginInternals, type EnginePluginStage, type ExtractContributionsOptions, type FootnoteDef, type FreezeBoundaryOptions, type IncrementalParseState, type IncrementalStage, type LinkDef, PIPELINE_STAGES, type ParsedMarkdown, type PhantomLabels, type PipelineOptions, type PipelineStage, type RefKind, type RefRecord, type Registry, type RegistryInternal, type RehypePlugins, type RehypeRebaseHashLinksOptions, type RehypeVerifyEngineTagsOptions, type RemarkPlugins, type RemarkRehypeOptions, type RemendPreprocessorOptions, SENTINEL_FN_CONTENT, SENTINEL_LINK_URL, SMOOTH_STREAM_PACING_PRESETS, STAGE_MEASURE_PREFIX, type SanitizeSchema, type SmoothStreamController, type SmoothStreamOptions, type SmoothStreamPacing, type SmoothStreamPacingParams, type TransformContext, type UrlAttrKey, type UrlAttrTag, type UrlTransform, advanceIncrementalParse, attributeHastChildren, buildCoreRehypePlugins, buildCoreRemarkPlugins, buildCoreRemarkRehypeOptions, buildCrossChunkHandlers, buildPhantomSuffix, buildTransform, codePointSnapshots, collectDefLabels, computeFreezeBoundary, createDefLabelScanner, createIncrementalLatexPreprocessor, createProcessor, createRegistry, createRemendPreprocessor, createSmoothStreamController, defaultEnginePlugins, defaultUrlTransform, definitionList, extendSanitizeSchema, extractContributions, extractDefBodiesFromHast, footnoteSafeId, getEnginePluginInternals, hasLoneSurrogate, highlight, isFootnoteSection, lastMeaningfulIdx, measureStage, normalizeForMatch, normalizeId, pangu, parseStage, phantomSuffixCloser, preprocessAIMDContent, preprocessLaTeX, rehypeFooterAdorn, rehypeRebaseHashLinks, rehypeVerifyEngineTags, removeComments, sanitizeCrossChunkUrl, sanitizeSchema, shortenDocumentId, smartypants, sourceIdFromFootnoteLiId, subscribeStageTimings, transformStage, withDefs };
1928
+ export { type AIMDContentPreprocessor, type AIMarkdownEnginePlugin, type AIMarkdownEnginePluginName, type AdvanceOptions, type AdvanceResult, type AllowElement, type ChunkData, type Contribution, type CoreRehypePluginsOptions, type CrossChunkHandlerOptions, DEFAULT_PAYLOAD, type DefLabelScanner, type DefLabels, type Deprecation, ENGINE_PLACEHOLDER_TAGS, ENGINE_PROVENANCE_PROPERTY, type EnginePluginInternals, type EnginePluginStage, type ExtractContributionsOptions, type FootnoteDef, type FreezeBoundaryOptions, type IncrementalParseState, type IncrementalStage, type LinkDef, PIPELINE_STAGES, type ParsedMarkdown, type PhantomLabels, type PipelineOptions, type PipelineStage, type RefKind, type RefRecord, type Registry, type RegistryInternal, type RehypePlugins, type RehypeRebaseHashLinksOptions, type RehypeVerifyEngineTagsOptions, type RemarkPlugins, type RemarkRehypeOptions, type RemendPreprocessorOptions, SENTINEL_FN_CONTENT, SENTINEL_LINK_URL, SMOOTH_STREAM_PACING_PRESETS, STAGE_MEASURE_PREFIX, type SanitizeSchema, type SmoothStreamController, type SmoothStreamOptions, type SmoothStreamPacing, type SmoothStreamPacingParams, type TransformContext, type UrlAttrKey, type UrlAttrTag, type UrlTransform, advanceIncrementalParse, attributeHastChildren, buildCoreRehypePlugins, buildCoreRemarkPlugins, buildCoreRemarkRehypeOptions, buildCrossChunkHandlers, buildPhantomSuffix, buildTransform, codePointSnapshots, collectDefLabels, computeFreezeBoundary, createDefLabelScanner, createIncrementalLatexPreprocessor, createProcessor, createRegistry, createRemendPreprocessor, createSmoothStreamController, defaultEnginePlugins, defaultUrlTransform, definitionList, extendSanitizeSchema, extractContributions, extractDefBodiesFromHast, footnoteSafeId, getEnginePluginInternals, hasLoneSurrogate, highlight, isFootnoteSection, lastMeaningfulIdx, measureStage, normalizeForMatch, normalizeId, pangu, parseStage, phantomSuffixCloser, preprocessAIMDContent, preprocessLaTeX, rehypeFooterAdorn, rehypeRebaseHashLinks, rehypeVerifyEngineTags, removeComments, resolveCrossChunkReference, sanitizeCrossChunkUrl, sanitizeSchema, shortenDocumentId, smartypants, sourceIdFromFootnoteLiId, subscribeStageTimings, transformStage, withDefs };