@ai-react-markdown/engine 2.5.5 → 2.6.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.cjs +14 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -199
- package/dist/index.d.ts +7 -199
- package/dist/index.dev.cjs +14 -7
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +14 -7
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -316,207 +316,15 @@ interface FreezeScanResult {
|
|
|
316
316
|
* re-lexing the confirmed prefix. Single-consumer; see module docs. */
|
|
317
317
|
checkpoint: FreezeScanCheckpoint;
|
|
318
318
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
htmlBalanced: boolean;
|
|
326
|
-
/** Rolling continuation-hazard verdict at emission (blocker 3). */
|
|
327
|
-
hazard: boolean;
|
|
328
|
-
/** Blocker-6: the run ending at this blank left balanced FLOATING raw
|
|
329
|
-
* remnant whose hast seam is tail-dependent; reject this candidate. */
|
|
330
|
-
seamRisk: boolean;
|
|
331
|
-
/** Blocker-4 settle verdict, decided by the NEXT confirmed line (`null`
|
|
332
|
-
* while that line hasn't confirmed — only the newest candidate can be
|
|
333
|
-
* pending). Storing the verdict instead of the line lets the checkpoint
|
|
334
|
-
* drop its lines array, which retained a full copy of the document
|
|
335
|
-
* (round-2 review: ~2-3× doc size per mounted instance). */
|
|
336
|
-
defListSettled: boolean | null;
|
|
337
|
-
}
|
|
338
|
-
interface UnresolvedRef {
|
|
339
|
-
offset: number;
|
|
340
|
-
label: string;
|
|
341
|
-
footnote: boolean;
|
|
342
|
-
}
|
|
343
|
-
/** Mutable resume state. All fields describe the scan strictly BEFORE the
|
|
344
|
-
* first unconfirmed character (`confirmedOffset`). */
|
|
319
|
+
/** Opaque resume token. Produced by one `computeFreezeBoundary` call and
|
|
320
|
+
* passed back on the next APPEND-ONLY call; the only supported operations
|
|
321
|
+
* are storing it and passing it back. The field set is an implementation
|
|
322
|
+
* detail of the scanner and changes between minor versions — the brand key
|
|
323
|
+
* (a structural string literal, safe across dual d.ts entries) is all that
|
|
324
|
+
* ships in the public type. */
|
|
345
325
|
interface FreezeScanCheckpoint {
|
|
346
|
-
|
|
347
|
-
/** Grammar-profile switches baked at creation — a checkpoint is only
|
|
348
|
-
* resumable under the exact profile that built it. */
|
|
349
|
-
mathFlow: boolean;
|
|
350
|
-
referenceTaint: boolean;
|
|
351
|
-
/** Start offset of the first line NOT yet baked into this checkpoint. */
|
|
352
|
-
confirmedOffset: number;
|
|
353
|
-
candidates: Candidate[];
|
|
354
|
-
defs: Map<string, number>;
|
|
355
|
-
footnoteDefs: Map<string, number>;
|
|
356
|
-
unresolvedRefs: UnresolvedRef[];
|
|
357
|
-
tagBalance: Map<string, number>;
|
|
358
|
-
openTotal: number;
|
|
359
|
-
commentOpen: boolean;
|
|
360
|
-
piOpen: boolean;
|
|
361
|
-
declOpen: boolean;
|
|
362
|
-
cdataOpen: boolean;
|
|
363
|
-
/** parse5 BOGUS COMMENT open inside a real html-flow run: `<!` not
|
|
364
|
-
* followed by `--` / letter / `[CDATA[`, or `</` not followed by a
|
|
365
|
-
* letter (`<!\n`, `<!-`, `</\n`, `<//`) — eaten up to the next `>`;
|
|
366
|
-
* a `</div>` inside is comment text, not a close (2026-08-19 review r2
|
|
367
|
-
* P1-3: the balance zeroed past an open div). micromark has no such
|
|
368
|
-
* construct: those bytes are just html-block content. */
|
|
369
|
-
bogusOpen: boolean;
|
|
370
|
-
/** The RAW_TEXT_ELEMENTS element currently open (its content is text to
|
|
371
|
-
* parse5): tags and comment tokens are ignored until `</name>`. */
|
|
372
|
-
rawTextOpen: string | null;
|
|
373
|
-
inFence: boolean;
|
|
374
|
-
fenceChar: string;
|
|
375
|
-
fenceLen: number;
|
|
376
|
-
inMath: boolean;
|
|
377
|
-
/** Opening dollar-run length while inMath — the close run must match it. */
|
|
378
|
-
mathFenceLen: number;
|
|
379
|
-
/** Indent (0-3 spaces) of the line that opened the current fence/math
|
|
380
|
-
* block. Not a blocker input — read by `phantomSuffixCloser` to emit a
|
|
381
|
-
* closer at the SAME indent, which closes the block whether it sits at
|
|
382
|
-
* top level (≤3 spaces are allowed there) or inside a list item whose
|
|
383
|
-
* content indent the opener line already satisfies. */
|
|
384
|
-
openIndent: number;
|
|
385
|
-
blankRun: number;
|
|
386
|
-
lastBlankStart: number;
|
|
387
|
-
/** Rolling blocker-3 verdict ("nearest decisive block start so far"). */
|
|
388
|
-
hazardVerdict: boolean;
|
|
389
|
-
/** Previous confirmed line was blank (block-start detection). */
|
|
390
|
-
prevLineBlank: boolean;
|
|
391
|
-
/** Previous confirmed line was a plain text line (def-chain detection). */
|
|
392
|
-
prevLineWasText: boolean;
|
|
393
|
-
/** Previous confirmed line registered a VALID definition (def chains). */
|
|
394
|
-
prevLineWasValidDef: boolean;
|
|
395
|
-
/** An earlier line of the current paragraph left an unpaired backtick
|
|
396
|
-
* run — masking is disabled until the paragraph ends (safety gate). */
|
|
397
|
-
/** A `[` left unclosed at the end of a paragraph line (code spans
|
|
398
|
-
* masked). micromark lets a reference label span soft line breaks, so
|
|
399
|
-
* the label may close on a LATER line where the per-line REF_RE never
|
|
400
|
-
* sees a `[…]` pair (v2.4.1 review P1: `see [foo\nbar] end` + a late
|
|
401
|
-
* `[foo bar]: /u` retargeted frozen output). Cleared wherever the
|
|
402
|
-
* paragraph ends. */
|
|
403
|
-
openBracket: {
|
|
404
|
-
offset: number;
|
|
405
|
-
text: string;
|
|
406
|
-
} | null;
|
|
407
|
-
paragraphHasUnpairedRun: boolean;
|
|
408
|
-
/** Blocker-6 pending flag: a confirmed html-flow line left balanced
|
|
409
|
-
* floating raw remnant, and no later content line has pinned the seam
|
|
410
|
-
* yet. Persists across blank lines (every candidate emitted while set
|
|
411
|
-
* has the remnant as its last frozen child); cleared by the next
|
|
412
|
-
* non-blank line that starts OUTSIDE an html-flow run. */
|
|
413
|
-
htmlSeamPending: boolean;
|
|
414
|
-
/** A line since the last blank started with `<` at block indent — an html
|
|
415
|
-
* FLOW block is (approximately) running, and it only ends at a blank
|
|
416
|
-
* line. micromark does no inline parsing there: backtick runs are
|
|
417
|
-
* literal text, so code-span masking would hide REAL tags from the
|
|
418
|
-
* balance scan (under-block — fuzz counterexample: `</details>` followed
|
|
419
|
-
* by an unblanked `` `<div>` `` line). While set, masking is skipped —
|
|
420
|
-
* which can only over-block (safe direction). */
|
|
421
|
-
htmlFlowSinceBlank: boolean;
|
|
422
|
-
/** Offset of the first fence/math OPEN suppressed by `htmlFlowSinceBlank`
|
|
423
|
-
* (Infinity = none). Whether the run really swallowed that line depends
|
|
424
|
-
* on container context the line scan cannot see (`<embed` inside a list
|
|
425
|
-
* item is a lazy paragraph line, and the glued `$$` a REAL math open —
|
|
426
|
-
* seed-20260757 under-block: the tracker's fence phase INVERTS from that
|
|
427
|
-
* line on, every later close reads as an open, and the corruption never
|
|
428
|
-
* resyncs). Candidates past this offset are rejected outright — sticky,
|
|
429
|
-
* pure over-block; candidates before it are untouched (the ambiguous
|
|
430
|
-
* region then re-parses inside the tail). The rolling hazard poison for
|
|
431
|
-
* ambiguous tag names stays, but it decays at the next decisive block
|
|
432
|
-
* start — this field is the phase-corruption backstop that does not. */
|
|
433
|
-
phasePoisonedAt: number;
|
|
434
|
-
/** Tag names of line-truncated opens (`<div` at EOL) counted into
|
|
435
|
-
* tagBalance but not yet confirmed by a later `>` — reverted at the next
|
|
436
|
-
* blank line (a tag cannot span one). See TRUNCATED_TAG_RE. */
|
|
437
|
-
pendingTruncatedTags: string[];
|
|
438
|
-
/** Line-truncated CLOSING tags (`</div` + EOL, no `>`) inside an html-flow
|
|
439
|
-
* run, waiting for a `>` on a later line of the same run. Unlike opens
|
|
440
|
-
* they are NOT counted up front: a close tag cannot carry attributes, so
|
|
441
|
-
* `para </style` (prose to micromark, still-open element to parse5 —
|
|
442
|
-
* RAWTEXT waits for the `>`) must not zero the balance (2026-08-19
|
|
443
|
-
* review P1 — the boundary crossed an open `<style>`). Confirmed and
|
|
444
|
-
* applied only when a later line of the run brings the `>` (parse5
|
|
445
|
-
* completes the end tag; micromark's block ends at the blank anyway);
|
|
446
|
-
* dropped unapplied at the blank (element stays counted — over-block).
|
|
447
|
-
* Paragraph-context truncated closes are never pended: a `>` at block
|
|
448
|
-
* indent on the next line is a blockquote to micromark, and the one
|
|
449
|
-
* shape that would complete the inline close (`</b\n >`, a 4+-space
|
|
450
|
-
* lazy continuation) is not modelled — the element stays counted,
|
|
451
|
-
* over-block. */
|
|
452
|
-
pendingTruncatedCloses: string[];
|
|
453
|
-
/** An html-flow line ended inside a tag (`<div`, `</div`, `<br` — open,
|
|
454
|
-
* close or void, with or without attributes): parse5's tokenizer is
|
|
455
|
-
* still in that tag, so on the following lines everything up to the
|
|
456
|
-
* FIRST `>` is attribute garbage — `</div>` there does NOT close
|
|
457
|
-
* anything (oracle review of 2.4.4: `<div>\n<div>\n</div\n</div>` froze
|
|
458
|
-
* past the still-open outer div; pre-existing, 1-char slices). While
|
|
459
|
-
* set: a line without `>` gets no tag scan at all; the line with the
|
|
460
|
-
* `>` completes the pending close (if any), then only its text after
|
|
461
|
-
* that `>` is scanned. Cleared there and at the blank line. */
|
|
462
|
-
tagAcrossLines: boolean;
|
|
463
|
-
/** Indent of the line that set `tagAcrossLines`. A following line that
|
|
464
|
-
* DE-INDENTS below it may have left the container (a list item's html
|
|
465
|
-
* block ends there; hast-util-raw resets the tokenizer at the li/ul
|
|
466
|
-
* boundary, so a `<div>` on that line is a real start tag, not garbage)
|
|
467
|
-
* — or may still be the same html block (root-level ` </div\n</div>`,
|
|
468
|
-
* still garbage). Unknowable here → poison (oracle 3rd pass). */
|
|
469
|
-
tagAcrossLinesIndent: number;
|
|
470
|
-
/** parse5's position inside that tag's attribute area at the end of the
|
|
471
|
-
* last scanned line (see TagAttrState). A quoted value left open swallows
|
|
472
|
-
* `>` and line endings; a `>` that arrives while `outside` ends the tag. */
|
|
473
|
-
tagAcrossLinesState: TagAttrState;
|
|
474
|
-
/** The html-flow run since the last blank REALLY started as a micromark
|
|
475
|
-
* html block (type 6 / type 1 / a paragraph-not-interrupting type 7) —
|
|
476
|
-
* as opposed to `htmlFlowSinceBlank`, which any `<tag` / `</tag` line
|
|
477
|
-
* start sets (over-approximation, fine for its over-blocking uses). Only
|
|
478
|
-
* in a real run are the bytes raw to parse5 across line endings; the
|
|
479
|
-
* cross-line-tag garbage model (`tagAcrossLines`, pended closes) is
|
|
480
|
-
* gated on it — in a paragraph starting `</i` the next line's `<div>` /
|
|
481
|
-
* `<!--` are REAL blocks (oracle re-check of 2.4.4: gating on
|
|
482
|
-
* htmlFlowSinceBlank swallowed them — a new under-block). Sticky to the
|
|
483
|
-
* blank; a type 6/1 start on a later line of a non-real run promotes it. */
|
|
484
|
-
htmlFlowReal: boolean;
|
|
485
|
-
/** The run since the last blank was OPENED by a CommonMark type-1 block
|
|
486
|
-
* (`<script` / `<pre` / `<style` / `<textarea`). Type 1 is the one block
|
|
487
|
-
* that ends at its CLOSER line rather than at a blank, so `htmlFlowReal`
|
|
488
|
-
* being "sticky to the blank" over-ran it: the line after `</script>` is
|
|
489
|
-
* a fresh PARAGRAPH to micromark, but the scanner still treated it as
|
|
490
|
-
* raw html flow — and in a real run end tags may carry attributes, so a
|
|
491
|
-
* `</div a="b">` there was counted as a REAL close. `p <div> x </div
|
|
492
|
-
* a="b"> y` after a `</script>` line therefore froze past an element the
|
|
493
|
-
* actual parse leaves OPEN, nesting the whole rest of the document
|
|
494
|
-
* inside it (2026-08-20 soak leg 2; identical for pre/style/textarea,
|
|
495
|
-
* and correct as-is for a type-6 run, which really does reach the blank).
|
|
496
|
-
* Only set when the type-1 opener is the line that STARTED the run — a
|
|
497
|
-
* `<script>` nested inside an open type-6 block must not end it. */
|
|
498
|
-
type1FlowOpen: boolean;
|
|
499
|
-
/** The currently open raw-text element (`rawTextOpen`) was opened INLINE —
|
|
500
|
-
* in paragraph context rather than in a real html-flow run. */
|
|
501
|
-
rawTextInline: boolean;
|
|
502
|
-
/** The open-element stack, in order. `tagBalance` and `openTotal` are
|
|
503
|
-
* derived views kept in step with it, but the STACK is the truth: an end
|
|
504
|
-
* tag's effect depends on what sits BETWEEN it and its match, which a
|
|
505
|
-
* name→count bag cannot represent (see SCOPE_BARRIER_NAMES). */
|
|
506
|
-
openStack: string[];
|
|
507
|
-
/** parse5 is in "script data escaped": a `<!--` has been seen inside the
|
|
508
|
-
* open `<script>`. Only meaningful while `rawTextOpen === 'script'`.
|
|
509
|
-
* Deliberately NOT cleared by `-->` — staying escaped can only poison
|
|
510
|
-
* more often, which is the over-blocking side. */
|
|
511
|
-
scriptDataEscaped: boolean;
|
|
326
|
+
readonly '~freezeScanCheckpoint'?: never;
|
|
512
327
|
}
|
|
513
|
-
/** parse5 tokenizer position inside a tag's attribute area, tracked across
|
|
514
|
-
* line endings for `tagAcrossLines` (2026-08-19 review r2 P1-2 / P2-3):
|
|
515
|
-
* `outside` = before/in an attribute name (a `"` here starts a NAME, not a
|
|
516
|
-
* value); `afterEq` = just past `=`; `unquoted` = in an unquoted value
|
|
517
|
-
* (whitespace ends it); `"` / `'` = inside a quoted value — `>` and line
|
|
518
|
-
* endings are value bytes there, only the matching quote leaves it. */
|
|
519
|
-
type TagAttrState = 'outside' | 'afterEq' | 'unquoted' | '"' | "'";
|
|
520
328
|
declare function computeFreezeBoundary(text: string, options: FreezeBoundaryOptions, resume?: FreezeScanCheckpoint | null): FreezeScanResult;
|
|
521
329
|
|
|
522
330
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -316,207 +316,15 @@ interface FreezeScanResult {
|
|
|
316
316
|
* re-lexing the confirmed prefix. Single-consumer; see module docs. */
|
|
317
317
|
checkpoint: FreezeScanCheckpoint;
|
|
318
318
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
htmlBalanced: boolean;
|
|
326
|
-
/** Rolling continuation-hazard verdict at emission (blocker 3). */
|
|
327
|
-
hazard: boolean;
|
|
328
|
-
/** Blocker-6: the run ending at this blank left balanced FLOATING raw
|
|
329
|
-
* remnant whose hast seam is tail-dependent; reject this candidate. */
|
|
330
|
-
seamRisk: boolean;
|
|
331
|
-
/** Blocker-4 settle verdict, decided by the NEXT confirmed line (`null`
|
|
332
|
-
* while that line hasn't confirmed — only the newest candidate can be
|
|
333
|
-
* pending). Storing the verdict instead of the line lets the checkpoint
|
|
334
|
-
* drop its lines array, which retained a full copy of the document
|
|
335
|
-
* (round-2 review: ~2-3× doc size per mounted instance). */
|
|
336
|
-
defListSettled: boolean | null;
|
|
337
|
-
}
|
|
338
|
-
interface UnresolvedRef {
|
|
339
|
-
offset: number;
|
|
340
|
-
label: string;
|
|
341
|
-
footnote: boolean;
|
|
342
|
-
}
|
|
343
|
-
/** Mutable resume state. All fields describe the scan strictly BEFORE the
|
|
344
|
-
* first unconfirmed character (`confirmedOffset`). */
|
|
319
|
+
/** Opaque resume token. Produced by one `computeFreezeBoundary` call and
|
|
320
|
+
* passed back on the next APPEND-ONLY call; the only supported operations
|
|
321
|
+
* are storing it and passing it back. The field set is an implementation
|
|
322
|
+
* detail of the scanner and changes between minor versions — the brand key
|
|
323
|
+
* (a structural string literal, safe across dual d.ts entries) is all that
|
|
324
|
+
* ships in the public type. */
|
|
345
325
|
interface FreezeScanCheckpoint {
|
|
346
|
-
|
|
347
|
-
/** Grammar-profile switches baked at creation — a checkpoint is only
|
|
348
|
-
* resumable under the exact profile that built it. */
|
|
349
|
-
mathFlow: boolean;
|
|
350
|
-
referenceTaint: boolean;
|
|
351
|
-
/** Start offset of the first line NOT yet baked into this checkpoint. */
|
|
352
|
-
confirmedOffset: number;
|
|
353
|
-
candidates: Candidate[];
|
|
354
|
-
defs: Map<string, number>;
|
|
355
|
-
footnoteDefs: Map<string, number>;
|
|
356
|
-
unresolvedRefs: UnresolvedRef[];
|
|
357
|
-
tagBalance: Map<string, number>;
|
|
358
|
-
openTotal: number;
|
|
359
|
-
commentOpen: boolean;
|
|
360
|
-
piOpen: boolean;
|
|
361
|
-
declOpen: boolean;
|
|
362
|
-
cdataOpen: boolean;
|
|
363
|
-
/** parse5 BOGUS COMMENT open inside a real html-flow run: `<!` not
|
|
364
|
-
* followed by `--` / letter / `[CDATA[`, or `</` not followed by a
|
|
365
|
-
* letter (`<!\n`, `<!-`, `</\n`, `<//`) — eaten up to the next `>`;
|
|
366
|
-
* a `</div>` inside is comment text, not a close (2026-08-19 review r2
|
|
367
|
-
* P1-3: the balance zeroed past an open div). micromark has no such
|
|
368
|
-
* construct: those bytes are just html-block content. */
|
|
369
|
-
bogusOpen: boolean;
|
|
370
|
-
/** The RAW_TEXT_ELEMENTS element currently open (its content is text to
|
|
371
|
-
* parse5): tags and comment tokens are ignored until `</name>`. */
|
|
372
|
-
rawTextOpen: string | null;
|
|
373
|
-
inFence: boolean;
|
|
374
|
-
fenceChar: string;
|
|
375
|
-
fenceLen: number;
|
|
376
|
-
inMath: boolean;
|
|
377
|
-
/** Opening dollar-run length while inMath — the close run must match it. */
|
|
378
|
-
mathFenceLen: number;
|
|
379
|
-
/** Indent (0-3 spaces) of the line that opened the current fence/math
|
|
380
|
-
* block. Not a blocker input — read by `phantomSuffixCloser` to emit a
|
|
381
|
-
* closer at the SAME indent, which closes the block whether it sits at
|
|
382
|
-
* top level (≤3 spaces are allowed there) or inside a list item whose
|
|
383
|
-
* content indent the opener line already satisfies. */
|
|
384
|
-
openIndent: number;
|
|
385
|
-
blankRun: number;
|
|
386
|
-
lastBlankStart: number;
|
|
387
|
-
/** Rolling blocker-3 verdict ("nearest decisive block start so far"). */
|
|
388
|
-
hazardVerdict: boolean;
|
|
389
|
-
/** Previous confirmed line was blank (block-start detection). */
|
|
390
|
-
prevLineBlank: boolean;
|
|
391
|
-
/** Previous confirmed line was a plain text line (def-chain detection). */
|
|
392
|
-
prevLineWasText: boolean;
|
|
393
|
-
/** Previous confirmed line registered a VALID definition (def chains). */
|
|
394
|
-
prevLineWasValidDef: boolean;
|
|
395
|
-
/** An earlier line of the current paragraph left an unpaired backtick
|
|
396
|
-
* run — masking is disabled until the paragraph ends (safety gate). */
|
|
397
|
-
/** A `[` left unclosed at the end of a paragraph line (code spans
|
|
398
|
-
* masked). micromark lets a reference label span soft line breaks, so
|
|
399
|
-
* the label may close on a LATER line where the per-line REF_RE never
|
|
400
|
-
* sees a `[…]` pair (v2.4.1 review P1: `see [foo\nbar] end` + a late
|
|
401
|
-
* `[foo bar]: /u` retargeted frozen output). Cleared wherever the
|
|
402
|
-
* paragraph ends. */
|
|
403
|
-
openBracket: {
|
|
404
|
-
offset: number;
|
|
405
|
-
text: string;
|
|
406
|
-
} | null;
|
|
407
|
-
paragraphHasUnpairedRun: boolean;
|
|
408
|
-
/** Blocker-6 pending flag: a confirmed html-flow line left balanced
|
|
409
|
-
* floating raw remnant, and no later content line has pinned the seam
|
|
410
|
-
* yet. Persists across blank lines (every candidate emitted while set
|
|
411
|
-
* has the remnant as its last frozen child); cleared by the next
|
|
412
|
-
* non-blank line that starts OUTSIDE an html-flow run. */
|
|
413
|
-
htmlSeamPending: boolean;
|
|
414
|
-
/** A line since the last blank started with `<` at block indent — an html
|
|
415
|
-
* FLOW block is (approximately) running, and it only ends at a blank
|
|
416
|
-
* line. micromark does no inline parsing there: backtick runs are
|
|
417
|
-
* literal text, so code-span masking would hide REAL tags from the
|
|
418
|
-
* balance scan (under-block — fuzz counterexample: `</details>` followed
|
|
419
|
-
* by an unblanked `` `<div>` `` line). While set, masking is skipped —
|
|
420
|
-
* which can only over-block (safe direction). */
|
|
421
|
-
htmlFlowSinceBlank: boolean;
|
|
422
|
-
/** Offset of the first fence/math OPEN suppressed by `htmlFlowSinceBlank`
|
|
423
|
-
* (Infinity = none). Whether the run really swallowed that line depends
|
|
424
|
-
* on container context the line scan cannot see (`<embed` inside a list
|
|
425
|
-
* item is a lazy paragraph line, and the glued `$$` a REAL math open —
|
|
426
|
-
* seed-20260757 under-block: the tracker's fence phase INVERTS from that
|
|
427
|
-
* line on, every later close reads as an open, and the corruption never
|
|
428
|
-
* resyncs). Candidates past this offset are rejected outright — sticky,
|
|
429
|
-
* pure over-block; candidates before it are untouched (the ambiguous
|
|
430
|
-
* region then re-parses inside the tail). The rolling hazard poison for
|
|
431
|
-
* ambiguous tag names stays, but it decays at the next decisive block
|
|
432
|
-
* start — this field is the phase-corruption backstop that does not. */
|
|
433
|
-
phasePoisonedAt: number;
|
|
434
|
-
/** Tag names of line-truncated opens (`<div` at EOL) counted into
|
|
435
|
-
* tagBalance but not yet confirmed by a later `>` — reverted at the next
|
|
436
|
-
* blank line (a tag cannot span one). See TRUNCATED_TAG_RE. */
|
|
437
|
-
pendingTruncatedTags: string[];
|
|
438
|
-
/** Line-truncated CLOSING tags (`</div` + EOL, no `>`) inside an html-flow
|
|
439
|
-
* run, waiting for a `>` on a later line of the same run. Unlike opens
|
|
440
|
-
* they are NOT counted up front: a close tag cannot carry attributes, so
|
|
441
|
-
* `para </style` (prose to micromark, still-open element to parse5 —
|
|
442
|
-
* RAWTEXT waits for the `>`) must not zero the balance (2026-08-19
|
|
443
|
-
* review P1 — the boundary crossed an open `<style>`). Confirmed and
|
|
444
|
-
* applied only when a later line of the run brings the `>` (parse5
|
|
445
|
-
* completes the end tag; micromark's block ends at the blank anyway);
|
|
446
|
-
* dropped unapplied at the blank (element stays counted — over-block).
|
|
447
|
-
* Paragraph-context truncated closes are never pended: a `>` at block
|
|
448
|
-
* indent on the next line is a blockquote to micromark, and the one
|
|
449
|
-
* shape that would complete the inline close (`</b\n >`, a 4+-space
|
|
450
|
-
* lazy continuation) is not modelled — the element stays counted,
|
|
451
|
-
* over-block. */
|
|
452
|
-
pendingTruncatedCloses: string[];
|
|
453
|
-
/** An html-flow line ended inside a tag (`<div`, `</div`, `<br` — open,
|
|
454
|
-
* close or void, with or without attributes): parse5's tokenizer is
|
|
455
|
-
* still in that tag, so on the following lines everything up to the
|
|
456
|
-
* FIRST `>` is attribute garbage — `</div>` there does NOT close
|
|
457
|
-
* anything (oracle review of 2.4.4: `<div>\n<div>\n</div\n</div>` froze
|
|
458
|
-
* past the still-open outer div; pre-existing, 1-char slices). While
|
|
459
|
-
* set: a line without `>` gets no tag scan at all; the line with the
|
|
460
|
-
* `>` completes the pending close (if any), then only its text after
|
|
461
|
-
* that `>` is scanned. Cleared there and at the blank line. */
|
|
462
|
-
tagAcrossLines: boolean;
|
|
463
|
-
/** Indent of the line that set `tagAcrossLines`. A following line that
|
|
464
|
-
* DE-INDENTS below it may have left the container (a list item's html
|
|
465
|
-
* block ends there; hast-util-raw resets the tokenizer at the li/ul
|
|
466
|
-
* boundary, so a `<div>` on that line is a real start tag, not garbage)
|
|
467
|
-
* — or may still be the same html block (root-level ` </div\n</div>`,
|
|
468
|
-
* still garbage). Unknowable here → poison (oracle 3rd pass). */
|
|
469
|
-
tagAcrossLinesIndent: number;
|
|
470
|
-
/** parse5's position inside that tag's attribute area at the end of the
|
|
471
|
-
* last scanned line (see TagAttrState). A quoted value left open swallows
|
|
472
|
-
* `>` and line endings; a `>` that arrives while `outside` ends the tag. */
|
|
473
|
-
tagAcrossLinesState: TagAttrState;
|
|
474
|
-
/** The html-flow run since the last blank REALLY started as a micromark
|
|
475
|
-
* html block (type 6 / type 1 / a paragraph-not-interrupting type 7) —
|
|
476
|
-
* as opposed to `htmlFlowSinceBlank`, which any `<tag` / `</tag` line
|
|
477
|
-
* start sets (over-approximation, fine for its over-blocking uses). Only
|
|
478
|
-
* in a real run are the bytes raw to parse5 across line endings; the
|
|
479
|
-
* cross-line-tag garbage model (`tagAcrossLines`, pended closes) is
|
|
480
|
-
* gated on it — in a paragraph starting `</i` the next line's `<div>` /
|
|
481
|
-
* `<!--` are REAL blocks (oracle re-check of 2.4.4: gating on
|
|
482
|
-
* htmlFlowSinceBlank swallowed them — a new under-block). Sticky to the
|
|
483
|
-
* blank; a type 6/1 start on a later line of a non-real run promotes it. */
|
|
484
|
-
htmlFlowReal: boolean;
|
|
485
|
-
/** The run since the last blank was OPENED by a CommonMark type-1 block
|
|
486
|
-
* (`<script` / `<pre` / `<style` / `<textarea`). Type 1 is the one block
|
|
487
|
-
* that ends at its CLOSER line rather than at a blank, so `htmlFlowReal`
|
|
488
|
-
* being "sticky to the blank" over-ran it: the line after `</script>` is
|
|
489
|
-
* a fresh PARAGRAPH to micromark, but the scanner still treated it as
|
|
490
|
-
* raw html flow — and in a real run end tags may carry attributes, so a
|
|
491
|
-
* `</div a="b">` there was counted as a REAL close. `p <div> x </div
|
|
492
|
-
* a="b"> y` after a `</script>` line therefore froze past an element the
|
|
493
|
-
* actual parse leaves OPEN, nesting the whole rest of the document
|
|
494
|
-
* inside it (2026-08-20 soak leg 2; identical for pre/style/textarea,
|
|
495
|
-
* and correct as-is for a type-6 run, which really does reach the blank).
|
|
496
|
-
* Only set when the type-1 opener is the line that STARTED the run — a
|
|
497
|
-
* `<script>` nested inside an open type-6 block must not end it. */
|
|
498
|
-
type1FlowOpen: boolean;
|
|
499
|
-
/** The currently open raw-text element (`rawTextOpen`) was opened INLINE —
|
|
500
|
-
* in paragraph context rather than in a real html-flow run. */
|
|
501
|
-
rawTextInline: boolean;
|
|
502
|
-
/** The open-element stack, in order. `tagBalance` and `openTotal` are
|
|
503
|
-
* derived views kept in step with it, but the STACK is the truth: an end
|
|
504
|
-
* tag's effect depends on what sits BETWEEN it and its match, which a
|
|
505
|
-
* name→count bag cannot represent (see SCOPE_BARRIER_NAMES). */
|
|
506
|
-
openStack: string[];
|
|
507
|
-
/** parse5 is in "script data escaped": a `<!--` has been seen inside the
|
|
508
|
-
* open `<script>`. Only meaningful while `rawTextOpen === 'script'`.
|
|
509
|
-
* Deliberately NOT cleared by `-->` — staying escaped can only poison
|
|
510
|
-
* more often, which is the over-blocking side. */
|
|
511
|
-
scriptDataEscaped: boolean;
|
|
326
|
+
readonly '~freezeScanCheckpoint'?: never;
|
|
512
327
|
}
|
|
513
|
-
/** parse5 tokenizer position inside a tag's attribute area, tracked across
|
|
514
|
-
* line endings for `tagAcrossLines` (2026-08-19 review r2 P1-2 / P2-3):
|
|
515
|
-
* `outside` = before/in an attribute name (a `"` here starts a NAME, not a
|
|
516
|
-
* value); `afterEq` = just past `=`; `unquoted` = in an unquoted value
|
|
517
|
-
* (whitespace ends it); `"` / `'` = inside a quoted value — `>` and line
|
|
518
|
-
* endings are value bytes there, only the matching quote leaves it. */
|
|
519
|
-
type TagAttrState = 'outside' | 'afterEq' | 'unquoted' | '"' | "'";
|
|
520
328
|
declare function computeFreezeBoundary(text: string, options: FreezeBoundaryOptions, resume?: FreezeScanCheckpoint | null): FreezeScanResult;
|
|
521
329
|
|
|
522
330
|
/**
|
package/dist/index.dev.cjs
CHANGED
|
@@ -651,7 +651,8 @@ function classifyBlockStart(text, indent, defListEnabled) {
|
|
|
651
651
|
function computeFreezeBoundary(text, options, resume) {
|
|
652
652
|
const mathFlow = options.mathFlow ?? true;
|
|
653
653
|
const referenceTaint = options.referenceTaint ?? true;
|
|
654
|
-
const
|
|
654
|
+
const prev = resume;
|
|
655
|
+
const cp = prev && prev.defListEnabled === options.defListEnabled && prev.mathFlow === mathFlow && prev.referenceTaint === referenceTaint && prev.confirmedOffset <= text.length ? prev : freshCheckpoint(options.defListEnabled, mathFlow, referenceTaint);
|
|
655
656
|
let start = cp.confirmedOffset;
|
|
656
657
|
let tailLine = null;
|
|
657
658
|
while (start < text.length) {
|
|
@@ -714,6 +715,14 @@ function computeFreezeBoundary(text, options, resume) {
|
|
|
714
715
|
}
|
|
715
716
|
return { boundary, checkpoint: cp };
|
|
716
717
|
}
|
|
718
|
+
function pendingFenceCloser(checkpoint) {
|
|
719
|
+
const cp = checkpoint;
|
|
720
|
+
if (cp.phasePoisonedAt !== Infinity) return "";
|
|
721
|
+
if (cp.openIndent !== 0) return "";
|
|
722
|
+
if (cp.inFence) return cp.fenceChar.repeat(cp.fenceLen);
|
|
723
|
+
if (cp.inMath) return "$".repeat(cp.mathFenceLen);
|
|
724
|
+
return "";
|
|
725
|
+
}
|
|
717
726
|
function floatingResidue(text, commentOpenAtStart) {
|
|
718
727
|
let out = "";
|
|
719
728
|
let open = commentOpenAtStart;
|
|
@@ -2265,12 +2274,10 @@ function phantomSuffixCloser(content) {
|
|
|
2265
2274
|
const endsWithNewline = content.endsWith("\n");
|
|
2266
2275
|
const confirmed = endsWithNewline ? content : content + "\n";
|
|
2267
2276
|
const { checkpoint } = computeFreezeBoundary(confirmed, { defListEnabled: false, referenceTaint: false });
|
|
2268
|
-
|
|
2269
|
-
if (
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
if (checkpoint.inMath) return `${nl}${"$".repeat(checkpoint.mathFenceLen)}`;
|
|
2273
|
-
return "";
|
|
2277
|
+
const closer = pendingFenceCloser(checkpoint);
|
|
2278
|
+
if (closer === "") return "";
|
|
2279
|
+
return endsWithNewline ? closer : `
|
|
2280
|
+
${closer}`;
|
|
2274
2281
|
}
|
|
2275
2282
|
|
|
2276
2283
|
// src/components/extractContributions.ts
|