@ai-react-markdown/engine 2.8.0 → 2.8.2

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/README.md CHANGED
@@ -90,7 +90,7 @@ for (const frame of ['# Hello', '# Hello\n\nworld', '# Hello\n\nworld and more']
90
90
 
91
91
  ## Verification
92
92
 
93
- The incremental engine ships with a five-layer equivalence stack (fixture pins, fuzz arbiter, direction battery, exhaustive census, arbiter-sensitivity meta-suite) plus a release-gate soak (`scripts/run-soak.sh`); the full record lives in `src/experiments/prefixFreeze/README.md`. Every reachable divergence found so far is pinned as a deterministic test.
93
+ The incremental engine ships with a five-layer equivalence stack (fixture pins, fuzz arbiter, direction battery, exhaustive census, arbiter-sensitivity meta-suite) plus a five-leg release-gate soak (`scripts/soak/fiveleg.sh`, from the repo root, with a fresh seed base); the full record lives in `src/experiments/prefixFreeze/README.md`. Every reachable divergence found so far is pinned as a deterministic test.
94
94
 
95
95
  ## Runtime support
96
96
 
package/dist/index.cjs CHANGED
@@ -48,7 +48,6 @@ __export(src_exports, {
48
48
  collectDefLabels: () => collectDefLabels,
49
49
  computeFreezeBoundary: () => computeFreezeBoundary,
50
50
  createDefLabelScanner: () => createDefLabelScanner,
51
- createFile: () => createFile,
52
51
  createIncrementalLatexPreprocessor: () => createIncrementalLatexPreprocessor,
53
52
  createProcessor: () => createProcessor,
54
53
  createRegistry: () => createRegistry,
@@ -65,10 +64,8 @@ __export(src_exports, {
65
64
  hasLoneSurrogate: () => hasLoneSurrogate,
66
65
  highlight: () => highlight,
67
66
  isFootnoteSection: () => isFootnoteSection,
68
- isWhitespaceText: () => isWhitespaceText,
69
67
  lastMeaningfulIdx: () => lastMeaningfulIdx,
70
68
  measureStage: () => measureStage,
71
- mergeClassNameAllowlist: () => mergeClassNameAllowlist,
72
69
  normalizeForMatch: () => normalizeForMatch,
73
70
  normalizeId: () => normalizeId,
74
71
  pangu: () => pangu,
@@ -84,7 +81,6 @@ __export(src_exports, {
84
81
  shortenDocumentId: () => shortenDocumentId,
85
82
  smartypants: () => smartypants,
86
83
  sourceIdFromFootnoteLiId: () => sourceIdFromFootnoteLiId,
87
- splitByProtectedRegions: () => splitByProtectedRegions,
88
84
  subscribeStageTimings: () => subscribeStageTimings,
89
85
  transformStage: () => transformStage,
90
86
  withDefs: () => withDefs
@@ -594,6 +590,7 @@ var isType7Line = (line) => {
594
590
  return i >= t.length;
595
591
  };
596
592
  var mdHtml = (b, type) => b.kind === "html" && b.type === type;
593
+ var mdType1RawText = (b) => b.kind === "html" && b.type === 1 && b.raw;
597
594
  var mdHtml25 = (b) => b.kind === "html" && b.type >= 2 && b.type <= 5;
598
595
  var commentEitherOpen = (md, p5) => mdHtml(md, 2) || p5.kind === "comment";
599
596
  var inRawTextTok = (t) => t.kind === "rawText" || t.kind === "script";
@@ -615,11 +612,13 @@ var VOID_TAGS = /* @__PURE__ */ new Set([
615
612
  "wbr"
616
613
  ]);
617
614
  var LIST_MARKER_RE = /^ {0,3}(?:[-*+]|\d{1,9}[.)])(?:[ \t]|$)/;
615
+ var CONTAINER_MARKER_RE = /^ {0,3}(?:>|(?:[-*+]|\d{1,9}[.)])[ \t]+\S)/;
618
616
  var ATX_HEADING_RE = /^#{1,6}(?:[ \t]|$)/;
619
617
  var THEMATIC_BREAK_RE = /^(?:(?:-[ \t]*){3,}|(?:\*[ \t]*){3,}|(?:_[ \t]*){3,})$/;
620
618
  var BARE_MARKER_RE = /^(?:[-*+]|\d{1,9}[.)])[ \t]*$/;
621
619
  var SETEXT_LEFTOVER_RE = /^(?:=+|--)[ \t]*$/;
622
620
  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]*$/;
623
622
  var FENCE_RE = /^ {0,3}(`{3,}|~{3,})/;
624
623
  var MATH_RUN_RE = /^ {0,3}(\$\$+)/;
625
624
  var TAG_OR_COMMENT_RE = /<(\/?)([A-Za-z][A-Za-z0-9-]*)(?=[\s/>])([^>]*)>|<!--|-->|--!>/g;
@@ -730,9 +729,12 @@ function freshCheckpoint(defListEnabled, mathFlow, referenceTaint) {
730
729
  prevLineWasValidDef: false,
731
730
  prevLineOpenContent: false,
732
731
  tableMaybeOpen: false,
732
+ containerMaybeOpen: false,
733
733
  paragraphHasUnpairedRun: false,
734
734
  openBracket: null,
735
735
  p5SealPending: false,
736
+ defBlockMaybeOpen: false,
737
+ fnDefResumable: false,
736
738
  phasePoisonedAt: Infinity,
737
739
  pendingTruncatedTags: [],
738
740
  pendingTruncatedCloses: [],
@@ -860,9 +862,10 @@ function processConfirmedLine(cp, ln, text) {
860
862
  }
861
863
  const isBlockStart = cp.prevLineBlank;
862
864
  if (cp.p5SealPending && !ln.blank && cp.mdBlock.kind !== "html" && !(cp.p5Tok.kind === "comment" || cp.p5Tok.kind === "bogus")) {
863
- const defShapedLine = DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text);
865
+ const defShapedLine = DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text) || cp.defBlockMaybeOpen || cp.fnDefResumable && !(isBlockStart && ln.indent <= 3);
864
866
  const commentOnly = ln.text.replace(/<!--[\s\S]*?-->/g, " ").replace(/<!--[\s\S]*$/, " ").replace(/[ \t\r]/g, "") === "";
865
- if (!defShapedLine && !commentOnly) {
867
+ const closeTagOnly = CLOSE_TAG_ONLY_RE.test(ln.text);
868
+ if (!defShapedLine && !commentOnly && !closeTagOnly) {
866
869
  cp.p5SealPending = false;
867
870
  }
868
871
  }
@@ -914,7 +917,7 @@ function processConfirmedLine(cp, ln, text) {
914
917
  cp.openTotal += 1;
915
918
  }
916
919
  };
917
- const definitelyInsideTable = () => (cp.tagBalance.get("table") ?? 0) > 0;
920
+ const definitelyInsideTable = () => (cp.tagBalance.get("table") ?? 0) > cp.pendingTruncatedTags.filter((t) => t === "table").length;
918
921
  const strayTablePart = (tag) => TABLE_PART_NAMES.has(tag) && !definitelyInsideTable();
919
922
  const commentOpenAtLineStart = commentEitherOpen(cp.mdBlock, cp.p5Tok);
920
923
  const bothCommentsOpenAtLineStart = mdHtml(cp.mdBlock, 2) && cp.p5Tok.kind === "comment";
@@ -936,6 +939,7 @@ function processConfirmedLine(cp, ln, text) {
936
939
  cp.prevLineWasValidDef = false;
937
940
  cp.prevLineOpenContent = false;
938
941
  cp.tableMaybeOpen = false;
942
+ cp.containerMaybeOpen = false;
939
943
  return;
940
944
  }
941
945
  if (cp.mdBlock.kind !== "math" && !rawOpenAtLineStart) {
@@ -957,6 +961,7 @@ function processConfirmedLine(cp, ln, text) {
957
961
  cp.prevLineWasValidDef = false;
958
962
  cp.prevLineOpenContent = false;
959
963
  cp.tableMaybeOpen = false;
964
+ cp.containerMaybeOpen = false;
960
965
  return;
961
966
  }
962
967
  }
@@ -973,6 +978,7 @@ function processConfirmedLine(cp, ln, text) {
973
978
  cp.prevLineWasValidDef = false;
974
979
  cp.prevLineOpenContent = false;
975
980
  cp.tableMaybeOpen = false;
981
+ cp.containerMaybeOpen = false;
976
982
  return;
977
983
  }
978
984
  const mathRun = cp.mathFlow && !rawOpenAtLineStart ? MATH_RUN_RE.exec(ln.text) : null;
@@ -995,6 +1001,7 @@ function processConfirmedLine(cp, ln, text) {
995
1001
  cp.prevLineWasValidDef = false;
996
1002
  cp.prevLineOpenContent = false;
997
1003
  cp.tableMaybeOpen = false;
1004
+ cp.containerMaybeOpen = false;
998
1005
  return;
999
1006
  }
1000
1007
  }
@@ -1043,8 +1050,10 @@ function processConfirmedLine(cp, ln, text) {
1043
1050
  cp.prevLineBlank = true;
1044
1051
  cp.prevLineWasText = false;
1045
1052
  cp.prevLineWasValidDef = false;
1053
+ cp.defBlockMaybeOpen = false;
1046
1054
  cp.prevLineOpenContent = false;
1047
1055
  cp.tableMaybeOpen = false;
1056
+ cp.containerMaybeOpen = false;
1048
1057
  return;
1049
1058
  }
1050
1059
  if (isBlockStart) {
@@ -1056,21 +1065,27 @@ function processConfirmedLine(cp, ln, text) {
1056
1065
  const tagStart = ln.indent <= 3 ? /^<\/?([A-Za-z][A-Za-z0-9-]*)/.exec(mdTrimStart(ln.text)) : null;
1057
1066
  if (tagStart) {
1058
1067
  const noRealBlockOpen = cp.mdBlock.kind !== "html";
1059
- if (noRealBlockOpen && TYPE1_START_RE.test(mdTrimStart(ln.text))) cp.mdBlock = { kind: "html", type: 1 };
1068
+ const t1 = noRealBlockOpen ? TYPE1_START_RE.exec(mdTrimStart(ln.text)) : null;
1069
+ if (t1) cp.mdBlock = { kind: "html", type: 1, raw: RAW_TEXT_ELEMENTS.has(t1[1].toLowerCase()), indent: ln.indent };
1060
1070
  if (cp.mdBlock.kind !== "html") {
1061
1071
  const t = mdTrimStart(ln.text);
1062
1072
  const t6 = TYPE6_START_RE.exec(t);
1063
1073
  const realT6 = t6 !== null && TYPE6_NAMES.has(t6[1].toLowerCase());
1064
- if (realT6 || TYPE1_START_RE.test(t) || // Type 7 cannot interrupt CONTENT (micromark's paragraph/definition
1074
+ const t1Line = TYPE1_START_RE.test(t);
1075
+ const type7Shaped = !realT6 && !t1Line && isType7Line(t);
1076
+ if (realT6 || t1Line || // Type 7 cannot interrupt CONTENT (micromark's paragraph/definition
1065
1077
  // construct — `prevLineOpenContent`, the exact interrupt input; the
1066
1078
  // old `prevLineWasText` gate refused after headings, terminator
1067
1079
  // lines and fence closes, where micromark measurably opens). The
1068
1080
  // classifier itself is exact too (isType7Line) — including closing
1069
1081
  // raw-text names (`</style>` alone is type 7, measured) and
1070
1082
  // quoted-`>` attribute values.
1071
- !cp.prevLineOpenContent && isType7Line(t)) {
1072
- if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: realT6 ? 6 : 7 };
1073
- } else if (cp.prevLineOpenContent && cp.tableMaybeOpen && isType7Line(t)) {
1083
+ !cp.prevLineOpenContent && type7Shaped) {
1084
+ if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: realT6 ? 6 : 7, indent: ln.indent };
1085
+ } else if (cp.prevLineOpenContent && cp.tableMaybeOpen && type7Shaped) {
1086
+ cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
1087
+ }
1088
+ if (type7Shaped && cp.containerMaybeOpen) {
1074
1089
  cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
1075
1090
  }
1076
1091
  }
@@ -1136,7 +1151,12 @@ function processConfirmedLine(cp, ln, text) {
1136
1151
  pos = c + 1;
1137
1152
  continue;
1138
1153
  }
1139
- if (commentOpenAtLineStart || inRawTextTok(cp.p5Tok) || mdHtml(cp.mdBlock, 1)) break;
1154
+ if (commentOpenAtLineStart || inRawTextTok(cp.p5Tok) || mdType1RawText(cp.mdBlock)) {
1155
+ if (inRawTextTok(cp.p5Tok) && cp.p5Tok.openedInline && (tailCarriesRetroactive(ln.text) || /<template(?![a-z0-9-])/i.test(ln.text))) {
1156
+ cp.phasePoisonedAt = 0;
1157
+ }
1158
+ break;
1159
+ }
1140
1160
  const pi = scanText.indexOf("<?", pos);
1141
1161
  const cd = scanText.indexOf("<![CDATA[", pos);
1142
1162
  const dm = scanText.slice(pos).search(/<![A-Za-z]/);
@@ -1153,7 +1173,7 @@ function processConfirmedLine(cp, ln, text) {
1153
1173
  pos = bogus + 2;
1154
1174
  } else if (first === cd) {
1155
1175
  rawSpans.push([cd, cd + 9]);
1156
- if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: 5 };
1176
+ if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: 5, indent: ln.indent };
1157
1177
  if (cp.p5Tok.kind === "data") cp.p5Tok = { kind: "bogus" };
1158
1178
  if (!isMdBlank(scanText.slice(0, cd)) || ln.indent > 3) inlineRawOpenerIdx = cd;
1159
1179
  pos = cd + 9;
@@ -1165,14 +1185,14 @@ function processConfirmedLine(cp, ln, text) {
1165
1185
  continue;
1166
1186
  }
1167
1187
  rawSpans.push([pi, pi + 2]);
1168
- if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: 3 };
1188
+ if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: 3, indent: ln.indent };
1169
1189
  if (cp.p5Tok.kind === "data") cp.p5Tok = { kind: "bogus" };
1170
1190
  if (!isMdBlank(scanText.slice(0, pi)) || ln.indent > 3) inlineRawOpenerIdx = pi;
1171
1191
  pos = pi + 2;
1172
1192
  } else {
1173
1193
  rawSpans.push([decl, decl + 2]);
1174
1194
  if (ln.indent <= 3 && /^doctype/i.test(scanText.slice(decl + 2))) cp.phasePoisonedAt = 0;
1175
- if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: 4 };
1195
+ if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: 4, indent: ln.indent };
1176
1196
  if (cp.p5Tok.kind === "data") cp.p5Tok = { kind: "bogus" };
1177
1197
  if (!isMdBlank(scanText.slice(0, decl)) || ln.indent > 3) inlineRawOpenerIdx = decl;
1178
1198
  pos = decl + 2;
@@ -1231,7 +1251,7 @@ function processConfirmedLine(cp, ln, text) {
1231
1251
  if (next.startsWith(">") || next === "->") {
1232
1252
  continue;
1233
1253
  }
1234
- if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: 2 };
1254
+ if (cp.mdBlock.kind === "none") cp.mdBlock = { kind: "html", type: 2, indent: ln.indent };
1235
1255
  if (cp.p5Tok.kind === "data") cp.p5Tok = { kind: "comment" };
1236
1256
  lastCommentOpenerIdx = m.index;
1237
1257
  continue;
@@ -1373,17 +1393,37 @@ function processConfirmedLine(cp, ln, text) {
1373
1393
  openContent = false;
1374
1394
  } else if (ln.indent >= 4) {
1375
1395
  openContent = cp.prevLineOpenContent;
1376
- } else if (ATX_HEADING_RE.test(tt) || THEMATIC_BREAK_RE.test(tt) || BARE_MARKER_RE.test(tt)) {
1396
+ } else if (ATX_HEADING_RE.test(tt) || THEMATIC_BREAK_RE.test(tt)) {
1377
1397
  openContent = false;
1398
+ } else if (BARE_MARKER_RE.test(tt)) {
1399
+ openContent = tt[0] === "-" ? false : cp.prevLineOpenContent;
1378
1400
  } else if (SETEXT_LEFTOVER_RE.test(tt)) {
1379
- openContent = !cp.prevLineOpenContent;
1401
+ openContent = cp.tableMaybeOpen && cp.prevLineOpenContent ? true : !cp.prevLineOpenContent;
1380
1402
  } else {
1381
1403
  openContent = true;
1382
1404
  }
1383
1405
  cp.prevLineOpenContent = openContent;
1384
- cp.tableMaybeOpen = ln.text.includes("|") || cp.tableMaybeOpen && openContent;
1406
+ cp.tableMaybeOpen = !htmlOwnedLine && ln.text.includes("|") || cp.tableMaybeOpen && openContent;
1407
+ const containerMarker = CONTAINER_MARKER_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text) || cp.defListEnabled && DEF_LIST_DD_RE.test(ln.text);
1408
+ cp.containerMaybeOpen = openContent && (containerMarker || cp.containerMaybeOpen);
1385
1409
  }
1386
1410
  cp.prevLineWasValidDef = validLinkDef;
1411
+ cp.defBlockMaybeOpen = cp.defBlockMaybeOpen || DEF_RE.test(ln.text) || FOOTNOTE_DEF_RE.test(ln.text);
1412
+ if (FOOTNOTE_DEF_RE.test(ln.text)) cp.fnDefResumable = true;
1413
+ else if (isBlockStart && ln.indent <= 3) cp.fnDefResumable = false;
1414
+ const isBarrier = (name) => SCOPE_BARRIER_NAMES.has(name);
1415
+ const topLevelHtmlBlock = cp.mdBlock.kind === "html" && cp.mdBlock.indent === 0;
1416
+ const confirmedBarriers = cp.openStack.filter(isBarrier).length - cp.pendingTruncatedTags.filter(isBarrier).length;
1417
+ if (!topLevelHtmlBlock && confirmedBarriers > 0) {
1418
+ cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
1419
+ }
1420
+ const maskUnbacked = mdType1RawText(cp.mdBlock) && !inRawTextTok(cp.p5Tok);
1421
+ if (maskUnbacked) {
1422
+ cp.phasePoisonedAt = Math.min(cp.phasePoisonedAt, ln.start);
1423
+ if (tailCarriesRetroactive(ln.text) || /<template(?![a-z0-9-])/i.test(ln.text)) {
1424
+ cp.phasePoisonedAt = 0;
1425
+ }
1426
+ }
1387
1427
  }
1388
1428
 
1389
1429
  // src/components/incrementalParse/spliceParse.ts
@@ -1898,7 +1938,7 @@ function alignPrefixCut(prefixMdast, cutRegion, tailWrapVisible) {
1898
1938
  if (sepBuffer.length !== trailingGaps && sepBuffer.length !== trailingGaps + 1) return null;
1899
1939
  for (let j = pairIdx + 1; j < visibles.length; j++) {
1900
1940
  const v = visibles[j];
1901
- if (v.type === "html" && !/^\s*<[!?]/.test(v.value)) return null;
1941
+ if (v.type === "html" && !isExactSanitizeStrippedConstruct(v.value)) return null;
1902
1942
  }
1903
1943
  for (let i = 0; i < trailingGaps + seam; i++) {
1904
1944
  out.push({ type: "text", value: "\n" });
@@ -1948,7 +1988,7 @@ function tailLeadingTextIsHoist(tailMdastChildren, tailHastChildren) {
1948
1988
  if (!isSeparatorText(firstText)) {
1949
1989
  if (firstText.type === "text" && firstText.position === void 0 && firstVisible?.type === "html") {
1950
1990
  if (/^\s*<\/[A-Za-z][A-Za-z0-9-]*\s*>/.test(firstVisible.value)) return true;
1951
- if (isCompleteRawConstruct(firstVisible.value)) return false;
1991
+ if (isSanitizeStrippedConstruct(firstVisible.value)) return false;
1952
1992
  return null;
1953
1993
  }
1954
1994
  return false;
@@ -1964,12 +2004,26 @@ function tailLeadingTextIsHoist(tailMdastChildren, tailHastChildren) {
1964
2004
  }
1965
2005
  }
1966
2006
  if (firstVisible.type === "math") return false;
1967
- if (firstVisible.type === "html" && isCompleteRawConstruct(firstVisible.value)) return false;
2007
+ if (firstVisible.type === "html" && isSanitizeStrippedConstruct(firstVisible.value)) return false;
1968
2008
  return null;
1969
2009
  }
1970
- function isCompleteRawConstruct(value) {
2010
+ function isSanitizeStrippedConstruct(value) {
1971
2011
  const v = value.trim();
1972
- return v.startsWith("<!--") && v.endsWith("-->") || v.startsWith("<?") && v.endsWith("?>") || v.startsWith("<![CDATA[") && v.endsWith("]]>") || /^<![A-Za-z]/.test(v) && v.endsWith(">");
2012
+ return v.startsWith("<!--") && v.endsWith("-->") || v.startsWith("<?") && v.endsWith("?>") || v.startsWith("<![CDATA[") && v.endsWith("]]>") || /^<![A-Za-z]/.test(v) && !/^<!doctype/i.test(v) && v.endsWith(">");
2013
+ }
2014
+ function isExactSanitizeStrippedConstruct(value) {
2015
+ if (value.startsWith("<!--")) {
2016
+ if (value.length < 7 || !value.endsWith("-->")) return false;
2017
+ const close = value.indexOf("-->", 4);
2018
+ const bangClose = value.indexOf("--!>", 4);
2019
+ if (close !== value.length - 3) return false;
2020
+ return bangClose === -1 || bangClose > close;
2021
+ }
2022
+ if (/^<!doctype/i.test(value)) return false;
2023
+ if (value.startsWith("<?") || /^<!(?:[A-Za-z]|\[CDATA\[)/.test(value)) {
2024
+ return value.indexOf(">") === value.length - 1;
2025
+ }
2026
+ return false;
1973
2027
  }
1974
2028
  function isSeparatorText(node) {
1975
2029
  return node.type === "text" && node.position === void 0 && node.value.trim() === "";
@@ -5123,7 +5177,6 @@ function createRemendPreprocessor(options) {
5123
5177
  collectDefLabels,
5124
5178
  computeFreezeBoundary,
5125
5179
  createDefLabelScanner,
5126
- createFile,
5127
5180
  createIncrementalLatexPreprocessor,
5128
5181
  createProcessor,
5129
5182
  createRegistry,
@@ -5140,10 +5193,8 @@ function createRemendPreprocessor(options) {
5140
5193
  hasLoneSurrogate,
5141
5194
  highlight,
5142
5195
  isFootnoteSection,
5143
- isWhitespaceText,
5144
5196
  lastMeaningfulIdx,
5145
5197
  measureStage,
5146
- mergeClassNameAllowlist,
5147
5198
  normalizeForMatch,
5148
5199
  normalizeId,
5149
5200
  pangu,
@@ -5159,7 +5210,6 @@ function createRemendPreprocessor(options) {
5159
5210
  shortenDocumentId,
5160
5211
  smartypants,
5161
5212
  sourceIdFromFootnoteLiId,
5162
- splitByProtectedRegions,
5163
5213
  subscribeStageTimings,
5164
5214
  transformStage,
5165
5215
  withDefs