@ai-react-markdown/engine 2.8.2 → 2.9.1

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 CHANGED
@@ -378,9 +378,9 @@ function inlineResourceEnd(text, openIdx) {
378
378
  }
379
379
  return -1;
380
380
  }
381
- function collectRefLine(cp, lnStart, lnEnd, scanText, inRawText, isBlockStart) {
382
- const defShaped = inRawText ? null : DEF_RE.exec(scanText);
383
- const def = defShaped !== null && (defShaped[1].startsWith("^") || isPlausibleLinkDefRest(scanText.slice(defShaped.index + defShaped[0].length))) ? defShaped : null;
381
+ function collectRefLine(cp, lnStart, lnEnd, scanText, rawText, inRawText, isBlockStart) {
382
+ const defShaped = inRawText ? null : DEF_RE.exec(rawText);
383
+ const def = defShaped !== null && (defShaped[1].startsWith("^") || isPlausibleLinkDefRest(rawText.slice(defShaped.index + defShaped[0].length))) ? defShaped : null;
384
384
  const defLineStart = isBlockStart || !cp.prevLineWasText || cp.prevLineWasValidDef;
385
385
  const validDef = def !== null && defLineStart;
386
386
  if (validDef) {
@@ -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
- "<html",
465
- "<head",
466
- "<body",
467
- "<frameset",
468
- "</html",
469
- "</head",
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();
@@ -598,12 +597,15 @@ var rawTextElement = (t) => t.kind === "rawText" ? t.element : t.kind === "scrip
598
597
  var VOID_TAGS = /* @__PURE__ */ new Set([
599
598
  "area",
600
599
  "base",
600
+ "basefont",
601
+ "bgsound",
601
602
  "br",
602
603
  "col",
603
604
  "embed",
604
605
  "hr",
605
606
  "img",
606
607
  "input",
608
+ "keygen",
607
609
  "link",
608
610
  "meta",
609
611
  "param",
@@ -618,7 +620,6 @@ var THEMATIC_BREAK_RE = /^(?:(?:-[ \t]*){3,}|(?:\*[ \t]*){3,}|(?:_[ \t]*){3,})$/
618
620
  var BARE_MARKER_RE = /^(?:[-*+]|\d{1,9}[.)])[ \t]*$/;
619
621
  var SETEXT_LEFTOVER_RE = /^(?:=+|--)[ \t]*$/;
620
622
  var DEF_LIST_DD_RE = /^ {0,3}:[ \t]/;
621
- var CLOSE_TAG_ONLY_RE = /^[ \t]*<\/[A-Za-z][A-Za-z0-9-]*[ \t]*>[ \t\r]*$/;
622
623
  var FENCE_RE = /^ {0,3}(`{3,}|~{3,})/;
623
624
  var MATH_RUN_RE = /^ {0,3}(\$\$+)/;
624
625
  var TAG_OR_COMMENT_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)(?=[\s/>])([^>]*)>|<!--|-->|--!>/g;
@@ -718,6 +719,7 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
718
719
  tagBalance: /* @__PURE__ */ new Map(),
719
720
  openTotal: 0,
720
721
  p5Tok: { kind: "data" },
722
+ formPointerMaybeSet: false,
721
723
  openStack: [],
722
724
  mdBlock: { kind: "none" },
723
725
  blankRun: 0,
@@ -855,6 +857,19 @@ function floatingResidue(text, commentOpenAtStart) {
855
857
  if (!open) out += text.slice(last);
856
858
  return out;
857
859
  }
860
+ var RAW_CONSTRUCT_START_RE = /^<(?:!--|\?|![A-Za-z]|!\[CDATA\[)/;
861
+ var sealResumableAbove = (cp) => cp.defBlockMaybeOpen || cp.fnDefResumable || cp.containerMaybeOpen;
862
+ function sealReleaseDerived(cp, ln, isBlockStart) {
863
+ if (sealResumableAbove(cp) && !(isBlockStart && ln.indent <= 3)) return false;
864
+ if (cp.prevLineOpenContent) return false;
865
+ if (cp.tableMaybeOpen) return false;
866
+ const head = mdTrimStart(ln.text);
867
+ if (RAW_CONSTRUCT_START_RE.test(head) || TYPE1_START_RE.test(head) || isType7Line(head)) return false;
868
+ const t6 = TYPE6_START_RE.exec(head);
869
+ if (t6 !== null && TYPE6_NAMES.has(t6[1].toLowerCase())) return false;
870
+ if (DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text)) return false;
871
+ return true;
872
+ }
858
873
  function processConfirmedLine(cp, ln, text) {
859
874
  const newest = cp.candidates[cp.candidates.length - 1];
860
875
  if (newest && newest.defListSettled === null) {
@@ -862,16 +877,22 @@ function processConfirmedLine(cp, ln, text) {
862
877
  }
863
878
  const isBlockStart = cp.prevLineBlank;
864
879
  if (cp.p5SealPending && !ln.blank && cp.mdBlock.kind !== "html" && !(cp.p5Tok.kind === "comment" || cp.p5Tok.kind === "bogus")) {
865
- const defShapedLine = DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text) || cp.defBlockMaybeOpen || cp.fnDefResumable && !(isBlockStart && ln.indent <= 3);
866
- const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").replace(/[ \t\r]/g, "") === "";
867
- const closeTagOnly = CLOSE_TAG_ONLY_RE.test(ln.text);
868
- if (!defShapedLine && !commentOnly && !closeTagOnly) {
880
+ if (sealReleaseDerived(cp, ln, isBlockStart)) {
869
881
  cp.p5SealPending = false;
882
+ if (false) {
883
+ sealReleaseEvaluations += 1;
884
+ if (!sealReleaseEnumerated(cp, ln, isBlockStart)) {
885
+ console.error(
886
+ `[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))}).`
887
+ );
888
+ }
889
+ }
870
890
  }
871
891
  }
872
892
  const possiblyInsideForeign = () => FOREIGN_ROOT_NAMES.some((name) => (cp.tagBalance.get(name) ?? 0) > 0);
873
893
  const honoursSelfClosing = (tag) => tag === "svg" || tag === "math";
874
894
  const foreignRawTextSwitchUnknowable = () => possiblyInsideForeign();
895
+ let discardedEndTag = false;
875
896
  const applyTag = (tag, closing) => {
876
897
  if (inRawTextTok(cp.p5Tok)) {
877
898
  if (cp.p5Tok.kind === "script" && cp.p5Tok.escaped && !closing && tag === "script") {
@@ -893,7 +914,7 @@ function processConfirmedLine(cp, ln, text) {
893
914
  if (tag === "plaintext") cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
894
915
  }
895
916
  }
896
- if (DOCUMENT_STRUCTURE_NAMES.has(tag)) cp.phasePoisonedAt = 0;
917
+ if (NO_ELEMENT_NAMES.has(tag)) cp.phasePoisonedAt = 0;
897
918
  if (tag === "template" && !closing) cp.phasePoisonedAt = 0;
898
919
  if (closing) {
899
920
  let idx = -1;
@@ -904,14 +925,19 @@ function processConfirmedLine(cp, ln, text) {
904
925
  }
905
926
  if (SCOPE_BARRIER_NAMES.has(cp.openStack[i])) break;
906
927
  }
907
- if (idx === -1) return;
928
+ if (idx === -1) {
929
+ discardedEndTag = true;
930
+ return;
931
+ }
908
932
  cp.openStack.splice(idx, 1);
933
+ if (tag === "form") cp.formPointerMaybeSet = false;
909
934
  const count = cp.tagBalance.get(tag) ?? 0;
910
935
  if (count > 0) {
911
936
  cp.tagBalance.set(tag, count - 1);
912
937
  cp.openTotal -= 1;
913
938
  }
914
939
  } else {
940
+ if (tag === "form") cp.formPointerMaybeSet = true;
915
941
  cp.openStack.push(tag);
916
942
  cp.tagBalance.set(tag, (cp.tagBalance.get(tag) ?? 0) + 1);
917
943
  cp.openTotal += 1;
@@ -1023,6 +1049,9 @@ function processConfirmedLine(cp, ln, text) {
1023
1049
  cp.p5Tok = { kind: "data" };
1024
1050
  }
1025
1051
  }
1052
+ if (cp.p5Tok.kind === "comment" && !mdHtml(cp.mdBlock, 2)) {
1053
+ cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
1054
+ }
1026
1055
  if (cp.mdBlock.kind === "html" && cp.mdBlock.type >= 6) cp.mdBlock = { kind: "none" };
1027
1056
  cp.blankRun += 1;
1028
1057
  cp.lastBlankStart = ln.start;
@@ -1035,7 +1064,11 @@ function processConfirmedLine(cp, ln, text) {
1035
1064
  // mask suppresses them — which is exactly why `openTotal` reads 0
1036
1065
  // and the candidate looked safe), and the 2-5 interiors are the
1037
1066
  // same construct to both grammars.
1038
- htmlBalanced: cp.openTotal === 0 && cp.mdBlock.kind !== "html" && cp.p5Tok.kind !== "bogus",
1067
+ htmlBalanced: cp.openTotal === 0 && cp.mdBlock.kind !== "html" && cp.p5Tok.kind !== "bogus" && // A form pointer parse5 may still be holding makes a LATER `<form>`
1068
+ // in the tail vanish from the full parse while a split parse opens
1069
+ // it — forward independence fails with every other condition clean.
1070
+ // See the field doc.
1071
+ !cp.formPointerMaybeSet,
1039
1072
  hazard: cp.hazardVerdict,
1040
1073
  seamRisk: cp.p5SealPending,
1041
1074
  defListSettled: null
@@ -1090,14 +1123,14 @@ function processConfirmedLine(cp, ln, text) {
1090
1123
  }
1091
1124
  }
1092
1125
  }
1093
- const rawFlowStart = ln.indent <= 3 && /^<(?:!--|\?|![A-Za-z]|!\[CDATA\[)/.test(mdTrimStart(ln.text));
1126
+ const rawFlowStart = ln.indent <= 3 && RAW_CONSTRUCT_START_RE.test(mdTrimStart(ln.text));
1094
1127
  const htmlOwnedLine = cp.mdBlock.kind === "html" || rawOpenAtLineStart || rawFlowStart;
1095
1128
  const maskingSuppressed = htmlOwnedLine || inRawTextTok(cp.p5Tok);
1096
1129
  const { masked, unpaired } = maskingSuppressed ? { masked: null, unpaired: false } : maskIntraLineCodeSpans(ln.text, cp.paragraphHasUnpairedRun);
1097
1130
  if (unpaired) cp.paragraphHasUnpairedRun = true;
1098
1131
  const scanText = masked ?? ln.text;
1099
1132
  const defRawToMicromark = cp.mdBlock.kind === "html" || rawOpenAtLineStart || inRawTextTok(cp.p5Tok);
1100
- const { validLinkDef } = collectRefLine(cp, ln.start, ln.end, scanText, defRawToMicromark, isBlockStart);
1133
+ const { validLinkDef } = collectRefLine(cp, ln.start, ln.end, scanText, ln.text, defRawToMicromark, isBlockStart);
1101
1134
  const rawSpans = [];
1102
1135
  let pos = 0;
1103
1136
  const poisonRawDivergence = () => {
@@ -1372,7 +1405,7 @@ function processConfirmedLine(cp, ln, text) {
1372
1405
  cursor = to;
1373
1406
  }
1374
1407
  masked2 += scanText.slice(cursor);
1375
- if (floatingResidue(masked2, bothCommentsOpenAtLineStart).length > 0) {
1408
+ if (floatingResidue(masked2, bothCommentsOpenAtLineStart).length > 0 || discardedEndTag) {
1376
1409
  cp.p5SealPending = true;
1377
1410
  }
1378
1411
  }
@@ -1425,6 +1458,21 @@ function processConfirmedLine(cp, ln, text) {
1425
1458
  }
1426
1459
  }
1427
1460
  }
1461
+ var SCANNER_NAME_LISTS = [
1462
+ ["type1", TYPE1_NAMES],
1463
+ ["rawText", RAW_TEXT_ELEMENTS],
1464
+ ["type6", TYPE6_NAMES],
1465
+ ["void", VOID_TAGS],
1466
+ ["documentStructure", DOCUMENT_STRUCTURE_NAMES],
1467
+ // Added with F28, and it is the list that would have made F28 visible: the
1468
+ // derived census alphabet partitions names by their membership across THIS
1469
+ // table, so before it existed `frame` shared one 39-name class with `div`
1470
+ // and could never be sampled apart from it.
1471
+ ["noElement", NO_ELEMENT_NAMES],
1472
+ ["tablePart", TABLE_PART_NAMES],
1473
+ ["scopeBarrier", SCOPE_BARRIER_NAMES],
1474
+ ["foreignRoot", new Set(FOREIGN_ROOT_NAMES)]
1475
+ ];
1428
1476
 
1429
1477
  // src/components/incrementalParse/spliceParse.ts
1430
1478
  var import_micromark_util_normalize_identifier2 = require("micromark-util-normalize-identifier");