@ai-markdown/core 3.0.0 → 3.0.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.
@@ -383,19 +383,49 @@ function createBlockPlanner() {
383
383
  let h = 0;
384
384
  let reusedContext = false;
385
385
  if (previous && source.startsWith(previous.source) && options.phantomFootnoteLabels === previous.phantoms) {
386
+ const prevHast = previous.hast.children;
387
+ const prevPlan = previous.result.plan;
388
+ const isRetainedGap = (i) => {
389
+ const gap = hast.children[i];
390
+ return gap === prevHast[i] && gap.type === "text" && !/\S/.test(gap.value);
391
+ };
386
392
  while (m < mdast.children.length) {
387
393
  const node = mdast.children[m];
388
394
  const el = hast.children[h];
389
- const item = previous.result.plan[h];
390
- if (node !== previous.mdast.children[m] || el !== previous.hast.children[h] || !el || el.type !== "element" || !item || item.kind !== "block" || item.info.startOffset !== node.position?.start.offset || !isEligible(node))
395
+ const item = prevPlan[h];
396
+ if (node !== previous.mdast.children[m] || el !== prevHast[h] || !el || el.type !== "element" || !item || item.kind !== "block" || item.info.startOffset !== node.position?.start.offset || !isEligible(node))
391
397
  break;
398
+ const startOffset = item.info.startOffset;
399
+ let next = h + 1;
400
+ let complete = true;
401
+ for (; ; ) {
402
+ let probe = next;
403
+ while (probe < hast.children.length && isRetainedGap(probe)) probe++;
404
+ const sibling = prevPlan[probe];
405
+ if (!sibling || sibling.kind !== "block" || sibling.info.startOffset !== startOffset) break;
406
+ if (hast.children[probe] !== prevHast[probe]) {
407
+ complete = false;
408
+ break;
409
+ }
410
+ next = probe + 1;
411
+ }
412
+ if (!complete) break;
392
413
  reusedContext ||= item.info.hasReference;
393
414
  m++;
394
- h++;
395
- while (h < hast.children.length) {
396
- const gap = hast.children[h];
397
- if (gap !== previous.hast.children[h] || gap.type !== "text" || /\S/.test(gap.value)) break;
398
- h++;
415
+ h = next;
416
+ while (h < hast.children.length && isRetainedGap(h)) h++;
417
+ }
418
+ if (m > 0) {
419
+ const prefixEnd = mdast.children[m - 1].position?.end.offset ?? 0;
420
+ for (let i = h; i < hast.children.length; i++) {
421
+ const child = hast.children[i];
422
+ const at = child.type === "element" ? child.position?.start.offset : void 0;
423
+ if (at !== void 0 && at < prefixEnd) {
424
+ m = 0;
425
+ h = 0;
426
+ reusedContext = false;
427
+ break;
428
+ }
399
429
  }
400
430
  }
401
431
  }
@@ -442,7 +472,12 @@ function createContributionSession() {
442
472
  phantomFootnoteLabels: targetPhantoms.missingFootnotes
443
473
  })) {
444
474
  if (node.kind === "ref") {
445
- refs.push({ label: node.label, kind: node.refKind, referenceType: node.referenceType });
475
+ refs.push({
476
+ label: node.label,
477
+ kind: node.refKind,
478
+ referenceType: node.referenceType,
479
+ ...node.nestedIn !== void 0 ? { nestedIn: node.nestedIn } : {}
480
+ });
446
481
  } else if (node.kind === "fnDef") {
447
482
  defMeta.set(node.label, {
448
483
  identifier: node.label,
@@ -476,14 +511,14 @@ function createContributionSession() {
476
511
  if (last?.registry === registry && last.symbol === sym && last.fp === fp && last.chain.length === chain.length && last.chain.every((dep, i) => dep === chain[i])) {
477
512
  return;
478
513
  }
479
- const bodiesByLabel = (0, import_engine2.extractDefBodiesFromHast)(pipeline.hast, clobberPrefix);
514
+ const bodiesBySafeId = (0, import_engine2.extractDefBodiesFromHast)(pipeline.hast, clobberPrefix);
480
515
  const defs = /* @__PURE__ */ new Map();
481
516
  for (const [label, meta] of defMeta) {
482
517
  defs.set(label, {
483
518
  identifier: meta.identifier,
484
519
  sourceIdentifier: meta.sourceIdentifier,
485
520
  contentSource: meta.contentSource,
486
- bodyHast: bodiesByLabel.get(label) ?? []
521
+ bodyHast: bodiesBySafeId.get((0, import_engine2.footnoteSafeId)(meta.sourceIdentifier)) ?? []
487
522
  });
488
523
  }
489
524
  lastContribution = { registry, symbol: sym, fp, chain };
@@ -691,6 +726,7 @@ function buildAggregateTree(registry, clobberPrefix, preserveOrphanReferences =
691
726
  });
692
727
  }
693
728
  }
729
+ ordered.sort((a, b) => (a.n ?? 0) - (b.n ?? 0));
694
730
  if (preserveOrphanReferences) {
695
731
  for (const sym of registry.chunkOrder) {
696
732
  const data = registry.chunkData.get(sym);
@@ -778,6 +814,30 @@ function buildAggregateTree(registry, clobberPrefix, preserveOrphanReferences =
778
814
  // src/pipelineSession.ts
779
815
  var import_engine4 = require("@ai-markdown/engine");
780
816
  var unmeasured = (_stage, fn) => fn();
817
+ function endPoint(text) {
818
+ let line = 1;
819
+ let lineStart = 0;
820
+ for (let i = 0; i < text.length; i++) {
821
+ const code = text.charCodeAt(i);
822
+ if (code === 10 || code === 13 && text.charCodeAt(i + 1) !== 10) {
823
+ line += 1;
824
+ lineStart = i + 1;
825
+ }
826
+ }
827
+ return { line, column: text.length - lineStart + 1, offset: text.length };
828
+ }
829
+ function plainTextTrees(content) {
830
+ const position = { start: { line: 1, column: 1, offset: 0 }, end: endPoint(content) };
831
+ const text = { type: "text", value: content, position };
832
+ return {
833
+ mdast: { type: "root", children: [{ type: "paragraph", children: [text], position }], position },
834
+ hast: {
835
+ type: "root",
836
+ children: [{ type: "element", tagName: "p", properties: {}, children: [text], position }],
837
+ position
838
+ }
839
+ };
840
+ }
781
841
  function createPipelineSession() {
782
842
  let state = null;
783
843
  return {
@@ -819,19 +879,33 @@ function createPipelineSession() {
819
879
  } : {
820
880
  ...remarkRehypeOptions
821
881
  };
882
+ const fullPipeline = () => {
883
+ try {
884
+ const parsed = measureHere(
885
+ "parse",
886
+ () => (0, import_engine4.parseStage)({
887
+ children: augmented,
888
+ remarkPlugins,
889
+ rehypePlugins,
890
+ remarkRehypeOptions: mergedRemarkRehypeOptions
891
+ })
892
+ );
893
+ const hastRoot = measureHere("transform", () => (0, import_engine4.transformStage)(parsed));
894
+ return { mdast: parsed.mdast, hast: hastRoot };
895
+ } catch (error) {
896
+ if (!(error instanceof import_engine4.EngineRawHtmlDepthError)) throw error;
897
+ if (true) {
898
+ console.error(
899
+ "[ai-react-markdown] raw HTML nested past the engine depth bound \u2014 rendering this frame as plain text:",
900
+ error
901
+ );
902
+ }
903
+ return plainTextTrees(content ?? "");
904
+ }
905
+ };
822
906
  if (!incrementalParse) {
823
907
  state = null;
824
- const parsed = measureHere(
825
- "parse",
826
- () => (0, import_engine4.parseStage)({
827
- children: augmented,
828
- remarkPlugins,
829
- rehypePlugins,
830
- remarkRehypeOptions: mergedRemarkRehypeOptions
831
- })
832
- );
833
- const hastRoot = measureHere("transform", () => (0, import_engine4.transformStage)(parsed));
834
- return { mdast: parsed.mdast, hast: hastRoot };
908
+ return fullPipeline();
835
909
  }
836
910
  try {
837
911
  const result = (0, import_engine4.advanceIncrementalParse)(state, content ?? "", {
@@ -854,7 +928,12 @@ function createPipelineSession() {
854
928
  // Explicit even though `rehypePlugins` already carries it: a
855
929
  // credential change must never reuse trees stamped under the
856
930
  // old one.
857
- provenance
931
+ provenance,
932
+ // The boundary scanner's grammar profile. The scan checkpoint
933
+ // already refuses to resume under a different profile, but the
934
+ // retained TREES were still spliced against — a prefix frozen
935
+ // under one profile must not survive into frames under the other.
936
+ defListEnabled
858
937
  ],
859
938
  defListEnabled,
860
939
  phantomSuffix,
@@ -867,17 +946,7 @@ function createPipelineSession() {
867
946
  if (true) {
868
947
  console.error("[ai-react-markdown] incremental parse failed \u2014 full parse fallback for this frame:", error);
869
948
  }
870
- const parsed = measureHere(
871
- "parse",
872
- () => (0, import_engine4.parseStage)({
873
- children: augmented,
874
- remarkPlugins,
875
- rehypePlugins,
876
- remarkRehypeOptions: mergedRemarkRehypeOptions
877
- })
878
- );
879
- const hastRoot = measureHere("transform", () => (0, import_engine4.transformStage)(parsed));
880
- return { mdast: parsed.mdast, hast: hastRoot };
949
+ return fullPipeline();
881
950
  }
882
951
  }
883
952
  };