@superdoc/mcp 1.2.1-next.1 → 1.2.1-next.2
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 +504 -98
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -31314,7 +31314,7 @@ var init_host = __esm(() => {
|
|
|
31314
31314
|
});
|
|
31315
31315
|
|
|
31316
31316
|
// ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
|
|
31317
|
-
var SDK_VERSION = "2.15.1-next.
|
|
31317
|
+
var SDK_VERSION = "2.15.1-next.2";
|
|
31318
31318
|
|
|
31319
31319
|
// ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
|
|
31320
31320
|
import { chmodSync, existsSync } from "node:fs";
|
|
@@ -140090,7 +140090,9 @@ function markFullParagraphInsertions(xml, fragments, structural, index, namespac
|
|
|
140090
140090
|
continue;
|
|
140091
140091
|
const structuralInParagraph = structuralByParagraph.get(`${paragraph.start}:${paragraph.end}`) ?? [];
|
|
140092
140092
|
const terminalDeletionOfPendingInsertion = marker.structuralKind === "paragraph-mark-insertion" && structuralInParagraph.length === 2 && structuralInParagraph[0] === marker && structuralInParagraph[1]?.structuralKind === "paragraph-mark-deletion";
|
|
140093
|
-
|
|
140093
|
+
const extraStructural = structuralInParagraph.filter((fragment2) => fragment2 !== marker);
|
|
140094
|
+
const extrasArePasteObjects = extraStructural.every((fragment2) => fragment2.structuralKind === "footnote-insertion" || fragment2.structuralKind === "endnote-insertion" || fragment2.structuralKind === "image-insertion" || fragment2.structuralKind === "field-insertion");
|
|
140095
|
+
if (structuralInParagraph.length !== 1 && !terminalDeletionOfPendingInsertion && !(extraStructural.length > 0 && extrasArePasteObjects))
|
|
140094
140096
|
continue;
|
|
140095
140097
|
const paragraphFragments = (fragmentsByParagraphStart.get(paragraph.start) ?? []).filter((candidate) => candidate.byteStart >= paragraph.openEnd && candidate.byteEnd <= paragraph.closeStart).sort((left, right) => left.byteStart - right.byteStart);
|
|
140096
140098
|
const markerIdentity = buildReviewIdentity({
|
|
@@ -168023,10 +168025,13 @@ function projectWordLikeReviewGroupsWithLookupContext(lookupContext, input) {
|
|
|
168023
168025
|
const partXml = input.partXmlByUri.get(partUri);
|
|
168024
168026
|
if (!partXml)
|
|
168025
168027
|
continue;
|
|
168026
|
-
if (isBodyStoryId(storyId)) {
|
|
168028
|
+
if (isBodyStoryId(storyId) || isNotesStoryId(storyId)) {
|
|
168027
168029
|
projectStoryReviewGroups(lookupContext, storyId, partUri, partXml, entries, input);
|
|
168028
168030
|
}
|
|
168029
168031
|
projectFullParagraphInsertions(lookupContext, storyId, partUri, partXml, entries, input);
|
|
168032
|
+
if (isBodyStoryId(storyId) || isNotesStoryId(storyId)) {
|
|
168033
|
+
foldSameRsidPastedParagraphParents(storyId, partXml, input);
|
|
168034
|
+
}
|
|
168030
168035
|
}
|
|
168031
168036
|
}
|
|
168032
168037
|
function projectFullParagraphInsertions(lookupContext, storyId, partUri, partXml, entries, input) {
|
|
@@ -168190,6 +168195,230 @@ function materializeFullParagraphInsertion(lookupContext, args) {
|
|
|
168190
168195
|
for (const fragment2 of objectFragments)
|
|
168191
168196
|
input.structuralKeyToLogicalId.set(fragment2.entityKey, id);
|
|
168192
168197
|
}
|
|
168198
|
+
function foldSameRsidPastedParagraphParents(storyId, partXml, input) {
|
|
168199
|
+
const storyEntries = input.byStory.get(storyId);
|
|
168200
|
+
if (!storyEntries)
|
|
168201
|
+
return;
|
|
168202
|
+
const parents = storyEntries.filter((entry) => isFoldablePastedParagraphParent(entry)).sort((left, right) => left.documentOrderStart - right.documentOrderStart);
|
|
168203
|
+
if (parents.length < 2)
|
|
168204
|
+
return;
|
|
168205
|
+
const clusters = [];
|
|
168206
|
+
let current = [];
|
|
168207
|
+
const flush = () => {
|
|
168208
|
+
if (current.length >= 2)
|
|
168209
|
+
clusters.push(current);
|
|
168210
|
+
current = [];
|
|
168211
|
+
};
|
|
168212
|
+
for (const parent of parents) {
|
|
168213
|
+
const previous = current.at(-1);
|
|
168214
|
+
if (!previous) {
|
|
168215
|
+
current = [parent];
|
|
168216
|
+
continue;
|
|
168217
|
+
}
|
|
168218
|
+
if (canFoldPastedParagraphParents(partXml, previous, parent, storyEntries)) {
|
|
168219
|
+
current.push(parent);
|
|
168220
|
+
continue;
|
|
168221
|
+
}
|
|
168222
|
+
flush();
|
|
168223
|
+
current = [parent];
|
|
168224
|
+
}
|
|
168225
|
+
flush();
|
|
168226
|
+
for (const cluster of clusters) {
|
|
168227
|
+
mergePastedParagraphParents(storyId, partXml, cluster, input);
|
|
168228
|
+
}
|
|
168229
|
+
}
|
|
168230
|
+
function isFoldablePastedParagraphParent(entry) {
|
|
168231
|
+
const kind = entry.reviewGroup?.kind;
|
|
168232
|
+
return entry.reviewGroup?.role === "parent" && (kind === "word-full-paragraph-insertion" || kind === "word-inserted-paragraph-range") && entry.subtype !== "table-split" && entry.subtype !== "image-insertion" && entry.subtype !== "list-item-insertion" && entry.subtype !== "field-insertion" && !entry.reviewGroup?.members.some((member) => member.subtype === "field-insertion") && pastedParagraphParentRsid(entry) != null;
|
|
168233
|
+
}
|
|
168234
|
+
function pastedParagraphParentRsid(entry) {
|
|
168235
|
+
const mark = entry.structuralFragments.find((fragment2) => fragment2.structuralKind === "paragraph-mark-insertion" || fragment2.structuralKind === "paragraph-insertion");
|
|
168236
|
+
const rsid = mark?.enclosingParagraphRsid ?? entry.sourceIds.rsids[0];
|
|
168237
|
+
return rsid ? rsid.toUpperCase() : null;
|
|
168238
|
+
}
|
|
168239
|
+
function pastedParagraphParentBounds(entry) {
|
|
168240
|
+
const marks = entry.structuralFragments.filter((fragment2) => fragment2.structuralKind === "paragraph-mark-insertion" || fragment2.structuralKind === "paragraph-insertion");
|
|
168241
|
+
const starts = marks.map((fragment2) => fragment2.enclosingElementStart).filter((value) => value != null);
|
|
168242
|
+
const ends = marks.map((fragment2) => fragment2.enclosingElementEnd).filter((value) => value != null);
|
|
168243
|
+
if (starts.length === 0 || ends.length === 0)
|
|
168244
|
+
return null;
|
|
168245
|
+
return { start: Math.min(...starts), end: Math.max(...ends) };
|
|
168246
|
+
}
|
|
168247
|
+
function canFoldPastedParagraphParents(partXml, previous, next, storyEntries) {
|
|
168248
|
+
if (pastedParagraphParentRsid(previous) !== pastedParagraphParentRsid(next))
|
|
168249
|
+
return false;
|
|
168250
|
+
if (previous.subtype !== next.subtype)
|
|
168251
|
+
return false;
|
|
168252
|
+
if (!isSameReviewGroupIdentity(buildReviewIdentity({
|
|
168253
|
+
name: previous.author.name,
|
|
168254
|
+
email: previous.authorEmail,
|
|
168255
|
+
initials: previous.author.initials
|
|
168256
|
+
}), buildReviewIdentity({
|
|
168257
|
+
name: next.author.name,
|
|
168258
|
+
email: next.authorEmail,
|
|
168259
|
+
initials: next.author.initials
|
|
168260
|
+
}))) {
|
|
168261
|
+
return false;
|
|
168262
|
+
}
|
|
168263
|
+
const previousBounds = pastedParagraphParentBounds(previous);
|
|
168264
|
+
const nextBounds = pastedParagraphParentBounds(next);
|
|
168265
|
+
if (!previousBounds || !nextBounds || nextBounds.start < previousBounds.end)
|
|
168266
|
+
return false;
|
|
168267
|
+
const stripped = partXml.slice(previousBounds.end, nextBounds.start).replace(/<\/?[\w.-]+:(?:footnote|endnote)\b[^>]*>/g, "");
|
|
168268
|
+
if (!isCleanGapXml(stripped))
|
|
168269
|
+
return false;
|
|
168270
|
+
return !hasInterveningVisibleReviewable(previous, next, storyEntries);
|
|
168271
|
+
}
|
|
168272
|
+
function hasInterveningVisibleReviewable(previous, next, storyEntries) {
|
|
168273
|
+
const spanStart = Math.min(previous.documentOrderStart, next.documentOrderStart);
|
|
168274
|
+
const spanEnd = Math.max(previous.documentOrderEnd, next.documentOrderEnd);
|
|
168275
|
+
const ownedIds = new Set([
|
|
168276
|
+
previous.id,
|
|
168277
|
+
next.id,
|
|
168278
|
+
...previous.reviewGroup?.ownedChildIds ?? [],
|
|
168279
|
+
...next.reviewGroup?.ownedChildIds ?? []
|
|
168280
|
+
]);
|
|
168281
|
+
for (const entry of storyEntries) {
|
|
168282
|
+
if (ownedIds.has(entry.id))
|
|
168283
|
+
continue;
|
|
168284
|
+
if (entry.reviewGroup?.role === "child")
|
|
168285
|
+
continue;
|
|
168286
|
+
if (entry.subsumption?.role === "child")
|
|
168287
|
+
continue;
|
|
168288
|
+
if (entry.documentOrderStart > spanStart && entry.documentOrderStart < spanEnd) {
|
|
168289
|
+
return true;
|
|
168290
|
+
}
|
|
168291
|
+
}
|
|
168292
|
+
return false;
|
|
168293
|
+
}
|
|
168294
|
+
function mergePastedParagraphParents(storyId, partXml, cluster, input) {
|
|
168295
|
+
const head = cluster[0];
|
|
168296
|
+
const memberEntries = [];
|
|
168297
|
+
const seenMemberIds = new Set;
|
|
168298
|
+
const addMember = (entry) => {
|
|
168299
|
+
if (!entry || seenMemberIds.has(entry.id))
|
|
168300
|
+
return;
|
|
168301
|
+
seenMemberIds.add(entry.id);
|
|
168302
|
+
memberEntries.push(entry);
|
|
168303
|
+
};
|
|
168304
|
+
for (const parent2 of cluster) {
|
|
168305
|
+
for (const childId of parent2.reviewGroup?.ownedChildIds ?? []) {
|
|
168306
|
+
addMember(input.byId.get(childId));
|
|
168307
|
+
}
|
|
168308
|
+
}
|
|
168309
|
+
if (memberEntries.length === 0 || memberEntries.some((entry) => entry.reviewGroup?.role === "child" && cluster.every((parent2) => parent2.id !== entry.reviewGroup?.parentId))) {
|
|
168310
|
+
return;
|
|
168311
|
+
}
|
|
168312
|
+
const textFragments = uniqueFragments(cluster.flatMap((parent2) => parent2.fragments));
|
|
168313
|
+
const structuralFragments = uniqueStructuralFragments(cluster.flatMap((parent2) => parent2.structuralFragments)).sort((left, right) => left.byteStart - right.byteStart);
|
|
168314
|
+
const members = cluster.flatMap((parent2) => parent2.reviewGroup?.members ?? []);
|
|
168315
|
+
const rsids = uniqueNonEmptyStrings(cluster.flatMap((parent2) => parent2.sourceIds.rsids));
|
|
168316
|
+
const memberWordIds = uniqueNonEmptyStrings([
|
|
168317
|
+
...cluster.flatMap((parent2) => [
|
|
168318
|
+
parent2.sourceIds.wordIdInsert ?? "",
|
|
168319
|
+
...parent2.sourceIds.wordIdOther
|
|
168320
|
+
]),
|
|
168321
|
+
...members.map((member) => member.wordId ?? "")
|
|
168322
|
+
]);
|
|
168323
|
+
const wordIdInsert = head.sourceIds.wordIdInsert ?? memberWordIds[0];
|
|
168324
|
+
const wordIdOther = memberWordIds.filter((id) => id !== wordIdInsert);
|
|
168325
|
+
const canonicalText = cluster.map((parent2) => {
|
|
168326
|
+
const text = parent2.after.text ?? "";
|
|
168327
|
+
return text.endsWith(`
|
|
168328
|
+
`) ? text : `${text}
|
|
168329
|
+
`;
|
|
168330
|
+
}).join("");
|
|
168331
|
+
const markParagraphIds = cluster.map((parent2) => {
|
|
168332
|
+
const start = parent2.structuralFragments.find((fragment2) => fragment2.structuralKind === "paragraph-mark-insertion")?.enclosingElementStart;
|
|
168333
|
+
return start != null ? readParagraphIdAt(partXml, start) : null;
|
|
168334
|
+
});
|
|
168335
|
+
const markKey = markParagraphIds.every((paraId) => paraId != null) ? markParagraphIds.map((paraId) => `p:${paraId}`).join(",") : cluster.map((parent2) => parent2.id).join(",");
|
|
168336
|
+
const identityKey = buildGroupIdentityKey(buildReviewIdentity({
|
|
168337
|
+
name: head.author.name,
|
|
168338
|
+
email: head.authorEmail,
|
|
168339
|
+
initials: head.author.initials
|
|
168340
|
+
}));
|
|
168341
|
+
const groupHash = hashGroupKey(["word-inserted-paragraph-range", storyId, identityKey, `pm:${markKey}`, `tx:${textFragments.length}`].join("|"));
|
|
168342
|
+
const groupId = buildLogicalId(storyId, "ins", "word-paragraph-range", groupHash);
|
|
168343
|
+
const noteIds = uniqueNonEmptyStrings(cluster.flatMap((entry) => ownedNoteIds(entry)));
|
|
168344
|
+
const parent = {
|
|
168345
|
+
...head,
|
|
168346
|
+
id: groupId,
|
|
168347
|
+
type: "insertion",
|
|
168348
|
+
subtype: "text-insertion",
|
|
168349
|
+
documentOrderStart: Math.min(...cluster.map((entry) => entry.documentOrderStart)),
|
|
168350
|
+
documentOrderEnd: Math.max(...cluster.map((entry) => entry.documentOrderEnd)),
|
|
168351
|
+
noteId: noteIds[0] ?? cluster.find((entry) => entry.noteId != null)?.noteId ?? head.noteId,
|
|
168352
|
+
noteIds: noteIds.length > 0 ? noteIds : null,
|
|
168353
|
+
sourceIds: { wordIdInsert, wordIdOther, rsids },
|
|
168354
|
+
revisionGroupId: groupId,
|
|
168355
|
+
after: { text: canonicalText },
|
|
168356
|
+
contributingRsids: rsids,
|
|
168357
|
+
fragments: textFragments,
|
|
168358
|
+
structuralFragments,
|
|
168359
|
+
structuralDelta: null,
|
|
168360
|
+
excerpt: canonicalText,
|
|
168361
|
+
reviewGroup: {
|
|
168362
|
+
kind: "word-inserted-paragraph-range",
|
|
168363
|
+
role: "parent",
|
|
168364
|
+
parentId: null,
|
|
168365
|
+
ownedChildIds: memberEntries.map((entry) => entry.id),
|
|
168366
|
+
duplicateDisplayPolicy: "subsumed",
|
|
168367
|
+
members
|
|
168368
|
+
}
|
|
168369
|
+
};
|
|
168370
|
+
for (const entry of memberEntries) {
|
|
168371
|
+
const mutable = entry;
|
|
168372
|
+
mutable.reviewGroup = {
|
|
168373
|
+
kind: "word-inserted-paragraph-range",
|
|
168374
|
+
role: "child",
|
|
168375
|
+
parentId: groupId,
|
|
168376
|
+
ownedChildIds: [],
|
|
168377
|
+
duplicateDisplayPolicy: "subsumed",
|
|
168378
|
+
members: []
|
|
168379
|
+
};
|
|
168380
|
+
mutable.revisionGroupId = groupId;
|
|
168381
|
+
}
|
|
168382
|
+
const storyArr = input.byStory.get(storyId);
|
|
168383
|
+
if (!storyArr)
|
|
168384
|
+
return;
|
|
168385
|
+
for (const dissolved of cluster) {
|
|
168386
|
+
input.byId.delete(dissolved.id);
|
|
168387
|
+
const index = storyArr.indexOf(dissolved);
|
|
168388
|
+
if (index >= 0)
|
|
168389
|
+
storyArr.splice(index, 1);
|
|
168390
|
+
}
|
|
168391
|
+
input.byId.set(groupId, parent);
|
|
168392
|
+
storyArr.push(parent);
|
|
168393
|
+
for (const fragment2 of textFragments)
|
|
168394
|
+
input.rsidToLogicalId.set(fragment2.rsid, groupId);
|
|
168395
|
+
for (const fragment2 of structuralFragments)
|
|
168396
|
+
input.structuralKeyToLogicalId.set(fragment2.entityKey, groupId);
|
|
168397
|
+
}
|
|
168398
|
+
function uniqueFragments(fragments) {
|
|
168399
|
+
const seen = new Set;
|
|
168400
|
+
const out = [];
|
|
168401
|
+
for (const fragment2 of fragments) {
|
|
168402
|
+
const key2 = `${fragment2.byteStart}:${fragment2.byteEnd}:${fragment2.rsid}`;
|
|
168403
|
+
if (seen.has(key2))
|
|
168404
|
+
continue;
|
|
168405
|
+
seen.add(key2);
|
|
168406
|
+
out.push(fragment2);
|
|
168407
|
+
}
|
|
168408
|
+
return out;
|
|
168409
|
+
}
|
|
168410
|
+
function uniqueStructuralFragments(fragments) {
|
|
168411
|
+
const seen = new Set;
|
|
168412
|
+
const out = [];
|
|
168413
|
+
for (const fragment2 of fragments) {
|
|
168414
|
+
const key2 = fragment2.entityKey;
|
|
168415
|
+
if (seen.has(key2))
|
|
168416
|
+
continue;
|
|
168417
|
+
seen.add(key2);
|
|
168418
|
+
out.push(fragment2);
|
|
168419
|
+
}
|
|
168420
|
+
return out;
|
|
168421
|
+
}
|
|
168193
168422
|
function classifyFullParagraphInsertion(lookupContext, partXml, paragraphStart, paragraphEnd, paragraphXml) {
|
|
168194
168423
|
const parent = findImmediateParentElementAtPosition(partXml, paragraphStart, lookupContext);
|
|
168195
168424
|
if (parent) {
|
|
@@ -168385,14 +168614,19 @@ function buildTrackedFieldLocationKey(lookupContext, partXml, fragment2) {
|
|
|
168385
168614
|
function extractDeletionText(deletion, partXml) {
|
|
168386
168615
|
return deletion.fragments.map((fragment2) => extractVisibleTextFromXml(partXml.slice(fragment2.byteStart, fragment2.byteEnd), "del")).join("");
|
|
168387
168616
|
}
|
|
168617
|
+
function isAbsorbableInlineObjectInsertion(entry, fragment2) {
|
|
168618
|
+
const kind = entry.subtype;
|
|
168619
|
+
return (kind === "footnote-insertion" || kind === "endnote-insertion" || kind === "image-insertion" || kind === "field-insertion") && fragment2.structuralKind === kind && entry.reviewGroup == null && entry.subsumption == null;
|
|
168620
|
+
}
|
|
168388
168621
|
function projectStoryReviewGroups(lookupContext, storyId, partUri, partXml, entries, input) {
|
|
168389
168622
|
const markCandidates = collectMarkCandidates(storyId, partXml, entries);
|
|
168390
168623
|
if (markCandidates.candidatesByParagraphStart.size === 0)
|
|
168391
168624
|
return;
|
|
168392
|
-
const textCandidates = collectTextCandidates(lookupContext, partXml, entries);
|
|
168625
|
+
const textCandidates = collectTextCandidates(lookupContext, partXml, entries, storyId);
|
|
168393
168626
|
if (textCandidates.length === 0)
|
|
168394
168627
|
return;
|
|
168395
|
-
const
|
|
168628
|
+
const objectCandidates = collectObjectCandidates(lookupContext, partXml, entries);
|
|
168629
|
+
const paragraphs = buildParagraphInfos(lookupContext, partXml, markCandidates, textCandidates, objectCandidates);
|
|
168396
168630
|
if (paragraphs.length === 0)
|
|
168397
168631
|
return;
|
|
168398
168632
|
const atoms = buildAtomSequence(partXml, paragraphs);
|
|
@@ -168403,17 +168637,33 @@ function projectStoryReviewGroups(lookupContext, storyId, partUri, partXml, entr
|
|
|
168403
168637
|
}
|
|
168404
168638
|
}
|
|
168405
168639
|
}
|
|
168406
|
-
function
|
|
168407
|
-
|
|
168408
|
-
|
|
168640
|
+
function paragraphRunHasImageInsertion(paragraphRun) {
|
|
168641
|
+
return paragraphRun.some((atom) => atom.kind === "object" && atom.candidate.entry.subtype === "image-insertion");
|
|
168642
|
+
}
|
|
168643
|
+
function paragraphRunFullParagraphRsid(paragraphRun) {
|
|
168644
|
+
for (const atom of paragraphRun) {
|
|
168409
168645
|
if (atom.kind !== "mark" || atom.candidate.fragment.fullParagraphInsertion !== true)
|
|
168410
|
-
|
|
168646
|
+
continue;
|
|
168411
168647
|
const rsid = atom.candidate.fragment.enclosingParagraphRsid;
|
|
168412
|
-
return rsid ?
|
|
168413
|
-
}
|
|
168414
|
-
|
|
168415
|
-
|
|
168648
|
+
return rsid ? rsid.toUpperCase() : null;
|
|
168649
|
+
}
|
|
168650
|
+
return null;
|
|
168651
|
+
}
|
|
168652
|
+
function paragraphRunIsFullParagraphInsertion(paragraphRun) {
|
|
168653
|
+
return paragraphRun.some((atom) => atom.kind === "mark" && atom.candidate.fragment.fullParagraphInsertion === true);
|
|
168654
|
+
}
|
|
168655
|
+
function canContinueFullParagraphRun(currentRun, nextParagraphRun, currentRsid, nextRsid, anyStampedFullParagraph) {
|
|
168656
|
+
if (paragraphRunHasImageInsertion(currentRun) !== paragraphRunHasImageInsertion(nextParagraphRun)) {
|
|
168657
|
+
return false;
|
|
168416
168658
|
}
|
|
168659
|
+
if (!anyStampedFullParagraph)
|
|
168660
|
+
return true;
|
|
168661
|
+
if (currentRsid == null || nextRsid == null)
|
|
168662
|
+
return false;
|
|
168663
|
+
return currentRsid === nextRsid;
|
|
168664
|
+
}
|
|
168665
|
+
function splitDistinctFullParagraphRuns(run) {
|
|
168666
|
+
const members = run.filter((atom) => atom.kind !== "blocker");
|
|
168417
168667
|
const paragraphRuns = [];
|
|
168418
168668
|
for (const member of members) {
|
|
168419
168669
|
const current = paragraphRuns.at(-1);
|
|
@@ -168423,6 +168673,11 @@ function splitDistinctFullParagraphRuns(run) {
|
|
|
168423
168673
|
paragraphRuns.push([member]);
|
|
168424
168674
|
}
|
|
168425
168675
|
}
|
|
168676
|
+
const fullParagraphRuns = paragraphRuns.filter(paragraphRunIsFullParagraphInsertion);
|
|
168677
|
+
if (fullParagraphRuns.length <= 1) {
|
|
168678
|
+
return [run];
|
|
168679
|
+
}
|
|
168680
|
+
const anyStampedFullParagraph = fullParagraphRuns.some((paragraphRun) => paragraphRunFullParagraphRsid(paragraphRun) != null);
|
|
168426
168681
|
const projectedRuns = [];
|
|
168427
168682
|
let currentRun = [];
|
|
168428
168683
|
let currentRsid = null;
|
|
@@ -168434,9 +168689,7 @@ function splitDistinctFullParagraphRuns(run) {
|
|
|
168434
168689
|
currentRsid = null;
|
|
168435
168690
|
};
|
|
168436
168691
|
for (const paragraphRun of paragraphRuns) {
|
|
168437
|
-
|
|
168438
|
-
const paragraphRsid = fullParagraphRsidsByStart.get(paragraphStart) ?? null;
|
|
168439
|
-
if (paragraphRsid === null) {
|
|
168692
|
+
if (!paragraphRunIsFullParagraphInsertion(paragraphRun)) {
|
|
168440
168693
|
if (currentRsid !== null && paragraphRun.every((atom) => atom.kind === "text")) {
|
|
168441
168694
|
currentRun.push(...paragraphRun);
|
|
168442
168695
|
continue;
|
|
@@ -168445,14 +168698,19 @@ function splitDistinctFullParagraphRuns(run) {
|
|
|
168445
168698
|
currentRun = [...paragraphRun];
|
|
168446
168699
|
continue;
|
|
168447
168700
|
}
|
|
168448
|
-
|
|
168701
|
+
const paragraphRsid = paragraphRunFullParagraphRsid(paragraphRun);
|
|
168702
|
+
if (currentRun.length > 0 && canContinueFullParagraphRun(currentRun, paragraphRun, currentRsid, paragraphRsid, anyStampedFullParagraph)) {
|
|
168449
168703
|
currentRun.push(...paragraphRun);
|
|
168704
|
+
if (currentRsid == null)
|
|
168705
|
+
currentRsid = paragraphRsid;
|
|
168450
168706
|
continue;
|
|
168451
168707
|
}
|
|
168452
|
-
if (currentRsid === null && currentRun.every((atom) => atom.kind === "mark")) {
|
|
168453
|
-
|
|
168454
|
-
|
|
168455
|
-
|
|
168708
|
+
if (currentRsid === null && currentRun.length > 0 && currentRun.every((atom) => atom.kind === "mark")) {
|
|
168709
|
+
if (canContinueFullParagraphRun(currentRun, paragraphRun, paragraphRsid, paragraphRsid, anyStampedFullParagraph)) {
|
|
168710
|
+
currentRsid = paragraphRsid;
|
|
168711
|
+
currentRun = [...currentRun, ...paragraphRun];
|
|
168712
|
+
continue;
|
|
168713
|
+
}
|
|
168456
168714
|
}
|
|
168457
168715
|
flushCurrentRun();
|
|
168458
168716
|
currentRsid = paragraphRsid;
|
|
@@ -168473,10 +168731,10 @@ function collectMarkCandidates(storyId, partXml, entries) {
|
|
|
168473
168731
|
continue;
|
|
168474
168732
|
if (fragment2.enclosingElementStart === undefined || fragment2.enclosingElementEnd === undefined)
|
|
168475
168733
|
continue;
|
|
168476
|
-
const isCandidateShape = entry.subtype === "paragraph-mark-insertion" && fragment2.structuralKind === "paragraph-mark-insertion" && entry.structuralFragments.length === 1 && entry.noteId == null && entry.subsumption == null && entry.reviewGroup == null;
|
|
168734
|
+
const isCandidateShape = entry.subtype === "paragraph-mark-insertion" && fragment2.structuralKind === "paragraph-mark-insertion" && entry.structuralFragments.length === 1 && (entry.noteId == null || isNotesStoryId(storyId)) && entry.subsumption == null && entry.reviewGroup == null;
|
|
168477
168735
|
if (isCandidateShape) {
|
|
168478
168736
|
markFragments.push({ entry, fragment: fragment2 });
|
|
168479
|
-
} else if (isTerminalDeletionOfPendingFullParagraphInsertion(fragment2, entries)) {} else {
|
|
168737
|
+
} else if (isTerminalDeletionOfPendingFullParagraphInsertion(fragment2, entries)) {} else if (isAbsorbableInlineObjectInsertion(entry, fragment2)) {} else {
|
|
168480
168738
|
blockedParagraphStarts.add(fragment2.enclosingElementStart);
|
|
168481
168739
|
}
|
|
168482
168740
|
}
|
|
@@ -168517,12 +168775,12 @@ function isTerminalDeletionOfPendingFullParagraphInsertion(fragment2, entries) {
|
|
|
168517
168775
|
const markers = entries.flatMap((entry) => entry.structuralFragments).filter((candidate2) => candidate2.enclosingElementStart === paragraphStart && candidate2.enclosingElementEnd === paragraphEnd && (candidate2.structuralKind === "paragraph-mark-insertion" || candidate2.structuralKind === "paragraph-mark-deletion")).sort((left, right) => left.byteStart - right.byteStart);
|
|
168518
168776
|
return markers.length === 2 && markers[0]?.structuralKind === "paragraph-mark-insertion" && markers[0].fullParagraphInsertion === true && markers[1] === fragment2;
|
|
168519
168777
|
}
|
|
168520
|
-
function collectTextCandidates(lookupContext, partXml, entries) {
|
|
168778
|
+
function collectTextCandidates(lookupContext, partXml, entries, storyId) {
|
|
168521
168779
|
const out = [];
|
|
168522
168780
|
for (const entry of entries) {
|
|
168523
168781
|
if (entry.type !== "insertion" || entry.subtype !== "text-insertion")
|
|
168524
168782
|
continue;
|
|
168525
|
-
if (entry.noteId != null)
|
|
168783
|
+
if (entry.noteId != null && !isNotesStoryId(storyId))
|
|
168526
168784
|
continue;
|
|
168527
168785
|
if (entry.sides || entry.movePair)
|
|
168528
168786
|
continue;
|
|
@@ -168567,14 +168825,60 @@ function collectTextCandidates(lookupContext, partXml, entries) {
|
|
|
168567
168825
|
}
|
|
168568
168826
|
return out;
|
|
168569
168827
|
}
|
|
168828
|
+
function collectObjectCandidates(lookupContext, partXml, entries) {
|
|
168829
|
+
const out = [];
|
|
168830
|
+
for (const entry of entries) {
|
|
168831
|
+
if (entry.type !== "structural")
|
|
168832
|
+
continue;
|
|
168833
|
+
if (entry.sides || entry.movePair)
|
|
168834
|
+
continue;
|
|
168835
|
+
if (entry.subsumption || entry.reviewGroup)
|
|
168836
|
+
continue;
|
|
168837
|
+
if (entry.structuralFragments.length === 0)
|
|
168838
|
+
continue;
|
|
168839
|
+
if (!entry.structuralFragments.every((fragment2) => isAbsorbableInlineObjectInsertion(entry, fragment2))) {
|
|
168840
|
+
continue;
|
|
168841
|
+
}
|
|
168842
|
+
let paragraphStart = null;
|
|
168843
|
+
let eligible = true;
|
|
168844
|
+
for (const fragment2 of entry.structuralFragments) {
|
|
168845
|
+
const paragraph = findEnclosingElementAtPosition(partXml, fragment2.byteStart, "p", undefined, lookupContext);
|
|
168846
|
+
if (!paragraph) {
|
|
168847
|
+
eligible = false;
|
|
168848
|
+
break;
|
|
168849
|
+
}
|
|
168850
|
+
if (paragraphStart == null)
|
|
168851
|
+
paragraphStart = paragraph.start;
|
|
168852
|
+
if (paragraph.start !== paragraphStart) {
|
|
168853
|
+
eligible = false;
|
|
168854
|
+
break;
|
|
168855
|
+
}
|
|
168856
|
+
}
|
|
168857
|
+
if (!eligible || paragraphStart == null)
|
|
168858
|
+
continue;
|
|
168859
|
+
const headFragment = entry.structuralFragments[0];
|
|
168860
|
+
out.push({
|
|
168861
|
+
entry,
|
|
168862
|
+
fragments: [...entry.structuralFragments].sort((a, b) => a.byteStart - b.byteStart),
|
|
168863
|
+
paragraphStart,
|
|
168864
|
+
identity: buildReviewIdentity({
|
|
168865
|
+
name: entry.author.name,
|
|
168866
|
+
email: entry.authorEmail ?? headFragment.authorEmail,
|
|
168867
|
+
initials: entry.author.initials
|
|
168868
|
+
}),
|
|
168869
|
+
initials: entry.author.initials
|
|
168870
|
+
});
|
|
168871
|
+
}
|
|
168872
|
+
return out;
|
|
168873
|
+
}
|
|
168570
168874
|
function isSimpleInlineInsertionWrapper(wrapperXml) {
|
|
168571
168875
|
const innerMatch = /^<[\w.-]+:ins\b[^>]*>([\s\S]*)<\/[\w.-]+:ins>\s*$/.exec(wrapperXml);
|
|
168572
168876
|
if (!innerMatch)
|
|
168573
168877
|
return false;
|
|
168574
168878
|
const inner = innerMatch[1] ?? "";
|
|
168575
|
-
return !/<[\w.-]+:(?:ins|del|moveFrom|moveTo
|
|
168879
|
+
return !/<[\w.-]+:(?:ins|del|moveFrom|moveTo)\b/.test(inner);
|
|
168576
168880
|
}
|
|
168577
|
-
function buildParagraphInfos(lookupContext, partXml, marks, textCandidates) {
|
|
168881
|
+
function buildParagraphInfos(lookupContext, partXml, marks, textCandidates, objectCandidates = []) {
|
|
168578
168882
|
const byStart = new Map;
|
|
168579
168883
|
const ensure = (start, end) => {
|
|
168580
168884
|
let info = byStart.get(start);
|
|
@@ -168585,6 +168889,7 @@ function buildParagraphInfos(lookupContext, partXml, marks, textCandidates) {
|
|
|
168585
168889
|
mark: null,
|
|
168586
168890
|
markBlocked: marks.blockedParagraphStarts.has(start),
|
|
168587
168891
|
textFragments: [],
|
|
168892
|
+
objectFragments: [],
|
|
168588
168893
|
invalid: false
|
|
168589
168894
|
};
|
|
168590
168895
|
byStart.set(start, info);
|
|
@@ -168604,17 +168909,28 @@ function buildParagraphInfos(lookupContext, partXml, marks, textCandidates) {
|
|
|
168604
168909
|
info.textFragments.push({ candidate: candidate2, fragment: fragment2 });
|
|
168605
168910
|
}
|
|
168606
168911
|
}
|
|
168912
|
+
for (const candidate2 of objectCandidates) {
|
|
168913
|
+
const paragraph = findEnclosingElementAtPosition(partXml, candidate2.fragments[0].byteStart, "p", undefined, lookupContext);
|
|
168914
|
+
if (!paragraph)
|
|
168915
|
+
continue;
|
|
168916
|
+
const info = ensure(paragraph.start, paragraph.end);
|
|
168917
|
+
for (const fragment2 of candidate2.fragments) {
|
|
168918
|
+
info.objectFragments.push({ candidate: candidate2, fragment: fragment2 });
|
|
168919
|
+
}
|
|
168920
|
+
}
|
|
168607
168921
|
const paragraphs = Array.from(byStart.values()).sort((a, b) => a.start - b.start);
|
|
168608
168922
|
for (const paragraph of paragraphs) {
|
|
168609
168923
|
paragraph.textFragments.sort((a, b) => a.fragment.byteStart - b.fragment.byteStart);
|
|
168924
|
+
paragraph.objectFragments.sort((a, b) => a.fragment.byteStart - b.fragment.byteStart);
|
|
168610
168925
|
paragraph.invalid = !isEligibleGroupParagraph(lookupContext, partXml, paragraph);
|
|
168611
168926
|
}
|
|
168612
168927
|
return paragraphs;
|
|
168613
168928
|
}
|
|
168614
168929
|
function isEligibleGroupParagraph(lookupContext, partXml, paragraph) {
|
|
168615
168930
|
const parent = findImmediateParentElementAtPosition(partXml, paragraph.start, lookupContext);
|
|
168616
|
-
if (!parent || parent.localName !== "body")
|
|
168931
|
+
if (!parent || parent.localName !== "body" && parent.localName !== "footnote" && parent.localName !== "endnote") {
|
|
168617
168932
|
return false;
|
|
168933
|
+
}
|
|
168618
168934
|
const paragraphXml = partXml.slice(paragraph.start, paragraph.end);
|
|
168619
168935
|
const pPrXml = readLeadingParagraphPropertyBlock(paragraphXml)?.xml ?? "";
|
|
168620
168936
|
if (pPrXml && /<[\w.-]+:sectPr\b/.test(pPrXml))
|
|
@@ -168659,7 +168975,7 @@ function buildAtomSequence(partXml, paragraphs) {
|
|
|
168659
168975
|
for (const paragraph of paragraphs) {
|
|
168660
168976
|
if (previous) {
|
|
168661
168977
|
const between = partXml.slice(previous.end, paragraph.start);
|
|
168662
|
-
if (!
|
|
168978
|
+
if (!isCleanGroupingGap(between, previous, paragraph))
|
|
168663
168979
|
atoms.push({ kind: "blocker" });
|
|
168664
168980
|
}
|
|
168665
168981
|
previous = paragraph;
|
|
@@ -168729,17 +169045,21 @@ function appendParagraphAtoms(partXml, paragraph, atoms, hyperlinkTags) {
|
|
|
168729
169045
|
return isCleanGapXml(gap + partXml.slice(cursor2, end));
|
|
168730
169046
|
};
|
|
168731
169047
|
let cursor = contentStart;
|
|
168732
|
-
|
|
168733
|
-
|
|
169048
|
+
const contentAtoms = [
|
|
169049
|
+
...paragraph.textFragments.map(({ candidate: candidate2, fragment: fragment2 }) => ({ kind: "text", candidate: candidate2, fragment: fragment2 })),
|
|
169050
|
+
...paragraph.objectFragments.map(({ candidate: candidate2, fragment: fragment2 }) => ({ kind: "object", candidate: candidate2, fragment: fragment2 }))
|
|
169051
|
+
].sort((left, right) => left.fragment.byteStart - right.fragment.byteStart);
|
|
169052
|
+
for (const atom of contentAtoms) {
|
|
169053
|
+
if (atom.fragment.byteStart < cursor || atom.fragment.byteEnd > contentEnd) {
|
|
168734
169054
|
atoms.push({ kind: "blocker" });
|
|
168735
|
-
cursor = Math.max(cursor,
|
|
169055
|
+
cursor = Math.max(cursor, atom.fragment.byteEnd);
|
|
168736
169056
|
continue;
|
|
168737
169057
|
}
|
|
168738
|
-
if (!cleanGap(cursor,
|
|
169058
|
+
if (!cleanGap(cursor, atom.fragment.byteStart)) {
|
|
168739
169059
|
atoms.push({ kind: "blocker" });
|
|
168740
169060
|
}
|
|
168741
|
-
atoms.push(
|
|
168742
|
-
cursor =
|
|
169061
|
+
atoms.push(atom);
|
|
169062
|
+
cursor = atom.fragment.byteEnd;
|
|
168743
169063
|
}
|
|
168744
169064
|
if (!cleanGap(cursor, contentEnd)) {
|
|
168745
169065
|
atoms.push({ kind: "blocker" });
|
|
@@ -168757,6 +169077,16 @@ function isCleanGapXml(xml) {
|
|
|
168757
169077
|
return false;
|
|
168758
169078
|
return containsOnlyAllowedPairingMarkers(xml);
|
|
168759
169079
|
}
|
|
169080
|
+
function isCleanGroupingGap(between, previous, next) {
|
|
169081
|
+
const stripped = between.replace(/<\/?[\w.-]+:(?:footnote|endnote)\b[^>]*>/g, "");
|
|
169082
|
+
if (!isCleanGapXml(stripped))
|
|
169083
|
+
return false;
|
|
169084
|
+
if (stripped === between)
|
|
169085
|
+
return true;
|
|
169086
|
+
const left = previous.mark?.fragment.enclosingParagraphRsid;
|
|
169087
|
+
const right = next.mark?.fragment.enclosingParagraphRsid;
|
|
169088
|
+
return Boolean(left && right && left.toUpperCase() === right.toUpperCase());
|
|
169089
|
+
}
|
|
168760
169090
|
function collectSameIdentityRuns(atoms) {
|
|
168761
169091
|
const runs = [];
|
|
168762
169092
|
let current = [];
|
|
@@ -168791,17 +169121,17 @@ function isSameGroupIdentity(a, b) {
|
|
|
168791
169121
|
function materializeReviewGroup(lookupContext, storyId, partUri, partXml, run, input) {
|
|
168792
169122
|
const textAtoms = run.filter((atom) => atom.kind === "text");
|
|
168793
169123
|
const markAtoms = run.filter((atom) => atom.kind === "mark");
|
|
169124
|
+
const objectAtoms = run.filter((atom) => atom.kind === "object");
|
|
168794
169125
|
if (textAtoms.length === 0 || markAtoms.length === 0)
|
|
168795
169126
|
return;
|
|
168796
169127
|
const carrierParagraphStarts = new Set([
|
|
168797
169128
|
...textAtoms.map((atom) => atom.candidate.paragraphStart),
|
|
169129
|
+
...objectAtoms.map((atom) => atom.candidate.paragraphStart),
|
|
168798
169130
|
...markAtoms.map((atom) => atom.candidate.paragraphStart)
|
|
168799
169131
|
]);
|
|
168800
|
-
const fullParagraphStarts = new Set(markAtoms.filter((atom) => atom.candidate.fragment.fullParagraphInsertion === true
|
|
168801
|
-
let
|
|
168802
|
-
if ([...carrierParagraphStarts].every((paragraphStart) => fullParagraphStarts.has(paragraphStart))) {
|
|
168803
|
-
if (markAtoms.length !== 1)
|
|
168804
|
-
return;
|
|
169132
|
+
const fullParagraphStarts = new Set(markAtoms.filter((atom) => atom.candidate.fragment.fullParagraphInsertion === true).map((atom) => atom.candidate.paragraphStart));
|
|
169133
|
+
let fullParagraphOwner;
|
|
169134
|
+
if (markAtoms.length === 1 && [...carrierParagraphStarts].every((paragraphStart) => fullParagraphStarts.has(paragraphStart))) {
|
|
168805
169135
|
const marker = markAtoms[0].candidate.fragment;
|
|
168806
169136
|
const paragraphStart = marker.enclosingElementStart;
|
|
168807
169137
|
const paragraphEnd = marker.enclosingElementEnd;
|
|
@@ -168811,12 +169141,12 @@ function materializeReviewGroup(lookupContext, storyId, partUri, partXml, run, i
|
|
|
168811
169141
|
const subtype = classifyFullParagraphInsertion(lookupContext, partXml, paragraphStart, paragraphEnd, paragraphXml).subtype;
|
|
168812
169142
|
if (subtype === "table-split")
|
|
168813
169143
|
return;
|
|
168814
|
-
if (subtype === "list-item-insertion") {
|
|
169144
|
+
if (subtype === "list-item-insertion" || objectAtoms.length > 0) {
|
|
168815
169145
|
const candidate2 = markAtoms[0].candidate;
|
|
168816
|
-
const ownsStructuralContent = input.byStory.get(storyId)?.some((entry) => entry.type === "structural" && entry !== candidate2.entry && entry.structuralFragments.some((fragment2) => fragment2.byteStart >= paragraphStart && fragment2.byteEnd <= paragraphEnd));
|
|
169146
|
+
const ownsStructuralContent = input.byStory.get(storyId)?.some((entry) => entry.type === "structural" && entry !== candidate2.entry && !objectAtoms.some((atom) => atom.candidate.entry === entry) && entry.structuralFragments.some((fragment2) => fragment2.byteStart >= paragraphStart && fragment2.byteEnd <= paragraphEnd));
|
|
168817
169147
|
if (ownsStructuralContent)
|
|
168818
169148
|
return;
|
|
168819
|
-
|
|
169149
|
+
fullParagraphOwner = candidate2;
|
|
168820
169150
|
}
|
|
168821
169151
|
}
|
|
168822
169152
|
const memberEntries = [];
|
|
@@ -168839,15 +169169,15 @@ function materializeReviewGroup(lookupContext, storyId, partUri, partXml, run, i
|
|
|
168839
169169
|
const markKey = markParagraphIds.every((paraId) => paraId != null) ? markParagraphIds.map((paraId) => `p:${paraId}`).join(",") : markOrdinals.join(",");
|
|
168840
169170
|
const groupHash = hashGroupKey(["word-inserted-paragraph-range", storyId, identityKey, `pm:${markKey}`, `tx:${textAtoms.length}`].join("|"));
|
|
168841
169171
|
const groupId = buildLogicalId(storyId, "ins", "word-paragraph-range", groupHash);
|
|
168842
|
-
if (
|
|
169172
|
+
if (fullParagraphOwner) {
|
|
168843
169173
|
materializeFullParagraphInsertion(lookupContext, {
|
|
168844
169174
|
storyId,
|
|
168845
169175
|
partUri,
|
|
168846
169176
|
partXml,
|
|
168847
|
-
structuralEntry:
|
|
168848
|
-
marker:
|
|
169177
|
+
structuralEntry: fullParagraphOwner.entry,
|
|
169178
|
+
marker: fullParagraphOwner.fragment,
|
|
168849
169179
|
textEntries: uniqueEntries(textAtoms.map((atom) => atom.candidate.entry)),
|
|
168850
|
-
objectEntries:
|
|
169180
|
+
objectEntries: uniqueEntries(objectAtoms.map((atom) => atom.candidate.entry)),
|
|
168851
169181
|
logicalId: groupId,
|
|
168852
169182
|
input
|
|
168853
169183
|
});
|
|
@@ -168855,8 +169185,11 @@ function materializeReviewGroup(lookupContext, storyId, partUri, partXml, run, i
|
|
|
168855
169185
|
}
|
|
168856
169186
|
const canonicalText = buildCanonicalGroupText(partXml, run);
|
|
168857
169187
|
const fragments = textAtoms.map((atom) => atom.fragment);
|
|
168858
|
-
const structuralFragments =
|
|
168859
|
-
|
|
169188
|
+
const structuralFragments = [
|
|
169189
|
+
...objectAtoms.map((atom) => atom.fragment),
|
|
169190
|
+
...markAtoms.map((atom) => atom.candidate.fragment)
|
|
169191
|
+
].sort((left, right) => left.byteStart - right.byteStart);
|
|
169192
|
+
const semanticPositions = run.filter((atom) => atom.kind !== "blocker").map((atom) => atom.kind === "mark" ? { start: atom.candidate.paragraphEnd, end: atom.candidate.paragraphEnd } : { start: atom.fragment.byteStart, end: atom.fragment.byteEnd });
|
|
168860
169193
|
const documentOrderStart = Math.min(...semanticPositions.map((position) => position.start));
|
|
168861
169194
|
const documentOrderEnd = Math.max(...semanticPositions.map((position) => position.end));
|
|
168862
169195
|
const textEntries = uniqueEntries(textAtoms.map((atom) => atom.candidate.entry));
|
|
@@ -168872,26 +169205,45 @@ function materializeReviewGroup(lookupContext, storyId, partUri, partXml, run, i
|
|
|
168872
169205
|
...structuralFragments.map((fragment2) => fragment2.date)
|
|
168873
169206
|
]);
|
|
168874
169207
|
const headEntry = memberEntries[0];
|
|
168875
|
-
const
|
|
168876
|
-
|
|
168877
|
-
|
|
168878
|
-
|
|
168879
|
-
|
|
168880
|
-
|
|
168881
|
-
|
|
168882
|
-
|
|
168883
|
-
|
|
168884
|
-
|
|
168885
|
-
|
|
168886
|
-
|
|
168887
|
-
|
|
168888
|
-
|
|
168889
|
-
|
|
168890
|
-
|
|
168891
|
-
|
|
168892
|
-
|
|
168893
|
-
|
|
168894
|
-
|
|
169208
|
+
const ownedNotes = uniqueNonEmptyStrings(memberEntries.flatMap((entry) => ownedNoteIds(entry)));
|
|
169209
|
+
const members = run.filter((atom) => atom.kind !== "blocker").map((atom) => {
|
|
169210
|
+
if (atom.kind === "text") {
|
|
169211
|
+
return {
|
|
169212
|
+
logicalId: atom.candidate.entry.id,
|
|
169213
|
+
carrier: "text",
|
|
169214
|
+
partUri,
|
|
169215
|
+
storyId,
|
|
169216
|
+
rsid: atom.fragment.rsid,
|
|
169217
|
+
...atom.fragment.wId ? { wordId: atom.fragment.wId } : {},
|
|
169218
|
+
subtype: "text-insertion",
|
|
169219
|
+
byteStart: atom.fragment.byteStart,
|
|
169220
|
+
byteEnd: atom.fragment.byteEnd
|
|
169221
|
+
};
|
|
169222
|
+
}
|
|
169223
|
+
if (atom.kind === "object") {
|
|
169224
|
+
return {
|
|
169225
|
+
logicalId: atom.candidate.entry.id,
|
|
169226
|
+
carrier: "structural",
|
|
169227
|
+
partUri,
|
|
169228
|
+
storyId,
|
|
169229
|
+
entityKey: atom.fragment.entityKey,
|
|
169230
|
+
...atom.fragment.wId ? { wordId: atom.fragment.wId } : {},
|
|
169231
|
+
subtype: atom.fragment.structuralKind,
|
|
169232
|
+
byteStart: atom.fragment.byteStart,
|
|
169233
|
+
byteEnd: atom.fragment.byteEnd
|
|
169234
|
+
};
|
|
169235
|
+
}
|
|
169236
|
+
return {
|
|
169237
|
+
logicalId: atom.candidate.entry.id,
|
|
169238
|
+
carrier: "structural",
|
|
169239
|
+
partUri,
|
|
169240
|
+
storyId,
|
|
169241
|
+
entityKey: atom.candidate.fragment.entityKey,
|
|
169242
|
+
...atom.candidate.fragment.wId ? { wordId: atom.candidate.fragment.wId } : {},
|
|
169243
|
+
subtype: "paragraph-mark-insertion",
|
|
169244
|
+
byteStart: atom.candidate.fragment.byteStart,
|
|
169245
|
+
byteEnd: atom.candidate.fragment.byteEnd
|
|
169246
|
+
};
|
|
168895
169247
|
});
|
|
168896
169248
|
const parent = {
|
|
168897
169249
|
id: groupId,
|
|
@@ -168900,7 +169252,8 @@ function materializeReviewGroup(lookupContext, storyId, partUri, partXml, run, i
|
|
|
168900
169252
|
state: "open",
|
|
168901
169253
|
storyId,
|
|
168902
169254
|
partUri,
|
|
168903
|
-
noteId: null,
|
|
169255
|
+
noteId: ownedNotes[0] ?? memberEntries.find((entry) => entry.noteId != null)?.noteId ?? null,
|
|
169256
|
+
noteIds: ownedNotes.length > 0 ? ownedNotes : null,
|
|
168904
169257
|
documentOrderStart,
|
|
168905
169258
|
documentOrderEnd,
|
|
168906
169259
|
author: { name: headEntry.author.name, initials: headEntry.author.initials },
|
|
@@ -169014,9 +169367,17 @@ function uniqueNonEmptyStrings(values) {
|
|
|
169014
169367
|
}
|
|
169015
169368
|
return out;
|
|
169016
169369
|
}
|
|
169370
|
+
function ownedNoteIds(entry) {
|
|
169371
|
+
if (entry.noteIds && entry.noteIds.length > 0)
|
|
169372
|
+
return [...entry.noteIds];
|
|
169373
|
+
return entry.noteId != null ? [entry.noteId] : [];
|
|
169374
|
+
}
|
|
169017
169375
|
function isBodyStoryId(storyId) {
|
|
169018
169376
|
return storyId.startsWith("main:") || storyId.endsWith(":/word/document.xml");
|
|
169019
169377
|
}
|
|
169378
|
+
function isNotesStoryId(storyId) {
|
|
169379
|
+
return storyId.startsWith("footnotes:") || storyId.startsWith("endnotes:");
|
|
169380
|
+
}
|
|
169020
169381
|
function buildBodyParagraphOrdinalIndexWithLookupContext(lookupContext, partXml) {
|
|
169021
169382
|
const bodyOpen = /<([\w.-]+):body\b[^>]*>/.exec(partXml);
|
|
169022
169383
|
if (!bodyOpen) {
|
|
@@ -169997,13 +170358,14 @@ function materializeDeletionGroup(storyId, partUri, partXml, run, carrierOrdinal
|
|
|
169997
170358
|
].filter((ordinal) => ordinal !== undefined).sort((a, b) => a - b);
|
|
169998
170359
|
const memberParagraphTokens = run.filter((atom) => atom.kind !== "blocker").map((atom) => {
|
|
169999
170360
|
const paraId = readParagraphIdAt(partXml, atom.candidate.paragraphStart);
|
|
170000
|
-
|
|
170361
|
+
const kindToken = atom.kind === "mark" ? "m" : atom.kind === "object" ? "o" : "t";
|
|
170362
|
+
return paraId != null ? `${kindToken}@p:${paraId}` : null;
|
|
170001
170363
|
});
|
|
170002
170364
|
const memberKey = memberParagraphTokens.every((token) => token != null) ? memberParagraphTokens.join(",") : carrierOrdinals.join(",");
|
|
170003
170365
|
const groupHash = hashGroupKey(["word-deleted-paragraph-range", storyId, partUri, `co:${memberKey}`].join("|"));
|
|
170004
170366
|
const groupId = buildLogicalId(storyId, "del", "word-deleted-paragraph-range", groupHash);
|
|
170005
170367
|
const canonicalText = buildCanonicalDeletionGroupText(partXml, run);
|
|
170006
|
-
const semanticPositions = run.filter((atom) => atom.kind !== "blocker").map((atom) => atom.kind === "
|
|
170368
|
+
const semanticPositions = run.filter((atom) => atom.kind !== "blocker").map((atom) => atom.kind === "mark" ? { start: atom.candidate.paragraphEnd, end: atom.candidate.paragraphEnd } : { start: atom.fragment.byteStart, end: atom.fragment.byteEnd });
|
|
170007
170369
|
const documentOrderStart = Math.min(...semanticPositions.map((position) => position.start));
|
|
170008
170370
|
const documentOrderEnd = Math.max(...semanticPositions.map((position) => position.end));
|
|
170009
170371
|
const textEntries = uniqueEntries(textAtoms.map((atom) => atom.candidate.entry));
|
|
@@ -170021,7 +170383,7 @@ function materializeDeletionGroup(storyId, partUri, partXml, run, carrierOrdinal
|
|
|
170021
170383
|
const headEntry = memberEntries[0];
|
|
170022
170384
|
const hasDeletedText = textAtoms.length > 0;
|
|
170023
170385
|
const structuralDelta = hasDeletedText ? null : buildDeletedParagraphMarkRangeStructuralDelta(partXml, structuralFragments);
|
|
170024
|
-
const members = run.filter((atom) => atom.kind
|
|
170386
|
+
const members = run.filter((atom) => atom.kind === "text" || atom.kind === "mark").map((atom) => atom.kind === "text" ? {
|
|
170025
170387
|
logicalId: atom.candidate.entry.id,
|
|
170026
170388
|
carrier: "text",
|
|
170027
170389
|
partUri,
|
|
@@ -174115,6 +174477,7 @@ function buildStructuralLogical(lookupContext, entityKey, group, noteId, partXml
|
|
|
174115
174477
|
documentOrderStart,
|
|
174116
174478
|
documentOrderEnd,
|
|
174117
174479
|
author: { name: head.author.name, initials: head.author.initials },
|
|
174480
|
+
authorEmail: head.authorEmail ?? null,
|
|
174118
174481
|
date: head.date,
|
|
174119
174482
|
sourceIds,
|
|
174120
174483
|
revisionGroupId: id,
|
|
@@ -180832,7 +181195,7 @@ function reserveRevisionWIdBlock(state, count) {
|
|
|
180832
181195
|
}
|
|
180833
181196
|
return base2;
|
|
180834
181197
|
}
|
|
180835
|
-
function planRevisionWIdBlock(state, count) {
|
|
181198
|
+
function planRevisionWIdBlock(state, count, options) {
|
|
180836
181199
|
let max2 = state.idReservations.revisionWIds.max;
|
|
180837
181200
|
if (!state.idReservations.revisionWIds.seeded) {
|
|
180838
181201
|
for (const [, bytes] of state.packageBytes.entries()) {
|
|
@@ -180841,6 +181204,9 @@ function planRevisionWIdBlock(state, count) {
|
|
|
180841
181204
|
max2 = value;
|
|
180842
181205
|
}
|
|
180843
181206
|
}
|
|
181207
|
+
if (options?.afterMax != null && options.afterMax > max2) {
|
|
181208
|
+
max2 = options.afterMax;
|
|
181209
|
+
}
|
|
180844
181210
|
const size = Math.max(1, Math.floor(count));
|
|
180845
181211
|
return Array.from({ length: size }, (_, index) => max2 + index + 1);
|
|
180846
181212
|
}
|
|
@@ -216733,7 +217099,8 @@ function compilePastedNotesMetadata(input) {
|
|
|
216733
217099
|
paragraph,
|
|
216734
217100
|
type,
|
|
216735
217101
|
includeMarker: index === 0,
|
|
216736
|
-
paraSalt: paraSalt += 1
|
|
217102
|
+
paraSalt: paraSalt += 1,
|
|
217103
|
+
trackedStamp: input.trackedStamp ?? null
|
|
216737
217104
|
})).join("");
|
|
216738
217105
|
fragments.push(`<w:${type} w:id="${escapeXmlAttribute(destinationId)}">${bodyXml}</w:${type}>`);
|
|
216739
217106
|
}
|
|
@@ -216837,7 +217204,18 @@ function renderNoteParagraphXml(input) {
|
|
|
216837
217204
|
const markerStyle = input.type === "footnote" ? "FootnoteReference" : "EndnoteReference";
|
|
216838
217205
|
const markerLocal = input.type === "footnote" ? "footnoteRef" : "endnoteRef";
|
|
216839
217206
|
const marker = input.includeMarker ? `<w:r><w:rPr><w:rStyle w:val="${markerStyle}"/></w:rPr><w:${markerLocal}/></w:r>` : "";
|
|
216840
|
-
|
|
217207
|
+
const runs = noteBodyRuns(input.paragraph);
|
|
217208
|
+
const inner = `${marker}${renderPasteRuns(runs)}`;
|
|
217209
|
+
const pPrXml = `<w:pPr><w:pStyle w:val="${escapeXmlAttribute(style)}"/></w:pPr>`;
|
|
217210
|
+
const stamp = input.trackedStamp;
|
|
217211
|
+
const pPr = stamp ? renderTrackedParagraphMarkProperties(pPrXml, stamp) : pPrXml;
|
|
217212
|
+
const body = stamp && inner ? wrapNoteTrackedInsertion(inner, stamp) : inner;
|
|
217213
|
+
const rsid = stamp ? ` w:rsidR="${escapeXmlAttribute(stamp.rsid)}"` : "";
|
|
217214
|
+
return `<w:p w14:paraId="${escapeXmlAttribute(paraId)}"${rsid}>` + `${pPr}${body}</w:p>`;
|
|
217215
|
+
}
|
|
217216
|
+
function wrapNoteTrackedInsertion(inner, stamp) {
|
|
217217
|
+
const id = stamp.allocateWId();
|
|
217218
|
+
return `${renderTrackedChangeOpen("ins", id, stamp, true)}${inner}</w:ins>`;
|
|
216841
217219
|
}
|
|
216842
217220
|
function noteBodyRuns(paragraph) {
|
|
216843
217221
|
if (!paragraph.inlines)
|
|
@@ -232266,12 +232644,19 @@ function preparePasteFragmentMutation(input) {
|
|
|
232266
232644
|
if (!review.ok)
|
|
232267
232645
|
return rejected18(txId, review.reason);
|
|
232268
232646
|
const mergedSidecarPerPart = { ...listExtras.perPart, ...imageExtras.value.perPart, ...review.perPart };
|
|
232647
|
+
const pastedNotes = op.fragment.notes ?? [];
|
|
232648
|
+
const noteParagraphs = pastedNotes.flatMap((note) => note.paragraphs);
|
|
232649
|
+
const notesStamp = changeMode === "tracked" && pastedNotes.length > 0 ? pickTrackedStamp(input, trackedFragmentCarrierBudget(noteParagraphs) + noteParagraphs.length) : null;
|
|
232650
|
+
if (changeMode === "tracked" && pastedNotes.length > 0 && !notesStamp) {
|
|
232651
|
+
return rejected18(txId, "no-author-configured");
|
|
232652
|
+
}
|
|
232269
232653
|
const notes = compilePastedNotesMetadata({
|
|
232270
232654
|
state,
|
|
232271
232655
|
blocks: resolvedBlocks,
|
|
232272
|
-
notes:
|
|
232656
|
+
notes: pastedNotes,
|
|
232273
232657
|
documentRelsBytes: plannedPackagePartBytes(state, mergedSidecarPerPart, DOCUMENT_RELS_PART_URI9),
|
|
232274
|
-
contentTypesBytes: plannedPackagePartBytes(state, mergedSidecarPerPart, CONTENT_TYPES_PART_URI11)
|
|
232658
|
+
contentTypesBytes: plannedPackagePartBytes(state, mergedSidecarPerPart, CONTENT_TYPES_PART_URI11),
|
|
232659
|
+
trackedStamp: notesStamp
|
|
232275
232660
|
});
|
|
232276
232661
|
if (!notes.ok)
|
|
232277
232662
|
return rejected18(txId, notes.reason);
|
|
@@ -232287,7 +232672,8 @@ function preparePasteFragmentMutation(input) {
|
|
|
232287
232672
|
patchMaps: { ...listExtras.patchMaps, ...imageExtras.value.patchMaps, ...review.patchMaps, ...notes.patchMaps },
|
|
232288
232673
|
createdRefs: review.createdRefs,
|
|
232289
232674
|
commentIdMap: review.commentIdMap,
|
|
232290
|
-
noteIdMap: notes.noteIdMap
|
|
232675
|
+
noteIdMap: notes.noteIdMap,
|
|
232676
|
+
revisionWIds: usedTrackedWIds(notesStamp)
|
|
232291
232677
|
};
|
|
232292
232678
|
if (isStoryTarget(pasteTarget)) {
|
|
232293
232679
|
if (preflight.plan.target.kind !== "story")
|
|
@@ -232495,7 +232881,9 @@ function runTrackedWholeStoryReplaceCommit(input, target, rendered, blocks, extr
|
|
|
232495
232881
|
const preview = prepare();
|
|
232496
232882
|
if (!preview)
|
|
232497
232883
|
return rejected18(txId, "paste-tracked-structural-unsupported");
|
|
232498
|
-
const revisionWIds = planRevisionWIdBlock(state, preview.wordIds.length
|
|
232884
|
+
const revisionWIds = planRevisionWIdBlock(state, preview.wordIds.length, {
|
|
232885
|
+
afterMax: afterMaxFromPlannedRevisionWIds(extras.revisionWIds)
|
|
232886
|
+
});
|
|
232499
232887
|
const replacement = prepare(revisionWIds);
|
|
232500
232888
|
if (!replacement)
|
|
232501
232889
|
return rejected18(txId, "paste-tracked-structural-unsupported");
|
|
@@ -232525,7 +232913,7 @@ function runTrackedWholeStoryReplaceCommit(input, target, rendered, blocks, extr
|
|
|
232525
232913
|
extraPatchMaps: extras.patchMaps,
|
|
232526
232914
|
packagePartUris: inlineExtras.partUris,
|
|
232527
232915
|
storyWideProjection: true,
|
|
232528
|
-
revisionWIds,
|
|
232916
|
+
revisionWIds: [...revisionWIds, ...extras.revisionWIds ?? []],
|
|
232529
232917
|
indexRefreshScope: { perPart: { [target.partUri]: {
|
|
232530
232918
|
beforeWindow: { startByte: target.byteStart, endByte: target.byteEnd },
|
|
232531
232919
|
kind: "wide-rewrite",
|
|
@@ -232611,7 +232999,7 @@ function runParagraphBlockPasteCommit(input, target, blocks, extras, inlineExtra
|
|
|
232611
232999
|
return rejected18(txId, "paste-target-unsupported");
|
|
232612
233000
|
const changeMode = op.changeMode ?? "direct";
|
|
232613
233001
|
const anchorXml = TD64.decode(bytes.subarray(anchor.byteStart, anchor.byteEnd));
|
|
232614
|
-
const trackedStamp = changeMode === "tracked" ? pickTrackedStamp(input, trackedFragmentCarrierBudget(blocks) + (target.placement === "replace" ? trackedBlockDeletionCarrierBudget(anchorXml) : 2)) : null;
|
|
233002
|
+
const trackedStamp = changeMode === "tracked" ? pickTrackedStamp(input, trackedFragmentCarrierBudget(blocks) + (target.placement === "replace" ? trackedBlockDeletionCarrierBudget(anchorXml) : 2), { afterMax: afterMaxFromPlannedRevisionWIds(extras.revisionWIds) }) : null;
|
|
232615
233003
|
if (changeMode === "tracked" && !trackedStamp)
|
|
232616
233004
|
return rejected18(txId, "no-author-configured");
|
|
232617
233005
|
const trackedDeletedAnchor = trackedStamp && target.placement === "replace" ? renderTrackedBlockDeletion({
|
|
@@ -232763,7 +233151,7 @@ function runParagraphBlockPasteCommit(input, target, blocks, extras, inlineExtra
|
|
|
232763
233151
|
extraPatchMaps: { ...extras.patchMaps, ...commentCascade.patchMaps, ...resourceCleanup.patchMaps },
|
|
232764
233152
|
packagePartUris: [...inlineExtras.partUris, ...resourceCleanup.packagePartUris],
|
|
232765
233153
|
storyWideProjection: target.placement === "replace" || blocks.some((block) => block.kind === "table"),
|
|
232766
|
-
revisionWIds: usedTrackedWIds(trackedStamp),
|
|
233154
|
+
revisionWIds: usedTrackedWIds(trackedStamp, extras.revisionWIds),
|
|
232767
233155
|
...target.placement === "replace" ? {
|
|
232768
233156
|
indexRefreshScope: {
|
|
232769
233157
|
perPart: {
|
|
@@ -232788,7 +233176,7 @@ function runWholeTableReplaceCommit(input, target, blocks, extras, inlineExtras)
|
|
|
232788
233176
|
return rejected18(txId, "paste-target-unsupported");
|
|
232789
233177
|
}
|
|
232790
233178
|
const replacedParagraphs = index.entries.filter((entry) => entry.byteStart >= target.byteStart && entry.byteEnd <= target.byteEnd);
|
|
232791
|
-
const trackedStamp = changeMode === "tracked" ? pickTrackedStamp(input, trackedFragmentCarrierBudget(blocks) + table.rows.length + 2) : null;
|
|
233179
|
+
const trackedStamp = changeMode === "tracked" ? pickTrackedStamp(input, trackedFragmentCarrierBudget(blocks) + table.rows.length + 2, { afterMax: afterMaxFromPlannedRevisionWIds(extras.revisionWIds) }) : null;
|
|
232792
233180
|
if (changeMode === "tracked" && !trackedStamp)
|
|
232793
233181
|
return rejected18(txId, "no-author-configured");
|
|
232794
233182
|
const replacedXml = TD64.decode(bytes.subarray(target.byteStart, target.byteEnd));
|
|
@@ -232893,7 +233281,7 @@ function runWholeTableReplaceCommit(input, target, blocks, extras, inlineExtras)
|
|
|
232893
233281
|
extraPatchMaps: { ...extras.patchMaps, ...commentCascade.patchMaps },
|
|
232894
233282
|
packagePartUris: inlineExtras.partUris,
|
|
232895
233283
|
storyWideProjection: true,
|
|
232896
|
-
revisionWIds: usedTrackedWIds(trackedStamp),
|
|
233284
|
+
revisionWIds: usedTrackedWIds(trackedStamp, extras.revisionWIds),
|
|
232897
233285
|
indexRefreshScope: {
|
|
232898
233286
|
perPart: {
|
|
232899
233287
|
[target.partUri]: {
|
|
@@ -232928,7 +233316,7 @@ function runCrossParagraphTrackedPasteCommit(input, target, blocks, extras, inli
|
|
|
232928
233316
|
if (!rangeIntegrity.ok)
|
|
232929
233317
|
return rejected18(txId, "invalid-range");
|
|
232930
233318
|
const coveredEntries = index.entries.filter((entry) => entry.ordinal >= start.ordinal && entry.ordinal <= end.ordinal);
|
|
232931
|
-
const stamp = pickTrackedStamp(input, trackedFragmentCarrierBudget(blocks) + coveredEntries.length * 3 + 4);
|
|
233319
|
+
const stamp = pickTrackedStamp(input, trackedFragmentCarrierBudget(blocks) + coveredEntries.length * 3 + 4, { afterMax: afterMaxFromPlannedRevisionWIds(extras.revisionWIds) });
|
|
232932
233320
|
if (!stamp)
|
|
232933
233321
|
return rejected18(txId, "no-author-configured");
|
|
232934
233322
|
const patches = [];
|
|
@@ -233030,7 +233418,7 @@ function runCrossParagraphTrackedPasteCommit(input, target, blocks, extras, inli
|
|
|
233030
233418
|
extraPatchMaps: extras.patchMaps,
|
|
233031
233419
|
packagePartUris: inlineExtras.partUris,
|
|
233032
233420
|
storyWideProjection: true,
|
|
233033
|
-
revisionWIds: usedTrackedWIds(stamp),
|
|
233421
|
+
revisionWIds: usedTrackedWIds(stamp, extras.revisionWIds),
|
|
233034
233422
|
indexRefreshScope: {
|
|
233035
233423
|
perPart: {
|
|
233036
233424
|
[target.partUri]: {
|
|
@@ -233070,7 +233458,9 @@ function runCrossParagraphPasteCommit(input, target, blocks, extras, inlineExtra
|
|
|
233070
233458
|
return rejected18(txId, "invalid-range");
|
|
233071
233459
|
const endpointXml = TD64.decode(bytes.subarray(start.byteStart, start.byteEnd)) + TD64.decode(bytes.subarray(end.byteStart, end.byteEnd));
|
|
233072
233460
|
const wrapperCount = [...endpointXml.matchAll(/<(?:[\w.-]+:)?(?:ins|del|moveFrom|moveTo)\b/g)].length;
|
|
233073
|
-
const plannedWIds = planRevisionWIdBlock(state, Math.max(1, wrapperCount * 2 + 4)
|
|
233461
|
+
const plannedWIds = planRevisionWIdBlock(state, Math.max(1, wrapperCount * 2 + 4), {
|
|
233462
|
+
afterMax: afterMaxFromPlannedRevisionWIds(extras.revisionWIds)
|
|
233463
|
+
});
|
|
233074
233464
|
let usedWIds = 0;
|
|
233075
233465
|
let splicePlan;
|
|
233076
233466
|
let mintSalt = 0;
|
|
@@ -233147,7 +233537,7 @@ function runCrossParagraphPasteCommit(input, target, blocks, extras, inlineExtra
|
|
|
233147
233537
|
packagePartUris: inlineExtras.partUris,
|
|
233148
233538
|
storyWideProjection: true,
|
|
233149
233539
|
indexRefreshScope: contribution.indexRefreshScope,
|
|
233150
|
-
revisionWIds: plannedWIds.slice(0, usedWIds)
|
|
233540
|
+
revisionWIds: [...plannedWIds.slice(0, usedWIds), ...extras.revisionWIds ?? []]
|
|
233151
233541
|
});
|
|
233152
233542
|
}
|
|
233153
233543
|
function collectRemovedBookmarkRefs(ownerXml, removedXml, storyId) {
|
|
@@ -233223,7 +233613,7 @@ function tryRunTableRowPasteCommit(input, pasteTarget, pastedBlocks, additionalP
|
|
|
233223
233613
|
scopeHintOpenTag: matchParagraphOpenTag(targetParagraphXml) ?? ""
|
|
233224
233614
|
});
|
|
233225
233615
|
const createdParagraphIds = [];
|
|
233226
|
-
const trackedStamp = (input.op.changeMode ?? "direct") === "tracked" ? pickTrackedStamp(input, trackedFragmentCarrierBudget(pastedBlocks) + 2) : null;
|
|
233616
|
+
const trackedStamp = (input.op.changeMode ?? "direct") === "tracked" ? pickTrackedStamp(input, trackedFragmentCarrierBudget(pastedBlocks) + 2, { afterMax: afterMaxFromPlannedRevisionWIds(additionalPatches.revisionWIds) }) : null;
|
|
233227
233617
|
if ((input.op.changeMode ?? "direct") === "tracked" && !trackedStamp) {
|
|
233228
233618
|
return rejected18(transactionId, "no-author-configured");
|
|
233229
233619
|
}
|
|
@@ -233310,7 +233700,7 @@ function tryRunTableRowPasteCommit(input, pasteTarget, pastedBlocks, additionalP
|
|
|
233310
233700
|
provisionalToFinal: Object.fromEntries(createdParagraphIds.map((paragraphId, index) => [`${transactionId}:paste:${index}`, paragraphId])),
|
|
233311
233701
|
extraPatchMaps: additionalPatches.patchMaps,
|
|
233312
233702
|
storyWideProjection: true,
|
|
233313
|
-
revisionWIds: usedTrackedWIds(trackedStamp)
|
|
233703
|
+
revisionWIds: usedTrackedWIds(trackedStamp, additionalPatches.revisionWIds)
|
|
233314
233704
|
});
|
|
233315
233705
|
}
|
|
233316
233706
|
function findContainingTableCell(tableCatalog, targetParagraph) {
|
|
@@ -233710,7 +234100,7 @@ function runPasteSpliceCommit(input, target, resolvedBlocks, listExtras, imageEx
|
|
|
233710
234100
|
const changeMode = input.op.changeMode ?? "direct";
|
|
233711
234101
|
const wrapAllTracked = changeMode === "tracked";
|
|
233712
234102
|
const fragmentTracked = fragmentHasTrackedInsertion(resolvedBlocks);
|
|
233713
|
-
const trackedStamp = wrapAllTracked || fragmentTracked ? pickTrackedStamp(input, trackedFragmentCarrierBudget(resolvedBlocks) + 4) : null;
|
|
234103
|
+
const trackedStamp = wrapAllTracked || fragmentTracked ? pickTrackedStamp(input, trackedFragmentCarrierBudget(resolvedBlocks) + 4, { afterMax: afterMaxFromPlannedRevisionWIds(listExtras.revisionWIds) }) : null;
|
|
233714
234104
|
if ((wrapAllTracked || fragmentTracked) && !trackedStamp)
|
|
233715
234105
|
return rejected18(txId, "no-author-configured");
|
|
233716
234106
|
let mintSalt = 0;
|
|
@@ -233840,7 +234230,7 @@ function runPasteSpliceCommit(input, target, resolvedBlocks, listExtras, imageEx
|
|
|
233840
234230
|
extraPatchMaps: listExtras.patchMaps,
|
|
233841
234231
|
storyWideProjection: resolvedBlocks.some((block) => block.kind === "table"),
|
|
233842
234232
|
packagePartUris: imageExtras.partUris,
|
|
233843
|
-
revisionWIds: usedTrackedWIds(trackedStamp),
|
|
234233
|
+
revisionWIds: usedTrackedWIds(trackedStamp, listExtras.revisionWIds),
|
|
233844
234234
|
indexRefreshScope: {
|
|
233845
234235
|
perPart: {
|
|
233846
234236
|
[partUri]: {
|
|
@@ -234860,11 +235250,11 @@ function injectTrackedMarkIntoLastParagraph(xml, stamp, kind) {
|
|
|
234860
235250
|
const replacement = injectTrackedParagraphMarkIntoXml(match[0], stamp, kind);
|
|
234861
235251
|
return xml.slice(0, match.index) + replacement + xml.slice(match.index + match[0].length);
|
|
234862
235252
|
}
|
|
234863
|
-
function pickTrackedStamp(input, capacity) {
|
|
235253
|
+
function pickTrackedStamp(input, capacity, options) {
|
|
234864
235254
|
const author = input.authorOverride ?? input.author;
|
|
234865
235255
|
if (!author)
|
|
234866
235256
|
return null;
|
|
234867
|
-
const plannedWIds = planRevisionWIdBlock(input.state, Math.max(1, capacity));
|
|
235257
|
+
const plannedWIds = planRevisionWIdBlock(input.state, Math.max(1, capacity), options);
|
|
234868
235258
|
const stamp = {
|
|
234869
235259
|
rsid: allocateTxRsid(input.txId),
|
|
234870
235260
|
plannedWIds,
|
|
@@ -234881,8 +235271,17 @@ function pickTrackedStamp(input, capacity) {
|
|
|
234881
235271
|
};
|
|
234882
235272
|
return stamp;
|
|
234883
235273
|
}
|
|
234884
|
-
function
|
|
234885
|
-
|
|
235274
|
+
function afterMaxFromPlannedRevisionWIds(revisionWIds) {
|
|
235275
|
+
if (!revisionWIds || revisionWIds.length === 0)
|
|
235276
|
+
return;
|
|
235277
|
+
return Math.max(...revisionWIds);
|
|
235278
|
+
}
|
|
235279
|
+
function usedTrackedWIds(stamp, extra) {
|
|
235280
|
+
const ids = [
|
|
235281
|
+
...stamp ? stamp.plannedWIds.slice(0, stamp.usedWIdCount) : [],
|
|
235282
|
+
...extra ?? []
|
|
235283
|
+
];
|
|
235284
|
+
return ids.length > 0 ? ids : undefined;
|
|
234886
235285
|
}
|
|
234887
235286
|
function replayTrackedStamp(source) {
|
|
234888
235287
|
const replay = {
|
|
@@ -357366,7 +357765,14 @@ function logicalEntryMatchesStoryFilter(entry, filter) {
|
|
|
357366
357765
|
return isBodyStoryId2(entry.storyId);
|
|
357367
357766
|
if (!filter.storyIds?.has(entry.storyId))
|
|
357368
357767
|
return false;
|
|
357369
|
-
|
|
357768
|
+
if (!filter.noteId)
|
|
357769
|
+
return true;
|
|
357770
|
+
return ownedLogicalNoteIds(entry).includes(filter.noteId);
|
|
357771
|
+
}
|
|
357772
|
+
function ownedLogicalNoteIds(entry) {
|
|
357773
|
+
if (entry.noteIds && entry.noteIds.length > 0)
|
|
357774
|
+
return entry.noteIds;
|
|
357775
|
+
return entry.noteId != null ? [entry.noteId] : [];
|
|
357370
357776
|
}
|
|
357371
357777
|
function isVisibleLogicalChange(entry) {
|
|
357372
357778
|
return isVisibleLogicalTrackedChange(entry);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc/mcp",
|
|
3
|
-
"version": "1.2.1-next.
|
|
3
|
+
"version": "1.2.1-next.2",
|
|
4
4
|
"description": "Model Context Protocol server for SuperDoc, giving an AI agent tools to read and edit .docx files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
27
|
-
"@superdoc/sdk": "2.15.1-next.
|
|
27
|
+
"@superdoc/sdk": "2.15.1-next.2",
|
|
28
28
|
"debug": "^4.4.3",
|
|
29
29
|
"zod": "^4.3.6"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"superdoc": "2.18.1-next.
|
|
33
|
-
"@superdoc/docx-engine": "0.17.1-next.
|
|
32
|
+
"superdoc": "2.18.1-next.2",
|
|
33
|
+
"@superdoc/docx-engine": "0.17.1-next.2",
|
|
34
34
|
"@superdoc/document-api": "0.1.0-alpha.0",
|
|
35
35
|
"@types/bun": "^1.3.8",
|
|
36
36
|
"@types/node": "22.19.2",
|