@superdoc/mcp 1.9.0-next.11 → 1.9.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.
- package/dist/index.js +686 -372
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -31620,7 +31620,7 @@ var init_host = __esm(() => {
|
|
|
31620
31620
|
});
|
|
31621
31621
|
|
|
31622
31622
|
// ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
|
|
31623
|
-
var SDK_VERSION = "2.22.0-next.
|
|
31623
|
+
var SDK_VERSION = "2.22.0-next.13";
|
|
31624
31624
|
|
|
31625
31625
|
// ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
|
|
31626
31626
|
import { accessSync, chmodSync, constants, existsSync, statSync } from "node:fs";
|
|
@@ -87423,10 +87423,10 @@ var init_action_descriptors = __esm(() => {
|
|
|
87423
87423
|
operations: ["create.heading"]
|
|
87424
87424
|
},
|
|
87425
87425
|
replace_text: {
|
|
87426
|
-
hint: "edits[{find,replace}], optional selector to scope replacements to one inspected block, caseSensitive?, changeMode? — for EDITING existing wording only;
|
|
87426
|
+
hint: "edits[{find,replace,occurrence?}], optional selector to scope replacements to one inspected block, caseSensitive?, expectedRevision?, changeMode? — for EDITING existing wording only; keep find/replace spans MINIMAL (the words that change, not the whole paragraph). When the find appears more than once in the selected block and only one should change, set that edit's occurrence (1-based match number within the block; requires selector; this is not selector.occurrence, which picks a block). NEVER use it to append a new sentence/clause/paragraph (use insert_paragraphs)",
|
|
87427
87427
|
group: "Text/structure actions",
|
|
87428
87428
|
groupOrder: 2,
|
|
87429
|
-
args: ["edits", "selector", "caseSensitive", "changeMode"],
|
|
87429
|
+
args: ["edits", "selector", "caseSensitive", "expectedRevision", "changeMode"],
|
|
87430
87430
|
operations: ["replace"]
|
|
87431
87431
|
},
|
|
87432
87432
|
delete_text: {
|
|
@@ -93107,12 +93107,10 @@ function normalizeTitleLikeRewriteText(targetText, rewrittenText) {
|
|
|
93107
93107
|
const displayTitle = toDisplayTitleCase(targetText);
|
|
93108
93108
|
if (rewrittenText.includes(displayTitle))
|
|
93109
93109
|
return rewrittenText;
|
|
93110
|
-
const
|
|
93111
|
-
|
|
93112
|
-
const index = lowerRewrite.indexOf(lowerTarget);
|
|
93113
|
-
if (index < 0)
|
|
93110
|
+
const match = findRanges(rewrittenText, targetText, false)[0];
|
|
93111
|
+
if (!match)
|
|
93114
93112
|
return rewrittenText;
|
|
93115
|
-
return `${rewrittenText.slice(0,
|
|
93113
|
+
return `${rewrittenText.slice(0, match.start)}${displayTitle}${rewrittenText.slice(match.end)}`;
|
|
93116
93114
|
}
|
|
93117
93115
|
async function executeCreateParagraph(doc2, text, placement, changeMode) {
|
|
93118
93116
|
const fn = maybeMethod2(doc2, ["create", "paragraph"]);
|
|
@@ -93417,6 +93415,7 @@ async function runReplaceTextUnchecked(doc2, args) {
|
|
|
93417
93415
|
const preIdentity = requiresBlockSnapshot ? null : await readDocumentIdentity(doc2);
|
|
93418
93416
|
const pre = requiresBlockSnapshot ? await buildMutationSnapshot(doc2, { includeDomains: selectorDomains ?? ["blocks"] }) : snapshotFromIdentity(preIdentity);
|
|
93419
93417
|
try {
|
|
93418
|
+
assertExpectedReplacementRevision(args.expectedRevision, pre.revision);
|
|
93420
93419
|
assertReplacementTextPayloads(args.edits);
|
|
93421
93420
|
if (args.edits.length === 0) {
|
|
93422
93421
|
return failedReceipt("replace_text", new Error("edits must be non-empty"), pre);
|
|
@@ -93425,7 +93424,7 @@ async function runReplaceTextUnchecked(doc2, args) {
|
|
|
93425
93424
|
const selectedTargets = [];
|
|
93426
93425
|
let skippedEdits = [];
|
|
93427
93426
|
let steps;
|
|
93428
|
-
let applyExpectedRevision;
|
|
93427
|
+
let applyExpectedRevision = args.expectedRevision != null ? pre.revision : undefined;
|
|
93429
93428
|
if (args.selector) {
|
|
93430
93429
|
const target = selectorToBlockTarget(args.selector, pre);
|
|
93431
93430
|
if (!target) {
|
|
@@ -95411,18 +95410,25 @@ function findRanges(haystack, needle, caseSensitive) {
|
|
|
95411
95410
|
const ranges = [];
|
|
95412
95411
|
if (needle.length === 0)
|
|
95413
95412
|
return ranges;
|
|
95414
|
-
|
|
95415
|
-
|
|
95416
|
-
|
|
95417
|
-
|
|
95418
|
-
|
|
95419
|
-
|
|
95420
|
-
|
|
95421
|
-
|
|
95422
|
-
|
|
95413
|
+
if (caseSensitive) {
|
|
95414
|
+
let offset = 0;
|
|
95415
|
+
while (offset < haystack.length) {
|
|
95416
|
+
const idx = haystack.indexOf(needle, offset);
|
|
95417
|
+
if (idx < 0)
|
|
95418
|
+
break;
|
|
95419
|
+
ranges.push({ start: idx, end: idx + needle.length });
|
|
95420
|
+
offset = idx + needle.length;
|
|
95421
|
+
}
|
|
95422
|
+
return ranges;
|
|
95423
|
+
}
|
|
95424
|
+
for (const match of haystack.matchAll(caseInsensitivePattern(needle))) {
|
|
95425
|
+
ranges.push({ start: match.index, end: match.index + match[0].length });
|
|
95423
95426
|
}
|
|
95424
95427
|
return ranges;
|
|
95425
95428
|
}
|
|
95429
|
+
function caseInsensitivePattern(needle) {
|
|
95430
|
+
return new RegExp(needle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "giu");
|
|
95431
|
+
}
|
|
95426
95432
|
async function runApplyLetterSpacing(doc2, args) {
|
|
95427
95433
|
const pre = await buildMutationSnapshot(doc2, { includeDomains: ["blocks"] });
|
|
95428
95434
|
try {
|
|
@@ -96168,29 +96174,59 @@ function trackedChangeRefIds(result) {
|
|
|
96168
96174
|
return entityId ? [entityId] : [];
|
|
96169
96175
|
}));
|
|
96170
96176
|
}
|
|
96171
|
-
function parseScopedReplaceArgs(args, changeMode) {
|
|
96172
|
-
if (args.action !== "replace_text")
|
|
96173
|
-
return null;
|
|
96177
|
+
function parseScopedReplaceArgs(args, edits, changeMode, expectedRevision) {
|
|
96174
96178
|
if (!isRecord2(args.selector))
|
|
96175
96179
|
return null;
|
|
96176
|
-
if (!Array.isArray(args.edits) || args.edits.length === 0)
|
|
96177
|
-
return null;
|
|
96178
|
-
const edits = [];
|
|
96179
|
-
for (const entry of args.edits) {
|
|
96180
|
-
if (!isRecord2(entry) || typeof entry.find !== "string" || entry.find.length === 0)
|
|
96181
|
-
return null;
|
|
96182
|
-
edits.push({ find: entry.find, replace: typeof entry.replace === "string" ? entry.replace : "" });
|
|
96183
|
-
}
|
|
96184
96180
|
return {
|
|
96185
96181
|
edits,
|
|
96186
96182
|
selector: args.selector,
|
|
96187
96183
|
caseSensitive: args.caseSensitive === true,
|
|
96184
|
+
expectedRevision,
|
|
96188
96185
|
changeMode
|
|
96189
96186
|
};
|
|
96190
96187
|
}
|
|
96188
|
+
function assertExpectedReplacementRevision(expected, actual) {
|
|
96189
|
+
if (expected != null && expected !== actual) {
|
|
96190
|
+
throw new SuperDocCliError("replace_text: expectedRevision is stale. Inspect this live document again before editing.", {
|
|
96191
|
+
code: "REVISION_CONFLICT"
|
|
96192
|
+
});
|
|
96193
|
+
}
|
|
96194
|
+
}
|
|
96195
|
+
async function fieldResultRanges(doc2, nodeId, blockText) {
|
|
96196
|
+
const fn = maybeMethod2(doc2, ["fields", "list"]);
|
|
96197
|
+
if (!fn)
|
|
96198
|
+
return null;
|
|
96199
|
+
const results = [];
|
|
96200
|
+
const limit = 500;
|
|
96201
|
+
for (let offset = 0;offset < 1e5; offset += limit) {
|
|
96202
|
+
const page = await fn({ limit, offset });
|
|
96203
|
+
const items = isRecord2(page) && Array.isArray(page.items) ? page.items.filter(isRecord2) : [];
|
|
96204
|
+
for (const item of items) {
|
|
96205
|
+
const address = isRecord2(item.address) ? item.address : null;
|
|
96206
|
+
const inBody = typeof address?.storyId !== "string" || address.storyId.startsWith("main:");
|
|
96207
|
+
if (address?.blockId !== nodeId || !inBody)
|
|
96208
|
+
continue;
|
|
96209
|
+
if (typeof item.resolvedText !== "string" || item.resolvedText.length === 0) {
|
|
96210
|
+
return [{ start: 0, end: blockText.length }];
|
|
96211
|
+
}
|
|
96212
|
+
results.push(item.resolvedText);
|
|
96213
|
+
}
|
|
96214
|
+
const total = isRecord2(page) && typeof page.total === "number" ? page.total : null;
|
|
96215
|
+
if (items.length < limit || total != null && offset + limit >= total)
|
|
96216
|
+
break;
|
|
96217
|
+
}
|
|
96218
|
+
const ranges = [];
|
|
96219
|
+
for (const result of results) {
|
|
96220
|
+
for (let at = blockText.indexOf(result);at >= 0; at = blockText.indexOf(result, at + 1)) {
|
|
96221
|
+
ranges.push({ start: at, end: at + result.length });
|
|
96222
|
+
}
|
|
96223
|
+
}
|
|
96224
|
+
return ranges;
|
|
96225
|
+
}
|
|
96191
96226
|
async function runScopedReplaceUnchecked(doc2, args) {
|
|
96192
96227
|
assertReplacementTextPayloads(args.edits);
|
|
96193
96228
|
const pre = await buildMutationSnapshot(doc2, { includeDomains: ["blocks", "tables"] });
|
|
96229
|
+
assertExpectedReplacementRevision(args.expectedRevision, pre.revision);
|
|
96194
96230
|
const matched = resolveSnapshotSelector(pre, args.selector);
|
|
96195
96231
|
if (matched.length !== 1) {
|
|
96196
96232
|
const failure2 = describeSelectorFailure(args.selector, matched, pre, args.edits.map((e) => e.find));
|
|
@@ -96210,13 +96246,22 @@ async function runScopedReplaceUnchecked(doc2, args) {
|
|
|
96210
96246
|
};
|
|
96211
96247
|
}
|
|
96212
96248
|
const caseSensitive = args.caseSensitive === true;
|
|
96249
|
+
const hasExplicitOccurrence = args.edits.some((edit) => edit.occurrence != null);
|
|
96213
96250
|
const perEdit = [];
|
|
96214
96251
|
const allSpans = [];
|
|
96215
96252
|
for (const edit of args.edits) {
|
|
96216
|
-
const
|
|
96217
|
-
|
|
96253
|
+
const matches = findRanges(block.text, edit.find, caseSensitive);
|
|
96254
|
+
const spans = edit.occurrence == null ? matches : matches.slice(edit.occurrence - 1, edit.occurrence);
|
|
96255
|
+
if (hasExplicitOccurrence && spans.length === 0) {
|
|
96256
|
+
return failedReceipt("replace_text", new SuperDocCliError(edit.occurrence == null ? `replace_text: ${JSON.stringify(edit.find)} not found in the selected block. Inspect and choose a valid target.` : `replace_text: ${JSON.stringify(edit.find)} occurrence ${edit.occurrence} not found in the selected block (${matches.length} matches). Inspect and choose a valid target.`, { code: "MATCH_NOT_FOUND" }), pre);
|
|
96257
|
+
}
|
|
96258
|
+
perEdit.push({
|
|
96259
|
+
find: edit.find,
|
|
96260
|
+
occurrences: spans.length,
|
|
96261
|
+
...edit.occurrence != null ? { occurrence: edit.occurrence } : {}
|
|
96262
|
+
});
|
|
96218
96263
|
for (const span of spans)
|
|
96219
|
-
allSpans.push({ ...span, replace: edit.replace
|
|
96264
|
+
allSpans.push({ ...span, replace: edit.replace, find: edit.find });
|
|
96220
96265
|
}
|
|
96221
96266
|
const appliedEdits = perEdit.filter((e) => e.occurrences > 0);
|
|
96222
96267
|
const skippedEdits = perEdit.filter((e) => e.occurrences === 0);
|
|
@@ -96241,6 +96286,9 @@ async function runScopedReplaceUnchecked(doc2, args) {
|
|
|
96241
96286
|
let lastEnd = -1;
|
|
96242
96287
|
for (const span of allSpans) {
|
|
96243
96288
|
if (span.start < lastEnd) {
|
|
96289
|
+
if (hasExplicitOccurrence) {
|
|
96290
|
+
return failedReceipt("replace_text", new SuperDocCliError("replace_text: explicit occurrence targets overlap. Choose non-overlapping edits in the pre-edit block.", { code: "INVALID_ARGUMENT" }), pre);
|
|
96291
|
+
}
|
|
96244
96292
|
droppedOverlaps.push(span);
|
|
96245
96293
|
continue;
|
|
96246
96294
|
}
|
|
@@ -96249,24 +96297,45 @@ async function runScopedReplaceUnchecked(doc2, args) {
|
|
|
96249
96297
|
}
|
|
96250
96298
|
const expected = planned.reduceRight((text, span) => text.slice(0, span.start) + span.replace + text.slice(span.end), block.text);
|
|
96251
96299
|
const tracked = (args.changeMode ?? "direct") === "tracked";
|
|
96252
|
-
let result = null;
|
|
96253
96300
|
const uniqueFinds = new Set(planned.map((s) => caseSensitive ? s.find : s.find.toLowerCase()));
|
|
96254
|
-
|
|
96255
|
-
|
|
96301
|
+
const deletions = tracked ? [] : planned.filter((span) => span.replace.length === 0);
|
|
96302
|
+
const fieldRanges = deletions.length > 0 ? await fieldResultRanges(doc2, nodeId, block.text) : [];
|
|
96303
|
+
const fieldDeletionRisk = fieldRanges == null || deletions.some((span) => fieldRanges.some((range) => span.start < range.end && span.end > range.start));
|
|
96304
|
+
const exactTargets = !fieldDeletionRisk && (hasExplicitOccurrence || tracked && uniqueFinds.size === planned.length);
|
|
96305
|
+
let result = null;
|
|
96306
|
+
let wroteExactTargets = false;
|
|
96307
|
+
if (exactTargets) {
|
|
96308
|
+
const targetedSpans = [...planned].reverse().filter((span) => block.text.slice(span.start, span.end) !== span.replace);
|
|
96309
|
+
const steps = targetedSpans.map((span, index) => ({
|
|
96256
96310
|
id: `scoped-replace-${index + 1}`,
|
|
96257
96311
|
op: "text.rewrite",
|
|
96258
96312
|
where: {
|
|
96259
|
-
by: "
|
|
96260
|
-
|
|
96261
|
-
|
|
96262
|
-
|
|
96313
|
+
by: "target",
|
|
96314
|
+
target: {
|
|
96315
|
+
kind: "selection",
|
|
96316
|
+
start: { kind: "text", blockId: nodeId, offset: span.start },
|
|
96317
|
+
end: { kind: "text", blockId: nodeId, offset: span.end }
|
|
96318
|
+
}
|
|
96263
96319
|
},
|
|
96264
96320
|
args: { replacement: { text: span.replace }, style: preserveRewriteStyle() }
|
|
96265
96321
|
}));
|
|
96266
|
-
|
|
96267
|
-
result =
|
|
96268
|
-
}
|
|
96269
|
-
|
|
96322
|
+
if (steps.length === 0) {
|
|
96323
|
+
result = { noop: true };
|
|
96324
|
+
} else {
|
|
96325
|
+
const preview = await previewMutations(doc2, steps, args.changeMode, pre.revision);
|
|
96326
|
+
const previewSteps = Array.isArray(preview.steps) ? preview.steps.filter(isRecord2) : [];
|
|
96327
|
+
const aligned = preview.valid === true && steps.every((step, index) => {
|
|
96328
|
+
const resolutions = previewSteps.find((candidate) => candidate.stepId === step.id)?.resolutions;
|
|
96329
|
+
const resolved = Array.isArray(resolutions) && isRecord2(resolutions[0]) ? resolutions[0].text : undefined;
|
|
96330
|
+
const span = targetedSpans[index];
|
|
96331
|
+
return resolved === block.text.slice(span.start, span.end);
|
|
96332
|
+
});
|
|
96333
|
+
if (aligned) {
|
|
96334
|
+
result = await executeMutations(doc2, steps, args.changeMode, pre.revision);
|
|
96335
|
+
wroteExactTargets = true;
|
|
96336
|
+
} else if (hasExplicitOccurrence) {
|
|
96337
|
+
return failedReceipt("replace_text", new SuperDocCliError("replace_text: the chosen occurrence does not resolve to the same text in the document. Inspect again before editing.", { code: "TARGET_NOT_FOUND" }), pre);
|
|
96338
|
+
}
|
|
96270
96339
|
}
|
|
96271
96340
|
}
|
|
96272
96341
|
if (result == null) {
|
|
@@ -96280,9 +96349,20 @@ async function runScopedReplaceUnchecked(doc2, args) {
|
|
|
96280
96349
|
];
|
|
96281
96350
|
result = await executeMutations(doc2, steps, args.changeMode, pre.revision);
|
|
96282
96351
|
}
|
|
96283
|
-
|
|
96284
|
-
|
|
96285
|
-
|
|
96352
|
+
let post = await buildMutationSnapshot(doc2, { includeDomains: ["blocks", "tables"] });
|
|
96353
|
+
let postBlock = findTextTarget(post, nodeId);
|
|
96354
|
+
let rolledBack = false;
|
|
96355
|
+
const appliedRevision = isRecord2(result) && isRecord2(result.revision) ? result.revision.after : undefined;
|
|
96356
|
+
if (wroteExactTargets && postBlock != null && postBlock.text !== expected && postBlock.text !== block.text && typeof appliedRevision === "string" && appliedRevision === post.revision) {
|
|
96357
|
+
const undoFn = maybeMethod2(doc2, ["history", "undo"]);
|
|
96358
|
+
if (undoFn) {
|
|
96359
|
+
await undoFn({});
|
|
96360
|
+
post = await buildMutationSnapshot(doc2, { includeDomains: ["blocks", "tables"] });
|
|
96361
|
+
postBlock = findTextTarget(post, nodeId);
|
|
96362
|
+
rolledBack = postBlock?.text === block.text;
|
|
96363
|
+
}
|
|
96364
|
+
}
|
|
96365
|
+
const passed = postBlock != null && !rolledBack && (tracked && !hasExplicitOccurrence && !wroteExactTargets ? planned.every((span) => span.replace.length === 0 || postBlock.text.includes(span.replace)) : postBlock.text === expected);
|
|
96286
96366
|
const status = !passed ? "failed" : skippedEdits.length > 0 ? "partial" : "ok";
|
|
96287
96367
|
return {
|
|
96288
96368
|
status,
|
|
@@ -96291,6 +96371,14 @@ async function runScopedReplaceUnchecked(doc2, args) {
|
|
|
96291
96371
|
nextStep: `${skippedEdits.length} of ${perEdit.length} edits were NOT applied — the find text is not in the selected block. ` + `Do not stop: call replace_text again for the remaining edits with a different selector (or no selector for a global replace).`,
|
|
96292
96372
|
recovery: { kind: "retry" }
|
|
96293
96373
|
} : {},
|
|
96374
|
+
...rolledBack ? {
|
|
96375
|
+
errors: [
|
|
96376
|
+
{
|
|
96377
|
+
code: "ACTION_FAILED",
|
|
96378
|
+
message: "replace_text: the engine changed more than the requested text, so the edit was undone. Inspect the block and retry with a larger find or rewrite the whole block."
|
|
96379
|
+
}
|
|
96380
|
+
]
|
|
96381
|
+
} : {},
|
|
96294
96382
|
preSnapshot: { revision: pre.revision },
|
|
96295
96383
|
postSnapshot: { revision: post.revision },
|
|
96296
96384
|
selectedBlock: { nodeId, nodeType: block.nodeType },
|
|
@@ -97622,8 +97710,17 @@ async function dispatchSuperdocPerformAction(doc2, args) {
|
|
|
97622
97710
|
code: "INVALID_ARGUMENT"
|
|
97623
97711
|
});
|
|
97624
97712
|
}
|
|
97713
|
+
const expectedRevision = args.expectedRevision;
|
|
97714
|
+
if (expectedRevision !== undefined && (typeof expectedRevision !== "string" || expectedRevision.length === 0)) {
|
|
97715
|
+
throw new SuperDocCliError("replace_text: expectedRevision must be a non-empty string from this live document handle", { code: "INVALID_ARGUMENT" });
|
|
97716
|
+
}
|
|
97717
|
+
if (edits.some((edit) => edit.occurrence != null) && !isRecord2(args.selector)) {
|
|
97718
|
+
throw new SuperDocCliError("replace_text: explicit occurrence requires a selector resolving to one block", {
|
|
97719
|
+
code: "INVALID_ARGUMENT"
|
|
97720
|
+
});
|
|
97721
|
+
}
|
|
97625
97722
|
const changeMode = parseReplaceTextChangeMode(args.changeMode);
|
|
97626
|
-
const scoped = parseScopedReplaceArgs(args, changeMode);
|
|
97723
|
+
const scoped = parseScopedReplaceArgs(args, edits, changeMode, expectedRevision);
|
|
97627
97724
|
if (scoped) {
|
|
97628
97725
|
return runScopedReplace(doc2, scoped);
|
|
97629
97726
|
}
|
|
@@ -97636,6 +97733,7 @@ async function dispatchSuperdocPerformAction(doc2, args) {
|
|
|
97636
97733
|
edits,
|
|
97637
97734
|
selector,
|
|
97638
97735
|
caseSensitive: args.caseSensitive === true,
|
|
97736
|
+
expectedRevision,
|
|
97639
97737
|
changeMode
|
|
97640
97738
|
});
|
|
97641
97739
|
}
|
|
@@ -98281,7 +98379,11 @@ function parseEdits2(value) {
|
|
|
98281
98379
|
const replace = asString2(entry.replace) ?? "";
|
|
98282
98380
|
if (!find)
|
|
98283
98381
|
return;
|
|
98284
|
-
|
|
98382
|
+
const occurrence = entry.occurrence;
|
|
98383
|
+
if (occurrence !== undefined && (typeof occurrence !== "number" || !Number.isSafeInteger(occurrence) || occurrence < 1)) {
|
|
98384
|
+
throw new SuperDocCliError("replace_text: occurrence must be a positive safe integer (one-based within the selected block)", { code: "INVALID_ARGUMENT" });
|
|
98385
|
+
}
|
|
98386
|
+
result.push({ find, replace, ...occurrence !== undefined ? { occurrence } : {} });
|
|
98285
98387
|
}
|
|
98286
98388
|
return result;
|
|
98287
98389
|
}
|
|
@@ -98743,10 +98845,24 @@ var init_catalog = __esm(() => {
|
|
|
98743
98845
|
type: "array",
|
|
98744
98846
|
items: {
|
|
98745
98847
|
type: "object",
|
|
98746
|
-
properties: {
|
|
98848
|
+
properties: {
|
|
98849
|
+
find: { type: "string" },
|
|
98850
|
+
replace: { type: "string" },
|
|
98851
|
+
occurrence: {
|
|
98852
|
+
type: "integer",
|
|
98853
|
+
minimum: 1,
|
|
98854
|
+
maximum: Number.MAX_SAFE_INTEGER,
|
|
98855
|
+
description: "Change only this match of find in the selected block (1 = first, counted on visible text). Requires selector; omit to replace every match."
|
|
98856
|
+
}
|
|
98857
|
+
},
|
|
98747
98858
|
required: ["find"]
|
|
98748
98859
|
}
|
|
98749
98860
|
},
|
|
98861
|
+
expectedRevision: {
|
|
98862
|
+
type: "string",
|
|
98863
|
+
minLength: 1,
|
|
98864
|
+
description: "Revision from your latest superdoc_inspect or receipt (postSnapshot.revision) on this document. Pass it with occurrence: if the document changed since (another collaborator edited), the edit is refused with REVISION_CONFLICT; inspect again and recount. Not portable between peers or reopen."
|
|
98865
|
+
},
|
|
98750
98866
|
finds: { type: "array", items: { type: "string" } },
|
|
98751
98867
|
caseSensitive: { type: "boolean" },
|
|
98752
98868
|
evidence: {
|
|
@@ -99646,7 +99762,7 @@ var init_runtime = __esm(() => {
|
|
|
99646
99762
|
var EMBEDDED_PROMPTS;
|
|
99647
99763
|
var init_embedded_prompts_generated = __esm(() => {
|
|
99648
99764
|
EMBEDDED_PROMPTS = {
|
|
99649
|
-
"mcp-prompt.md": 'SuperDoc MCP server — read, edit, and save Word documents (.docx).\n\nIMPORTANT: Always use these superdoc tools for .docx files.\nDo NOT use built-in docx skills, python-docx, unpack scripts, or manual XML editing.\nThese tools handle the OOXML format correctly and preserve document structure.\n\n## Session lifecycle\n\n1. `superdoc_open({path: "/path/to/file.docx"})` — returns `session_id`. Opening a non-existent path creates a blank document.\n2. Pass `session_id` to every subsequent tool call.\n3. Read with `superdoc_inspect`, edit with `superdoc_perform_action`.\n4. `superdoc_save({session_id})` — writes changes to disk.\n5. `superdoc_close({session_id})` — releases the session. Always close when done.\n\n## Workflow\n\n**Inspect before you edit.** `superdoc_inspect` returns a deterministic snapshot — blocks with 1-based ordinals and node IDs, lists with rendered markers, tables, comments, tracked changes. Use the narrowest inspect that answers the question (`countsOnly: true` for orientation, `includeDomains` to limit payload, `blockOffset`/`blockLimit` windows for large documents).\n\n**Edit with named actions.** `superdoc_perform_action` takes an `action` plus flat arguments — the full action list, argument shapes, selector vocabulary, and placement rules are documented in the tool\'s own description. Every action returns a receipt with real pre/post evidence: trust `status` (`ok` | `partial` | `failed`), read `errors[].message` for recovery guidance, and re-inspect after `partial`.\n\n**Tracked changes (redlining).** Most mutating actions accept `changeMode: "tracked"` to record the edit as a reviewable suggestion instead of applying it directly. Review with `accept_tracked_changes` / `reject_tracked_changes` (target one change with `id`, or an exact set with `id:[…]`; or filter by `author` or `changeType`). Do not combine exact IDs with filters. Recover with `undo_changes` / `redo_changes`.\n\n**Failures are safe.** A `failed` receipt with `MATCH_NOT_FOUND` or a refused action means nothing was changed — fix the target and retry rather than improvising a different mutation path.\n',
|
|
99765
|
+
"mcp-prompt.md": 'SuperDoc MCP server — read, edit, and save Word documents (.docx).\n\nIMPORTANT: Always use these superdoc tools for .docx files.\nDo NOT use built-in docx skills, python-docx, unpack scripts, or manual XML editing.\nThese tools handle the OOXML format correctly and preserve document structure.\n\n## Session lifecycle\n\n1. `superdoc_open({path: "/path/to/file.docx"})` — returns `session_id`. Opening a non-existent path creates a blank document.\n2. Pass `session_id` to every subsequent tool call.\n3. Read with `superdoc_inspect`, edit with `superdoc_perform_action`.\n4. `superdoc_save({session_id})` — writes changes to disk.\n5. `superdoc_close({session_id})` — releases the session. Always close when done.\n\n## Workflow\n\n**Inspect before you edit.** `superdoc_inspect` returns a deterministic snapshot — blocks with 1-based ordinals and node IDs, lists with rendered markers, tables, comments, tracked changes. Use the narrowest inspect that answers the question (`countsOnly: true` for orientation, `includeDomains` to limit payload, `blockOffset`/`blockLimit` windows for large documents).\n\n**Edit with named actions.** `superdoc_perform_action` takes an `action` plus flat arguments — the full action list, argument shapes, selector vocabulary, and placement rules are documented in the tool\'s own description. Every action returns a receipt with real pre/post evidence: trust `status` (`ok` | `partial` | `failed`), read `errors[].message` for recovery guidance, and re-inspect after `partial`.\n\n**Target one repeated match.** For `replace_text`, scope to one block with a selector and set `occurrence` on the edit (1 = first match in that block) to change only that match. Also pass `expectedRevision` from your latest inspect or receipt; on `REVISION_CONFLICT`, inspect again and recount.\n\n**Tracked changes (redlining).** Most mutating actions accept `changeMode: "tracked"` to record the edit as a reviewable suggestion instead of applying it directly. Review with `accept_tracked_changes` / `reject_tracked_changes` (target one change with `id`, or an exact set with `id:[…]`; or filter by `author` or `changeType`). Do not combine exact IDs with filters. Recover with `undo_changes` / `redo_changes`.\n\n**Failures are safe.** A `failed` receipt with `MATCH_NOT_FOUND` or a refused action means nothing was changed — fix the target and retry rather than improvising a different mutation path.\n',
|
|
99650
99766
|
"system-prompt.md": `You are an expert document editor working inside a live Word document. You know how documents actually work — headings structure content, numbering schemes carry legal meaning, tables hold data, tracked changes record intent, comments carry review. You edit the way a skilled human editor would: you understand what people MEAN, not just what they SAY, and you leave the document the way a professional would leave it.
|
|
99651
99767
|
|
|
99652
99768
|
============================================================
|
|
@@ -99697,7 +99813,7 @@ ACTIONS (superdoc_perform_action with flat args)
|
|
|
99697
99813
|
- 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.
|
|
99698
99814
|
- 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.
|
|
99699
99815
|
- 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).
|
|
99700
|
-
- replace_text: edits:[{find,replace}], caseSensitive default false. selector to scope. 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.
|
|
99816
|
+
- 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.
|
|
99701
99817
|
- 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.
|
|
99702
99818
|
- 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.
|
|
99703
99819
|
- rewrite_block: selector, text. Inspect first to gather current text; never ask the user to paste text already in the doc.
|
|
@@ -159330,7 +159446,7 @@ function buildCommentsCatalog(state) {
|
|
|
159330
159446
|
const extendedBytes = state.packageBytes.get(COMMENTS_EXTENDED_PART_URI);
|
|
159331
159447
|
let extendedByParaId = extendedBytes ? parseCommentsExtendedXml(TD12.decode(extendedBytes)) : new Map;
|
|
159332
159448
|
if (entries.length > 1) {
|
|
159333
|
-
extendedByParaId = mergeInferredThreading(extendedByParaId, inferThreadingFromStoryAnchors(state, entries));
|
|
159449
|
+
extendedByParaId = mergeInferredThreading(extendedByParaId, inferThreadingFromStoryAnchors(state, entries, extendedByParaId));
|
|
159334
159450
|
}
|
|
159335
159451
|
const idsBytes = state.packageBytes.get(COMMENTS_IDS_PART_URI);
|
|
159336
159452
|
const durableByParaId = idsBytes ? parseCommentsIdsXml(TD12.decode(idsBytes)) : new Map;
|
|
@@ -159630,17 +159746,25 @@ function normalizeNullableCustomAttr(value) {
|
|
|
159630
159746
|
return null;
|
|
159631
159747
|
return decodeAttr(value);
|
|
159632
159748
|
}
|
|
159633
|
-
function inferThreadingFromStoryAnchors(state, entries) {
|
|
159749
|
+
function inferThreadingFromStoryAnchors(state, entries, explicit) {
|
|
159634
159750
|
const entryByWId = new Map;
|
|
159635
159751
|
for (const entry of entries) {
|
|
159636
159752
|
if (!entryByWId.has(entry.wId))
|
|
159637
159753
|
entryByWId.set(entry.wId, entry);
|
|
159638
159754
|
}
|
|
159755
|
+
const paraIdOwners = new Map;
|
|
159756
|
+
for (const entry of entries) {
|
|
159757
|
+
for (const paraId of new Set(entry.bodyParaIds))
|
|
159758
|
+
paraIdOwners.set(paraId, (paraIdOwners.get(paraId) ?? 0) + 1);
|
|
159759
|
+
}
|
|
159639
159760
|
const sessionParaIds = state.idReservations.comments.paraIds;
|
|
159640
159761
|
const importedSourceIds = new Set(entries.filter((entry) => {
|
|
159641
159762
|
const paraId = entry.bodyParaIds[0];
|
|
159642
|
-
return paraId && !entry.isExplicitRoot && !sessionParaIds.has(paraId);
|
|
159763
|
+
return paraId && paraIdOwners.get(paraId) === 1 && !entry.isExplicitRoot && !sessionParaIds.has(paraId);
|
|
159643
159764
|
}).map((entry) => entry.wId));
|
|
159765
|
+
const inferenceSourceIds = new Set([...entryByWId.values()].filter((entry) => importedSourceIds.has(entry.wId) && !entry.bodyParaIds.some((paraId) => explicit.has(paraId))).map((entry) => entry.wId));
|
|
159766
|
+
if (inferenceSourceIds.size === 0)
|
|
159767
|
+
return new Map;
|
|
159644
159768
|
const sourceOrder = new Map;
|
|
159645
159769
|
for (let i = 0;i < entries.length; i += 1) {
|
|
159646
159770
|
const entry = entries[i];
|
|
@@ -159664,11 +159788,6 @@ function inferThreadingFromStoryAnchors(state, entries) {
|
|
|
159664
159788
|
groups.push([anchor]);
|
|
159665
159789
|
}
|
|
159666
159790
|
const out = new Map;
|
|
159667
|
-
for (const entry of entries) {
|
|
159668
|
-
const paraId = entry.bodyParaIds[0];
|
|
159669
|
-
if (paraId)
|
|
159670
|
-
out.set(paraId, { parentParaId: null, done: false });
|
|
159671
|
-
}
|
|
159672
159791
|
for (const group of groups) {
|
|
159673
159792
|
const uniqueSourceIds = Array.from(new Set(group.map((a) => a.sourceWId)));
|
|
159674
159793
|
if (uniqueSourceIds.length < 2)
|
|
@@ -159680,7 +159799,7 @@ function inferThreadingFromStoryAnchors(state, entries) {
|
|
|
159680
159799
|
if (!rootParaId)
|
|
159681
159800
|
continue;
|
|
159682
159801
|
for (const sourceWId of uniqueSourceIds) {
|
|
159683
|
-
if (sourceWId === rootSourceId)
|
|
159802
|
+
if (sourceWId === rootSourceId || !inferenceSourceIds.has(sourceWId))
|
|
159684
159803
|
continue;
|
|
159685
159804
|
const replyEntry = entryByWId.get(sourceWId);
|
|
159686
159805
|
const replyParaId = replyEntry?.bodyParaIds[0];
|
|
@@ -159688,12 +159807,25 @@ function inferThreadingFromStoryAnchors(state, entries) {
|
|
|
159688
159807
|
continue;
|
|
159689
159808
|
const parentSourceId = chooseContainingParentSourceId(sourceWId, uniqueSourceIds, envelopeBySourceId, sourceOrder) ?? rootSourceId;
|
|
159690
159809
|
const parentEntry = entryByWId.get(parentSourceId);
|
|
159691
|
-
const parentParaId = parentEntry
|
|
159810
|
+
const parentParaId = parentEntry ? selectThreadingParaId(parentEntry, explicit) : rootParaId;
|
|
159811
|
+
if (wouldCreateThreadCycle(replyParaId, parentParaId, explicit, out))
|
|
159812
|
+
continue;
|
|
159692
159813
|
out.set(replyParaId, { parentParaId, done: false });
|
|
159693
159814
|
}
|
|
159694
159815
|
}
|
|
159695
159816
|
return out;
|
|
159696
159817
|
}
|
|
159818
|
+
function wouldCreateThreadCycle(childParaId, parentParaId, explicit, inferred) {
|
|
159819
|
+
const seen = new Set([childParaId]);
|
|
159820
|
+
let cursor = parentParaId;
|
|
159821
|
+
while (cursor !== null) {
|
|
159822
|
+
if (seen.has(cursor))
|
|
159823
|
+
return true;
|
|
159824
|
+
seen.add(cursor);
|
|
159825
|
+
cursor = (explicit.get(cursor) ?? inferred.get(cursor))?.parentParaId ?? null;
|
|
159826
|
+
}
|
|
159827
|
+
return false;
|
|
159828
|
+
}
|
|
159697
159829
|
function representativeEnvelopeBySourceId(group) {
|
|
159698
159830
|
const out = new Map;
|
|
159699
159831
|
for (const envelope of group) {
|
|
@@ -159758,17 +159890,8 @@ function mergeInferredThreading(explicit, inferred) {
|
|
|
159758
159890
|
return explicit;
|
|
159759
159891
|
const out = new Map(explicit);
|
|
159760
159892
|
for (const [paraId, inferredExt] of inferred) {
|
|
159761
|
-
|
|
159762
|
-
if (!existing) {
|
|
159893
|
+
if (!out.has(paraId))
|
|
159763
159894
|
out.set(paraId, inferredExt);
|
|
159764
|
-
continue;
|
|
159765
|
-
}
|
|
159766
|
-
if (existing.parentParaId === null && inferredExt.parentParaId !== null) {
|
|
159767
|
-
out.set(paraId, {
|
|
159768
|
-
parentParaId: inferredExt.parentParaId,
|
|
159769
|
-
done: existing.done
|
|
159770
|
-
});
|
|
159771
|
-
}
|
|
159772
159895
|
}
|
|
159773
159896
|
return out;
|
|
159774
159897
|
}
|
|
@@ -159779,25 +159902,38 @@ function collectCommentAnchorEnvelopes(state) {
|
|
|
159779
159902
|
continue;
|
|
159780
159903
|
const xml = TD12.decode(bytes);
|
|
159781
159904
|
const starts = [];
|
|
159782
|
-
const
|
|
159905
|
+
const endsBySourceId = new Map;
|
|
159783
159906
|
const tokenRe = /<[\w.-]+:(commentRangeStart|commentRangeEnd)\b[^>]*\bw:id="([^"]+)"[^>]*\/?>/g;
|
|
159784
159907
|
for (let match = tokenRe.exec(xml);match; match = tokenRe.exec(xml)) {
|
|
159785
159908
|
const item = { sourceWId: match[2] ?? "", pos: match.index };
|
|
159786
159909
|
if (match[1] === "commentRangeStart")
|
|
159787
159910
|
starts.push(item);
|
|
159788
|
-
else
|
|
159789
|
-
ends.
|
|
159911
|
+
else {
|
|
159912
|
+
const ends = endsBySourceId.get(item.sourceWId);
|
|
159913
|
+
if (ends)
|
|
159914
|
+
ends.push(item.pos);
|
|
159915
|
+
else
|
|
159916
|
+
endsBySourceId.set(item.sourceWId, [item.pos]);
|
|
159917
|
+
}
|
|
159790
159918
|
}
|
|
159919
|
+
const endCursors = new Map;
|
|
159791
159920
|
for (const start of starts) {
|
|
159792
|
-
const
|
|
159793
|
-
if (
|
|
159794
|
-
|
|
159921
|
+
const ends = endsBySourceId.get(start.sourceWId);
|
|
159922
|
+
if (!ends)
|
|
159923
|
+
continue;
|
|
159924
|
+
let cursor = endCursors.get(start.sourceWId) ?? 0;
|
|
159925
|
+
while (cursor < ends.length && ends[cursor] < start.pos)
|
|
159926
|
+
cursor++;
|
|
159927
|
+
endCursors.set(start.sourceWId, cursor);
|
|
159928
|
+
const end = ends[cursor];
|
|
159929
|
+
if (end !== undefined)
|
|
159930
|
+
out.push({ partUri, sourceWId: start.sourceWId, start: start.pos, end });
|
|
159795
159931
|
}
|
|
159796
159932
|
}
|
|
159797
159933
|
return out;
|
|
159798
159934
|
}
|
|
159799
159935
|
function envelopesOverlap(a, b) {
|
|
159800
|
-
return a.start <= b.end && b.start <= a.end;
|
|
159936
|
+
return a.partUri === b.partUri && a.start <= b.end && b.start <= a.end;
|
|
159801
159937
|
}
|
|
159802
159938
|
function isStoryPartUri(partUri) {
|
|
159803
159939
|
return partUri === "/word/document.xml" || /^\/word\/header\d+\.xml$/.test(partUri) || /^\/word\/footer\d+\.xml$/.test(partUri) || partUri === "/word/footnotes.xml" || partUri === "/word/endnotes.xml";
|
|
@@ -159961,27 +160097,42 @@ function shiftedMarker(marker, delta) {
|
|
|
159961
160097
|
paragraph: marker.paragraph ? { ...marker.paragraph, range: shift(marker.paragraph.range) } : null
|
|
159962
160098
|
};
|
|
159963
160099
|
}
|
|
159964
|
-
function
|
|
160100
|
+
function indexMarkersBySourceId(markers) {
|
|
160101
|
+
const index = new Map;
|
|
160102
|
+
for (const marker of markers) {
|
|
160103
|
+
const existing = index.get(marker.id);
|
|
160104
|
+
if (existing)
|
|
160105
|
+
existing.push(marker);
|
|
160106
|
+
else
|
|
160107
|
+
index.set(marker.id, [marker]);
|
|
160108
|
+
}
|
|
160109
|
+
return index;
|
|
160110
|
+
}
|
|
160111
|
+
function getBodyCommentByteFacts(state, partUri) {
|
|
159965
160112
|
const bytes = state.packageBytes.get(partUri);
|
|
159966
160113
|
const revision = state.parts.get(partUri)?.descriptor.revision;
|
|
159967
160114
|
if (!bytes || !revision)
|
|
159968
|
-
return
|
|
160115
|
+
return null;
|
|
159969
160116
|
const cache = byteFacts(state);
|
|
159970
160117
|
const prior = cache.get(partUri);
|
|
159971
160118
|
if (prior?.bytes === bytes && prior.partRevision === revision)
|
|
159972
|
-
return prior
|
|
160119
|
+
return prior;
|
|
159973
160120
|
const bom = bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191 ? 3 : 0;
|
|
159974
160121
|
const scanned = scanBodyCommentMarkers(TD13.decode(bytes));
|
|
159975
160122
|
const markers = scanned.markers.map((marker) => shiftedMarker(marker, bom));
|
|
159976
|
-
|
|
159977
|
-
|
|
160123
|
+
const facts = { bytes, partRevision: revision, markers, markersBySourceId: indexMarkersBySourceId(markers), complete: scanned.complete };
|
|
160124
|
+
cache.set(partUri, facts);
|
|
160125
|
+
return facts;
|
|
160126
|
+
}
|
|
160127
|
+
function getBodyCommentMarkerFacts(state, partUri) {
|
|
160128
|
+
return getBodyCommentByteFacts(state, partUri)?.markers ?? [];
|
|
160129
|
+
}
|
|
160130
|
+
function getBodyCommentMarkersForSourceId(state, partUri, commentId) {
|
|
160131
|
+
return getBodyCommentByteFacts(state, partUri)?.markersBySourceId.get(commentId) ?? [];
|
|
159978
160132
|
}
|
|
159979
160133
|
function readCompleteBodyCommentMarkerFacts(state, partUri) {
|
|
159980
|
-
|
|
159981
|
-
|
|
159982
|
-
const markers = getBodyCommentMarkerFacts(state, partUri);
|
|
159983
|
-
const facts = byteFacts(state).get(partUri);
|
|
159984
|
-
return facts?.complete === true && facts.bytes === state.packageBytes.get(partUri) && facts.partRevision === state.parts.get(partUri)?.descriptor.revision ? markers : null;
|
|
160134
|
+
const facts = getBodyCommentByteFacts(state, partUri);
|
|
160135
|
+
return facts?.complete === true ? facts.markers : null;
|
|
159985
160136
|
}
|
|
159986
160137
|
function peekBodyCommentMarkerFacts(state, partUri) {
|
|
159987
160138
|
const cache = state.partRegistries.get(BYTE_FACTS_KEY);
|
|
@@ -160011,22 +160162,22 @@ function refreshBodyCommentMarkerFactsAfterParagraphMutation(input) {
|
|
|
160011
160162
|
}
|
|
160012
160163
|
const scanned = scanBodyCommentMarkers(TD13.decode(bytes.subarray(input.beforeStart, input.afterEnd)), input.namespaceBindings);
|
|
160013
160164
|
const current = scanned.markers.map((marker) => shiftedMarker(marker, input.beforeStart));
|
|
160165
|
+
const markers = [...unchanged, ...current].sort((a, b) => a.range.byteStart - b.range.byteStart);
|
|
160014
160166
|
cache.set(input.partUri, {
|
|
160015
160167
|
bytes,
|
|
160016
160168
|
partRevision: revision,
|
|
160017
160169
|
complete: prior.complete && scanned.complete,
|
|
160018
|
-
markers
|
|
160170
|
+
markers,
|
|
160171
|
+
markersBySourceId: indexMarkersBySourceId(markers)
|
|
160019
160172
|
});
|
|
160020
160173
|
}
|
|
160021
160174
|
function findRetainedBodyCommentAnchors(state, partUri, commentId, occurrenceIndex) {
|
|
160022
|
-
return anchorsFromMarkers(
|
|
160175
|
+
return anchorsFromMarkers(getBodyCommentMarkersForSourceId(state, partUri, commentId), commentId, occurrenceIndex);
|
|
160023
160176
|
}
|
|
160024
160177
|
function countRetainedBodyCommentAnchorOccurrences(state, partUri, commentId) {
|
|
160025
160178
|
const counts = { commentRangeStart: 0, commentRangeEnd: 0, commentReference: 0 };
|
|
160026
|
-
for (const marker of
|
|
160027
|
-
|
|
160028
|
-
counts[marker.kind] += 1;
|
|
160029
|
-
}
|
|
160179
|
+
for (const marker of getBodyCommentMarkersForSourceId(state, partUri, commentId))
|
|
160180
|
+
counts[marker.kind] += 1;
|
|
160030
160181
|
return Math.max(counts.commentRangeStart, counts.commentRangeEnd, counts.commentReference);
|
|
160031
160182
|
}
|
|
160032
160183
|
function collectBodyCommentMarkers(documentXml, namespaceBindings) {
|
|
@@ -185500,7 +185651,8 @@ function createReviewStagingState(state, targetBlockIds) {
|
|
|
185500
185651
|
result[key3] = clone2(item);
|
|
185501
185652
|
return result;
|
|
185502
185653
|
};
|
|
185503
|
-
Object.assign(staged, Object.fromEntries(Object.entries(staged).filter(([key3]) => !["packageBytes", "paragraphIndexes", "partRegistries"].includes(key3)).map(([key3, value]) => [key3, clone2(value)])));
|
|
185654
|
+
Object.assign(staged, Object.fromEntries(Object.entries(staged).filter(([key3]) => !["packageBytes", "paragraphIndexes", "partRegistries", "history"].includes(key3)).map(([key3, value]) => [key3, clone2(value)])));
|
|
185655
|
+
staged.history = { entries: new Map(state.history.entries), order: [...state.history.order] };
|
|
185504
185656
|
staged.paragraphIndexes = new Map;
|
|
185505
185657
|
staged.partRegistries = new Map;
|
|
185506
185658
|
staged.revisions = new RevisionAllocator("review-preview");
|
|
@@ -202035,6 +202187,7 @@ function commitResidentText(input, view) {
|
|
|
202035
202187
|
return null;
|
|
202036
202188
|
const range = { byteStart: paragraph.byteStart, byteEnd: paragraph.byteEnd };
|
|
202037
202189
|
const collapsed = op.on.startOffset === op.on.endOffset;
|
|
202190
|
+
const leadingBookmarkBoundary = collapsed && op.newText.length > 0 && edit.visibleStart === 0 && edit.before.model.leaves().some((piece) => piece.kind === "marker" && piece.visibleStart === 0 && (piece.markerKind === "bookmarkStart" || piece.markerKind === "bookmarkEnd"));
|
|
202038
202191
|
const requiresCollaborationSessionSync = op.changeMode === "direct" && op.on.coordinateSpace === "tracked" && edit.visibleStart !== op.on.startOffset;
|
|
202039
202192
|
return finalizeCommit({
|
|
202040
202193
|
input,
|
|
@@ -202059,7 +202212,8 @@ function commitResidentText(input, view) {
|
|
|
202059
202212
|
blockId: op.on.startBlockId,
|
|
202060
202213
|
startOffset: edit.visibleStart,
|
|
202061
202214
|
text: op.newText,
|
|
202062
|
-
runPropertiesXml: leaf.runProperties ?? ""
|
|
202215
|
+
runPropertiesXml: leaf.runProperties ?? "",
|
|
202216
|
+
...leadingBookmarkBoundary ? { afterLeadingMarkers: true } : {}
|
|
202063
202217
|
} } : {},
|
|
202064
202218
|
...edit.insertionRsid && !collapsed ? { trackedTextRefinement: {
|
|
202065
202219
|
kind: "trackedTextRefinement",
|
|
@@ -264694,8 +264848,7 @@ class TxContext {
|
|
|
264694
264848
|
const documentBytes = this.state.packageBytes.get(op.on.partUri);
|
|
264695
264849
|
if (!documentBytes)
|
|
264696
264850
|
return rejected21(this.txId, "invalid-range");
|
|
264697
|
-
const
|
|
264698
|
-
const anchors = findBodyCommentAnchors(documentXml, markerWId, sourceStoryInfo.localOccurrenceIndex);
|
|
264851
|
+
const anchors = sourceStoryInfo.anchors;
|
|
264699
264852
|
if (!anchors.rangeStart || !anchors.rangeEnd) {
|
|
264700
264853
|
return rejected21(this.txId, "comment-anchor-not-found");
|
|
264701
264854
|
}
|
|
@@ -264714,7 +264867,7 @@ class TxContext {
|
|
|
264714
264867
|
continue;
|
|
264715
264868
|
if (threadStory.partUri !== op.on.partUri)
|
|
264716
264869
|
return rejected21(this.txId, "comment-move-cross-story");
|
|
264717
|
-
const threadAnchors =
|
|
264870
|
+
const threadAnchors = threadStory.anchors;
|
|
264718
264871
|
if (threadAnchors.rangeStart)
|
|
264719
264872
|
removeRanges.push(threadAnchors.rangeStart);
|
|
264720
264873
|
if (threadAnchors.rangeEnd)
|
|
@@ -264741,7 +264894,7 @@ class TxContext {
|
|
|
264741
264894
|
};
|
|
264742
264895
|
if (newRange.byteEnd < newRange.byteStart)
|
|
264743
264896
|
return rejected21(this.txId, "invalid-range");
|
|
264744
|
-
if (!op.allowMarkerCarrierOverlap && rangesOverlap(oldEnvelope, newRange)) {
|
|
264897
|
+
if (!op.allowMarkerCarrierOverlap && rangesOverlap(oldEnvelope, newRange) && !isUnchangedCommentRange(this.state, op.on, markerWId, anchors)) {
|
|
264745
264898
|
return rejected21(this.txId, "comment-move-overlap");
|
|
264746
264899
|
}
|
|
264747
264900
|
const stripped = stripBytes2(documentBytes, mergedRemovals);
|
|
@@ -264749,7 +264902,7 @@ class TxContext {
|
|
|
264749
264902
|
const newEnd = translateAfterRemovals(newRange.byteEnd, mergedRemovals);
|
|
264750
264903
|
if (newStart == null || newEnd == null)
|
|
264751
264904
|
return rejected21(this.txId, "comment-move-overlap");
|
|
264752
|
-
const rewrite = rewriteDocumentXml(
|
|
264905
|
+
const rewrite = rewriteDocumentXml(TD_KEEP_BOM.decode(stripped), { ...op.on, startByte: newStart, endByte: newEnd }, markerWId, undefined, {
|
|
264753
264906
|
start: relocatedAnchors.map((anchor) => commentRangeStart(anchor.markerWId)).join(""),
|
|
264754
264907
|
end: relocatedAnchors.map((anchor) => commentRangeEnd(anchor.markerWId) + commentReferenceRun(anchor.markerWId, anchor.referenceRunXml)).join("")
|
|
264755
264908
|
});
|
|
@@ -264778,28 +264931,31 @@ class TxContext {
|
|
|
264778
264931
|
const commentsBytes = this.state.packageBytes.get(COMMENTS_PART_URI3);
|
|
264779
264932
|
if (!commentsBytes)
|
|
264780
264933
|
return rejected21(this.txId, "comments-part-missing");
|
|
264781
|
-
const
|
|
264782
|
-
|
|
264934
|
+
const bom = commentsBytes[0] === 239 && commentsBytes[1] === 187 && commentsBytes[2] === 191 ? 3 : 0;
|
|
264935
|
+
const commentsPatches = [];
|
|
264783
264936
|
for (const threadEntry of threadEntries) {
|
|
264784
|
-
const
|
|
264937
|
+
const startByte = threadEntry.byteStart + bom;
|
|
264938
|
+
const endByte = threadEntry.byteEnd + bom;
|
|
264939
|
+
const fragment3 = TD78.decode(commentsBytes.subarray(startByte, endByte));
|
|
264940
|
+
const rewritten = rewriteCommentTrackedChangeMetadata(fragment3, threadEntry.sourceWId || threadEntry.wId, 0, op.trackedChangeMetadata);
|
|
264785
264941
|
if (!rewritten.ok)
|
|
264786
264942
|
return rejected21(this.txId, rewritten.reason);
|
|
264787
|
-
|
|
264943
|
+
if (rewritten.xml !== fragment3)
|
|
264944
|
+
commentsPatches.push({
|
|
264945
|
+
kind: "replaceBytes",
|
|
264946
|
+
order: commentsPatches.length,
|
|
264947
|
+
startByte,
|
|
264948
|
+
endByte,
|
|
264949
|
+
bytes: TE44.encode(rewritten.xml)
|
|
264950
|
+
});
|
|
264788
264951
|
}
|
|
264789
|
-
if (
|
|
264790
|
-
|
|
264791
|
-
kind: "replaceBytes",
|
|
264792
|
-
order: 0,
|
|
264793
|
-
startByte: 0,
|
|
264794
|
-
endByte: commentsBytes.length,
|
|
264795
|
-
bytes: TE44.encode(commentsNext)
|
|
264796
|
-
};
|
|
264797
|
-
perPart[COMMENTS_PART_URI3] = { kind: "modify", patches: [commentsPatch] };
|
|
264952
|
+
if (commentsPatches.length > 0) {
|
|
264953
|
+
perPart[COMMENTS_PART_URI3] = { kind: "modify", patches: commentsPatches };
|
|
264798
264954
|
preconditions.push(byteWindowPrecondition10(COMMENTS_PART_URI3, commentsBytes));
|
|
264799
264955
|
const commentsMap = buildPatchMap({
|
|
264800
264956
|
partUri: COMMENTS_PART_URI3,
|
|
264801
264957
|
originalLength: commentsBytes.length,
|
|
264802
|
-
patches:
|
|
264958
|
+
patches: commentsPatches
|
|
264803
264959
|
});
|
|
264804
264960
|
patchMaps[COMMENTS_PART_URI3] = commentsMap.ok ? commentsMap.value : { partUri: COMMENTS_PART_URI3, ranges: [] };
|
|
264805
264961
|
}
|
|
@@ -265440,6 +265596,34 @@ function locateCommentAnchorStory(state, commentId, occurrenceIndex) {
|
|
|
265440
265596
|
}
|
|
265441
265597
|
return null;
|
|
265442
265598
|
}
|
|
265599
|
+
function isUnchangedCommentRange(state, target, markerWId, anchors) {
|
|
265600
|
+
if (!anchors.rangeStart || !anchors.rangeEnd)
|
|
265601
|
+
return false;
|
|
265602
|
+
const markers = getBodyCommentMarkersForSourceId(state, target.partUri, markerWId);
|
|
265603
|
+
const bytes = state.packageBytes.get(target.partUri);
|
|
265604
|
+
if (!bytes)
|
|
265605
|
+
return false;
|
|
265606
|
+
const models = new Map;
|
|
265607
|
+
const matchesBoundary = (kind, anchor, blockId, offset) => {
|
|
265608
|
+
const marker = markers.find((item) => item.kind === kind && item.range.byteStart === anchor.byteStart);
|
|
265609
|
+
const paragraph = marker?.paragraph;
|
|
265610
|
+
if (!paragraph || anchor.byteStart < paragraph.range.byteStart || anchor.byteEnd > paragraph.range.byteEnd)
|
|
265611
|
+
return false;
|
|
265612
|
+
if (paragraph.blockId !== blockId) {
|
|
265613
|
+
const indexed = getStoryParagraphIndexFromState(state, target.storyId)?.byParaId(blockId);
|
|
265614
|
+
if (!indexed || indexed.partUri !== target.partUri || indexed.partRevision !== target.partRevision || indexed.byteStart !== paragraph.range.byteStart || indexed.byteEnd !== paragraph.range.byteEnd)
|
|
265615
|
+
return false;
|
|
265616
|
+
}
|
|
265617
|
+
let model = models.get(paragraph.range.byteStart);
|
|
265618
|
+
if (!model) {
|
|
265619
|
+
model = parseParagraphInlineMap(TD78.decode(bytes.subarray(paragraph.range.byteStart, paragraph.range.byteEnd)), paragraph.namespaceBindings);
|
|
265620
|
+
models.set(paragraph.range.byteStart, model);
|
|
265621
|
+
}
|
|
265622
|
+
const leaf = model.leaves().find((piece) => piece.kind === "marker" && piece.id === markerWId && piece.markerKind === kind && piece.byteStart + paragraph.range.byteStart === anchor.byteStart);
|
|
265623
|
+
return !!leaf && (target.coordinateSpace === "tracked" ? leaf.trackedStart : leaf.visibleStart) === offset;
|
|
265624
|
+
};
|
|
265625
|
+
return matchesBoundary("commentRangeStart", anchors.rangeStart, target.startBlockId, target.startOffset) && matchesBoundary("commentRangeEnd", anchors.rangeEnd, target.endBlockId, target.endOffset);
|
|
265626
|
+
}
|
|
265443
265627
|
function findCommentAnchorsForStory(state, partUri, storyXml, commentId, occurrenceIndex) {
|
|
265444
265628
|
const localOccurrenceIndex = localOccurrenceIndexForStory(state, partUri, storyXml, commentId, occurrenceIndex);
|
|
265445
265629
|
if (localOccurrenceIndex === null) {
|
|
@@ -266206,22 +266390,25 @@ function materializeCurrentCommentThreadExtendedRows(input) {
|
|
|
266206
266390
|
Object.assign(input.patchMaps, compiled.value.patchMaps);
|
|
266207
266391
|
return { ok: true };
|
|
266208
266392
|
}
|
|
266209
|
-
|
|
266210
|
-
|
|
266211
|
-
|
|
266212
|
-
const
|
|
266213
|
-
|
|
266214
|
-
|
|
266215
|
-
|
|
266216
|
-
|
|
266217
|
-
|
|
266218
|
-
|
|
266219
|
-
|
|
266220
|
-
|
|
266221
|
-
|
|
266222
|
-
|
|
266393
|
+
const xml = TD_KEEP_BOM.decode(extendedBytes);
|
|
266394
|
+
const remaining = new Map(entries2.map((item) => [item.paraId, item]));
|
|
266395
|
+
let nextXml = xml.replace(/<[\w.-]+:commentEx\b[^>]*>/g, (fragment3) => {
|
|
266396
|
+
const paraId = /\b(?:w14|w15):paraId="([^"]*)"/.exec(fragment3)?.[1];
|
|
266397
|
+
const item = paraId ? remaining.get(paraId) : undefined;
|
|
266398
|
+
if (!item)
|
|
266399
|
+
return fragment3;
|
|
266400
|
+
remaining.delete(item.paraId);
|
|
266401
|
+
const next = upsertCommentsExtendedThreadRow(fragment3, item);
|
|
266402
|
+
return next.ok ? next.value : fragment3;
|
|
266403
|
+
});
|
|
266404
|
+
if (remaining.size > 0) {
|
|
266405
|
+
const fragments = [...remaining.values()].map(commentsExtendedRowXml).join("");
|
|
266406
|
+
const appended = appendToExistingXmlRoot(nextXml, fragments, "commentsEx");
|
|
266407
|
+
if (!appended.ok)
|
|
266408
|
+
return appended;
|
|
266409
|
+
nextXml = appended.value;
|
|
266223
266410
|
}
|
|
266224
|
-
if (
|
|
266411
|
+
if (nextXml !== xml)
|
|
266225
266412
|
addWholePartReplace(input, COMMENTS_EXTENDED_PART_URI3, extendedBytes, nextXml);
|
|
266226
266413
|
return { ok: true };
|
|
266227
266414
|
}
|
|
@@ -266277,11 +266464,13 @@ function threadRootParaId(catalog, entry) {
|
|
|
266277
266464
|
}
|
|
266278
266465
|
return entry.paraId;
|
|
266279
266466
|
}
|
|
266280
|
-
function
|
|
266467
|
+
function commentsExtendedRowXml(input) {
|
|
266281
266468
|
const parentAttr = input.parentParaId ? ` w15:paraIdParent="${escapeXmlAttribute(input.parentParaId)}"` : "";
|
|
266282
266469
|
const doneAttr = input.done ? "1" : "0";
|
|
266283
|
-
|
|
266284
|
-
|
|
266470
|
+
return `<w15:commentEx w15:paraId="${escapeXmlAttribute(input.paraId)}" w15:done="${doneAttr}"${parentAttr}/>`;
|
|
266471
|
+
}
|
|
266472
|
+
function appendCommentsExtendedXml(xml, input) {
|
|
266473
|
+
return appendToExistingXmlRoot(xml, commentsExtendedRowXml(input), "commentsEx");
|
|
266285
266474
|
}
|
|
266286
266475
|
function appendCommentsIdsXml(xml, input) {
|
|
266287
266476
|
const fragment3 = `<w16cid:commentId w16cid:paraId="${escapeXmlAttribute(input.paraId)}" w16cid:durableId="${escapeXmlAttribute(input.durableId)}"/>`;
|
|
@@ -266448,7 +266637,7 @@ function emptyHeaderFooterSkeleton(kind) {
|
|
|
266448
266637
|
const root = kind === "header" ? "w:hdr" : "w:ftr";
|
|
266449
266638
|
return '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + `<${root}` + ' xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"' + ' xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"' + ">" + "<w:p/>" + `</${root}>`;
|
|
266450
266639
|
}
|
|
266451
|
-
var TE44, TD78, nextTx = 0, CONTENT_TYPES_PART_URI12 = "/[Content_Types].xml", DOCUMENT_RELS_PART_URI10 = "/word/_rels/document.xml.rels", COMMENTS_PART_URI3 = "/word/comments.xml", COMMENTS_IDS_PART_URI3 = "/word/commentsIds.xml", COMMENTS_EXTENDED_PART_URI3 = "/word/commentsExtended.xml", SDCOM_COMMENTS_NS_URI = "http://superdoc.dev/2024/comments", COMMENT_ELEMENT_RE, RUN_HAS_TEXT_LEAF_VISIBLE_RE, RUN_HAS_TEXT_LEAF_TRACKED_RE, RUN_CONTROL_LEAF_RE, RUN_TEXT_LEAF_RE_VISIBLE, RUN_TEXT_LEAF_RE_TRACKED;
|
|
266640
|
+
var TE44, TD78, TD_KEEP_BOM, nextTx = 0, CONTENT_TYPES_PART_URI12 = "/[Content_Types].xml", DOCUMENT_RELS_PART_URI10 = "/word/_rels/document.xml.rels", COMMENTS_PART_URI3 = "/word/comments.xml", COMMENTS_IDS_PART_URI3 = "/word/commentsIds.xml", COMMENTS_EXTENDED_PART_URI3 = "/word/commentsExtended.xml", SDCOM_COMMENTS_NS_URI = "http://superdoc.dev/2024/comments", COMMENT_ELEMENT_RE, RUN_HAS_TEXT_LEAF_VISIBLE_RE, RUN_HAS_TEXT_LEAF_TRACKED_RE, RUN_CONTROL_LEAF_RE, RUN_TEXT_LEAF_RE_VISIBLE, RUN_TEXT_LEAF_RE_TRACKED;
|
|
266452
266641
|
var init_tx_context = __esm(() => {
|
|
266453
266642
|
init_resident_paragraph_ownership();
|
|
266454
266643
|
init_canonical_xml_analysis_frame();
|
|
@@ -266494,6 +266683,7 @@ var init_tx_context = __esm(() => {
|
|
|
266494
266683
|
init_compile_image_ops();
|
|
266495
266684
|
TE44 = new TextEncoder;
|
|
266496
266685
|
TD78 = new TextDecoder;
|
|
266686
|
+
TD_KEEP_BOM = new TextDecoder("utf-8", { ignoreBOM: true });
|
|
266497
266687
|
COMMENT_ELEMENT_RE = /<[\w.-]+:comment(?=[\s>/])/;
|
|
266498
266688
|
RUN_HAS_TEXT_LEAF_VISIBLE_RE = /<[\w.-]+:t\b/;
|
|
266499
266689
|
RUN_HAS_TEXT_LEAF_TRACKED_RE = /<[\w.-]+:(t|delText)\b/;
|
|
@@ -377832,13 +378022,29 @@ function resolveCommentEntryByParaId(catalog, paraId) {
|
|
|
377832
378022
|
return null;
|
|
377833
378023
|
return catalog.commentsByCommentId.get(canonicalCommentId) ?? null;
|
|
377834
378024
|
}
|
|
378025
|
+
function commentAnchorProjectionEntry(entry, catalog, anchorIndex) {
|
|
378026
|
+
let cursor = entry;
|
|
378027
|
+
const seen = new Set;
|
|
378028
|
+
while (cursor.parentParaId !== null) {
|
|
378029
|
+
if (seen.has(cursor.commentId))
|
|
378030
|
+
return entry;
|
|
378031
|
+
seen.add(cursor.commentId);
|
|
378032
|
+
const hits = anchorIndex.hitsBySourceWId.get(cursor.sourceWId) ?? [];
|
|
378033
|
+
if (catalog.commentsBySourceWId.get(cursor.sourceWId)?.length !== 1 || !hits.some((hit) => hit.hasReference) || hits.some((hit) => hit.hasRangeStart || hit.hasRangeEnd))
|
|
378034
|
+
break;
|
|
378035
|
+
const parent = resolveCommentEntryByParaId(catalog, cursor.parentParaId);
|
|
378036
|
+
if (!parent)
|
|
378037
|
+
break;
|
|
378038
|
+
cursor = parent;
|
|
378039
|
+
}
|
|
378040
|
+
return cursor;
|
|
378041
|
+
}
|
|
377835
378042
|
function toCommentInfo(entry, catalog, anchorIndex, headerFooterRels, trackedAssociations) {
|
|
377836
378043
|
const publicCommentId = publicCommentIdForEntry(entry);
|
|
377837
378044
|
const parentParaId = entry.parentParaId;
|
|
377838
378045
|
const parentEntry = parentParaId ? resolveCommentEntryByParaId(catalog, parentParaId) : null;
|
|
377839
378046
|
const parentCommentId = parentEntry ? publicCommentIdForEntry(parentEntry) : undefined;
|
|
377840
378047
|
const rootCommentId = parentCommentId ? rootCommentIdForCatalogEntry(entry, catalog) : null;
|
|
377841
|
-
const anchorProjectionEntry = entry;
|
|
377842
378048
|
const info = {
|
|
377843
378049
|
address: { kind: "entity", entityType: "comment", entityId: publicCommentId },
|
|
377844
378050
|
commentId: publicCommentId,
|
|
@@ -377860,10 +378066,9 @@ function toCommentInfo(entry, catalog, anchorIndex, headerFooterRels, trackedAss
|
|
|
377860
378066
|
info.creatorImage = entry.authorImage;
|
|
377861
378067
|
if (entry.importedId !== null && entry.importedId !== publicCommentId)
|
|
377862
378068
|
info.importedId = entry.importedId;
|
|
377863
|
-
let sourceSiblings;
|
|
377864
378069
|
if (entry.sourceWId) {
|
|
377865
378070
|
info.rawOoxmlId = entry.sourceWId;
|
|
377866
|
-
sourceSiblings = catalog.commentsBySourceWId.get(entry.sourceWId);
|
|
378071
|
+
const sourceSiblings = catalog.commentsBySourceWId.get(entry.sourceWId);
|
|
377867
378072
|
if (sourceSiblings && sourceSiblings.length > 1) {
|
|
377868
378073
|
info.rawOoxmlOccurrenceIndex = entry.sourceWIdOccurrenceIndex;
|
|
377869
378074
|
}
|
|
@@ -377901,11 +378106,12 @@ function toCommentInfo(entry, catalog, anchorIndex, headerFooterRels, trackedAss
|
|
|
377901
378106
|
if (!info.trackedChange) {
|
|
377902
378107
|
attachMetadataOnlyTrackedChangeLink(info, entry, anchorIndex ? null : trackedAssociations, metadataAssociation.status !== "unsafe");
|
|
377903
378108
|
}
|
|
377904
|
-
if (anchorIndex
|
|
378109
|
+
if (anchorIndex) {
|
|
378110
|
+
const anchorProjectionEntry = commentAnchorProjectionEntry(entry, catalog, anchorIndex);
|
|
377905
378111
|
const hits = anchorIndex.hitsBySourceWId.get(anchorProjectionEntry.sourceWId) ?? [];
|
|
377906
378112
|
const projectable = hits.filter((h) => h.story.kind === "body" || h.story.kind === "header" || h.story.kind === "footer");
|
|
377907
378113
|
if (projectable.length > 0) {
|
|
377908
|
-
|
|
378114
|
+
const sourceSiblings = catalog.commentsBySourceWId.get(anchorProjectionEntry.sourceWId);
|
|
377909
378115
|
const globalSegmentIndex = sourceSiblings && sourceSiblings.length > 1 ? anchorProjectionEntry.sourceWIdOccurrenceIndex : undefined;
|
|
377910
378116
|
const projected = projectAnchor(projectable, headerFooterRels, globalSegmentIndex);
|
|
377911
378117
|
if (projected) {
|
|
@@ -385238,6 +385444,7 @@ class V2ListsAdapter {
|
|
|
385238
385444
|
if (insertReceipt.status === "rejected") {
|
|
385239
385445
|
return failure8(mapRejectionReason(insertReceipt.rejectedReason ?? "internal-error"), insertReceipt.rejectedReason ?? "list insert: paragraph insert rejected");
|
|
385240
385446
|
}
|
|
385447
|
+
this.context.invalidate(insertReceipt);
|
|
385241
385448
|
recordCommittedTxIdForHistory(this.context, insertReceipt.txId);
|
|
385242
385449
|
const newParaId = readCreatedParagraphRefId(insertReceipt.createdRefs ?? [], insertReceipt.provisionalToFinal);
|
|
385243
385450
|
if (!newParaId) {
|
|
@@ -385364,6 +385571,7 @@ class V2ListsAdapter {
|
|
|
385364
385571
|
if (insertReceipt.status === "rejected") {
|
|
385365
385572
|
return failure8(mapRejectionReason(insertReceipt.rejectedReason ?? "internal-error"), insertReceipt.rejectedReason ?? "list create: paragraph insert rejected");
|
|
385366
385573
|
}
|
|
385574
|
+
this.context.invalidate(insertReceipt);
|
|
385367
385575
|
recordCommittedTxIdForHistory(this.context, insertReceipt.txId);
|
|
385368
385576
|
const newParaId = readCreatedParagraphRefId(insertReceipt.createdRefs ?? [], insertReceipt.provisionalToFinal);
|
|
385369
385577
|
if (!newParaId) {
|
|
@@ -387095,6 +387303,7 @@ function applyListSeed(adapter, storyId, paraId, kind, expectedRevision, changeM
|
|
|
387095
387303
|
if (receipt3.status === "rejected") {
|
|
387096
387304
|
return failure8(mapRejectionReason(receipt3.rejectedReason ?? "internal-error"), receipt3.rejectedReason ?? "list create rejected");
|
|
387097
387305
|
}
|
|
387306
|
+
adapter.context.invalidate(receipt3);
|
|
387098
387307
|
recordCommittedTxIdForHistory(adapter.context, receipt3.txId);
|
|
387099
387308
|
const summary = readListItemSummaryForSession(adapter.context.session, storyId, paraId);
|
|
387100
387309
|
return {
|
|
@@ -419150,8 +419359,67 @@ async function compilePlan(context, input) {
|
|
|
419150
419359
|
}
|
|
419151
419360
|
detectTargetConflicts(context, steps, failures);
|
|
419152
419361
|
detectUnsupportedRuntimeDrift(input.steps, failures);
|
|
419153
|
-
|
|
419154
|
-
|
|
419362
|
+
const exactProgram = failures.length === 0 ? compileDescendingExactTargets(context, steps) : undefined;
|
|
419363
|
+
if (exactProgram) {
|
|
419364
|
+
if (exactProgram.edits.length > 0) {
|
|
419365
|
+
const preview = new V2SelectionMutationAdapter(context).executeResolvedTextRewrites(exactProgram.edits, { changeMode: changeMode ?? "direct", dryRun: true });
|
|
419366
|
+
if (!preview.success)
|
|
419367
|
+
failures.push({
|
|
419368
|
+
code: preview.failure.code,
|
|
419369
|
+
stepId: exactProgram.edits[0].ownerStepId,
|
|
419370
|
+
phase: "compile",
|
|
419371
|
+
message: preview.failure.message
|
|
419372
|
+
});
|
|
419373
|
+
}
|
|
419374
|
+
} else
|
|
419375
|
+
detectTargetOffsetDriftRisk(steps, failures);
|
|
419376
|
+
return {
|
|
419377
|
+
evaluatedRevision,
|
|
419378
|
+
steps,
|
|
419379
|
+
failures,
|
|
419380
|
+
...exactProgram ? { atomicTextProgram: exactProgram } : {}
|
|
419381
|
+
};
|
|
419382
|
+
}
|
|
419383
|
+
function compileDescendingExactTargets(context, steps) {
|
|
419384
|
+
const mutating = steps.filter((step3) => step3.op !== "assert");
|
|
419385
|
+
if (mutating.length < 2)
|
|
419386
|
+
return;
|
|
419387
|
+
const edits = [];
|
|
419388
|
+
let blockId;
|
|
419389
|
+
let previousStart = Infinity;
|
|
419390
|
+
const index2 = getSDDocumentSessionInternalParagraphIndex(context.session);
|
|
419391
|
+
if (!index2)
|
|
419392
|
+
return;
|
|
419393
|
+
for (const step3 of mutating) {
|
|
419394
|
+
const source = step3.source;
|
|
419395
|
+
if (step3.op !== "text.rewrite" && step3.op !== "text.delete" || source.op === "assert" || !("where" in source) || source.where.by !== "target" || !step3.resolution || step3.request?.kind !== "replace")
|
|
419396
|
+
return;
|
|
419397
|
+
const target = source.where.target;
|
|
419398
|
+
if (target.kind !== "selection" || target.start.kind !== "text" || target.end.kind !== "text" || target.coordinateSpace === "tracked" || !isSupportedMutationStoryScope(target.story) || !isSupportedMutationStoryScope(target.start.story) || !isSupportedMutationStoryScope(target.end.story) || target.start.blockId !== target.end.blockId)
|
|
419399
|
+
return;
|
|
419400
|
+
blockId ?? (blockId = target.start.blockId);
|
|
419401
|
+
if (target.start.blockId !== blockId || step3.resolution.range.from >= step3.resolution.range.to || step3.resolution.range.to > previousStart)
|
|
419402
|
+
return;
|
|
419403
|
+
previousStart = step3.resolution.range.from;
|
|
419404
|
+
const on = resolveSelectionTargetToRange({
|
|
419405
|
+
target,
|
|
419406
|
+
index: index2,
|
|
419407
|
+
readPartBytes: (partUri) => getSDDocumentSessionInternalPartBytes(context.session, partUri),
|
|
419408
|
+
readPartRange: (partUri, start, end) => getSDDocumentSessionInternalPartRange(context.session, partUri, start, end),
|
|
419409
|
+
buildOffsetMap: buildOffsetMapForCoordinateSpace4
|
|
419410
|
+
});
|
|
419411
|
+
if ("error" in on)
|
|
419412
|
+
throw new DocumentApiValidationError2(on.error, on.message);
|
|
419413
|
+
if (step3.request.text !== step3.resolution.text)
|
|
419414
|
+
edits.push({
|
|
419415
|
+
on,
|
|
419416
|
+
newText: step3.request.text,
|
|
419417
|
+
resolution: step3.resolution,
|
|
419418
|
+
ownerStepId: step3.stepId,
|
|
419419
|
+
rewriteIntent: step3.op === "text.rewrite"
|
|
419420
|
+
});
|
|
419421
|
+
}
|
|
419422
|
+
return { edits };
|
|
419155
419423
|
}
|
|
419156
419424
|
function isOrderedAtomicTextProgram(steps) {
|
|
419157
419425
|
return steps.length > 1 && steps.every((step3) => (step3.op === "text.rewrite" || step3.op === "text.delete") && step3.where.by === "select" && step3.where.select.type === "text" && step3.where.require === "all");
|
|
@@ -420748,6 +421016,7 @@ var init_engine3 = __esm(() => {
|
|
|
420748
421016
|
init_sd_document_session_internal();
|
|
420749
421017
|
init_search();
|
|
420750
421018
|
init_raw_block_ref();
|
|
421019
|
+
init_selection_target();
|
|
420751
421020
|
init_story_identity();
|
|
420752
421021
|
init_story_surface();
|
|
420753
421022
|
init_v2_search_ref();
|
|
@@ -475103,7 +475372,7 @@ function tryMirrorStoryText(prepared, extension2, options, admitted) {
|
|
|
475103
475372
|
text: source.newText,
|
|
475104
475373
|
txId: prepared.txId,
|
|
475105
475374
|
directInsert: validation.directInsert,
|
|
475106
|
-
preserveZeroLengthAtOffset: validation.inlineControl?.afterParagraphTail,
|
|
475375
|
+
preserveZeroLengthAtOffset: validation.directInsert.afterLeadingMarkers || validation.inlineControl?.afterParagraphTail,
|
|
475107
475376
|
acceptedTextInsertionSplit: validation.acceptedTextInsertionSplit
|
|
475108
475377
|
});
|
|
475109
475378
|
} else {
|
|
@@ -475534,7 +475803,7 @@ function validateDirectTextInsert(source, extension2) {
|
|
|
475534
475803
|
if (!directInsert) {
|
|
475535
475804
|
return { ok: false, failureReason: "direct insert requires typed storySurface metadata" };
|
|
475536
475805
|
}
|
|
475537
|
-
if (directInsert.kind !== "directTextInsert" || directInsert.blockId !== source.on.startBlockId || directInsert.startOffset !== source.on.startOffset || directInsert.text !== source.newText) {
|
|
475806
|
+
if (directInsert.kind !== "directTextInsert" || directInsert.blockId !== source.on.startBlockId || directInsert.startOffset !== source.on.startOffset || directInsert.text !== source.newText || directInsert.afterLeadingMarkers !== undefined && (directInsert.afterLeadingMarkers !== true || directInsert.startOffset !== 0)) {
|
|
475538
475807
|
return { ok: false, failureReason: "direct insert storySurface metadata does not match source" };
|
|
475539
475808
|
}
|
|
475540
475809
|
if (parsePreparedRunAttributes(directInsert.runPropertiesXml) === null) {
|
|
@@ -482861,6 +483130,25 @@ async function openV2CollaborativeDocumentSession(options) {
|
|
|
482861
483130
|
} else {
|
|
482862
483131
|
trace.mark("source-complete-deferred");
|
|
482863
483132
|
}
|
|
483133
|
+
if (ownsPreparedBootstrap) {
|
|
483134
|
+
const current = readRoomManifest(rootConn.ydoc);
|
|
483135
|
+
if (current.snapshot?.meta.bootstrapState === "committed") {
|
|
483136
|
+
const committed = options.runtime.validateLateJoin({
|
|
483137
|
+
compatibility: { supports: COLLAB_V2_ROOM_SCHEMA_VERSION },
|
|
483138
|
+
readiness: READINESS_CLASS.bodyEditable
|
|
483139
|
+
});
|
|
483140
|
+
if (!committed.ok)
|
|
483141
|
+
throwLateJoinValidationFailure(committed, options.runtime.rootId);
|
|
483142
|
+
throw new CollabV2DiagnosticError(COLLAB_V2_DIAGNOSTICS.COLLAB_V2_ROOM_ALREADY_EXISTS, "another creator committed this v2 collaboration room during open; reopen with join", { rootId: options.runtime.rootId });
|
|
483143
|
+
}
|
|
483144
|
+
if (current.snapshot?.meta.bootstrapState !== "pending" || current.diagnostics.length > 0) {
|
|
483145
|
+
throw new CollabV2DiagnosticError(COLLAB_V2_DIAGNOSTICS.COLLAB_V2_ROOM_CORRUPT, "prepared v2 collaboration room is no longer a valid pending room; this open did not publish content", { rootId: options.runtime.rootId });
|
|
483146
|
+
}
|
|
483147
|
+
const leader = readBootstrapClaims(rootConn.ydoc).find((claim) => claim.status !== "aborted");
|
|
483148
|
+
if (leader?.claimerId !== expectedClaimerId || leader?.status !== "pending") {
|
|
483149
|
+
throw new CollabV2DiagnosticError(COLLAB_V2_DIAGNOSTICS.COLLAB_V2_ROOM_INITIALIZING, "another creator is initializing this v2 collaboration room", { rootId: options.runtime.rootId });
|
|
483150
|
+
}
|
|
483151
|
+
}
|
|
482864
483152
|
const canonical = await buildCanonicalShardGraph({
|
|
482865
483153
|
runtime: options.runtime,
|
|
482866
483154
|
rootDoc: rootConn.ydoc,
|
|
@@ -483395,14 +483683,17 @@ async function buildCanonicalShardGraph(input) {
|
|
|
483395
483683
|
for (const { story, shardId, bytes } of stories) {
|
|
483396
483684
|
let unit;
|
|
483397
483685
|
if (maySeedStoryShardsFromLocalSource && bytes) {
|
|
483398
|
-
unit =
|
|
483399
|
-
|
|
483400
|
-
|
|
483401
|
-
|
|
483402
|
-
|
|
483403
|
-
|
|
483404
|
-
|
|
483405
|
-
|
|
483686
|
+
unit = rootDoc.transact(() => {
|
|
483687
|
+
const created = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.story });
|
|
483688
|
+
trySeedStoryShard(created, {
|
|
483689
|
+
shardId,
|
|
483690
|
+
storyId: story.storyId,
|
|
483691
|
+
storyKind: story.storyKind,
|
|
483692
|
+
sourcePartUri: story.partUri,
|
|
483693
|
+
bytes
|
|
483694
|
+
});
|
|
483695
|
+
return created;
|
|
483696
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483406
483697
|
} else {
|
|
483407
483698
|
await waitForStoryShardSeeded(rootDoc, shardId);
|
|
483408
483699
|
unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.story });
|
|
@@ -483475,13 +483766,16 @@ async function buildCanonicalShardGraph(input) {
|
|
|
483475
483766
|
let commentsHandle = null;
|
|
483476
483767
|
const commentsShardId = packageShardId2(input.runtime.rootId, SHARD_KIND.comments, COMMENTS_PART_URI6);
|
|
483477
483768
|
{
|
|
483478
|
-
const unit =
|
|
483479
|
-
|
|
483480
|
-
|
|
483481
|
-
|
|
483482
|
-
|
|
483483
|
-
|
|
483484
|
-
|
|
483769
|
+
const unit = rootDoc.transact(() => {
|
|
483770
|
+
const created = createCollabUnitHandle({ rootDoc, shardId: commentsShardId, shardKind: SHARD_KIND.comments });
|
|
483771
|
+
if (commentsFamily != null) {
|
|
483772
|
+
const commentsCatalog = buildCommentsCatalogFromParts(new Map(commentsFamily.parts.flatMap((part) => part.bytes ? [[part.partUri, part.bytes]] : [])));
|
|
483773
|
+
trySeedCommentsShard(created, commentsShardId, commentsCatalog, commentsFamily.partKeys, commentsFamily.parts);
|
|
483774
|
+
} else {
|
|
483775
|
+
trySeedEmptyCommentsShard(created, commentsShardId);
|
|
483776
|
+
}
|
|
483777
|
+
return created;
|
|
483778
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483485
483779
|
projectionHandles.set(commentsShardId, {
|
|
483486
483780
|
shardId: commentsShardId,
|
|
483487
483781
|
shardKind: SHARD_KIND.comments,
|
|
@@ -483609,243 +483903,259 @@ function subtreePackageHandle(rootDoc, unit, shardKind, bootstrap) {
|
|
|
483609
483903
|
};
|
|
483610
483904
|
}
|
|
483611
483905
|
async function connectRelationshipsShard(rootDoc, shardId, part) {
|
|
483612
|
-
|
|
483613
|
-
|
|
483614
|
-
|
|
483615
|
-
|
|
483616
|
-
|
|
483617
|
-
|
|
483618
|
-
relsUri: part.partUri,
|
|
483619
|
-
resolveTarget(target, targetMode) {
|
|
483620
|
-
return resolveTargetUri(ownerPartUri2, target, targetMode);
|
|
483621
|
-
}
|
|
483622
|
-
});
|
|
483623
|
-
try {
|
|
483624
|
-
seedRelationshipsShard({
|
|
483625
|
-
doc: unit,
|
|
483626
|
-
shardId,
|
|
483627
|
-
ownerPartKey: part.partKey,
|
|
483906
|
+
return rootDoc.transact(() => {
|
|
483907
|
+
const unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.relationships });
|
|
483908
|
+
if (part.bytes) {
|
|
483909
|
+
const ownerPartUri2 = ownerPartUriForRels3(part.partUri);
|
|
483910
|
+
const xml = TEXT_DECODER12.decode(part.bytes);
|
|
483911
|
+
const parsed = parseRelationshipsXml(xml, {
|
|
483628
483912
|
ownerPartUri: ownerPartUri2,
|
|
483629
|
-
|
|
483630
|
-
|
|
483631
|
-
|
|
483632
|
-
|
|
483633
|
-
targetMode: relationship.targetMode,
|
|
483634
|
-
external: relationship.targetMode === "External"
|
|
483635
|
-
}))
|
|
483913
|
+
relsUri: part.partUri,
|
|
483914
|
+
resolveTarget(target, targetMode) {
|
|
483915
|
+
return resolveTargetUri(ownerPartUri2, target, targetMode);
|
|
483916
|
+
}
|
|
483636
483917
|
});
|
|
483637
|
-
|
|
483638
|
-
|
|
483639
|
-
|
|
483918
|
+
try {
|
|
483919
|
+
seedRelationshipsShard({
|
|
483920
|
+
doc: unit,
|
|
483921
|
+
shardId,
|
|
483922
|
+
ownerPartKey: part.partKey,
|
|
483923
|
+
ownerPartUri: ownerPartUri2,
|
|
483924
|
+
relationships: parsed.relationships.map((relationship) => ({
|
|
483925
|
+
rId: relationship.id,
|
|
483926
|
+
type: relationship.type,
|
|
483927
|
+
target: relationship.target,
|
|
483928
|
+
targetMode: relationship.targetMode,
|
|
483929
|
+
external: relationship.targetMode === "External"
|
|
483930
|
+
}))
|
|
483931
|
+
});
|
|
483932
|
+
} catch (error50) {
|
|
483933
|
+
if (!isAlreadySeededError(error50))
|
|
483934
|
+
throw error50;
|
|
483935
|
+
}
|
|
483640
483936
|
}
|
|
483641
|
-
|
|
483642
|
-
|
|
483937
|
+
return subtreePackageHandle(rootDoc, unit, SHARD_KIND.relationships);
|
|
483938
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483643
483939
|
}
|
|
483644
483940
|
async function connectContentTypesShard(rootDoc, shardId, part) {
|
|
483645
|
-
|
|
483646
|
-
|
|
483647
|
-
|
|
483648
|
-
|
|
483649
|
-
|
|
483650
|
-
|
|
483651
|
-
|
|
483652
|
-
|
|
483653
|
-
|
|
483654
|
-
|
|
483655
|
-
|
|
483656
|
-
|
|
483657
|
-
|
|
483658
|
-
|
|
483659
|
-
|
|
483660
|
-
|
|
483661
|
-
|
|
483662
|
-
|
|
483663
|
-
|
|
483664
|
-
|
|
483665
|
-
|
|
483941
|
+
return rootDoc.transact(() => {
|
|
483942
|
+
const unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.contentTypes });
|
|
483943
|
+
if (part.bytes) {
|
|
483944
|
+
const parsed = parseContentTypes(TEXT_DECODER12.decode(part.bytes));
|
|
483945
|
+
try {
|
|
483946
|
+
seedContentTypesShard({
|
|
483947
|
+
doc: unit,
|
|
483948
|
+
shardId,
|
|
483949
|
+
ownerPartKey: part.partKey,
|
|
483950
|
+
ownerPartUri: part.partUri,
|
|
483951
|
+
defaults: Array.from(parsed.defaults.entries()).map(([extension2, contentType]) => ({
|
|
483952
|
+
extension: extension2,
|
|
483953
|
+
contentType
|
|
483954
|
+
})),
|
|
483955
|
+
overrides: Array.from(parsed.overrides.entries()).map(([partKey2, contentType]) => ({
|
|
483956
|
+
partKey: partKey2,
|
|
483957
|
+
contentType
|
|
483958
|
+
}))
|
|
483959
|
+
});
|
|
483960
|
+
} catch (error50) {
|
|
483961
|
+
if (!isAlreadySeededError(error50))
|
|
483962
|
+
throw error50;
|
|
483963
|
+
}
|
|
483666
483964
|
}
|
|
483667
|
-
|
|
483668
|
-
|
|
483965
|
+
return subtreePackageHandle(rootDoc, unit, SHARD_KIND.contentTypes);
|
|
483966
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483669
483967
|
}
|
|
483670
483968
|
async function connectStylesShard(rootDoc, shardId, part) {
|
|
483671
|
-
|
|
483672
|
-
|
|
483673
|
-
|
|
483674
|
-
|
|
483675
|
-
|
|
483676
|
-
|
|
483677
|
-
|
|
483678
|
-
|
|
483679
|
-
|
|
483680
|
-
|
|
483681
|
-
|
|
483682
|
-
|
|
483683
|
-
|
|
483684
|
-
|
|
483685
|
-
|
|
483686
|
-
|
|
483687
|
-
|
|
483688
|
-
|
|
483969
|
+
return rootDoc.transact(() => {
|
|
483970
|
+
const unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.styles });
|
|
483971
|
+
let bootstrap;
|
|
483972
|
+
if (part.bytes) {
|
|
483973
|
+
const xml = TEXT_DECODER12.decode(part.bytes);
|
|
483974
|
+
const parsed = parseStylesPart3(xml);
|
|
483975
|
+
bootstrap = bootstrapPartProjection(xml);
|
|
483976
|
+
try {
|
|
483977
|
+
seedStylesShard({
|
|
483978
|
+
doc: unit,
|
|
483979
|
+
shardId,
|
|
483980
|
+
ownerPartKey: part.partKey,
|
|
483981
|
+
ownerPartUri: part.partUri,
|
|
483982
|
+
documentDefaults: parsed.documentDefaults,
|
|
483983
|
+
styles: parsed.styles
|
|
483984
|
+
});
|
|
483985
|
+
} catch (error50) {
|
|
483986
|
+
if (!isAlreadySeededError(error50))
|
|
483987
|
+
throw error50;
|
|
483988
|
+
}
|
|
483689
483989
|
}
|
|
483690
|
-
|
|
483691
|
-
|
|
483990
|
+
return subtreePackageHandle(rootDoc, unit, SHARD_KIND.styles, bootstrap);
|
|
483991
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483692
483992
|
}
|
|
483693
483993
|
async function connectNumberingShard(rootDoc, shardId, part, numbering) {
|
|
483694
|
-
|
|
483695
|
-
|
|
483696
|
-
|
|
483697
|
-
|
|
483698
|
-
|
|
483699
|
-
|
|
483700
|
-
|
|
483701
|
-
|
|
483702
|
-
|
|
483703
|
-
|
|
483704
|
-
|
|
483705
|
-
|
|
483706
|
-
|
|
483707
|
-
|
|
483708
|
-
|
|
483709
|
-
|
|
483710
|
-
|
|
483711
|
-
|
|
483712
|
-
|
|
483713
|
-
|
|
483714
|
-
|
|
483715
|
-
|
|
483716
|
-
|
|
483717
|
-
|
|
483718
|
-
|
|
483719
|
-
|
|
483720
|
-
|
|
483721
|
-
|
|
483722
|
-
|
|
483723
|
-
ilvl,
|
|
483724
|
-
|
|
483994
|
+
return rootDoc.transact(() => {
|
|
483995
|
+
const unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.numbering });
|
|
483996
|
+
let bootstrap;
|
|
483997
|
+
if (part.bytes) {
|
|
483998
|
+
bootstrap = bootstrapPartProjection(TEXT_DECODER12.decode(part.bytes));
|
|
483999
|
+
}
|
|
484000
|
+
if (part.bytes && numbering.present) {
|
|
484001
|
+
try {
|
|
484002
|
+
seedNumberingShard({
|
|
484003
|
+
doc: unit,
|
|
484004
|
+
shardId,
|
|
484005
|
+
ownerPartKey: part.partKey,
|
|
484006
|
+
ownerPartUri: part.partUri,
|
|
484007
|
+
abstractNums: Array.from(numbering.abstracts.values()).map((entry) => ({
|
|
484008
|
+
abstractNumId: entry.abstractNumId,
|
|
484009
|
+
multiLevelType: entry.multiLevelType,
|
|
484010
|
+
rawXml: entry.rawXml,
|
|
484011
|
+
levels: Array.from(entry.levels.values()).map((level) => ({
|
|
484012
|
+
ilvl: level.ilvl,
|
|
484013
|
+
numFmt: level.numFmt,
|
|
484014
|
+
lvlText: level.lvlText,
|
|
484015
|
+
start: level.start,
|
|
484016
|
+
opaqueXml: null
|
|
484017
|
+
}))
|
|
484018
|
+
})),
|
|
484019
|
+
nums: Array.from(numbering.instances.values()).map((entry) => ({
|
|
484020
|
+
numId: entry.numId,
|
|
484021
|
+
abstractNumId: entry.abstractNumId,
|
|
484022
|
+
rawXml: entry.rawXml,
|
|
484023
|
+
lvlOverrides: Array.from(entry.lvlOverrides.entries()).map(([ilvl, value2]) => ({
|
|
484024
|
+
ilvl,
|
|
484025
|
+
startOverride: value2.startOverride
|
|
484026
|
+
}))
|
|
483725
484027
|
}))
|
|
483726
|
-
})
|
|
483727
|
-
})
|
|
483728
|
-
|
|
483729
|
-
|
|
483730
|
-
|
|
484028
|
+
});
|
|
484029
|
+
} catch (error50) {
|
|
484030
|
+
if (!isAlreadySeededError(error50))
|
|
484031
|
+
throw error50;
|
|
484032
|
+
}
|
|
483731
484033
|
}
|
|
483732
|
-
|
|
483733
|
-
|
|
484034
|
+
return subtreePackageHandle(rootDoc, unit, SHARD_KIND.numbering, bootstrap);
|
|
484035
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483734
484036
|
}
|
|
483735
484037
|
async function connectSettingsShard(rootDoc, shardId, settingsPart, webSettingsPart) {
|
|
483736
|
-
|
|
483737
|
-
|
|
483738
|
-
|
|
483739
|
-
|
|
483740
|
-
|
|
483741
|
-
|
|
483742
|
-
|
|
483743
|
-
|
|
483744
|
-
|
|
483745
|
-
|
|
483746
|
-
|
|
483747
|
-
|
|
483748
|
-
|
|
483749
|
-
|
|
483750
|
-
|
|
483751
|
-
|
|
483752
|
-
|
|
483753
|
-
|
|
483754
|
-
|
|
483755
|
-
|
|
483756
|
-
|
|
484038
|
+
return rootDoc.transact(() => {
|
|
484039
|
+
const unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.settings });
|
|
484040
|
+
const settingsBootstrap = settingsPart?.bytes ? bootstrapPartProjection(TEXT_DECODER12.decode(settingsPart.bytes)) : null;
|
|
484041
|
+
const webSettingsBootstrap = webSettingsPart?.bytes ? bootstrapPartProjection(TEXT_DECODER12.decode(webSettingsPart.bytes)) : null;
|
|
484042
|
+
if (settingsPart?.bytes || webSettingsPart?.bytes) {
|
|
484043
|
+
try {
|
|
484044
|
+
seedSettingsShard({
|
|
484045
|
+
doc: unit,
|
|
484046
|
+
shardId,
|
|
484047
|
+
ownerPartKey: settingsPart?.partKey ?? encodeLogicalOwnerKey(SETTINGS_PART_URI7),
|
|
484048
|
+
ownerPartUri: settingsPart?.partUri ?? SETTINGS_PART_URI7,
|
|
484049
|
+
pairedPartKeys: [settingsPart?.partKey, webSettingsPart?.partKey].filter(Boolean),
|
|
484050
|
+
settings: {
|
|
484051
|
+
fields: {},
|
|
484052
|
+
webFields: {},
|
|
484053
|
+
opaqueXml: settingsPart?.bytes ? settingsInnerXmlWithNamespaceScope(TEXT_DECODER12.decode(settingsPart.bytes)) : null,
|
|
484054
|
+
webOpaqueXml: webSettingsPart?.bytes ? settingsInnerXmlWithNamespaceScope(TEXT_DECODER12.decode(webSettingsPart.bytes)) : null
|
|
484055
|
+
}
|
|
484056
|
+
});
|
|
484057
|
+
} catch (error50) {
|
|
484058
|
+
if (!isAlreadySeededError(error50))
|
|
484059
|
+
throw error50;
|
|
484060
|
+
}
|
|
483757
484061
|
}
|
|
483758
|
-
|
|
483759
|
-
|
|
483760
|
-
|
|
483761
|
-
|
|
483762
|
-
|
|
483763
|
-
|
|
483764
|
-
|
|
483765
|
-
});
|
|
484062
|
+
return subtreePackageHandle(rootDoc, unit, SHARD_KIND.settings, {
|
|
484063
|
+
sourceXml: settingsBootstrap?.sourceXml ?? null,
|
|
484064
|
+
rootOpenTagXml: settingsBootstrap?.rootOpenTagXml ?? null,
|
|
484065
|
+
rootCloseTagXml: settingsBootstrap?.rootCloseTagXml ?? null,
|
|
484066
|
+
containerOpenTagXml: webSettingsBootstrap?.rootOpenTagXml ?? null,
|
|
484067
|
+
containerCloseTagXml: webSettingsBootstrap?.rootCloseTagXml ?? null
|
|
484068
|
+
});
|
|
484069
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483766
484070
|
}
|
|
483767
484071
|
async function connectMediaManifestShard(rootDoc, shardId, parts, session, binaryMode) {
|
|
483768
|
-
|
|
483769
|
-
|
|
483770
|
-
|
|
483771
|
-
|
|
483772
|
-
|
|
483773
|
-
|
|
483774
|
-
|
|
483775
|
-
|
|
483776
|
-
|
|
483777
|
-
|
|
483778
|
-
|
|
483779
|
-
|
|
483780
|
-
|
|
483781
|
-
|
|
484072
|
+
return rootDoc.transact(() => {
|
|
484073
|
+
const unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.mediaManifest });
|
|
484074
|
+
const assets = buildMediaAssets(parts, session, binaryMode);
|
|
484075
|
+
if (assets.length > 0) {
|
|
484076
|
+
try {
|
|
484077
|
+
seedMediaManifestShard({
|
|
484078
|
+
doc: unit,
|
|
484079
|
+
shardId,
|
|
484080
|
+
ownerPartKey: encodeLogicalOwnerKey(MEDIA_OWNER_URI2),
|
|
484081
|
+
ownerPartUri: MEDIA_OWNER_URI2,
|
|
484082
|
+
assets
|
|
484083
|
+
});
|
|
484084
|
+
} catch (error50) {
|
|
484085
|
+
if (!isAlreadySeededError(error50))
|
|
484086
|
+
throw error50;
|
|
484087
|
+
}
|
|
483782
484088
|
}
|
|
483783
|
-
|
|
483784
|
-
|
|
484089
|
+
return subtreePackageHandle(rootDoc, unit, SHARD_KIND.mediaManifest);
|
|
484090
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483785
484091
|
}
|
|
483786
484092
|
async function connectBinaryShard(rootDoc, shardId, part, assetId, binaryMode, blobStore) {
|
|
483787
|
-
|
|
483788
|
-
|
|
483789
|
-
|
|
483790
|
-
|
|
483791
|
-
|
|
483792
|
-
|
|
483793
|
-
|
|
483794
|
-
|
|
483795
|
-
|
|
483796
|
-
|
|
483797
|
-
|
|
483798
|
-
|
|
483799
|
-
|
|
483800
|
-
|
|
483801
|
-
|
|
483802
|
-
|
|
483803
|
-
|
|
483804
|
-
|
|
483805
|
-
|
|
483806
|
-
|
|
483807
|
-
|
|
483808
|
-
|
|
483809
|
-
|
|
483810
|
-
|
|
484093
|
+
return rootDoc.transact(() => {
|
|
484094
|
+
const unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.binary });
|
|
484095
|
+
if (part.bytes) {
|
|
484096
|
+
try {
|
|
484097
|
+
const payload = prepareSingleDocBinaryPayload(part.bytes, binaryMode, blobStore);
|
|
484098
|
+
seedBinaryShard({
|
|
484099
|
+
doc: unit,
|
|
484100
|
+
shardId,
|
|
484101
|
+
ownerPartKey: part.partKey,
|
|
484102
|
+
ownerPartUri: part.partUri,
|
|
484103
|
+
assetId,
|
|
484104
|
+
mode: payload.mode,
|
|
484105
|
+
contentType: part.contentType ?? "",
|
|
484106
|
+
...payload.mode === BINARY_MODE.blob ? {
|
|
484107
|
+
blobRef: payload.blobRef,
|
|
484108
|
+
sha256: payload.sha256,
|
|
484109
|
+
byteLength: payload.byteLength
|
|
484110
|
+
} : {
|
|
484111
|
+
bytes: payload.bytes,
|
|
484112
|
+
sha256: payload.sha256
|
|
484113
|
+
}
|
|
484114
|
+
});
|
|
484115
|
+
} catch (error50) {
|
|
484116
|
+
if (!isAlreadySeededError(error50))
|
|
484117
|
+
throw error50;
|
|
484118
|
+
}
|
|
483811
484119
|
}
|
|
483812
|
-
|
|
483813
|
-
|
|
484120
|
+
return subtreePackageHandle(rootDoc, unit, SHARD_KIND.binary);
|
|
484121
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483814
484122
|
}
|
|
483815
484123
|
async function connectOpaqueShard(rootDoc, shardId, part, sourceZipSha256, binaryMode, blobStore) {
|
|
483816
|
-
|
|
483817
|
-
|
|
483818
|
-
|
|
483819
|
-
|
|
483820
|
-
|
|
483821
|
-
|
|
483822
|
-
|
|
483823
|
-
|
|
483824
|
-
|
|
483825
|
-
|
|
483826
|
-
|
|
483827
|
-
|
|
483828
|
-
|
|
483829
|
-
|
|
483830
|
-
|
|
483831
|
-
|
|
483832
|
-
|
|
483833
|
-
|
|
483834
|
-
|
|
483835
|
-
|
|
483836
|
-
|
|
483837
|
-
|
|
483838
|
-
|
|
483839
|
-
|
|
483840
|
-
|
|
483841
|
-
|
|
483842
|
-
|
|
483843
|
-
|
|
483844
|
-
|
|
483845
|
-
|
|
484124
|
+
return rootDoc.transact(() => {
|
|
484125
|
+
const unit = createCollabUnitHandle({ rootDoc, shardId, shardKind: SHARD_KIND.opaquePart });
|
|
484126
|
+
if (part.bytes) {
|
|
484127
|
+
try {
|
|
484128
|
+
const payload = prepareSingleDocBinaryPayload(part.bytes, binaryMode, blobStore);
|
|
484129
|
+
seedOpaquePartShard({
|
|
484130
|
+
doc: unit,
|
|
484131
|
+
shardId,
|
|
484132
|
+
ownerPartKey: part.partKey,
|
|
484133
|
+
ownerPartUri: part.partUri,
|
|
484134
|
+
partKey: part.partKey,
|
|
484135
|
+
partUri: part.partUri,
|
|
484136
|
+
contentType: part.contentType,
|
|
484137
|
+
mode: payload.mode,
|
|
484138
|
+
...payload.mode === BINARY_MODE.blob ? {
|
|
484139
|
+
blobRef: payload.blobRef,
|
|
484140
|
+
sha256: payload.sha256,
|
|
484141
|
+
byteLength: payload.byteLength
|
|
484142
|
+
} : {
|
|
484143
|
+
bytes: payload.bytes,
|
|
484144
|
+
sha256: payload.sha256
|
|
484145
|
+
},
|
|
484146
|
+
sourceProvenance: {
|
|
484147
|
+
sha256Zip: sourceZipSha256,
|
|
484148
|
+
committedAt: null,
|
|
484149
|
+
committerId: null
|
|
484150
|
+
}
|
|
484151
|
+
});
|
|
484152
|
+
} catch (error50) {
|
|
484153
|
+
if (!isAlreadySeededError(error50))
|
|
484154
|
+
throw error50;
|
|
484155
|
+
}
|
|
483846
484156
|
}
|
|
483847
|
-
|
|
483848
|
-
|
|
484157
|
+
return subtreePackageHandle(rootDoc, unit, SHARD_KIND.opaquePart);
|
|
484158
|
+
}, "collab-v2:bootstrap:seed-unit");
|
|
483849
484159
|
}
|
|
483850
484160
|
function storyProjectionHandle(handle) {
|
|
483851
484161
|
return {
|
|
@@ -485263,8 +485573,12 @@ function jsonSchemaPropertyToZod(prop, definitions = {}, resolvingReferences = n
|
|
|
485263
485573
|
return describe3(intersection3);
|
|
485264
485574
|
}
|
|
485265
485575
|
switch (type) {
|
|
485266
|
-
case "string":
|
|
485267
|
-
|
|
485576
|
+
case "string": {
|
|
485577
|
+
let schema = exports_external.string();
|
|
485578
|
+
if (typeof prop.minLength === "number")
|
|
485579
|
+
schema = schema.min(prop.minLength);
|
|
485580
|
+
return describe3(schema);
|
|
485581
|
+
}
|
|
485268
485582
|
case "number": {
|
|
485269
485583
|
let schema = exports_external.number();
|
|
485270
485584
|
if (typeof prop.exclusiveMinimum === "number")
|