@superdoc/mcp 1.2.1-next.2 → 1.2.1-next.4

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 +1019 -791
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31314,7 +31314,7 @@ var init_host = __esm(() => {
31314
31314
  });
31315
31315
 
31316
31316
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31317
- var SDK_VERSION = "2.15.1-next.2";
31317
+ var SDK_VERSION = "2.15.1-next.4";
31318
31318
 
31319
31319
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31320
31320
  import { chmodSync, existsSync } from "node:fs";
@@ -118889,6 +118889,11 @@ function validateId(id, operationName) {
118889
118889
  });
118890
118890
  }
118891
118891
  }
118892
+ function validateContentControlId(id, operationName) {
118893
+ if (id !== undefined && (typeof id !== "string" || id.length === 0)) {
118894
+ throw new DocumentApiValidationError("INVALID_INPUT", `${operationName} requires a non-empty 'contentControlId' string when provided.`);
118895
+ }
118896
+ }
118892
118897
  function validateNamespace(namespace, operationName) {
118893
118898
  if (typeof namespace !== "string" || namespace.length === 0) {
118894
118899
  throw new DocumentApiValidationError("INVALID_INPUT", `${operationName} requires a non-empty 'namespace' string.`, {
@@ -118956,6 +118961,14 @@ function executeAnchoredMetadataList(adapter, query2) {
118956
118961
  }
118957
118962
  function executeAnchoredMetadataGet(adapter, input) {
118958
118963
  validateId(input.id, "metadata.get");
118964
+ validateContentControlId(input.contentControlId, "metadata.get");
118965
+ if (input.contentControlId !== undefined) {
118966
+ if (input.story === undefined)
118967
+ return null;
118968
+ validateStoryLocator(input.story, "metadata.get.story");
118969
+ if (input.story.storyType !== "body")
118970
+ return null;
118971
+ }
118959
118972
  return adapter.get(input);
118960
118973
  }
118961
118974
  function executeAnchoredMetadataUpdate(adapter, input, options) {
@@ -118969,6 +118982,14 @@ function executeAnchoredMetadataRemove(adapter, input, options) {
118969
118982
  }
118970
118983
  function executeAnchoredMetadataResolve(adapter, input) {
118971
118984
  validateId(input.id, "metadata.resolve");
118985
+ validateContentControlId(input.contentControlId, "metadata.resolve");
118986
+ if (input.contentControlId !== undefined) {
118987
+ if (input.story === undefined)
118988
+ return null;
118989
+ validateStoryLocator(input.story, "metadata.resolve.story");
118990
+ if (input.story.storyType !== "body")
118991
+ return null;
118992
+ }
118972
118993
  return adapter.resolve(input);
118973
118994
  }
118974
118995
  var init_anchored_metadata = __esm(() => {
@@ -118976,6 +118997,7 @@ var init_anchored_metadata = __esm(() => {
118976
118997
  init_errors5();
118977
118998
  init_selection_target_validator();
118978
118999
  init_validation_primitives();
119000
+ init_story_validator();
118979
119001
  });
118980
119002
 
118981
119003
  // ../../packages/document-api/dist/protection/protection.js
@@ -162777,7 +162799,7 @@ var init_collapsed_inline_insertion_site = __esm(() => {
162777
162799
  });
162778
162800
 
162779
162801
  // ../../../v2/editor-core/dist/document/transactions/compile-edit-text-inline-plan.js
162780
- function planDirectInlineEdit(paragraphBytes, startOffset, endOffset, newText, collapsedObjectBoundary, collapsedInlineAffinity, inheritedNamespaceBindings = {}) {
162802
+ function planDirectInlineEdit(paragraphBytes, startOffset, endOffset, newText, collapsedObjectBoundary, collapsedInlineAffinity, inheritedNamespaceBindings = {}, collapsedOutsideContentControl = false) {
162781
162803
  const xml = TD21.decode(paragraphBytes);
162782
162804
  const model = parseParagraphInlineMap(xml, inheritedNamespaceBindings);
162783
162805
  const leaves = model.leaves();
@@ -162820,7 +162842,7 @@ function planDirectInlineEdit(paragraphBytes, startOffset, endOffset, newText, c
162820
162842
  if (beside)
162821
162843
  return beside;
162822
162844
  }
162823
- const scope = resolveEditScope(model.pieces, startOffset, endOffset, collapsedInlineAffinity);
162845
+ const scope = resolveEditScope(model.pieces, startOffset, endOffset, collapsedInlineAffinity, collapsedOutsideContentControl);
162824
162846
  if (!scope.ok)
162825
162847
  return { ok: false, reason: scope.reason };
162826
162848
  const pieces = scope.pieces;
@@ -162832,7 +162854,7 @@ function planDirectInlineEdit(paragraphBytes, startOffset, endOffset, newText, c
162832
162854
  return { ok: false, reason: "invalid-range" };
162833
162855
  }
162834
162856
  const hasEditableLeaf = pieces.some((piece) => isVisibleText(piece) || isLiveControl(piece) || startOffset !== endOffset && isLiveNoteReference(piece));
162835
- if (!hasEditableLeaf) {
162857
+ if (!hasEditableLeaf && !(collapsedOutsideContentControl && startOffset === endOffset && newText.length > 0)) {
162836
162858
  if (newText.length === 0 && scope.wrapperRemovalOps.length > 0) {
162837
162859
  return {
162838
162860
  ok: true,
@@ -162849,7 +162871,7 @@ function planDirectInlineEdit(paragraphBytes, startOffset, endOffset, newText, c
162849
162871
  }
162850
162872
  if (startOffset === endOffset) {
162851
162873
  const plan2 = planCollapsedInsert(paragraphBytes, xml, pieces, leaves, startOffset, newText, visibleLength === 0, inlineContext, collapsedInlineAffinity);
162852
- return plan2.ok && scope.requiresCollaborationSessionSync ? { ...plan2, requiresCollaborationSessionSync: true } : plan2;
162874
+ return plan2.ok && (scope.requiresCollaborationSessionSync || collapsedOutsideContentControl) ? { ...plan2, requiresCollaborationSessionSync: true } : plan2;
162853
162875
  }
162854
162876
  const plan = planReplace(paragraphBytes, pieces, leaves, startOffset, endOffset, newText, scope.wrapperRemovalOps);
162855
162877
  return plan.ok && (scope.requiresCollaborationSessionSync || preservesCrossedBookmarks) ? { ...plan, requiresCollaborationSessionSync: true } : plan;
@@ -163441,13 +163463,13 @@ function hasNonWordMarkerAtCollapsedMoveBoundary(pieces, at, coordinateSpace = "
163441
163463
  function firstNonFieldRangeStartMarker(markers) {
163442
163464
  return markers.find((piece) => piece.role === "range-start" && !isFieldMarker(piece.markerKind)) ?? null;
163443
163465
  }
163444
- function resolveEditScope(pieces, start, end, collapsedInlineAffinity) {
163466
+ function resolveEditScope(pieces, start, end, collapsedInlineAffinity, collapsedOutsideContentControl = false) {
163445
163467
  let current = pieces;
163446
163468
  let descended = false;
163447
163469
  let emptySdt;
163448
163470
  let requiresCollaborationSessionSync = false;
163449
163471
  for (;; ) {
163450
- const container = current.find((piece) => piece.kind === "container" && containerContainsRange(piece, start, end)) ?? (start === end ? findCollapsedEdgeContainer(current, start, collapsedInlineAffinity == null) : undefined);
163472
+ const container = current.find((piece) => piece.kind === "container" && containerContainsRange(piece, start, end)) ?? (start === end ? findCollapsedEdgeContainer(current, start, collapsedInlineAffinity, collapsedOutsideContentControl) : undefined);
163451
163473
  if (!container) {
163452
163474
  if (start === end) {
163453
163475
  return {
@@ -163550,9 +163572,24 @@ function containerContainsRange(piece, start, end) {
163550
163572
  return piece.visibleStart < start && start < piece.visibleEnd;
163551
163573
  return piece.visibleStart <= start && end <= piece.visibleEnd;
163552
163574
  }
163553
- function findCollapsedEdgeContainer(pieces, at, allowEmptySdt = false) {
163575
+ function findCollapsedEdgeContainer(pieces, at, collapsedInlineAffinity, collapsedOutsideContentControl = false) {
163554
163576
  const emptySdtsAtPoint = pieces.filter((piece) => piece.kind === "container" && piece.containerKind === "sdt" && piece.visibleStart === at && piece.visibleEnd === at);
163555
- return pieces.find((piece) => piece.kind === "container" && (allowEmptySdt && emptySdtsAtPoint.length === 1 && piece.containerKind === "sdt" && piece.visibleStart === at && piece.visibleEnd === at || piece.visibleEnd > piece.visibleStart && (piece.visibleStart === at && (piece.containerKind === "sdt" || !hasVisibleSiblingEndingAt(pieces, at)) || piece.visibleEnd === at && (piece.containerKind === "sdt" ? !hasVisibleSiblingStartingAt(pieces, at, "sdt") : !hasVisibleSiblingStartingAt(pieces, at)))));
163577
+ return pieces.find((piece) => {
163578
+ if (piece.kind !== "container")
163579
+ return false;
163580
+ if (collapsedOutsideContentControl && piece.containerKind === "sdt")
163581
+ return false;
163582
+ if (piece.visibleStart === piece.visibleEnd) {
163583
+ return collapsedInlineAffinity == null && emptySdtsAtPoint.length === 1 && piece.containerKind === "sdt" && piece.visibleStart === at;
163584
+ }
163585
+ if (piece.visibleStart === at) {
163586
+ return piece.containerKind === "sdt" ? collapsedInlineAffinity !== "upstream" : !hasVisibleSiblingEndingAt(pieces, at);
163587
+ }
163588
+ if (piece.visibleEnd === at) {
163589
+ return piece.containerKind === "sdt" ? collapsedInlineAffinity !== "downstream" && !hasVisibleSiblingStartingAt(pieces, at, "sdt") : !hasVisibleSiblingStartingAt(pieces, at);
163590
+ }
163591
+ return false;
163592
+ });
163556
163593
  }
163557
163594
  function planEmptySdtInsert(paragraphBytes, piece, newText) {
163558
163595
  const raw = piece.rawXml;
@@ -196194,7 +196231,7 @@ function rewriteLocalizedDirect(bytes, window2, op, inheritedNamespaceBindings =
196194
196231
  return rewritten;
196195
196232
  return { ok: true, bytes: TE16.encode(rewritten.xml), runPropertiesXml: "" };
196196
196233
  }
196197
- const plan = planDirectInlineEdit(paragraphBytes, op.on.startOffset, op.on.endOffset, op.newText, op.on.collapsedObjectBoundary, op.on.collapsedInlineAffinity, inheritedNamespaceBindings);
196234
+ const plan = planDirectInlineEdit(paragraphBytes, op.on.startOffset, op.on.endOffset, op.newText, op.on.collapsedObjectBoundary, op.on.collapsedInlineAffinity, inheritedNamespaceBindings, op.on.collapsedOutsideContentControl);
196198
196235
  if (plan.ok) {
196199
196236
  return {
196200
196237
  ok: true,
@@ -209787,7 +209824,7 @@ function planCut(pieces, levelStart, input, rootPieces, chain = []) {
209787
209824
  if (strict.kind === "container" && strict.containerKind === "sdt" && input.allowMetadataAnchorSplit) {
209788
209825
  if (input.space === "tracked")
209789
209826
  return { kind: "reject", reason: "paragraph-split-point-unsupported" };
209790
- const chunks = anchoredMetadataChunks(strict, input.allocateWId);
209827
+ const chunks = anchoredMetadataChunks(strict, input.allocateWId, input.knownMetadataAnchorIds, input.onMetadataAnchorClone);
209791
209828
  if (!chunks)
209792
209829
  return { kind: "reject", reason: "paragraph-split-point-unsupported" };
209793
209830
  return planCut(strict.children, chunks.contentStart, input, rootPieces, [
@@ -209843,7 +209880,7 @@ function wrapperChunks(piece) {
209843
209880
  contentStart: piece.charStart + openEnd
209844
209881
  };
209845
209882
  }
209846
- function anchoredMetadataChunks(piece, allocateWId) {
209883
+ function anchoredMetadataChunks(piece, allocateWId, knownMetadataAnchorIds, onMetadataAnchorClone) {
209847
209884
  if (piece.children.length === 0)
209848
209885
  return null;
209849
209886
  const raw = piece.rawXml;
@@ -209857,16 +209894,23 @@ function anchoredMetadataChunks(piece, allocateWId) {
209857
209894
  const originalId = /<w:id w:val="\d+"\s*\/>/.exec(properties)?.[0];
209858
209895
  const alias = '<w:alias w:val="Anchored metadata"/>';
209859
209896
  const tag = /<w:tag w:val="[^"]+"\/>/.exec(normalizedProperties)?.[0];
209897
+ const tagValue = tag ? /w:val="([^"]+)"/.exec(tag)?.[1] : null;
209860
209898
  const appearance = '<w15:appearance w15:val="hidden"/>';
209861
209899
  const plainText = "<w:text/>";
209862
- if (!id || !originalId || !tag || !normalizedProperties.includes(alias) || !normalizedProperties.includes(appearance) || !normalizedProperties.includes(plainText) || normalizedProperties !== `<w:sdtPr>${id}${alias}${tag}${appearance}${plainText}</w:sdtPr>`) {
209900
+ const canonical = `<w:sdtPr>${id}${alias}${tag}${appearance}${plainText}</w:sdtPr>`;
209901
+ const legacy = `<w:sdtPr>${id}${tag}${appearance}${plainText}</w:sdtPr>`;
209902
+ if (!id || !originalId || !tag || !tagValue || !knownMetadataAnchorIds?.has(decodeXmlAttributeValue(tagValue)) || !normalizedProperties.includes(appearance) || !normalizedProperties.includes(plainText) || normalizedProperties !== canonical && !(normalizedProperties === legacy && knownMetadataAnchorIds?.has(decodeXmlAttributeValue(tagValue)))) {
209863
209903
  return null;
209864
209904
  }
209865
209905
  const originalPrefix = prefix[0];
209866
209906
  return {
209867
209907
  contentStart: piece.charStart + originalPrefix.length,
209868
209908
  close,
209869
- reopen: () => originalPrefix.replace(originalId, originalId.replace(/(w:val=")\d+/, (_match, attribute) => `${attribute}${allocateWId()}`))
209909
+ reopen: () => {
209910
+ const cloneId = String(allocateWId());
209911
+ onMetadataAnchorClone?.(decodeXmlAttributeValue(tagValue), /\d+/.exec(originalId)[0], cloneId);
209912
+ return originalPrefix.replace(originalId, originalId.replace(/(w:val=")\d+/, (_match, attribute) => `${attribute}${cloneId}`));
209913
+ }
209870
209914
  };
209871
209915
  }
209872
209916
  function openTagEnd(raw) {
@@ -214161,7 +214205,9 @@ function prepareParagraphSplit(input) {
214161
214205
  space: input.coordinateSpace,
214162
214206
  allocateWId: input.allocateWId,
214163
214207
  atomicObjectsAsCaretSlots: true,
214164
- allowMetadataAnchorSplit: true
214208
+ allowMetadataAnchorSplit: true,
214209
+ knownMetadataAnchorIds: new Set(input.knownMetadataAnchorIds),
214210
+ onMetadataAnchorClone: input.onMetadataAnchorClone
214165
214211
  });
214166
214212
  if (!slice.ok)
214167
214213
  return slice;
@@ -214196,6 +214242,64 @@ function renderPreparedParagraphSplit(split, trackedStamp) {
214196
214242
  const head = trackedStamp ? injectParagraphMarkTrackedMarker(split.headXml, "ins", trackedStamp) : split.headXml;
214197
214243
  return head + split.tailXml;
214198
214244
  }
214245
+ function prepareMetadataSplitStorage(state, bindings, clones) {
214246
+ const perPart = {};
214247
+ const preconditions = [];
214248
+ const parts = new Map;
214249
+ for (const clone3 of clones) {
214250
+ const binding = bindings?.find((candidate2) => candidate2.id === clone3.id);
214251
+ if (!binding || binding.physicalIds && !binding.physicalIds.includes(clone3.originalId))
214252
+ return { ok: false };
214253
+ const entries = parts.get(binding.partUri) ?? [];
214254
+ entries.push({ ...clone3, physicalIds: binding.physicalIds });
214255
+ parts.set(binding.partUri, entries);
214256
+ }
214257
+ for (const [partUri, entries] of parts) {
214258
+ const bytes = state.packageBytes.get(partUri);
214259
+ if (!bytes)
214260
+ return { ok: false };
214261
+ let xml = TD51.decode(bytes);
214262
+ const updatedIds = new Map;
214263
+ for (const entry of entries) {
214264
+ let matched = 0;
214265
+ let updated = 0;
214266
+ xml = xml.replace(/<ref\b[^>]*>/g, (tag) => {
214267
+ const rawId = /\bid="([^"]*)"/.exec(tag)?.[1];
214268
+ if (rawId === undefined || decodeXmlAttributeValue(rawId) !== entry.id)
214269
+ return tag;
214270
+ matched += 1;
214271
+ const bindingAttributes = [...tag.matchAll(/\bsdAnchorIdsV1\s*=\s*(['"])(.*?)\1/g)];
214272
+ const currentIds = updatedIds.get(entry.id);
214273
+ if (bindingAttributes.length > 1 || bindingAttributes.length === 0 && /\bsdAnchorIdsV1\b/.test(tag))
214274
+ return tag;
214275
+ const rawIds = bindingAttributes[0]?.[2];
214276
+ if (rawIds !== undefined && decodeXmlAttributeValue(rawIds) !== (currentIds ?? entry.physicalIds)?.join(","))
214277
+ return tag;
214278
+ if (rawIds === undefined && (entry.physicalIds || currentIds))
214279
+ return tag;
214280
+ const ids = currentIds ?? entry.physicalIds ?? [entry.originalId];
214281
+ if (ids.includes(entry.cloneId))
214282
+ return tag;
214283
+ const attribute = `sdAnchorIdsV1="${[...ids, entry.cloneId].join(",")}"`;
214284
+ updatedIds.set(entry.id, [...ids, entry.cloneId]);
214285
+ updated += 1;
214286
+ return rawIds === undefined ? tag.replace(/>$/, ` ${attribute}>`) : tag.replace(bindingAttributes[0][0], attribute);
214287
+ });
214288
+ if (matched !== 1 || updated !== 1)
214289
+ return { ok: false };
214290
+ }
214291
+ const patches = [{
214292
+ kind: "replaceBytes",
214293
+ order: 0,
214294
+ startByte: 0,
214295
+ endByte: bytes.length,
214296
+ bytes: TE24.encode(xml)
214297
+ }];
214298
+ perPart[partUri] = { kind: "modify", patches };
214299
+ preconditions.push(localizedByteWindowPrecondition2(partUri, bytes, patches));
214300
+ }
214301
+ return { ok: true, perPart, preconditions };
214302
+ }
214199
214303
  function runParagraphSplitCommit(input) {
214200
214304
  const op = input.op;
214201
214305
  if (input.options.expectedPackageRevision && input.options.expectedPackageRevision !== input.state.packageRevision) {
@@ -214211,12 +214315,15 @@ function runParagraphSplitCommit(input) {
214211
214315
  const provisionalParaId = op.provisionalParaId ?? mintParaId(input.state, input.state.packageRevision, target.entry.ordinal + 1);
214212
214316
  const tailParaId = provisionalParaId;
214213
214317
  const splitAllocatedWIds = [];
214318
+ const metadataClones = [];
214214
214319
  const primarySplit = prepareParagraphSplit({
214215
214320
  paragraphXml: paraXml,
214216
214321
  partBytes: bytes,
214217
214322
  paragraphByteStart: target.entry.byteStart,
214218
214323
  offset: op.offset,
214219
214324
  coordinateSpace: op.coordinateSpace ?? "visible",
214325
+ knownMetadataAnchorIds: op.knownMetadataAnchorIds,
214326
+ onMetadataAnchorClone: (id, originalId, cloneId) => metadataClones.push({ id, originalId, cloneId }),
214220
214327
  tailParaId,
214221
214328
  allocateWId: () => {
214222
214329
  const wId = allocateRevisionWId(input.state);
@@ -214252,6 +214359,7 @@ function runParagraphSplitCommit(input) {
214252
214359
  paragraphByteStart: context.byteStart,
214253
214360
  offset: op.offset,
214254
214361
  coordinateSpace: op.coordinateSpace ?? "visible",
214362
+ knownMetadataAnchorIds: op.knownMetadataAnchorIds,
214255
214363
  tailParaId,
214256
214364
  allocateWId: () => {
214257
214365
  const wId = splitAllocatedWIds[replayIndex++];
@@ -214278,6 +214386,9 @@ function runParagraphSplitCommit(input) {
214278
214386
  });
214279
214387
  if (!counterpartRewrite.ok)
214280
214388
  return rejected8(input.txId, counterpartRewrite.reason);
214389
+ const metadataStorage = prepareMetadataSplitStorage(input.state, op.metadataAnchorBindings, metadataClones);
214390
+ if (!metadataStorage.ok)
214391
+ return rejected8(input.txId, "paragraph-split-point-unsupported");
214281
214392
  const patch = counterpartRewrite.plan?.patch ?? {
214282
214393
  kind: "replaceBytes",
214283
214394
  order: 0,
@@ -214291,6 +214402,8 @@ function runParagraphSplitCommit(input) {
214291
214402
  partUri: target.entry.partUri,
214292
214403
  partBytes: bytes,
214293
214404
  patches: [patch],
214405
+ extraPerPart: metadataStorage.perPart,
214406
+ extraPreconditions: metadataStorage.preconditions,
214294
214407
  textRangeShifts: [],
214295
214408
  createdRefs: [
214296
214409
  { kind: "block", nodeId: tailParaId, storyId: op.target.storyId },
@@ -271814,7 +271927,7 @@ function ensureCustomXmlPartForNamespace(context, namespace) {
271814
271927
  return listCustomXmlRecords(context).find((record3) => record3.rootNamespace === namespace) ?? null;
271815
271928
  }
271816
271929
  function buildMetadataStorageXml(namespace, refs) {
271817
- const body = refs.map((ref5) => `<ref id="${xmlEscapeAttr(ref5.id)}" encoding="json">${xmlEscapeAttr(ref5.payloadJson)}</ref>`).join("");
271930
+ const body = refs.map((ref5) => `<ref id="${xmlEscapeAttr(ref5.id)}" encoding="json"${ref5.physicalIds === undefined ? "" : ` sdAnchorIdsV1="${xmlEscapeAttr(ref5.physicalIds?.join(",") ?? "")}"`}>${xmlEscapeAttr(ref5.payloadJson)}</ref>`).join("");
271818
271931
  return `<refs xmlns="${xmlEscapeAttr(namespace)}">${body}</refs>`;
271819
271932
  }
271820
271933
  function buildCustomXmlCreateUpdates(context, input) {
@@ -292203,8 +292316,13 @@ class V2SelectionMutationAdapter {
292203
292316
  const tx = begun.tx;
292204
292317
  const editTextStartedAt = nowMs6();
292205
292318
  const collapsedInlineAffinity = selectionCollapsedInlineAffinity(options);
292319
+ const collapsedOutsideContentControl = options?.collapsedOutsideContentControl === true;
292206
292320
  const kernelEdits = edits.map((edit, index2) => ({
292207
- on: collapsedInlineAffinity && edit.on.startOffset === edit.on.endOffset ? { ...edit.on, collapsedInlineAffinity } : edit.on,
292321
+ on: edit.on.startOffset === edit.on.endOffset ? {
292322
+ ...edit.on,
292323
+ ...collapsedInlineAffinity ? { collapsedInlineAffinity } : {},
292324
+ ...collapsedOutsideContentControl ? { collapsedOutsideContentControl: true } : {}
292325
+ } : edit.on,
292208
292326
  newText: edit.newText,
292209
292327
  ...options?.changeMode === "tracked" && (isRewrite || edits.length > 1) && !typingHistoryMetadata(options) && story.storyKind !== "textbox" ? {
292210
292328
  rewriteGroupId: `${tx.txId}:0`,
@@ -295198,6 +295316,737 @@ var init_context = __esm(() => {
295198
295316
  init_story_surface();
295199
295317
  });
295200
295318
 
295319
+ // ../../../v2/document-api-v2-adapter/dist/metadata/adapter.js
295320
+ class V2AnchoredMetadataAdapter {
295321
+ constructor(context) {
295322
+ this.context = context;
295323
+ }
295324
+ attach(input, options) {
295325
+ const mutationGuard = guardDirectOnlyMutation(this.context, input, options);
295326
+ if (mutationGuard)
295327
+ return mutationGuard;
295328
+ const id = input.id ?? newOpaqueId("metadata");
295329
+ const existingRecords = listMetadataRecords(this.context);
295330
+ if (existingRecords.some((record3) => record3.id === id)) {
295331
+ throw operationError("INVALID_INPUT", `metadata id ${id} already exists.`);
295332
+ }
295333
+ const payloadJson = JSON.stringify(input.payload);
295334
+ if (payloadJson === undefined)
295335
+ throw operationError("INVALID_INPUT", "metadata payload must be JSON serializable.");
295336
+ const documentXml = readDocumentXml(this.context);
295337
+ if (findMetadataAnchor(documentXml, id)) {
295338
+ throw operationError("INVALID_INPUT", `metadata id ${id} already exists.`);
295339
+ }
295340
+ const resolvedSegments = input.target.kind === "text" ? resolveMultiSegmentTarget(documentXml, input.target) : resolveSingleSegmentTarget(this.context, documentXml, input.target);
295341
+ if ("error" in resolvedSegments)
295342
+ throw operationError(resolvedSegments.error, resolvedSegments.message);
295343
+ const knownIds = new Set(existingRecords.map((record3) => record3.id));
295344
+ if (hasOverlappingMetadataAnchor(documentXml, resolvedSegments.segments, knownIds)) {
295345
+ return failure2("INVALID_TARGET", "metadata.attach target overlaps an existing metadata anchor.");
295346
+ }
295347
+ const existingPart = ensureCustomXmlPartForNamespace(this.context, input.namespace);
295348
+ const allocatedPart = existingPart ? null : allocateCustomXmlPartNames(this.context);
295349
+ const partName = existingPart?.partName ?? allocatedPart.partName;
295350
+ const partUri = existingPart?.partUri ?? allocatedPart.partUri;
295351
+ const storageXml = existingPart?.content ?? buildMetadataStorageXml(input.namespace, []);
295352
+ const sdtIds = allocateMetadataSdtIds(documentXml, resolvedSegments.segments.length);
295353
+ const refs = readMetadataRefs(storageXml, input.namespace);
295354
+ refs.push({ id, payloadJson, physicalIds: sdtIds.map(String) });
295355
+ const nextStorageXml = buildMetadataStorageXml(input.namespace, refs);
295356
+ const bySegmentPosition = resolvedSegments.segments.map((segment, index) => ({ segment, sdtId: sdtIds[index] })).sort((a, b) => b.segment.para.start - a.segment.para.start);
295357
+ let nextDocumentXml = documentXml;
295358
+ for (const { segment, sdtId } of bySegmentPosition) {
295359
+ const wrapped = wrapTextRangeWithMetadataSdt(segment.para.xml, segment.startOffset, segment.endOffset, id, sdtId);
295360
+ if (!wrapped.ok)
295361
+ throw metadataWrapRejectError(wrapped.reason);
295362
+ nextDocumentXml = replaceRange2(nextDocumentXml, segment.para.start, segment.para.end, wrapped.xml);
295363
+ }
295364
+ if (!dryRunRequested(input, options)) {
295365
+ nextDocumentXml = ensureW15Namespace(nextDocumentXml);
295366
+ const updates = existingPart ? { [partUri]: encodeXml(nextStorageXml) } : buildCustomXmlCreateUpdates(this.context, {
295367
+ id: newGuid(),
295368
+ content: nextStorageXml,
295369
+ partUri,
295370
+ propsPartUri: allocatedPart.propsPartUri,
295371
+ relsPartUri: allocatedPart.relsPartUri
295372
+ });
295373
+ updates[DOCUMENT_PART_URI5] = encodeXml(nextDocumentXml);
295374
+ const committed = commitWholePartUpdates(this.context, "metadata-attach", updates, {
295375
+ expectedRevision: expectedRevisionFrom(input, options),
295376
+ storySurface: {
295377
+ family: "storyAnchor",
295378
+ targetBlockIds: resolvedSegments.segments.map((segment) => segment.blockId)
295379
+ }
295380
+ });
295381
+ if (!committed.ok)
295382
+ return { success: false, failure: { code: committed.code, message: committed.message } };
295383
+ }
295384
+ return { success: true, id, namespace: input.namespace, partName };
295385
+ }
295386
+ list(query3) {
295387
+ let records = listMetadataRecords(this.context);
295388
+ const recordCounts = new Map;
295389
+ for (const record3 of records)
295390
+ recordCounts.set(record3.id, (recordCounts.get(record3.id) ?? 0) + 1);
295391
+ if (query3?.namespace !== undefined)
295392
+ records = records.filter((record3) => record3.namespace === query3.namespace);
295393
+ const documentXml = readDocumentXml(this.context);
295394
+ if (query3?.resolvedOnly === true) {
295395
+ records = records.filter((record3) => recordCounts.get(record3.id) === 1 && groupMetadataAnchor(documentXml, record3.id, new Set([record3.id]), record3.physicalIds) !== null);
295396
+ }
295397
+ if (query3?.within !== undefined) {
295398
+ records = records.filter((record3) => {
295399
+ const resolved = this.resolve({ id: record3.id });
295400
+ return resolved ? overlaps(query3.within, resolved.target) : false;
295401
+ });
295402
+ }
295403
+ const page = pageSlice(records, query3);
295404
+ return buildDiscoveryResult({
295405
+ evaluatedRevision: this.context.currentPublicRevision(),
295406
+ total: records.length,
295407
+ items: page.items.map((record3) => buildDiscoveryItem(record3.id, buildResolvedHandle(`metadata:${record3.id}`, "stable", "ext:metadata"), metadataSummary(record3, documentXml))),
295408
+ page: { offset: page.offset, limit: page.limit, returned: page.items.length }
295409
+ });
295410
+ }
295411
+ get(input) {
295412
+ if (input.contentControlId !== undefined && input.story?.storyType !== "body")
295413
+ return null;
295414
+ const record3 = findMetadataRecord(this.context, input.id);
295415
+ if (record3 && input.contentControlId !== undefined && !matchesPhysicalMetadataAnchor(readDocumentXml(this.context), record3, input.contentControlId))
295416
+ return null;
295417
+ return record3 ? { ...metadataSummary(record3, readDocumentXml(this.context)), payload: record3.payload } : null;
295418
+ }
295419
+ update(input, options) {
295420
+ const mutationGuard = guardDirectOnlyMutation(this.context, input, options);
295421
+ if (mutationGuard)
295422
+ return mutationGuard;
295423
+ if (listMetadataRecords(this.context).filter((candidate2) => candidate2.id === input.id).length > 1) {
295424
+ return failure2("INVALID_TARGET", `metadata ${input.id} has ambiguous payload records.`);
295425
+ }
295426
+ const record3 = findMetadataRecord(this.context, input.id);
295427
+ if (!record3)
295428
+ throw operationError("TARGET_NOT_FOUND", `metadata ${input.id} not found.`);
295429
+ const payloadJson = JSON.stringify(input.payload);
295430
+ if (payloadJson === undefined)
295431
+ throw operationError("INVALID_INPUT", "metadata payload must be JSON serializable.");
295432
+ if (dryRunRequested(input, options))
295433
+ return { success: true, id: input.id };
295434
+ const records = listMetadataRecords(this.context).filter((candidate2) => candidate2.partUri === record3.partUri);
295435
+ const refs = records.map((candidate2) => ({
295436
+ id: candidate2.id,
295437
+ payloadJson: candidate2.id === input.id ? payloadJson : JSON.stringify(candidate2.payload),
295438
+ physicalIds: candidate2.physicalIds
295439
+ }));
295440
+ const committed = commitWholePartUpdates(this.context, "metadata-update", { [record3.partUri]: encodeXml(buildMetadataStorageXml(record3.namespace, refs)) }, { expectedRevision: expectedRevisionFrom(input, options) });
295441
+ if (!committed.ok)
295442
+ return { success: false, failure: { code: committed.code, message: committed.message } };
295443
+ return { success: true, id: input.id };
295444
+ }
295445
+ remove(input, options) {
295446
+ const mutationGuard = guardDirectOnlyMutation(this.context, input, options);
295447
+ if (mutationGuard)
295448
+ return mutationGuard;
295449
+ if (listMetadataRecords(this.context).filter((candidate2) => candidate2.id === input.id).length > 1) {
295450
+ return failure2("INVALID_TARGET", `metadata ${input.id} has ambiguous payload records.`);
295451
+ }
295452
+ const record3 = findMetadataRecord(this.context, input.id);
295453
+ if (!record3)
295454
+ throw operationError("TARGET_NOT_FOUND", `metadata ${input.id} not found.`);
295455
+ const documentXml = readDocumentXml(this.context);
295456
+ const knownIds = new Set(listMetadataRecords(this.context).map((candidate2) => candidate2.id));
295457
+ const matchingAnchors = listMetadataAnchors(documentXml, knownIds).filter((anchor) => anchor.id === input.id);
295458
+ const grouped = groupMetadataAnchor(documentXml, input.id, knownIds, record3.physicalIds);
295459
+ const malformedLegacyAnchor = record3.physicalIds === undefined && matchingAnchors.length === 1 && (matchingAnchors[0].unmatched || unwrapSdt(matchingAnchors[0].xml) === null);
295460
+ if ((matchingAnchors.length > 0 || record3.physicalIds !== undefined) && !grouped && !malformedLegacyAnchor) {
295461
+ return { success: false, failure: { code: "INVALID_TARGET", message: `metadata ${input.id} has ambiguous anchors.` } };
295462
+ }
295463
+ if (dryRunRequested(input, options))
295464
+ return { success: true, id: input.id };
295465
+ const updates = {};
295466
+ if (grouped) {
295467
+ const bySegmentPosition = [...grouped.segments].sort((a, b) => b.start - a.start);
295468
+ let nextDocumentXml = documentXml;
295469
+ for (const anchor of bySegmentPosition) {
295470
+ if (anchor.unmatched)
295471
+ continue;
295472
+ const unwrapped = unwrapSdt(anchor.xml);
295473
+ if (unwrapped === null)
295474
+ continue;
295475
+ nextDocumentXml = replaceRange2(nextDocumentXml, anchor.start, anchor.end, unwrapped);
295476
+ }
295477
+ if (nextDocumentXml !== documentXml)
295478
+ updates[DOCUMENT_PART_URI5] = encodeXml(nextDocumentXml);
295479
+ }
295480
+ const remaining = listMetadataRecords(this.context).filter((candidate2) => candidate2.partUri === record3.partUri && candidate2.id !== input.id).map((candidate2) => ({ id: candidate2.id, payloadJson: JSON.stringify(candidate2.payload), physicalIds: candidate2.physicalIds }));
295481
+ const targetBlockIds2 = grouped ? grouped.segments.map((anchor) => anchor.blockId) : undefined;
295482
+ if (remaining.length > 0) {
295483
+ updates[record3.partUri] = encodeXml(buildMetadataStorageXml(record3.namespace, remaining));
295484
+ const committed = commitWholePartUpdates(this.context, "metadata-remove", updates, {
295485
+ expectedRevision: expectedRevisionFrom(input, options),
295486
+ ...targetBlockIds2 ? { storySurface: { family: "storyAnchor", targetBlockIds: targetBlockIds2 } } : {}
295487
+ });
295488
+ if (!committed.ok)
295489
+ return { success: false, failure: { code: committed.code, message: committed.message } };
295490
+ } else {
295491
+ Object.assign(updates, buildCustomXmlRemoveUpdates(this.context, record3));
295492
+ const committed = commitWholePartUpdates(this.context, "metadata-remove", updates, {
295493
+ expectedRevision: expectedRevisionFrom(input, options),
295494
+ ...targetBlockIds2 ? { storySurface: { family: "storyAnchor", targetBlockIds: targetBlockIds2 } } : {}
295495
+ });
295496
+ if (!committed.ok)
295497
+ return { success: false, failure: { code: committed.code, message: committed.message } };
295498
+ }
295499
+ return { success: true, id: input.id };
295500
+ }
295501
+ resolve(input) {
295502
+ if (input.contentControlId !== undefined && input.story?.storyType !== "body")
295503
+ return null;
295504
+ const record3 = findMetadataRecord(this.context, input.id);
295505
+ if (!record3)
295506
+ return null;
295507
+ const knownIds = new Set(listMetadataRecords(this.context).map((candidate2) => candidate2.id));
295508
+ const grouped = groupMetadataAnchor(readDocumentXml(this.context), input.id, knownIds, record3.physicalIds);
295509
+ if (!grouped)
295510
+ return null;
295511
+ if (input.contentControlId !== undefined && !grouped.segments.some((anchor) => metadataAnchorPhysicalId(anchor) === input.contentControlId))
295512
+ return null;
295513
+ return { id: input.id, target: grouped.target };
295514
+ }
295515
+ }
295516
+ function matchesPhysicalMetadataAnchor(documentXml, record3, contentControlId) {
295517
+ const grouped = groupMetadataAnchor(documentXml, record3.id, new Set([record3.id]), record3.physicalIds);
295518
+ return grouped !== null && grouped.segments.some((anchor) => metadataAnchorPhysicalId(anchor) === contentControlId);
295519
+ }
295520
+ function listMetadataSplitBindings(context, paragraphXml) {
295521
+ const candidateIds = new Set([...paragraphXml.matchAll(/<w:tag\b[^>]*\/>/g)].map((match) => attrValue(match[0], "val")).filter((id) => id !== null));
295522
+ if (candidateIds.size === 0)
295523
+ return [];
295524
+ const records = listMetadataRecords(context);
295525
+ const counts = new Map;
295526
+ for (const record3 of records)
295527
+ counts.set(record3.id, (counts.get(record3.id) ?? 0) + 1);
295528
+ const documentXml = readDocumentXml(context);
295529
+ return records.filter((record3) => candidateIds.has(record3.id) && counts.get(record3.id) === 1 && groupMetadataAnchor(documentXml, record3.id, new Set([record3.id]), record3.physicalIds) !== null).map((record3) => ({
295530
+ id: record3.id,
295531
+ partUri: record3.partUri,
295532
+ ...record3.physicalIds ? { physicalIds: record3.physicalIds } : {}
295533
+ }));
295534
+ }
295535
+ function listMetadataRecords(context) {
295536
+ const out = [];
295537
+ for (const part of listCustomXmlRecords(context)) {
295538
+ if (!part.rootNamespace || !/^<refs\b/.test(part.content.replace(/^<\?xml[^>]*>/, "").trim()))
295539
+ continue;
295540
+ for (const ref5 of readMetadataRefs(part.content, part.rootNamespace)) {
295541
+ let payload = null;
295542
+ try {
295543
+ payload = JSON.parse(ref5.payloadJson);
295544
+ } catch {
295545
+ payload = null;
295546
+ }
295547
+ out.push({
295548
+ id: ref5.id,
295549
+ namespace: part.rootNamespace,
295550
+ partName: part.partName,
295551
+ partUri: part.partUri,
295552
+ ...part.propsPartUri ? { propsPartUri: part.propsPartUri } : {},
295553
+ payload,
295554
+ ...ref5.physicalIds !== undefined ? { physicalIds: ref5.physicalIds } : {}
295555
+ });
295556
+ }
295557
+ }
295558
+ return out;
295559
+ }
295560
+ function findMetadataRecord(context, id) {
295561
+ const matches = listMetadataRecords(context).filter((record3) => record3.id === id);
295562
+ return matches.length === 1 ? matches[0] : null;
295563
+ }
295564
+ function metadataSummary(record3, documentXml) {
295565
+ return {
295566
+ id: record3.id,
295567
+ namespace: record3.namespace,
295568
+ partName: record3.partName,
295569
+ anchorStatus: groupMetadataAnchor(documentXml, record3.id, new Set([record3.id]), record3.physicalIds) ? "resolved" : "orphan"
295570
+ };
295571
+ }
295572
+ function readMetadataRefs(xml, _namespace) {
295573
+ const refs = [];
295574
+ const re = /(<ref\b[^>]*\bid="([^"]*)"[^>]*>)([\s\S]*?)<\/ref>/g;
295575
+ for (let match = re.exec(xml);match; match = re.exec(xml)) {
295576
+ const bindingAttributes = [...match[1].matchAll(/\bsdAnchorIdsV1\s*=\s*(['"])(.*?)\1/g)];
295577
+ const ids = bindingAttributes.length === 0 && !/\bsdAnchorIdsV1\b/.test(match[1]) ? undefined : bindingAttributes.length === 1 ? decodeXmlEntities(bindingAttributes[0][2]).split(",") : [];
295578
+ const validIds = ids && ids.length > 0 && ids.every((value2) => /^(?:0|[1-9]\d*)$/.test(value2)) && new Set(ids).size === ids.length;
295579
+ refs.push({
295580
+ id: decodeXmlEntities(match[2]),
295581
+ payloadJson: decodeXmlEntities(match[3]),
295582
+ ...ids !== undefined ? { physicalIds: validIds ? ids : null } : {}
295583
+ });
295584
+ }
295585
+ return refs;
295586
+ }
295587
+ function findMetadataAnchor(documentXml, id) {
295588
+ return listMetadataAnchors(documentXml, new Set([id])).find((anchor) => anchor.id === id) ?? null;
295589
+ }
295590
+ function listMetadataAnchors(documentXml, knownIds) {
295591
+ const anchors = [];
295592
+ for (const sdt of listSdtRanges(documentXml)) {
295593
+ const pr = ownSdtPr(sdt.xml);
295594
+ const tag = attrValue(/<w:tag\b[^>]*\/>/.exec(pr)?.[0] ?? "", "val");
295595
+ if (!tag || !isMetadataAnchorPr(pr, tag, knownIds))
295596
+ continue;
295597
+ const anchor = materializeMetadataAnchor(documentXml, sdt, tag);
295598
+ if (anchor)
295599
+ anchors.push(anchor);
295600
+ }
295601
+ return anchors.sort((left, right) => left.start - right.start);
295602
+ }
295603
+ function ownSdtPr(sdtXml) {
295604
+ const openTag = /<w:sdt\b[^>]*>/.exec(sdtXml);
295605
+ if (!openTag)
295606
+ return "";
295607
+ const headStart = openTag.index + openTag[0].length;
295608
+ const contentOrNested = /<w:sdtContent\b[^>]*>|<w:sdt\b[^>]*>/.exec(sdtXml.slice(headStart));
295609
+ const head = contentOrNested ? sdtXml.slice(headStart, headStart + contentOrNested.index) : sdtXml.slice(headStart);
295610
+ return /<w:sdtPr\b[^>]*>[\s\S]*?<\/w:sdtPr>/.exec(head)?.[0] ?? "";
295611
+ }
295612
+ function listSdtRanges(documentXml) {
295613
+ const ranges = [];
295614
+ const stack = [];
295615
+ const tokenRe = /<w:sdt\b[^>]*>|<\/w:sdt>/g;
295616
+ for (let match = tokenRe.exec(documentXml);match; match = tokenRe.exec(documentXml)) {
295617
+ if (match[0].startsWith("</")) {
295618
+ const start = stack.pop();
295619
+ if (start === undefined)
295620
+ continue;
295621
+ const end = tokenRe.lastIndex;
295622
+ ranges.push({ start, end, xml: documentXml.slice(start, end) });
295623
+ } else if (/\/\s*>$/.test(match[0])) {
295624
+ ranges.push({ start: match.index, end: tokenRe.lastIndex, xml: match[0] });
295625
+ } else {
295626
+ stack.push(match.index);
295627
+ }
295628
+ }
295629
+ for (const start of stack) {
295630
+ const end = unmatchedSdtExtent(documentXml, start);
295631
+ ranges.push({ start, end, xml: documentXml.slice(start, end), unmatched: true });
295632
+ }
295633
+ return ranges.sort((left, right) => left.start - right.start);
295634
+ }
295635
+ function unmatchedSdtExtent(documentXml, start) {
295636
+ const paraClose = documentXml.indexOf("</w:p>", start);
295637
+ return paraClose === -1 ? documentXml.length : paraClose;
295638
+ }
295639
+ function isMetadataAnchorPr(pr, tag, knownIds) {
295640
+ const alias = attrValue(/<w:alias\b[^>]*\/>/.exec(pr)?.[0] ?? "", "val");
295641
+ if (alias !== null && alias !== METADATA_ANCHOR_ALIAS)
295642
+ return false;
295643
+ const hasHiddenAppearance = attrValue(/<w15:appearance\b[^>]*\/>/.exec(pr)?.[0] ?? "", "val") === "hidden";
295644
+ const hasPlainTextPr = /<w:text\b/.test(pr);
295645
+ return knownIds.has(tag) && hasHiddenAppearance && hasPlainTextPr;
295646
+ }
295647
+ function materializeMetadataAnchor(documentXml, sdt, id) {
295648
+ const para = findParagraphContaining2(documentXml, sdt.start);
295649
+ if (!para)
295650
+ return null;
295651
+ const startOffset = extractVisibleTextFromXml2(para.xml.slice(0, sdt.start - para.start)).length;
295652
+ const length = extractVisibleTextFromXml2(unwrapSdt(sdt.xml) ?? sdt.xml).length;
295653
+ const endOffset = startOffset + length;
295654
+ return {
295655
+ id,
295656
+ start: sdt.start,
295657
+ end: sdt.end,
295658
+ xml: sdt.xml,
295659
+ blockId: para.blockId,
295660
+ startOffset,
295661
+ endOffset,
295662
+ unmatched: sdt.unmatched === true,
295663
+ target: {
295664
+ kind: "selection",
295665
+ start: { kind: "text", blockId: para.blockId, offset: startOffset, story: bodyStoryLocator2() },
295666
+ end: { kind: "text", blockId: para.blockId, offset: endOffset, story: bodyStoryLocator2() }
295667
+ }
295668
+ };
295669
+ }
295670
+ function groupMetadataAnchor(documentXml, id, knownIds, physicalIds) {
295671
+ const matches = listMetadataAnchors(documentXml, knownIds).filter((anchor) => anchor.id === id);
295672
+ if (matches.length === 0)
295673
+ return null;
295674
+ if (physicalIds === null)
295675
+ return null;
295676
+ if (physicalIds === undefined && matches.length !== 1)
295677
+ return null;
295678
+ if (physicalIds !== undefined && (matches.length !== physicalIds.length || matches.some((anchor) => {
295679
+ const physicalId = metadataAnchorPhysicalId(anchor);
295680
+ return physicalId === null || !physicalIds.includes(physicalId);
295681
+ }) || new Set(matches.map(metadataAnchorPhysicalId)).size !== matches.length))
295682
+ return null;
295683
+ const controlIdCounts = countBodyControlIds(documentXml);
295684
+ if (!controlIdCounts)
295685
+ return null;
295686
+ if (matches.some((anchor) => controlIdCounts.get(metadataAnchorPhysicalId(anchor) ?? "") !== 1))
295687
+ return null;
295688
+ const kept = contiguousAnchorPrefix(documentXml, matches);
295689
+ if (kept.length !== matches.length)
295690
+ return null;
295691
+ if (kept.some((anchor) => anchor.unmatched || unwrapSdt(anchor.xml) === null))
295692
+ return null;
295693
+ if (kept.length === 1)
295694
+ return { id, segments: kept, target: kept[0].target };
295695
+ const textSegments = [];
295696
+ for (const anchor of kept) {
295697
+ const previous = textSegments.at(-1);
295698
+ if (previous?.blockId === anchor.blockId && previous.range.end === anchor.startOffset) {
295699
+ previous.range.end = anchor.endOffset;
295700
+ } else {
295701
+ textSegments.push({ blockId: anchor.blockId, range: { start: anchor.startOffset, end: anchor.endOffset } });
295702
+ }
295703
+ }
295704
+ if (textSegments.length === 1) {
295705
+ const range = textSegments[0];
295706
+ return {
295707
+ id,
295708
+ segments: kept,
295709
+ target: {
295710
+ kind: "selection",
295711
+ start: { kind: "text", blockId: range.blockId, offset: range.range.start, story: bodyStoryLocator2() },
295712
+ end: { kind: "text", blockId: range.blockId, offset: range.range.end, story: bodyStoryLocator2() }
295713
+ }
295714
+ };
295715
+ }
295716
+ return {
295717
+ id,
295718
+ segments: kept,
295719
+ target: { kind: "text", segments: [textSegments[0], ...textSegments.slice(1)] }
295720
+ };
295721
+ }
295722
+ function metadataAnchorPhysicalId(anchor) {
295723
+ const idTag = /<w:id\b[^>]*\/>/.exec(ownSdtPr(anchor.xml))?.[0];
295724
+ const value2 = idTag && /\bw:val\s*=\s*(['"])(.*?)\1/.exec(idTag)?.[2];
295725
+ return value2 === undefined ? null : decodeXmlEntities(value2);
295726
+ }
295727
+ function countBodyControlIds(documentXml) {
295728
+ const counts = new Map;
295729
+ const stack = [];
295730
+ const parser = createXmlSaxParser({ namespaceAware: true });
295731
+ let parseFailed = false;
295732
+ parser.on("error", () => {
295733
+ parseFailed = true;
295734
+ });
295735
+ parser.on("opentag", (tag) => {
295736
+ const parent = stack.at(-1);
295737
+ const owner = stack.at(-2);
295738
+ if (tag.namespaceUri === WORD_NAMESPACE5 && tag.localName === "id" && parent?.namespaceUri === WORD_NAMESPACE5 && parent.localName === "sdtPr" && owner?.namespaceUri === WORD_NAMESPACE5 && owner.localName === "sdt") {
295739
+ const value2 = tag.attributes.find((attribute) => attribute.namespaceUri === WORD_NAMESPACE5 && attribute.localName === "val")?.value;
295740
+ if (value2 !== undefined)
295741
+ counts.set(value2, (counts.get(value2) ?? 0) + 1);
295742
+ }
295743
+ stack.push(tag);
295744
+ });
295745
+ parser.on("closetag", () => {
295746
+ stack.pop();
295747
+ });
295748
+ try {
295749
+ parser.write(documentXml).close();
295750
+ } catch {
295751
+ return null;
295752
+ }
295753
+ return parseFailed ? null : counts;
295754
+ }
295755
+ function contiguousAnchorPrefix(documentXml, matches) {
295756
+ if (matches.length <= 1)
295757
+ return [...matches];
295758
+ const map3 = buildStructuralBoundaryMap(TEXT_ENCODER.encode(documentXml));
295759
+ const first = map3.byBlockId(matches[0].blockId);
295760
+ if (!first)
295761
+ return [matches[0]];
295762
+ const kept = [matches[0]];
295763
+ let prev = first;
295764
+ for (let i2 = 1;i2 < matches.length; i2 += 1) {
295765
+ const context = map3.byBlockId(matches[i2].blockId);
295766
+ if (!context)
295767
+ break;
295768
+ const sameParagraph = context.ordinal === prev.ordinal;
295769
+ if (sameParagraph) {
295770
+ const previousAnchor = kept.at(-1);
295771
+ if (context.blockId !== previousAnchor.blockId || matches[i2].startOffset !== previousAnchor.endOffset || !isMetadataCarrierGap(documentXml.slice(previousAnchor.end, matches[i2].start)))
295772
+ break;
295773
+ } else if (context.ordinal !== prev.ordinal + 1)
295774
+ break;
295775
+ if (!sameTableCellPath(context.tableCellPath, first.tableCellPath))
295776
+ break;
295777
+ if (!sameOrdinalPath2(context.blockSdtPath, first.blockSdtPath))
295778
+ break;
295779
+ if (!sameOrdinalPath2(context.blockCustomXmlPath, first.blockCustomXmlPath))
295780
+ break;
295781
+ if (context.sectionIndex !== first.sectionIndex)
295782
+ break;
295783
+ if (prev.carriesSectionBreak)
295784
+ break;
295785
+ kept.push(matches[i2]);
295786
+ prev = context;
295787
+ }
295788
+ return kept;
295789
+ }
295790
+ function isMetadataCarrierGap(xml) {
295791
+ return /^(?:\s*<w:proofErr\s+w:type="(?:spellStart|spellEnd|gramStart|gramEnd)"\s*\/>)*\s*$/.test(xml);
295792
+ }
295793
+ function sameOrdinalPath2(left, right) {
295794
+ return left.length === right.length && left.every((value2, index) => value2 === right[index]);
295795
+ }
295796
+ function resolveSingleSegmentTarget(context, documentXml, target) {
295797
+ const resolved = resolveBodySelectionTarget(context, target);
295798
+ if ("error" in resolved)
295799
+ return resolved;
295800
+ if (resolved.startBlockId !== resolved.endBlockId) {
295801
+ return { error: "INVALID_TARGET", message: "metadata.attach requires a same-paragraph text selection." };
295802
+ }
295803
+ if (resolved.startOffset >= resolved.endOffset) {
295804
+ return { error: "INVALID_TARGET", message: "metadata.attach requires a non-empty text range." };
295805
+ }
295806
+ const para = findParagraphById2(documentXml, resolved.startBlockId);
295807
+ if (!para)
295808
+ return { error: "TARGET_NOT_FOUND", message: `paragraph ${resolved.startBlockId} not found.` };
295809
+ return {
295810
+ segments: [{ blockId: para.blockId, startOffset: resolved.startOffset, endOffset: resolved.endOffset, para }]
295811
+ };
295812
+ }
295813
+ function resolveMultiSegmentTarget(documentXml, target) {
295814
+ if (target.story !== undefined && target.story.storyType !== "body") {
295815
+ return {
295816
+ error: "TARGET_NOT_FOUND",
295817
+ message: "metadata.attach resolves paragraphs against the main document body only."
295818
+ };
295819
+ }
295820
+ if (target.coordinateSpace === "tracked") {
295821
+ return {
295822
+ error: "INVALID_TARGET",
295823
+ message: "metadata.attach does not support a tracked-coordinate-space TextTarget."
295824
+ };
295825
+ }
295826
+ const segments = [];
295827
+ for (const segment of target.segments) {
295828
+ if (segment.range.start >= segment.range.end) {
295829
+ return {
295830
+ error: "INVALID_TARGET",
295831
+ message: "metadata.attach requires a non-empty text range in every TextTarget segment."
295832
+ };
295833
+ }
295834
+ const para = findParagraphById2(documentXml, segment.blockId);
295835
+ if (!para)
295836
+ return { error: "TARGET_NOT_FOUND", message: `paragraph ${segment.blockId} not found.` };
295837
+ segments.push({ blockId: segment.blockId, startOffset: segment.range.start, endOffset: segment.range.end, para });
295838
+ }
295839
+ const boundaryError = validateContiguousStructuralRun(documentXml, segments.map((segment) => segment.blockId));
295840
+ if (boundaryError)
295841
+ return boundaryError;
295842
+ return { segments };
295843
+ }
295844
+ function validateContiguousStructuralRun(documentXml, blockIds) {
295845
+ if (blockIds.length <= 1)
295846
+ return null;
295847
+ const map3 = buildStructuralBoundaryMap(TEXT_ENCODER.encode(documentXml));
295848
+ const contexts = blockIds.map((blockId) => map3.byBlockId(blockId));
295849
+ const first = contexts[0];
295850
+ if (!first) {
295851
+ return { error: "INVALID_TARGET", message: `paragraph "${blockIds[0]}" is not visible to the structural map.` };
295852
+ }
295853
+ for (let i2 = 1;i2 < contexts.length; i2 += 1) {
295854
+ const context = contexts[i2];
295855
+ const prev = contexts[i2 - 1];
295856
+ if (!context) {
295857
+ return { error: "INVALID_TARGET", message: `paragraph "${blockIds[i2]}" is not visible to the structural map.` };
295858
+ }
295859
+ if (context.ordinal !== prev.ordinal + 1) {
295860
+ return {
295861
+ error: "INVALID_TARGET",
295862
+ message: "metadata.attach TextTarget segments must be contiguous paragraphs in document order."
295863
+ };
295864
+ }
295865
+ if (!sameTableCellPath(context.tableCellPath, first.tableCellPath)) {
295866
+ return { error: "INVALID_TARGET", message: "metadata.attach TextTarget cannot cross a table-cell boundary." };
295867
+ }
295868
+ if (!sameOrdinalPath2(context.blockSdtPath, first.blockSdtPath)) {
295869
+ return {
295870
+ error: "INVALID_TARGET",
295871
+ message: "metadata.attach TextTarget cannot cross a block content-control boundary."
295872
+ };
295873
+ }
295874
+ if (!sameOrdinalPath2(context.blockCustomXmlPath, first.blockCustomXmlPath)) {
295875
+ return {
295876
+ error: "INVALID_TARGET",
295877
+ message: "metadata.attach TextTarget cannot cross a block custom-XML boundary."
295878
+ };
295879
+ }
295880
+ if (context.sectionIndex !== first.sectionIndex) {
295881
+ return { error: "INVALID_TARGET", message: "metadata.attach TextTarget cannot cross a section boundary." };
295882
+ }
295883
+ if (prev.carriesSectionBreak) {
295884
+ return { error: "INVALID_TARGET", message: "metadata.attach TextTarget cannot cross a section boundary." };
295885
+ }
295886
+ }
295887
+ if (contexts[contexts.length - 1].carriesSectionBreak) {
295888
+ return { error: "INVALID_TARGET", message: "metadata.attach TextTarget cannot cross a section boundary." };
295889
+ }
295890
+ return null;
295891
+ }
295892
+ function hasOverlappingMetadataAnchor(documentXml, segments, knownIds) {
295893
+ const anchors = listMetadataAnchors(documentXml, knownIds);
295894
+ return segments.some((segment) => anchors.some((anchor) => anchor.blockId === segment.blockId && rangesStrictlyOverlap(segment.startOffset, segment.endOffset, anchor.startOffset, anchor.endOffset)));
295895
+ }
295896
+ function rangesStrictlyOverlap(leftStart, leftEnd, rightStart, rightEnd) {
295897
+ return leftStart < rightEnd && rightStart < leftEnd;
295898
+ }
295899
+ function bodyStoryLocator2() {
295900
+ return { kind: "story", storyType: "body" };
295901
+ }
295902
+ function wrapTextRangeWithMetadataSdt(paragraphXml, start, end, id, sdtId) {
295903
+ return wrapRangeWithMarkupInParagraphXml({
295904
+ paragraphXml,
295905
+ rangeStart: start,
295906
+ rangeEnd: end,
295907
+ open: metadataSdtOpenXml(id, sdtId),
295908
+ close: "</w:sdtContent></w:sdt>"
295909
+ });
295910
+ }
295911
+ function metadataSdtOpenXml(id, sdtId) {
295912
+ return [
295913
+ `<w:sdt xmlns:w15="${W15_NS}"><w:sdtPr>`,
295914
+ `<w:id w:val="${sdtId}"/>`,
295915
+ `<w:alias w:val="${xmlEscapeAttr(METADATA_ANCHOR_ALIAS)}"/>`,
295916
+ `<w:tag w:val="${xmlEscapeAttr(id)}"/>`,
295917
+ '<w15:appearance w15:val="hidden"/>',
295918
+ "<w:text/>",
295919
+ "</w:sdtPr><w:sdtContent>"
295920
+ ].join("");
295921
+ }
295922
+ function metadataWrapRejectError(reason) {
295923
+ if (reason === "invalid-range") {
295924
+ return operationError("TARGET_NOT_FOUND", "metadata target text range not found.");
295925
+ }
295926
+ return operationError("INVALID_TARGET", `metadata.attach target overlaps unsupported content (${reason}).`);
295927
+ }
295928
+ function allocateMetadataSdtIds(documentXml, count) {
295929
+ const used = new Set;
295930
+ const idRe = /<w:id\b[^>]*(?:\/>|>)/g;
295931
+ for (let match = idRe.exec(documentXml);match; match = idRe.exec(documentXml)) {
295932
+ const value2 = Number.parseInt(attrValue(match[0], "val") ?? "", 10);
295933
+ if (Number.isInteger(value2))
295934
+ used.add(value2);
295935
+ }
295936
+ const ids = [];
295937
+ for (let i2 = 0;i2 < count; i2 += 1) {
295938
+ let candidate2 = Math.max(1, Math.floor(Math.random() * MAX_SDT_ID));
295939
+ while (used.has(candidate2))
295940
+ candidate2 = candidate2 >= MAX_SDT_ID ? 1 : candidate2 + 1;
295941
+ used.add(candidate2);
295942
+ ids.push(candidate2);
295943
+ }
295944
+ return ids;
295945
+ }
295946
+ function ensureW15Namespace(documentXml) {
295947
+ return documentXml.replace(/<w:document\b[^>]*>/, (openTag) => {
295948
+ let next = openTag;
295949
+ if (!/\sxmlns:w15\s*=/.test(next))
295950
+ next = next.replace(/>$/, ` xmlns:w15="${W15_NS}">`);
295951
+ const ignorable = /\smc:Ignorable\s*=\s*(["'])([^"']*)\1/.exec(next);
295952
+ if (!ignorable)
295953
+ return next;
295954
+ const prefixes = ignorable[2].split(/\s+/).filter(Boolean);
295955
+ if (prefixes.includes("w15"))
295956
+ return next;
295957
+ return next.replace(ignorable[0], ` mc:Ignorable="${[...prefixes, "w15"].join(" ")}"`);
295958
+ });
295959
+ }
295960
+ function readDocumentXml(context) {
295961
+ const xml = readPartXml(context, DOCUMENT_PART_URI5);
295962
+ if (!xml)
295963
+ throw operationError("PRECONDITION_FAILED", "document.xml bytes are unavailable.");
295964
+ return xml;
295965
+ }
295966
+ function findParagraphById2(documentXml, blockId) {
295967
+ const paraRe = /<w:p\b[^>]*>[\s\S]*?<\/w:p>/g;
295968
+ for (let match = paraRe.exec(documentXml);match; match = paraRe.exec(documentXml)) {
295969
+ if (match[0].includes(`w14:paraId="${blockId}"`))
295970
+ return { start: match.index, end: paraRe.lastIndex, xml: match[0], blockId };
295971
+ }
295972
+ return null;
295973
+ }
295974
+ function findParagraphContaining2(documentXml, index) {
295975
+ const paraRe = /<w:p\b[^>]*>[\s\S]*?<\/w:p>/g;
295976
+ for (let match = paraRe.exec(documentXml);match; match = paraRe.exec(documentXml)) {
295977
+ if (match.index <= index && paraRe.lastIndex >= index) {
295978
+ const open = /^<w:p\b[^>]*>/.exec(match[0])?.[0] ?? "";
295979
+ return {
295980
+ start: match.index,
295981
+ end: paraRe.lastIndex,
295982
+ xml: match[0],
295983
+ blockId: attrValue(open, "paraId") ?? "unknown"
295984
+ };
295985
+ }
295986
+ }
295987
+ return null;
295988
+ }
295989
+ function unwrapSdt(sdtXml) {
295990
+ const open = /<w:sdtContent\b[^>]*>/.exec(sdtXml);
295991
+ if (!open)
295992
+ return null;
295993
+ if (/\/\s*>$/.test(open[0]))
295994
+ return "";
295995
+ const contentStart = open.index + open[0].length;
295996
+ const tokenRe = /<w:sdtContent\b[^>]*>|<\/w:sdtContent>/g;
295997
+ tokenRe.lastIndex = contentStart;
295998
+ let depth = 0;
295999
+ for (let match = tokenRe.exec(sdtXml);match; match = tokenRe.exec(sdtXml)) {
296000
+ if (match[0].startsWith("</")) {
296001
+ if (depth === 0)
296002
+ return sdtXml.slice(contentStart, match.index);
296003
+ depth -= 1;
296004
+ } else if (!/\/\s*>$/.test(match[0])) {
296005
+ depth += 1;
296006
+ }
296007
+ }
296008
+ return null;
296009
+ }
296010
+ function replaceRange2(xml, start, end, replacement) {
296011
+ return `${xml.slice(0, start)}${replacement}${xml.slice(end)}`;
296012
+ }
296013
+ function toFlatSegments(target) {
296014
+ if (target.story !== undefined && target.story.storyType !== "body")
296015
+ return null;
296016
+ if (target.coordinateSpace === "tracked")
296017
+ return null;
296018
+ if (target.kind === "text") {
296019
+ return target.segments.map((segment) => ({
296020
+ blockId: segment.blockId,
296021
+ start: segment.range.start,
296022
+ end: segment.range.end
296023
+ }));
296024
+ }
296025
+ if (target.start.kind !== "text" || target.end.kind !== "text")
296026
+ return null;
296027
+ if (target.start.blockId !== target.end.blockId)
296028
+ return null;
296029
+ return [{ blockId: target.start.blockId, start: target.start.offset, end: target.end.offset }];
296030
+ }
296031
+ function overlaps(left, right) {
296032
+ const leftSegments = toFlatSegments(left);
296033
+ const rightSegments = toFlatSegments(right);
296034
+ if (!leftSegments || !rightSegments)
296035
+ return false;
296036
+ return leftSegments.some((leftSegment) => rightSegments.some((rightSegment) => leftSegment.blockId === rightSegment.blockId && rangesStrictlyOverlap(leftSegment.start, leftSegment.end, rightSegment.start, rightSegment.end)));
296037
+ }
296038
+ var TEXT_ENCODER, WORD_NAMESPACE5 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", METADATA_ANCHOR_ALIAS = "Anchored metadata", W15_NS = "http://schemas.microsoft.com/office/word/2012/wordml", MAX_SDT_ID = 2147483646;
296039
+ var init_adapter9 = __esm(() => {
296040
+ init_src3();
296041
+ init_sd_document_session_internal();
296042
+ init_visible_text();
296043
+ init_inline();
296044
+ init_adapter2();
296045
+ init_shared();
296046
+ init_xml();
296047
+ TEXT_ENCODER = new TextEncoder;
296048
+ });
296049
+
295201
296050
  // ../../../v2/document-api-v2-adapter/dist/core/cooperative-slices.js
295202
296051
  function createCooperativeSliceGate(yieldPoint, sliceTargetMs = COOPERATIVE_SLICE_TARGET_MS) {
295203
296052
  let sliceStartedAt = now();
@@ -295585,11 +296434,14 @@ function prepareNativeCellSplit(resolved, original, columnInsertIndex) {
295585
296434
  if (grids.length !== 1 || rows.length !== original.rows.length)
295586
296435
  return null;
295587
296436
  const grid = grids[0];
295588
- if (children2(grid).some((range) => !owns(range, "gridCol")))
296437
+ const originalGridChangeXml = original.tblGrid.changeXml;
296438
+ const gridChildren = children2(grid);
296439
+ const gridChanges = gridChildren.filter((range) => owns(range, "tblGridChange"));
296440
+ if (gridChanges.length > 1 || gridChildren.some((range) => !owns(range, "gridCol") && !owns(range, "tblGridChange")) || gridChanges[0] && source.slice(gridChanges[0].start, gridChanges[0].end) !== originalGridChangeXml)
295589
296441
  return null;
295590
296442
  const originalGridXml = source.slice(grid.start, grid.end);
295591
296443
  const originalGridColumns = [...original.tblGrid.gridColXmls];
295592
- const gridColumns = children2(grid);
296444
+ const gridColumns = gridChildren.filter((range) => owns(range, "gridCol"));
295593
296445
  if (gridColumns.length !== originalGridColumns.length || columnInsertIndex < 0 || columnInsertIndex > gridColumns.length)
295594
296446
  return null;
295595
296447
  const rowFacts = new Map;
@@ -295692,7 +296544,7 @@ function prepareNativeCellSplit(resolved, original, columnInsertIndex) {
295692
296544
  const addedColumns = model.tblGrid.gridColXmls.length - originalGridColumns.length;
295693
296545
  if (addedColumns < 0 || originalGridColumns.some((column, index) => model.tblGrid.gridColXmls[index < columnInsertIndex ? index : index + addedColumns] !== column))
295694
296546
  return null;
295695
- if (model.tblGrid.changeXml || addedColumns) {
296547
+ if (model.tblGrid.changeXml !== originalGridChangeXml || addedColumns) {
295696
296548
  const gridPatches = [];
295697
296549
  if (addedColumns) {
295698
296550
  const at = columnInsertIndex > 0 ? gridColumns[columnInsertIndex - 1].end : grid.openEnd;
@@ -295702,12 +296554,15 @@ function prepareNativeCellSplit(resolved, original, columnInsertIndex) {
295702
296554
  xml: model.tblGrid.gridColXmls.slice(columnInsertIndex, columnInsertIndex + addedColumns).join("")
295703
296555
  });
295704
296556
  }
295705
- if (model.tblGrid.changeXml)
296557
+ if (model.tblGrid.changeXml !== originalGridChangeXml) {
296558
+ const previousChange = gridChanges[0];
296559
+ const at = previousChange?.start ?? grid.closeStart;
295706
296560
  gridPatches.push({
295707
- start: grid.closeStart,
295708
- end: grid.closeStart,
295709
- xml: model.tblGrid.changeXml
296561
+ start: at,
296562
+ end: previousChange?.end ?? at,
296563
+ xml: model.tblGrid.changeXml ?? ""
295710
296564
  });
296565
+ }
295711
296566
  patches.push({ start: grid.start, end: grid.end, xml: apply(grid, gridPatches) });
295712
296567
  }
295713
296568
  return apply(table, patches);
@@ -301392,7 +302247,7 @@ function writeAfterPropertyXml(model, spec, wrappedXml) {
301392
302247
  }
301393
302248
  }
301394
302249
  var COLLABORATIVE_TABLE_REWRITE_PREFIXES, TD89, EMPTY_TABLE_CONTEXT_AT_SELECTION, TRACKED_TABLE_COLUMN_RESTORE_NS2 = "urn:superdoc:tracked-table-column", DEFAULT_PAGE_WIDTH_TWIPS = 12240, DEFAULT_PAGE_MARGIN_TWIPS = 1440;
301395
- var init_adapter9 = __esm(() => {
302250
+ var init_adapter10 = __esm(() => {
301396
302251
  init_src3();
301397
302252
  init_sd_document_session_internal();
301398
302253
  init_tracked_paragraph_body();
@@ -304158,6 +305013,8 @@ class V2BlocksAdapter {
304158
305013
  const paraXml = partBytes ? TD90.decode(partBytes.subarray(resolved.entry.byteStart, resolved.entry.byteEnd)) : "";
304159
305014
  const objectSlack = (paraXml.match(/<[\w.-]+:(?:drawing|pict|object)\b/g) ?? []).length;
304160
305015
  const coordinateSpace = input.coordinateSpace ?? "visible";
305016
+ const metadataAnchorBindings = storyPartUriFromId5(resolved.storyId) === "/word/document.xml" ? listMetadataSplitBindings(this.context, paraXml) : [];
305017
+ const knownMetadataAnchorIds = metadataAnchorBindings.map((binding) => binding.id);
304161
305018
  const offset = coordinateSpace === "tracked" ? Math.max(0, Math.trunc(Number.isFinite(input.offset) ? input.offset : 0)) : clampStructuralOffset(input.offset, resolved.entry.textLength + objectSlack);
304162
305019
  if (options?.dryRun) {
304163
305020
  const policy = this.context.validateMutation(options);
@@ -304170,7 +305027,8 @@ class V2BlocksAdapter {
304170
305027
  partBytes,
304171
305028
  paragraphByteStart: resolved.entry.byteStart,
304172
305029
  offset,
304173
- coordinateSpace
305030
+ coordinateSpace,
305031
+ knownMetadataAnchorIds
304174
305032
  });
304175
305033
  if (!planned.ok)
304176
305034
  return failure4(mapRejectionReason(planned.reason), planned.reason);
@@ -304184,6 +305042,8 @@ class V2BlocksAdapter {
304184
305042
  target: { storyId: resolved.storyId, paraId: input.target.nodeId },
304185
305043
  offset,
304186
305044
  coordinateSpace,
305045
+ knownMetadataAnchorIds,
305046
+ metadataAnchorBindings,
304187
305047
  changeMode: options?.changeMode ?? "direct"
304188
305048
  });
304189
305049
  const txPerf = createSDTxPerfProbe();
@@ -305373,13 +306233,14 @@ function readTailParaId(provisionalToFinal, createdRefs) {
305373
306233
  return null;
305374
306234
  }
305375
306235
  var TD90, PARAGRAPH_TYPES, TOP_LEVEL_LIST_ROWS_CACHE;
305376
- var init_adapter10 = __esm(() => {
306236
+ var init_adapter11 = __esm(() => {
305377
306237
  init_sd_document_session_internal();
306238
+ init_adapter9();
305378
306239
  init_materialize_slot();
305379
306240
  init_adapter();
305380
306241
  init_stories();
305381
306242
  init_text_range_shifts();
305382
- init_adapter9();
306243
+ init_adapter10();
305383
306244
  init_tracked_pr_change();
305384
306245
  init_note_story();
305385
306246
  init_textbox_story();
@@ -305563,7 +306424,7 @@ function operationError4(code, message) {
305563
306424
  error48.code = code;
305564
306425
  return error48;
305565
306426
  }
305566
- var init_adapter11 = __esm(() => {
306427
+ var init_adapter12 = __esm(() => {
305567
306428
  init_src3();
305568
306429
  init_sd_document_session_internal();
305569
306430
  init_runtime2();
@@ -329428,7 +330289,7 @@ class V2ContentControlsAdapter {
329428
330289
  }
329429
330290
  }
329430
330291
  if (input.at) {
329431
- const anchor = input.at.start.kind === "text" ? findParagraphById2(part.xml, input.at.start.blockId) : null;
330292
+ const anchor = input.at.start.kind === "text" ? findParagraphById3(part.xml, input.at.start.blockId) : null;
329432
330293
  if (anchor && /<(?:[\w.-]+:)?(?:ins|del|moveFrom|moveTo)\b/.test(anchor.xml)) {
329433
330294
  this.requireDirectControlStructure(input, options);
329434
330295
  }
@@ -329439,7 +330300,7 @@ class V2ContentControlsAdapter {
329439
330300
  let beforeXml = "";
329440
330301
  let namespaceBindings = new Map(Object.entries(collectXmlElementRanges(part.xml).ranges[0]?.namespaceBindings ?? {}));
329441
330302
  if (input.at?.start.kind === "text") {
329442
- const anchor = findParagraphById2(part.xml, input.at.start.blockId);
330303
+ const anchor = findParagraphById3(part.xml, input.at.start.blockId);
329443
330304
  if (anchor) {
329444
330305
  namespaceBindings = new Map(contentControlNamespaceBindings(part.xml, anchor.start, true));
329445
330306
  if (input.kind === "block" && extractVisibleTextFromXml2(anchor.xml).trim().length === 0) {
@@ -329481,11 +330342,11 @@ class V2ContentControlsAdapter {
329481
330342
  if (wholeBlocks.kind === "failure") {
329482
330343
  return { success: false, failure: { code: wholeBlocks.code, message: wholeBlocks.message } };
329483
330344
  }
329484
- const anchor = at.start.kind === "text" ? findParagraphById2(part.xml, at.start.blockId) : null;
330345
+ const anchor = at.start.kind === "text" ? findParagraphById3(part.xml, at.start.blockId) : null;
329485
330346
  if (wholeBlocks.kind === "ok") {
329486
330347
  const selectedXml = part.xml.slice(wholeBlocks.start, wholeBlocks.end);
329487
330348
  const wrapped = replaceSdtContentInTemplate(sdtXml, buildInnerXml(selectedXml));
329488
- nextXml = replaceRange2(part.xml, wholeBlocks.start, wholeBlocks.end, wrapped);
330349
+ nextXml = replaceRange3(part.xml, wholeBlocks.start, wholeBlocks.end, wrapped);
329489
330350
  targetBlockIds2 = wholeBlocks.blockIds;
329490
330351
  } else if (anchor && at.start.kind === "text" && at.end.kind === "text" && at.start.offset !== at.end.offset && input.content === undefined && input.html === undefined && input.json === undefined) {
329491
330352
  const splitMarker = "<sd-content-control-split/>";
@@ -329526,7 +330387,7 @@ class V2ContentControlsAdapter {
329526
330387
  });
329527
330388
  if (!prepared.ok)
329528
330389
  return { success: false, failure: prepared.failure };
329529
- nextXml = replaceRange2(part.xml, anchor.start, anchor.end, prepared.xml);
330390
+ nextXml = replaceRange3(part.xml, anchor.start, anchor.end, prepared.xml);
329530
330391
  createRefOptions = {
329531
330392
  createdRefs: prepared.wordIds.map((entityId) => ({
329532
330393
  kind: "trackedChange",
@@ -329535,7 +330396,7 @@ class V2ContentControlsAdapter {
329535
330396
  }))
329536
330397
  };
329537
330398
  } else {
329538
- nextXml = replaceRange2(part.xml, anchor.start, anchor.end, replacementXml);
330399
+ nextXml = replaceRange3(part.xml, anchor.start, anchor.end, replacementXml);
329539
330400
  }
329540
330401
  targetBlockIds2 = [at.start.blockId];
329541
330402
  } else {
@@ -329680,7 +330541,7 @@ class V2ContentControlsAdapter {
329680
330541
  const preview = this.validateDryRun(input, options, control.target);
329681
330542
  return preview.success ? { ...preview, updatedRef } : preview;
329682
330543
  }
329683
- const nextXml = replaceRange2(loaded.documentXml, control.start, control.end, wrapper);
330544
+ const nextXml = replaceRange3(loaded.documentXml, control.start, control.end, wrapper);
329684
330545
  return this.commitDocument(nextXml, "content-control-wrap", input, options, control.target, {
329685
330546
  updatedRef,
329686
330547
  createdRefs,
@@ -329797,7 +330658,7 @@ class V2ContentControlsAdapter {
329797
330658
  const updatedRef = { ...source.target, nodeId: clone3.rootId };
329798
330659
  if (dryRunRequested(input, options))
329799
330660
  return { success: true, contentControl: source.target, updatedRef };
329800
- const withSource = replaceRange2(loaded.documentXml, source.start, source.end, prepared.sourceXml);
330661
+ const withSource = replaceRange3(loaded.documentXml, source.start, source.end, prepared.sourceXml);
329801
330662
  const offset = destination.offset >= source.end ? destination.offset + prepared.sourceXml.length - source.xml.length : destination.offset;
329802
330663
  const xml2 = withSource.slice(0, offset) + prepared.destinationXml + withSource.slice(offset);
329803
330664
  return this.commitDocument(xml2, "content-control-move", input, options, source.target, {
@@ -329807,7 +330668,7 @@ class V2ContentControlsAdapter {
329807
330668
  }
329808
330669
  if (dryRunRequested(input, options))
329809
330670
  return { success: true, contentControl: source.target };
329810
- let xml = replaceRange2(loaded.documentXml, source.start, source.end, "");
330671
+ let xml = replaceRange3(loaded.documentXml, source.start, source.end, "");
329811
330672
  const adjustedOffset = destination.offset >= source.end ? destination.offset - (source.end - source.start) : destination.offset;
329812
330673
  const movedXml = destination.wrapInlineInParagraph && source.info.kind === "inline" ? buildParaIdParagraphXml(createParaIdAllocator(this.context)(), source.xml) : source.xml;
329813
330674
  xml = `${xml.slice(0, adjustedOffset)}${movedXml}${xml.slice(adjustedOffset)}`;
@@ -329833,7 +330694,7 @@ class V2ContentControlsAdapter {
329833
330694
  const destinationXml = rewriteContentControlMoveDestinationXml(source.xml, destinationId, createParaIdAllocator(this.context));
329834
330695
  const sourceSideXml = wrapMoveSourceBlock(source.xml, stamp);
329835
330696
  const destinationSideXml = wrapMoveDestinationBlock(destinationXml, stamp);
329836
- const withSource = replaceRange2(loaded.documentXml, source.start, source.end, sourceSideXml);
330697
+ const withSource = replaceRange3(loaded.documentXml, source.start, source.end, sourceSideXml);
329837
330698
  const inserted = insertAfterExactlyOnce(withSource, destination.xml, destinationSideXml);
329838
330699
  if (!inserted.ok) {
329839
330700
  return { success: false, failure: { code: "INTERNAL_ERROR", message: inserted.message } };
@@ -329860,7 +330721,7 @@ class V2ContentControlsAdapter {
329860
330721
  }
329861
330722
  moveToParagraphCaret(input, options, loaded, source) {
329862
330723
  const blockId = typeof input.destination?.target?.nodeId === "string" ? input.destination.target.nodeId : "";
329863
- const anchor = findParagraphById2(loaded.documentXml, blockId);
330724
+ const anchor = findParagraphById3(loaded.documentXml, blockId);
329864
330725
  if (!anchor) {
329865
330726
  return {
329866
330727
  success: false,
@@ -329885,7 +330746,7 @@ class V2ContentControlsAdapter {
329885
330746
  requestedOffset = Math.max(beforeSource, requestedOffset - sourceVisible);
329886
330747
  }
329887
330748
  if (source.info.kind === "inline") {
329888
- const preview = findParagraphById2(replaceRange2(loaded.documentXml, source.start, source.end, ""), blockId);
330749
+ const preview = findParagraphById3(replaceRange3(loaded.documentXml, source.start, source.end, ""), blockId);
329889
330750
  if (!preview || spliceXmlAtVisibleOffset(preview.xml, requestedOffset, source.xml).kind === "shared-run") {
329890
330751
  return { success: false, failure: {
329891
330752
  code: "CAPABILITY_UNAVAILABLE",
@@ -329926,8 +330787,8 @@ class V2ContentControlsAdapter {
329926
330787
  }
329927
330788
  if (dryRunRequested(input, options))
329928
330789
  return { success: true, contentControl: source.target, updatedRef: commitOptions.updatedRef };
329929
- const withoutSource = replaceRange2(loaded.documentXml, source.start, source.end, sourceReplacement);
329930
- const para = findParagraphById2(withoutSource, blockId);
330790
+ const withoutSource = replaceRange3(loaded.documentXml, source.start, source.end, sourceReplacement);
330791
+ const para = findParagraphById3(withoutSource, blockId);
329931
330792
  if (!para) {
329932
330793
  return {
329933
330794
  success: false,
@@ -329947,7 +330808,7 @@ class V2ContentControlsAdapter {
329947
330808
  };
329948
330809
  }
329949
330810
  const updatedPara = spliced.kind === "ok" ? spliced.xml : insertXmlIntoParagraphContent(para.xml, destinationXml);
329950
- nextXml = replaceRange2(withoutSource, para.start, para.end, updatedPara);
330811
+ nextXml = replaceRange3(withoutSource, para.start, para.end, updatedPara);
329951
330812
  } else {
329952
330813
  const insertBefore = requestedOffset === 0 && extractVisibleTextFromXml2(para.xml).trim().length > 0;
329953
330814
  nextXml = insertBefore ? `${withoutSource.slice(0, para.start)}${destinationXml}${withoutSource.slice(para.start)}` : `${withoutSource.slice(0, para.end)}${destinationXml}${withoutSource.slice(para.end)}`;
@@ -330037,7 +330898,7 @@ class V2ContentControlsAdapter {
330037
330898
  return { success: false, failure: replacement.failure };
330038
330899
  if (dryRunRequested(input, options))
330039
330900
  return this.validateDryRun(input, options, control.target);
330040
- const nextXml2 = replaceRange2(part.xml, control.start, control.end, replaceSdtContentXml(control, replacement.xml));
330901
+ const nextXml2 = replaceRange3(part.xml, control.start, control.end, replaceSdtContentXml(control, replacement.xml));
330041
330902
  return this.commitDocument(nextXml2, "content-control-replace-content", input, options, control.target, {
330042
330903
  partUri: part.partUri,
330043
330904
  storySurface: { family: "storyBlocks", contentControlRewrite: true, targetBlockIds: [] },
@@ -330051,7 +330912,7 @@ class V2ContentControlsAdapter {
330051
330912
  }
330052
330913
  if (dryRunRequested(input, options))
330053
330914
  return this.validateDryRun(input, options, control.target);
330054
- const nextXml = replaceRange2(part.xml, control.start, control.end, replaceSdtContentXml(control, contentXml));
330915
+ const nextXml = replaceRange3(part.xml, control.start, control.end, replaceSdtContentXml(control, contentXml));
330055
330916
  return this.commitDocument(nextXml, "content-control-replace-content", input, options, control.target, {
330056
330917
  partUri: part.partUri,
330057
330918
  storySurface: { family: "storyBlocks", contentControlRewrite: true, targetBlockIds: [] },
@@ -330109,7 +330970,7 @@ class V2ContentControlsAdapter {
330109
330970
  if (at.start.kind !== "text" || at.end.kind !== "text" || at.start.blockId !== at.end.blockId) {
330110
330971
  throw operationError("CAPABILITY_UNAVAILABLE", "Content-control creation requires a selection within one paragraph.");
330111
330972
  }
330112
- const paragraph4 = findParagraphById2(part.xml, at.start.blockId);
330973
+ const paragraph4 = findParagraphById3(part.xml, at.start.blockId);
330113
330974
  if (!paragraph4)
330114
330975
  throw operationError("TARGET_NOT_FOUND", `Paragraph ${at.start.blockId} was not found in the target story.`);
330115
330976
  if (![at.start.offset, at.end.offset].every((offset) => Number.isInteger(offset) && offset >= 0 && offset <= parseParagraphInlineMap(paragraph4.xml).visibleLength) || at.start.offset > at.end.offset) {
@@ -330142,7 +331003,7 @@ class V2ContentControlsAdapter {
330142
331003
  return this.validateDryRun(input, options, control.target);
330143
331004
  const part = loaded.parts.find((candidate2) => candidate2.storyId === control.storyId);
330144
331005
  const replacement = replaceSdtContentXml(control, buildTextReplacementContentXml(value2, control.info.kind, createParaIdAllocator(this.context), control.contentXml, false));
330145
- const nextXml = replaceRange2(part.xml, control.start, control.end, replacement);
331006
+ const nextXml = replaceRange3(part.xml, control.start, control.end, replacement);
330146
331007
  return this.commitDocument(nextXml, "content-control-replace-content", input, options, control.target, {
330147
331008
  partUri: part.partUri,
330148
331009
  storySurface: { family: "storyBlocks", contentControlRewrite: true, targetBlockIds: [] },
@@ -330182,7 +331043,7 @@ class V2ContentControlsAdapter {
330182
331043
  createdRefs: [{ kind: "trackedChange", entityId: String(stamp.revisionId), storyId: body.storyId }]
330183
331044
  };
330184
331045
  }
330185
- const nextXml = replaceRange2(loaded.documentXml, control.start, control.end, replacement);
331046
+ const nextXml = replaceRange3(loaded.documentXml, control.start, control.end, replacement);
330186
331047
  return this.commitDocument(nextXml, "content-control-pr", input, options, control.target, commitOptions);
330187
331048
  }
330188
331049
  setChoiceListItems(input, options) {
@@ -330404,7 +331265,7 @@ class V2ContentControlsAdapter {
330404
331265
  replacement = prepared.xml;
330405
331266
  createdRefs = prepared.wordIds.map((entityId) => ({ kind: "trackedChange", entityId, storyId: control.storyId }));
330406
331267
  }
330407
- const nextXml = replaceRange2(part.xml, control.start, control.end, replacement);
331268
+ const nextXml = replaceRange3(part.xml, control.start, control.end, replacement);
330408
331269
  return this.commitDocument(nextXml, prefix, input, options, control.target, {
330409
331270
  partUri: part.partUri,
330410
331271
  storySurface: { family: "storyBlocks", contentControlRewrite: true, targetBlockIds: [] },
@@ -330451,7 +331312,7 @@ class V2ContentControlsAdapter {
330451
331312
  const replacement = !anchor || insertIndex <= 0 ? replaceSdtContentXml(control, `${item}${control.contentXml}`) : `${control.xml.slice(0, anchor.end - control.start)}${item}${control.xml.slice(anchor.end - control.start)}`;
330452
331313
  if (dryRunRequested(input, options))
330453
331314
  return { success: true, contentControl: target };
330454
- const nextXml = replaceRange2(loaded.documentXml, control.start, control.end, replacement);
331315
+ const nextXml = replaceRange3(loaded.documentXml, control.start, control.end, replacement);
330455
331316
  return this.commitDocument(nextXml, "content-control-repeat-insert", input, options, target, { createdRefs });
330456
331317
  }
330457
331318
  cloneRepeatingItem(input, options) {
@@ -330495,13 +331356,13 @@ class V2ContentControlsAdapter {
330495
331356
  return this.validateDryRun(input, options, control.target);
330496
331357
  const localEnd = item.end - control.start;
330497
331358
  const replacement = `${control.xml.slice(0, localEnd)}${clone3}${control.xml.slice(localEnd)}`;
330498
- const nextXml = replaceRange2(loaded.documentXml, control.start, control.end, replacement);
331359
+ const nextXml = replaceRange3(loaded.documentXml, control.start, control.end, replacement);
330499
331360
  return this.commitDocument(nextXml, "content-control-repeat-clone", input, options, control.target, { createdRefs });
330500
331361
  }
330501
331362
  deleteRepeatingItem(input, options) {
330502
331363
  return this.mutateControl(input.target, input, options, (control, loaded) => {
330503
331364
  const item = this.repeatingItems(control, loaded)[input.index];
330504
- return replaceRange2(control.xml, item.start - control.start, item.end - control.start, "");
331365
+ return replaceRange3(control.xml, item.start - control.start, item.end - control.start, "");
330505
331366
  }, "content-control-repeat-delete", (control, loaded) => {
330506
331367
  if (control.info.controlType !== "repeatingSection") {
330507
331368
  throw operationError("INVALID_TARGET", "contentControls.repeatingSection operation requires control type repeatingSection.");
@@ -331770,7 +332631,7 @@ function unwrapSdtXml(sdtXml) {
331770
332631
  const contentRange = findDirectSdtChildRange(sdtXml, "sdtContent");
331771
332632
  return contentRange ? sdtXml.slice(contentRange.openEnd, contentRange.closeStart) : "";
331772
332633
  }
331773
- function replaceRange2(xml, start, end, replacement) {
332634
+ function replaceRange3(xml, start, end, replacement) {
331774
332635
  return `${xml.slice(0, start)}${replacement}${xml.slice(end)}`;
331775
332636
  }
331776
332637
  function resolveContentControlMoveDestination(loaded, destination) {
@@ -332312,7 +333173,7 @@ function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacem
332312
333173
  if (target?.kind !== "selection" || target.start?.kind !== "text" || target.end?.kind !== "text") {
332313
333174
  return { ok: false, failure: { code: "INVALID_TARGET", message: "A text selection is required." } };
332314
333175
  }
332315
- const para = findParagraphById2(documentXml, target.start.blockId);
333176
+ const para = findParagraphById3(documentXml, target.start.blockId);
332316
333177
  if (!para)
332317
333178
  return { ok: false, failure: { code: "TARGET_NOT_FOUND", message: "Target paragraph was not found." } };
332318
333179
  if (kind === "inline" && target.start.offset === target.end.offset) {
@@ -332329,12 +333190,12 @@ function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacem
332329
333190
  const insertXml = replaceSdtContentInTemplate(sdtXml, buildReplacementContentXml2(hasReplacementContent ? replacementContent : ""));
332330
333191
  const spliced = spliceXmlAtVisibleOffset(para.xml, target.start.offset, insertXml);
332331
333192
  if (spliced.kind === "ok") {
332332
- return { ok: true, xml: replaceRange2(documentXml, para.start, para.end, spliced.xml) };
333193
+ return { ok: true, xml: replaceRange3(documentXml, para.start, para.end, spliced.xml) };
332333
333194
  }
332334
333195
  if (spliced.kind === "empty") {
332335
333196
  return {
332336
333197
  ok: true,
332337
- xml: replaceRange2(documentXml, para.start, para.end, insertXmlIntoParagraphContent(para.xml, insertXml))
333198
+ xml: replaceRange3(documentXml, para.start, para.end, insertXmlIntoParagraphContent(para.xml, insertXml))
332338
333199
  };
332339
333200
  }
332340
333201
  return {
@@ -332364,7 +333225,7 @@ function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacem
332364
333225
  close: template.close
332365
333226
  });
332366
333227
  if (wrappedRuns.ok) {
332367
- return { ok: true, xml: replaceRange2(documentXml, para.start, para.end, wrappedRuns.xml) };
333228
+ return { ok: true, xml: replaceRange3(documentXml, para.start, para.end, wrappedRuns.xml) };
332368
333229
  }
332369
333230
  return { ok: false, failure: { code: "CAPABILITY_UNAVAILABLE", message: "Content-control selection spans unsupported inline structures." } };
332370
333231
  }
@@ -332376,7 +333237,7 @@ function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacem
332376
333237
  replacementXml: replaceSdtContentInTemplate(sdtXml, buildReplacementContentXml2(replacementContent))
332377
333238
  });
332378
333239
  if (replaced.ok) {
332379
- return { ok: true, xml: replaceRange2(documentXml, para.start, para.end, replaced.xml) };
333240
+ return { ok: true, xml: replaceRange3(documentXml, para.start, para.end, replaced.xml) };
332380
333241
  }
332381
333242
  return {
332382
333243
  ok: false,
@@ -332392,7 +333253,7 @@ function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacem
332392
333253
  });
332393
333254
  if (wrapped === para.xml)
332394
333255
  return { ok: false, failure: { code: "CAPABILITY_UNAVAILABLE", message: "Content-control selection spans unsupported inline structures." } };
332395
- return { ok: true, xml: replaceRange2(documentXml, para.start, para.end, wrapped) };
333256
+ return { ok: true, xml: replaceRange3(documentXml, para.start, para.end, wrapped) };
332396
333257
  }
332397
333258
  function splitSdtTemplateAroundContent(sdtXml) {
332398
333259
  const sdtRange = findFirstSdtElementRange(sdtXml);
@@ -332416,7 +333277,7 @@ function insertBlockContentControlAtSelection(documentXml, paragraphs, target, s
332416
333277
  throw operationError("TARGET_NOT_FOUND", "Target paragraph was not found.");
332417
333278
  const collapsed = target.start.blockId === target.end.blockId && target.start.offset === target.end.offset;
332418
333279
  if (collapsed && extractVisibleTextFromXml2(anchor.xml).trim().length === 0) {
332419
- return replaceRange2(documentXml, anchor.start, anchor.end, sdtXml);
333280
+ return replaceRange3(documentXml, anchor.start, anchor.end, sdtXml);
332420
333281
  }
332421
333282
  return `${documentXml.slice(0, anchor.end)}${sdtXml}${documentXml.slice(anchor.end)}`;
332422
333283
  }
@@ -332545,7 +333406,7 @@ function findFirstSdtElementRange(xml) {
332545
333406
  }
332546
333407
  return null;
332547
333408
  }
332548
- function findParagraphById2(documentXml, blockId) {
333409
+ function findParagraphById3(documentXml, blockId) {
332549
333410
  const paraRe = /<w:p\b[^>]*?(?:\/>|>[\s\S]*?<\/w:p>)/g;
332550
333411
  for (let match = paraRe.exec(documentXml);match; match = paraRe.exec(documentXml)) {
332551
333412
  if (match[0].includes(`w14:paraId="${blockId}"`)) {
@@ -332659,7 +333520,7 @@ function replaceTextRangeInParagraph2(paragraphXml, start, end, replacement) {
332659
333520
  return paragraphXml;
332660
333521
  }
332661
333522
  var DEFAULT_CHECKED, DEFAULT_UNCHECKED, SECONDARY_STORY_MUTATION_MESSAGE = "Content control mutations outside the document body are not supported by this adapter.", TYPE_TAGS, COOPERATIVE_PARSE_SLICE_PARAGRAPHS = 128, COOPERATIVE_PARSE_SLICE_CONTROLS = 16, RAW_ATTRIBUTE_PATTERN;
332662
- var init_adapter12 = __esm(() => {
333523
+ var init_adapter13 = __esm(() => {
332663
333524
  init_sd_document_session_internal();
332664
333525
  init_src6();
332665
333526
  init_part();
@@ -332836,7 +333697,7 @@ var init_tracked_regeneration = __esm(() => {
332836
333697
  init_tracked_pr_change();
332837
333698
  init_runtime2();
332838
333699
  init_xml();
332839
- init_adapter13();
333700
+ init_adapter14();
332840
333701
  });
332841
333702
 
332842
333703
  // ../../../v2/document-api-v2-adapter/dist/captions/tracked-commit.js
@@ -333136,8 +333997,8 @@ var nativeStamp = (stamp) => ({
333136
333997
  });
333137
333998
  var init_tracked_generated_paragraph = __esm(() => {
333138
333999
  init_sd_document_session_internal();
333139
- init_adapter15();
333140
334000
  init_adapter16();
334001
+ init_adapter17();
333141
334002
  init_tracked_commit();
333142
334003
  init_tracked_paragraph();
333143
334004
  init_paragraph_ids();
@@ -334028,7 +334889,7 @@ function operationError5(code2, message) {
334028
334889
  return error48;
334029
334890
  }
334030
334891
  var EMPTY_TOC_CONTEXT_AT_SELECTION, TOC_CONFIGURABLE_SWITCH_FLAGS, TOC_SWITCH_FRAGMENT_RE;
334031
- var init_adapter13 = __esm(() => {
334892
+ var init_adapter14 = __esm(() => {
334032
334893
  init_tracked_regeneration();
334033
334894
  init_removal();
334034
334895
  init_deletion_locks();
@@ -334205,7 +335066,7 @@ var init_tracked_creation = __esm(() => {
334205
335066
  init_tracked_pr_change();
334206
335067
  init_runtime2();
334207
335068
  init_xml();
334208
- init_adapter13();
335069
+ init_adapter14();
334209
335070
  });
334210
335071
 
334211
335072
  // ../../../v2/document-api-v2-adapter/dist/sections/adapter.js
@@ -334719,7 +335580,7 @@ function documentFailure(message, code2 = "CAPABILITY_UNAVAILABLE") {
334719
335580
  return { success: false, failure: { code: code2, message } };
334720
335581
  }
334721
335582
  var VALID_BREAK_TYPES, VALID_PAGE_NUMBER_FORMATS, VALID_LINE_NUMBER_RESTARTS, VALID_VERTICAL_ALIGNS, VALID_PAGE_BORDER_DISPLAYS, VALID_PAGE_BORDER_OFFSETS, VALID_PAGE_BORDER_Z_ORDERS;
334722
- var init_adapter14 = __esm(() => {
335583
+ var init_adapter15 = __esm(() => {
334723
335584
  init_src3();
334724
335585
  init_sd_document_session_internal();
334725
335586
  init_document_reader();
@@ -335849,20 +336710,20 @@ function storyErrorMessage3(error48) {
335849
336710
  }
335850
336711
  }
335851
336712
  var VALUED_TOC_SWITCHES;
335852
- var init_adapter15 = __esm(() => {
336713
+ var init_adapter16 = __esm(() => {
335853
336714
  init_sd_document_session_internal();
335854
336715
  init_sd_document_session_internal();
335855
336716
  init_materialize_slot();
335856
- init_adapter12();
336717
+ init_adapter13();
335857
336718
  init_adapter();
335858
336719
  init_runtime2();
335859
336720
  init_xml();
335860
336721
  init_section_xml();
335861
- init_adapter9();
336722
+ init_adapter10();
335862
336723
  init_xml3();
335863
- init_adapter13();
335864
- init_tracked_creation();
335865
336724
  init_adapter14();
336725
+ init_tracked_creation();
336726
+ init_adapter15();
335866
336727
  init_note_story();
335867
336728
  init_textbox_story();
335868
336729
  init_src6();
@@ -336522,11 +337383,11 @@ function operationError6(code2, message) {
336522
337383
  error48.code = code2;
336523
337384
  return error48;
336524
337385
  }
336525
- var init_adapter16 = __esm(() => {
337386
+ var init_adapter17 = __esm(() => {
336526
337387
  init_src3();
336527
337388
  init_sd_document_session_internal();
336528
337389
  init_document_reader();
336529
- init_adapter15();
337390
+ init_adapter16();
336530
337391
  init_composite();
336531
337392
  init_paragraph_ids();
336532
337393
  init_xml();
@@ -346236,7 +347097,7 @@ function commitTrackedImageCaption(context, change, options) {
346236
347097
  });
346237
347098
  }
346238
347099
  var init_tracked_caption = __esm(() => {
346239
- init_adapter16();
347100
+ init_adapter17();
346240
347101
  init_tracked_commit();
346241
347102
  init_tracked_paragraph();
346242
347103
  init_paragraph_ids();
@@ -350148,7 +351009,7 @@ function escapeRegExp17(value2) {
350148
351009
  return value2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
350149
351010
  }
350150
351011
  var IMAGE_HYPERLINK_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", EMU_PER_PX5 = 9525, CROP_SCALE2 = 1000, DEFAULT_FLOATING_RELATIVE_HEIGHT = 251659264, DECORATIVE_EXT_URI = "{C183D7F6-B498-43B3-948B-1728B52AA6E4}", DECORATIVE_NAMESPACE = "http://schemas.microsoft.com/office/drawing/2017/decorative", DRAWING_NAMESPACE = "http://schemas.openxmlformats.org/drawingml/2006/main", RELATIONSHIP_NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", CONVERTED_INLINE_ANCHORS, DEFAULT_PAGE_WIDTH_TWIPS2 = 12240, DEFAULT_PAGE_MARGIN_TWIPS2 = 1440, TWIPS_PER_PX = 15;
350151
- var init_adapter17 = __esm(() => {
351012
+ var init_adapter18 = __esm(() => {
350152
351013
  init_pending_image_insertion();
350153
351014
  init_src3();
350154
351015
  init_sd_document_session_internal();
@@ -350165,7 +351026,7 @@ var init_adapter17 = __esm(() => {
350165
351026
  init_receipt_entities();
350166
351027
  init_xml_rewrite();
350167
351028
  init_public_model();
350168
- init_adapter15();
351029
+ init_adapter16();
350169
351030
  init_adapter3();
350170
351031
  init_runtime2();
350171
351032
  init_tracked_caption();
@@ -350439,7 +351300,7 @@ function projectOperationCapabilities(context) {
350439
351300
  return out;
350440
351301
  }
350441
351302
  var V2_SUPPORTED_STEP_OPS, V2_SUPPORTED_NON_UNIFORM_STRATEGIES, V2_SUPPORTED_SET_MARKS, V2_REGEX_LIMITS;
350442
- var init_adapter18 = __esm(() => {
351303
+ var init_adapter19 = __esm(() => {
350443
351304
  init_src3();
350444
351305
  init_search();
350445
351306
  init_support_contract();
@@ -350448,8 +351309,8 @@ var init_adapter18 = __esm(() => {
350448
351309
  init_rich_fragment_apply();
350449
351310
  init_digest();
350450
351311
  init_registry3();
350451
- init_adapter17();
350452
- init_adapter9();
351312
+ init_adapter18();
351313
+ init_adapter10();
350453
351314
  V2_SUPPORTED_STEP_OPS = MUTATION_PLAN_SUPPORTED_STEP_OPS;
350454
351315
  V2_SUPPORTED_NON_UNIFORM_STRATEGIES = Object.freeze([]);
350455
351316
  V2_SUPPORTED_SET_MARKS = Object.freeze([]);
@@ -351072,10 +351933,10 @@ function operationError8(code2, message) {
351072
351933
  error48.code = code2;
351073
351934
  return error48;
351074
351935
  }
351075
- var init_adapter19 = __esm(() => {
351936
+ var init_adapter20 = __esm(() => {
351076
351937
  init_src3();
351077
351938
  init_sd_document_session_internal();
351078
- init_adapter15();
351939
+ init_adapter16();
351079
351940
  init_adapter8();
351080
351941
  init_tracked_generated_paragraph();
351081
351942
  init_tracked_pr_change();
@@ -353371,7 +354232,7 @@ class V2CommentsAdapter {
353371
354232
  function notImplemented(message) {
353372
354233
  return { success: false, failure: { code: "CAPABILITY_UNAVAILABLE", message } };
353373
354234
  }
353374
- var init_adapter20 = __esm(() => {
354235
+ var init_adapter21 = __esm(() => {
353375
354236
  init_create2();
353376
354237
  init_edit();
353377
354238
  init_move();
@@ -353660,7 +354521,7 @@ function operationError9(code2, message) {
353660
354521
  error48.code = code2;
353661
354522
  return error48;
353662
354523
  }
353663
- var init_adapter21 = __esm(() => {
354524
+ var init_adapter22 = __esm(() => {
353664
354525
  init_src3();
353665
354526
  init_adapter8();
353666
354527
  init_inline();
@@ -354402,7 +355263,7 @@ var TD99, TE56, SETTINGS_PART_URI4 = "/word/settings.xml", WORDPROCESSINGML_NS3
354402
355263
  var init_definitions = __esm(() => {
354403
355264
  init_src2();
354404
355265
  init_sd_document_session_internal();
354405
- init_adapter14();
355266
+ init_adapter15();
354406
355267
  init_part();
354407
355268
  TD99 = new TextDecoder("utf-8", { fatal: false });
354408
355269
  TE56 = new TextEncoder;
@@ -356265,13 +357126,13 @@ function recordWhole(overlapsByFragment, entry, logical) {
356265
357126
  });
356266
357127
  }
356267
357128
  function normalizeNestedOverlaps(overlapsByFragment, rangeByFragment) {
356268
- const overlaps = Array.from(overlapsByFragment.values());
357129
+ const overlaps2 = Array.from(overlapsByFragment.values());
356269
357130
  const remove = new Set;
356270
- for (const parent of overlaps) {
357131
+ for (const parent of overlaps2) {
356271
357132
  const parentRange = rangeByFragment.get(fragmentKey(parent.fragment));
356272
357133
  if (!parentRange || parent.coverage !== "partial")
356273
357134
  continue;
356274
- for (const child of overlaps) {
357135
+ for (const child of overlaps2) {
356275
357136
  if (child === parent)
356276
357137
  continue;
356277
357138
  const childRange = rangeByFragment.get(fragmentKey(child.fragment));
@@ -356296,7 +357157,7 @@ function normalizeNestedOverlaps(overlapsByFragment, rangeByFragment) {
356296
357157
  }
356297
357158
  return {
356298
357159
  ok: true,
356299
- overlaps: overlaps.filter((overlap) => !remove.has(fragmentKey(overlap.fragment)))
357160
+ overlaps: overlaps2.filter((overlap) => !remove.has(fragmentKey(overlap.fragment)))
356300
357161
  };
356301
357162
  }
356302
357163
  function fragmentKey(fragment3) {
@@ -357399,12 +358260,12 @@ function pushTextTarget(targets, seen, target) {
357399
358260
  seen.add(key2);
357400
358261
  targets.push(target);
357401
358262
  }
357402
- function shouldExpandWholePairedReplacementSide(overlap, overlaps) {
358263
+ function shouldExpandWholePairedReplacementSide(overlap, overlaps2) {
357403
358264
  const logical = overlap.logical;
357404
358265
  if (overlap.coverage !== "whole" || !logical || logical.type !== "replacement" || !logical.sides?.inserted || !logical.sides.deleted) {
357405
358266
  return false;
357406
358267
  }
357407
- const sameLogicalOverlaps = overlaps.filter((candidate2) => candidate2.logical?.id === logical.id);
358268
+ const sameLogicalOverlaps = overlaps2.filter((candidate2) => candidate2.logical?.id === logical.id);
357408
358269
  return !sameLogicalOverlaps.some((candidate2) => candidate2.coverage === "partial");
357409
358270
  }
357410
358271
  function isLogicalRangeDecideTarget(target) {
@@ -358159,7 +359020,7 @@ function extractStructuralCellTexts(xml, side) {
358159
359020
  }
358160
359021
  function extractStructuralText(xml, side) {
358161
359022
  const readText = side === "deleted" ? extractTrackedTextFromXml : extractVisibleTextFromXml2;
358162
- const paragraphs = scanParagraphXmlSpans({ bytes: TEXT_ENCODER.encode(xml) });
359023
+ const paragraphs = scanParagraphXmlSpans({ bytes: TEXT_ENCODER2.encode(xml) });
358163
359024
  if (paragraphs.length === 0)
358164
359025
  return readText(xml);
358165
359026
  return paragraphs.map((paragraph4) => readText(paragraph4.xml).trim()).filter(Boolean).join(`
@@ -358734,8 +359595,8 @@ function structuralFieldSemanticSubtype(entry, context, resolveSession) {
358734
359595
  if (!partBytes)
358735
359596
  return null;
358736
359597
  const partXml = decodeTrackedChangePartXml(partBytes, entry.partUri, resolveSession);
358737
- const entryByteStart = TEXT_ENCODER.encode(partXml.slice(0, entry.documentOrderStart)).byteLength;
358738
- const entryByteEnd = TEXT_ENCODER.encode(partXml.slice(0, entry.documentOrderEnd)).byteLength;
359598
+ const entryByteStart = TEXT_ENCODER2.encode(partXml.slice(0, entry.documentOrderStart)).byteLength;
359599
+ const entryByteEnd = TEXT_ENCODER2.encode(partXml.slice(0, entry.documentOrderEnd)).byteLength;
358739
359600
  const fields = catalog.fields.filter((candidate2) => candidate2.complete && candidate2.byteStart >= entryByteStart && candidate2.byteEnd <= entryByteEnd);
358740
359601
  const field = fields.length === 1 ? fields[0] : undefined;
358741
359602
  const subtype = field && field.classification !== "unknown" ? field.classification : null;
@@ -359070,8 +359931,8 @@ function createSuccessorRsidAllocator(raw) {
359070
359931
  return counter.toString(16).toUpperCase().padStart(8, "0");
359071
359932
  };
359072
359933
  }
359073
- var resolvedTrackedChangeIdsBySession, TEXT_ENCODER, EMUS_PER_CSS_PIXEL = 9525, BROWSER_RENDERABLE_IMAGE_CONTENT_TYPES, DocumentApiAdapterError, STRUCTURAL_DESCRIPTOR_OPERATIONS;
359074
- var init_adapter22 = __esm(() => {
359934
+ var resolvedTrackedChangeIdsBySession, TEXT_ENCODER2, EMUS_PER_CSS_PIXEL = 9525, BROWSER_RENDERABLE_IMAGE_CONTENT_TYPES, DocumentApiAdapterError, STRUCTURAL_DESCRIPTOR_OPERATIONS;
359935
+ var init_adapter23 = __esm(() => {
359075
359936
  init_review_read_model();
359076
359937
  init_review_read_model();
359077
359938
  init_src3();
@@ -359087,7 +359948,7 @@ var init_adapter22 = __esm(() => {
359087
359948
  init_logical_view_cache();
359088
359949
  init_local_text_projection();
359089
359950
  resolvedTrackedChangeIdsBySession = new WeakMap;
359090
- TEXT_ENCODER = new TextEncoder;
359951
+ TEXT_ENCODER2 = new TextEncoder;
359091
359952
  BROWSER_RENDERABLE_IMAGE_CONTENT_TYPES = new Map([
359092
359953
  ["png", "image/png"],
359093
359954
  ["jpg", "image/jpeg"],
@@ -361940,7 +362801,7 @@ var init_legacy_body = __esm(() => {
361940
362801
  init_src3();
361941
362802
  init_document_reader();
361942
362803
  init_adapter();
361943
- init_adapter22();
362804
+ init_adapter23();
361944
362805
  init_sd_document_session_internal();
361945
362806
  init_payloads();
361946
362807
  });
@@ -364798,13 +365659,13 @@ function stripRootReplayNamespaceDeclarations(xml) {
364798
365659
  return stripReplayNamespaceDeclarations(xml.slice(0, openEnd)) + xml.slice(openEnd);
364799
365660
  }
364800
365661
  var FULL_DIFF_APPLY_SUPPORTED_FAMILIES, TE65, TD109, DOCUMENT_PART_URI6 = "/word/document.xml", NUMBERING_PART_URI4 = "/word/numbering.xml", EMPTY_MAIN_DOCUMENT_SOURCE, WORDPROCESSINGML_NS7 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", WORDPROCESSINGML_2010_NS2 = "http://schemas.microsoft.com/office/word/2010/wordml", WORDPROCESSING_MATH_NS = "http://schemas.openxmlformats.org/officeDocument/2006/math", MARKUP_COMPATIBILITY_NS3 = "http://schemas.openxmlformats.org/markup-compatibility/2006", VML_NS = "urn:schemas-microsoft-com:vml", STRUCTURAL_PARA_EDIT_DELETE_WML_NAMES, STRUCTURAL_PARA_EDIT_DELETE_MATH_NAMES, STRUCTURAL_PARA_FORMAT_EDIT_WML_NAMES;
364801
- var init_adapter23 = __esm(() => {
365662
+ var init_adapter24 = __esm(() => {
364802
365663
  init_tracked_table_property_replay();
364803
365664
  init_src2();
364804
365665
  init_compare();
364805
365666
  init_sd_document_session_internal();
364806
365667
  init_section_xml();
364807
- init_adapter22();
365668
+ init_adapter23();
364808
365669
  init_header_footer_lifecycle();
364809
365670
  init_errors8();
364810
365671
  init_main_document_revision_closure();
@@ -364912,7 +365773,7 @@ class V2ExportAdapter {
364912
365773
  };
364913
365774
  }
364914
365775
  }
364915
- var init_adapter24 = __esm(() => {
365776
+ var init_adapter25 = __esm(() => {
364916
365777
  init_src3();
364917
365778
  init_sd_document_session_internal();
364918
365779
  });
@@ -365373,9 +366234,9 @@ function operationError10(code2, message) {
365373
366234
  error48.code = code2;
365374
366235
  return error48;
365375
366236
  }
365376
- var init_adapter25 = __esm(() => {
366237
+ var init_adapter26 = __esm(() => {
365377
366238
  init_src3();
365378
- init_adapter15();
366239
+ init_adapter16();
365379
366240
  init_adapter8();
365380
366241
  init_tracked_field_prefix();
365381
366242
  init_tracked_generated_paragraph();
@@ -370422,7 +371283,7 @@ function readCreatedParagraphRefId(createdRefs, provisionalToFinal) {
370422
371283
  return null;
370423
371284
  }
370424
371285
  var LISTS_XML_DECODER, BULLET_GLYPH_BY_LEVEL;
370425
- var init_adapter26 = __esm(() => {
371286
+ var init_adapter27 = __esm(() => {
370426
371287
  init_src3();
370427
371288
  init_sd_document_session_internal();
370428
371289
  init_adapter();
@@ -370430,7 +371291,7 @@ var init_adapter26 = __esm(() => {
370430
371291
  init_stories();
370431
371292
  init_text_range_shifts();
370432
371293
  init_adapter7();
370433
- init_adapter22();
371294
+ init_adapter23();
370434
371295
  init_tracked_pr_change();
370435
371296
  init_receipt_entities();
370436
371297
  init_runtime3();
@@ -370462,7 +371323,7 @@ class V2GetTextAdapter {
370462
371323
  }
370463
371324
  }
370464
371325
  var TD111, extractVisibleTextFromXml4;
370465
- var init_adapter27 = __esm(() => {
371326
+ var init_adapter28 = __esm(() => {
370466
371327
  init_sd_document_session_internal();
370467
371328
  init_story_identity();
370468
371329
  init_story_surface();
@@ -370770,7 +371631,7 @@ var init_node_discovery = __esm(() => {
370770
371631
  init_sd_document_session_internal();
370771
371632
  init_document_reader();
370772
371633
  init_paragraph();
370773
- init_adapter27();
371634
+ init_adapter28();
370774
371635
  init_note_story();
370775
371636
  init_textbox_story();
370776
371637
  init_within();
@@ -371809,7 +372670,7 @@ function txIdPrefixToOperation(prefix) {
371809
372670
  }
371810
372671
  }
371811
372672
  var TD113, TE67;
371812
- var init_adapter28 = __esm(() => {
372673
+ var init_adapter29 = __esm(() => {
371813
372674
  init_sd_document_session_internal();
371814
372675
  init_src6();
371815
372676
  init_materialize_slot();
@@ -373606,7 +374467,7 @@ var init_engine3 = __esm(() => {
373606
374467
  init_tracked_text_search();
373607
374468
  init_structural_rewrite_span();
373608
374469
  init_adapter7();
373609
- init_adapter28();
374470
+ init_adapter29();
373610
374471
  init_adapter6();
373611
374472
  init_composite();
373612
374473
  init_stories();
@@ -373628,7 +374489,7 @@ class V2MutationsAdapter {
373628
374489
  return applyPlan(this.context, input);
373629
374490
  }
373630
374491
  }
373631
- var init_adapter29 = __esm(() => {
374492
+ var init_adapter30 = __esm(() => {
373632
374493
  init_engine3();
373633
374494
  });
373634
374495
 
@@ -373762,7 +374623,7 @@ function deleteFailure(code2, message) {
373762
374623
  return { success: false, failure: { code: code2, message } };
373763
374624
  }
373764
374625
  var OPERATION_ID = "v2-textbox-geometry";
373765
- var init_adapter30 = __esm(() => {
374626
+ var init_adapter31 = __esm(() => {
373766
374627
  init_sd_document_session_internal();
373767
374628
  init_adapter();
373768
374629
  init_stories();
@@ -374299,7 +375160,7 @@ function containsOnlyZeroWidthReferenceTail(xml) {
374299
375160
  return normalized.length === 0;
374300
375161
  }
374301
375162
  var TD115;
374302
- var init_adapter31 = __esm(() => {
375163
+ var init_adapter32 = __esm(() => {
374303
375164
  init_sd_document_session_internal();
374304
375165
  init_materialize_slot();
374305
375166
  init_story_surface();
@@ -374855,9 +375716,9 @@ function operationError11(code2, message) {
374855
375716
  error48.code = code2;
374856
375717
  return error48;
374857
375718
  }
374858
- var init_adapter32 = __esm(() => {
375719
+ var init_adapter33 = __esm(() => {
374859
375720
  init_src3();
374860
- init_adapter15();
375721
+ init_adapter16();
374861
375722
  init_adapter8();
374862
375723
  init_tracked_field_prefix();
374863
375724
  init_tracked_generated_paragraph();
@@ -376195,7 +377056,7 @@ function defaultRelationshipsXml3() {
376195
377056
  return '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
376196
377057
  }
376197
377058
  var HYPERLINK_REL_TYPE3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", TD116, TE68;
376198
- var init_adapter33 = __esm(() => {
377059
+ var init_adapter34 = __esm(() => {
376199
377060
  init_sd_document_session_internal();
376200
377061
  init_inline();
376201
377062
  init_adapter();
@@ -376954,12 +377815,12 @@ function failure22(code2, message) {
376954
377815
  return { success: false, failure: { code: code2, message } };
376955
377816
  }
376956
377817
  var IMAGE_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", RELATIONSHIPS_CT2 = "application/vnd.openxmlformats-package.relationships+xml", EMPTY_RELATIONSHIPS_XML4, TD117;
376957
- var init_adapter34 = __esm(() => {
377818
+ var init_adapter35 = __esm(() => {
376958
377819
  init_src3();
376959
377820
  init_sd_document_session_internal();
376960
377821
  init_document_reader();
376961
377822
  init_adapter3();
376962
- init_adapter17();
377823
+ init_adapter18();
376963
377824
  init_public_model();
376964
377825
  init_section_xml();
376965
377826
  init_xml();
@@ -378037,7 +378898,7 @@ function structuredError4(code2, message) {
378037
378898
  return error48;
378038
378899
  }
378039
378900
  var W14_NS4 = "http://schemas.microsoft.com/office/word/2010/wordml", FOOTNOTES_PART_URI4 = "/word/footnotes.xml", ENDNOTES_PART_URI4 = "/word/endnotes.xml", FOOTNOTES_CT = "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", ENDNOTES_CT = "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml", FOOTNOTES_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes", ENDNOTES_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes";
378040
- var init_adapter35 = __esm(() => {
378901
+ var init_adapter36 = __esm(() => {
378041
378902
  init_src3();
378042
378903
  init_tracked_pr_change();
378043
378904
  init_tracked_structural_wrapper();
@@ -382013,7 +382874,7 @@ function isPasteReason(reason) {
382013
382874
  return !!reason && reason.startsWith("paste-");
382014
382875
  }
382015
382876
  var CLIPBOARD_TD;
382016
- var init_adapter36 = __esm(() => {
382877
+ var init_adapter37 = __esm(() => {
382017
382878
  init_src3();
382018
382879
  init_sd_document_session_internal();
382019
382880
  init_note_story();
@@ -382065,7 +382926,7 @@ class V2SelectionAdapter {
382065
382926
  };
382066
382927
  }
382067
382928
  }
382068
- var init_adapter37 = __esm(() => {
382929
+ var init_adapter38 = __esm(() => {
382069
382930
  init_sd_document_session_internal();
382070
382931
  });
382071
382932
 
@@ -382213,651 +383074,6 @@ var init_clear_content_adapter = __esm(() => {
382213
383074
  TE69 = new TextEncoder;
382214
383075
  });
382215
383076
 
382216
- // ../../../v2/document-api-v2-adapter/dist/metadata/adapter.js
382217
- class V2AnchoredMetadataAdapter {
382218
- constructor(context) {
382219
- this.context = context;
382220
- }
382221
- attach(input, options) {
382222
- const mutationGuard = guardDirectOnlyMutation(this.context, input, options);
382223
- if (mutationGuard)
382224
- return mutationGuard;
382225
- const id = input.id ?? newOpaqueId("metadata");
382226
- const existingRecords = listMetadataRecords(this.context);
382227
- if (existingRecords.some((record3) => record3.id === id)) {
382228
- throw operationError("INVALID_INPUT", `metadata id ${id} already exists.`);
382229
- }
382230
- const payloadJson = JSON.stringify(input.payload);
382231
- if (payloadJson === undefined)
382232
- throw operationError("INVALID_INPUT", "metadata payload must be JSON serializable.");
382233
- const documentXml = readDocumentXml(this.context);
382234
- if (findMetadataAnchor(documentXml, id)) {
382235
- throw operationError("INVALID_INPUT", `metadata id ${id} already exists.`);
382236
- }
382237
- const resolvedSegments = input.target.kind === "text" ? resolveMultiSegmentTarget(documentXml, input.target) : resolveSingleSegmentTarget(this.context, documentXml, input.target);
382238
- if ("error" in resolvedSegments)
382239
- throw operationError(resolvedSegments.error, resolvedSegments.message);
382240
- const knownIds = new Set(existingRecords.map((record3) => record3.id));
382241
- if (hasOverlappingMetadataAnchor(documentXml, resolvedSegments.segments, knownIds)) {
382242
- return failure2("INVALID_TARGET", "metadata.attach target overlaps an existing metadata anchor.");
382243
- }
382244
- const existingPart = ensureCustomXmlPartForNamespace(this.context, input.namespace);
382245
- const allocatedPart = existingPart ? null : allocateCustomXmlPartNames(this.context);
382246
- const partName = existingPart?.partName ?? allocatedPart.partName;
382247
- const partUri = existingPart?.partUri ?? allocatedPart.partUri;
382248
- const storageXml = existingPart?.content ?? buildMetadataStorageXml(input.namespace, []);
382249
- const refs = readMetadataRefs(storageXml, input.namespace);
382250
- refs.push({ id, payloadJson });
382251
- const nextStorageXml = buildMetadataStorageXml(input.namespace, refs);
382252
- const sdtIds = allocateMetadataSdtIds(documentXml, resolvedSegments.segments.length);
382253
- const bySegmentPosition = resolvedSegments.segments.map((segment, index2) => ({ segment, sdtId: sdtIds[index2] })).sort((a, b) => b.segment.para.start - a.segment.para.start);
382254
- let nextDocumentXml = documentXml;
382255
- for (const { segment, sdtId } of bySegmentPosition) {
382256
- const wrapped = wrapTextRangeWithMetadataSdt(segment.para.xml, segment.startOffset, segment.endOffset, id, sdtId);
382257
- if (!wrapped.ok)
382258
- throw metadataWrapRejectError(wrapped.reason);
382259
- nextDocumentXml = replaceRange3(nextDocumentXml, segment.para.start, segment.para.end, wrapped.xml);
382260
- }
382261
- if (!dryRunRequested(input, options)) {
382262
- nextDocumentXml = ensureW15Namespace(nextDocumentXml);
382263
- const updates = existingPart ? { [partUri]: encodeXml(nextStorageXml) } : buildCustomXmlCreateUpdates(this.context, {
382264
- id: newGuid(),
382265
- content: nextStorageXml,
382266
- partUri,
382267
- propsPartUri: allocatedPart.propsPartUri,
382268
- relsPartUri: allocatedPart.relsPartUri
382269
- });
382270
- updates[DOCUMENT_PART_URI5] = encodeXml(nextDocumentXml);
382271
- const committed = commitWholePartUpdates(this.context, "metadata-attach", updates, {
382272
- expectedRevision: expectedRevisionFrom(input, options),
382273
- storySurface: {
382274
- family: "storyAnchor",
382275
- targetBlockIds: resolvedSegments.segments.map((segment) => segment.blockId)
382276
- }
382277
- });
382278
- if (!committed.ok)
382279
- return { success: false, failure: { code: committed.code, message: committed.message } };
382280
- }
382281
- return { success: true, id, namespace: input.namespace, partName };
382282
- }
382283
- list(query3) {
382284
- let records = listMetadataRecords(this.context);
382285
- const recordCounts = new Map;
382286
- for (const record3 of records)
382287
- recordCounts.set(record3.id, (recordCounts.get(record3.id) ?? 0) + 1);
382288
- if (query3?.namespace !== undefined)
382289
- records = records.filter((record3) => record3.namespace === query3.namespace);
382290
- const documentXml = readDocumentXml(this.context);
382291
- if (query3?.resolvedOnly === true) {
382292
- records = records.filter((record3) => recordCounts.get(record3.id) === 1 && groupMetadataAnchor(documentXml, record3.id, new Set([record3.id])) !== null);
382293
- }
382294
- if (query3?.within !== undefined) {
382295
- records = records.filter((record3) => {
382296
- const resolved = this.resolve({ id: record3.id });
382297
- return resolved ? overlaps(query3.within, resolved.target) : false;
382298
- });
382299
- }
382300
- const page = pageSlice(records, query3);
382301
- return buildDiscoveryResult({
382302
- evaluatedRevision: this.context.currentPublicRevision(),
382303
- total: records.length,
382304
- items: page.items.map((record3) => buildDiscoveryItem(record3.id, buildResolvedHandle(`metadata:${record3.id}`, "stable", "ext:metadata"), metadataSummary(record3, documentXml))),
382305
- page: { offset: page.offset, limit: page.limit, returned: page.items.length }
382306
- });
382307
- }
382308
- get(input) {
382309
- const record3 = findMetadataRecord(this.context, input.id);
382310
- return record3 ? { ...metadataSummary(record3, readDocumentXml(this.context)), payload: record3.payload } : null;
382311
- }
382312
- update(input, options) {
382313
- const mutationGuard = guardDirectOnlyMutation(this.context, input, options);
382314
- if (mutationGuard)
382315
- return mutationGuard;
382316
- if (listMetadataRecords(this.context).filter((candidate2) => candidate2.id === input.id).length > 1) {
382317
- return failure2("INVALID_TARGET", `metadata ${input.id} has ambiguous payload records.`);
382318
- }
382319
- const record3 = findMetadataRecord(this.context, input.id);
382320
- if (!record3)
382321
- throw operationError("TARGET_NOT_FOUND", `metadata ${input.id} not found.`);
382322
- const payloadJson = JSON.stringify(input.payload);
382323
- if (payloadJson === undefined)
382324
- throw operationError("INVALID_INPUT", "metadata payload must be JSON serializable.");
382325
- if (dryRunRequested(input, options))
382326
- return { success: true, id: input.id };
382327
- const records = listMetadataRecords(this.context).filter((candidate2) => candidate2.partUri === record3.partUri);
382328
- const refs = records.map((candidate2) => ({
382329
- id: candidate2.id,
382330
- payloadJson: candidate2.id === input.id ? payloadJson : JSON.stringify(candidate2.payload)
382331
- }));
382332
- const committed = commitWholePartUpdates(this.context, "metadata-update", { [record3.partUri]: encodeXml(buildMetadataStorageXml(record3.namespace, refs)) }, { expectedRevision: expectedRevisionFrom(input, options) });
382333
- if (!committed.ok)
382334
- return { success: false, failure: { code: committed.code, message: committed.message } };
382335
- return { success: true, id: input.id };
382336
- }
382337
- remove(input, options) {
382338
- const mutationGuard = guardDirectOnlyMutation(this.context, input, options);
382339
- if (mutationGuard)
382340
- return mutationGuard;
382341
- if (listMetadataRecords(this.context).filter((candidate2) => candidate2.id === input.id).length > 1) {
382342
- return failure2("INVALID_TARGET", `metadata ${input.id} has ambiguous payload records.`);
382343
- }
382344
- const record3 = findMetadataRecord(this.context, input.id);
382345
- if (!record3)
382346
- throw operationError("TARGET_NOT_FOUND", `metadata ${input.id} not found.`);
382347
- const documentXml = readDocumentXml(this.context);
382348
- const knownIds = new Set(listMetadataRecords(this.context).map((candidate2) => candidate2.id));
382349
- const matchingAnchors = listMetadataAnchors(documentXml, knownIds).filter((anchor) => anchor.id === input.id);
382350
- const grouped = groupMetadataAnchor(documentXml, input.id, knownIds);
382351
- if (matchingAnchors.length > 0 && !grouped) {
382352
- return { success: false, failure: { code: "INVALID_TARGET", message: `metadata ${input.id} has ambiguous anchors.` } };
382353
- }
382354
- if (dryRunRequested(input, options))
382355
- return { success: true, id: input.id };
382356
- const updates = {};
382357
- if (grouped) {
382358
- const bySegmentPosition = [...grouped.segments].sort((a, b) => b.start - a.start);
382359
- let nextDocumentXml = documentXml;
382360
- for (const anchor of bySegmentPosition) {
382361
- if (anchor.unmatched)
382362
- continue;
382363
- const unwrapped = unwrapSdt(anchor.xml);
382364
- if (unwrapped === null)
382365
- continue;
382366
- nextDocumentXml = replaceRange3(nextDocumentXml, anchor.start, anchor.end, unwrapped);
382367
- }
382368
- if (nextDocumentXml !== documentXml)
382369
- updates[DOCUMENT_PART_URI5] = encodeXml(nextDocumentXml);
382370
- }
382371
- const remaining = listMetadataRecords(this.context).filter((candidate2) => candidate2.partUri === record3.partUri && candidate2.id !== input.id).map((candidate2) => ({ id: candidate2.id, payloadJson: JSON.stringify(candidate2.payload) }));
382372
- const targetBlockIds2 = grouped ? grouped.segments.map((anchor) => anchor.blockId) : undefined;
382373
- if (remaining.length > 0) {
382374
- updates[record3.partUri] = encodeXml(buildMetadataStorageXml(record3.namespace, remaining));
382375
- const committed = commitWholePartUpdates(this.context, "metadata-remove", updates, {
382376
- expectedRevision: expectedRevisionFrom(input, options),
382377
- ...targetBlockIds2 ? { storySurface: { family: "storyAnchor", targetBlockIds: targetBlockIds2 } } : {}
382378
- });
382379
- if (!committed.ok)
382380
- return { success: false, failure: { code: committed.code, message: committed.message } };
382381
- } else {
382382
- Object.assign(updates, buildCustomXmlRemoveUpdates(this.context, record3));
382383
- const committed = commitWholePartUpdates(this.context, "metadata-remove", updates, {
382384
- expectedRevision: expectedRevisionFrom(input, options),
382385
- ...targetBlockIds2 ? { storySurface: { family: "storyAnchor", targetBlockIds: targetBlockIds2 } } : {}
382386
- });
382387
- if (!committed.ok)
382388
- return { success: false, failure: { code: committed.code, message: committed.message } };
382389
- }
382390
- return { success: true, id: input.id };
382391
- }
382392
- resolve(input) {
382393
- const record3 = findMetadataRecord(this.context, input.id);
382394
- if (!record3)
382395
- return null;
382396
- const knownIds = new Set(listMetadataRecords(this.context).map((candidate2) => candidate2.id));
382397
- const grouped = groupMetadataAnchor(readDocumentXml(this.context), input.id, knownIds);
382398
- if (!grouped)
382399
- return null;
382400
- return { id: input.id, target: grouped.target };
382401
- }
382402
- }
382403
- function listMetadataRecords(context) {
382404
- const out = [];
382405
- for (const part of listCustomXmlRecords(context)) {
382406
- if (!part.rootNamespace || !/^<refs\b/.test(part.content.replace(/^<\?xml[^>]*>/, "").trim()))
382407
- continue;
382408
- for (const ref5 of readMetadataRefs(part.content, part.rootNamespace)) {
382409
- let payload = null;
382410
- try {
382411
- payload = JSON.parse(ref5.payloadJson);
382412
- } catch {
382413
- payload = null;
382414
- }
382415
- out.push({
382416
- id: ref5.id,
382417
- namespace: part.rootNamespace,
382418
- partName: part.partName,
382419
- partUri: part.partUri,
382420
- ...part.propsPartUri ? { propsPartUri: part.propsPartUri } : {},
382421
- payload
382422
- });
382423
- }
382424
- }
382425
- return out;
382426
- }
382427
- function findMetadataRecord(context, id) {
382428
- const matches = listMetadataRecords(context).filter((record3) => record3.id === id);
382429
- return matches.length === 1 ? matches[0] : null;
382430
- }
382431
- function metadataSummary(record3, documentXml) {
382432
- return {
382433
- id: record3.id,
382434
- namespace: record3.namespace,
382435
- partName: record3.partName,
382436
- anchorStatus: groupMetadataAnchor(documentXml, record3.id, new Set([record3.id])) ? "resolved" : "orphan"
382437
- };
382438
- }
382439
- function readMetadataRefs(xml, _namespace) {
382440
- const refs = [];
382441
- const re = /<ref\b[^>]*\bid="([^"]*)"[^>]*>([\s\S]*?)<\/ref>/g;
382442
- for (let match = re.exec(xml);match; match = re.exec(xml)) {
382443
- refs.push({ id: decodeXmlEntities(match[1]), payloadJson: decodeXmlEntities(match[2]) });
382444
- }
382445
- return refs;
382446
- }
382447
- function findMetadataAnchor(documentXml, id) {
382448
- return listMetadataAnchors(documentXml, new Set([id])).find((anchor) => anchor.id === id) ?? null;
382449
- }
382450
- function listMetadataAnchors(documentXml, knownIds) {
382451
- const anchors = [];
382452
- for (const sdt of listSdtRanges(documentXml)) {
382453
- const pr = ownSdtPr(sdt.xml);
382454
- const tag = attrValue(/<w:tag\b[^>]*\/>/.exec(pr)?.[0] ?? "", "val");
382455
- if (!tag || !isMetadataAnchorPr(pr, tag, knownIds))
382456
- continue;
382457
- const anchor = materializeMetadataAnchor(documentXml, sdt, tag);
382458
- if (anchor)
382459
- anchors.push(anchor);
382460
- }
382461
- return anchors.sort((left, right) => left.start - right.start);
382462
- }
382463
- function ownSdtPr(sdtXml) {
382464
- const openTag = /<w:sdt\b[^>]*>/.exec(sdtXml);
382465
- if (!openTag)
382466
- return "";
382467
- const headStart = openTag.index + openTag[0].length;
382468
- const contentOrNested = /<w:sdtContent\b[^>]*>|<w:sdt\b[^>]*>/.exec(sdtXml.slice(headStart));
382469
- const head = contentOrNested ? sdtXml.slice(headStart, headStart + contentOrNested.index) : sdtXml.slice(headStart);
382470
- return /<w:sdtPr\b[^>]*>[\s\S]*?<\/w:sdtPr>/.exec(head)?.[0] ?? "";
382471
- }
382472
- function listSdtRanges(documentXml) {
382473
- const ranges = [];
382474
- const stack = [];
382475
- const tokenRe = /<w:sdt\b[^>]*>|<\/w:sdt>/g;
382476
- for (let match = tokenRe.exec(documentXml);match; match = tokenRe.exec(documentXml)) {
382477
- if (match[0].startsWith("</")) {
382478
- const start = stack.pop();
382479
- if (start === undefined)
382480
- continue;
382481
- const end = tokenRe.lastIndex;
382482
- ranges.push({ start, end, xml: documentXml.slice(start, end) });
382483
- } else if (/\/\s*>$/.test(match[0])) {
382484
- ranges.push({ start: match.index, end: tokenRe.lastIndex, xml: match[0] });
382485
- } else {
382486
- stack.push(match.index);
382487
- }
382488
- }
382489
- for (const start of stack) {
382490
- const end = unmatchedSdtExtent(documentXml, start);
382491
- ranges.push({ start, end, xml: documentXml.slice(start, end), unmatched: true });
382492
- }
382493
- return ranges.sort((left, right) => left.start - right.start);
382494
- }
382495
- function unmatchedSdtExtent(documentXml, start) {
382496
- const paraClose = documentXml.indexOf("</w:p>", start);
382497
- return paraClose === -1 ? documentXml.length : paraClose;
382498
- }
382499
- function isMetadataAnchorPr(pr, tag, knownIds) {
382500
- const alias = attrValue(/<w:alias\b[^>]*\/>/.exec(pr)?.[0] ?? "", "val");
382501
- if (alias !== null && alias !== METADATA_ANCHOR_ALIAS)
382502
- return false;
382503
- const hasHiddenAppearance = attrValue(/<w15:appearance\b[^>]*\/>/.exec(pr)?.[0] ?? "", "val") === "hidden";
382504
- const hasPlainTextPr = /<w:text\b/.test(pr);
382505
- return knownIds.has(tag) && hasHiddenAppearance && hasPlainTextPr;
382506
- }
382507
- function materializeMetadataAnchor(documentXml, sdt, id) {
382508
- const para = findParagraphContaining2(documentXml, sdt.start);
382509
- if (!para)
382510
- return null;
382511
- const startOffset = extractVisibleTextFromXml2(para.xml.slice(0, sdt.start - para.start)).length;
382512
- const length = extractVisibleTextFromXml2(unwrapSdt(sdt.xml) ?? sdt.xml).length;
382513
- const endOffset = startOffset + length;
382514
- return {
382515
- id,
382516
- start: sdt.start,
382517
- end: sdt.end,
382518
- xml: sdt.xml,
382519
- blockId: para.blockId,
382520
- startOffset,
382521
- endOffset,
382522
- unmatched: sdt.unmatched === true,
382523
- target: {
382524
- kind: "selection",
382525
- start: { kind: "text", blockId: para.blockId, offset: startOffset, story: bodyStoryLocator2() },
382526
- end: { kind: "text", blockId: para.blockId, offset: endOffset, story: bodyStoryLocator2() }
382527
- }
382528
- };
382529
- }
382530
- function groupMetadataAnchor(documentXml, id, knownIds) {
382531
- const matches = listMetadataAnchors(documentXml, knownIds).filter((anchor) => anchor.id === id);
382532
- if (matches.length === 0)
382533
- return null;
382534
- const kept = contiguousAnchorPrefix(documentXml, matches);
382535
- if (kept.length !== matches.length)
382536
- return null;
382537
- if (kept.length === 1)
382538
- return { id, segments: kept, target: kept[0].target };
382539
- const textSegments = [];
382540
- for (const anchor of kept) {
382541
- const previous3 = textSegments.at(-1);
382542
- if (previous3?.blockId === anchor.blockId && previous3.range.end === anchor.startOffset) {
382543
- previous3.range.end = anchor.endOffset;
382544
- } else {
382545
- textSegments.push({ blockId: anchor.blockId, range: { start: anchor.startOffset, end: anchor.endOffset } });
382546
- }
382547
- }
382548
- if (textSegments.length === 1) {
382549
- const range = textSegments[0];
382550
- return {
382551
- id,
382552
- segments: kept,
382553
- target: {
382554
- kind: "selection",
382555
- start: { kind: "text", blockId: range.blockId, offset: range.range.start, story: bodyStoryLocator2() },
382556
- end: { kind: "text", blockId: range.blockId, offset: range.range.end, story: bodyStoryLocator2() }
382557
- }
382558
- };
382559
- }
382560
- return {
382561
- id,
382562
- segments: kept,
382563
- target: { kind: "text", segments: [textSegments[0], ...textSegments.slice(1)] }
382564
- };
382565
- }
382566
- function contiguousAnchorPrefix(documentXml, matches) {
382567
- if (matches.length <= 1)
382568
- return [...matches];
382569
- const map3 = buildStructuralBoundaryMap(TEXT_ENCODER2.encode(documentXml));
382570
- const first = map3.byBlockId(matches[0].blockId);
382571
- if (!first)
382572
- return [matches[0]];
382573
- const kept = [matches[0]];
382574
- let prev = first;
382575
- for (let i2 = 1;i2 < matches.length; i2 += 1) {
382576
- const context = map3.byBlockId(matches[i2].blockId);
382577
- if (!context)
382578
- break;
382579
- const sameParagraph = context.ordinal === prev.ordinal;
382580
- if (sameParagraph) {
382581
- const previousAnchor = kept.at(-1);
382582
- if (context.blockId !== previousAnchor.blockId || matches[i2].startOffset !== previousAnchor.endOffset || !isMetadataCarrierGap(documentXml.slice(previousAnchor.end, matches[i2].start)))
382583
- break;
382584
- } else if (context.ordinal !== prev.ordinal + 1)
382585
- break;
382586
- if (!sameTableCellPath(context.tableCellPath, first.tableCellPath))
382587
- break;
382588
- if (!sameOrdinalPath2(context.blockSdtPath, first.blockSdtPath))
382589
- break;
382590
- if (!sameOrdinalPath2(context.blockCustomXmlPath, first.blockCustomXmlPath))
382591
- break;
382592
- if (context.sectionIndex !== first.sectionIndex)
382593
- break;
382594
- if (prev.carriesSectionBreak)
382595
- break;
382596
- kept.push(matches[i2]);
382597
- prev = context;
382598
- }
382599
- return kept;
382600
- }
382601
- function isMetadataCarrierGap(xml) {
382602
- return /^(?:\s*<w:proofErr\s+w:type="(?:spellStart|spellEnd|gramStart|gramEnd)"\s*\/>)*\s*$/.test(xml);
382603
- }
382604
- function sameOrdinalPath2(left, right) {
382605
- return left.length === right.length && left.every((value2, index2) => value2 === right[index2]);
382606
- }
382607
- function resolveSingleSegmentTarget(context, documentXml, target) {
382608
- const resolved = resolveBodySelectionTarget(context, target);
382609
- if ("error" in resolved)
382610
- return resolved;
382611
- if (resolved.startBlockId !== resolved.endBlockId) {
382612
- return { error: "INVALID_TARGET", message: "metadata.attach requires a same-paragraph text selection." };
382613
- }
382614
- if (resolved.startOffset >= resolved.endOffset) {
382615
- return { error: "INVALID_TARGET", message: "metadata.attach requires a non-empty text range." };
382616
- }
382617
- const para = findParagraphById3(documentXml, resolved.startBlockId);
382618
- if (!para)
382619
- return { error: "TARGET_NOT_FOUND", message: `paragraph ${resolved.startBlockId} not found.` };
382620
- return {
382621
- segments: [{ blockId: para.blockId, startOffset: resolved.startOffset, endOffset: resolved.endOffset, para }]
382622
- };
382623
- }
382624
- function resolveMultiSegmentTarget(documentXml, target) {
382625
- if (target.story !== undefined && target.story.storyType !== "body") {
382626
- return {
382627
- error: "TARGET_NOT_FOUND",
382628
- message: "metadata.attach resolves paragraphs against the main document body only."
382629
- };
382630
- }
382631
- if (target.coordinateSpace === "tracked") {
382632
- return {
382633
- error: "INVALID_TARGET",
382634
- message: "metadata.attach does not support a tracked-coordinate-space TextTarget."
382635
- };
382636
- }
382637
- const segments = [];
382638
- for (const segment of target.segments) {
382639
- if (segment.range.start >= segment.range.end) {
382640
- return {
382641
- error: "INVALID_TARGET",
382642
- message: "metadata.attach requires a non-empty text range in every TextTarget segment."
382643
- };
382644
- }
382645
- const para = findParagraphById3(documentXml, segment.blockId);
382646
- if (!para)
382647
- return { error: "TARGET_NOT_FOUND", message: `paragraph ${segment.blockId} not found.` };
382648
- segments.push({ blockId: segment.blockId, startOffset: segment.range.start, endOffset: segment.range.end, para });
382649
- }
382650
- const boundaryError = validateContiguousStructuralRun(documentXml, segments.map((segment) => segment.blockId));
382651
- if (boundaryError)
382652
- return boundaryError;
382653
- return { segments };
382654
- }
382655
- function validateContiguousStructuralRun(documentXml, blockIds) {
382656
- if (blockIds.length <= 1)
382657
- return null;
382658
- const map3 = buildStructuralBoundaryMap(TEXT_ENCODER2.encode(documentXml));
382659
- const contexts = blockIds.map((blockId) => map3.byBlockId(blockId));
382660
- const first = contexts[0];
382661
- if (!first) {
382662
- return { error: "INVALID_TARGET", message: `paragraph "${blockIds[0]}" is not visible to the structural map.` };
382663
- }
382664
- for (let i2 = 1;i2 < contexts.length; i2 += 1) {
382665
- const context = contexts[i2];
382666
- const prev = contexts[i2 - 1];
382667
- if (!context) {
382668
- return { error: "INVALID_TARGET", message: `paragraph "${blockIds[i2]}" is not visible to the structural map.` };
382669
- }
382670
- if (context.ordinal !== prev.ordinal + 1) {
382671
- return {
382672
- error: "INVALID_TARGET",
382673
- message: "metadata.attach TextTarget segments must be contiguous paragraphs in document order."
382674
- };
382675
- }
382676
- if (!sameTableCellPath(context.tableCellPath, first.tableCellPath)) {
382677
- return { error: "INVALID_TARGET", message: "metadata.attach TextTarget cannot cross a table-cell boundary." };
382678
- }
382679
- if (!sameOrdinalPath2(context.blockSdtPath, first.blockSdtPath)) {
382680
- return {
382681
- error: "INVALID_TARGET",
382682
- message: "metadata.attach TextTarget cannot cross a block content-control boundary."
382683
- };
382684
- }
382685
- if (!sameOrdinalPath2(context.blockCustomXmlPath, first.blockCustomXmlPath)) {
382686
- return {
382687
- error: "INVALID_TARGET",
382688
- message: "metadata.attach TextTarget cannot cross a block custom-XML boundary."
382689
- };
382690
- }
382691
- if (context.sectionIndex !== first.sectionIndex) {
382692
- return { error: "INVALID_TARGET", message: "metadata.attach TextTarget cannot cross a section boundary." };
382693
- }
382694
- if (prev.carriesSectionBreak) {
382695
- return { error: "INVALID_TARGET", message: "metadata.attach TextTarget cannot cross a section boundary." };
382696
- }
382697
- }
382698
- if (contexts[contexts.length - 1].carriesSectionBreak) {
382699
- return { error: "INVALID_TARGET", message: "metadata.attach TextTarget cannot cross a section boundary." };
382700
- }
382701
- return null;
382702
- }
382703
- function hasOverlappingMetadataAnchor(documentXml, segments, knownIds) {
382704
- const anchors = listMetadataAnchors(documentXml, knownIds);
382705
- return segments.some((segment) => anchors.some((anchor) => anchor.blockId === segment.blockId && rangesStrictlyOverlap(segment.startOffset, segment.endOffset, anchor.startOffset, anchor.endOffset)));
382706
- }
382707
- function rangesStrictlyOverlap(leftStart, leftEnd, rightStart, rightEnd) {
382708
- return leftStart < rightEnd && rightStart < leftEnd;
382709
- }
382710
- function bodyStoryLocator2() {
382711
- return { kind: "story", storyType: "body" };
382712
- }
382713
- function wrapTextRangeWithMetadataSdt(paragraphXml, start, end, id, sdtId) {
382714
- return wrapRangeWithMarkupInParagraphXml({
382715
- paragraphXml,
382716
- rangeStart: start,
382717
- rangeEnd: end,
382718
- open: metadataSdtOpenXml(id, sdtId),
382719
- close: "</w:sdtContent></w:sdt>"
382720
- });
382721
- }
382722
- function metadataSdtOpenXml(id, sdtId) {
382723
- return [
382724
- `<w:sdt xmlns:w15="${W15_NS}"><w:sdtPr>`,
382725
- `<w:id w:val="${sdtId}"/>`,
382726
- `<w:alias w:val="${xmlEscapeAttr(METADATA_ANCHOR_ALIAS)}"/>`,
382727
- `<w:tag w:val="${xmlEscapeAttr(id)}"/>`,
382728
- '<w15:appearance w15:val="hidden"/>',
382729
- "<w:text/>",
382730
- "</w:sdtPr><w:sdtContent>"
382731
- ].join("");
382732
- }
382733
- function metadataWrapRejectError(reason) {
382734
- if (reason === "invalid-range") {
382735
- return operationError("TARGET_NOT_FOUND", "metadata target text range not found.");
382736
- }
382737
- return operationError("INVALID_TARGET", `metadata.attach target overlaps unsupported content (${reason}).`);
382738
- }
382739
- function allocateMetadataSdtIds(documentXml, count) {
382740
- const used = new Set;
382741
- const idRe = /<w:id\b[^>]*(?:\/>|>)/g;
382742
- for (let match = idRe.exec(documentXml);match; match = idRe.exec(documentXml)) {
382743
- const value2 = Number.parseInt(attrValue(match[0], "val") ?? "", 10);
382744
- if (Number.isInteger(value2))
382745
- used.add(value2);
382746
- }
382747
- const ids = [];
382748
- for (let i2 = 0;i2 < count; i2 += 1) {
382749
- let candidate2 = Math.max(1, Math.floor(Math.random() * MAX_SDT_ID));
382750
- while (used.has(candidate2))
382751
- candidate2 = candidate2 >= MAX_SDT_ID ? 1 : candidate2 + 1;
382752
- used.add(candidate2);
382753
- ids.push(candidate2);
382754
- }
382755
- return ids;
382756
- }
382757
- function ensureW15Namespace(documentXml) {
382758
- return documentXml.replace(/<w:document\b[^>]*>/, (openTag) => {
382759
- let next = openTag;
382760
- if (!/\sxmlns:w15\s*=/.test(next))
382761
- next = next.replace(/>$/, ` xmlns:w15="${W15_NS}">`);
382762
- const ignorable = /\smc:Ignorable\s*=\s*(["'])([^"']*)\1/.exec(next);
382763
- if (!ignorable)
382764
- return next;
382765
- const prefixes = ignorable[2].split(/\s+/).filter(Boolean);
382766
- if (prefixes.includes("w15"))
382767
- return next;
382768
- return next.replace(ignorable[0], ` mc:Ignorable="${[...prefixes, "w15"].join(" ")}"`);
382769
- });
382770
- }
382771
- function readDocumentXml(context) {
382772
- const xml = readPartXml(context, DOCUMENT_PART_URI5);
382773
- if (!xml)
382774
- throw operationError("PRECONDITION_FAILED", "document.xml bytes are unavailable.");
382775
- return xml;
382776
- }
382777
- function findParagraphById3(documentXml, blockId) {
382778
- const paraRe = /<w:p\b[^>]*>[\s\S]*?<\/w:p>/g;
382779
- for (let match = paraRe.exec(documentXml);match; match = paraRe.exec(documentXml)) {
382780
- if (match[0].includes(`w14:paraId="${blockId}"`))
382781
- return { start: match.index, end: paraRe.lastIndex, xml: match[0], blockId };
382782
- }
382783
- return null;
382784
- }
382785
- function findParagraphContaining2(documentXml, index2) {
382786
- const paraRe = /<w:p\b[^>]*>[\s\S]*?<\/w:p>/g;
382787
- for (let match = paraRe.exec(documentXml);match; match = paraRe.exec(documentXml)) {
382788
- if (match.index <= index2 && paraRe.lastIndex >= index2) {
382789
- const open = /^<w:p\b[^>]*>/.exec(match[0])?.[0] ?? "";
382790
- return {
382791
- start: match.index,
382792
- end: paraRe.lastIndex,
382793
- xml: match[0],
382794
- blockId: attrValue(open, "paraId") ?? "unknown"
382795
- };
382796
- }
382797
- }
382798
- return null;
382799
- }
382800
- function unwrapSdt(sdtXml) {
382801
- const open = /<w:sdtContent\b[^>]*>/.exec(sdtXml);
382802
- if (!open)
382803
- return null;
382804
- if (/\/\s*>$/.test(open[0]))
382805
- return "";
382806
- const contentStart = open.index + open[0].length;
382807
- const tokenRe = /<w:sdtContent\b[^>]*>|<\/w:sdtContent>/g;
382808
- tokenRe.lastIndex = contentStart;
382809
- let depth = 0;
382810
- for (let match = tokenRe.exec(sdtXml);match; match = tokenRe.exec(sdtXml)) {
382811
- if (match[0].startsWith("</")) {
382812
- if (depth === 0)
382813
- return sdtXml.slice(contentStart, match.index);
382814
- depth -= 1;
382815
- } else if (!/\/\s*>$/.test(match[0])) {
382816
- depth += 1;
382817
- }
382818
- }
382819
- return null;
382820
- }
382821
- function replaceRange3(xml, start, end, replacement) {
382822
- return `${xml.slice(0, start)}${replacement}${xml.slice(end)}`;
382823
- }
382824
- function toFlatSegments(target) {
382825
- if (target.story !== undefined && target.story.storyType !== "body")
382826
- return null;
382827
- if (target.coordinateSpace === "tracked")
382828
- return null;
382829
- if (target.kind === "text") {
382830
- return target.segments.map((segment) => ({
382831
- blockId: segment.blockId,
382832
- start: segment.range.start,
382833
- end: segment.range.end
382834
- }));
382835
- }
382836
- if (target.start.kind !== "text" || target.end.kind !== "text")
382837
- return null;
382838
- if (target.start.blockId !== target.end.blockId)
382839
- return null;
382840
- return [{ blockId: target.start.blockId, start: target.start.offset, end: target.end.offset }];
382841
- }
382842
- function overlaps(left, right) {
382843
- const leftSegments = toFlatSegments(left);
382844
- const rightSegments = toFlatSegments(right);
382845
- if (!leftSegments || !rightSegments)
382846
- return false;
382847
- return leftSegments.some((leftSegment) => rightSegments.some((rightSegment) => leftSegment.blockId === rightSegment.blockId && rangesStrictlyOverlap(leftSegment.start, leftSegment.end, rightSegment.start, rightSegment.end)));
382848
- }
382849
- var TEXT_ENCODER2, METADATA_ANCHOR_ALIAS = "Anchored metadata", W15_NS = "http://schemas.microsoft.com/office/word/2012/wordml", MAX_SDT_ID = 2147483646;
382850
- var init_adapter38 = __esm(() => {
382851
- init_src3();
382852
- init_sd_document_session_internal();
382853
- init_visible_text();
382854
- init_inline();
382855
- init_adapter2();
382856
- init_shared();
382857
- init_xml();
382858
- TEXT_ENCODER2 = new TextEncoder;
382859
- });
382860
-
382861
383077
  // ../../../v2/document-api-v2-adapter/dist/formatting/styles.js
382862
383078
  function applyStylesDocDefaultsPatch(stylesXml, input) {
382863
383079
  const normalized = normalizeStylesWordprocessingMlQNames(stylesXml);
@@ -386012,47 +386228,47 @@ function createV2DocumentApiAdapter(session, options = {}) {
386012
386228
  }
386013
386229
  var init_factory = __esm(() => {
386014
386230
  init_context();
386015
- init_adapter10();
386016
386231
  init_adapter11();
386017
- init_adapter16();
386018
- init_adapter18();
386232
+ init_adapter12();
386233
+ init_adapter17();
386019
386234
  init_adapter19();
386020
386235
  init_adapter20();
386021
- init_adapter12();
386022
- init_adapter15();
386023
386236
  init_adapter21();
386237
+ init_adapter13();
386238
+ init_adapter16();
386239
+ init_adapter22();
386024
386240
  init_adapter2();
386025
- init_adapter23();
386026
386241
  init_adapter24();
386027
- init_adapter();
386028
386242
  init_adapter25();
386243
+ init_adapter();
386029
386244
  init_adapter26();
386030
- init_adapter29();
386245
+ init_adapter27();
386246
+ init_adapter30();
386031
386247
  init_adapter6();
386032
386248
  init_adapter7();
386033
- init_adapter9();
386034
- init_adapter30();
386035
- init_adapter13();
386036
- init_adapter22();
386037
- init_reader();
386249
+ init_adapter10();
386038
386250
  init_adapter31();
386039
- init_search2();
386251
+ init_adapter14();
386252
+ init_adapter23();
386253
+ init_reader();
386040
386254
  init_adapter32();
386255
+ init_search2();
386041
386256
  init_adapter33();
386257
+ init_adapter34();
386042
386258
  init_adapter8();
386043
- init_adapter17();
386259
+ init_adapter18();
386044
386260
  init_adapter3();
386045
- init_adapter34();
386046
386261
  init_adapter35();
386047
386262
  init_adapter36();
386048
- init_adapter27();
386049
386263
  init_adapter37();
386050
- init_clear_content_adapter();
386051
386264
  init_adapter28();
386265
+ init_adapter38();
386266
+ init_clear_content_adapter();
386267
+ init_adapter29();
386052
386268
  init_adapter4();
386053
386269
  init_adapter5();
386054
- init_adapter38();
386055
- init_adapter14();
386270
+ init_adapter9();
386271
+ init_adapter15();
386056
386272
  init_adapter39();
386057
386273
  init_adapter40();
386058
386274
  init_read_adapters();
@@ -419956,7 +420172,7 @@ class XmlEmissionContext {
419956
420172
  stack.push(namespaceBindings);
419957
420173
  if (namespaceBindings !== inherited)
419958
420174
  events.push({ offset: end, bindings: namespaceBindings });
419959
- if (tag.localName !== "p" || tag.namespaceUri !== WORD_NAMESPACE5)
420175
+ if (tag.localName !== "p" || tag.namespaceUri !== WORD_NAMESPACE6)
419960
420176
  return;
419961
420177
  if (paragraphDepth++ > 0)
419962
420178
  return;
@@ -419966,7 +420182,7 @@ class XmlEmissionContext {
419966
420182
  this.paragraphs.set(blockIdForParagraphXmlSpan({ paraId: id2 ?? null, ordinal: paragraphOrdinal++ }), context);
419967
420183
  },
419968
420184
  onCloseTag: ({ tag, end }) => {
419969
- if (tag.localName === "p" && tag.namespaceUri === WORD_NAMESPACE5)
420185
+ if (tag.localName === "p" && tag.namespaceUri === WORD_NAMESPACE6)
419970
420186
  paragraphDepth -= 1;
419971
420187
  const previous3 = stack.pop();
419972
420188
  const bindings = stack[stack.length - 1] ?? this.initial;
@@ -419991,17 +420207,17 @@ function paragraphEmissionNames(context, preservedXml) {
419991
420207
  bindings[prefix] = namespace;
419992
420208
  return prefix;
419993
420209
  };
419994
- const word3 = choose("w", WORD_NAMESPACE5);
420210
+ const word3 = choose("w", WORD_NAMESPACE6);
419995
420211
  const word2010 = choose("w14", WORD_2010_NAMESPACE3);
419996
420212
  const declarations = Object.entries({ "": "", ...bindings }).filter(([prefix, uri]) => prefix !== "xml" && (context.inherited[prefix] ?? "") !== uri).sort(([left], [right]) => left.localeCompare(right)).map(([prefix, uri]) => ` xmlns${prefix ? `:${prefix}` : ""}="${xmlEscape(uri)}"`).join("");
419997
420213
  return { word: word3, word2010, declarations };
419998
420214
  }
419999
- var WORD_NAMESPACE5 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", WORD_2010_NAMESPACE3 = "http://schemas.microsoft.com/office/word/2010/wordml", CANONICAL_NAMESPACES;
420215
+ var WORD_NAMESPACE6 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", WORD_2010_NAMESPACE3 = "http://schemas.microsoft.com/office/word/2010/wordml", CANONICAL_NAMESPACES;
420000
420216
  var init_xml_emission_context = __esm(() => {
420001
420217
  init_sd_document_session_internal();
420002
420218
  init_canonical();
420003
420219
  CANONICAL_NAMESPACES = {
420004
- w: WORD_NAMESPACE5,
420220
+ w: WORD_NAMESPACE6,
420005
420221
  w14: WORD_2010_NAMESPACE3
420006
420222
  };
420007
420223
  });
@@ -426505,6 +426721,7 @@ function syncTrackedDecisionTableOverlaysFromSession(session, prepared, storyId,
426505
426721
  partUri,
426506
426722
  preparedTxId: prepared.txId,
426507
426723
  lastDeltaKind: "tracked-change.decision.sync",
426724
+ reversibleReviewDecision: prepared.backendExtensions.storySurface?.historyReplay != null,
426508
426725
  tableXml,
426509
426726
  sourceXmlStart,
426510
426727
  sourceXmlEnd: sourceXmlStart + tableXml.length,
@@ -426559,6 +426776,16 @@ function writeTableOverlayState(input) {
426559
426776
  input.tableMap.set(overlayTableNodeId, tableValue);
426560
426777
  }
426561
426778
  const tableState = tableValue;
426779
+ if (input.lastDeltaKind === "tracked-change.decision.sync") {
426780
+ const previousTableXml = tableState.get("xml");
426781
+ const previousGridXml = typeof previousTableXml === "string" ? readDirectChildPropertyXml3(previousTableXml, "tbl", "tblGrid") : "";
426782
+ const nextGridXml = readDirectChildPropertyXml3(input.tableXml, "tbl", "tblGrid");
426783
+ writeTableRevisionDecisionDiff(tableState, "grid", overlayTableNodeId, previousGridXml, nextGridXml, input.reversibleReviewDecision === true);
426784
+ const nextGridChangeXml = readDirectChildPropertyXml3(nextGridXml, "tblGrid", "tblGridChange");
426785
+ if (nextGridChangeXml || tableState.has("gridChange")) {
426786
+ tableState.set("gridChange", nextGridChangeXml || null);
426787
+ }
426788
+ }
426562
426789
  tableState.set("tableNodeId", overlayTableNodeId);
426563
426790
  if (overlayTableNodeId === input.table.tableNodeId)
426564
426791
  tableState.delete("currentTableNodeId");
@@ -426948,6 +427175,7 @@ var init_story_surface_session_sync = __esm(() => {
426948
427175
  init_table_structural_refs();
426949
427176
  init_schema4();
426950
427177
  init_seed();
427178
+ init_table_revision_decisions();
426951
427179
  init_story_surface_origin();
426952
427180
  init_paragraph_inline_sync();
426953
427181
  init_story_surface_origin();