@superdoc/mcp 1.10.0-next.11 → 1.10.0-next.13

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 +766 -96
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31630,7 +31630,7 @@ var init_host = __esm(() => {
31630
31630
  });
31631
31631
 
31632
31632
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31633
- var SDK_VERSION = "2.23.0-next.11";
31633
+ var SDK_VERSION = "2.23.0-next.13";
31634
31634
 
31635
31635
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31636
31636
  import { accessSync, chmodSync, constants, existsSync, statSync } from "node:fs";
@@ -93757,7 +93757,7 @@ async function runInsertParagraphs(doc2, args, formatArgs) {
93757
93757
  kind: "placement",
93758
93758
  at: placement.kind === "documentStart" ? "document_start" : "document_end"
93759
93759
  });
93760
- const preRows = pre.complete ? await listBlockRows(doc2) : anchor ? [anchor] : [];
93760
+ let preRows = pre.complete ? await listBlockRows(doc2) : anchor ? [anchor] : [];
93761
93761
  let currentPlacement = placement;
93762
93762
  const nodeIds = [];
93763
93763
  const specs = [];
@@ -93795,6 +93795,16 @@ async function runInsertParagraphs(doc2, args, formatArgs) {
93795
93795
  if (!pre.complete) {
93796
93796
  const created = await post.page({ nodeIds, limit: Math.max(nodeIds.length, 1) });
93797
93797
  localRows = [...anchor ? [anchor] : [], ...created].sort((a, b) => a.ordinal - b.ordinal);
93798
+ const placed = anchor && texts.some((text) => typedMarkerPrefixOf(text)) ? await post.block(anchor.nodeId) : null;
93799
+ if (placed) {
93800
+ const span = TYPED_SIBLING_WINDOW + nodeIds.length;
93801
+ const window2 = await post.page({ offset: Math.max(0, placed.ordinal - 1 - span), limit: 2 * span + 1 });
93802
+ const createdIds = new Set(nodeIds);
93803
+ if (nodeIds.every((id) => window2.some((row) => row.nodeId === id))) {
93804
+ preRows = window2.filter((row) => !createdIds.has(row.nodeId));
93805
+ localRows = window2;
93806
+ }
93807
+ }
93798
93808
  }
93799
93809
  const count = context.executedOperations.length;
93800
93810
  formatted = await matchInsertedBlockFormatting(context.document, preRows, context.receipt("insert_paragraphs", []), formatArgs, localRows);
@@ -94122,6 +94132,164 @@ async function runDeleteText(doc2, args) {
94122
94132
  return failedReceipt("delete_text", err, pre);
94123
94133
  }
94124
94134
  }
94135
+ function enumerationSlotOf(block) {
94136
+ const numbering = blockNumbering(block);
94137
+ const path5 = numbering?.path;
94138
+ if (Array.isArray(path5) && path5.length > 0) {
94139
+ return { key: `scheme:${path5.slice(0, -1).join(".")}:${path5.length}`, depth: path5.length, typed: null };
94140
+ }
94141
+ const markerShape = numbering?.marker ? markerShapeOf(numbering.marker) : null;
94142
+ if (markerShape)
94143
+ return { key: `scheme-marker:${markerShape.wrapper}:${markerShape.kind}`, depth: null, typed: null };
94144
+ const text = block.text || block.textPreview || "";
94145
+ const typedMarker = typedMarkerPrefixOf(text)?.marker;
94146
+ const typedShape = typedMarker ? markerShapeOf(text) : null;
94147
+ if (!typedMarker || !typedShape)
94148
+ return null;
94149
+ const parent = typedShape.kind === "digit" ? typedDigitParentOf(typedMarker) : "";
94150
+ return { key: `typed:${typedShape.wrapper}:${typedShape.kind}:${parent}`, depth: null, typed: typedShape };
94151
+ }
94152
+ function typedDigitParentOf(marker) {
94153
+ const segments = marker.replace(/^\(/, "").replace(/[.)]$/, "").split(".");
94154
+ return `${segments.length}:${segments.slice(0, -1).join(".")}`;
94155
+ }
94156
+ function markerValueOf(token, shape) {
94157
+ const core2 = token.replace(/^\(/, "").replace(/[.)]$/, "").toLowerCase();
94158
+ if (shape.kind === "digit")
94159
+ return Number(core2.split(".").pop());
94160
+ if (shape.kind === "lower-roman" || shape.kind === "upper-roman") {
94161
+ let total = 0;
94162
+ for (let i = 0;i < core2.length; i += 1) {
94163
+ const value = ROMAN_DIGITS[core2[i]] ?? 0;
94164
+ total += value < (ROMAN_DIGITS[core2[i + 1] ?? ""] ?? 0) ? -value : value;
94165
+ }
94166
+ return total;
94167
+ }
94168
+ const letter = core2.charCodeAt(0) - 96;
94169
+ return core2.length === 1 ? letter : 26 * (core2.length - 1) + letter;
94170
+ }
94171
+ function enumerationRunOf(blocks, index, slot, textOf) {
94172
+ const typed = slot.typed;
94173
+ const valueOf = (block) => {
94174
+ if (!typed) {
94175
+ const path5 = blockNumbering(block)?.path;
94176
+ return Array.isArray(path5) && path5.length > 0 ? Number(path5[path5.length - 1]) : null;
94177
+ }
94178
+ const token = typed ? typedMarkerPrefixOf(textOf(block))?.marker : null;
94179
+ return token && typed ? markerValueOf(token, typed) : null;
94180
+ };
94181
+ const walk = (step) => {
94182
+ const found = [];
94183
+ let edge = valueOf(blocks[index]);
94184
+ let crossed = false;
94185
+ for (let i = index + step;i >= 0 && i < blocks.length; i += step) {
94186
+ const block = blocks[i];
94187
+ if (textOf(block).length === 0)
94188
+ continue;
94189
+ const other = enumerationSlotOf(block);
94190
+ const continuesAsLetter = typed != null && other?.typed != null && markerShapeFits(typed, other.typed) && edge != null && valueOf(block) === edge + step;
94191
+ if (other?.key === slot.key || continuesAsLetter) {
94192
+ const value = valueOf(block);
94193
+ if (value != null && edge != null) {
94194
+ const advance = (value - edge) * step;
94195
+ if (advance <= 0 || (crossed || !typed) && advance !== 1)
94196
+ break;
94197
+ }
94198
+ found.push(block);
94199
+ edge = value;
94200
+ crossed = false;
94201
+ continue;
94202
+ }
94203
+ if (typed && other?.typed) {
94204
+ if (step === -1 && edge != null) {
94205
+ const prefix = typedMarkerPrefixOf(textOf(block)).prefix;
94206
+ const inline = new RegExp(String.raw`(?:^|\s)(${TYPED_MARKER_TOKEN}) `).exec(textOf(block).slice(prefix.length));
94207
+ const inlineShape = inline ? markerShapeOf(inline[1]) : null;
94208
+ if (inline && sameMarkerShape(inlineShape, typed) && markerValueOf(inline[1], typed) === edge - 1) {
94209
+ found.push(block);
94210
+ break;
94211
+ }
94212
+ }
94213
+ crossed = true;
94214
+ continue;
94215
+ }
94216
+ if (slot.depth != null && other?.depth != null && other.depth > slot.depth)
94217
+ continue;
94218
+ break;
94219
+ }
94220
+ return found;
94221
+ };
94222
+ return [...walk(-1).reverse(), blocks[index], ...walk(1)];
94223
+ }
94224
+ function listPunctuationAfterDelete(blocks, deletedIds) {
94225
+ const textOf = (block) => (block.text || (block.textPreview ?? "").replace(/…\s*$/, "")).trimEnd();
94226
+ const endingOf = (block) => {
94227
+ const text = textOf(block);
94228
+ const closers = ITEM_CLOSERS.exec(text)?.[0] ?? "";
94229
+ const body = text.slice(0, text.length - closers.length).trimEnd();
94230
+ const ending = ITEM_ENDING.exec(body);
94231
+ return {
94232
+ core: ending?.[0].trim() ?? "",
94233
+ real: ending ? `${ending[0].trim()}${closers}` : closers,
94234
+ closers,
94235
+ conjunction: CONJUNCTION_TAIL.exec(body)?.[0].trim() ?? null
94236
+ };
94237
+ };
94238
+ const quote = (block) => {
94239
+ const text = textOf(block);
94240
+ return JSON.stringify(text.length > 40 ? `...${text.slice(-40)}` : text);
94241
+ };
94242
+ const change = (block, to) => {
94243
+ const ending = endingOf(block);
94244
+ return `change the ending of ${quote(block)} (nodeId ${block.nodeId}) from "${ending.real}" to "${to}${ending.closers}"`;
94245
+ };
94246
+ const entries = [];
94247
+ const covered = new Set;
94248
+ blocks.forEach((block, index) => {
94249
+ if (!deletedIds.has(block.nodeId) || covered.has(block.nodeId))
94250
+ return;
94251
+ const slot = enumerationSlotOf(block);
94252
+ if (!slot)
94253
+ return;
94254
+ const run = enumerationRunOf(blocks, index, slot, textOf);
94255
+ for (const item of run)
94256
+ covered.add(item.nodeId);
94257
+ const survivors = run.filter((item) => !deletedIds.has(item.nodeId));
94258
+ if (survivors.length === 0)
94259
+ return;
94260
+ const last = survivors[survivors.length - 1];
94261
+ const penultimate = survivors.length >= 2 ? survivors[survivors.length - 2] : undefined;
94262
+ const originalPenultimate = run[run.length - 2];
94263
+ if (run.some((item) => item !== originalPenultimate && endingOf(item).conjunction))
94264
+ return;
94265
+ const runEnd = run[run.length - 1];
94266
+ if (!deletedIds.has(runEnd.nodeId))
94267
+ return;
94268
+ const tail = originalPenultimate ? endingOf(originalPenultimate).conjunction : null;
94269
+ const separator = tail ? tail.charAt(0) : ";";
94270
+ const closing = endingOf(runEnd).core || ".";
94271
+ const lastEnding = endingOf(last);
94272
+ if (lastEnding.core === ":")
94273
+ return;
94274
+ const needsClose = lastEnding.core !== closing && (lastEnding.conjunction != null || lastEnding.core === separator);
94275
+ const needsTail = penultimate != null && tail != null && endingOf(penultimate).core !== ":" && !endingOf(penultimate).conjunction;
94276
+ if (!needsClose && !(needsTail && lastEnding.core !== closing))
94277
+ return;
94278
+ const edits = [
94279
+ `end ${quote(last)} (nodeId ${last.nodeId}) with "${closing}${lastEnding.closers}" instead of "${lastEnding.real}"`
94280
+ ];
94281
+ if (needsTail)
94282
+ edits.push(change(penultimate, tail));
94283
+ entries.push({
94284
+ deleted: runEnd.nodeId,
94285
+ lastItem: last.nodeId,
94286
+ lastItemEnds: lastEnding.real,
94287
+ ...penultimate ? { penultimate: penultimate.nodeId, penultimateEnds: endingOf(penultimate).real } : {},
94288
+ suggestion: `The run now ends at ${quote(last)}: ${edits.join(", and ")}, using replace_text.`
94289
+ });
94290
+ });
94291
+ return entries;
94292
+ }
94125
94293
  async function runDeleteBlocks(doc2, args) {
94126
94294
  const domains = new Set(["blocks", "trackedChanges"]);
94127
94295
  for (const selector of args.selectors) {
@@ -94235,6 +94403,10 @@ async function runDeleteBlocks(doc2, args) {
94235
94403
  }
94236
94404
  const allApplied = deleted.length === targets.length && errors4.length === 0;
94237
94405
  const verified = verification.every((v) => v.passed);
94406
+ let listPunctuation = [];
94407
+ try {
94408
+ listPunctuation = listPunctuationAfterDelete(pre.blocks, new Set(deleted.map((entry) => entry.nodeId)));
94409
+ } catch {}
94238
94410
  return {
94239
94411
  status: !verified || deleted.length === 0 ? "failed" : allApplied ? "ok" : "partial",
94240
94412
  intent: `delete_blocks: ${deleted.length} block(s)`,
@@ -94244,6 +94416,7 @@ async function runDeleteBlocks(doc2, args) {
94244
94416
  executedOperations,
94245
94417
  verification,
94246
94418
  deletedBlocks: deleted,
94419
+ ...listPunctuation.length > 0 ? { listPunctuation } : {},
94247
94420
  ...errors4.length ? { errors: errors4 } : {},
94248
94421
  ...errors4.length ? { nextStep: "Re-inspect the document and retry the selectors that did not resolve to one block." } : {}
94249
94422
  };
@@ -96706,8 +96879,9 @@ async function runScopedReplaceUnchecked(doc2, args) {
96706
96879
  occurrences: spans.length,
96707
96880
  ...edit.occurrence != null ? { occurrence: edit.occurrence } : {}
96708
96881
  });
96709
- for (const span of spans)
96710
- allSpans.push({ ...span, replace: edit.replace, find: edit.find });
96882
+ for (const span of spans) {
96883
+ allSpans.push({ ...span, replace: edit.replace, find: edit.find, editIndex: perEdit.length - 1 });
96884
+ }
96711
96885
  }
96712
96886
  const appliedEdits = perEdit.filter((e) => e.occurrences > 0);
96713
96887
  const skippedEdits = perEdit.filter((e) => e.occurrences === 0);
@@ -96741,6 +96915,23 @@ async function runScopedReplaceUnchecked(doc2, args) {
96741
96915
  planned.push(span);
96742
96916
  lastEnd = span.end;
96743
96917
  }
96918
+ planned.forEach((span, at) => {
96919
+ if (span.replace.trim().length > 0)
96920
+ return;
96921
+ const text = block.text;
96922
+ if (text.charAt(span.start - 1) !== " " || text.charAt(span.end) !== " ")
96923
+ return;
96924
+ if (text.charAt(span.start - 2) === " " || text.charAt(span.end + 1) === " ")
96925
+ return;
96926
+ if (/[.!?]["'\u201d\u2019)\]]*$/.test(text.slice(0, span.start - 1)))
96927
+ return;
96928
+ if ((planned[at + 1]?.start ?? Infinity) <= span.end || (planned[at - 1]?.end ?? -1) >= span.start - 1)
96929
+ return;
96930
+ if (span.replace.length > 0)
96931
+ span.start -= 1;
96932
+ span.end += 1;
96933
+ perEdit[span.editIndex].collapsedSpace = true;
96934
+ });
96744
96935
  const expected = planned.reduceRight((text, span) => text.slice(0, span.start) + span.replace + text.slice(span.end), block.text);
96745
96936
  const tracked = (args.changeMode ?? "direct") === "tracked";
96746
96937
  const uniqueFinds = new Set(planned.map((s) => caseSensitive ? s.find : s.find.toLowerCase()));
@@ -96913,6 +97104,8 @@ function leadInShapeOf(blockText, labelText, quote) {
96913
97104
  return null;
96914
97105
  }
96915
97106
  function leadInSpanOf(text, shape) {
97107
+ if (shape.kind === "typed")
97108
+ return typedCaptionSpanOf(text, shape.delimiter);
96916
97109
  if (shape.kind === "word") {
96917
97110
  const next = text.charAt(shape.label.length);
96918
97111
  return text.startsWith(shape.label) && (next === "" || /\s/.test(next)) ? { start: 0, end: shape.label.length } : null;
@@ -96940,6 +97133,71 @@ function leadInSpanOf(text, shape) {
96940
97133
  const end = leadInEndOf(text, shape.delimiter);
96941
97134
  return end == null ? null : { start: 0, end };
96942
97135
  }
97136
+ function typedMarkerPrefixOf(text) {
97137
+ const match = TYPED_MARKER_PREFIX.exec(text);
97138
+ return match ? { prefix: match[0], marker: match[1] } : null;
97139
+ }
97140
+ function markerShapeOf(text) {
97141
+ const match = LEADING_MARKER_TOKEN.exec(text);
97142
+ if (!match)
97143
+ return null;
97144
+ const token = match[1];
97145
+ const wrapper = token.startsWith("(") ? "paren" : token.endsWith(".") ? "period" : "close";
97146
+ const core2 = token.replace(/^\(/, "").replace(/[.)]$/, "");
97147
+ let kind;
97148
+ if (/^\d/.test(core2))
97149
+ kind = "digit";
97150
+ else if (/^[ivx]+$/.test(core2))
97151
+ kind = "lower-roman";
97152
+ else if (/^[IVX]+$/.test(core2))
97153
+ kind = "upper-roman";
97154
+ else if (/^[a-z]+$/.test(core2))
97155
+ kind = "lower-alpha";
97156
+ else if (/^[A-Z]+$/.test(core2))
97157
+ kind = "upper-alpha";
97158
+ else
97159
+ return null;
97160
+ return { wrapper, kind };
97161
+ }
97162
+ function sameMarkerShape(a, b) {
97163
+ return a != null && b != null && a.wrapper === b.wrapper && a.kind === b.kind;
97164
+ }
97165
+ function markerShapeFits(reference, created) {
97166
+ if (!reference || reference.wrapper !== created.wrapper)
97167
+ return false;
97168
+ if (reference.kind === created.kind)
97169
+ return true;
97170
+ return created.kind === "lower-roman" && reference.kind === "lower-alpha" || created.kind === "upper-roman" && reference.kind === "upper-alpha";
97171
+ }
97172
+ function continuesAlphabet(referenceText, createdText, referenceBefore) {
97173
+ const letterOf = (text) => /^[a-zA-Z]$/.exec(LEADING_MARKER_TOKEN.exec(text)?.[1]?.replace(/[().]/g, "") ?? "")?.[0];
97174
+ const reference = letterOf(referenceText);
97175
+ const created = letterOf(createdText);
97176
+ return reference != null && created != null && created.charCodeAt(0) - reference.charCodeAt(0) === (referenceBefore ? 1 : -1);
97177
+ }
97178
+ function isTitleLike(caption) {
97179
+ const words = caption.match(/\p{L}+/gu) ?? [];
97180
+ const capitalised = words.filter((word) => /^\p{Lu}/u.test(word)).length;
97181
+ return words.length > 0 && words.every((word) => word.length < 4 || /^\p{Lu}/u.test(word)) && capitalised * 2 >= words.length;
97182
+ }
97183
+ function typedCaptionSpanOf(text, delimiter = ".") {
97184
+ const typed = typedMarkerPrefixOf(text);
97185
+ const mark = delimiter.trim();
97186
+ if (!typed || !mark)
97187
+ return null;
97188
+ const start = typed.prefix.length;
97189
+ for (let at = text.indexOf(mark, start);at >= 0; at = text.indexOf(mark, at + 1)) {
97190
+ const end = at + mark.length;
97191
+ if (end - start > TYPED_CAPTION_MAX_CHARS)
97192
+ return null;
97193
+ if (at === start || !/\s/.test(text.charAt(end)))
97194
+ continue;
97195
+ if (!isTitleLike(text.slice(start, at)))
97196
+ return null;
97197
+ return text.slice(end).trim().length > 0 ? { start, end } : null;
97198
+ }
97199
+ return null;
97200
+ }
96943
97201
  function sliceWholeChars(text, end) {
96944
97202
  if (end >= text.length)
96945
97203
  return text;
@@ -96980,7 +97238,10 @@ async function listItemRunPattern(doc2, text, blockId) {
96980
97238
  if (!queryFn || !text.trim())
96981
97239
  return null;
96982
97240
  const delimiterAt = leadInEndOf(text);
96983
- const windowEnd = delimiterAt != null ? delimiterAt + LEAD_IN_BODY_SAMPLE_CHARS : LEAD_IN_BODY_SAMPLE_CHARS;
97241
+ let windowEnd = delimiterAt != null ? delimiterAt + LEAD_IN_BODY_SAMPLE_CHARS : LEAD_IN_BODY_SAMPLE_CHARS;
97242
+ const typedCaption = typedCaptionSpanOf(text);
97243
+ if (typedCaption)
97244
+ windowEnd = Math.max(windowEnd, typedCaption.end + LEAD_IN_BODY_SAMPLE_CHARS);
96984
97245
  const pattern = sliceWholeChars(text, windowEnd);
96985
97246
  const result = asRecord2(await queryFn({ select: { type: "text", pattern } }));
96986
97247
  const items = Array.isArray(result?.items) ? result.items : [];
@@ -96994,6 +97255,9 @@ async function listItemRunPattern(doc2, text, blockId) {
96994
97255
  const runs = (Array.isArray(rec?.runs) ? rec.runs : []).filter((r) => runTextOf(r).length > 0);
96995
97256
  if (runs.length === 0)
96996
97257
  continue;
97258
+ const typedLead = typedPrefixLabelOf(runs, runTextOf);
97259
+ if (typedLead)
97260
+ return typedLead;
96997
97261
  const blockText = asString2(rec?.text, "") ?? "";
96998
97262
  const opener = runTextOf(runs[0]).trim();
96999
97263
  const quote = LEAD_IN_QUOTES.find((q) => opener === q);
@@ -97017,6 +97281,59 @@ async function listItemRunPattern(doc2, text, blockId) {
97017
97281
  }
97018
97282
  return null;
97019
97283
  }
97284
+ function typedPrefixLabelOf(runs, runTextOf) {
97285
+ const typed = typedMarkerPrefixOf(runs.map(runTextOf).join(""));
97286
+ if (!typed)
97287
+ return null;
97288
+ const markerEnd = typed.prefix.indexOf(typed.marker) + typed.marker.length;
97289
+ let covered = 0;
97290
+ let labelIndex = 0;
97291
+ while (labelIndex < runs.length && covered + runTextOf(runs[labelIndex]).length <= typed.prefix.length) {
97292
+ covered += runTextOf(runs[labelIndex]).length;
97293
+ labelIndex += 1;
97294
+ }
97295
+ if (covered < markerEnd || labelIndex + 1 >= runs.length)
97296
+ return null;
97297
+ const underlined = (run) => asRecord2(asRecord2(asRecord2(run)?.styles)?.effective)?.underline === true;
97298
+ const emphasisOf = (run) => {
97299
+ const style = matchRunStyle(run);
97300
+ return `${style.bold}/${style.italic}/${underlined(run)}`;
97301
+ };
97302
+ const label = runs[labelIndex];
97303
+ if (emphasisOf(label) === "false/false/false")
97304
+ return null;
97305
+ const isBlank = (run) => runTextOf(run).trim().length === 0;
97306
+ const continuesLabel = (index) => {
97307
+ if (emphasisOf(runs[index]) === emphasisOf(label))
97308
+ return true;
97309
+ let next = index;
97310
+ while (next < runs.length && isBlank(runs[next]))
97311
+ next += 1;
97312
+ return next > index && next < runs.length && emphasisOf(runs[next]) === emphasisOf(label);
97313
+ };
97314
+ let bodyIndex = labelIndex + 1;
97315
+ while (bodyIndex < runs.length && continuesLabel(bodyIndex))
97316
+ bodyIndex += 1;
97317
+ while (bodyIndex < runs.length - 1 && isBlank(runs[bodyIndex]))
97318
+ bodyIndex += 1;
97319
+ if (bodyIndex >= runs.length)
97320
+ return null;
97321
+ const labelText = runs.slice(labelIndex, bodyIndex).map(runTextOf).join("").trim();
97322
+ if (labelText.length === 0 || labelText.length > LEAD_IN_MAX_CHARS)
97323
+ return null;
97324
+ const delimiter = [".", ...LEAD_IN_DELIMITERS.map((d) => d.trim())].find((d) => labelText.endsWith(d) && labelText.length > d.length);
97325
+ if (!delimiter)
97326
+ return null;
97327
+ const body = runs[bodyIndex];
97328
+ const leadStyle = matchRunStyle(label);
97329
+ const bodyStyle = matchRunStyle(body);
97330
+ const leadUnderline = underlined(label);
97331
+ const bodyUnderline = underlined(body);
97332
+ const look = inlineFromMatchStyle(leadStyle, bodyStyle);
97333
+ if (leadUnderline || bodyUnderline)
97334
+ look.underline = leadUnderline;
97335
+ return { body: inlineFromMatchStyle(bodyStyle), lead: { look, shape: { kind: "typed", delimiter } } };
97336
+ }
97020
97337
  function paragraphIndentOf(payload) {
97021
97338
  const node = isRecord(payload) ? payload.node : null;
97022
97339
  if (!isRecord(node))
@@ -97707,6 +98024,7 @@ async function matchOneBlock(doc2, postBlocks, preIds, created, createdIndex, an
97707
98024
  }
97708
98025
  if (!reference)
97709
98026
  return null;
98027
+ reference = typedShapeReference(postBlocks, preIds, created, createdIndex, createdText, reference, compatibleHeading);
97710
98028
  const applied = {};
97711
98029
  const refNumbering = blockNumbering(reference);
97712
98030
  if (allowNumberingAttach && refNumbering && !blockNumbering(created)) {
@@ -97726,7 +98044,8 @@ async function matchOneBlock(doc2, postBlocks, preIds, created, createdIndex, an
97726
98044
  }
97727
98045
  }
97728
98046
  if (reference.styleId && reference.styleId !== created.styleId) {
97729
- const setStyleFn = maybeMethod2(doc2, ["styles", "paragraph", "setStyle"]);
98047
+ const keepRunMarks = !allowLeadPattern;
98048
+ const setStyleFn = (keepRunMarks ? maybeMethod2(doc2, ["styles", "paragraph", "setStyleRef"]) : null) ?? maybeMethod2(doc2, ["styles", "paragraph", "setStyle"]);
97730
98049
  if (setStyleFn) {
97731
98050
  const target = { kind: "block", nodeType: created.nodeType, nodeId: created.nodeId };
97732
98051
  let canCopyStyle = true;
@@ -97801,6 +98120,38 @@ async function matchOneBlock(doc2, postBlocks, preIds, created, createdIndex, an
97801
98120
  return { matchedSibling: null, skipped: reasonOf(err) };
97802
98121
  }
97803
98122
  }
98123
+ function typedShapeReference(postBlocks, preIds, created, createdIndex, createdText, reference, compatible) {
98124
+ const typed = createdText ? typedMarkerPrefixOf(createdText) : null;
98125
+ if (!typed || createdText.slice(typed.prefix.length).trim().length === 0)
98126
+ return reference;
98127
+ const shape = markerShapeOf(createdText);
98128
+ const referenceShape = markerShapeOf(reference.textPreview ?? "");
98129
+ if (!shape || sameMarkerShape(referenceShape, shape))
98130
+ return reference;
98131
+ const usable = (row) => !!row && preIds.has(row.nodeId) && row.nodeType === created.nodeType && !row.isEmpty && compatible(row);
98132
+ const before = postBlocks.slice(0, createdIndex).reverse().find(usable);
98133
+ const after = postBlocks.slice(createdIndex + 1).find(usable);
98134
+ const continued = [reference, before, after].find((row) => !!row && markerShapeFits(markerShapeOf(row.textPreview ?? ""), shape) && continuesAlphabet(row.textPreview ?? "", createdText, postBlocks.findIndex((b) => b.nodeId === row.nodeId) < createdIndex));
98135
+ if (continued)
98136
+ return continued;
98137
+ const candidate = (row) => {
98138
+ if (!usable(row))
98139
+ return null;
98140
+ const preview = row.textPreview ?? "";
98141
+ return typedMarkerPrefixOf(preview) ? markerShapeOf(preview) : null;
98142
+ };
98143
+ const nearest = (accepts) => {
98144
+ for (let distance = 1;distance < postBlocks.length; distance += 1) {
98145
+ for (const index of [createdIndex - distance, createdIndex + distance]) {
98146
+ const row = postBlocks[index];
98147
+ if (index >= 0 && accepts(candidate(row)))
98148
+ return row;
98149
+ }
98150
+ }
98151
+ return null;
98152
+ };
98153
+ return nearest((rowShape) => sameMarkerShape(rowShape, shape)) ?? nearest((rowShape) => markerShapeFits(rowShape, shape)) ?? reference;
98154
+ }
97804
98155
  async function matchLeadMarkerPattern(doc2, reference, created, createdText) {
97805
98156
  const createdPreview = created.textPreview ?? "";
97806
98157
  if (!reference.nodeId || !created.nodeId || !createdPreview)
@@ -97878,7 +98229,7 @@ async function matchBlockRunPattern(doc2, reference, created, createdText) {
97878
98229
  }
97879
98230
  if (pattern.lead) {
97880
98231
  const span = leadInSpanOf(fullText, pattern.lead.shape);
97881
- const range = span ?? (Object.keys(pattern.body).length === 0 ? { start: 0, end } : null);
98232
+ const range = span ?? (Object.keys(pattern.body).length === 0 && pattern.lead.shape.kind !== "typed" ? { start: 0, end } : null);
97882
98233
  if (range && await applyInlineQuiet(formatFn, { blockId: created.nodeId, ...range, inline: pattern.lead.look })) {
97883
98234
  applied.lead = { ...pattern.lead.look, range: [range.start, range.end] };
97884
98235
  }
@@ -97898,7 +98249,7 @@ async function matchInsertedBlockFormatting(doc2, preBlocks, receipt, args, avai
97898
98249
  const anchorSelector = placement && isRecord(placement.selector) ? placement.selector : null;
97899
98250
  const anchorId = anchorSelector && typeof anchorSelector.nodeId === "string" ? anchorSelector.nodeId : null;
97900
98251
  const anchorRow = anchorId ? postBlocks.find((b) => b.nodeId === anchorId) ?? null : null;
97901
- const rawTexts = Array.isArray(args?.texts) ? args.texts : [];
98252
+ const rawTexts = Array.isArray(args?.texts) ? args.texts : args?.text != null ? [args.text] : [];
97902
98253
  const hasExplicitStyling = rawTexts.some((entry) => isRecord(entry) && (Array.isArray(entry.runs) || entry.marks != null));
97903
98254
  const insertedTexts = rawTexts.map((entry) => {
97904
98255
  if (typeof entry === "string")
@@ -98056,7 +98407,7 @@ async function runAttachNumbering(doc2, args) {
98056
98407
  errors: [
98057
98408
  {
98058
98409
  code: "TARGET_NOT_FOUND",
98059
- message: `no block renders marker ${JSON.stringify(likeMarker)}. Available: ${available.join(" ")}`,
98410
+ message: available.length > 0 ? `no block renders marker ${JSON.stringify(likeMarker)}. Available: ${available.join(" ")}` : rows.some((r) => typedMarkerPrefixOf(r.textPreview ?? "") != null) ? `no block renders marker ${JSON.stringify(likeMarker)}: this document has no numbering scheme; its clause numbers are typed text. ` + `Copy the sibling's typed prefix (tab, next number, tab) into the paragraph text with insert_paragraphs or replace_text, ` + `then renumber the following typed markers with replace_text.` : `no block renders marker ${JSON.stringify(likeMarker)}: no block in this document carries numbering. ` + `To add a paragraph that matches its neighbours use insert_paragraphs next to them; ` + `to start a numbered list use append_list or convert_list.`,
98060
98411
  recovery: { kind: "reinspect" }
98061
98412
  }
98062
98413
  ]
@@ -98983,7 +99334,7 @@ function parseSelector(value) {
98983
99334
  }
98984
99335
  return;
98985
99336
  }
98986
- var ACTION_DEFINITIONS, ACTION_NAMES, ACTION_HINTS, ACTION_ARGS, ACTION_DISPOSITIONS, ACTION_GROUP_LABELS, ACTION_GROUPS, DELETABLE_BLOCK_NODE_TYPES, RUN_BOOL_MARKS, NAMED_COLORS, HEX_COLOR_PATTERN, TWIPS_PER_POINT = 20, LEAD_IN_DELIMITERS, LEAD_IN_MAX_CHARS = 90, LEAD_IN_BODY_SAMPLE_CHARS = 40, LEAD_IN_QUOTES, LEAD_IN_TAIL_DELIMITERS, normMarker = (m) => m.trim().replace(/\.$/, ""), LEAD_MARKER_PATTERN, ACTION_NAMES_LIST;
99337
+ var ACTION_DEFINITIONS, ACTION_NAMES, ACTION_HINTS, ACTION_ARGS, ACTION_DISPOSITIONS, ACTION_GROUP_LABELS, ACTION_GROUPS, TYPED_SIBLING_WINDOW = 20, CONJUNCTION_TAIL, ITEM_ENDING, ITEM_CLOSERS, ROMAN_DIGITS, DELETABLE_BLOCK_NODE_TYPES, RUN_BOOL_MARKS, NAMED_COLORS, HEX_COLOR_PATTERN, TWIPS_PER_POINT = 20, LEAD_IN_DELIMITERS, LEAD_IN_MAX_CHARS = 90, LEAD_IN_BODY_SAMPLE_CHARS = 40, LEAD_IN_QUOTES, LEAD_IN_TAIL_DELIMITERS, TYPED_MARKER_CORE, TYPED_MARKER_TOKEN, TYPED_MARKER_PREFIX, LEADING_MARKER_TOKEN, TYPED_CAPTION_MAX_CHARS = 60, normMarker = (m) => m.trim().replace(/\.$/, ""), LEAD_MARKER_PATTERN, ACTION_NAMES_LIST;
98987
99338
  var init_actions = __esm(() => {
98988
99339
  init_action_descriptors();
98989
99340
  init_execution_context();
@@ -99016,6 +99367,10 @@ var init_actions = __esm(() => {
99016
99367
  label,
99017
99368
  actions: ACTION_NAMES.filter((name) => ACTION_DEFINITIONS[name].group === label).sort((left, right) => ACTION_DEFINITIONS[left].groupOrder - ACTION_DEFINITIONS[right].groupOrder)
99018
99369
  }));
99370
+ CONJUNCTION_TAIL = /[;,]\s*(and|or)\s*$/i;
99371
+ ITEM_ENDING = /(?:[;,]\s*(?:and|or)|[.;,:])\s*$/i;
99372
+ ITEM_CLOSERS = /["'”’)\]]+$/;
99373
+ ROMAN_DIGITS = { i: 1, v: 5, x: 10 };
99019
99374
  DELETABLE_BLOCK_NODE_TYPES = new Set(["paragraph", "heading", "listItem"]);
99020
99375
  RUN_BOOL_MARKS = ["bold", "italic", "underline", "strike"];
99021
99376
  NAMED_COLORS = {
@@ -99036,6 +99391,10 @@ var init_actions = __esm(() => {
99036
99391
  LEAD_IN_DELIMITERS = [":", " — ", " – ", " - ", "—", "–"];
99037
99392
  LEAD_IN_QUOTES = ['"', "“", "‘", "'"];
99038
99393
  LEAD_IN_TAIL_DELIMITERS = [". ", ": ", ...LEAD_IN_DELIMITERS];
99394
+ TYPED_MARKER_CORE = String.raw`(?:\d{1,3}(?:\.\d{1,3})*|[ivx]{1,6}|[IVX]{1,6}|[a-z]{1,2}|[A-Z])`;
99395
+ TYPED_MARKER_TOKEN = String.raw`(?:\(${TYPED_MARKER_CORE}\)|${TYPED_MARKER_CORE}[.)])`;
99396
+ TYPED_MARKER_PREFIX = new RegExp(String.raw`^[ \t]*(${TYPED_MARKER_TOKEN})\t[\t ]*`);
99397
+ LEADING_MARKER_TOKEN = new RegExp(String.raw`^\s*(${TYPED_MARKER_TOKEN})(?=\s|$)`);
99039
99398
  LEAD_MARKER_PATTERN = /^\(?(?:[a-zA-Z]{1,3}|\d{1,3})[).:\]]/;
99040
99399
  ACTION_NAMES_LIST = ACTION_NAMES;
99041
99400
  });
@@ -100224,8 +100583,8 @@ Users speak in what they SEE, not in file-format terms. Translate their words in
100224
100583
  - PLACEMENT: when the user names a position, honor it exactly. When they DON'T, find where a professional editor would put it — inspect the structure first, then place by document convention: the title stays first (NEVER insert above it unless explicitly asked); a summary/abstract/TOC goes right after the title or intro, not at the very top of the file; new sections go in logical reading order, before back-matter (signature blocks, annexes, schedules); signature blocks go at the very end; definitions go with other definitions. Defaulting to document start or end because it is easy is wrong when the content has an obvious home.
100225
100584
  - LEGAL DOCUMENTS ARE CROSS-REFERENCED. Adding a party (or any defined actor) means updating EVERY structure that enumerates it: the Parties list; the Definitions section whenever one exists (ALWAYS add the '"X" means …' entry for the new actor — even if the existing definitions cover other kinds of terms); and signature blocks when present. Same for removals. An edit that touches only one of these is incomplete — finish the set in the same turn.
100226
100585
  - CLEANUP is part of the job. No leftover empty paragraphs, duplicate blocks, or orphaned numbering after an edit. If your edit creates debris, remove it in the same turn.
100227
- - NUMBERS COME FROM SCHEMES, NEVER FROM TEXT. Do not type "11." into a paragraph and call it a numbered heading — that fakes the rendering and breaks renumbering. Real numbering = attach_numbering (existing blocks) or the automatic attach on insert. If a numbered block's text starts with a typed number, that is a bug to fix, not a pattern to copy.
100228
- - NEW SECTIONS in clause-numbered documents (clauses 1.–10.): "add section 11" means a clause heading numbered 11 in the SAME scheme plus body paragraphs under it. Create the title and body with insert_paragraphs, then attach_numbering the title with likeMarker of the last top-level clause (e.g. "10.") — it renders as "11." automatically.
100586
+ - CLAUSE NUMBERS follow the siblings. SCHEME numbering (inspect shows numbering.marker on the blocks): never type a number into the text; a new clause = insert_paragraphs, then attach_numbering with likeMarker of the last sibling (e.g. "10.") and the rest renumbers itself. TYPED numbering (counts.lists is 0 and the siblings' text starts with the number: "\\t4.\\t", "\\t(b)\\t", "\\t(i)\\t"): copy that exact shape into the inserted text (leading tab, next number, tab, caption, two spaces), style a sub-item like an existing sub-item (apply_style likeText), never attach_numbering or append_list there, and renumber what follows yourself in ONE replace_text call: the later markers of the SAME sequence (a new top-level clause shifts the top-level clauses after it, not their (a)/(i) sub-runs, not an attachment's own clauses) AND every "Section N" cross-reference to a moved clause (a clause's reference to itself takes its new number). Schedule, Exhibit, Annex and Appendix labels are not clause numbers: leave them alone. A typed number is the document's convention, not a bug to fix.
100587
+ - REMOVING an item from a lettered or numbered run ("(a) …, (b) … and (c) …", sub-clauses ending "; and") reletters the items that follow and moves the closing conjunction to the new penultimate item, so the last one ends the way the list ends: deleting (iv) from "(ii) …; (iii) …; and (iv) …." takes TWO edits, (ii) "…;" becomes "…; and" and (iii) "…; and" becomes "…." (read (ii) first; it is in the paragraph above). Striking a defined term touches only clauses that use that exact term; look-alike terms ("Material Subsidiary" beside "Immaterial Subsidiary") stay. Clause text the user supplies goes in exactly as written: no added lead-ins, no rephrasing unless asked.
100229
100588
  - NEVER END THE TURN WITH THE DOCUMENT WORSE THAN YOU FOUND IT. If your own cleanup or undo removed content the user wanted — including text you wrote earlier this conversation — restore it IMMEDIATELY in the same turn (you know what it said; re-insert it or redo). Do not ask permission to repair damage you caused.
100230
100589
  - REVIEW means READING. "Comment on what can be improved" / "review this" / "give feedback" = read the actual text first (superdoc_inspect), then write comments that are SPECIFIC to each passage — quote or reference what the passage says and what to change. Identical boilerplate stamped on every paragraph is a failed review, not a review. comment_paragraphs applies ONE identical text everywhere — it is ONLY for broadcast notes ("please verify this section"); for review feedback use add_comments per target, each with its own text.
100231
100590
  - ACT when intent is plain; ask only when the request is genuinely ambiguous AND the wrong guess would be destructive. One clarifying question maximum, with your best-guess default stated.
@@ -100250,15 +100609,15 @@ ACTIONS (superdoc_perform_action with flat args)
100250
100609
  - insert_paragraphs: texts (in final order) — or a single text for one paragraph. headingLevel makes the first item a heading (1-6). changeMode:"tracked" if asked. Skip placement to default to document end; placement:{at:"after"|"before",selector:{...}} to position. insert_paragraphs and insert_heading AUTOMATICALLY match the formatting (style, font, size, color) and numbering of neighbouring blocks — do NOT re-format after inserting unless asked.
100251
100610
  - insert_heading: text, level (1-6).
100252
100611
  - append_list: items (string array), kind:"ordered"|"bullet". headingText/headingLevel only if asked for a heading above. placement:{at:"after"|"before",selector:{...}} builds the list at that block instead of document end — when the list belongs inside a section, ALWAYS pass placement. The receipt's placement-honored check is the truth.
100253
- - add_list_items: entries:[{text, level?}] (level relative to the anchor: 0 = same level, 1 = nested sub-item) — or items:[…] plain strings at the list level. Locate the list by anchorText (text inside one of its items) or listOrdinal (1-based). THE way to ADD items into an EXISTING list — reuses its numbering + markers, matches the anchor item's font/size/bold/colour automatically (receipt.formattingMatched — do NOT re-format after adding unless asked), joins imported list-looking paragraphs in place, and is tracked-safe. NOT append_list (which starts a brand-new list).
100612
+ - add_list_items: entries:[{text, level?}] (level relative to the anchor: 0 = same level, 1 = nested sub-item) — or items:[…] plain strings at the list level. Locate the list by anchorText (text inside one of its items) or listOrdinal (1-based). THE way to ADD items into an EXISTING list or scheme-numbered sequence (never a typed one) — reuses its numbering + markers, matches the anchor item's font/size/bold/colour automatically (receipt.formattingMatched — do NOT re-format after adding unless asked), joins imported list-looking paragraphs in place, and is tracked-safe. NOT append_list (which starts a brand-new list).
100254
100613
  - convert_list: kind:"ordered"|"bullet", with listOrdinal or anchorText for real lists, OR fromMarker+toMarker (rendered clause numbers from inspect, e.g. "2.1.", "2.3.") for NUMBERED-CLAUSE ranges — including heading-styled clauses, OR fromText+toText (exact text inside the FIRST and LAST of consecutive plain paragraphs) to convert existing paragraphs into a list IN PLACE. Sub-clauses in range included automatically. THE way to convert numbering<->bullets AND the way to make existing paragraphs a list; never rewrite text to fake it, never recreate-the-content-then-delete-the-originals (two chances to lose text — convert_list fromText/toText is one lossless call).
100255
100614
  - split_list: anchorText (text inside the item that should START the second list), restartNumbering? (default true). Splits ONE list into two at that item — the new list restarts at 1, nested sub-items stay with their parent. THE way to "split the list starting at item N into a new list with reset numbering"; never fake it with convert_list/attach_numbering. changeMode:"tracked" records the change for review.
100256
100615
  - undo_changes: untilMarker (rendered marker from the original state, e.g. "2.1.") or steps (1-25). Deterministic revert — steps history back until the marker reappears; the receipt proves it. NEVER use steps > 1 blindly: prefer untilMarker, and after ANY undo verify (superdoc_inspect) that content you meant to KEEP still exists — if you overshot, redo_changes {steps:N} steps forward again to recover it.
100257
100616
  - redo_changes: steps (1-25, default 1). Steps history FORWARD to re-apply edits a prior undo removed — THE recovery for an undo overshoot. Only reaches the forward branch until a NEW edit is made.
100258
- - attach_numbering: anchorText (text of the block) or nodeId, likeMarker (rendered marker of a sibling clause, e.g. "10."). Makes an EXISTING block a numbered clause at the same scheme/level — "make this the section 11 heading" in a clause-numbered document is exactly this (it will render as the next number).
100617
+ - attach_numbering: anchorText (text of the block) or nodeId, likeMarker (rendered marker of a sibling clause, e.g. "10."). Scheme numbering only (it fails where the numbers are typed text). Makes an EXISTING block a numbered clause at the same scheme/level — "make this the section 11 heading" in a clause-numbered document is exactly this (it will render as the next number).
100259
100618
  - replace_text: edits:[{find,replace,occurrence?}], caseSensitive default false. selector to scope. Keep find/replace spans MINIMAL. If the find appears more than once in the selected block and only one should change, give that edit occurrence (1 = first match in the block; needs selector; not selector.occurrence). With occurrence, also pass expectedRevision from your latest inspect or receipt; on REVISION_CONFLICT inspect again and recount. changeMode:"tracked" if asked. The receipt reports editsApplied and editsSkipped per find — READ IT: a skipped find is not in the selected block; re-target instead of assuming success.
100260
100619
  - delete_text: finds:[string]. selector to scope deletions to ONE block — REQUIRED for whitespace-only finds (unscoped whitespace matches document-wide and is refused). changeMode:"tracked" if asked. Deletes TEXT ONLY: the block survives, so a list item keeps its bullet/number and an accepted tracked deletion leaves an empty numbered item behind. To remove the item itself use delete_blocks.
100261
- - delete_blocks: selectors:[…], each resolving to ONE block (list item, paragraph or heading). changeMode:"tracked" if asked. THE way to DELETE a whole LIST ITEM, paragraph or heading — the bullet/number goes with it and the remaining items renumber. "Delete the first item under Article II" / "remove that clause" is exactly this, NOT delete_text. Pass every target in ONE call. Use delete_table for a whole table.
100620
+ - delete_blocks: selectors:[…], each resolving to ONE block (list item, paragraph or heading). changeMode:"tracked" if asked. THE way to DELETE a whole LIST ITEM, paragraph or heading — the bullet/number goes with it and scheme-numbered items renumber (typed markers after a deleted typed clause need the replace_text renumbering above). "Delete the first item under Article II" / "remove that clause" is exactly this, NOT delete_text. Pass every target in ONE call. Use delete_table for a whole table. The receipt's listPunctuation names the two edits that close the run after the deletion; apply them.
100262
100621
  - rewrite_block: selector, text. Inspect first to gather current text; never ask the user to paste text already in the doc.
100263
100622
  - create_table: rows, columns, optional cellTexts (2D array). rows counts ALL rows INCLUDING the header — header plus one data row is rows:2. placement defaults to document end. changeMode:"tracked" if asked ("track-changes table") — the insertion itself becomes a tracked change.
100264
100623
  - comment_paragraphs: commentText. excludeBlockQuotes:true to skip block quotes. Applies the SAME text to every BODY paragraph (it does NOT comment the title/heading) — broadcast notes only, never review feedback (see REVIEW rule). To comment a heading too, add_comments on it explicitly.
@@ -100304,7 +100663,7 @@ OPERATING RULES
100304
100663
  - REVERTS: "undo / revert / make it back" = superdoc_perform_action undo_changes with untilMarker from the original state (a convert receipt's revertHint contains the exact call) — NEVER re-convert or re-edit to approximate the old state.
100305
100664
  - If the request names a target descriptively ("the indented heading", "the second clause"), inspect FIRST and use the block's actual text or nodeId — never invent find text.
100306
100665
  - Numbered legal clauses ("2.3.") usually live on numbered HEADINGS, not lists: if counts.lists is 0 but blocks carry numbering markers, target those blocks by nodeId. "Add item 2.4" = insert_paragraphs (one text) after the "2.3." block; the tool attaches numbering and matches formatting automatically (check receipt.contextualFormatting).
100307
- - ADDING SEVERAL items to an existing list or numbered sequence = ONE add_list_items call (it joins the sequence and is tracked-safe — it works even when the "list" is clause numbering and counts.lists is 0). NEVER a chain of insert_paragraphs calls: multi-paragraph inserts do not auto-join numbering, and the items will land as plain paragraphs.
100666
+ - ADDING SEVERAL items to an existing list or scheme-numbered sequence = ONE add_list_items call (it joins the sequence and is tracked-safe — it works even when the "list" is clause numbering with markers and counts.lists is 0). NEVER a chain of insert_paragraphs calls there: multi-paragraph inserts do not auto-join numbering, and the items will land as plain paragraphs. TYPED sequences are the exception: ONE insert_paragraphs call whose texts carry the typed markers.
100308
100667
  - New SECTION headings use the SAME headingLevel as sibling section headings (title is usually level 1; sections 2+). Never default to level 1.
100309
100668
  - paragraphOrdinal counts visible non-empty paragraphs; bodyParagraphOrdinal counts substantive body paragraphs after front matter. Prefer paragraphOrdinal for "first/second paragraph".
100310
100669
  - For literal ordinal rewrites, do not switch paragraphs because the matched one looks title-like or short. If a rewrite is a no-op, keep the target and change the rewrite.
@@ -218056,6 +218415,7 @@ function compileSemanticStyleDependencies(state, requestedRoles, roleStyleIdHint
218056
218415
  const occupied = new Set(Object.keys(records));
218057
218416
  const styleIdByRole = new Map;
218058
218417
  const definitions = [];
218418
+ const hasThemePart = documentHasThemePart(state);
218059
218419
  for (const role of roles) {
218060
218420
  const resolution = index.resolve(role);
218061
218421
  if (resolution.status === "authored") {
@@ -218082,6 +218442,8 @@ function compileSemanticStyleDependencies(state, requestedRoles, roleStyleIdHint
218082
218442
  });
218083
218443
  if (!definition)
218084
218444
  return { ok: false, reason: "style-reference-not-found" };
218445
+ if (!hasThemePart)
218446
+ withoutThemeReferences(definition);
218085
218447
  definitions.push(definition);
218086
218448
  occupied.add(styleId);
218087
218449
  records[styleId] = definition;
@@ -218453,7 +218815,52 @@ function byteWindowPrecondition3(partUri, bytes) {
218453
218815
  exactLength: bytes.length
218454
218816
  };
218455
218817
  }
218456
- var TE22, TD48, CONTENT_TYPES_NS3 = "http://schemas.openxmlformats.org/package/2006/content-types", STYLES_PART_URI, CONTENT_TYPES_PART_URI4 = "/[Content_Types].xml", STYLES_CONTENT_TYPE, STYLES_RELATIONSHIP_TYPE;
218818
+ function withoutThemeReferences(definition) {
218819
+ const run = definition.runProperties;
218820
+ if (!run)
218821
+ return;
218822
+ const fontFamily = run.fontFamily;
218823
+ if (fontFamily) {
218824
+ const literal3 = {};
218825
+ for (const [key3, value] of Object.entries(fontFamily)) {
218826
+ if (!/Theme$|^cstheme$/i.test(key3))
218827
+ literal3[key3] = value;
218828
+ }
218829
+ const ascii = fontFamily.ascii ?? THEME_FONT_FALLBACKS[fontFamily.asciiTheme ?? ""];
218830
+ const hAnsi = fontFamily.hAnsi ?? THEME_FONT_FALLBACKS[fontFamily.hAnsiTheme ?? ""] ?? ascii;
218831
+ if (ascii)
218832
+ literal3.ascii = ascii;
218833
+ if (hAnsi)
218834
+ literal3.hAnsi = hAnsi;
218835
+ if (Object.keys(literal3).length)
218836
+ run.fontFamily = literal3;
218837
+ else
218838
+ delete run.fontFamily;
218839
+ }
218840
+ const color = run.color;
218841
+ if (color?.themeColor) {
218842
+ if (color.val)
218843
+ run.color = { val: color.val };
218844
+ else
218845
+ delete run.color;
218846
+ }
218847
+ }
218848
+ function documentHasThemePart(state) {
218849
+ const relsUri = "/word/_rels/document.xml.rels";
218850
+ const relsBytes = ensurePackagePartBytes(state, relsUri);
218851
+ if (relsBytes) {
218852
+ const rels = parseRelationshipsXml(new TextDecoder().decode(relsBytes), {
218853
+ ownerPartUri: "/word/document.xml",
218854
+ relsUri,
218855
+ resolveTarget: (target, mode) => mode === "External" ? target : resolveTargetUri("/word/document.xml", target, mode, state.parts)
218856
+ });
218857
+ const related = rels.relationships.some((rel) => rel.targetMode === "Internal" && rel.type.endsWith("/relationships/theme") && state.parts.has(rel.resolvedTarget));
218858
+ if (related)
218859
+ return true;
218860
+ }
218861
+ return [...state.parts.keys()].some((uri) => /\/theme\/theme\d*\.xml$/i.test(uri));
218862
+ }
218863
+ var TE22, TD48, CONTENT_TYPES_NS3 = "http://schemas.openxmlformats.org/package/2006/content-types", STYLES_PART_URI, CONTENT_TYPES_PART_URI4 = "/[Content_Types].xml", STYLES_CONTENT_TYPE, STYLES_RELATIONSHIP_TYPE, THEME_FONT_FALLBACKS;
218457
218864
  var init_semantic_style_dependencies = __esm(() => {
218458
218865
  init_semantic_style_roles();
218459
218866
  init_semantic_style_definitions();
@@ -218468,6 +218875,12 @@ var init_semantic_style_dependencies = __esm(() => {
218468
218875
  STYLES_PART_URI = CANONICAL_STYLE_DEFINITIONS_PART_URI;
218469
218876
  STYLES_CONTENT_TYPE = CONTENT_TYPE_FOR_KIND.styles;
218470
218877
  STYLES_RELATIONSHIP_TYPE = RELATIONSHIP_TYPE_FOR_KIND.styles;
218878
+ THEME_FONT_FALLBACKS = {
218879
+ majorHAnsi: "Calibri Light",
218880
+ majorAscii: "Calibri Light",
218881
+ minorHAnsi: "Calibri",
218882
+ minorAscii: "Calibri"
218883
+ };
218471
218884
  });
218472
218885
 
218473
218886
  // ../../../v2/editor-core/dist/document/transactions/types.js
@@ -223018,6 +223431,7 @@ function runListApplyCommit(input) {
223018
223431
  const paraRewrite = trackedFormatting ? rewriteParagraphNumPrTracked(paraXml, { numId: chosenNumId, ilvl }, trackedFormatting) : rewriteParagraphNumPr(paraXml, { numId: chosenNumId, ilvl });
223019
223432
  if (!paraRewrite.ok)
223020
223433
  return rejected4(input.txId, paraRewrite.reason);
223434
+ const recordedRevision = recordedFormatting(trackedFormatting, paraRewrite);
223021
223435
  const paragraphPatch = {
223022
223436
  kind: "replaceBytes",
223023
223437
  order: 0,
@@ -223059,10 +223473,10 @@ function runListApplyCommit(input) {
223059
223473
  perPart,
223060
223474
  preconditions,
223061
223475
  extraPatchMaps,
223062
- createdRefs: trackedFormatting ? [
223476
+ createdRefs: recordedRevision ? [
223063
223477
  {
223064
223478
  kind: "trackedChange",
223065
- entityId: trackedFormatting.entityKey,
223479
+ entityId: recordedRevision.entityKey,
223066
223480
  storyId: op.target.storyId
223067
223481
  }
223068
223482
  ] : [],
@@ -223260,10 +223674,11 @@ function runListApplyRangeCommit(input) {
223260
223674
  const paraRewrite = trackedFormatting ? rewriteParagraphNumPrTracked(target.paraXml, { numId: chosenNumId, ilvl: writeIlvl }, trackedFormatting) : rewriteParagraphNumPr(target.paraXml, { numId: chosenNumId, ilvl: writeIlvl });
223261
223675
  if (!paraRewrite.ok)
223262
223676
  return rejected4(input.txId, paraRewrite.reason);
223263
- if (trackedFormatting) {
223677
+ const recordedRevision = recordedFormatting(trackedFormatting, paraRewrite);
223678
+ if (recordedRevision) {
223264
223679
  trackedCreatedRefs.push({
223265
223680
  kind: "trackedChange",
223266
- entityId: trackedFormatting.entityKey,
223681
+ entityId: recordedRevision.entityKey,
223267
223682
  storyId: op.target.storyId
223268
223683
  });
223269
223684
  }
@@ -223438,6 +223853,7 @@ function runListRestartCommit(input) {
223438
223853
  });
223439
223854
  if (!paraRewrite.ok)
223440
223855
  return rejected4(input.txId, paraRewrite.reason);
223856
+ const recordedRevision = recordedFormatting(trackedFormatting, paraRewrite);
223441
223857
  const paragraphPatch = {
223442
223858
  kind: "replaceBytes",
223443
223859
  order: 0,
@@ -223481,10 +223897,10 @@ function runListRestartCommit(input) {
223481
223897
  extraPatchMaps: {
223482
223898
  [NUMBERING_PART_URI]: { partUri: NUMBERING_PART_URI, ranges: [] }
223483
223899
  },
223484
- createdRefs: trackedFormatting ? [
223900
+ createdRefs: recordedRevision ? [
223485
223901
  {
223486
223902
  kind: "trackedChange",
223487
- entityId: trackedFormatting.entityKey,
223903
+ entityId: recordedRevision.entityKey,
223488
223904
  storyId: op.target.storyId
223489
223905
  }
223490
223906
  ] : [],
@@ -223725,7 +224141,7 @@ function changeIlvlRange(input, delta) {
223725
224141
  entry: target.entry,
223726
224142
  paraXml,
223727
224143
  nextXml: rewrite.xml,
223728
- trackedEntityKey: trackedFormatting?.entityKey ?? null
224144
+ trackedEntityKey: recordedFormatting(trackedFormatting, rewrite)?.entityKey ?? null
223729
224145
  });
223730
224146
  }
223731
224147
  if (!storyPartUri || !storyBytes)
@@ -223825,15 +224241,16 @@ function runListRemoveCommit(input) {
223825
224241
  const rewrite = trackedFormatting ? wrapParagraphTrackedChange(directRewrite.xml, paraXml, trackedFormatting) : directRewrite;
223826
224242
  if (!rewrite.ok)
223827
224243
  return rejected4(input.txId, rewrite.reason);
224244
+ const recordedRevision = recordedFormatting(trackedFormatting, rewrite);
223828
224245
  return commitParagraphRewrite({
223829
224246
  input,
223830
224247
  target,
223831
224248
  bytes,
223832
224249
  nextXml: rewrite.xml,
223833
- createdRefs: trackedFormatting ? [
224250
+ createdRefs: recordedRevision ? [
223834
224251
  {
223835
224252
  kind: "trackedChange",
223836
- entityId: trackedFormatting.entityKey,
224253
+ entityId: recordedRevision.entityKey,
223837
224254
  storyId: op.target.storyId
223838
224255
  }
223839
224256
  ] : [],
@@ -224110,15 +224527,16 @@ function commitParagraphNumPrRewrite(args) {
224110
224527
  const rewrite = args.trackedFormatting ? rewriteParagraphNumPrTracked(args.paraXml, args.numPr, args.trackedFormatting, args.paragraphStyleId) : rewriteParagraphNumPr(args.paraXml, args.numPr, args.paragraphStyleId);
224111
224528
  if (!rewrite.ok)
224112
224529
  return rejected4(args.input.txId, rewrite.reason);
224530
+ const recordedRevision = recordedFormatting(args.trackedFormatting, rewrite);
224113
224531
  return commitParagraphRewrite({
224114
224532
  input: args.input,
224115
224533
  target: args.target,
224116
224534
  bytes: args.bytes,
224117
224535
  nextXml: rewrite.xml,
224118
- createdRefs: args.trackedFormatting ? [
224536
+ createdRefs: recordedRevision ? [
224119
224537
  {
224120
224538
  kind: "trackedChange",
224121
- entityId: args.trackedFormatting.entityKey,
224539
+ entityId: recordedRevision.entityKey,
224122
224540
  storyId: args.input.op.target.storyId
224123
224541
  }
224124
224542
  ] : [],
@@ -224208,6 +224626,9 @@ function buildTrackedListFormattingAllocator(input, storyId) {
224208
224626
  }
224209
224627
  };
224210
224628
  }
224629
+ function recordedFormatting(tracked, rewrite) {
224630
+ return tracked && rewrite.recorded ? tracked : undefined;
224631
+ }
224211
224632
  function rewriteParagraphNumPrTracked(paraXml, numPr, tracked, paragraphStyleId) {
224212
224633
  const direct = rewriteParagraphNumPr(paraXml, numPr, paragraphStyleId);
224213
224634
  if (!direct.ok)
@@ -224223,6 +224644,9 @@ function wrapParagraphTrackedChange(nextParaXml, beforeParaXml, tracked) {
224223
224644
  if (existingChange && existingChange.author !== tracked.author) {
224224
224645
  return { ok: false, reason: "list-tracked-wrapper-unsupported" };
224225
224646
  }
224647
+ if (beforeBlock && paragraphMarkInsertedBy(beforeBlock.inner, tracked.author) || paragraphMarkInsertedBy(afterBlock.inner, tracked.author)) {
224648
+ return { ok: true, xml: nextParaXml, recorded: false };
224649
+ }
224226
224650
  const beforeXml = buildParagraphPropertyBaseSnapshot(existingChange?.innerXml ?? beforeBlock?.fullXml, afterBlock.prefix);
224227
224651
  const afterInner = removeParagraphPropertyChangeBlocks(afterBlock.inner);
224228
224652
  const names = wordNamesForPrefix(afterBlock.prefix);
@@ -224231,9 +224655,23 @@ function wrapParagraphTrackedChange(nextParaXml, beforeParaXml, tracked) {
224231
224655
  const replacement2 = `${afterBlock.openTag}${afterInner}${wrapper}${afterBlock.closeTag}`;
224232
224656
  return {
224233
224657
  ok: true,
224234
- xml: nextParaXml.slice(0, afterBlock.start) + replacement2 + nextParaXml.slice(afterBlock.end)
224658
+ xml: nextParaXml.slice(0, afterBlock.start) + replacement2 + nextParaXml.slice(afterBlock.end),
224659
+ recorded: true
224235
224660
  };
224236
224661
  }
224662
+ function paragraphMarkInsertedBy(pPrInner, author) {
224663
+ const markProps = /<(?:\w+:)?rPr\b[^>]*>([\s\S]*?)<\/(?:\w+:)?rPr>/.exec(pPrInner)?.[1];
224664
+ if (!markProps)
224665
+ return false;
224666
+ const ins = /<(?:\w+:)?ins\b([^>]*)\/?>/.exec(markProps)?.[1];
224667
+ if (ins == null)
224668
+ return false;
224669
+ const insAuthor = /(?:^|\s)(?:\w+:)?author="([^"]*)"/.exec(ins)?.[1];
224670
+ return insAuthor != null && unescapeAttr(insAuthor) === author;
224671
+ }
224672
+ function unescapeAttr(value) {
224673
+ return value.replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
224674
+ }
224237
224675
  function directXmlChildren(xml) {
224238
224676
  const tagPattern = /<\/?([\w.-]+):([\w.-]+)\b[^>]*>/g;
224239
224677
  const children = [];
@@ -271539,7 +271977,7 @@ function prepareLocalCommentInsert(state, bytes, range, commentId) {
271539
271977
  });
271540
271978
  if (!rewritten.ok)
271541
271979
  return rewritten;
271542
- const after = TE46.encode(rewritten.xml);
271980
+ const after = TE46.encode(hoistCommentAnchorsOutOfTrackedWrappers(rewritten.xml, commentId));
271543
271981
  const evidence = commentParagraphEvidence(bytes, paragraph, paragraph.byteStart, paragraph.byteEnd, after.length);
271544
271982
  return evidence ? {
271545
271983
  ok: true,
@@ -271586,10 +272024,30 @@ function rewriteDocumentXml(documentXml, range, commentId, commentReferenceXml,
271586
272024
  });
271587
272025
  if (!rewritten.ok)
271588
272026
  return rewritten;
271589
- xml = xml.slice(0, p.byteStart) + rewritten.xml + xml.slice(p.byteEnd);
272027
+ xml = xml.slice(0, p.byteStart) + hoistCommentAnchorsOutOfTrackedWrappers(rewritten.xml, commentId) + xml.slice(p.byteEnd);
271590
272028
  }
271591
272029
  return { ok: true, xml };
271592
272030
  }
272031
+ function hoistCommentAnchorsOutOfTrackedWrappers(paragraphXml, commentId) {
272032
+ const id = commentId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
272033
+ const start = `(?:\\s*<(?:[\\w.-]+:)?commentRangeStart\\b[^>]*\\bw:id="${id}"[^>]*/>)`;
272034
+ const end = `(?:\\s*<(?:[\\w.-]+:)?commentRangeEnd\\b[^>]*\\bw:id="${id}"[^>]*/>)`;
272035
+ const reference = `(?:\\s*<(?:[\\w.-]+:)?r\\b[^>]*>(?:<(?:[\\w.-]+:)?rPr>[\\s\\S]*?</(?:[\\w.-]+:)?rPr>)?<(?:[\\w.-]+:)?commentReference\\b[^>]*\\bw:id="${id}"[^>]*/></(?:[\\w.-]+:)?r>)`;
272036
+ const leading = new RegExp(`^(${start}+)`);
272037
+ const trailing = new RegExp(`(${end}(?:${reference})?)\\s*$`);
272038
+ const wrapper = /<((?:[\w.-]+:)?(?:ins|del))\b([^>]*)>([\s\S]*?)<\/\1>/g;
272039
+ return paragraphXml.replace(wrapper, (whole, tag, attrs, inner) => {
272040
+ const before = leading.exec(inner)?.[1] ?? "";
272041
+ let body = inner.slice(before.length);
272042
+ const tail = trailing.exec(body);
272043
+ const after = tail ? body.slice(tail.index) : "";
272044
+ body = tail ? body.slice(0, tail.index) : body;
272045
+ if (!before && !after)
272046
+ return whole;
272047
+ const kept = body.trim() ? `<${tag}${attrs}>${body}</${tag}>` : "";
272048
+ return `${before}${kept}${after}`;
272049
+ });
272050
+ }
271593
272051
  function prepareCommentAnchor(documentXml, range, inheritedNamespaceBindings) {
271594
272052
  if (range.startBlockId !== range.endBlockId)
271595
272053
  return null;
@@ -326296,22 +326754,75 @@ function setPageBordersXml(sectPrXml, borders) {
326296
326754
  function clearPageBordersXml(sectPrXml) {
326297
326755
  return removeSectPrChild(sectPrXml, "pgBorders");
326298
326756
  }
326299
- function setOddEvenHeadersFootersXml(context, enabled, options) {
326300
- const settingsBytes = readPartBytes2(context, SETTINGS_PART_URI5);
326301
- if (!settingsBytes) {
326302
- return { ok: false, failure: { code: "PRECONDITION_FAILED", message: "settings.xml bytes are unavailable." } };
326757
+ function prepareSettingsPart(context) {
326758
+ const relsBytes = readPartBytes2(context, DOCUMENT_RELS_PART_URI12);
326759
+ const relsXml = relsBytes ? readPartXml(context, DOCUMENT_RELS_PART_URI12) ?? "" : EMPTY_RELATIONSHIPS_XML3;
326760
+ const rels = readDocumentRelationships(relsXml);
326761
+ const related = rels.settingsUri;
326762
+ const settingsUri = related ?? SETTINGS_PART_URI5;
326763
+ const settingsBytes = readPartBytes2(context, settingsUri);
326764
+ if (settingsBytes) {
326765
+ return {
326766
+ ok: true,
326767
+ xml: readPartXml(context, settingsUri) ?? "",
326768
+ perPart: (nextXml) => ({ [settingsUri]: replaceWholePartEntry(settingsBytes, encodeXml(nextXml)) })
326769
+ };
326770
+ }
326771
+ if (related) {
326772
+ return { ok: false, failure: { code: "PRECONDITION_FAILED", message: `settings part ${related} is related but unreadable.` } };
326303
326773
  }
326304
- const settingsXml = readPartXml(context, SETTINGS_PART_URI5) ?? "";
326305
- const nextXml = enabled ? upsertSettingsChild(settingsXml, "evenAndOddHeaders", "<w:evenAndOddHeaders/>") : removeSettingsChild(settingsXml, "evenAndOddHeaders");
326774
+ if (rels.parseError) {
326775
+ return { ok: false, failure: { code: "PRECONDITION_FAILED", message: `document relationships are unreadable: ${rels.parseError}` } };
326776
+ }
326777
+ const contentTypesBytes = readPartBytes2(context, CONTENT_TYPES_PART_URI14);
326778
+ if (!contentTypesBytes) {
326779
+ return { ok: false, failure: { code: "PRECONDITION_FAILED", message: "[Content_Types].xml bytes are unavailable." } };
326780
+ }
326781
+ let index = 1;
326782
+ while (rels.ids.has(`rId${index}`))
326783
+ index += 1;
326784
+ const nextRelsXml = addRelationship(relsXml, { id: `rId${index}`, type: SETTINGS_REL, target: "settings.xml" });
326785
+ const nextContentTypesXml = addContentTypeOverride(readPartXml(context, CONTENT_TYPES_PART_URI14) ?? "", SETTINGS_PART_URI5, SETTINGS_CT);
326786
+ return {
326787
+ ok: true,
326788
+ xml: EMPTY_SETTINGS_XML,
326789
+ perPart: (nextXml) => ({
326790
+ [SETTINGS_PART_URI5]: { kind: "create", bytes: encodeXml(nextXml), contentType: SETTINGS_CT },
326791
+ [DOCUMENT_RELS_PART_URI12]: relsBytes ? replaceWholePartEntry(relsBytes, encodeXml(nextRelsXml)) : { kind: "create", bytes: encodeXml(nextRelsXml), contentType: RELATIONSHIPS_CT },
326792
+ [CONTENT_TYPES_PART_URI14]: replaceWholePartEntry(contentTypesBytes, encodeXml(nextContentTypesXml))
326793
+ })
326794
+ };
326795
+ }
326796
+ function readableSettingsPartUri(context) {
326797
+ return readDocumentRelationships(readPartXml(context, DOCUMENT_RELS_PART_URI12) ?? "").settingsUri ?? SETTINGS_PART_URI5;
326798
+ }
326799
+ function readDocumentRelationships(relsXml) {
326800
+ if (!relsXml.trim())
326801
+ return { settingsUri: null, ids: new Set, parseError: null };
326802
+ const parsed = parseRelationshipsXml(relsXml, {
326803
+ ownerPartUri: DOCUMENT_PART_URI5,
326804
+ relsUri: DOCUMENT_RELS_PART_URI12,
326805
+ resolveTarget: (target, mode) => mode === "External" ? target : resolveTargetUri(DOCUMENT_PART_URI5, target, mode)
326806
+ });
326807
+ const settings = parsed.relationships.find((rel) => rel.targetMode === "Internal" && rel.type.endsWith("/relationships/settings"));
326808
+ return {
326809
+ settingsUri: settings?.resolvedTarget ?? null,
326810
+ ids: new Set(parsed.relationships.map((rel) => rel.id)),
326811
+ parseError: parsed.parseError
326812
+ };
326813
+ }
326814
+ function setOddEvenHeadersFootersXml(context, enabled, options) {
326815
+ const settings = prepareSettingsPart(context);
326816
+ if (!settings.ok)
326817
+ return settings;
326818
+ const nextXml = enabled ? upsertSettingsChild(settings.xml, "evenAndOddHeaders", "<w:evenAndOddHeaders/>") : removeSettingsChild(settings.xml, "evenAndOddHeaders");
326306
326819
  if (options?.dryRun)
326307
326820
  return { ok: true, dryRun: true };
326308
326821
  const committed = commitKernelStorySurfacePatch({
326309
326822
  context,
326310
326823
  txIdPrefix: "sections-settings",
326311
326824
  expectedRevision: options?.expectedRevision,
326312
- perPart: {
326313
- [SETTINGS_PART_URI5]: replaceWholePartEntry(settingsBytes, encodeXml(nextXml))
326314
- },
326825
+ perPart: settings.perPart(nextXml),
326315
326826
  signalLanesToRebuild: ["sections"]
326316
326827
  });
326317
326828
  if (!committed.ok)
@@ -326520,12 +327031,14 @@ function borderElement(name, border) {
326520
327031
  attrs.frame = border.frame ? "1" : "0";
326521
327032
  return emptyElement(name, attrs);
326522
327033
  }
326523
- var RELATIONSHIPS_NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", LIVE_SECTION_SIGNALS_CACHE, SECTPR_CHILD_ORDER, SECTPR_CHILD_RANK;
327034
+ var RELATIONSHIPS_NAMESPACE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", LIVE_SECTION_SIGNALS_CACHE, SETTINGS_CT = "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", SETTINGS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings", RELATIONSHIPS_CT = "application/vnd.openxmlformats-package.relationships+xml", EMPTY_SETTINGS_XML, EMPTY_RELATIONSHIPS_XML3, SECTPR_CHILD_ORDER, SECTPR_CHILD_RANK;
326524
327035
  var init_section_xml = __esm(() => {
326525
327036
  init_xml();
326526
327037
  init_sd_document_session_internal();
326527
327038
  init_tracked_pr_change();
326528
327039
  LIVE_SECTION_SIGNALS_CACHE = new WeakMap;
327040
+ EMPTY_SETTINGS_XML = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '<w:settings xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"></w:settings>';
327041
+ EMPTY_RELATIONSHIPS_XML3 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
326529
327042
  SECTPR_CHILD_ORDER = [
326530
327043
  "headerReference",
326531
327044
  "footerReference",
@@ -327310,7 +327823,8 @@ function insertXmlAtCollapsedTopLevelWrapperBoundary(paragraphXml, offset, inser
327310
327823
  const childTextEnd = childTextStart + visibleTextLength3(childXml);
327311
327824
  textCursor = childTextEnd;
327312
327825
  cursor = childEnd;
327313
- if (!COLLAPSED_INSERTION_BOUNDARY_WRAPPERS.has(localName2) || childTextStart === childTextEnd) {
327826
+ const boundaryChild = COLLAPSED_INSERTION_BOUNDARY_WRAPPERS.has(localName2) || localName2 === "r" && !parsePlainRun2(childXml, childTextStart, childStart, childEnd).ok;
327827
+ if (!boundaryChild || childTextStart === childTextEnd) {
327314
327828
  continue;
327315
327829
  }
327316
327830
  if (offset === childTextStart) {
@@ -327442,7 +327956,9 @@ function insertXmlAtRangeStartInSimpleFieldResultInParagraphXml(input) {
327442
327956
  return { ok: true, xml };
327443
327957
  }
327444
327958
  function projectMatchRuns(input) {
327445
- const collected = collectPlainTextRuns2(input.paragraphXml, input.rangeStart, input.rangeEnd);
327959
+ const collected = collectPlainTextRuns2(input.paragraphXml, input.rangeStart, input.rangeEnd, {
327960
+ splitMixedRuns: true
327961
+ });
327446
327962
  if (!collected.ok) {
327447
327963
  input.onProjectionUnavailable?.();
327448
327964
  return [
@@ -327528,7 +328044,7 @@ function collectPlainTextRuns2(paragraphXml, rangeStart, rangeEnd, options = {})
327528
328044
  const markers = scanComplexFieldMarkers2(childXml);
327529
328045
  complexFieldDepth = Math.max(0, complexFieldDepth + markers.begins - markers.ends);
327530
328046
  complexFieldResultDepth = Math.max(0, complexFieldResultDepth + markers.separates - markers.ends);
327531
- const parsed = parsePlainRun2(childXml, childTextStart, cursor - childXml.length, cursor);
328047
+ const parsed = options.splitMixedRuns ? parsePlainRunLeaves(childXml, childTextStart, cursor - childXml.length, cursor) : parsePlainRun2(childXml, childTextStart, cursor - childXml.length, cursor);
327532
328048
  if (!parsed.ok) {
327533
328049
  if (intersects) {
327534
328050
  return { ok: false, reason: parsed.reason };
@@ -327544,7 +328060,10 @@ function collectPlainTextRuns2(paragraphXml, rangeStart, rangeEnd, options = {})
327544
328060
  if (fieldDepthBefore > 0 && fieldResultDepthBefore > 0 && !options.allowFieldResultContent && rangesOverlap7(childTextStart, childTextEnd, rangeStart, rangeEnd)) {
327545
328061
  return { ok: false, reason: "text-range-in-field" };
327546
328062
  }
327547
- runs.push(parsed.run);
328063
+ if ("runs" in parsed)
328064
+ runs.push(...parsed.runs);
328065
+ else
328066
+ runs.push(parsed.run);
327548
328067
  continue;
327549
328068
  }
327550
328069
  if (localName2 === "ins" || localName2 === "del" || localName2 === "moveFrom" || localName2 === "moveTo") {
@@ -327637,6 +328156,63 @@ function parsePlainRun2(runXml, textStart, xmlStart, xmlEnd) {
327637
328156
  }
327638
328157
  };
327639
328158
  }
328159
+ function parsePlainRunLeaves(runXml, textStart, xmlStart, xmlEnd) {
328160
+ const single = parsePlainRun2(runXml, textStart, xmlStart, xmlEnd);
328161
+ if (single.ok)
328162
+ return { ok: true, runs: [single.run] };
328163
+ if (single.reason !== "invalid-range")
328164
+ return single;
328165
+ const run = parseContainerXml(runXml, "r");
328166
+ if (!run)
328167
+ return single;
328168
+ const children2 = parseTopLevelChildren(run.inner);
328169
+ const rPr = getChildXml(children2, "rPr") ?? "";
328170
+ const runs = [];
328171
+ let cursor = textStart;
328172
+ for (const child of children2) {
328173
+ if (child.localName === "rPr")
328174
+ continue;
328175
+ let text;
328176
+ let kind;
328177
+ if (child.localName === "t") {
328178
+ text = decodeXmlText8(child.xml.replace(/^<[\w.-]+:t\b[^>]*>|<\/[\w.-]+:t>$/g, ""));
328179
+ kind = "text";
328180
+ } else if (child.localName === "tab") {
328181
+ text = "\t";
328182
+ kind = "tab";
328183
+ } else if (child.localName === "br" || child.localName === "cr") {
328184
+ const breakType = child.localName === "br" ? readAttr2(child.xml, "type") : null;
328185
+ if (child.localName === "br" && breakType && breakType !== "textWrapping") {
328186
+ return { ok: false, reason: "unsupported-context" };
328187
+ }
328188
+ text = `
328189
+ `;
328190
+ kind = child.localName;
328191
+ } else {
328192
+ const marker = child.localName === "bookmarkStart" || child.localName === "bookmarkEnd" || child.localName === "commentRangeStart" || child.localName === "commentRangeEnd" || child.localName === "commentReference";
328193
+ if (marker)
328194
+ continue;
328195
+ return single;
328196
+ }
328197
+ runs.push({
328198
+ kind,
328199
+ xmlStart,
328200
+ xmlEnd,
328201
+ xml: runXml,
328202
+ open: run.open,
328203
+ prefix: run.prefix,
328204
+ textStart: cursor,
328205
+ textEnd: cursor + text.length,
328206
+ text,
328207
+ rPr,
328208
+ leafXml: kind === "text" ? null : child.xml
328209
+ });
328210
+ cursor += text.length;
328211
+ }
328212
+ if (runs.length === 0 || cursor - textStart !== visibleTextLength3(runXml))
328213
+ return single;
328214
+ return { ok: true, runs };
328215
+ }
327640
328216
  function buildRunSpan2(runs, rangeStart, rangeEnd) {
327641
328217
  if (rangeEnd <= rangeStart)
327642
328218
  return { ok: false, reason: "invalid-range" };
@@ -336816,12 +337392,18 @@ function pushTrackedSourceMap(map3, sourceId, changeId) {
336816
337392
  function visibleParagraphTextFromXml(xml) {
336817
337393
  const stripped = stripTextboxContent2(stripParagraphProperties3(stripDeletedRevisions(xml)));
336818
337394
  let out = "";
336819
- for (const token of stripped.matchAll(/<[\w.-]+:t\b[^>]*>([\s\S]*?)<\/[\w.-]+:t>|<[\w.-]+:(tab|br|cr)\b[^>]*\/>/g)) {
337395
+ for (const token of stripped.matchAll(/<(?:[\w.-]+:)?t\b(?![^>]*\/>)[^>]*>([\s\S]*?)<\/(?:[\w.-]+:)?t>|<(?:[\w.-]+:)?(tab|br|cr|noBreakHyphen|footnoteReference|endnoteReference)\b[^>]*\/?>/g)) {
336820
337396
  if (token[1] != null) {
336821
337397
  out += decodeXmlText9(token[1]);
336822
337398
  continue;
336823
337399
  }
336824
- out += token[2] === "tab" ? "\t" : `
337400
+ const control2 = token[2];
337401
+ if (control2 === "noBreakHyphen")
337402
+ out += "‑";
337403
+ else if (control2 === "footnoteReference" || control2 === "endnoteReference")
337404
+ out += "";
337405
+ else
337406
+ out += control2 === "tab" ? "\t" : `
336825
337407
  `;
336826
337408
  }
336827
337409
  return out;
@@ -336909,9 +337491,9 @@ function visibleTrackedChangeSourceSlicesFromXml(xml, qualified, storyId) {
336909
337491
  const slices = [];
336910
337492
  const activeSourceIdStack = [];
336911
337493
  const elementStack = [];
336912
- let delDepth = 0;
337494
+ let removalDepth = 0;
336913
337495
  let cursor = 0;
336914
- const tokenRe = /<\/(?:[\w.-]+:)?(ins|del|moveFrom|moveTo)>|<(?:[\w.-]+:)?t\b[^>]*>([\s\S]*?)<\/(?:[\w.-]+:)?t>|<(?:[\w.-]+:)?delText\b[^>]*>([\s\S]*?)<\/(?:[\w.-]+:)?delText>|<(?:[\w.-]+:)?(ins|del|moveFrom|moveTo|tab|br|cr)\b([^>]*)\/?>/g;
337496
+ const tokenRe = /<\/(?:[\w.-]+:)?(ins|del|moveFrom|moveTo)>|<(?:[\w.-]+:)?t\b(?![^>]*\/>)[^>]*>([\s\S]*?)<\/(?:[\w.-]+:)?t>|<(?:[\w.-]+:)?delText\b(?![^>]*\/>)[^>]*>([\s\S]*?)<\/(?:[\w.-]+:)?delText>|<(?:[\w.-]+:)?(ins|del|moveFrom|moveTo|tab|br|cr|noBreakHyphen|footnoteReference|endnoteReference)\b([^>]*)\/?>/g;
336915
337497
  for (const match of stripped.matchAll(tokenRe)) {
336916
337498
  const closingName = match[1];
336917
337499
  const tText = match[2];
@@ -336922,12 +337504,12 @@ function visibleTrackedChangeSourceSlicesFromXml(xml, qualified, storyId) {
336922
337504
  const frame = elementStack.pop();
336923
337505
  if (frame?.hadId)
336924
337506
  activeSourceIdStack.pop();
336925
- if (closingName === "del")
336926
- delDepth = Math.max(0, delDepth - 1);
337507
+ if (closingName === "del" || closingName === "moveFrom")
337508
+ removalDepth = Math.max(0, removalDepth - 1);
336927
337509
  continue;
336928
337510
  }
336929
337511
  if (tText != null) {
336930
- if (delDepth > 0) {
337512
+ if (removalDepth > 0) {
336931
337513
  pushZeroWidthTrackedSourceSlice(slices, cursor, activeSourceIdStack);
336932
337514
  } else {
336933
337515
  cursor = pushTrackedSourceSlice(slices, cursor, decodeXmlText9(tText).length, activeSourceIdStack);
@@ -336940,8 +337522,8 @@ function visibleTrackedChangeSourceSlicesFromXml(xml, qualified, storyId) {
336940
337522
  }
336941
337523
  if (!openingName)
336942
337524
  continue;
336943
- if (openingName === "tab" || openingName === "br" || openingName === "cr") {
336944
- if (delDepth > 0) {
337525
+ if (openingName === "tab" || openingName === "br" || openingName === "cr" || openingName === "noBreakHyphen" || openingName === "footnoteReference" || openingName === "endnoteReference") {
337526
+ if (removalDepth > 0) {
336945
337527
  pushZeroWidthTrackedSourceSlice(slices, cursor, activeSourceIdStack);
336946
337528
  } else {
336947
337529
  cursor = pushTrackedSourceSlice(slices, cursor, 1, activeSourceIdStack);
@@ -336956,8 +337538,8 @@ function visibleTrackedChangeSourceSlicesFromXml(xml, qualified, storyId) {
336956
337538
  elementStack.push({ name: openingName, hadId: Boolean(sourceId) });
336957
337539
  if (sourceId)
336958
337540
  activeSourceIdStack.push(sourceId);
336959
- if (openingName === "del")
336960
- delDepth += 1;
337541
+ if (openingName === "del" || openingName === "moveFrom")
337542
+ removalDepth += 1;
336961
337543
  }
336962
337544
  }
336963
337545
  return slices;
@@ -337002,7 +337584,7 @@ function stripParagraphProperties3(xml) {
337002
337584
  return stripElements(xml, "pPr");
337003
337585
  }
337004
337586
  function stripDeletedRevisions(xml) {
337005
- return xml.replace(/<[\w.-]+:del\b(?![^>]*\/>)[^>]*>[\s\S]*?<\/[\w.-]+:del>/g, "");
337587
+ return stripElements(stripElements(xml, "del"), "moveFrom");
337006
337588
  }
337007
337589
  function stripTextboxContent2(xml) {
337008
337590
  return xml.replace(/<(?:[\w.-]+:)?txbxContent\b[^>]*>[\s\S]*?<\/(?:[\w.-]+:)?txbxContent>/g, "").replace(/<(?:[\w.-]+:)?txbxContent\b[^>]*>[\s\S]*$/g, "");
@@ -366818,12 +367400,25 @@ function greedyTokenMatches(before, after, aStart, aEnd, bStart, bEnd) {
366818
367400
  }
366819
367401
  return matches;
366820
367402
  }
367403
+ function wordTokens(text4) {
367404
+ const out = [];
367405
+ for (const chunk of text4.match(/\S+|\s+/gu) ?? []) {
367406
+ const trailing = /\S/.test(chunk) ? TRAILING_PUNCTUATION.exec(chunk)?.[0] : undefined;
367407
+ if (trailing && trailing.length < chunk.length) {
367408
+ out.push(chunk.slice(0, chunk.length - trailing.length));
367409
+ for (const mark of trailing)
367410
+ out.push(mark);
367411
+ } else {
367412
+ out.push(chunk);
367413
+ }
367414
+ }
367415
+ return out;
367416
+ }
366821
367417
  function narrowTextReplacement(before, after) {
366822
367418
  if (before === after)
366823
367419
  return null;
366824
- const tokens = /[\p{L}\p{N}\p{M}_]+|\s+|[^\p{L}\p{N}\p{M}_\s]/gu;
366825
- const oldTokens = before.match(tokens) ?? [];
366826
- const newTokens = after.match(tokens) ?? [];
367420
+ const oldTokens = wordTokens(before);
367421
+ const newTokens = wordTokens(after);
366827
367422
  let prefix2 = 0;
366828
367423
  let start = 0;
366829
367424
  while (prefix2 < oldTokens.length && prefix2 < newTokens.length && oldTokens[prefix2] === newTokens[prefix2]) {
@@ -366844,9 +367439,8 @@ function planTextReplacement(before, after) {
366844
367439
  const boundary = narrowTextReplacement(before, after);
366845
367440
  if (!boundary)
366846
367441
  return [];
366847
- const tokens = /[\p{L}\p{N}\p{M}_]+|\s+|[^\p{L}\p{N}\p{M}_\s]/gu;
366848
- const oldTokens = before.slice(boundary.start, boundary.end).match(tokens) ?? [];
366849
- const newTokens = boundary.text.match(tokens) ?? [];
367442
+ const oldTokens = wordTokens(before.slice(boundary.start, boundary.end));
367443
+ const newTokens = wordTokens(boundary.text);
366850
367444
  const matches = [];
366851
367445
  const oldValues = new Set(oldTokens);
366852
367446
  if (!newTokens.some((token) => oldValues.has(token)))
@@ -366938,6 +367532,10 @@ function planTextReplacement(before, after) {
366938
367532
  }
366939
367533
  return spans;
366940
367534
  }
367535
+ var TRAILING_PUNCTUATION;
367536
+ var init_replacement_span = __esm(() => {
367537
+ TRAILING_PUNCTUATION = /[.,;:!?)\]}'"\u00bb\u2019\u201d]+$/u;
367538
+ });
366941
367539
 
366942
367540
  // ../../../v2/document-api-v2-adapter/dist/selection-mutation/structural-rewrite-span.js
366943
367541
  function planTrackedRewriteReplacement(before, after, scope) {
@@ -366978,6 +367576,7 @@ function rewriteRangeContainsCoupledStructure(paragraphXml, start, end, coordina
366978
367576
  }
366979
367577
  var init_structural_rewrite_span = __esm(() => {
366980
367578
  init_sd_document_session_internal();
367579
+ init_replacement_span();
366981
367580
  });
366982
367581
 
366983
367582
  // ../../../v2/document-api-v2-adapter/dist/fields/tracked-field-removal.js
@@ -372159,6 +372758,7 @@ var init_adapter7 = __esm(() => {
372159
372758
  init_mutation_guard();
372160
372759
  init_story_surface();
372161
372760
  init_textbox_story();
372761
+ init_replacement_span();
372162
372762
  init_structural_rewrite_span();
372163
372763
  init_runtime2();
372164
372764
  init_tracked_field_removal();
@@ -391768,7 +392368,7 @@ function projectSectionDomain(mainStory, section, index2, oddEvenHeadersFooters)
391768
392368
  };
391769
392369
  }
391770
392370
  function readLiveOddEvenHeadersFooters(context, snapshot2) {
391771
- const settingsXml = readPartXml(context, SETTINGS_PART_URI5);
392371
+ const settingsXml = readPartXml(context, readableSettingsPartUri(context));
391772
392372
  if (!settingsXml)
391773
392373
  return projectToggle(snapshot2.settings?.evenAndOddHeaders ?? null) ?? false;
391774
392374
  const match = /<w:evenAndOddHeaders\b[^>]*\/?>/i.exec(settingsXml);
@@ -392329,6 +392929,7 @@ class V2CreateAdapter {
392329
392929
  });
392330
392930
  const carrierParagraph = `<w:p><w:pPr>${sectPrPlan.previousSectPr}</w:pPr></w:p>`;
392331
392931
  let nextXml;
392932
+ let splitSectionIndex = null;
392332
392933
  if (!input.at || input.at.kind === "documentEnd") {
392333
392934
  if (representation === "attachToPreviousParagraph") {
392334
392935
  const attached = attachSectPrToPreviousBodyParagraph(documentXml, sectPrPlan);
@@ -392344,8 +392945,24 @@ class V2CreateAdapter {
392344
392945
  nextXml = documentXml.replace(/<\/w:body>/, `${carrierParagraph}${sectPrPlan.finalSectPr}</w:body>`);
392345
392946
  }
392346
392947
  }
392948
+ } else if ((input.at.kind === "before" || input.at.kind === "after") && input.at.target?.kind === "block" && (!input.at.target.story || input.at.target.story.storyType === "body")) {
392949
+ if (options?.changeMode === "tracked") {
392950
+ return createFailure("CAPABILITY_UNAVAILABLE", "create.sectionBreak records only document-end breaks as tracked changes.");
392951
+ }
392952
+ const placed = placeSectionBreakAtBodyParagraph(documentXml, {
392953
+ nodeId: input.at.target.nodeId,
392954
+ placement: input.at.kind,
392955
+ representation,
392956
+ breakType,
392957
+ pageMargins: input.pageMargins,
392958
+ headerFooterMargins: input.headerFooterMargins
392959
+ });
392960
+ if (!placed.ok)
392961
+ return createFailure(placed.code, placed.message);
392962
+ nextXml = placed.xml;
392963
+ splitSectionIndex = placed.sectionIndex;
392347
392964
  } else {
392348
- return createFailure("INVALID_TARGET", "create.sectionBreak currently supports body documentEnd targets on v2.");
392965
+ return createFailure("INVALID_TARGET", "create.sectionBreak supports documentEnd and before/after a body paragraph on v2.");
392349
392966
  }
392350
392967
  const dryRun = options?.dryRun || input.dryRun;
392351
392968
  const createdRefs = [];
@@ -392378,8 +392995,8 @@ class V2CreateAdapter {
392378
392995
  if (!committed.ok)
392379
392996
  return createFailure(committed.code, committed.message);
392380
392997
  const sectionItems = new V2SectionsAdapter(this.context).list().items;
392381
- const lastSectionId = sectionItems[sectionItems.length - 1]?.id;
392382
- const section = { kind: "section", sectionId: lastSectionId ?? "section-0" };
392998
+ const createdSectionId = splitSectionIndex === null ? sectionItems[sectionItems.length - 1]?.id : sectionItems[splitSectionIndex]?.id;
392999
+ const section = { kind: "section", sectionId: createdSectionId ?? "section-0" };
392383
393000
  const trackedChangeRefs = projectTrackedStructuralEntityIds(this.context, createdRefs.flatMap((ref5) => ref5.kind === "trackedChange" ? [ref5.entityId] : [])).map((entityId) => ({ kind: "entity", entityType: "trackedChange", entityId }));
392384
393001
  return { success: true, section, ...trackedChangeRefs.length ? { trackedChangeRefs } : {} };
392385
393002
  }
@@ -392801,6 +393418,54 @@ function attachSectPrToPreviousBodyParagraph(documentXml, plan) {
392801
393418
  xml: documentXml.slice(0, body.start + target.start) + merged + documentXml.slice(body.start + target.end, finalStart) + plan.finalSectPr + documentXml.slice(finalEnd)
392802
393419
  };
392803
393420
  }
393421
+ function placeSectionBreakAtBodyParagraph(documentXml, input) {
393422
+ const body = readBodyInnerWithOffsets(documentXml);
393423
+ if (!body)
393424
+ return { ok: false, code: "PRECONDITION_FAILED", message: "document body was not found." };
393425
+ const children2 = scanDirectBodyChildrenWithOffsets(body.inner);
393426
+ const index2 = children2.findIndex((child) => isWordParagraphQName2(child.qname) && bodyParagraphIdOf(body.inner.slice(child.start, child.end)) === input.nodeId);
393427
+ if (index2 < 0) {
393428
+ return { ok: false, code: "INVALID_TARGET", message: "The target is not a body paragraph with a durable id; re-inspect and pass its nodeId." };
393429
+ }
393430
+ const boundary = body.start + (input.placement === "after" ? children2[index2].end : children2[index2].start);
393431
+ if (!findAllElements(documentXml, "sectPr").some((element) => element.start >= boundary)) {
393432
+ const bodyEnd = body.start + body.inner.length;
393433
+ documentXml = `${documentXml.slice(0, bodyEnd)}<w:sectPr/>${documentXml.slice(bodyEnd)}`;
393434
+ }
393435
+ const sectPrs = findAllElements(documentXml, "sectPr");
393436
+ const sectionIndex = sectPrs.findIndex((element) => element.start >= boundary);
393437
+ const governing = sectPrs[sectionIndex];
393438
+ if (!governing)
393439
+ return { ok: false, code: "PRECONDITION_FAILED", message: "The body has no section properties after the target." };
393440
+ const closingSectPr = setSectionBreakTypeXml(governing.xml, input.breakType);
393441
+ let trailingSectPr = governing.xml;
393442
+ if (input.pageMargins)
393443
+ trailingSectPr = setPageMarginsXml(trailingSectPr, input.pageMargins);
393444
+ if (input.headerFooterMargins)
393445
+ trailingSectPr = setPageMarginsXml(trailingSectPr, input.headerFooterMargins);
393446
+ let xml = `${documentXml.slice(0, governing.start)}${trailingSectPr}${documentXml.slice(governing.end)}`;
393447
+ if (input.representation === "attachToPreviousParagraph") {
393448
+ const carrier = children2[input.placement === "after" ? index2 : index2 - 1];
393449
+ if (!carrier || !isWordParagraphQName2(carrier.qname)) {
393450
+ return { ok: false, code: "INVALID_TARGET", message: 'No body paragraph ends the section at that boundary; use representation "asNewParagraph".' };
393451
+ }
393452
+ const carrierXml = body.inner.slice(carrier.start, carrier.end);
393453
+ if (findFirstElement(carrierXml, "sectPr")) {
393454
+ return { ok: false, code: "INVALID_TARGET", message: "That paragraph already carries a section break." };
393455
+ }
393456
+ const merged = mergeSectPrIntoParagraph(carrierXml, closingSectPr);
393457
+ if (!merged)
393458
+ return { ok: false, code: "INVALID_TARGET", message: "That paragraph cannot carry this section break." };
393459
+ xml = xml.slice(0, body.start + carrier.start) + merged + xml.slice(body.start + carrier.end);
393460
+ return { ok: true, xml, sectionIndex };
393461
+ }
393462
+ xml = `${xml.slice(0, boundary)}<w:p><w:pPr>${closingSectPr}</w:pPr></w:p>${xml.slice(boundary)}`;
393463
+ return { ok: true, xml, sectionIndex };
393464
+ }
393465
+ function bodyParagraphIdOf(paragraphXml) {
393466
+ const open2 = /^<w:p\b[^>]*>/.exec(paragraphXml)?.[0] ?? "";
393467
+ return /\sw14:paraId="([^"]+)"/.exec(open2)?.[1] ?? null;
393468
+ }
392804
393469
  function readBodyInnerWithOffsets(documentXml) {
392805
393470
  const bodyOpen = /<[\w.-]+:body\b[^>]*>/.exec(documentXml);
392806
393471
  if (!bodyOpen)
@@ -406713,8 +407378,8 @@ function createHeaderFooterPart(context, input, options) {
406713
407378
  const relType = input.kind === "header" ? HEADER_REL2 : FOOTER_REL2;
406714
407379
  const nextRelsXml = addRelationship(relsXml, { id: refId, type: relType, target: partUri.replace(/^\/word\//, "") });
406715
407380
  let nextContentTypesXml = addContentTypeOverride(contentTypesXml, partUri, contentType);
406716
- if (Object.keys(clonedRelationships.perPart).length > 0 && parseContentTypes(contentTypesXml).defaults.get("rels") !== RELATIONSHIPS_CT) {
406717
- nextContentTypesXml = addContentTypeOverride(nextContentTypesXml, relsUriFor(partUri), RELATIONSHIPS_CT);
407381
+ if (Object.keys(clonedRelationships.perPart).length > 0 && parseContentTypes(contentTypesXml).defaults.get("rels") !== RELATIONSHIPS_CT2) {
407382
+ nextContentTypesXml = addContentTypeOverride(nextContentTypesXml, relsUriFor(partUri), RELATIONSHIPS_CT2);
406718
407383
  }
406719
407384
  const partPath = partUri.replace(/^\//, "");
406720
407385
  if (options?.dryRun)
@@ -406871,8 +407536,8 @@ function prepareHeaderFooterSlotMaterialization(context, target, additionalTarge
406871
407536
  const relType = input.kind === "header" ? HEADER_REL2 : FOOTER_REL2;
406872
407537
  const nextRelsXml = addRelationship(relsXml, { id: refId, type: relType, target: partUri.replace(/^\/word\//, "") });
406873
407538
  let nextContentTypesXml = addContentTypeOverride(contentTypesXml, partUri, contentType);
406874
- if (Object.keys(clonedRelationships.perPart).length > 0 && parseContentTypes(contentTypesXml).defaults.get("rels") !== RELATIONSHIPS_CT) {
406875
- nextContentTypesXml = addContentTypeOverride(nextContentTypesXml, relsUriFor(partUri), RELATIONSHIPS_CT);
407539
+ if (Object.keys(clonedRelationships.perPart).length > 0 && parseContentTypes(contentTypesXml).defaults.get("rels") !== RELATIONSHIPS_CT2) {
407540
+ nextContentTypesXml = addContentTypeOverride(nextContentTypesXml, relsUriFor(partUri), RELATIONSHIPS_CT2);
406876
407541
  }
406877
407542
  const prepared = prepareHeaderFooterRefTargetsSectionXmlMutationsUnchecked(context, [normalizedTarget, ...normalizedAdditionalTargets], refId);
406878
407543
  if (!prepared.ok)
@@ -406945,15 +407610,15 @@ function prepareClonedPartRelationships(context, sourcePartUri, destinationPartU
406945
407610
  [relsUriFor(destinationPartUri)]: {
406946
407611
  kind: "create",
406947
407612
  bytes: cloned.value === sourceXml ? new Uint8Array(sourceBytes) : encodeXml(cloned.value),
406948
- contentType: RELATIONSHIPS_CT
407613
+ contentType: RELATIONSHIPS_CT2
406949
407614
  }
406950
407615
  } };
406951
407616
  }
406952
407617
  function prepareDocumentRelationshipsPart(context) {
406953
407618
  const existingBytes = readPartBytes2(context, DOCUMENT_RELS_PART_URI12);
406954
407619
  return {
406955
- xml: existingBytes ? readPartXml(context, DOCUMENT_RELS_PART_URI12) ?? "" : EMPTY_RELATIONSHIPS_XML3,
406956
- buildPatch: (nextXml) => existingBytes ? replaceWholePartEntry(existingBytes, encodeXml(nextXml)) : { kind: "create", bytes: encodeXml(nextXml), contentType: RELATIONSHIPS_CT }
407620
+ xml: existingBytes ? readPartXml(context, DOCUMENT_RELS_PART_URI12) ?? "" : EMPTY_RELATIONSHIPS_XML4,
407621
+ buildPatch: (nextXml) => existingBytes ? replaceWholePartEntry(existingBytes, encodeXml(nextXml)) : { kind: "create", bytes: encodeXml(nextXml), contentType: RELATIONSHIPS_CT2 }
406957
407622
  };
406958
407623
  }
406959
407624
  function resolveTrailingFinalSectionInheritedRefTarget(context, target) {
@@ -407198,7 +407863,7 @@ function structuredError3(code2, message) {
407198
407863
  error48.code = code2;
407199
407864
  return error48;
407200
407865
  }
407201
- var HEADER_CT2 = "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml", FOOTER_CT2 = "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml", HEADER_REL2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", FOOTER_REL2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", RELATIONSHIPS_CT = "application/vnd.openxmlformats-package.relationships+xml", EMPTY_RELATIONSHIPS_XML3;
407866
+ var HEADER_CT2 = "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml", FOOTER_CT2 = "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml", HEADER_REL2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", FOOTER_REL2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", RELATIONSHIPS_CT2 = "application/vnd.openxmlformats-package.relationships+xml", EMPTY_RELATIONSHIPS_XML4;
407202
407867
  var init_adapter18 = __esm(() => {
407203
407868
  init_src3();
407204
407869
  init_sd_document_session_internal();
@@ -407207,7 +407872,7 @@ var init_adapter18 = __esm(() => {
407207
407872
  init_xml();
407208
407873
  init_xml3();
407209
407874
  init_section_xml();
407210
- EMPTY_RELATIONSHIPS_XML3 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
407875
+ EMPTY_RELATIONSHIPS_XML4 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
407211
407876
  });
407212
407877
 
407213
407878
  // ../../../v2/document-api-v2-adapter/dist/address/materialize-slot.js
@@ -440750,6 +441415,7 @@ var init_engine3 = __esm(() => {
440750
441415
  init_query_adapter();
440751
441416
  init_within();
440752
441417
  init_tracked_text_search();
441418
+ init_replacement_span();
440753
441419
  init_structural_rewrite_span();
440754
441420
  init_adapter7();
440755
441421
  init_adapter17();
@@ -441843,7 +442509,7 @@ function preparePicturePlan(context, part, input, shapeId, contentTypesXml) {
441843
442509
  return { ok: false, message: "Header relationships path could not be resolved." };
441844
442510
  const preparedRels = part.perPart[relsUri];
441845
442511
  const existingRelsBytes = resultingWholePartBytes(context, relsUri, preparedRels);
441846
- const relsXml = existingRelsBytes ? TD133.decode(existingRelsBytes) : EMPTY_RELATIONSHIPS_XML4;
442512
+ const relsXml = existingRelsBytes ? TD133.decode(existingRelsBytes) : EMPTY_RELATIONSHIPS_XML5;
441847
442513
  const imageRefId = allocateRId2(relsXml);
441848
442514
  const mediaPartUri = allocateMediaPartUri(context, decoded.format);
441849
442515
  const mediaTarget = relativeTarget3(part.partUri, mediaPartUri);
@@ -441859,7 +442525,7 @@ function preparePicturePlan(context, part, input, shapeId, contentTypesXml) {
441859
442525
  bytes: decoded.binary,
441860
442526
  contentType: imageMimeType2(decoded.format)
441861
442527
  },
441862
- [relsUri]: preparedRels?.kind === "create" ? { kind: "create", bytes: encodeXml(nextRelsXml), contentType: RELATIONSHIPS_CT2 } : readPartBytes2(context, relsUri) ? replaceWholePartEntry(readPartBytes2(context, relsUri), encodeXml(nextRelsXml)) : { kind: "create", bytes: encodeXml(nextRelsXml), contentType: RELATIONSHIPS_CT2 }
442528
+ [relsUri]: preparedRels?.kind === "create" ? { kind: "create", bytes: encodeXml(nextRelsXml), contentType: RELATIONSHIPS_CT3 } : readPartBytes2(context, relsUri) ? replaceWholePartEntry(readPartBytes2(context, relsUri), encodeXml(nextRelsXml)) : { kind: "create", bytes: encodeXml(nextRelsXml), contentType: RELATIONSHIPS_CT3 }
441863
442529
  };
441864
442530
  return {
441865
442531
  ok: true,
@@ -441875,7 +442541,7 @@ function removePictureResources(context, entry, perPart, contentTypesXml) {
441875
442541
  if (!relsUri || !entry.imageRefId || !entry.mediaPartUri)
441876
442542
  return { contentTypesXml };
441877
442543
  const relsBytes = readPartBytes2(context, relsUri);
441878
- const relsXml = relsBytes ? TD133.decode(relsBytes) : EMPTY_RELATIONSHIPS_XML4;
442544
+ const relsXml = relsBytes ? TD133.decode(relsBytes) : EMPTY_RELATIONSHIPS_XML5;
441879
442545
  const remainingPartXml = replaceExactlyOnce4(entry.partXml, entry.pictXml, "");
441880
442546
  if (remainingPartXml && [...remainingPartXml.matchAll(/<[A-Za-z_][^>]*>/g)].some((match) => ["r:id", "r:embed", "r:link"].some((attribute3) => xmlAttribute3(match[0], attribute3) === entry.imageRefId))) {
441881
442547
  return { contentTypesXml };
@@ -442169,7 +442835,7 @@ function readAspectLock(pictXml) {
442169
442835
  return /^(?:t|true|1)$/.test(instanceLock[1] ?? instanceLock[2] ?? "");
442170
442836
  return /<o:lock\b[^>]*\baspectratio=["'](?:t|true|1)["']/.test(pictXml);
442171
442837
  }
442172
- var IMAGE_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", RELATIONSHIPS_CT2 = "application/vnd.openxmlformats-package.relationships+xml", EMPTY_RELATIONSHIPS_XML4, TD133;
442838
+ var IMAGE_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", RELATIONSHIPS_CT3 = "application/vnd.openxmlformats-package.relationships+xml", EMPTY_RELATIONSHIPS_XML5, TD133;
442173
442839
  var init_parts = __esm(() => {
442174
442840
  init_sd_document_session_internal();
442175
442841
  init_adapter18();
@@ -442179,7 +442845,7 @@ var init_parts = __esm(() => {
442179
442845
  init_xml();
442180
442846
  init_xml3();
442181
442847
  init_serialization();
442182
- EMPTY_RELATIONSHIPS_XML4 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
442848
+ EMPTY_RELATIONSHIPS_XML5 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
442183
442849
  TD133 = new TextDecoder;
442184
442850
  });
442185
442851
 
@@ -442401,7 +443067,7 @@ function applyWatermarks(context, input, options) {
442401
443067
  perPart[header.partUri] = partPatch(context, header.partUri, encodeXml(header.xml), HEADER_CT3);
442402
443068
  const relsUri = relsPartUriForPart2(header.partUri);
442403
443069
  if (header.relsXml !== EMPTY_RELS || readPartBytes2(context, relsUri) || perPart[relsUri])
442404
- perPart[relsUri] = partPatch(context, relsUri, encodeXml(header.relsXml), RELATIONSHIPS_CT3);
443070
+ perPart[relsUri] = partPatch(context, relsUri, encodeXml(header.relsXml), RELATIONSHIPS_CT4);
442405
443071
  }
442406
443072
  for (const mediaPartUri of new Set(removedImages.map((entry) => entry.mediaPartUri))) {
442407
443073
  if (isReferencedInFinalRelationships(context, perPart, mediaPartUri))
@@ -442410,7 +443076,7 @@ function applyWatermarks(context, input, options) {
442410
443076
  contentTypesXml = removeContentTypeOverride(contentTypesXml, mediaPartUri);
442411
443077
  }
442412
443078
  if (documentRelsXml !== (readPartXml(context, DOCUMENT_RELS_PART_URI12) ?? EMPTY_RELS))
442413
- perPart[DOCUMENT_RELS_PART_URI12] = partPatch(context, DOCUMENT_RELS_PART_URI12, encodeXml(documentRelsXml), RELATIONSHIPS_CT3);
443079
+ perPart[DOCUMENT_RELS_PART_URI12] = partPatch(context, DOCUMENT_RELS_PART_URI12, encodeXml(documentRelsXml), RELATIONSHIPS_CT4);
442414
443080
  if (contentTypesXml !== readPartXml(context, CONTENT_TYPES_PART_URI14))
442415
443081
  perPart[CONTENT_TYPES_PART_URI14] = partPatch(context, CONTENT_TYPES_PART_URI14, encodeXml(contentTypesXml), "application/xml");
442416
443082
  const impact = { affectedSlots: affected.map((slot2) => slot2.address), preservedSlots };
@@ -442572,7 +443238,7 @@ function isReferencedInFinalRelationships(context, perPart, mediaPartUri) {
442572
443238
  }
442573
443239
  return false;
442574
443240
  }
442575
- var HEADER_CT3 = "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml", HEADER_REL3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", IMAGE_REL2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", RELATIONSHIPS_CT3 = "application/vnd.openxmlformats-package.relationships+xml", EMPTY_RELS = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>', VARIANTS;
443241
+ var HEADER_CT3 = "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml", HEADER_REL3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", IMAGE_REL2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", RELATIONSHIPS_CT4 = "application/vnd.openxmlformats-package.relationships+xml", EMPTY_RELS = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>', VARIANTS;
442576
443242
  var init_scoped_apply = __esm(() => {
442577
443243
  init_sd_document_session_internal();
442578
443244
  init_document_reader();
@@ -443463,19 +444129,16 @@ class V2FootnotesAdapter {
443463
444129
  message: "section-scoped note configuration is not supported by v2 yet."
443464
444130
  });
443465
444131
  }
443466
- const settingsBytes = readPartBytes2(this.context, SETTINGS_PART_URI5);
443467
- if (!settingsBytes)
443468
- return failure24({
443469
- code: "PRECONDITION_FAILED",
443470
- message: "settings.xml bytes are unavailable."
443471
- });
443472
- const nextXml = configureSettings(readPartXml(this.context, SETTINGS_PART_URI5) ?? "", input);
444132
+ const settings = prepareSettingsPart(this.context);
444133
+ if (!settings.ok)
444134
+ return failure24(settings.failure);
444135
+ const nextXml = configureSettings(settings.xml, input);
443473
444136
  if (options?.dryRun)
443474
444137
  return { success: true };
443475
444138
  const committed = commitKernelStorySurfacePatch({
443476
444139
  context: this.context,
443477
444140
  txIdPrefix: "footnotes-configure",
443478
- perPart: { [SETTINGS_PART_URI5]: replaceWholePartEntry(settingsBytes, encodeXml(nextXml)) },
444141
+ perPart: settings.perPart(nextXml),
443479
444142
  signalLanesToRebuild: ["sections"]
443480
444143
  });
443481
444144
  if (!committed.ok)
@@ -444015,6 +444678,7 @@ var W14_NS4 = "http://schemas.microsoft.com/office/word/2010/wordml", FOOTNOTES_
444015
444678
  var init_adapter36 = __esm(() => {
444016
444679
  init_src3();
444017
444680
  init_document_styles();
444681
+ init_section_xml();
444018
444682
  init_tracked_pr_change();
444019
444683
  init_tracked_structural_wrapper();
444020
444684
  init_common();
@@ -448603,7 +449267,7 @@ function planPackageCompanion(input) {
448603
449267
  }
448604
449268
  };
448605
449269
  }
448606
- let documentRelsXml = input.documentRelsXml ?? EMPTY_RELATIONSHIPS_XML5;
449270
+ let documentRelsXml = input.documentRelsXml ?? EMPTY_RELATIONSHIPS_XML6;
448607
449271
  const relationshipTarget = relativeRelationshipTarget(input.relationshipOwnerPartName, input.def.partName);
448608
449272
  const relationshipElements = findEmptyXmlElements(documentRelsXml, "Relationship");
448609
449273
  if (input.def.scope === "styles") {
@@ -448774,7 +449438,7 @@ function importHeaderFooterAssets(input) {
448774
449438
  }
448775
449439
  let nextContentTypesXml = input.contentTypesXml;
448776
449440
  let contentTypesChanged = false;
448777
- let nextDocumentRelsXml = input.documentRelsXml ?? EMPTY_RELATIONSHIPS_XML5;
449441
+ let nextDocumentRelsXml = input.documentRelsXml ?? EMPTY_RELATIONSHIPS_XML6;
448778
449442
  let documentRelsChanged = false;
448779
449443
  let changed = false;
448780
449444
  const idMappings = [];
@@ -449651,7 +450315,7 @@ function replaceChildValAttr(defXml, tag, value3) {
449651
450315
  const escaped = escapeTag(tag);
449652
450316
  return defXml.replace(new RegExp(`(<${escaped}\\b[^>]*\\bw:val=")[^"]*(")`), `$1${value3}$2`);
449653
450317
  }
449654
- var CONTENT_TYPES_NAME = "[Content_Types].xml", CONTENT_TYPES_PART_URI16 = "/[Content_Types].xml", DOCUMENT_PART_URI7 = "/word/document.xml", STYLES_CONTENT_TYPE2 = "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", STRICT_WORDPROCESSINGML_NAMESPACE3 = "http://purl.oclc.org/ooxml/wordprocessingml/main", THEME_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", FONT_TABLE_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", WEB_SETTINGS_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings", HEADER_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", FOOTER_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", IMAGE_REL_TYPE3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", SINGLE_SCOPE_DEFS, STYLES_PART_NAME = "word/styles.xml", STYLES_SCOPE_DEF, NUMBERING_PART_NAME = "word/numbering.xml", WORDPROCESSINGML_NAMESPACE9 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", SETTINGS_ADOPTION_LOCAL_NAMES, UNSUPPORTED_CATEGORIES, EMPTY_RELATIONSHIPS_XML5;
450318
+ var CONTENT_TYPES_NAME = "[Content_Types].xml", CONTENT_TYPES_PART_URI16 = "/[Content_Types].xml", DOCUMENT_PART_URI7 = "/word/document.xml", STYLES_CONTENT_TYPE2 = "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", STRICT_WORDPROCESSINGML_NAMESPACE3 = "http://purl.oclc.org/ooxml/wordprocessingml/main", THEME_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", FONT_TABLE_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", WEB_SETTINGS_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings", HEADER_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", FOOTER_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", IMAGE_REL_TYPE3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", SINGLE_SCOPE_DEFS, STYLES_PART_NAME = "word/styles.xml", STYLES_SCOPE_DEF, NUMBERING_PART_NAME = "word/numbering.xml", WORDPROCESSINGML_NAMESPACE9 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", SETTINGS_ADOPTION_LOCAL_NAMES, UNSUPPORTED_CATEGORIES, EMPTY_RELATIONSHIPS_XML6;
449655
450319
  var init_adapter40 = __esm(() => {
449656
450320
  init_src3();
449657
450321
  init_esm2();
@@ -449722,7 +450386,7 @@ var init_adapter40 = __esm(() => {
449722
450386
  { test: (n) => n === "word/footnotes.xml" || n === "word/endnotes.xml", category: "notes" },
449723
450387
  { test: (n) => n === "word/people.xml", category: "people" }
449724
450388
  ];
449725
- EMPTY_RELATIONSHIPS_XML5 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
450389
+ EMPTY_RELATIONSHIPS_XML6 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
449726
450390
  });
449727
450391
 
449728
450392
  // ../../../v2/document-api-v2-adapter/dist/atomic-plan.js
@@ -493588,6 +494252,9 @@ var init_dist9 = __esm(() => {
493588
494252
  });
493589
494253
 
493590
494254
  // ../../../v2/collaboration-v2/dist/backend/story-surface-execution-backend.js
494255
+ function isCollapsedDirectTextInsertion(source) {
494256
+ return source.kind === "editText" && source.changeMode === "direct" && source.newText.length > 0 && source.on.startBlockId === source.on.endBlockId && source.on.startOffset === source.on.endOffset;
494257
+ }
493591
494258
  function storyTextRequiresMergedCarrierSync(validation) {
493592
494259
  if (!validation)
493593
494260
  return false;
@@ -494856,6 +495523,9 @@ function admitPreparedStorySurfaceMutation(prepared, options) {
494856
495523
  }
494857
495524
  if (extension2.family === "storyText") {
494858
495525
  if (extension2.historyReplay || extension2.resyncFromSession || extension2.sessionSync || isNoteTextEdit(prepared)) {
495526
+ if (extension2.sessionSync && extension2.targetBlockIds.length === 1 && options.isSessionProjectionCurrent?.() === false && isCollapsedDirectTextInsertion(prepared.source)) {
495527
+ return { ok: false, message: "text insertion session sync requires a current session projection" };
495528
+ }
494859
495529
  return validateStoryTextSessionSync(prepared, extension2, options);
494860
495530
  }
494861
495531
  const direct = validateDirectStoryText(prepared, extension2, options);