@superdoc/mcp 1.3.1-next.6 → 1.3.1-next.8

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.
Files changed (2) hide show
  1. package/dist/index.js +364 -203
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31318,7 +31318,7 @@ var init_host = __esm(() => {
31318
31318
  });
31319
31319
 
31320
31320
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31321
- var SDK_VERSION = "2.16.1-next.6";
31321
+ var SDK_VERSION = "2.16.1-next.8";
31322
31322
 
31323
31323
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31324
31324
  import { chmodSync, existsSync } from "node:fs";
@@ -132506,6 +132506,7 @@ function createSDTxPerfProbe() {
132506
132506
  sourceCoverageChunksCarried: null,
132507
132507
  sourceCoverageFullRescans: null,
132508
132508
  sourceCoverageBytesScanned: null,
132509
+ sourceCoverageCurrentPartBytesRead: null,
132509
132510
  renderCommitEnvelopeMs: null,
132510
132511
  catalogMaintenanceMs: null,
132511
132512
  catalogTextSplicesApplied: null,
@@ -132655,6 +132656,58 @@ function findEnclosingRunElementAt(xml, pos) {
132655
132656
  }
132656
132657
  var escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), ATTRS = `(?:"[^"]*"|'[^']*'|[^>"'])*?`, qnamePattern = (escapedLocalName) => `(?:[\\w.-]+:)?${escapedLocalName}(?=[\\s/>])`;
132657
132658
 
132659
+ // ../../../v2/editor-core/dist/document/internal/inline-text-extraction.js
132660
+ function extractVisibleTextFromXml(xml, telemetry) {
132661
+ return extractInlineText(xml, "visible", telemetry);
132662
+ }
132663
+ function extractTrackedTextFromXml(xml, telemetry) {
132664
+ return extractInlineText(xml, "tracked", telemetry);
132665
+ }
132666
+ function projectParagraphInlineText(paragraphXml, space, telemetry) {
132667
+ return projectReadOnlyParagraphText(paragraphXml, space, telemetry);
132668
+ }
132669
+ function extractInlineText(xml, space, telemetry) {
132670
+ const chunks = [];
132671
+ for (const { tagStart, node: node2 } of iterateTopLevelParagraphElements(xml)) {
132672
+ chunks.push(projectParagraphInlineText(xml.slice(tagStart, node2.end), space, telemetry));
132673
+ }
132674
+ return chunks.length === 0 ? tolerantTokenWalk(xml, space) : chunks.join("");
132675
+ }
132676
+ function tolerantTokenWalk(xml, space) {
132677
+ const contentXml = stripElements(xml, "sdtPr");
132678
+ const body = stripOpaqueObjectBlocks(space === "visible" ? stripParagraphProperties(stripHiddenRevisionBlocks(contentXml)) : stripParagraphProperties(contentXml));
132679
+ const pattern = space === "visible" ? /<[\w.-]+:t\b[^>]*>([\s\S]*?)<\/[\w.-]+:t>|<[\w.-]+:(tab|br|cr)\b[^>]*\/>/g : /<[\w.-]+:(?:t|delText)\b[^>]*>([\s\S]*?)<\/[\w.-]+:(?:t|delText)>|<[\w.-]+:(tab|br|cr)\b[^>]*\/>/g;
132680
+ let out = "";
132681
+ for (const token of body.matchAll(pattern)) {
132682
+ if (token[1] != null) {
132683
+ out += decodeXmlText(token[1]);
132684
+ continue;
132685
+ }
132686
+ out += controlChar2(token[2]);
132687
+ }
132688
+ return out;
132689
+ }
132690
+ function controlChar2(control) {
132691
+ if (control === "tab")
132692
+ return "\t";
132693
+ return `
132694
+ `;
132695
+ }
132696
+ function stripParagraphProperties(xml) {
132697
+ return stripElements(xml, "pPr");
132698
+ }
132699
+ function stripHiddenRevisionBlocks(xml) {
132700
+ return xml.replace(/<[\w.-]+:(?:del|moveFrom)\b(?![^>]*\/>)[^>]*>[\s\S]*?<\/[\w.-]+:(?:del|moveFrom)>/g, "");
132701
+ }
132702
+ function stripOpaqueObjectBlocks(xml) {
132703
+ return xml.replace(/<[\w.-]+:(?:drawing|object|pict)\b(?![^>]*\/>)[^>]*>[\s\S]*?<\/[\w.-]+:(?:drawing|object|pict)>|<[\w.-]+:(?:drawing|object|pict)\b[^>]*\/>/g, "");
132704
+ }
132705
+ var init_inline_text_extraction = __esm(() => {
132706
+ init_paragraph_scan_count();
132707
+ init_paragraph_text_projection();
132708
+ init_xml_text();
132709
+ });
132710
+
132658
132711
  // ../../../v2/editor-core/dist/document/lazy-indexes.js
132659
132712
  function ensureLazyIndexState(state) {
132660
132713
  const carrier = state;
@@ -133172,53 +133225,7 @@ function buildSearchTextIndex(input) {
133172
133225
  };
133173
133226
  }
133174
133227
  function visibleParagraphTextWithFieldPolicy(paragraphXml, includeDeletedText = false) {
133175
- const visibleXml = stripParagraphPropertiesXml(paragraphXml);
133176
- const TOK_RE = /<([\w.-]+):(t|delText|instrText|fldChar)\b([^>]*)>(?:([\s\S]*?)<\/\1:\2>)?|<([\w.-]+):(tab|br|cr)\b([^>]*)\/>/g;
133177
- let out = "";
133178
- let fieldDepth = 0;
133179
- let instrSuppressed = false;
133180
- let m;
133181
- while (m = TOK_RE.exec(visibleXml)) {
133182
- const local = m[2] ?? m[6];
133183
- const attrs = m[3] ?? m[7] ?? "";
133184
- const inner = m[4] ?? "";
133185
- if (local === "fldChar") {
133186
- const kind = attrs.match(/(?:[\w.-]+:)?fldCharType="([^"]+)"/)?.[1] ?? "";
133187
- if (kind === "begin") {
133188
- fieldDepth += 1;
133189
- instrSuppressed = true;
133190
- } else if (kind === "separate") {
133191
- instrSuppressed = false;
133192
- } else if (kind === "end") {
133193
- fieldDepth = Math.max(0, fieldDepth - 1);
133194
- instrSuppressed = fieldDepth > 0;
133195
- }
133196
- continue;
133197
- }
133198
- if (local === "tab" || local === "br" || local === "cr") {
133199
- if (instrSuppressed)
133200
- continue;
133201
- out += local === "tab" ? "\t" : `
133202
- `;
133203
- continue;
133204
- }
133205
- if (local === "instrText")
133206
- continue;
133207
- if (local === "delText") {
133208
- if (includeDeletedText)
133209
- out += decodeXmlText(inner);
133210
- continue;
133211
- }
133212
- if (local === "t") {
133213
- if (instrSuppressed)
133214
- continue;
133215
- out += decodeXmlText(inner);
133216
- }
133217
- }
133218
- return out;
133219
- }
133220
- function stripParagraphPropertiesXml(paragraphXml) {
133221
- return stripElements(paragraphXml, "pPr");
133228
+ return projectParagraphInlineText(paragraphXml, includeDeletedText ? "tracked" : "visible");
133222
133229
  }
133223
133230
  function normalizeParagraphXmlForSearch(paragraphXml, storyId) {
133224
133231
  return shouldExcludeNestedTextboxContent(storyId) ? stripTextboxContent(paragraphXml) : paragraphXml;
@@ -133245,7 +133252,7 @@ function storyPartUriFromStoryId(storyId) {
133245
133252
  var TD7, SEARCH_TEXT_INDEX_REGISTRY_PREFIX = "__sd:search-text-index:", SEARCH_TEXT_INDEX_TAG, SEARCH_TEXT_INDEX_DEFERRED_PREFIX = "__sd:search-text-index-deferred:", SEARCH_TEXT_INDEX_PART_GENERATION_PREFIX = "__sd:search-text-generation:", SEARCH_TEXT_INDEX_PART_GENERATION_TAG, INITIAL_SEARCH_TEXT_INDEX_PART_GENERATION, SEARCH_TEXT_INDEX_DELETED_SUFFIX = "#deleted";
133246
133253
  var init_search_text_index = __esm(() => {
133247
133254
  init_sd_document_state();
133248
- init_xml_text();
133255
+ init_inline_text_extraction();
133249
133256
  init_lazy_indexes();
133250
133257
  init_paragraph_index();
133251
133258
  TD7 = new TextDecoder;
@@ -142323,7 +142330,8 @@ function stageRetainedSourceChunkWindowSplice(input) {
142323
142330
  if (input.windowStart < target.byteStart)
142324
142331
  return null;
142325
142332
  if (input.windowEnd <= target.byteEnd) {
142326
- const bootstrapDecision = deriveExactBootstrapRetiling({
142333
+ const retainsTextBoundary = input.directBodyChildDelta == null && input.nestedParagraphDelta == null && target.byteEnd - target.byteStart + input.delta <= DEFAULT_SOURCE_BOOTSTRAP_POLICY.maxBytes;
142334
+ const bootstrapDecision = retainsTextBoundary ? { applicable: false } : deriveExactBootstrapRetiling({
142327
142335
  retained,
142328
142336
  target,
142329
142337
  targetIndex: k,
@@ -150962,9 +150970,17 @@ function refreshMainStorySourceCoverageFromCurrentBytes(state, mainStoryId, loca
150962
150970
  return current;
150963
150971
  }
150964
150972
  const partUri = mainDocumentPartUriFromStoryId(storyId);
150965
- const bytes = state.packageBytes.get(partUri);
150966
- if (!bytes)
150973
+ if (!state.packageBytes.has(partUri))
150967
150974
  return current;
150975
+ let materializedBytes;
150976
+ const readCurrentBytes = () => {
150977
+ if (!materializedBytes) {
150978
+ materializedBytes = state.packageBytes.get(partUri);
150979
+ recordSDTxPerf("sourceCoverageCurrentPartBytesRead", materializedBytes.byteLength);
150980
+ }
150981
+ return materializedBytes;
150982
+ };
150983
+ recordSDTxPerf("sourceCoverageCurrentPartBytesRead", 0);
150968
150984
  const storyRevision = state.stories.get(storyId)?.descriptor.revision ?? current.chunks[0]?.storyRevision ?? state.packageRevision;
150969
150985
  const sourceCoverageRevision = state.revisions.sourceCoverageRevision();
150970
150986
  const localizedBatch = localizedMutation && "splices" in localizedMutation ? localizedMutation : null;
@@ -151005,13 +151021,17 @@ function refreshMainStorySourceCoverageFromCurrentBytes(state, mainStoryId, loca
151005
151021
  delta: localizedSplice.delta,
151006
151022
  beforeWindowBytes: localizedSplice.beforeWindowBytes,
151007
151023
  afterWindowBytes: localizedSplice.afterWindowBytes,
151008
- currentPartBytes: bytes,
151024
+ get currentPartBytes() {
151025
+ return readCurrentBytes();
151026
+ },
151009
151027
  storyRevision,
151010
151028
  ...localizedSplice.directBodyChildDelta == null ? {} : { directBodyChildDelta: localizedSplice.directBodyChildDelta },
151011
151029
  ...localizedSplice.nestedParagraphDelta == null ? {} : { nestedParagraphDelta: localizedSplice.nestedParagraphDelta }
151012
151030
  });
151013
151031
  if (staged) {
151014
151032
  staged.commit(storyRevision);
151033
+ recordSDTxPerf("sourceCoverageFullRescans", 0);
151034
+ recordSDTxPerf("sourceCoverageBytesScanned", localizedSplice.beforeWindowBytes.byteLength + localizedSplice.afterWindowBytes.byteLength);
151015
151035
  recordSDTxPerf("sourceCoverageChunksRebuilt", staged.work.coverageChunksRebuilt);
151016
151036
  recordSDTxPerf("sourceCoverageChunksCarried", Math.max(0, current.chunks.length - staged.work.coverageChunksVisited));
151017
151037
  const next2 = {
@@ -151031,6 +151051,7 @@ function refreshMainStorySourceCoverageFromCurrentBytes(state, mainStoryId, loca
151031
151051
  return next2;
151032
151052
  }
151033
151053
  }
151054
+ const bytes = readCurrentBytes();
151034
151055
  let next;
151035
151056
  if (current.status === "source-complete") {
151036
151057
  const shifted = localizedSplice && current.byteCoverageComplete && !exactBootstrapRetilingRequired ? shiftStorySpineChunksForLocalizedSplice({
@@ -168958,7 +168979,7 @@ function projectDeletedImageParagraphGroups(input) {
168958
168979
  const deletedText = [
168959
168980
  ...fragments,
168960
168981
  ...structuralFragments.filter((fragment2) => fragment2 !== marker)
168961
- ].sort((left, right) => left.byteStart - right.byteStart).map((fragment2) => extractVisibleTextFromXml(xml.slice(fragment2.byteStart, fragment2.byteEnd), "del")).join("");
168982
+ ].sort((left, right) => left.byteStart - right.byteStart).map((fragment2) => extractVisibleTextFromXml2(xml.slice(fragment2.byteStart, fragment2.byteEnd), "del")).join("");
168962
168983
  const grouped = {
168963
168984
  ...mark,
168964
168985
  id,
@@ -169106,7 +169127,7 @@ function materializeFullParagraphInsertion(lookupContext, args) {
169106
169127
  const paragraphKind = classifyFullParagraphInsertion(lookupContext, partXml, paragraphStart, paragraphEnd, paragraphXml);
169107
169128
  const textFragments = textEntries.flatMap((entry) => entry.fragments).sort((left, right) => left.byteStart - right.byteStart);
169108
169129
  const objectFragments = objectEntries.flatMap((entry) => entry.structuralFragments);
169109
- const insertedText = [...textFragments, ...objectFragments].sort((left, right) => left.byteStart - right.byteStart).map((fragment2) => extractVisibleTextFromXml(partXml.slice(fragment2.byteStart, fragment2.byteEnd), "ins")).join("");
169130
+ const insertedText = [...textFragments, ...objectFragments].sort((left, right) => left.byteStart - right.byteStart).map((fragment2) => extractVisibleTextFromXml2(partXml.slice(fragment2.byteStart, fragment2.byteEnd), "ins")).join("");
169110
169131
  const imageOnlyEntry = textFragments.length === 0 && insertedText === "" && objectEntries.length === 1 && objectFragments.length === 1 && objectEntries[0].subtype === "image-insertion" ? objectEntries[0] : undefined;
169111
169132
  const imageEntry = paragraphKind.subtype === "paragraph-insertion" ? imageOnlyEntry : undefined;
169112
169133
  const subtype = imageEntry ? "image-insertion" : paragraphKind.subtype;
@@ -169475,7 +169496,7 @@ function projectTrackedHyperlinkWrapGroupsWithLookupContext(lookupContext, input
169475
169496
  const fieldXml = partXml.slice(fieldFragment.byteStart, fieldFragment.byteEnd);
169476
169497
  if (!/<[\w.-]+:instrText\b[^>]*>[\s\S]*?\bHYPERLINK\b/i.test(fieldXml))
169477
169498
  continue;
169478
- const fieldResultText = extractVisibleTextFromXml(fieldXml);
169499
+ const fieldResultText = extractVisibleTextFromXml2(fieldXml);
169479
169500
  if (!fieldResultText)
169480
169501
  continue;
169481
169502
  const candidates = deletions.filter((deletion) => {
@@ -169638,7 +169659,7 @@ function buildTrackedFieldLocationKey(lookupContext, partXml, fragment2) {
169638
169659
  return `${paragraphKey}|text-prefix:${hashGroupKey(visiblePrefix)}`;
169639
169660
  }
169640
169661
  function extractDeletionText(deletion, partXml) {
169641
- return deletion.fragments.map((fragment2) => extractVisibleTextFromXml(partXml.slice(fragment2.byteStart, fragment2.byteEnd), "del")).join("");
169662
+ return deletion.fragments.map((fragment2) => extractVisibleTextFromXml2(partXml.slice(fragment2.byteStart, fragment2.byteEnd), "del")).join("");
169642
169663
  }
169643
169664
  function isAbsorbableInlineObjectInsertion(entry, fragment2) {
169644
169665
  const kind = entry.subtype;
@@ -170342,7 +170363,7 @@ function buildCanonicalGroupText(partXml, run) {
170342
170363
  let out = "";
170343
170364
  for (const atom of run) {
170344
170365
  if (atom.kind === "text") {
170345
- out += extractVisibleTextFromXml(partXml.slice(atom.fragment.byteStart, atom.fragment.byteEnd), "ins");
170366
+ out += extractVisibleTextFromXml2(partXml.slice(atom.fragment.byteStart, atom.fragment.byteEnd), "ins");
170346
170367
  } else if (atom.kind === "mark") {
170347
170368
  out += `
170348
170369
  `;
@@ -170929,7 +170950,7 @@ function materializeRunFormattingGroup(storyId, partUri, partXml, run, input, st
170929
170950
  const documentOrderStart = Math.min(...fragments.map((fragment2) => fragment2.byteStart));
170930
170951
  const documentOrderEnd = Math.max(...fragments.map((fragment2) => fragment2.byteEnd));
170931
170952
  const formattingDelta = childEntries.every((entry) => entry.formattingDelta && entry.formattingDelta.beforeXml === childEntries[0].formattingDelta?.beforeXml && entry.formattingDelta.afterXml === childEntries[0].formattingDelta?.afterXml) ? childEntries[0].formattingDelta : null;
170932
- const excerpt = head.paragraphOrdinal === undefined && formattingDelta ? childEntries[0].excerpt : extractVisibleTextFromXml(partXml.slice(head.paragraph.start, head.paragraph.end), "ins");
170953
+ const excerpt = head.paragraphOrdinal === undefined && formattingDelta ? childEntries[0].excerpt : extractVisibleTextFromXml2(partXml.slice(head.paragraph.start, head.paragraph.end), "ins");
170933
170954
  const date6 = earliestDate(fragments.map((fragment2) => fragment2.date));
170934
170955
  const wordIdOther = uniqueNonEmptyStrings(fragments.map((fragment2) => fragment2.wId));
170935
170956
  const members = run.map((member) => ({
@@ -171116,7 +171137,7 @@ function materializeFormattingGroup(storyId, partUri, partXml, run, input) {
171116
171137
  const fragments = run.map((member) => member.fragment);
171117
171138
  const documentOrderStart = Math.min(...fragments.map((fragment2) => fragment2.byteStart));
171118
171139
  const documentOrderEnd = Math.max(...fragments.map((fragment2) => fragment2.byteEnd));
171119
- const excerpt = run.map((member) => extractVisibleTextFromXml(partXml.slice(member.paragraph.start, member.paragraph.end), "ins")).join(`
171140
+ const excerpt = run.map((member) => extractVisibleTextFromXml2(partXml.slice(member.paragraph.start, member.paragraph.end), "ins")).join(`
171120
171141
  `);
171121
171142
  const date6 = earliestDate(fragments.map((fragment2) => fragment2.date));
171122
171143
  const wordIdOther = uniqueNonEmptyStrings(fragments.map((fragment2) => fragment2.wId));
@@ -171515,7 +171536,7 @@ function buildCanonicalDeletionGroupText(partXml, run) {
171515
171536
  let out = "";
171516
171537
  for (const atom of run) {
171517
171538
  if (atom.kind === "text") {
171518
- out += extractVisibleTextFromXml(partXml.slice(atom.fragment.byteStart, atom.fragment.byteEnd), "del");
171539
+ out += extractVisibleTextFromXml2(partXml.slice(atom.fragment.byteStart, atom.fragment.byteEnd), "del");
171519
171540
  } else if (atom.kind === "mark") {
171520
171541
  out += `
171521
171542
  `;
@@ -174217,8 +174238,8 @@ function isAdjacentIgnoringMarkers(lookupContext, a, b, partXml) {
174217
174238
  return false;
174218
174239
  if (!isSameReviewGroupIdentity(buildReviewIdentity({ ...first.author, email: first.authorEmail }), buildReviewIdentity({ ...second.author, email: second.authorEmail })))
174219
174240
  return false;
174220
- const before = extractVisibleTextFromXml(partXml.slice(first.byteStart, first.byteEnd), "del");
174221
- const after = extractVisibleTextFromXml(partXml.slice(second.byteStart, second.byteEnd), "ins");
174241
+ const before = extractVisibleTextFromXml2(partXml.slice(first.byteStart, first.byteEnd), "del");
174242
+ const after = extractVisibleTextFromXml2(partXml.slice(second.byteStart, second.byteEnd), "ins");
174222
174243
  const insertionOpenEnd = partXml.indexOf(">", second.byteStart) + 1;
174223
174244
  const insertionCloseStart = partXml.indexOf("</", insertionOpenEnd);
174224
174245
  const insertionCloseEnd = partXml.indexOf(">", insertionCloseStart) + 1;
@@ -176600,7 +176621,7 @@ function enrichLogicalChangeExcerpts(catalog, partXmlByUri) {
176600
176621
  const afterTexts = [];
176601
176622
  for (const fragment2 of logical.fragments) {
176602
176623
  const inner = xml.slice(fragment2.byteStart, fragment2.byteEnd);
176603
- const visible = extractVisibleTextFromXml(inner, fragment2.kind);
176624
+ const visible = extractVisibleTextFromXml2(inner, fragment2.kind);
176604
176625
  if (visible.length === 0 && logical.subtype === "move-image") {
176605
176626
  continue;
176606
176627
  }
@@ -176719,7 +176740,7 @@ function findEnclosingContainerId(xml, start, localName2) {
176719
176740
  }
176720
176741
  return null;
176721
176742
  }
176722
- function extractVisibleTextFromXml(xml, kind) {
176743
+ function extractVisibleTextFromXml2(xml, kind) {
176723
176744
  const sanitizedXml = kind ? stripNestedSameKindWrapperXml(xml, kind) : xml;
176724
176745
  const tag = kind === "del" ? "(?:delText)" : kind === "ins" ? "(?:t)" : "(?:t|delText)";
176725
176746
  const re = new RegExp(`<[\\w.-]+:${tag}\\b[^>]*>([\\s\\S]*?)<\\/[\\w.-]+:${tag}>`, "g");
@@ -177466,8 +177487,10 @@ function buildSDRenderCommitEnvelope(state, prepared, result, context = {}, opti
177466
177487
  if (!storySurface || !storySurface.storyLocal || !storySurfaceFamilyMatchesSource(storySurface.family, source.sourceKind)) {
177467
177488
  return broad("non-local-story");
177468
177489
  }
177469
- if (op.on.storyId !== state.mainStoryId)
177470
- return broad("non-main-story");
177490
+ if (op.on.storyId !== state.mainStoryId) {
177491
+ const immutableStoryOwner = captureImmutableHeaderFooterTextEffect(state, prepared, result, context);
177492
+ return { ...broad("non-main-story"), ...immutableStoryOwner ? { immutableStoryOwner } : {} };
177493
+ }
177471
177494
  const ownerContentEffects = source.sourceKind === "textboxAtomReplacement" ? textboxOwnerContentEffects(state, prepared, result.storiesChanged ?? []) : [];
177472
177495
  if (!ownerContentEffects)
177473
177496
  return broad("multi-story");
@@ -177742,6 +177765,54 @@ function captureTrackedDecisionAllResolvedProof(state, prepared, base2) {
177742
177765
  function trackedChangeInvalidationIds(refs) {
177743
177766
  return [...new Set(refs.flatMap((ref3) => ref3.kind === "trackedChange" ? [ref3.entityId] : []))];
177744
177767
  }
177768
+ function captureImmutableHeaderFooterTextEffect(state, prepared, result, context) {
177769
+ const op = prepared.source;
177770
+ if (op.kind !== "editText" || op.on.startBlockId !== op.on.endBlockId || state.sourceCompletePosture !== "source-complete" || prepared.resolvedTargets.stories.length !== 1 || result.storiesChanged?.length !== 1 || prepared.resolvedTargets.partUris.length !== 1 || result.partsChanged?.length !== 1 || !hasOnlyLocalTextDependencies(prepared, op.changeMode))
177771
+ return null;
177772
+ const descriptor = getStoryDescriptorFromState(state, op.on.storyId);
177773
+ if (!descriptor || descriptor.storyKind !== "header" && descriptor.storyKind !== "footer")
177774
+ return null;
177775
+ const story = result.storiesChanged[0];
177776
+ const part = result.partsChanged[0];
177777
+ if (story.storyId !== op.on.storyId || part.partUri !== op.on.partUri || part.kind !== "modified" || !part.previousRevision || !part.nextRevision)
177778
+ return null;
177779
+ const annotations = op.changeMode === "tracked" ? captureTrackedAnnotationDelta(prepared) : [];
177780
+ if (annotations == null)
177781
+ return null;
177782
+ const patchGroup = result.forwardPatchGroup ?? prepared.localApplyBundle;
177783
+ const entry = patchGroup.perPart[op.on.partUri];
177784
+ if (entry?.kind !== "modify" || entry.patches.length !== 1)
177785
+ return null;
177786
+ const patch = entry.patches[0];
177787
+ if (patch.kind !== "replaceBytes" || patch.startByte !== op.on.paragraphByteStart || patch.endByte !== op.on.paragraphByteEnd || classifyUnprovedSliceDependency(TD25.decode(patch.bytes), annotations, context.originParagraphXml))
177788
+ return null;
177789
+ const length = state.packageBytes.byteLength(op.on.partUri);
177790
+ if (length == null || length > MAX_NARROW_SLICE_BYTES)
177791
+ return null;
177792
+ const bytes = readPartRangeFromStateSync(state, op.on.partUri, 0, length);
177793
+ if (!bytes)
177794
+ return null;
177795
+ const xml = TD25.decode(bytes);
177796
+ if (GLOBAL_SLICE_DEPENDENCY_RE.test(xml) || FAIL_CLOSED_NON_COMMENT_REF_OR_ANCHOR_RE.test(xml) || COMMENT_ANCHOR_RE.test(xml) || /<(?:[\w.-]+:)?(?:numPr|txbxContent|hyperlink)\b/.test(xml))
177797
+ return null;
177798
+ const dependencies = captureRenderDependencyParts(state, op.on.partUri, null);
177799
+ if (!dependencies)
177800
+ return null;
177801
+ return {
177802
+ schemaVersion: 1,
177803
+ kind: descriptor.storyKind,
177804
+ storyId: story.storyId,
177805
+ partUri: part.partUri,
177806
+ previousStoryRevision: story.previousRevision,
177807
+ storyRevision: story.nextRevision,
177808
+ previousPartRevision: part.previousRevision,
177809
+ partRevision: part.nextRevision,
177810
+ paragraphId: op.on.startBlockId,
177811
+ partXml: xml,
177812
+ byteLength: bytes.byteLength,
177813
+ dependencies
177814
+ };
177815
+ }
177745
177816
  function buildNoteOwnerRenderCommitEnvelope(state, prepared, result, context, base2) {
177746
177817
  const broad = (reason) => ({
177747
177818
  ...base2,
@@ -177757,7 +177828,10 @@ function buildNoteOwnerRenderCommitEnvelope(state, prepared, result, context, ba
177757
177828
  if (!noteStory)
177758
177829
  return broad("note-owner-identity-mismatch");
177759
177830
  const changeMode = source.kind === "editText" ? source.changeMode : source.changeMode ?? "direct";
177760
- if (changeMode !== "direct")
177831
+ if (changeMode === "tracked" && source.kind !== "editText")
177832
+ return broad("tracked-annotation-unproved");
177833
+ const trackedAnnotations = changeMode === "tracked" ? captureTrackedAnnotationDelta(prepared) : [];
177834
+ if (changeMode === "tracked" && !trackedAnnotations)
177761
177835
  return broad("tracked-annotation-unproved");
177762
177836
  const storySurface = prepared.backendExtensions.storySurface;
177763
177837
  if (!storySurface || !storySurface.storyLocal)
@@ -177785,8 +177859,8 @@ function buildNoteOwnerRenderCommitEnvelope(state, prepared, result, context, ba
177785
177859
  if (source.kind === "editText") {
177786
177860
  if (source.on.startBlockId !== source.on.endBlockId)
177787
177861
  return broad("range-not-single-block");
177788
- if (!hasOnlyLocalTextDependencies(prepared, "direct")) {
177789
- return broad(hasUnexpectedRefs(prepared, "direct") ? "ref-dependency-change" : "global-dependency-change");
177862
+ if (!hasOnlyLocalTextDependencies(prepared, changeMode)) {
177863
+ return broad(hasUnexpectedRefs(prepared, changeMode) ? "ref-dependency-change" : "global-dependency-change");
177790
177864
  }
177791
177865
  } else {
177792
177866
  const deltaReason = classifyUnexpectedStructuralDelta(prepared, source, storyId, noteStory.partUri, null, null);
@@ -177827,7 +177901,7 @@ function buildNoteOwnerRenderCommitEnvelope(state, prepared, result, context, ba
177827
177901
  return broad("paragraph-index-mismatch");
177828
177902
  }
177829
177903
  const postParagraphXml = TD25.decode(patch.bytes);
177830
- const dependencyReason = classifyUnprovedSliceDependency(postParagraphXml, [], context.originParagraphXml);
177904
+ const dependencyReason = classifyUnprovedSliceDependency(postParagraphXml, trackedAnnotations, context.originParagraphXml);
177831
177905
  if (dependencyReason)
177832
177906
  return broad(dependencyReason);
177833
177907
  }
@@ -177858,7 +177932,7 @@ function buildNoteOwnerRenderCommitEnvelope(state, prepared, result, context, ba
177858
177932
  classification: {
177859
177933
  kind: "narrow-note-owner",
177860
177934
  operation,
177861
- changeMode: "direct",
177935
+ changeMode,
177862
177936
  noteType: noteStory.noteType,
177863
177937
  noteId: origin.noteId,
177864
177938
  storyId,
@@ -193035,7 +193109,25 @@ function splitInsertionAroundChildChange(input, allTokens, parent) {
193035
193109
  const headRuns = coalesceWrappedRuns(flat.slice(0, localStart));
193036
193110
  const removedRuns = coalesceWrappedRuns(flat.slice(localStart, localEnd));
193037
193111
  const tailRuns = coalesceWrappedRuns(flat.slice(localEnd));
193038
- const headInsXml = headText.length > 0 || headOwnedNested.length > 0 ? buildInsWrapperXml({
193112
+ let freshBaseWId = null;
193113
+ let freshWIdCount = 0;
193114
+ const allocateFreshWId = () => {
193115
+ if (freshBaseWId === null)
193116
+ freshBaseWId = resolveNextWId(input);
193117
+ const offset = freshWIdCount++;
193118
+ if (offset === 0)
193119
+ return String(freshBaseWId);
193120
+ if (typeof input.nextWId === "number" && offset === 1)
193121
+ return String(freshBaseWId + 1);
193122
+ return String(input.reserveWId ? input.reserveWId() : freshBaseWId + offset);
193123
+ };
193124
+ const childDelWId = removedText.length > 0 ? allocateFreshWId() : null;
193125
+ const childInsWId = input.newText.length > 0 ? allocateFreshWId() : null;
193126
+ const hasHeadFragment = headText.length > 0 || headOwnedNested.length > 0;
193127
+ const hasTailFragment = tailText.length > 0 || tailOwnedNested.length > 0;
193128
+ const emitsTrailingParentFragment = hasTailFragment || removedText.length > 0 && input.newText.length > 0;
193129
+ const tailParentWId = input.changeMode === "tracked" && input.newText.length > 0 && hasHeadFragment && emitsTrailingParentFragment ? allocateFreshWId() : parent.wId;
193130
+ const headInsXml = hasHeadFragment ? buildInsWrapperXml({
193039
193131
  openTag: parent.openTag,
193040
193132
  namespaceBindings: parent.namespaceBindings,
193041
193133
  nsPrefix: parent.nsPrefix,
@@ -193046,11 +193138,11 @@ function splitInsertionAroundChildChange(input, allTokens, parent) {
193046
193138
  inner: headRuns[0] ?? parent.inner,
193047
193139
  innerXml: buildInsInnerXmlInterleaved(flat, headOwnedNested, 0, localStart)
193048
193140
  }) : "";
193049
- const tailInsXml = tailText.length > 0 || tailOwnedNested.length > 0 ? buildInsWrapperXml({
193141
+ const tailInsXml = hasTailFragment ? buildInsWrapperXml({
193050
193142
  openTag: parent.openTag,
193051
193143
  namespaceBindings: parent.namespaceBindings,
193052
193144
  nsPrefix: parent.nsPrefix,
193053
- wId: parent.wId,
193145
+ wId: tailParentWId,
193054
193146
  author: parent.author,
193055
193147
  date: parent.date,
193056
193148
  rsidR: parent.rsidR,
@@ -193065,11 +193157,10 @@ function splitInsertionAroundChildChange(input, allTokens, parent) {
193065
193157
  let childDelXml = "";
193066
193158
  let childInsXml = "";
193067
193159
  const emittedRsids = [];
193068
- if (removedText.length > 0) {
193069
- const delWId = resolveNextWId(input);
193160
+ if (childDelWId !== null) {
193070
193161
  childDelXml = buildDelWrapperXml({
193071
193162
  nsPrefix: parent.nsPrefix,
193072
- wId: String(delWId),
193163
+ wId: childDelWId,
193073
193164
  author: currentAuthor,
193074
193165
  date: input.txTimestamp,
193075
193166
  rsidDel: input.rsid,
@@ -193078,15 +193169,13 @@ function splitInsertionAroundChildChange(input, allTokens, parent) {
193078
193169
  });
193079
193170
  emittedRsids.push(input.rsid);
193080
193171
  }
193081
- if (input.newText.length > 0) {
193082
- const nextWId = resolveNextWId(input);
193083
- const insWId = removedText.length > 0 ? nextWId + 1 : nextWId;
193172
+ if (childInsWId !== null) {
193084
193173
  const preferNextRunAtBoundary = localEnd > localStart;
193085
193174
  const insertMeta = runMetaAtInsertionPoint(parent, localStart, preferNextRunAtBoundary);
193086
193175
  const insertRPr = rPrAtInsertionPoint(parent, localStart, preferNextRunAtBoundary);
193087
193176
  childInsXml = buildInsWrapperXml({
193088
193177
  nsPrefix: parent.nsPrefix,
193089
- wId: String(insWId),
193178
+ wId: childInsWId,
193090
193179
  author: currentAuthor,
193091
193180
  date: input.txTimestamp,
193092
193181
  rsidR: input.insRsid,
@@ -193111,7 +193200,7 @@ function splitInsertionAroundChildChange(input, allTokens, parent) {
193111
193200
  openTag: parent.openTag,
193112
193201
  namespaceBindings: parent.namespaceBindings,
193113
193202
  nsPrefix: parent.nsPrefix,
193114
- wId: parent.wId,
193203
+ wId: tailParentWId,
193115
193204
  author: parent.author,
193116
193205
  date: parent.date,
193117
193206
  rsidR: parent.rsidR,
@@ -193132,7 +193221,7 @@ function splitInsertionAroundChildChange(input, allTokens, parent) {
193132
193221
  ok: true,
193133
193222
  xml,
193134
193223
  emittedRsids,
193135
- ...removedText.length > 0 ? { requiresCollaborationSessionSync: true } : {}
193224
+ ...removedText.length > 0 || tailParentWId !== parent.wId ? { requiresCollaborationSessionSync: true } : {}
193136
193225
  };
193137
193226
  }
193138
193227
  function insertAtForeignDeletion(input, allTokens, parent, sameUser) {
@@ -199148,7 +199237,7 @@ function hasProvableSelectedCommentRange(paragraphXml, rangeStart, rangeEnd) {
199148
199237
  markerKindsById.set(marker.id, markerKinds);
199149
199238
  }
199150
199239
  for (const marker of markers) {
199151
- const selected = marker.markerKind === "commentRangeStart" ? rangeStart <= marker.visibleStart && marker.visibleStart < rangeEnd : rangeStart < marker.visibleStart && marker.visibleStart <= rangeEnd;
199240
+ const selected = marker.markerKind === "commentRangeStart" ? rangeStart <= marker.visibleStart && marker.visibleStart < rangeEnd : selectionStraddlesMarker2(rangeStart, rangeEnd, marker.visibleStart);
199152
199241
  if (!selected)
199153
199242
  continue;
199154
199243
  if (marker.id === null)
@@ -204299,6 +204388,18 @@ var init_decide_engine = __esm(() => {
204299
204388
  });
204300
204389
 
204301
204390
  // ../../../v2/editor-core/dist/document/transactions/tracked-changes/structural-inline-decision.js
204391
+ function hasSessionSyncRepeatedTrackedTextDecision(fragments) {
204392
+ const seen = new Set;
204393
+ for (const fragment2 of fragments) {
204394
+ if (fragment2.kind !== "ins" && fragment2.kind !== "del")
204395
+ continue;
204396
+ const key2 = `${fragment2.storyId}:${fragment2.kind}:${fragment2.rsid}`;
204397
+ if (seen.has(key2))
204398
+ return true;
204399
+ seen.add(key2);
204400
+ }
204401
+ return false;
204402
+ }
204302
204403
  function hasSessionSyncStructuralInlineDeletion(xml, fragments, namespaceBindings = new Map) {
204303
204404
  const selectedRanges = fragments.filter((fragment2) => fragment2.kind === "del").map((fragment2) => ({ start: fragment2.byteStart, end: fragment2.byteEnd })).sort((left, right) => left.start - right.start || right.end - left.end);
204304
204405
  if (selectedRanges.length === 0)
@@ -204517,7 +204618,7 @@ function tryRunLocalTrackedChangeDecideCommit(input) {
204517
204618
  };
204518
204619
  })
204519
204620
  };
204520
- const sessionSyncedTextDecision = hasSessionSyncStructuralInlineDeletion(beforeXml, decisions.map(({ localFragment }) => localFragment), new Map(Object.entries(state.mainStorySourceOverlay?.rootNamespaceBindings ?? {})));
204621
+ const sessionSyncedTextDecision = hasSessionSyncStructuralInlineDeletion(beforeXml, decisions.map(({ localFragment }) => localFragment), new Map(Object.entries(state.mainStorySourceOverlay?.rootNamespaceBindings ?? {}))) || hasSessionSyncRepeatedTrackedTextDecision(decisions.map(({ fragment: fragment2 }) => fragment2));
204521
204622
  const prepared = {
204522
204623
  txId,
204523
204624
  source: op,
@@ -208237,7 +208338,7 @@ function runTrackedChangeDecideCommitWithLookupContext(lookupContext, input) {
208237
208338
  fragmentsByPart,
208238
208339
  structuralTargets
208239
208340
  });
208240
- const sessionSyncedTextDecision = trackedTextDecide && (hasNestedTextDecision(catalog, fragmentsByPart) || hasStructuralInlineDeletionDecision(state, fragmentsByPart) || hasMarkerSeparatedTextDecision(state, fragmentsByPart));
208341
+ const sessionSyncedTextDecision = trackedTextDecide && (hasNestedTextDecision(catalog, fragmentsByPart) || hasStructuralInlineDeletionDecision(state, fragmentsByPart) || hasMarkerSeparatedTextDecision(state, fragmentsByPart) || hasSessionSyncRepeatedTrackedTextDecision(Array.from(fragmentsByPart.values()).flat()));
208241
208342
  const prepared = {
208242
208343
  txId,
208243
208344
  source: op,
@@ -232846,7 +232947,12 @@ function planParagraphSplice(input) {
232846
232947
  };
232847
232948
  const mergeable = (block) => block.kind === "paragraph" && !block.styleRef && !block.numbering && !block.listIntent && !block.paragraphProps && !block.pPrXml && !block.blockSdts?.length && !block.complete;
232848
232949
  const paragraphs = [];
232849
- if (blocks.length === 1 && mergeable(blocks[0])) {
232950
+ const blockControlsBeforeAnchor = start === 0 && end === 0 && split.headXml.length === 0 && !input.trackedStamp && blocks.length > 0 && blocks.every((block) => (block.kind === "paragraph" || block.kind === "table") && !!block.blockSdts?.length);
232951
+ if (blockControlsBeforeAnchor) {
232952
+ const rendered = blocks.map((block, index) => standalone(block, index));
232953
+ paragraphs.push(renderBlockSdtSequence(blocks, rendered, input.blockSdtIds ?? new Map));
232954
+ paragraphs.push(input.anchorXml);
232955
+ } else if (blocks.length === 1 && mergeable(blocks[0])) {
232850
232956
  if (anchorParaId)
232851
232957
  destinationParaIdsByBlock[0].push(anchorParaId);
232852
232958
  paragraphs.push(envelope.open + envelope.pPr + split.headXml + runsOf(blocks[0]) + split.tailXml + envelope.close);
@@ -232892,7 +232998,8 @@ function planParagraphSplice(input) {
232892
232998
  createdParaIds,
232893
232999
  destinationParaIdsByBlock,
232894
233000
  insertedVisibleChars,
232895
- removedVisibleChars: end - start
233001
+ removedVisibleChars: end - start,
233002
+ anchorParagraphUnchanged: blockControlsBeforeAnchor
232896
233003
  };
232897
233004
  }
232898
233005
  function paragraphPropertiesAllowEmptyAnchorRelocation(pPrXml) {
@@ -235240,9 +235347,9 @@ function preflightFragmentApply(input) {
235240
235347
  const target = resolveFragmentApplyTarget(state, op);
235241
235348
  if (!target.ok)
235242
235349
  return target;
235243
- if (isTextTarget2(op.target) && op.formattingMode === "match-destination" && op.fragment.blocks.some((block) => (block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length))
235350
+ if (isTextTarget2(op.target) && op.formattingMode === "match-destination" && op.fragment.blocks.some((block) => (block.kind === "paragraph" || block.kind === "heading" || block.kind === "table") && block.blockSdts?.length))
235244
235351
  return { ok: false, reason: "paste-structure-unsupported" };
235245
- if ((op.changeMode ?? "direct") === "tracked" && op.fragment.blocks.some((block) => (block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length))
235352
+ if ((op.changeMode ?? "direct") === "tracked" && op.fragment.blocks.some((block) => (block.kind === "paragraph" || block.kind === "heading" || block.kind === "table") && block.blockSdts?.length))
235246
235353
  return { ok: false, reason: "paste-tracked-structural-unsupported" };
235247
235354
  if ((op.changeMode ?? "direct") === "tracked" && target.target.kind === "block" && target.target.blockKind === "table" && !trackedWholeTableRowsAreDirectChildren(state, target.target)) {
235248
235355
  return { ok: false, reason: "paste-tracked-structural-unsupported" };
@@ -235508,7 +235615,7 @@ function validateFragmentRangeIntegrity(input) {
235508
235615
  }
235509
235616
  function fragmentRequiresCommit5Materialization(blocks) {
235510
235617
  for (const block of blocks) {
235511
- if ((block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length)
235618
+ if ((block.kind === "paragraph" || block.kind === "heading" || block.kind === "table") && block.blockSdts?.length)
235512
235619
  return true;
235513
235620
  if (block.kind === "heading" || block.kind === "horizontalRule")
235514
235621
  return true;
@@ -237504,8 +237611,8 @@ function runPasteSpliceCommit(input, target, resolvedBlocks, listExtras, imageEx
237504
237611
  {
237505
237612
  storyId: target.storyId,
237506
237613
  atChar: anchor.charPrefix + target.charOffset,
237507
- blockId: anchor.entry.blockId,
237508
- atCharInBlock: target.charOffset,
237614
+ blockId: plan.anchorParagraphUnchanged ? plan.createdParaIds[0] : anchor.entry.blockId,
237615
+ atCharInBlock: plan.anchorParagraphUnchanged ? 0 : target.charOffset,
237509
237616
  delta
237510
237617
  }
237511
237618
  ];
@@ -237709,7 +237816,8 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
237709
237816
  }
237710
237817
  }
237711
237818
  }
237712
- if (inlineParagraphs.length === 0) {
237819
+ const blockControls = blocks.flatMap((block) => block.kind === "paragraph" || block.kind === "table" ? block.blockSdts ?? [] : []);
237820
+ if (inlineParagraphs.length === 0 && blockControls.length === 0) {
237713
237821
  return { ok: true, value: { inlineSpecs: new Map, blockSdtIds: new Map, partUris: [], perPart: {}, preconditions: [], patchMaps: {} } };
237714
237822
  }
237715
237823
  const assets = new Map((fragment2.assets ?? []).map((asset) => [asset.id, asset]));
@@ -237805,7 +237913,7 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
237805
237913
  }
237806
237914
  let docPrId = allocateDocPrId(state, storyId);
237807
237915
  const inlineSpecs = new Map;
237808
- const hasControls = inlineParagraphs.some((paragraph) => paragraph.blockSdts?.length || paragraph.inlines?.some((inline) => inline.kind === "sdt"));
237916
+ const hasControls = blockControls.length > 0 || inlineParagraphs.some((paragraph) => paragraph.inlines?.some((inline) => inline.kind === "sdt"));
237809
237917
  const usedControlIds = new Set;
237810
237918
  if (hasControls) {
237811
237919
  for (const [uri, bytes] of state.packageBytes) {
@@ -237836,11 +237944,9 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
237836
237944
  return String(id);
237837
237945
  };
237838
237946
  const blockSdtIds = new Map;
237839
- for (const paragraph of inlineParagraphs) {
237840
- for (const wrapper of paragraph.blockSdts ?? []) {
237841
- if (!blockSdtIds.has(wrapper.sourceId))
237842
- blockSdtIds.set(wrapper.sourceId, mintControlId());
237843
- }
237947
+ for (const wrapper of blockControls) {
237948
+ if (!blockSdtIds.has(wrapper.sourceId))
237949
+ blockSdtIds.set(wrapper.sourceId, mintControlId());
237844
237950
  }
237845
237951
  const leafSpec = (inline) => {
237846
237952
  if (inline.kind === "text")
@@ -237909,8 +238015,8 @@ function validateBlocks(blocks) {
237909
238015
  const closedControls = new Set;
237910
238016
  let activeControls = [];
237911
238017
  for (const block of blocks) {
237912
- const controls = block.kind === "paragraph" || block.kind === "heading" ? block.blockSdts ?? [] : [];
237913
- if (controls.length && (block.kind !== "paragraph" && block.kind !== "heading" || !block.complete || controls.length > 16)) {
238018
+ const controls = block.kind === "paragraph" || block.kind === "heading" || block.kind === "table" ? block.blockSdts ?? [] : [];
238019
+ if (controls.length && ((block.kind === "paragraph" || block.kind === "heading") && !block.complete || controls.length > 16)) {
237914
238020
  return { ok: false, reason: "paste-structure-unsupported" };
237915
238021
  }
237916
238022
  let common = 0;
@@ -253971,58 +254077,6 @@ var init_creation_date = __esm(() => {
253971
254077
  DECODER2 = new TextDecoder;
253972
254078
  });
253973
254079
 
253974
- // ../../../v2/editor-core/dist/document/internal/inline-text-extraction.js
253975
- function extractVisibleTextFromXml2(xml, telemetry) {
253976
- return extractInlineText(xml, "visible", telemetry);
253977
- }
253978
- function extractTrackedTextFromXml(xml, telemetry) {
253979
- return extractInlineText(xml, "tracked", telemetry);
253980
- }
253981
- function projectParagraphInlineText(paragraphXml, space, telemetry) {
253982
- return projectReadOnlyParagraphText(paragraphXml, space, telemetry);
253983
- }
253984
- function extractInlineText(xml, space, telemetry) {
253985
- const chunks = [];
253986
- for (const { tagStart, node: node2 } of iterateTopLevelParagraphElements(xml)) {
253987
- chunks.push(projectParagraphInlineText(xml.slice(tagStart, node2.end), space, telemetry));
253988
- }
253989
- return chunks.length === 0 ? tolerantTokenWalk(xml, space) : chunks.join("");
253990
- }
253991
- function tolerantTokenWalk(xml, space) {
253992
- const contentXml = stripElements(xml, "sdtPr");
253993
- const body = stripOpaqueObjectBlocks(space === "visible" ? stripParagraphProperties(stripHiddenRevisionBlocks(contentXml)) : stripParagraphProperties(contentXml));
253994
- const pattern = space === "visible" ? /<[\w.-]+:t\b[^>]*>([\s\S]*?)<\/[\w.-]+:t>|<[\w.-]+:(tab|br|cr)\b[^>]*\/>/g : /<[\w.-]+:(?:t|delText)\b[^>]*>([\s\S]*?)<\/[\w.-]+:(?:t|delText)>|<[\w.-]+:(tab|br|cr)\b[^>]*\/>/g;
253995
- let out = "";
253996
- for (const token of body.matchAll(pattern)) {
253997
- if (token[1] != null) {
253998
- out += decodeXmlText(token[1]);
253999
- continue;
254000
- }
254001
- out += controlChar2(token[2]);
254002
- }
254003
- return out;
254004
- }
254005
- function controlChar2(control) {
254006
- if (control === "tab")
254007
- return "\t";
254008
- return `
254009
- `;
254010
- }
254011
- function stripParagraphProperties(xml) {
254012
- return stripElements(xml, "pPr");
254013
- }
254014
- function stripHiddenRevisionBlocks(xml) {
254015
- return xml.replace(/<[\w.-]+:(?:del|moveFrom)\b(?![^>]*\/>)[^>]*>[\s\S]*?<\/[\w.-]+:(?:del|moveFrom)>/g, "");
254016
- }
254017
- function stripOpaqueObjectBlocks(xml) {
254018
- return xml.replace(/<[\w.-]+:(?:drawing|object|pict)\b(?![^>]*\/>)[^>]*>[\s\S]*?<\/[\w.-]+:(?:drawing|object|pict)>|<[\w.-]+:(?:drawing|object|pict)\b[^>]*\/>/g, "");
254019
- }
254020
- var init_inline_text_extraction = __esm(() => {
254021
- init_paragraph_scan_count();
254022
- init_paragraph_text_projection();
254023
- init_xml_text();
254024
- });
254025
-
254026
254080
  // ../../../v2/editor-core/dist/document/transactions/tracked-bookmark-rename.js
254027
254081
  function prepareTrackedBookmarkRename(input) {
254028
254082
  const parsed = collectXmlElementRanges(input.xml);
@@ -283091,7 +283145,7 @@ function scanParagraphNamespaceBindingsByByteStart(xml) {
283091
283145
  return bindings;
283092
283146
  }
283093
283147
  function readVisibleParagraphText(xml) {
283094
- return extractVisibleTextFromXml2(xml);
283148
+ return extractVisibleTextFromXml(xml);
283095
283149
  }
283096
283150
  function readTrackedParagraphText(xml) {
283097
283151
  return extractTrackedTextFromXml(xml);
@@ -285312,7 +285366,8 @@ function wrapHyperlinkInParagraphXml(input) {
285312
285366
  }
285313
285367
  function wrapRangeWithMarkupInParagraphXml(input) {
285314
285368
  const collected = collectPlainTextRuns2(input.paragraphXml, input.rangeStart, input.rangeEnd, {
285315
- allowFieldResultContent: true
285369
+ allowFieldResultContent: input.allowFieldResultContent ?? true,
285370
+ rejectUnsupportedMarkers: input.rejectUnsupportedMarkers
285316
285371
  });
285317
285372
  if (!collected.ok)
285318
285373
  return collected;
@@ -285736,6 +285791,9 @@ function collectPlainTextRuns2(paragraphXml, rangeStart, rangeEnd, options = {})
285736
285791
  const openXml = childMatch[0].slice(leadingWhitespace.length);
285737
285792
  const selfClosing = /\/>$/.test(openXml);
285738
285793
  if (selfClosing) {
285794
+ if (options.rejectUnsupportedMarkers && localName2 !== "pPr" && selectionStraddlesMarker3(rangeStart, rangeEnd, textCursor)) {
285795
+ return { ok: false, reason: "unsupported-context" };
285796
+ }
285739
285797
  if (isReferenceMarker(localName2) && selectionStraddlesMarker3(rangeStart, rangeEnd, textCursor)) {
285740
285798
  return { ok: false, reason: "unsupported-context" };
285741
285799
  }
@@ -285750,6 +285808,7 @@ function collectPlainTextRuns2(paragraphXml, rangeStart, rangeEnd, options = {})
285750
285808
  const childTextEnd = textCursor + visibleTextLength3(childXml);
285751
285809
  textCursor = childTextEnd;
285752
285810
  cursor = end;
285811
+ const intersects = rangesOverlap7(childTextStart, childTextEnd, rangeStart, rangeEnd) || options.rejectUnsupportedMarkers === true && childTextStart === childTextEnd && selectionStraddlesMarker3(rangeStart, rangeEnd, childTextStart);
285753
285812
  if (localName2 === "pPr")
285754
285813
  continue;
285755
285814
  if (localName2 === "r") {
@@ -285760,7 +285819,7 @@ function collectPlainTextRuns2(paragraphXml, rangeStart, rangeEnd, options = {})
285760
285819
  complexFieldResultDepth = Math.max(0, complexFieldResultDepth + markers.separates - markers.ends);
285761
285820
  const parsed = parsePlainRun2(childXml, childTextStart, cursor - childXml.length, cursor);
285762
285821
  if (!parsed.ok) {
285763
- if (rangesOverlap7(childTextStart, childTextEnd, rangeStart, rangeEnd)) {
285822
+ if (intersects) {
285764
285823
  return { ok: false, reason: parsed.reason };
285765
285824
  }
285766
285825
  continue;
@@ -285778,29 +285837,31 @@ function collectPlainTextRuns2(paragraphXml, rangeStart, rangeEnd, options = {})
285778
285837
  continue;
285779
285838
  }
285780
285839
  if (localName2 === "ins" || localName2 === "del" || localName2 === "moveFrom" || localName2 === "moveTo") {
285781
- if (rangesOverlap7(childTextStart, childTextEnd, rangeStart, rangeEnd)) {
285840
+ if (intersects) {
285782
285841
  return { ok: false, reason: "text-range-in-unsupported-tracked-wrapper" };
285783
285842
  }
285784
285843
  continue;
285785
285844
  }
285786
285845
  if (localName2 === "sdt") {
285787
- if (rangesOverlap7(childTextStart, childTextEnd, rangeStart, rangeEnd)) {
285846
+ if (intersects) {
285788
285847
  return { ok: false, reason: "text-range-in-sdt" };
285789
285848
  }
285790
285849
  continue;
285791
285850
  }
285792
285851
  if (localName2 === "hyperlink" || localName2 === "fldSimple") {
285793
- if (rangesOverlap7(childTextStart, childTextEnd, rangeStart, rangeEnd)) {
285852
+ if (intersects) {
285794
285853
  return { ok: false, reason: "text-range-in-field" };
285795
285854
  }
285796
285855
  continue;
285797
285856
  }
285798
285857
  if (localName2 === "oMath" || localName2 === "oMathPara") {
285799
- if (rangesOverlap7(childTextStart, childTextEnd, rangeStart, rangeEnd)) {
285858
+ if (intersects) {
285800
285859
  return { ok: false, reason: "text-range-in-equation" };
285801
285860
  }
285802
285861
  continue;
285803
285862
  }
285863
+ if (options.rejectUnsupportedMarkers && intersects)
285864
+ return { ok: false, reason: "unsupported-context" };
285804
285865
  }
285805
285866
  return { ok: true, runs };
285806
285867
  }
@@ -298242,7 +298303,7 @@ function findCreatedField(context, storyId, blockId, beforeFieldIds, expected) {
298242
298303
  function fieldTextStartOffset(paragraph2, entry) {
298243
298304
  const relativeByteStart = Math.max(0, entry.descriptor.byteStart - paragraph2.byteStart);
298244
298305
  const rawXmlBeforeField = paragraph2.rawXml.slice(0, charIndexForUtf8ByteOffset(paragraph2.rawXml, relativeByteStart));
298245
- return extractVisibleTextFromXml2(rawXmlBeforeField).length;
298306
+ return extractVisibleTextFromXml(rawXmlBeforeField).length;
298246
298307
  }
298247
298308
  function charIndexForUtf8ByteOffset(text, byteOffset) {
298248
298309
  let bytes = 0;
@@ -299064,7 +299125,7 @@ class V2AnchoredMetadataAdapter {
299064
299125
  if ("error" in resolvedSegments)
299065
299126
  throw operationError(resolvedSegments.error, resolvedSegments.message);
299066
299127
  const knownIds = new Set(existingRecords.map((record3) => record3.id));
299067
- if (hasOverlappingMetadataAnchor(documentXml, resolvedSegments.segments, knownIds)) {
299128
+ if (hasOverlappingMetadataAnchor(documentXml, resolvedSegments.segments, existingRecords)) {
299068
299129
  return failure2("INVALID_TARGET", "metadata.attach target overlaps an existing metadata anchor.");
299069
299130
  }
299070
299131
  const existingPart = ensureCustomXmlPartForNamespace(this.context, input.namespace);
@@ -299079,9 +299140,15 @@ class V2AnchoredMetadataAdapter {
299079
299140
  const bySegmentPosition = resolvedSegments.segments.map((segment, index) => ({ segment, sdtId: sdtIds[index] })).sort((a, b) => b.segment.para.start - a.segment.para.start);
299080
299141
  let nextDocumentXml = documentXml;
299081
299142
  for (const { segment, sdtId } of bySegmentPosition) {
299082
- const wrapped = wrapTextRangeWithMetadataSdt(segment.para.xml, segment.startOffset, segment.endOffset, id, sdtId);
299143
+ const wrapped = wrapTextRangeWithMetadataSdt(segment.para.xml, segment.startOffset, segment.endOffset, id, sdtId, knownIds);
299083
299144
  if (!wrapped.ok)
299084
299145
  throw metadataWrapRejectError(wrapped.reason);
299146
+ if (wrapped.contained) {
299147
+ const ids = countBodyControlIds(documentXml);
299148
+ if (!ids || wrapped.parentId !== null && ids.get(wrapped.parentId) !== 1 || buildStructuralBoundaryMap(TEXT_ENCODER.encode(documentXml)).byBlockId(segment.blockId)?.blockSdtPath.length) {
299149
+ throw metadataWrapRejectError("text-range-in-sdt");
299150
+ }
299151
+ }
299085
299152
  nextDocumentXml = replaceRange2(nextDocumentXml, segment.para.start, segment.para.end, wrapped.xml);
299086
299153
  }
299087
299154
  if (!dryRunRequested(input, options)) {
@@ -299372,8 +299439,8 @@ function materializeMetadataAnchor(documentXml, sdt, id) {
299372
299439
  const para = findParagraphContaining2(documentXml, sdt.start);
299373
299440
  if (!para)
299374
299441
  return null;
299375
- const startOffset = extractVisibleTextFromXml2(para.xml.slice(0, sdt.start - para.start)).length;
299376
- const length = extractVisibleTextFromXml2(unwrapSdt(sdt.xml) ?? sdt.xml).length;
299442
+ const startOffset = extractVisibleTextFromXml(para.xml.slice(0, sdt.start - para.start)).length;
299443
+ const length = extractVisibleTextFromXml(unwrapSdt(sdt.xml) ?? sdt.xml).length;
299377
299444
  const endOffset = startOffset + length;
299378
299445
  return {
299379
299446
  id,
@@ -299613,9 +299680,22 @@ function validateContiguousStructuralRun(documentXml, blockIds) {
299613
299680
  }
299614
299681
  return null;
299615
299682
  }
299616
- function hasOverlappingMetadataAnchor(documentXml, segments, knownIds) {
299683
+ function hasOverlappingMetadataAnchor(documentXml, segments, records) {
299684
+ const knownIds = new Set(records.map((record3) => record3.id));
299617
299685
  const anchors = listMetadataAnchors(documentXml, knownIds);
299618
- return segments.some((segment) => anchors.some((anchor) => anchor.blockId === segment.blockId && rangesStrictlyOverlap(segment.startOffset, segment.endOffset, anchor.startOffset, anchor.endOffset)));
299686
+ return segments.some((segment) => {
299687
+ const overlapping = anchors.filter((anchor) => anchor.blockId === segment.blockId && rangesStrictlyOverlap(segment.startOffset, segment.endOffset, anchor.startOffset, anchor.endOffset));
299688
+ if (overlapping.length === 0)
299689
+ return false;
299690
+ const parent = overlapping[0];
299691
+ if (segments.length !== 1 || overlapping.length !== 1 || segment.startOffset <= parent.startOffset || segment.endOffset >= parent.endOffset)
299692
+ return true;
299693
+ const parentRecords = records.filter((record3) => record3.id === parent.id);
299694
+ if (parentRecords.length !== 1)
299695
+ return true;
299696
+ const grouped = groupMetadataAnchor(documentXml, parent.id, knownIds, parentRecords[0].physicalIds);
299697
+ return grouped?.segments.length !== 1 || grouped.segments[0].start !== parent.start;
299698
+ });
299619
299699
  }
299620
299700
  function rangesStrictlyOverlap(leftStart, leftEnd, rightStart, rightEnd) {
299621
299701
  return leftStart < rightEnd && rightStart < leftEnd;
@@ -299623,14 +299703,60 @@ function rangesStrictlyOverlap(leftStart, leftEnd, rightStart, rightEnd) {
299623
299703
  function bodyStoryLocator2() {
299624
299704
  return { kind: "story", storyType: "body" };
299625
299705
  }
299626
- function wrapTextRangeWithMetadataSdt(paragraphXml, start, end, id, sdtId) {
299627
- return wrapRangeWithMarkupInParagraphXml({
299628
- paragraphXml,
299629
- rangeStart: start,
299630
- rangeEnd: end,
299706
+ function wrapTextRangeWithMetadataSdt(paragraphXml, start, end, id, sdtId, knownIds) {
299707
+ const candidates = listSdtRanges(paragraphXml).filter((sdt) => {
299708
+ const from2 = extractVisibleTextFromXml(paragraphXml.slice(0, sdt.start)).length;
299709
+ const to = from2 + extractVisibleTextFromXml(unwrapSdt(sdt.xml) ?? sdt.xml).length;
299710
+ return rangesStrictlyOverlap(start, end, from2, to) || from2 === to && start < from2 && from2 < end;
299711
+ });
299712
+ const wrap = (xml, from2, to, contained = false) => wrapRangeWithMarkupInParagraphXml({
299713
+ paragraphXml: xml,
299714
+ rangeStart: from2,
299715
+ rangeEnd: to,
299631
299716
  open: metadataSdtOpenXml(id, sdtId),
299632
- close: "</w:sdtContent></w:sdt>"
299717
+ close: "</w:sdtContent></w:sdt>",
299718
+ ...contained ? { allowFieldResultContent: false, rejectUnsupportedMarkers: true } : {}
299633
299719
  });
299720
+ if (candidates.length === 0)
299721
+ return wrap(paragraphXml, start, end);
299722
+ if (candidates.length !== 1)
299723
+ return { ok: false, reason: "text-range-in-sdt" };
299724
+ const parent = candidates[0];
299725
+ const paragraph2 = parseContainerXml(paragraphXml, "p");
299726
+ if (parent.unmatched || !paragraph2 || !parseTopLevelChildren(paragraph2.inner).some((child) => child.name === "w:sdt" && child.xml === parent.xml)) {
299727
+ return { ok: false, reason: "text-range-in-sdt" };
299728
+ }
299729
+ const from = extractVisibleTextFromXml(paragraphXml.slice(0, parent.start)).length;
299730
+ const content = unwrapSdt(parent.xml);
299731
+ if (content === null || start <= from || end >= from + extractVisibleTextFromXml(content).length) {
299732
+ return { ok: false, reason: "text-range-in-sdt" };
299733
+ }
299734
+ const pr = ownSdtPr(parent.xml);
299735
+ const parentContainer = parseContainerXml(parent.xml, "sdt");
299736
+ const children2 = parentContainer ? parseTopLevelChildren(parentContainer.inner) : [];
299737
+ if (children2.filter((child) => child.localName === "sdtContent").length !== 1 || children2.filter((child) => child.localName === "sdtPr").length > 1 || [...pr.matchAll(/<w:id\b/g)].length > 1 || [...pr.matchAll(/<w:(?:text|richText)\b/g)].length > 1) {
299738
+ return { ok: false, reason: "text-range-in-sdt" };
299739
+ }
299740
+ const tag = attrValue(/<w:tag\b[^>]*\/>/.exec(pr)?.[0] ?? "", "val");
299741
+ const metadataParent = tag !== null && isMetadataAnchorPr(pr, tag, knownIds);
299742
+ const alias = attrValue(/<w:alias\b[^>]*\/>/.exec(pr)?.[0] ?? "", "val");
299743
+ if (!isSdtContentEditable(parent.xml) || /<w:lock\b/.test(pr) && attrValue(/<w:lock\b[^>]*>/.exec(pr)?.[0] ?? "", "val") !== "unlocked" || !metadataParent && (/<w:text\b/.test(pr) || alias === METADATA_ANCHOR_ALIAS)) {
299744
+ return { ok: false, reason: "text-range-in-sdt" };
299745
+ }
299746
+ const wrapped = wrap(`<w:p>${content}</w:p>`, start - from, end - from, true);
299747
+ if (!wrapped.ok)
299748
+ return wrapped;
299749
+ const nextContent = parseContainerXml(wrapped.xml, "p").inner;
299750
+ const open = /<w:sdtContent\b[^>]*>/.exec(parent.xml);
299751
+ const contentStart = open.index + open[0].length;
299752
+ let nextParent = replaceRange2(parent.xml, contentStart, contentStart + content.length, nextContent);
299753
+ if (metadataParent && /<w:text\b/.test(pr)) {
299754
+ let nextPr = pr.replace(/<w:text\b[^>]*(?:\/>|>[\s\S]*?<\/w:text>)/, "<w:richText/>");
299755
+ if (alias === null)
299756
+ nextPr = nextPr.replace("</w:sdtPr>", `<w:alias w:val="${METADATA_ANCHOR_ALIAS}"/></w:sdtPr>`);
299757
+ nextParent = nextParent.replace(pr, nextPr);
299758
+ }
299759
+ return { ok: true, xml: replaceRange2(paragraphXml, parent.start, parent.end, nextParent), contained: true, parentId: metadataAnchorPhysicalId(parent) };
299634
299760
  }
299635
299761
  function metadataSdtOpenXml(id, sdtId) {
299636
299762
  return [
@@ -299765,6 +299891,7 @@ var init_adapter9 = __esm(() => {
299765
299891
  init_sd_document_session_internal();
299766
299892
  init_visible_text();
299767
299893
  init_inline();
299894
+ init_common();
299768
299895
  init_adapter2();
299769
299896
  init_shared();
299770
299897
  init_xml();
@@ -308947,7 +309074,7 @@ function toParagraphNumberingFromListSummary(listItem) {
308947
309074
  return { numId, level: listItem.ilvl };
308948
309075
  }
308949
309076
  function visibleText(xml, telemetry) {
308950
- return extractVisibleTextFromXml2(xml, telemetry);
309077
+ return extractVisibleTextFromXml(xml, telemetry);
308951
309078
  }
308952
309079
  function visibleParagraphText2(paragraphXml, telemetry) {
308953
309080
  return projectParagraphInlineText(paragraphXml, "visible", telemetry);
@@ -334034,7 +334161,7 @@ class V2ContentControlsAdapter {
334034
334161
  const anchor = findParagraphById3(part.xml, input.at.start.blockId);
334035
334162
  if (anchor) {
334036
334163
  namespaceBindings = new Map(contentControlNamespaceBindings(part.xml, anchor.start, true));
334037
- if (input.kind === "block" && extractVisibleTextFromXml2(anchor.xml).trim().length === 0) {
334164
+ if (input.kind === "block" && extractVisibleTextFromXml(anchor.xml).trim().length === 0) {
334038
334165
  beforeXml = anchor.xml;
334039
334166
  }
334040
334167
  }
@@ -334471,8 +334598,8 @@ class V2ContentControlsAdapter {
334471
334598
  }
334472
334599
  let requestedOffset = offset;
334473
334600
  if (source.info.kind === "inline" && source.start >= anchor.start && source.end <= anchor.end) {
334474
- const beforeSource = extractVisibleTextFromXml2(loaded.documentXml.slice(anchor.start, source.start)).length;
334475
- const sourceVisible = extractVisibleTextFromXml2(source.xml).length;
334601
+ const beforeSource = extractVisibleTextFromXml(loaded.documentXml.slice(anchor.start, source.start)).length;
334602
+ const sourceVisible = extractVisibleTextFromXml(source.xml).length;
334476
334603
  if (requestedOffset > beforeSource)
334477
334604
  requestedOffset = Math.max(beforeSource, requestedOffset - sourceVisible);
334478
334605
  }
@@ -334541,7 +334668,7 @@ class V2ContentControlsAdapter {
334541
334668
  const updatedPara = spliced.kind === "ok" ? spliced.xml : insertXmlIntoParagraphContent(para.xml, destinationXml);
334542
334669
  nextXml = replaceRange3(withoutSource, para.start, para.end, updatedPara);
334543
334670
  } else {
334544
- const insertBefore = requestedOffset === 0 && extractVisibleTextFromXml2(para.xml).trim().length > 0;
334671
+ const insertBefore = requestedOffset === 0 && extractVisibleTextFromXml(para.xml).trim().length > 0;
334545
334672
  nextXml = insertBefore ? `${withoutSource.slice(0, para.start)}${destinationXml}${withoutSource.slice(para.start)}` : `${withoutSource.slice(0, para.end)}${destinationXml}${withoutSource.slice(para.end)}`;
334546
334673
  }
334547
334674
  return this.commitDocument(nextXml, "content-control-move", input, options, source.target, commitOptions);
@@ -335332,7 +335459,7 @@ function parseParagraphWindows(documentXml) {
335332
335459
  start: match.index,
335333
335460
  end: paragraphRe.lastIndex,
335334
335461
  xml,
335335
- textLength: extractVisibleTextFromXml2(xml).length
335462
+ textLength: extractVisibleTextFromXml(xml).length
335336
335463
  });
335337
335464
  }
335338
335465
  return paragraphs;
@@ -335351,7 +335478,7 @@ async function parseParagraphWindowsCooperatively(documentXml, yieldPoint) {
335351
335478
  start: match.index,
335352
335479
  end: paragraphRe.lastIndex,
335353
335480
  xml,
335354
- textLength: extractVisibleTextFromXml2(xml).length
335481
+ textLength: extractVisibleTextFromXml(xml).length
335355
335482
  });
335356
335483
  if ((sinceYield += 1) >= COOPERATIVE_PARSE_SLICE_PARAGRAPHS) {
335357
335484
  sinceYield = 0;
@@ -335793,7 +335920,7 @@ function selectionOffsetInParagraph(paragraph4, absoluteIndex) {
335793
335920
  if (absoluteIndex <= paragraph4.start)
335794
335921
  return 0;
335795
335922
  const relative = Math.min(absoluteIndex, paragraph4.end) - paragraph4.start;
335796
- const textOffset = extractVisibleTextFromXml2(paragraph4.xml.slice(0, relative)).length;
335923
+ const textOffset = extractVisibleTextFromXml(paragraph4.xml.slice(0, relative)).length;
335797
335924
  if (!/<[\w.-]+:(?:drawing|pict|object)\b/.test(paragraph4.xml.slice(0, relative))) {
335798
335925
  return Math.max(0, Math.min(paragraph4.textLength, textOffset));
335799
335926
  }
@@ -337019,7 +337146,7 @@ function insertBlockContentControlAtSelection(documentXml, paragraphs, target, s
337019
337146
  if (!anchor)
337020
337147
  throw operationError("TARGET_NOT_FOUND", "Target paragraph was not found.");
337021
337148
  const collapsed = target.start.blockId === target.end.blockId && target.start.offset === target.end.offset;
337022
- if (collapsed && extractVisibleTextFromXml2(anchor.xml).trim().length === 0) {
337149
+ if (collapsed && extractVisibleTextFromXml(anchor.xml).trim().length === 0) {
337023
337150
  return replaceRange3(documentXml, anchor.start, anchor.end, sdtXml);
337024
337151
  }
337025
337152
  return `${documentXml.slice(0, anchor.end)}${sdtXml}${documentXml.slice(anchor.end)}`;
@@ -362873,7 +363000,7 @@ function extractStructuralCellTexts(xml, side) {
362873
363000
  return findAllElements(xml, "tc").map((cell) => extractStructuralText(cell.xml, side)).filter((value2) => value2.trim().length > 0);
362874
363001
  }
362875
363002
  function extractStructuralText(xml, side) {
362876
- const readText = side === "deleted" ? extractTrackedTextFromXml : extractVisibleTextFromXml2;
363003
+ const readText = side === "deleted" ? extractTrackedTextFromXml : extractVisibleTextFromXml;
362877
363004
  const paragraphs = scanParagraphXmlSpans({ bytes: TEXT_ENCODER2.encode(xml) });
362878
363005
  if (paragraphs.length === 0)
362879
363006
  return readText(xml);
@@ -376464,7 +376591,7 @@ var init_adapter28 = __esm(() => {
376464
376591
  init_story_surface();
376465
376592
  init_visible_text();
376466
376593
  TD113 = new TextDecoder;
376467
- extractVisibleTextFromXml4 = extractVisibleTextFromXml2;
376594
+ extractVisibleTextFromXml4 = extractVisibleTextFromXml;
376468
376595
  });
376469
376596
 
376470
376597
  // ../../../v2/document-api-v2-adapter/dist/search/node-discovery.js
@@ -381070,8 +381197,8 @@ function resolveDescriptorVisibleTextRange(paragraph4, descriptor) {
381070
381197
  }
381071
381198
  const innerStartIndex = stringIndexAtUtf8Offset(paragraph4.rawXml, relativeInnerStart);
381072
381199
  const innerEndIndex = stringIndexAtUtf8Offset(paragraph4.rawXml, relativeInnerEnd);
381073
- const start = extractVisibleTextFromXml2(paragraph4.rawXml.slice(0, innerStartIndex)).length;
381074
- const length = extractVisibleTextFromXml2(paragraph4.rawXml.slice(innerStartIndex, innerEndIndex)).length;
381200
+ const start = extractVisibleTextFromXml(paragraph4.rawXml.slice(0, innerStartIndex)).length;
381201
+ const length = extractVisibleTextFromXml(paragraph4.rawXml.slice(innerStartIndex, innerEndIndex)).length;
381075
381202
  return { start, end: start + length };
381076
381203
  }
381077
381204
  function utf8CodePointWidth(codePoint) {
@@ -385626,6 +385753,12 @@ function normalizeTableBlock(block, index2, version2) {
385626
385753
  reason: "paste-structure-unsupported",
385627
385754
  diagnostics: [diagnostic("paste-structure-unsupported", message, "superdoc-v2-fragment", "error", ["blocks", index2])]
385628
385755
  });
385756
+ const blockSdts = normalizeBlockSdts(block.blockSdts, ["blocks", index2, "blockSdts"]);
385757
+ if (isPlanFailure(blockSdts))
385758
+ return blockSdts;
385759
+ if (blockSdts && version2 !== SUPERDOC_V22_CLIPBOARD_FRAGMENT_VERSION) {
385760
+ return fail6("Block content controls around tables require a v2.2 fragment.");
385761
+ }
385629
385762
  if (block.cellSpacingPt !== undefined && !isSafePaddingPoints2(block.cellSpacingPt)) {
385630
385763
  return fail6("Paste table cellSpacingPt must be a non-negative finite point value within the safe twip range.");
385631
385764
  }
@@ -385725,6 +385858,7 @@ function normalizeTableBlock(block, index2, version2) {
385725
385858
  return sourcePath;
385726
385859
  return {
385727
385860
  kind: "table",
385861
+ ...blockSdts ? { blockSdts } : {},
385728
385862
  rows,
385729
385863
  ...block.cellSpacingPt !== undefined ? { cellSpacingPt: block.cellSpacingPt } : {},
385730
385864
  ...sourcePath ? { sourcePath } : {}
@@ -386532,7 +386666,8 @@ function serializeSelectionRange(context, target, includeHtml, options) {
386532
386666
  const tableCellPath = boundaryMap.byBlockId(entry.blockId)?.tableCellPath ?? [];
386533
386667
  const blockSdtPath = boundaryMap.byBlockId(entry.blockId)?.blockSdtPath ?? [];
386534
386668
  const properties = readParagraphProperties(paragraphXml);
386535
- const fullyCovered = from === 0 && to === map3.visibleLength && (options?.wholeParagraphs === true || startEntry.ordinal !== endEntry.ordinal || properties.styleRef !== undefined || properties.numbering !== undefined || hasParagraphProperties(paragraphXml));
386669
+ const selectedInlineControl = options?.wholeParagraphs !== true && startEntry.ordinal === endEntry.ordinal && map3.pieces.some((piece) => piece.kind === "container" && piece.containerKind === "sdt" && piece.visibleStart === from && piece.visibleEnd === to);
386670
+ const fullyCovered = !selectedInlineControl && from === 0 && to === map3.visibleLength && (options?.wholeParagraphs === true || startEntry.ordinal !== endEntry.ordinal || properties.styleRef !== undefined || properties.numbering !== undefined || hasParagraphProperties(paragraphXml));
386536
386671
  const styleModel = copyStyleModel ?? (copyStyleModel = compileCopyStyleModel(context));
386537
386672
  const styleContext = copyStyleContext(styleModel, properties.styleRef);
386538
386673
  const semanticStyleRole = portableSemanticStyleRole(styleModel, properties.styleRef);
@@ -386638,7 +386773,7 @@ function serializeSelectionRange(context, target, includeHtml, options) {
386638
386773
  const listLevel = numbering ? Number.parseInt(numbering.ilvl, 10) : undefined;
386639
386774
  const blockSdts = blockSdtPath.map((ordinal) => {
386640
386775
  const wrapper = blockSdtWrappers.get(ordinal);
386641
- if (!wrapper || !fullyCovered || tableCellPath.length > 0 || !wrapper.supported || index2.entries.some((candidate2) => boundaryMap.byBlockId(candidate2.blockId)?.blockSdtPath.includes(ordinal) && (candidate2.ordinal < startEntry.ordinal || candidate2.ordinal > endEntry.ordinal || candidate2.ordinal === startEntry.ordinal && startPoint.offset !== 0 || candidate2.ordinal === endEntry.ordinal && endPoint.offset !== parseParagraphInlineMap(SERIALIZE_TD.decode(bytes.subarray(endEntry.byteStart, endEntry.byteEnd))).visibleLength)))
386776
+ if (!wrapper || !fullyCovered || !wrapper.supported || index2.entries.some((candidate2) => boundaryMap.byBlockId(candidate2.blockId)?.blockSdtPath.includes(ordinal) && ((boundaryMap.byBlockId(candidate2.blockId)?.tableCellPath.length ?? 0) > 1 || candidate2.ordinal < startEntry.ordinal || candidate2.ordinal > endEntry.ordinal || candidate2.ordinal === startEntry.ordinal && startPoint.offset !== 0 || candidate2.ordinal === endEntry.ordinal && endPoint.offset !== parseParagraphInlineMap(SERIALIZE_TD.decode(bytes.subarray(endEntry.byteStart, endEntry.byteEnd))).visibleLength)))
386642
386777
  return null;
386643
386778
  return wrapper.properties;
386644
386779
  });
@@ -386786,11 +386921,20 @@ function parseSupportedSdtProperties(xml) {
386786
386921
  function scanBlockSdtWrappers(xml) {
386787
386922
  const wrappers = new Map;
386788
386923
  const stack = [];
386789
- const tokens = /<w:p\b[^>]*>[\s\S]*?<\/w:p\s*>|<w:sdt\b[^>]*>|<\/w:sdt\s*>/g;
386924
+ const tokens = /<w:p\b[^>]*>[\s\S]*?<\/w:p\s*>|<w:(?:sdt|tc)\b[^>]*>|<\/w:(?:sdt|tc)\s*>/g;
386925
+ let cellDepth = 0;
386790
386926
  let ordinal = 0;
386791
386927
  for (const token of xml.matchAll(tokens)) {
386792
386928
  if (token[0].startsWith("<w:p"))
386793
386929
  continue;
386930
+ if (token[0].startsWith("<w:tc")) {
386931
+ cellDepth += 1;
386932
+ continue;
386933
+ }
386934
+ if (token[0].startsWith("</w:tc")) {
386935
+ cellDepth -= 1;
386936
+ continue;
386937
+ }
386794
386938
  if (token[0].startsWith("</")) {
386795
386939
  const frame = stack.pop();
386796
386940
  if (!frame)
@@ -386801,10 +386945,10 @@ function scanBlockSdtWrappers(xml) {
386801
386945
  const children2 = contentXml === undefined ? [] : parseTopLevelChildren(contentXml);
386802
386946
  const parsedProperties = propertiesXml === undefined ? null : parseSupportedSdtProperties(propertiesXml);
386803
386947
  const properties = { sourceId: String(frame.ordinal), ...parsedProperties ?? { controlType: "richText" } };
386804
- const supported = parsedProperties !== null && contentXml !== undefined && children2.length > 0 && children2.every((child) => child.prefix === "w" && (child.localName === "p" || child.localName === "sdt")) && topLevelChildrenCoverXml(contentXml, children2);
386948
+ const supported = !frame.inCell && parsedProperties !== null && contentXml !== undefined && children2.length > 0 && children2.every((child) => child.prefix === "w" && (child.localName === "p" || child.localName === "sdt" || child.localName === "tbl")) && topLevelChildrenCoverXml(contentXml, children2);
386805
386949
  wrappers.set(frame.ordinal, { properties, supported });
386806
386950
  } else {
386807
- stack.push({ ordinal: ordinal++, start: token.index });
386951
+ stack.push({ ordinal: ordinal++, start: token.index, inCell: cellDepth > 0 });
386808
386952
  }
386809
386953
  }
386810
386954
  return wrappers;
@@ -387648,6 +387792,7 @@ function groupTableBlocks(blocks) {
387648
387792
  ordinal: coord.table,
387649
387793
  group: {
387650
387794
  kind: "table",
387795
+ ...block.blockSdts ? { blockSdts: block.blockSdts } : {},
387651
387796
  ...coord.cellSpacingPt !== undefined ? { cellSpacingPt: coord.cellSpacingPt } : {},
387652
387797
  rows: []
387653
387798
  }
@@ -387670,7 +387815,8 @@ function groupTableBlocks(blocks) {
387670
387815
  };
387671
387816
  row.cells.push(cell);
387672
387817
  }
387673
- cell.blocks.push(block);
387818
+ const { blockSdts: _tableWrappers, ...cellBlock } = block;
387819
+ cell.blocks.push(cellBlock);
387674
387820
  }
387675
387821
  return out;
387676
387822
  }
@@ -387756,6 +387902,7 @@ function richFragmentBlockFor(grouped) {
387756
387902
  return richParagraphFragmentFor(grouped.block);
387757
387903
  return {
387758
387904
  kind: "table",
387905
+ ...grouped.blockSdts ? { blockSdts: grouped.blockSdts } : {},
387759
387906
  ...grouped.cellSpacingPt !== undefined ? { cellSpacingPt: grouped.cellSpacingPt } : {},
387760
387907
  rows: grouped.rows.map((row) => ({
387761
387908
  cells: row.cells.map((cell) => ({
@@ -429197,7 +429344,7 @@ function replaceLiveTableStructuralProperties(tableXml, tableBlocks, rowProperti
429197
429344
  const replacements = [];
429198
429345
  for (const row of directElementSpans(tableXml, table.openEnd, table.closeStart, "tr")) {
429199
429346
  const cells = directElementSpans(tableXml, row.openEnd, row.closeStart, "tc");
429200
- const rowBlock = cells.flatMap((cell) => directParagraphSpans(tableXml, cell)).map((paragraph4) => blockIdFromParagraphXml(tableXml.slice(paragraph4.start, paragraph4.end))).map((blockId) => blockId == null ? undefined : blockById.get(blockId)).find(Boolean);
429347
+ const rowBlock = cells.flatMap((cell) => cellParagraphSpans(tableXml, cell)).map((paragraph4) => blockIdFromParagraphXml(tableXml.slice(paragraph4.start, paragraph4.end))).map((blockId) => blockId == null ? undefined : blockById.get(blockId)).find(Boolean);
429201
429348
  const rowNodeId = rowBlock?.structuralRefs.rowNodeId;
429202
429349
  if (rowNodeId && cells[0] && rowProperties.has(rowNodeId)) {
429203
429350
  const prefix = tableXml.slice(row.start, cells[0].start);
@@ -429208,12 +429355,12 @@ function replaceLiveTableStructuralProperties(tableXml, tableBlocks, rowProperti
429208
429355
  });
429209
429356
  }
429210
429357
  for (const cell of cells) {
429211
- const paragraphs = directParagraphSpans(tableXml, cell);
429358
+ const paragraphs = cellParagraphSpans(tableXml, cell);
429212
429359
  const cellBlock = paragraphs.map((paragraph4) => blockIdFromParagraphXml(tableXml.slice(paragraph4.start, paragraph4.end))).map((blockId) => blockId == null ? undefined : blockById.get(blockId)).find(Boolean);
429213
429360
  const cellNodeId = cellBlock?.structuralRefs.cellNodeId;
429214
429361
  if (!cellNodeId || !cellProperties.has(cellNodeId))
429215
429362
  continue;
429216
- const contentStart = paragraphs[0]?.start ?? cell.closeStart;
429363
+ const contentStart = directParagraphSpans(tableXml, cell)[0]?.start ?? cell.closeStart;
429217
429364
  const prefix = tableXml.slice(cell.start, contentStart);
429218
429365
  replacements.push({
429219
429366
  start: cell.start,
@@ -429533,7 +429680,7 @@ function tableBlockIdsFromXml(tableXml) {
429533
429680
  return blockIds;
429534
429681
  for (const row of directElementSpans(tableXml, table.openEnd, table.closeStart, "tr")) {
429535
429682
  for (const cell of directElementSpans(tableXml, row.openEnd, row.closeStart, "tc")) {
429536
- for (const paragraph4 of directParagraphSpans(tableXml, cell)) {
429683
+ for (const paragraph4 of cellParagraphSpans(tableXml, cell)) {
429537
429684
  const blockId = blockIdFromParagraphXml(tableXml.slice(paragraph4.start, paragraph4.end));
429538
429685
  if (blockId)
429539
429686
  blockIds.add(blockId);
@@ -429590,6 +429737,15 @@ function findContainingTableCellSpan(xml, offset) {
429590
429737
  }
429591
429738
  return containing;
429592
429739
  }
429740
+ function cellParagraphSpans(xml, cellSpan) {
429741
+ const spans = directParagraphSpans(xml, cellSpan);
429742
+ for (const control of directElementSpans(xml, cellSpan.openEnd, cellSpan.closeStart, "sdt")) {
429743
+ for (const content3 of directElementSpans(xml, control.openEnd, control.closeStart, "sdtContent")) {
429744
+ spans.push(...cellParagraphSpans(xml, content3));
429745
+ }
429746
+ }
429747
+ return spans;
429748
+ }
429593
429749
  function directParagraphSpans(xml, cellSpan) {
429594
429750
  const spans = [];
429595
429751
  let cursor = cellSpan.openEnd;
@@ -435442,13 +435598,18 @@ function usesTrackedDecisionSessionSync(prepared, extension2, options) {
435442
435598
  const doc2 = options.resolveStoryShard(target.storyId);
435443
435599
  if (!doc2)
435444
435600
  return false;
435445
- const liveSpans = collectLiveTrackedTextSpans(doc2, target.rsid, target.trackedKind, [target.blockId]);
435601
+ const liveSpans = collectLiveTrackedTextSpansInLogicalTarget(doc2, target);
435446
435602
  if (liveSpans.length > 1)
435447
435603
  return true;
435448
- if (!hasTrackedDecisionLedgerEntry(doc2, target.rsid) || findPreparedLiveTrackedTextSpans(doc2, target).length > 0) {
435449
- return false;
435450
- }
435451
- return liveSpans.length > 0;
435604
+ return hasTrackedDecisionLedgerEntry(doc2, target.rsid) && liveSpans.length > 0;
435605
+ });
435606
+ }
435607
+ function collectLiveTrackedTextSpansInLogicalTarget(doc2, target) {
435608
+ return collectLiveTrackedTextSpans(doc2, target.rsid, target.trackedKind, []).filter((span) => {
435609
+ if (span.blockId === target.blockId)
435610
+ return true;
435611
+ const carrier = findBlockMap(doc2, span.blockId)?.block;
435612
+ return carrier?.get(BLOCK_KEY.mergedIntoBlockId) === target.blockId;
435452
435613
  });
435453
435614
  }
435454
435615
  function tryMirrorStoryText(prepared, extension2, options, admitted) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdoc/mcp",
3
- "version": "1.3.1-next.6",
3
+ "version": "1.3.1-next.8",
4
4
  "description": "Model Context Protocol server for SuperDoc, giving an AI agent tools to read and edit .docx files.",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0",
@@ -24,13 +24,13 @@
24
24
  ],
25
25
  "dependencies": {
26
26
  "@modelcontextprotocol/sdk": "^1.26.0",
27
- "@superdoc/sdk": "2.16.1-next.6",
27
+ "@superdoc/sdk": "2.16.1-next.8",
28
28
  "debug": "^4.4.3",
29
29
  "zod": "^4.3.6"
30
30
  },
31
31
  "devDependencies": {
32
- "superdoc": "2.19.1-next.2",
33
- "@superdoc/docx-engine": "0.18.1-next.2",
32
+ "superdoc": "2.19.1-next.5",
33
+ "@superdoc/docx-engine": "0.18.1-next.5",
34
34
  "@superdoc/document-api": "0.1.0-alpha.0",
35
35
  "@types/bun": "^1.3.8",
36
36
  "@types/node": "22.19.2",