@beyondwork/docx-react-component 1.0.100 → 1.0.101

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@beyondwork/docx-react-component",
3
3
  "publisher": "beyondwork",
4
- "version": "1.0.100",
4
+ "version": "1.0.101",
5
5
  "description": "Embeddable React Word (docx) editor with review, comments, tracked changes, and round-trip OOXML fidelity.",
6
6
  "type": "module",
7
7
  "sideEffects": [
@@ -294,6 +294,7 @@ import type {
294
294
  ParagraphNode,
295
295
  SectionProperties,
296
296
  SubPartsCatalog,
297
+ TocCachedEntry,
297
298
  TocRegion,
298
299
  } from "../model/canonical-document.ts";
299
300
  import {
@@ -7550,14 +7551,16 @@ function refreshDocumentTableOfContents(
7550
7551
  : parseTocLevelRange(field.instruction);
7551
7552
  const entries = navigation.headings
7552
7553
  .filter((heading) => heading.level >= levelRange.from && heading.level <= levelRange.to)
7553
- .map((heading) => {
7554
+ .map((heading, index) => {
7554
7555
  const bookmarkName = bookmarkNameByOffset.get(heading.offset);
7555
- return {
7556
+ const entry: RuntimeTocEntry = {
7556
7557
  level: heading.level,
7557
7558
  text: heading.text,
7558
7559
  pageIndex: heading.pageIndex,
7559
7560
  ...(bookmarkName ? { bookmarkName } : {}),
7560
7561
  };
7562
+ const cachedPageText = resolveCachedTocPageText(selectedRegion, entry, index);
7563
+ return cachedPageText ? { ...entry, pageText: cachedPageText } : entry;
7561
7564
  });
7562
7565
  if (resultEntries.length === 0) {
7563
7566
  resultEntries = entries;
@@ -7657,6 +7660,7 @@ type RuntimeTocEntry = {
7657
7660
  level: number;
7658
7661
  text: string;
7659
7662
  pageIndex: number;
7663
+ pageText?: string;
7660
7664
  bookmarkName?: string;
7661
7665
  };
7662
7666
 
@@ -7688,11 +7692,54 @@ function buildTocRefreshResult(
7688
7692
  level: entry.level,
7689
7693
  text: entry.text,
7690
7694
  pageIndex: entry.pageIndex,
7695
+ ...(entry.pageText ? { pageText: entry.pageText } : {}),
7691
7696
  source: "generated",
7692
7697
  })),
7693
7698
  };
7694
7699
  }
7695
7700
 
7701
+ function resolveCachedTocPageText(
7702
+ region: TocRegion | undefined,
7703
+ entry: RuntimeTocEntry,
7704
+ index: number,
7705
+ ): string | undefined {
7706
+ if (!region || region.cachedEntries.length === 0) {
7707
+ return undefined;
7708
+ }
7709
+ const indexed = region.cachedEntries[index];
7710
+ if (indexed?.pageText && cachedTocEntryMatchesRuntimeEntry(indexed, entry)) {
7711
+ return indexed.pageText;
7712
+ }
7713
+ if (entry.bookmarkName) {
7714
+ const bookmarkMatch = region.cachedEntries.find(
7715
+ (cached) =>
7716
+ cached.bookmarkName === entry.bookmarkName &&
7717
+ cached.pageText &&
7718
+ cached.level === entry.level,
7719
+ );
7720
+ if (bookmarkMatch?.pageText) {
7721
+ return bookmarkMatch.pageText;
7722
+ }
7723
+ }
7724
+ return undefined;
7725
+ }
7726
+
7727
+ function cachedTocEntryMatchesRuntimeEntry(
7728
+ cached: TocCachedEntry,
7729
+ entry: RuntimeTocEntry,
7730
+ ): boolean {
7731
+ return cached.level === entry.level &&
7732
+ normalizeTocEntryPageReuseText(cached.text) === normalizeTocEntryPageReuseText(entry.text);
7733
+ }
7734
+
7735
+ function normalizeTocEntryPageReuseText(text: string): string {
7736
+ return text
7737
+ .replace(/\s+/gu, " ")
7738
+ .trim()
7739
+ .replace(/^(\d+(?:\.\d+)*\.?)\s+/u, "$1")
7740
+ .toLowerCase();
7741
+ }
7742
+
7696
7743
  function tocPageTextToPageIndex(pageText: string | undefined): number {
7697
7744
  const value = Number.parseInt(pageText ?? "", 10);
7698
7745
  return Number.isFinite(value) && value > 0 ? value - 1 : 0;
@@ -7873,7 +7920,7 @@ function buildTocEntryInlineNodes(
7873
7920
  children.push({ type: "text", text: entry.text });
7874
7921
  }
7875
7922
  children.push({ type: "tab" });
7876
- const displayed = resolveDisplayPageNumber?.(entry.pageIndex);
7923
+ const displayed = entry.pageText ?? resolveDisplayPageNumber?.(entry.pageIndex);
7877
7924
  children.push({
7878
7925
  type: "text",
7879
7926
  text: String(displayed ?? entry.pageIndex + 1),
@@ -8056,7 +8103,7 @@ function buildInlineNodesFromDisplayText(text: string): InlineNode[] {
8056
8103
  * resolver, falls back to the raw `pageIndex + 1` (pre-P5 behavior).
8057
8104
  */
8058
8105
  function buildTocInlineNodes(
8059
- entries: ReadonlyArray<{ level: number; text: string; pageIndex: number; bookmarkName?: string }>,
8106
+ entries: ReadonlyArray<{ level: number; text: string; pageIndex: number; pageText?: string; bookmarkName?: string }>,
8060
8107
  resolveDisplayPageNumber?: (pageIndex: number) => number | null,
8061
8108
  ): InlineNode[] {
8062
8109
  const children: InlineNode[] = [];
@@ -8071,7 +8118,7 @@ function buildTocInlineNodes(
8071
8118
  children.push({ type: "text", text: entry.text });
8072
8119
  }
8073
8120
  children.push({ type: "tab" });
8074
- const displayed = resolveDisplayPageNumber?.(entry.pageIndex);
8121
+ const displayed = entry.pageText ?? resolveDisplayPageNumber?.(entry.pageIndex);
8075
8122
  children.push({
8076
8123
  type: "text",
8077
8124
  text: String(displayed ?? entry.pageIndex + 1),
@@ -8085,7 +8132,7 @@ function buildTocInlineNodes(
8085
8132
 
8086
8133
  /** Test-only export of `buildTocInlineNodes` (P5 unit tests). */
8087
8134
  export function __buildTocInlineNodes(
8088
- entries: ReadonlyArray<{ level: number; text: string; pageIndex: number; bookmarkName?: string }>,
8135
+ entries: ReadonlyArray<{ level: number; text: string; pageIndex: number; pageText?: string; bookmarkName?: string }>,
8089
8136
  resolveDisplayPageNumber?: (pageIndex: number) => number | null,
8090
8137
  ): InlineNode[] {
8091
8138
  return buildTocInlineNodes(entries, resolveDisplayPageNumber);