@ai-react-markdown/engine 2.9.0 → 2.10.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 +69 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -36
- package/dist/index.d.ts +68 -36
- package/dist/index.dev.cjs +71 -40
- package/dist/index.dev.cjs.map +1 -1
- package/dist/index.dev.js +71 -40
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +69 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1498,22 +1498,29 @@ declare const sanitizeSchema: Schema;
|
|
|
1498
1498
|
* exactly the incremental-parse engine's fast path — the controller sits
|
|
1499
1499
|
* upstream of the renderer and never touches the parse pipeline.
|
|
1500
1500
|
*
|
|
1501
|
-
* Pacing model —
|
|
1502
|
-
*
|
|
1503
|
-
*
|
|
1504
|
-
*
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1508
|
-
*
|
|
1509
|
-
*
|
|
1510
|
-
*
|
|
1511
|
-
*
|
|
1512
|
-
*
|
|
1513
|
-
*
|
|
1501
|
+
* Pacing model — a completion-deadline law over a gap-quantile estimator
|
|
1502
|
+
* (v2.10 redesign; the prior water-level jitter buffer's rationale and the
|
|
1503
|
+
* falsified alternatives live in the archived design plan):
|
|
1504
|
+
* - Every inter-arrival gap enters a small sliding window — there is NO
|
|
1505
|
+
* pause classifier. The target interval Î is a high quantile of that
|
|
1506
|
+
* window: two slow-gap confirmations flip the controller into a slower
|
|
1507
|
+
* mode, while leaving it takes the window turning over ("cautious
|
|
1508
|
+
* fast, aggressive slow").
|
|
1509
|
+
* - Streaming: everything on hand should be on screen by the time the
|
|
1510
|
+
* next lump is expected. The horizon H = clamp(bufferFactor × Î + pad,
|
|
1511
|
+
* 16, maxLagMs) stamps a deadline at the last arrival + H, and
|
|
1512
|
+
* rate = backlog / time-to-deadline — constant within a period, so a
|
|
1513
|
+
* coarse feed reads as an even typewriter, not pour-then-crawl. The
|
|
1514
|
+
* floor is a tiny anti-freeze trickle. `maxLagMs` is the preset's
|
|
1515
|
+
* max-lag promise AND the pause handler: a gap beyond it saturates H
|
|
1516
|
+
* and cannot change any further decision.
|
|
1517
|
+
* - Pre-stats (first lump after construction/snap — no gap sample yet):
|
|
1518
|
+
* the backlog reveals over roughly one correction window.
|
|
1514
1519
|
* - Finished: rate = backlog / time-to-deadline, deadline stamped at
|
|
1515
|
-
* `finish() +
|
|
1516
|
-
*
|
|
1520
|
+
* `finish()` + a rate-continuity window — the tail reveals at most
|
|
1521
|
+
* ~2× the stream's measured throughput, clamped to [drainMs, 3×drainMs]
|
|
1522
|
+
* — so the backlog empties BY the deadline without an end-of-message
|
|
1523
|
+
* pour.
|
|
1517
1524
|
* - A deadline credit accumulator converts elapsed time (injectable
|
|
1518
1525
|
* `now()`) into whole-grapheme reveals per scheduled frame — timers
|
|
1519
1526
|
* carry no state between frames, so throttled/paused schedulers
|
|
@@ -1538,39 +1545,63 @@ declare const sanitizeSchema: Schema;
|
|
|
1538
1545
|
* latency-vs-smoothness axis (the audio-plugin buffer-preset convention —
|
|
1539
1546
|
* perceptual parameters resist meaningful numeric tuning).
|
|
1540
1547
|
*
|
|
1541
|
-
* - `'smooth'` —
|
|
1542
|
-
* between server flushes,
|
|
1543
|
-
* - `'balanced'` (default) — ~1
|
|
1544
|
-
*
|
|
1545
|
-
* - `'responsive'` —
|
|
1546
|
-
* visible
|
|
1548
|
+
* - `'smooth'` — ~1.7 delivery intervals of runway (max lag 3.5s): extra
|
|
1549
|
+
* slack between server flushes, the most delivery coarseness absorbed.
|
|
1550
|
+
* - `'balanced'` (default) — ~1 interval of runway (max lag 2.5s): even
|
|
1551
|
+
* pacing for delivery intervals up to ~2.5s at minimal lag.
|
|
1552
|
+
* - `'responsive'` — ~0.45 of an interval (max lag 0.8s): lowest lag,
|
|
1553
|
+
* accepts visible pauses on coarse or bursty delivery.
|
|
1547
1554
|
*/
|
|
1548
1555
|
type SmoothStreamPacing = 'smooth' | 'balanced' | 'responsive';
|
|
1549
1556
|
/** The numeric parameter bundle a {@link SmoothStreamPacing} preset names. */
|
|
1550
1557
|
interface SmoothStreamPacingParams {
|
|
1551
|
-
/**
|
|
1558
|
+
/**
|
|
1559
|
+
* Horizon multiple — "periods of runway": the reveal deadline sits this
|
|
1560
|
+
* many expected delivery intervals after the last arrival. 1.0 means
|
|
1561
|
+
* everything on hand is on screen just as the next chunk is expected.
|
|
1562
|
+
*/
|
|
1552
1563
|
bufferFactor: number;
|
|
1553
1564
|
/**
|
|
1554
|
-
*
|
|
1555
|
-
*
|
|
1556
|
-
*
|
|
1565
|
+
* Pre-stats reveal window (ms) for the FIRST lump of a stream, before
|
|
1566
|
+
* any inter-arrival sample exists. The streaming path no longer reads
|
|
1567
|
+
* it — the v2.10 deadline law replaced the old feedback term it used to
|
|
1568
|
+
* time-constant.
|
|
1557
1569
|
*/
|
|
1558
1570
|
correctionTauMs: number;
|
|
1559
|
-
/**
|
|
1571
|
+
/**
|
|
1572
|
+
* @deprecated Read by nothing since the v2.10 deadline-law redesign (it
|
|
1573
|
+
* used to be the EMA horizon AND, harmfully, the pause-classifier
|
|
1574
|
+
* threshold — the "1.8s cliff"). Kept in the preset objects so their
|
|
1575
|
+
* exported shape is unchanged; setting it has no effect.
|
|
1576
|
+
*/
|
|
1560
1577
|
emaTauMs: number;
|
|
1578
|
+
/**
|
|
1579
|
+
* The preset's max-lag promise (ms): the reveal DEADLINE never targets
|
|
1580
|
+
* more than this far behind the live source (a throttled scheduler can
|
|
1581
|
+
* transiently exceed it; the next tick self-corrects). It is also the
|
|
1582
|
+
* whole pause story —
|
|
1583
|
+
* a gap longer than `maxLagMs / bufferFactor` saturates the horizon and
|
|
1584
|
+
* cannot change any further decision. Pay-per-use: a fine-grained
|
|
1585
|
+
* stream's horizon tracks its own (small) cadence and never approaches
|
|
1586
|
+
* this cap. Full smoothing of a coarse feed requires
|
|
1587
|
+
* delivery-interval ≤ maxLagMs (bufferFactor ≥ 1 presets); steady mean
|
|
1588
|
+
* lag there is about half the delivery period.
|
|
1589
|
+
*/
|
|
1590
|
+
maxLagMs?: number;
|
|
1561
1591
|
/**
|
|
1562
1592
|
* Anti-freeze floor (grapheme clusters/s). Deliberately tiny — smaller
|
|
1563
|
-
* than any realistic arrival rate —
|
|
1564
|
-
*
|
|
1565
|
-
* freezing visible progress entirely.
|
|
1593
|
+
* than any realistic arrival rate — a last-resort trickle so visible
|
|
1594
|
+
* progress never freezes entirely while anything is pending.
|
|
1566
1595
|
*/
|
|
1567
1596
|
minCharsPerSecond: number;
|
|
1568
1597
|
/**
|
|
1569
|
-
*
|
|
1570
|
-
* deadline is stamped at `finish()
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1598
|
+
* Drain-budget FLOOR after {@link SmoothStreamController.finish}: the
|
|
1599
|
+
* drain deadline is stamped at `finish()` plus a rate-continuity window
|
|
1600
|
+
* — enough time that the tail reveals at ~2× the stream's measured
|
|
1601
|
+
* throughput — clamped to `[drainMs, 3 × drainMs]`. Short backlogs
|
|
1602
|
+
* behave exactly as the pre-v2.10 fixed window did. Consumed when the
|
|
1603
|
+
* deadline is stamped — changing it affects the next drain, not one in
|
|
1604
|
+
* progress.
|
|
1574
1605
|
*/
|
|
1575
1606
|
drainMs: number;
|
|
1576
1607
|
}
|
|
@@ -1609,8 +1640,9 @@ interface SmoothStreamController {
|
|
|
1609
1640
|
update(source: string): void;
|
|
1610
1641
|
/**
|
|
1611
1642
|
* Signals end of stream: confirms the held-back trailing grapheme and
|
|
1612
|
-
* switches the control law to the
|
|
1613
|
-
* a later {@link update} resumes
|
|
1643
|
+
* switches the control law to the rate-continuity drain window (floored
|
|
1644
|
+
* at `drainMs`). Not terminal — a later {@link update} resumes
|
|
1645
|
+
* animation.
|
|
1614
1646
|
*/
|
|
1615
1647
|
finish(): void;
|
|
1616
1648
|
/** Jumps to `source` instantly, no animation, and clears any backlog.
|
package/dist/index.d.ts
CHANGED
|
@@ -1498,22 +1498,29 @@ declare const sanitizeSchema: Schema;
|
|
|
1498
1498
|
* exactly the incremental-parse engine's fast path — the controller sits
|
|
1499
1499
|
* upstream of the renderer and never touches the parse pipeline.
|
|
1500
1500
|
*
|
|
1501
|
-
* Pacing model —
|
|
1502
|
-
*
|
|
1503
|
-
*
|
|
1504
|
-
*
|
|
1505
|
-
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1508
|
-
*
|
|
1509
|
-
*
|
|
1510
|
-
*
|
|
1511
|
-
*
|
|
1512
|
-
*
|
|
1513
|
-
*
|
|
1501
|
+
* Pacing model — a completion-deadline law over a gap-quantile estimator
|
|
1502
|
+
* (v2.10 redesign; the prior water-level jitter buffer's rationale and the
|
|
1503
|
+
* falsified alternatives live in the archived design plan):
|
|
1504
|
+
* - Every inter-arrival gap enters a small sliding window — there is NO
|
|
1505
|
+
* pause classifier. The target interval Î is a high quantile of that
|
|
1506
|
+
* window: two slow-gap confirmations flip the controller into a slower
|
|
1507
|
+
* mode, while leaving it takes the window turning over ("cautious
|
|
1508
|
+
* fast, aggressive slow").
|
|
1509
|
+
* - Streaming: everything on hand should be on screen by the time the
|
|
1510
|
+
* next lump is expected. The horizon H = clamp(bufferFactor × Î + pad,
|
|
1511
|
+
* 16, maxLagMs) stamps a deadline at the last arrival + H, and
|
|
1512
|
+
* rate = backlog / time-to-deadline — constant within a period, so a
|
|
1513
|
+
* coarse feed reads as an even typewriter, not pour-then-crawl. The
|
|
1514
|
+
* floor is a tiny anti-freeze trickle. `maxLagMs` is the preset's
|
|
1515
|
+
* max-lag promise AND the pause handler: a gap beyond it saturates H
|
|
1516
|
+
* and cannot change any further decision.
|
|
1517
|
+
* - Pre-stats (first lump after construction/snap — no gap sample yet):
|
|
1518
|
+
* the backlog reveals over roughly one correction window.
|
|
1514
1519
|
* - Finished: rate = backlog / time-to-deadline, deadline stamped at
|
|
1515
|
-
* `finish() +
|
|
1516
|
-
*
|
|
1520
|
+
* `finish()` + a rate-continuity window — the tail reveals at most
|
|
1521
|
+
* ~2× the stream's measured throughput, clamped to [drainMs, 3×drainMs]
|
|
1522
|
+
* — so the backlog empties BY the deadline without an end-of-message
|
|
1523
|
+
* pour.
|
|
1517
1524
|
* - A deadline credit accumulator converts elapsed time (injectable
|
|
1518
1525
|
* `now()`) into whole-grapheme reveals per scheduled frame — timers
|
|
1519
1526
|
* carry no state between frames, so throttled/paused schedulers
|
|
@@ -1538,39 +1545,63 @@ declare const sanitizeSchema: Schema;
|
|
|
1538
1545
|
* latency-vs-smoothness axis (the audio-plugin buffer-preset convention —
|
|
1539
1546
|
* perceptual parameters resist meaningful numeric tuning).
|
|
1540
1547
|
*
|
|
1541
|
-
* - `'smooth'` —
|
|
1542
|
-
* between server flushes,
|
|
1543
|
-
* - `'balanced'` (default) — ~1
|
|
1544
|
-
*
|
|
1545
|
-
* - `'responsive'` —
|
|
1546
|
-
* visible
|
|
1548
|
+
* - `'smooth'` — ~1.7 delivery intervals of runway (max lag 3.5s): extra
|
|
1549
|
+
* slack between server flushes, the most delivery coarseness absorbed.
|
|
1550
|
+
* - `'balanced'` (default) — ~1 interval of runway (max lag 2.5s): even
|
|
1551
|
+
* pacing for delivery intervals up to ~2.5s at minimal lag.
|
|
1552
|
+
* - `'responsive'` — ~0.45 of an interval (max lag 0.8s): lowest lag,
|
|
1553
|
+
* accepts visible pauses on coarse or bursty delivery.
|
|
1547
1554
|
*/
|
|
1548
1555
|
type SmoothStreamPacing = 'smooth' | 'balanced' | 'responsive';
|
|
1549
1556
|
/** The numeric parameter bundle a {@link SmoothStreamPacing} preset names. */
|
|
1550
1557
|
interface SmoothStreamPacingParams {
|
|
1551
|
-
/**
|
|
1558
|
+
/**
|
|
1559
|
+
* Horizon multiple — "periods of runway": the reveal deadline sits this
|
|
1560
|
+
* many expected delivery intervals after the last arrival. 1.0 means
|
|
1561
|
+
* everything on hand is on screen just as the next chunk is expected.
|
|
1562
|
+
*/
|
|
1552
1563
|
bufferFactor: number;
|
|
1553
1564
|
/**
|
|
1554
|
-
*
|
|
1555
|
-
*
|
|
1556
|
-
*
|
|
1565
|
+
* Pre-stats reveal window (ms) for the FIRST lump of a stream, before
|
|
1566
|
+
* any inter-arrival sample exists. The streaming path no longer reads
|
|
1567
|
+
* it — the v2.10 deadline law replaced the old feedback term it used to
|
|
1568
|
+
* time-constant.
|
|
1557
1569
|
*/
|
|
1558
1570
|
correctionTauMs: number;
|
|
1559
|
-
/**
|
|
1571
|
+
/**
|
|
1572
|
+
* @deprecated Read by nothing since the v2.10 deadline-law redesign (it
|
|
1573
|
+
* used to be the EMA horizon AND, harmfully, the pause-classifier
|
|
1574
|
+
* threshold — the "1.8s cliff"). Kept in the preset objects so their
|
|
1575
|
+
* exported shape is unchanged; setting it has no effect.
|
|
1576
|
+
*/
|
|
1560
1577
|
emaTauMs: number;
|
|
1578
|
+
/**
|
|
1579
|
+
* The preset's max-lag promise (ms): the reveal DEADLINE never targets
|
|
1580
|
+
* more than this far behind the live source (a throttled scheduler can
|
|
1581
|
+
* transiently exceed it; the next tick self-corrects). It is also the
|
|
1582
|
+
* whole pause story —
|
|
1583
|
+
* a gap longer than `maxLagMs / bufferFactor` saturates the horizon and
|
|
1584
|
+
* cannot change any further decision. Pay-per-use: a fine-grained
|
|
1585
|
+
* stream's horizon tracks its own (small) cadence and never approaches
|
|
1586
|
+
* this cap. Full smoothing of a coarse feed requires
|
|
1587
|
+
* delivery-interval ≤ maxLagMs (bufferFactor ≥ 1 presets); steady mean
|
|
1588
|
+
* lag there is about half the delivery period.
|
|
1589
|
+
*/
|
|
1590
|
+
maxLagMs?: number;
|
|
1561
1591
|
/**
|
|
1562
1592
|
* Anti-freeze floor (grapheme clusters/s). Deliberately tiny — smaller
|
|
1563
|
-
* than any realistic arrival rate —
|
|
1564
|
-
*
|
|
1565
|
-
* freezing visible progress entirely.
|
|
1593
|
+
* than any realistic arrival rate — a last-resort trickle so visible
|
|
1594
|
+
* progress never freezes entirely while anything is pending.
|
|
1566
1595
|
*/
|
|
1567
1596
|
minCharsPerSecond: number;
|
|
1568
1597
|
/**
|
|
1569
|
-
*
|
|
1570
|
-
* deadline is stamped at `finish()
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1598
|
+
* Drain-budget FLOOR after {@link SmoothStreamController.finish}: the
|
|
1599
|
+
* drain deadline is stamped at `finish()` plus a rate-continuity window
|
|
1600
|
+
* — enough time that the tail reveals at ~2× the stream's measured
|
|
1601
|
+
* throughput — clamped to `[drainMs, 3 × drainMs]`. Short backlogs
|
|
1602
|
+
* behave exactly as the pre-v2.10 fixed window did. Consumed when the
|
|
1603
|
+
* deadline is stamped — changing it affects the next drain, not one in
|
|
1604
|
+
* progress.
|
|
1574
1605
|
*/
|
|
1575
1606
|
drainMs: number;
|
|
1576
1607
|
}
|
|
@@ -1609,8 +1640,9 @@ interface SmoothStreamController {
|
|
|
1609
1640
|
update(source: string): void;
|
|
1610
1641
|
/**
|
|
1611
1642
|
* Signals end of stream: confirms the held-back trailing grapheme and
|
|
1612
|
-
* switches the control law to the
|
|
1613
|
-
* a later {@link update} resumes
|
|
1643
|
+
* switches the control law to the rate-continuity drain window (floored
|
|
1644
|
+
* at `drainMs`). Not terminal — a later {@link update} resumes
|
|
1645
|
+
* animation.
|
|
1614
1646
|
*/
|
|
1615
1647
|
finish(): void;
|
|
1616
1648
|
/** Jumps to `source` instantly, no animation, and clears any backlog.
|
package/dist/index.dev.cjs
CHANGED
|
@@ -459,16 +459,15 @@ function settleRefsAndEarliestUnresolved(cp) {
|
|
|
459
459
|
var TYPE6_NAMES = new Set(import_micromark_util_html_tag_name.htmlBlockNames);
|
|
460
460
|
var TABLE_PART_NAMES = /* @__PURE__ */ new Set(["td", "th", "tr", "tbody", "thead", "tfoot", "caption", "col", "colgroup"]);
|
|
461
461
|
var DOCUMENT_STRUCTURE_NAMES = /* @__PURE__ */ new Set(["html", "head", "body", "frameset"]);
|
|
462
|
+
var NO_ELEMENT_NAMES = /* @__PURE__ */ new Set([...DOCUMENT_STRUCTURE_NAMES, "frame", "image"]);
|
|
462
463
|
var RETROACTIVE_OPENERS = [
|
|
463
464
|
"<!doctype",
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
"</body",
|
|
471
|
-
"</frameset"
|
|
465
|
+
// DERIVED, so the trailing-partial guard cannot drift from the poison the
|
|
466
|
+
// confirmed lines get. It was transcribed until F28, and the transcription
|
|
467
|
+
// was already two names behind by then. `<frame` subsumes `<frameset`,
|
|
468
|
+
// which is why the derived list is SHORTER than the one it replaces and
|
|
469
|
+
// still covers strictly more.
|
|
470
|
+
...[...NO_ELEMENT_NAMES].flatMap((name) => [`<${name}`, `</${name}`])
|
|
472
471
|
];
|
|
473
472
|
function tailCarriesRetroactive(text) {
|
|
474
473
|
const lower = text.toLowerCase();
|
|
@@ -721,6 +720,7 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
|
|
|
721
720
|
tagBalance: /* @__PURE__ */ new Map(),
|
|
722
721
|
openTotal: 0,
|
|
723
722
|
p5Tok: { kind: "data" },
|
|
723
|
+
formPointerMaybeSet: false,
|
|
724
724
|
openStack: [],
|
|
725
725
|
mdBlock: { kind: "none" },
|
|
726
726
|
blankRun: 0,
|
|
@@ -871,6 +871,7 @@ function sealReleaseDerived(cp, ln, isBlockStart) {
|
|
|
871
871
|
if (DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text)) return false;
|
|
872
872
|
return true;
|
|
873
873
|
}
|
|
874
|
+
var sealReleaseEvaluations = 0;
|
|
874
875
|
function sealReleaseEnumerated(cp, ln, isBlockStart) {
|
|
875
876
|
const defShapedLine = DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text) || cp.defBlockMaybeOpen || cp.fnDefResumable && !(isBlockStart && ln.indent <= 3);
|
|
876
877
|
const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").replace(/[ \t\r]/g, "") === "";
|
|
@@ -885,10 +886,13 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
885
886
|
if (cp.p5SealPending && !ln.blank && cp.mdBlock.kind !== "html" && !(cp.p5Tok.kind === "comment" || cp.p5Tok.kind === "bogus")) {
|
|
886
887
|
if (sealReleaseDerived(cp, ln, isBlockStart)) {
|
|
887
888
|
cp.p5SealPending = false;
|
|
888
|
-
if (
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
889
|
+
if (true) {
|
|
890
|
+
sealReleaseEvaluations += 1;
|
|
891
|
+
if (!sealReleaseEnumerated(cp, ln, isBlockStart)) {
|
|
892
|
+
console.error(
|
|
893
|
+
`[ai-react-markdown] seal-release containment broken at offset ${ln.start}: the derived predicate released a line the retired enumeration withheld (${JSON.stringify(ln.text.slice(0, 80))}).`
|
|
894
|
+
);
|
|
895
|
+
}
|
|
892
896
|
}
|
|
893
897
|
}
|
|
894
898
|
}
|
|
@@ -917,7 +921,7 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
917
921
|
if (tag === "plaintext") cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
|
|
918
922
|
}
|
|
919
923
|
}
|
|
920
|
-
if (
|
|
924
|
+
if (NO_ELEMENT_NAMES.has(tag)) cp.phasePoisonedAt = 0;
|
|
921
925
|
if (tag === "template" && !closing) cp.phasePoisonedAt = 0;
|
|
922
926
|
if (closing) {
|
|
923
927
|
let idx = -1;
|
|
@@ -933,12 +937,14 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
933
937
|
return;
|
|
934
938
|
}
|
|
935
939
|
cp.openStack.splice(idx, 1);
|
|
940
|
+
if (tag === "form") cp.formPointerMaybeSet = false;
|
|
936
941
|
const count = cp.tagBalance.get(tag) ?? 0;
|
|
937
942
|
if (count > 0) {
|
|
938
943
|
cp.tagBalance.set(tag, count - 1);
|
|
939
944
|
cp.openTotal -= 1;
|
|
940
945
|
}
|
|
941
946
|
} else {
|
|
947
|
+
if (tag === "form") cp.formPointerMaybeSet = true;
|
|
942
948
|
cp.openStack.push(tag);
|
|
943
949
|
cp.tagBalance.set(tag, (cp.tagBalance.get(tag) ?? 0) + 1);
|
|
944
950
|
cp.openTotal += 1;
|
|
@@ -1065,7 +1071,11 @@ function processConfirmedLine(cp, ln, text) {
|
|
|
1065
1071
|
// mask suppresses them — which is exactly why `openTotal` reads 0
|
|
1066
1072
|
// and the candidate looked safe), and the 2-5 interiors are the
|
|
1067
1073
|
// same construct to both grammars.
|
|
1068
|
-
htmlBalanced: cp.openTotal === 0 && cp.mdBlock.kind !== "html" && cp.p5Tok.kind !== "bogus"
|
|
1074
|
+
htmlBalanced: cp.openTotal === 0 && cp.mdBlock.kind !== "html" && cp.p5Tok.kind !== "bogus" && // A form pointer parse5 may still be holding makes a LATER `<form>`
|
|
1075
|
+
// in the tail vanish from the full parse while a split parse opens
|
|
1076
|
+
// it — forward independence fails with every other condition clean.
|
|
1077
|
+
// See the field doc.
|
|
1078
|
+
!cp.formPointerMaybeSet,
|
|
1069
1079
|
hazard: cp.hazardVerdict,
|
|
1070
1080
|
seamRisk: cp.p5SealPending,
|
|
1071
1081
|
defListSettled: null
|
|
@@ -1461,6 +1471,11 @@ var SCANNER_NAME_LISTS = [
|
|
|
1461
1471
|
["type6", TYPE6_NAMES],
|
|
1462
1472
|
["void", VOID_TAGS],
|
|
1463
1473
|
["documentStructure", DOCUMENT_STRUCTURE_NAMES],
|
|
1474
|
+
// Added with F28, and it is the list that would have made F28 visible: the
|
|
1475
|
+
// derived census alphabet partitions names by their membership across THIS
|
|
1476
|
+
// table, so before it existed `frame` shared one 39-name class with `div`
|
|
1477
|
+
// and could never be sampled apart from it.
|
|
1478
|
+
["noElement", NO_ELEMENT_NAMES],
|
|
1464
1479
|
["tablePart", TABLE_PART_NAMES],
|
|
1465
1480
|
["scopeBarrier", SCOPE_BARRIER_NAMES],
|
|
1466
1481
|
["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
|
|
@@ -4428,24 +4443,32 @@ var SMOOTH_STREAM_PACING_PRESETS = Object.freeze({
|
|
|
4428
4443
|
correctionTauMs: 280,
|
|
4429
4444
|
emaTauMs: 2600,
|
|
4430
4445
|
minCharsPerSecond: 4,
|
|
4431
|
-
drainMs: 320
|
|
4446
|
+
drainMs: 320,
|
|
4447
|
+
maxLagMs: 3500
|
|
4432
4448
|
}),
|
|
4433
4449
|
balanced: Object.freeze({
|
|
4434
4450
|
bufferFactor: 1,
|
|
4435
4451
|
correctionTauMs: 180,
|
|
4436
4452
|
emaTauMs: 1800,
|
|
4437
4453
|
minCharsPerSecond: 6,
|
|
4438
|
-
drainMs: 240
|
|
4454
|
+
drainMs: 240,
|
|
4455
|
+
maxLagMs: 2500
|
|
4439
4456
|
}),
|
|
4440
4457
|
responsive: Object.freeze({
|
|
4441
4458
|
bufferFactor: 0.45,
|
|
4442
4459
|
correctionTauMs: 110,
|
|
4443
4460
|
emaTauMs: 1100,
|
|
4444
4461
|
minCharsPerSecond: 10,
|
|
4445
|
-
drainMs: 150
|
|
4462
|
+
drainMs: 150,
|
|
4463
|
+
maxLagMs: 800
|
|
4446
4464
|
})
|
|
4447
4465
|
});
|
|
4448
|
-
var
|
|
4466
|
+
var GAP_WINDOW = 16;
|
|
4467
|
+
var INTERVAL_QUANTILE = 0.9;
|
|
4468
|
+
var HORIZON_PAD_MS = 50;
|
|
4469
|
+
var DEADLINE_FLOOR_MS = 33;
|
|
4470
|
+
var DRAIN_CATCHUP_FACTOR = 2;
|
|
4471
|
+
var DRAIN_MAX_FACTOR = 3;
|
|
4449
4472
|
var defaultNow = typeof performance !== "undefined" && typeof performance.now === "function" ? () => performance.now() : () => Date.now();
|
|
4450
4473
|
var defaultSchedule = (cb) => {
|
|
4451
4474
|
if (typeof requestAnimationFrame === "function") {
|
|
@@ -4496,18 +4519,18 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4496
4519
|
let lastTickAt = 0;
|
|
4497
4520
|
let cancelFrame;
|
|
4498
4521
|
let disposed = false;
|
|
4499
|
-
let
|
|
4500
|
-
let intervalEma;
|
|
4522
|
+
let gapWindow = [];
|
|
4501
4523
|
let lastArrivalAt;
|
|
4502
4524
|
const listeners = /* @__PURE__ */ new Set();
|
|
4503
4525
|
const resolveParams = () => {
|
|
4504
|
-
const preset = SMOOTH_STREAM_PACING_PRESETS[options.pacing]
|
|
4526
|
+
const preset = Object.hasOwn(SMOOTH_STREAM_PACING_PRESETS, options.pacing) ? SMOOTH_STREAM_PACING_PRESETS[options.pacing] : SMOOTH_STREAM_PACING_PRESETS.balanced;
|
|
4505
4527
|
return {
|
|
4506
4528
|
bufferFactor: finiteOr(options.bufferFactor, preset.bufferFactor),
|
|
4507
4529
|
correctionTauMs: finiteOr(options.correctionTauMs, preset.correctionTauMs),
|
|
4508
4530
|
emaTauMs: finiteOr(options.emaTauMs, preset.emaTauMs),
|
|
4509
4531
|
minCharsPerSecond: finiteOr(options.minCharsPerSecond, preset.minCharsPerSecond),
|
|
4510
|
-
drainMs: finiteOr(options.drainMs, preset.drainMs)
|
|
4532
|
+
drainMs: finiteOr(options.drainMs, preset.drainMs),
|
|
4533
|
+
maxLagMs: finiteOr(options.maxLagMs, preset.maxLagMs ?? 2500)
|
|
4511
4534
|
};
|
|
4512
4535
|
};
|
|
4513
4536
|
const recordArrival = (t, added) => {
|
|
@@ -4518,12 +4541,8 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4518
4541
|
}
|
|
4519
4542
|
const gap = Math.max(1, t - lastArrivalAt);
|
|
4520
4543
|
lastArrivalAt = t;
|
|
4521
|
-
|
|
4522
|
-
if (
|
|
4523
|
-
const alpha = 1 - Math.exp(-gap / tau);
|
|
4524
|
-
const instantRate = added * 1e3 / gap;
|
|
4525
|
-
rateEma = (rateEma ?? 0) + alpha * (instantRate - (rateEma ?? 0));
|
|
4526
|
-
intervalEma = (intervalEma ?? 0) + alpha * (gap - (intervalEma ?? 0));
|
|
4544
|
+
gapWindow.push({ gap, added });
|
|
4545
|
+
if (gapWindow.length > GAP_WINDOW) gapWindow.shift();
|
|
4527
4546
|
};
|
|
4528
4547
|
const notify = () => {
|
|
4529
4548
|
visibleCache = source.slice(0, visibleEnd);
|
|
@@ -4549,15 +4568,12 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4549
4568
|
let rate;
|
|
4550
4569
|
if (finished && drainDeadlineAt !== void 0) {
|
|
4551
4570
|
rate = Math.max(params.minCharsPerSecond, pending.length * 1e3 / Math.max(1, drainDeadlineAt - t));
|
|
4552
|
-
} else if (
|
|
4553
|
-
const
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
);
|
|
4557
|
-
rate = Math.max(
|
|
4558
|
-
params.minCharsPerSecond,
|
|
4559
|
-
rateEma + (pending.length - targetBuffer) * 1e3 / Math.max(1, params.correctionTauMs)
|
|
4560
|
-
);
|
|
4571
|
+
} else if (gapWindow.length > 0 && lastArrivalAt !== void 0) {
|
|
4572
|
+
const gaps = gapWindow.map((s) => s.gap).sort((a, b) => a - b);
|
|
4573
|
+
const intervalQ = gaps[Math.min(gaps.length - 1, Math.floor(gaps.length * INTERVAL_QUANTILE))];
|
|
4574
|
+
const horizon = Math.max(16, Math.min(params.bufferFactor * intervalQ + HORIZON_PAD_MS, params.maxLagMs));
|
|
4575
|
+
const deadline = Math.max(lastArrivalAt + horizon, t + DEADLINE_FLOOR_MS);
|
|
4576
|
+
rate = Math.max(params.minCharsPerSecond, pending.length * 1e3 / Math.max(1, deadline - t));
|
|
4561
4577
|
} else {
|
|
4562
4578
|
rate = Math.max(params.minCharsPerSecond, pending.length * 1e3 / Math.max(1, params.correctionTauMs));
|
|
4563
4579
|
}
|
|
@@ -4603,8 +4619,7 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4603
4619
|
initialized = true;
|
|
4604
4620
|
finished = false;
|
|
4605
4621
|
drainDeadlineAt = void 0;
|
|
4606
|
-
|
|
4607
|
-
intervalEma = void 0;
|
|
4622
|
+
gapWindow = [];
|
|
4608
4623
|
lastArrivalAt = void 0;
|
|
4609
4624
|
source = next;
|
|
4610
4625
|
visibleEnd = next.length;
|
|
@@ -4641,10 +4656,26 @@ var createSmoothStreamController = (options = {}) => {
|
|
|
4641
4656
|
if (finished) return;
|
|
4642
4657
|
finished = true;
|
|
4643
4658
|
lastArrivalAt = void 0;
|
|
4644
|
-
drainDeadlineAt = now() + resolveParams().drainMs;
|
|
4645
4659
|
if (tentativeEnd > (pending.length > 0 ? pending[pending.length - 1] : visibleEnd)) {
|
|
4646
4660
|
pending.push(tentativeEnd);
|
|
4647
4661
|
}
|
|
4662
|
+
const params = resolveParams();
|
|
4663
|
+
let drainWin = params.drainMs;
|
|
4664
|
+
let chars = 0;
|
|
4665
|
+
let ms = 0;
|
|
4666
|
+
for (let i = 0; i < gapWindow.length - 1; i += 1) {
|
|
4667
|
+
chars += gapWindow[i].added;
|
|
4668
|
+
ms += gapWindow[i].gap;
|
|
4669
|
+
}
|
|
4670
|
+
const backlog = source.length - visibleEnd;
|
|
4671
|
+
if (chars > 0 && ms > 0 && backlog > 0) {
|
|
4672
|
+
const throughput = chars * 1e3 / ms;
|
|
4673
|
+
drainWin = Math.min(
|
|
4674
|
+
Math.max(backlog * 1e3 / (DRAIN_CATCHUP_FACTOR * throughput), params.drainMs),
|
|
4675
|
+
DRAIN_MAX_FACTOR * params.drainMs
|
|
4676
|
+
);
|
|
4677
|
+
}
|
|
4678
|
+
drainDeadlineAt = now() + drainWin;
|
|
4648
4679
|
seam = source.length;
|
|
4649
4680
|
ensureScheduled();
|
|
4650
4681
|
},
|