@superdoc/mcp 1.2.0-next.11 → 1.2.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 +1295 -188
- 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.0-next.
|
|
31317
|
+
var SDK_VERSION = "2.15.0-next.13";
|
|
31318
31318
|
|
|
31319
31319
|
// ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
|
|
31320
31320
|
import { chmodSync, existsSync } from "node:fs";
|
|
@@ -188376,6 +188376,8 @@ function renderPasteParagraphBlock(spec) {
|
|
|
188376
188376
|
return `<w:p${nsDecl} w14:paraId="${escapeXmlAttribute(spec.paraId)}">${pPr}${renderPasteRuns(spec.runs)}</w:p>`;
|
|
188377
188377
|
}
|
|
188378
188378
|
function renderReviewAwarePasteRun(run, stamp) {
|
|
188379
|
+
if (run.kind === "sdt")
|
|
188380
|
+
return renderPasteSdt(run, stamp);
|
|
188379
188381
|
let xml = renderPasteRun(run);
|
|
188380
188382
|
if (!("text" in run))
|
|
188381
188383
|
return xml;
|
|
@@ -188516,6 +188518,11 @@ function renderTrackedPasteRuns(runs, stamp) {
|
|
|
188516
188518
|
out.push(wrapTrackedInsertion(inner, stamp));
|
|
188517
188519
|
};
|
|
188518
188520
|
for (const run of runs) {
|
|
188521
|
+
if (run.kind === "sdt") {
|
|
188522
|
+
flushOrdinary();
|
|
188523
|
+
out.push(wrapTrackedInsertion(renderPasteSdt(run), stamp));
|
|
188524
|
+
continue;
|
|
188525
|
+
}
|
|
188519
188526
|
if (run.kind !== "hyperlink") {
|
|
188520
188527
|
if (run.kind === "footnoteRef" || run.kind === "endnoteRef") {
|
|
188521
188528
|
flushOrdinary();
|
|
@@ -188581,6 +188588,8 @@ function renderPasteTableCell(cell, renderParagraph = renderPasteParagraphBlock)
|
|
|
188581
188588
|
return `<w:tc>${tcPr}${cell.paragraphs.map(renderParagraph).join("")}</w:tc>`;
|
|
188582
188589
|
}
|
|
188583
188590
|
function renderPasteRun(run, options = {}) {
|
|
188591
|
+
if (run.kind === "sdt")
|
|
188592
|
+
return renderPasteSdt(run);
|
|
188584
188593
|
if (run.kind === "image")
|
|
188585
188594
|
return run.xml;
|
|
188586
188595
|
if (run.kind === "hyperlink")
|
|
@@ -188611,6 +188620,32 @@ function renderPasteRun(run, options = {}) {
|
|
|
188611
188620
|
}
|
|
188612
188621
|
return out.join("");
|
|
188613
188622
|
}
|
|
188623
|
+
function renderPasteSdt(run, stamp) {
|
|
188624
|
+
const properties = (run.alias !== undefined ? `<w:alias w:val="${escapeXmlAttribute(run.alias)}"/>` : "") + (run.tag !== undefined ? `<w:tag w:val="${escapeXmlAttribute(run.tag)}"/>` : "") + `<w:id w:val="${escapeXmlAttribute(run.id)}"/>` + (run.lockMode !== undefined ? `<w:lock w:val="${run.lockMode}"/>` : "") + (run.controlType === "text" && run.multiline !== undefined ? `<w:text w:multiLine="${run.multiline ? "1" : "0"}"/>` : `<w:${run.controlType}/>`);
|
|
188625
|
+
return `<w:sdt><w:sdtPr>${properties}</w:sdtPr><w:sdtContent>${renderPasteRuns(run.runs, stamp)}</w:sdtContent></w:sdt>`;
|
|
188626
|
+
}
|
|
188627
|
+
function renderBlockSdtSequence(blocks, xml, ids) {
|
|
188628
|
+
let result = "";
|
|
188629
|
+
let previous = [];
|
|
188630
|
+
for (let index = 0;index <= blocks.length; index += 1) {
|
|
188631
|
+
const block = blocks[index];
|
|
188632
|
+
const current = block && "blockSdts" in block ? block.blockSdts ?? [] : [];
|
|
188633
|
+
let shared = 0;
|
|
188634
|
+
while (shared < previous.length && shared < current.length && previous[shared].sourceId === current[shared].sourceId)
|
|
188635
|
+
shared += 1;
|
|
188636
|
+
for (let depth = previous.length - 1;depth >= shared; depth -= 1)
|
|
188637
|
+
result += "</w:sdtContent></w:sdt>";
|
|
188638
|
+
for (let depth = shared;depth < current.length; depth += 1) {
|
|
188639
|
+
const wrapper = current[depth];
|
|
188640
|
+
const id = ids.get(wrapper.sourceId);
|
|
188641
|
+
result += "<w:sdt><w:sdtPr>" + (wrapper.alias !== undefined ? `<w:alias w:val="${escapeXmlAttribute(wrapper.alias)}"/>` : "") + (wrapper.tag !== undefined ? `<w:tag w:val="${escapeXmlAttribute(wrapper.tag)}"/>` : "") + `<w:id w:val="${escapeXmlAttribute(id)}"/>` + (wrapper.lockMode !== undefined ? `<w:lock w:val="${wrapper.lockMode}"/>` : "") + (wrapper.controlType === "text" && wrapper.multiline !== undefined ? `<w:text w:multiLine="${wrapper.multiline ? "1" : "0"}"/>` : `<w:${wrapper.controlType}/>`) + "</w:sdtPr><w:sdtContent>";
|
|
188642
|
+
}
|
|
188643
|
+
if (index < blocks.length)
|
|
188644
|
+
result += xml[index];
|
|
188645
|
+
previous = current;
|
|
188646
|
+
}
|
|
188647
|
+
return result;
|
|
188648
|
+
}
|
|
188614
188649
|
function renderPasteHyperlink(run) {
|
|
188615
188650
|
const targetAttribute = run.target.kind === "external" ? `r:id="${escapeXmlAttribute(run.target.relationshipId ?? "")}"` : `w:anchor="${escapeXmlAttribute(run.target.anchor)}"`;
|
|
188616
188651
|
const tooltipAttribute = run.tooltip ? ` w:tooltip="${escapeXmlAttribute(run.tooltip)}"` : "";
|
|
@@ -189891,6 +189926,18 @@ function compileParsedOverlapEdit(input, tokens, descendedEditableContainers) {
|
|
|
189891
189926
|
});
|
|
189892
189927
|
token._classification = input.existingRevisionOwnership === "foreign" ? "different-user" : classifyOwnership(current, wrapperAuthor);
|
|
189893
189928
|
}
|
|
189929
|
+
const commented = wrappers.filter((entry) => entry.token.kind === "ins" && entry.token.commentedBoundary != null);
|
|
189930
|
+
if (commented.length > 0) {
|
|
189931
|
+
const parent = commented[0].token;
|
|
189932
|
+
const following = touched.filter((entry) => entry.token.kind === "plain");
|
|
189933
|
+
if (commented.length !== 1 || wrappers.length !== 1 || following.length !== 1 || following[0].token.byteStart < parent.byteEnd || parent._classification === "same-user" || input.changeMode !== "tracked" || input.newText.length === 0 || input.rangeStart <= parent.visibleStart || input.rangeStart >= parent.visibleEnd || input.rangeEnd <= parent.visibleEnd || input.rangeEnd > following[0].token.visibleEnd) {
|
|
189934
|
+
return {
|
|
189935
|
+
ok: false,
|
|
189936
|
+
reason: "text-range-in-unsupported-tracked-wrapper",
|
|
189937
|
+
detail: "overlap compiler: comment-bearing insertion requires a bounded foreign spanning replacement."
|
|
189938
|
+
};
|
|
189939
|
+
}
|
|
189940
|
+
}
|
|
189894
189941
|
if (input.newText.length > 0 && input.rangeStart < input.rangeEnd) {
|
|
189895
189942
|
const spanningReplacement = tryRangeReplacementAcrossTokens(input, tokens, touched);
|
|
189896
189943
|
if (spanningReplacement)
|
|
@@ -190531,8 +190578,21 @@ function authorTrackedPureDelete(input, allTokens, touched, touchedBreaks = [])
|
|
|
190531
190578
|
author: currentAuthor,
|
|
190532
190579
|
date: input.txTimestamp,
|
|
190533
190580
|
rsidDel: input.rsid,
|
|
190534
|
-
inner: { runOpen: token.inner.runOpen, runClose: token.inner.runClose, rPr: token.inner.rPr, text: removed }
|
|
190581
|
+
inner: { runOpen: token.inner.runOpen, runClose: token.inner.runClose, rPr: token.inner.rPr, text: removed },
|
|
190582
|
+
...token.commentedBoundary ? {
|
|
190583
|
+
innerXml: renderDelRun(removed, token.inner.runOpen, token.inner.runClose, token.inner.rPr) + token.commentedBoundary.endXml + token.commentedBoundary.referenceRunXml
|
|
190584
|
+
} : {}
|
|
190535
190585
|
});
|
|
190586
|
+
if (token.commentedBoundary) {
|
|
190587
|
+
if (!childIns || tail.length > 0)
|
|
190588
|
+
return null;
|
|
190589
|
+
pieces.push(token.commentedBoundary.startXml + token.openTag + nestedHead + childDel + token.closeTag + childIns);
|
|
190590
|
+
replacementInserted = true;
|
|
190591
|
+
if (!emittedRsids.includes(input.insRsid))
|
|
190592
|
+
emittedRsids.push(input.insRsid);
|
|
190593
|
+
emitDeletionRsid();
|
|
190594
|
+
continue;
|
|
190595
|
+
}
|
|
190536
190596
|
if (childIns) {
|
|
190537
190597
|
const headIns = head.length > 0 ? buildInsWrapperXml({
|
|
190538
190598
|
openTag: token.openTag,
|
|
@@ -191893,6 +191953,55 @@ function isSupportedStructuralDeletionChild(piece) {
|
|
|
191893
191953
|
}
|
|
191894
191954
|
return piece.containerKind === "unknown" && (piece.localName === "smartTag" || piece.localName === "dir" || piece.localName === "bdo");
|
|
191895
191955
|
}
|
|
191956
|
+
function readCommentedInsertionBoundary(piece) {
|
|
191957
|
+
const markers = piece.children.filter((child) => child.kind === "marker");
|
|
191958
|
+
if (markers.length !== 3 || piece.children.length !== 4)
|
|
191959
|
+
return null;
|
|
191960
|
+
const [start, end, reference] = markers;
|
|
191961
|
+
if (start.markerKind !== "commentRangeStart" || end.markerKind !== "commentRangeEnd" || reference.markerKind !== "commentReference" || !start.id || start.id !== end.id || start.id !== reference.id || start.runCharStart != null || end.runCharStart != null)
|
|
191962
|
+
return null;
|
|
191963
|
+
const text = piece.children.find((child) => child.kind === "text");
|
|
191964
|
+
if (!text || !text.decodedText)
|
|
191965
|
+
return null;
|
|
191966
|
+
const source = piece.rawXml;
|
|
191967
|
+
const base2 = piece.charStart;
|
|
191968
|
+
const openEnd = findXmlTagEnd(source, 1);
|
|
191969
|
+
const closeStart = source.lastIndexOf(`</${piece.qname}>`);
|
|
191970
|
+
const outsideBindings = Object.fromEntries(piece.namespaceBindings);
|
|
191971
|
+
for (const attribute of scanRawXmlAttributes(source.slice(0, openEnd))) {
|
|
191972
|
+
if (attribute.name === "xmlns" || attribute.prefix === "xmlns") {
|
|
191973
|
+
delete outsideBindings[attribute.name === "xmlns" ? "" : attribute.localName];
|
|
191974
|
+
}
|
|
191975
|
+
}
|
|
191976
|
+
const startXml = closeNamespaceScope(start.rawXml, Object.fromEntries(start.namespaceBindings), outsideBindings, { referencedOnly: true });
|
|
191977
|
+
if (startXml == null)
|
|
191978
|
+
return null;
|
|
191979
|
+
const textRunStart = text.runCharStart - base2;
|
|
191980
|
+
const textRunEnd = text.runCharEnd - base2;
|
|
191981
|
+
const startStart = start.charStart - base2;
|
|
191982
|
+
const startEnd = start.charEnd - base2;
|
|
191983
|
+
const endStart = end.charStart - base2;
|
|
191984
|
+
const endEnd = end.charEnd - base2;
|
|
191985
|
+
if (openEnd < 0 || closeStart < 0 || startStart < openEnd || startEnd > textRunStart || textRunEnd > endStart || endEnd > reference.charStart - base2 || [
|
|
191986
|
+
source.slice(openEnd, startStart),
|
|
191987
|
+
source.slice(startEnd, textRunStart),
|
|
191988
|
+
source.slice(textRunEnd, endStart)
|
|
191989
|
+
].some((gap) => gap.trim().length > 0))
|
|
191990
|
+
return null;
|
|
191991
|
+
const textRun = source.slice(textRunStart, textRunEnd);
|
|
191992
|
+
if (textRun.replace(text.runOpenTag, "").replace(text.runProperties ?? "", "").replace(text.rawXml, "").replace(text.runCloseTag, "").trim().length > 0)
|
|
191993
|
+
return null;
|
|
191994
|
+
const referenceRunXml = source.slice(endEnd, closeStart).trim();
|
|
191995
|
+
const referenceOpenEnd = findXmlTagEnd(referenceRunXml, 1);
|
|
191996
|
+
const referenceCloseStart = referenceRunXml.lastIndexOf("</");
|
|
191997
|
+
if (referenceOpenEnd < 0 || referenceCloseStart < referenceOpenEnd || !/^<([\w.-]+:)?r(?=[\s>])/.test(referenceRunXml) || !/<\/[\w.-]+:r>$/.test(referenceRunXml) || referenceRunXml.slice(referenceOpenEnd, referenceCloseStart).trim() !== reference.rawXml)
|
|
191998
|
+
return null;
|
|
191999
|
+
return {
|
|
192000
|
+
startXml,
|
|
192001
|
+
endXml: end.rawXml,
|
|
192002
|
+
referenceRunXml
|
|
192003
|
+
};
|
|
192004
|
+
}
|
|
191896
192005
|
function trackedToken(piece, spanStart, spanEnd, allowComplexDeletions, allowStructuralDeletionPassThrough) {
|
|
191897
192006
|
const visibleStart = spanStart(piece);
|
|
191898
192007
|
const visibleEnd = spanEnd(piece);
|
|
@@ -191932,6 +192041,7 @@ function trackedToken(piece, spanStart, spanEnd, allowComplexDeletions, allowStr
|
|
|
191932
192041
|
rawXml: child.rawXml
|
|
191933
192042
|
})).sort((a, b) => a.localOffset - b.localOffset);
|
|
191934
192043
|
}
|
|
192044
|
+
const commentedBoundary = piece.trackedKind === "ins" && !nestedDeletions ? readCommentedInsertionBoundary(piece) : null;
|
|
191935
192045
|
if (allowComplexDeletions && piece.trackedKind === "del") {
|
|
191936
192046
|
const unsupportedChild = piece.children.find((child) => child.kind !== "text" && !(child.kind === "marker" && isCommentMarker2(child.markerKind)) && !(allowStructuralDeletionPassThrough && isSupportedStructuralDeletionChild(child)));
|
|
191937
192047
|
if (unsupportedChild) {
|
|
@@ -191994,7 +192104,7 @@ function trackedToken(piece, spanStart, spanEnd, allowComplexDeletions, allowStr
|
|
|
191994
192104
|
}
|
|
191995
192105
|
};
|
|
191996
192106
|
}
|
|
191997
|
-
const foreignChild = piece.children.find((child) => child.kind === "container" || child.kind === "unknown" || child.kind === "noteReference" || child.kind === "control" && !(piece.trackedKind === "ins" && child.control === "tab") || child.kind === "marker");
|
|
192107
|
+
const foreignChild = piece.children.find((child) => child.kind === "container" || child.kind === "unknown" || child.kind === "noteReference" || child.kind === "control" && !(piece.trackedKind === "ins" && child.control === "tab") || child.kind === "marker" && !commentedBoundary);
|
|
191998
192108
|
if (foreignChild) {
|
|
191999
192109
|
if (foreignChild.kind === "container") {
|
|
192000
192110
|
return unsupported2(containerRejectionReason(foreignChild.containerKind), `overlap compiler: ${foreignChild.containerKind} inside w:${piece.trackedKind}`);
|
|
@@ -192059,7 +192169,13 @@ function trackedToken(piece, spanStart, spanEnd, allowComplexDeletions, allowStr
|
|
|
192059
192169
|
},
|
|
192060
192170
|
...innerRuns.length > 1 ? { innerRuns } : {}
|
|
192061
192171
|
};
|
|
192062
|
-
return piece.trackedKind === "ins" ? {
|
|
192172
|
+
return piece.trackedKind === "ins" ? {
|
|
192173
|
+
kind: "ins",
|
|
192174
|
+
...base2,
|
|
192175
|
+
rsidR,
|
|
192176
|
+
...nestedDeletions ? { nestedDeletions } : {},
|
|
192177
|
+
...commentedBoundary ? { commentedBoundary } : {}
|
|
192178
|
+
} : { kind: "del", ...base2, rsidDel };
|
|
192063
192179
|
}
|
|
192064
192180
|
function isCommentMarker2(markerKind) {
|
|
192065
192181
|
return markerKind === "commentRangeStart" || markerKind === "commentRangeEnd" || markerKind === "commentReference";
|
|
@@ -192110,6 +192226,7 @@ var init_overlap_edit_compiler = __esm(() => {
|
|
|
192110
192226
|
init_word_text_payload();
|
|
192111
192227
|
init_xml_text();
|
|
192112
192228
|
init_xml_sax();
|
|
192229
|
+
init_xml_namespace_scope();
|
|
192113
192230
|
init_word_text_names();
|
|
192114
192231
|
init_paragraph_inline_model();
|
|
192115
192232
|
init_comment_cascade();
|
|
@@ -206730,6 +206847,8 @@ function collectRetiredTrackedChangeCommentMetadataIds(op, logicalCatalog) {
|
|
|
206730
206847
|
return ids;
|
|
206731
206848
|
}
|
|
206732
206849
|
function applyRetiredTrackedChangeCommentMetadataCleanup(args) {
|
|
206850
|
+
if (args.perPart[COMMENTS_PART_URI]?.kind === "remove")
|
|
206851
|
+
return [];
|
|
206733
206852
|
const commentsBytes = args.state.packageBytes.get(COMMENTS_PART_URI);
|
|
206734
206853
|
if (!commentsBytes || args.retiredSourceIds.size === 0)
|
|
206735
206854
|
return [];
|
|
@@ -206831,16 +206950,45 @@ function applyCommentCascade(args) {
|
|
|
206831
206950
|
const next = removeCommentCatalogEntries(TD46.decode(commentsBytes), wids);
|
|
206832
206951
|
if (!next.ok)
|
|
206833
206952
|
return { ok: false, reason: next.reason };
|
|
206834
|
-
const
|
|
206835
|
-
|
|
206836
|
-
|
|
206837
|
-
|
|
206838
|
-
|
|
206839
|
-
|
|
206840
|
-
|
|
206841
|
-
|
|
206842
|
-
|
|
206843
|
-
|
|
206953
|
+
const parsedComments = collectXmlElementRanges(next.xml);
|
|
206954
|
+
const commentsRoot = parsedComments.ranges.find((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "comments");
|
|
206955
|
+
const emptyComments = parsedComments.errors.length === 0 && commentsRoot && next.xml.slice(commentsRoot.openEnd, commentsRoot.closeStart).trim().length === 0;
|
|
206956
|
+
const hasCommentSidecars = args.state.packageBytes.has(COMMENTS_EXTENDED_PART_URI) || args.state.packageBytes.has(COMMENTS_IDS_PART_URI);
|
|
206957
|
+
if (emptyComments && !hasCommentSidecars) {
|
|
206958
|
+
args.perPart[COMMENTS_PART_URI] = { kind: "remove" };
|
|
206959
|
+
args.preconditions.push(byteWindowPrecondition4(COMMENTS_PART_URI, commentsBytes));
|
|
206960
|
+
args.patchMaps[COMMENTS_PART_URI] = { partUri: COMMENTS_PART_URI, ranges: [] };
|
|
206961
|
+
const relsBytes = args.state.packageBytes.get(DOCUMENT_RELS_PART_URI3);
|
|
206962
|
+
if (relsBytes) {
|
|
206963
|
+
const relsXml = currentPartXml(args.state, args.perPart, DOCUMENT_RELS_PART_URI3, XML_TD) ?? XML_TD.decode(relsBytes);
|
|
206964
|
+
const removed = removeRelationshipForPartAndTypeXml({
|
|
206965
|
+
relsXml,
|
|
206966
|
+
ownerPartUri: DOCUMENT_PART_URI,
|
|
206967
|
+
partUri: COMMENTS_PART_URI,
|
|
206968
|
+
relationshipType: COMMENTS_RELATIONSHIP_TYPE
|
|
206969
|
+
});
|
|
206970
|
+
if (!removed.ok)
|
|
206971
|
+
return { ok: false, reason: "unsupported-context" };
|
|
206972
|
+
if (removed.value.xml !== relsXml) {
|
|
206973
|
+
setWholePartReplacement(args, DOCUMENT_RELS_PART_URI3, relsBytes, removed.value.xml);
|
|
206974
|
+
}
|
|
206975
|
+
}
|
|
206976
|
+
const contentTypesBytes = args.state.packageBytes.get(CONTENT_TYPES_PART_URI4);
|
|
206977
|
+
if (contentTypesBytes) {
|
|
206978
|
+
const contentTypesXml = currentPartXml(args.state, args.perPart, CONTENT_TYPES_PART_URI4, XML_TD) ?? XML_TD.decode(contentTypesBytes);
|
|
206979
|
+
const removed = removeContentTypeOverrideXml({
|
|
206980
|
+
contentTypesXml,
|
|
206981
|
+
partName: COMMENTS_PART_URI
|
|
206982
|
+
});
|
|
206983
|
+
if (!removed.ok)
|
|
206984
|
+
return { ok: false, reason: "unsupported-context" };
|
|
206985
|
+
if (removed.value.xml !== contentTypesXml) {
|
|
206986
|
+
setWholePartReplacement(args, CONTENT_TYPES_PART_URI4, contentTypesBytes, removed.value.xml);
|
|
206987
|
+
}
|
|
206988
|
+
}
|
|
206989
|
+
} else {
|
|
206990
|
+
setWholePartReplacement(args, COMMENTS_PART_URI, commentsBytes, next.xml);
|
|
206991
|
+
}
|
|
206844
206992
|
}
|
|
206845
206993
|
const extendedBytes = args.state.packageBytes.get(COMMENTS_EXTENDED_PART_URI);
|
|
206846
206994
|
if (extendedBytes && removedParaIds.size > 0) {
|
|
@@ -209038,7 +209186,7 @@ function dedupeRemappedRefs(refs) {
|
|
|
209038
209186
|
function refKey(ref3) {
|
|
209039
209187
|
return `${ref3.kind}|${ref3.entityId ?? ref3.commentId ?? ""}|${ref3.storyId ?? ""}`;
|
|
209040
209188
|
}
|
|
209041
|
-
var TD46, XML_TD, TE23, DOCUMENT_PART_URI = "/word/document.xml", DOCUMENT_RELS_PART_URI3 = "/word/_rels/document.xml.rels", NUMBERING_PART_URI2 = "/word/numbering.xml", CONTENT_TYPES_PART_URI4 = "/[Content_Types].xml", NUMBERING_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", NOTE_LIFECYCLE_PROVENANCE_NS = "urn:superdoc:note-lifecycle", NOTE_FAMILY_PROFILE, INDEXABLE_STRUCTURAL_KINDS, TRACKED_TABLE_COLUMN_RESTORE_NS = "urn:superdoc:tracked-table-column";
|
|
209189
|
+
var TD46, XML_TD, TE23, DOCUMENT_PART_URI = "/word/document.xml", DOCUMENT_RELS_PART_URI3 = "/word/_rels/document.xml.rels", NUMBERING_PART_URI2 = "/word/numbering.xml", CONTENT_TYPES_PART_URI4 = "/[Content_Types].xml", NUMBERING_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", COMMENTS_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", NOTE_LIFECYCLE_PROVENANCE_NS = "urn:superdoc:note-lifecycle", NOTE_FAMILY_PROFILE, INDEXABLE_STRUCTURAL_KINDS, TRACKED_TABLE_COLUMN_RESTORE_NS = "urn:superdoc:tracked-table-column";
|
|
209042
209190
|
var init_compile_tracked_change_decide = __esm(() => {
|
|
209043
209191
|
init_empty_paragraph_move();
|
|
209044
209192
|
init_native_sdt_ownership();
|
|
@@ -220127,6 +220275,18 @@ function collectProtectedReferenceTokens(xml, referenceSteps) {
|
|
|
220127
220275
|
const tokens = [];
|
|
220128
220276
|
for (let index = 0;index < referenceSteps.length; index += 1) {
|
|
220129
220277
|
const step2 = referenceSteps[index];
|
|
220278
|
+
if (step2.kind === "bookmark-range" || step2.kind === "complex-field") {
|
|
220279
|
+
const fragment2 = step2.beforeFragmentXml;
|
|
220280
|
+
if (!fragment2)
|
|
220281
|
+
return null;
|
|
220282
|
+
const start = xml.indexOf(fragment2);
|
|
220283
|
+
if (start >= 0) {
|
|
220284
|
+
if (xml.indexOf(fragment2, start + fragment2.length) >= 0)
|
|
220285
|
+
return null;
|
|
220286
|
+
tokens.push({ key: `reference:${index}`, start, end: start + fragment2.length, xml: fragment2 });
|
|
220287
|
+
}
|
|
220288
|
+
continue;
|
|
220289
|
+
}
|
|
220130
220290
|
const expectedLocalName = step2.kind === "bookmark-start" ? "bookmarkStart" : "fldSimple";
|
|
220131
220291
|
const parsed = collectXmlElementRanges(xml, {
|
|
220132
220292
|
fragment: true,
|
|
@@ -221281,7 +221441,7 @@ function validateLocalizedMainDocumentReplay(state, sectionSteps, referenceSteps
|
|
|
221281
221441
|
function uniqueLocalizedReplayStart(xml, step2, documentRanges, allowRootNamespaceDeclarations = false) {
|
|
221282
221442
|
const ranges = documentRanges ?? collectXmlElementRanges(xml).ranges;
|
|
221283
221443
|
if (allowRootNamespaceDeclarations && isReferenceReplayStep(step2)) {
|
|
221284
|
-
const expectedLocalName = step2
|
|
221444
|
+
const expectedLocalName = referenceReplayElementName(step2);
|
|
221285
221445
|
const starts2 = ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === expectedLocalName && replayCarrierXmlEquals(xml.slice(range.start, range.end), step2.beforeXml)).map((range) => range.start);
|
|
221286
221446
|
return starts2.length === 1 ? starts2[0] : null;
|
|
221287
221447
|
}
|
|
@@ -221302,7 +221462,7 @@ function isInsideWordElement(ranges, position, localName2) {
|
|
|
221302
221462
|
return ranges.some((range) => range.tag.namespaceUri === NS_W && range.tag.localName === localName2 && range.start < position && range.end > position);
|
|
221303
221463
|
}
|
|
221304
221464
|
function localizedReplayContext(xml, step2, start, documentRanges, allowRootNamespaceDeclarations = false) {
|
|
221305
|
-
const expectedLocalName = isReferenceReplayStep(step2) ? step2
|
|
221465
|
+
const expectedLocalName = isReferenceReplayStep(step2) ? referenceReplayElementName(step2) : "sectPr";
|
|
221306
221466
|
const ranges = documentRanges ?? collectXmlElementRanges(xml).ranges;
|
|
221307
221467
|
const before = ranges.find((range) => range.start === start && range.tag.namespaceUri === NS_W && range.tag.localName === expectedLocalName && (range.end === start + step2.beforeXml.length || allowRootNamespaceDeclarations && isReferenceReplayStep(step2) && replayCarrierXmlEquals(xml.slice(range.start, range.end), step2.beforeXml)));
|
|
221308
221468
|
if (!before)
|
|
@@ -221336,8 +221496,55 @@ function isSafeReferenceReplayStep(step2, context) {
|
|
|
221336
221496
|
const afterName = readResolvedReplayAttribute(context.after, "name");
|
|
221337
221497
|
return afterName !== null && readResolvedReplayAttribute(context.before, "id") === readResolvedReplayAttribute(context.after, "id") && replaceReplayAttribute(step2.beforeXml, context.before, "name", afterName) === step2.afterXml;
|
|
221338
221498
|
}
|
|
221339
|
-
|
|
221340
|
-
|
|
221499
|
+
if (step2.kind === "simple-field") {
|
|
221500
|
+
const instruction = readResolvedReplayAttribute(context.after, "instr");
|
|
221501
|
+
return instruction !== null && /^\s*REF\s+[A-Za-z_][A-Za-z0-9_.]*(?:\s|$)/i.test(instruction) && replaceReplayAttribute(step2.beforeXml, context.before, "instr", instruction) === step2.afterXml;
|
|
221502
|
+
}
|
|
221503
|
+
const beforeFragment = step2.beforeFragmentXml;
|
|
221504
|
+
const afterFragment = step2.afterFragmentXml;
|
|
221505
|
+
if (!beforeFragment || !afterFragment || replaceUniqueReplayFragment(step2.beforeXml, beforeFragment, afterFragment) !== step2.afterXml)
|
|
221506
|
+
return false;
|
|
221507
|
+
if (step2.kind === "bookmark-range") {
|
|
221508
|
+
return isBalancedAddedBookmarkFragment(afterFragment, beforeFragment, context.parentNamespaceBindings);
|
|
221509
|
+
}
|
|
221510
|
+
return isCompleteAddedRefFieldFragment(afterFragment, beforeFragment, context.parentNamespaceBindings);
|
|
221511
|
+
}
|
|
221512
|
+
function referenceReplayElementName(step2) {
|
|
221513
|
+
return step2.kind === "bookmark-start" ? "bookmarkStart" : step2.kind === "simple-field" ? "fldSimple" : "p";
|
|
221514
|
+
}
|
|
221515
|
+
function replaceUniqueReplayFragment(xml, before, after) {
|
|
221516
|
+
const start = xml.indexOf(before);
|
|
221517
|
+
if (start < 0 || xml.indexOf(before, start + before.length) >= 0)
|
|
221518
|
+
return null;
|
|
221519
|
+
return xml.slice(0, start) + after + xml.slice(start + before.length);
|
|
221520
|
+
}
|
|
221521
|
+
function isBalancedAddedBookmarkFragment(xml, expectedContent, namespaceBindings) {
|
|
221522
|
+
const parsed = collectXmlElementRanges(xml, { fragment: true, additionalNamespaces: { ...namespaceBindings } });
|
|
221523
|
+
if (parsed.errors.length > 0)
|
|
221524
|
+
return false;
|
|
221525
|
+
const starts = parsed.ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "bookmarkStart");
|
|
221526
|
+
const ends = parsed.ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "bookmarkEnd");
|
|
221527
|
+
if (starts.length !== 1 || ends.length !== 1 || !starts[0].tag.isSelfClosing || !ends[0].tag.isSelfClosing)
|
|
221528
|
+
return false;
|
|
221529
|
+
const id = readResolvedReplayAttribute(starts[0], "id");
|
|
221530
|
+
return id !== null && readResolvedReplayAttribute(starts[0], "name") !== null && readResolvedReplayAttribute(ends[0], "id") === id && xml.slice(starts[0].end, ends[0].start) === expectedContent;
|
|
221531
|
+
}
|
|
221532
|
+
function isCompleteAddedRefFieldFragment(xml, expectedResult, namespaceBindings) {
|
|
221533
|
+
const parsed = collectXmlElementRanges(xml, { fragment: true, additionalNamespaces: { ...namespaceBindings } });
|
|
221534
|
+
if (parsed.errors.length > 0)
|
|
221535
|
+
return false;
|
|
221536
|
+
const chars = parsed.ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "fldChar");
|
|
221537
|
+
const types4 = chars.map((range) => readResolvedReplayAttribute(range, "fldCharType"));
|
|
221538
|
+
if (types4.length !== 3 || types4.join(",") !== "begin,separate,end")
|
|
221539
|
+
return false;
|
|
221540
|
+
const instruction = parsed.ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "instrText" && range.start > chars[0].end && range.end < chars[1].start).map((range) => xml.slice(range.start, range.end).replace(/^<[^>]+>|<\/[^>]+>$/g, "")).join("");
|
|
221541
|
+
return /^\s*REF\s+[A-Za-z_][A-Za-z0-9_.]*(?:\s|$)/i.test(instruction) && xml.slice(parentRunEnd(parsed.ranges, chars[1]), parentRunStart(parsed.ranges, chars[2])) === expectedResult;
|
|
221542
|
+
}
|
|
221543
|
+
function parentRunStart(ranges, child) {
|
|
221544
|
+
return ranges.find((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "r" && range.start <= child.start && range.end >= child.end)?.start ?? -1;
|
|
221545
|
+
}
|
|
221546
|
+
function parentRunEnd(ranges, child) {
|
|
221547
|
+
return ranges.find((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "r" && range.start <= child.start && range.end >= child.end)?.end ?? -1;
|
|
221341
221548
|
}
|
|
221342
221549
|
function isReferenceReplayStep(step2) {
|
|
221343
221550
|
return "kind" in step2;
|
|
@@ -221455,6 +221662,13 @@ function renderTrackedSectionReplay(step2, stamp, context) {
|
|
|
221455
221662
|
return step2.afterXml.slice(0, close) + marker + step2.afterXml.slice(close);
|
|
221456
221663
|
}
|
|
221457
221664
|
function renderTrackedReferenceReplay(step2, stamps, context) {
|
|
221665
|
+
if (step2.kind === "bookmark-range" || step2.kind === "complex-field") {
|
|
221666
|
+
const beforeFragment = step2.beforeFragmentXml;
|
|
221667
|
+
const afterFragment = step2.afterFragmentXml;
|
|
221668
|
+
const deletionXml2 = renameWordTextElementsToDeletedText(beforeFragment, context.parentNamespaceBindings);
|
|
221669
|
+
const tracked = renderTrackedWrapper("del", deletionXml2, stamps.del, context) + renderTrackedWrapper("ins", afterFragment, stamps.ins, context);
|
|
221670
|
+
return replaceUniqueReplayFragment(step2.beforeXml, beforeFragment, tracked) ?? step2.beforeXml;
|
|
221671
|
+
}
|
|
221458
221672
|
const deletionXml = step2.kind === "simple-field" ? renameWordTextElementsToDeletedText(step2.beforeXml, context.parentNamespaceBindings) : step2.beforeXml;
|
|
221459
221673
|
return renderTrackedWrapper("del", deletionXml, stamps.del, context) + renderTrackedWrapper("ins", step2.afterXml, stamps.ins, context);
|
|
221460
221674
|
}
|
|
@@ -221544,7 +221758,7 @@ function validateTableTopologySteps(state, changeMode, steps) {
|
|
|
221544
221758
|
if (deletedRows.has(key2) || step2.rowsXml.length !== 1 || table.rows.length <= 1)
|
|
221545
221759
|
return false;
|
|
221546
221760
|
const rowXml = TD58.decode(partBytes.subarray(anchor.row.rowByteStart, anchor.row.rowByteEnd));
|
|
221547
|
-
if (step2.rowsXml[0] !== rowXml || !
|
|
221761
|
+
if (step2.rowsXml[0] !== rowXml || !isNamespaceSafeWordprocessingRow(rowXml, namespaceBindings))
|
|
221548
221762
|
return false;
|
|
221549
221763
|
const parsed = collectXmlElementRanges(rowXml, { fragment: true, additionalNamespaces: { ...namespaceBindings } });
|
|
221550
221764
|
if (parsed.errors.length || parsed.ranges.some((range) => range.tag.namespaceUri === NS_W && [
|
|
@@ -221555,7 +221769,6 @@ function validateTableTopologySteps(state, changeMode, steps) {
|
|
|
221555
221769
|
"commentReference",
|
|
221556
221770
|
"footnoteReference",
|
|
221557
221771
|
"endnoteReference",
|
|
221558
|
-
"sdt",
|
|
221559
221772
|
"fldSimple",
|
|
221560
221773
|
"fldChar"
|
|
221561
221774
|
].includes(range.tag.localName)))
|
|
@@ -228918,7 +229131,7 @@ function planParagraphSplice(input) {
|
|
|
228918
229131
|
};
|
|
228919
229132
|
return input.trackedStamp ? renderTrackedPasteParagraphBlock(spec, input.trackedStamp) : renderPasteParagraphBlock(spec);
|
|
228920
229133
|
};
|
|
228921
|
-
const mergeable = (block) => block.kind === "paragraph" && !block.styleRef && !block.numbering && !block.listIntent && !block.paragraphProps && !block.pPrXml && !block.complete;
|
|
229134
|
+
const mergeable = (block) => block.kind === "paragraph" && !block.styleRef && !block.numbering && !block.listIntent && !block.paragraphProps && !block.pPrXml && !block.blockSdts?.length && !block.complete;
|
|
228922
229135
|
const paragraphs = [];
|
|
228923
229136
|
if (blocks.length === 1 && mergeable(blocks[0])) {
|
|
228924
229137
|
if (anchorParaId)
|
|
@@ -228937,10 +229150,13 @@ function planParagraphSplice(input) {
|
|
|
228937
229150
|
paragraphs.push(headOpen + headPPr + split.headXml + (mergeFirst ? runsOf(blocks[0]) : "") + envelope.close);
|
|
228938
229151
|
}
|
|
228939
229152
|
const middleStart = mergeFirst ? 1 : 0;
|
|
229153
|
+
const middleXml = [];
|
|
228940
229154
|
for (let middleIndex = 0;middleIndex < middleBlocks.length; middleIndex += 1) {
|
|
228941
229155
|
const block = middleBlocks[middleIndex];
|
|
228942
|
-
|
|
229156
|
+
middleXml.push(standalone(block, middleStart + middleIndex, mergeable(block) ? envelope.pPr : undefined));
|
|
228943
229157
|
}
|
|
229158
|
+
if (middleXml.length)
|
|
229159
|
+
paragraphs.push(renderBlockSdtSequence(middleBlocks, middleXml, input.blockSdtIds ?? new Map));
|
|
228944
229160
|
const tailRunsXml = (mergeLast ? runsOf(blocks[blocks.length - 1]) : "") + split.tailXml;
|
|
228945
229161
|
if (mergeLast || split.tailXml.length > 0) {
|
|
228946
229162
|
const tailOpen = relocateEmptyAnchor ? envelope.open : withParaId(envelope.open, mintId(), input.partBytes, input.paragraphStartByte);
|
|
@@ -231243,6 +231459,10 @@ function preflightFragmentApply(input) {
|
|
|
231243
231459
|
const target = resolveFragmentApplyTarget(state, op);
|
|
231244
231460
|
if (!target.ok)
|
|
231245
231461
|
return target;
|
|
231462
|
+
if (isTextTarget2(op.target) && op.formattingMode === "match-destination" && op.fragment.blocks.some((block) => (block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length))
|
|
231463
|
+
return { ok: false, reason: "paste-structure-unsupported" };
|
|
231464
|
+
if ((op.changeMode ?? "direct") === "tracked" && op.fragment.blocks.some((block) => (block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length))
|
|
231465
|
+
return { ok: false, reason: "paste-tracked-structural-unsupported" };
|
|
231246
231466
|
if ((op.changeMode ?? "direct") === "tracked" && target.target.kind === "block" && target.target.blockKind === "table" && !trackedWholeTableRowsAreDirectChildren(state, target.target)) {
|
|
231247
231467
|
return { ok: false, reason: "paste-tracked-structural-unsupported" };
|
|
231248
231468
|
}
|
|
@@ -231507,6 +231727,8 @@ function validateFragmentRangeIntegrity(input) {
|
|
|
231507
231727
|
}
|
|
231508
231728
|
function fragmentRequiresCommit5Materialization(blocks) {
|
|
231509
231729
|
for (const block of blocks) {
|
|
231730
|
+
if ((block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length)
|
|
231731
|
+
return true;
|
|
231510
231732
|
if (block.kind === "heading" || block.kind === "horizontalRule")
|
|
231511
231733
|
return true;
|
|
231512
231734
|
if (block.kind === "table") {
|
|
@@ -231526,7 +231748,7 @@ function fragmentRequiresCommit5Materialization(blocks) {
|
|
|
231526
231748
|
return false;
|
|
231527
231749
|
}
|
|
231528
231750
|
function paragraphHasFutureInline(block) {
|
|
231529
|
-
return block.paragraphProps !== undefined || block.listIntent?.start !== undefined || (block.inlines?.some((inline) => inline.kind === "lineBreak" || inline.kind === "hyperlink" || inline.kind === "footnoteRef" || inline.kind === "endnoteRef") ?? false);
|
|
231751
|
+
return block.paragraphProps !== undefined || block.listIntent?.start !== undefined || (block.inlines?.some((inline) => inline.kind === "lineBreak" || inline.kind === "hyperlink" || inline.kind === "sdt" || inline.kind === "footnoteRef" || inline.kind === "endnoteRef") ?? false);
|
|
231530
231752
|
}
|
|
231531
231753
|
function collectFragmentSourcePaths(blocks) {
|
|
231532
231754
|
const paths = [];
|
|
@@ -232037,6 +232259,7 @@ function runWholeStoryReplaceCommit(input, target, blocks, extras, inlineExtras)
|
|
|
232037
232259
|
state,
|
|
232038
232260
|
blocks,
|
|
232039
232261
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
232262
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232040
232263
|
partBytes: bytes,
|
|
232041
232264
|
insertionByte: target.byteStart,
|
|
232042
232265
|
ordinalSeed: 0,
|
|
@@ -232275,7 +232498,7 @@ function renderCompletePasteFragment(input) {
|
|
|
232275
232498
|
renderedBlocks.push(xml);
|
|
232276
232499
|
}
|
|
232277
232500
|
return {
|
|
232278
|
-
xml: renderedBlocks.
|
|
232501
|
+
xml: renderBlockSdtSequence(input.blocks, renderedBlocks, input.blockSdtIds),
|
|
232279
232502
|
createdParaIds,
|
|
232280
232503
|
destinationParaIdsByBlock
|
|
232281
232504
|
};
|
|
@@ -232307,6 +232530,7 @@ function runParagraphBlockPasteCommit(input, target, blocks, extras, inlineExtra
|
|
|
232307
232530
|
state,
|
|
232308
232531
|
blocks,
|
|
232309
232532
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
232533
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232310
232534
|
partBytes: bytes,
|
|
232311
232535
|
insertionByte: target.placement === "after" ? anchor.byteEnd : anchor.byteStart,
|
|
232312
232536
|
ordinalSeed: anchor.ordinal,
|
|
@@ -232475,6 +232699,7 @@ function runWholeTableReplaceCommit(input, target, blocks, extras, inlineExtras)
|
|
|
232475
232699
|
state,
|
|
232476
232700
|
blocks,
|
|
232477
232701
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
232702
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232478
232703
|
partBytes: bytes,
|
|
232479
232704
|
insertionByte: target.byteStart,
|
|
232480
232705
|
ordinalSeed: replacedParagraphs[0]?.ordinal ?? 0,
|
|
@@ -232644,6 +232869,7 @@ function runCrossParagraphTrackedPasteCommit(input, target, blocks, extras, inli
|
|
|
232644
232869
|
paragraphStartByte: start.byteStart,
|
|
232645
232870
|
mintParaId: () => mintParaId(state, state.packageRevision, start.ordinal + 1 + (mintSalt += 1)),
|
|
232646
232871
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
232872
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232647
232873
|
trackedStamp: stamp,
|
|
232648
232874
|
wrapAllTracked: true,
|
|
232649
232875
|
...extras.commentIdMap ? { commentIdMap: extras.commentIdMap } : {},
|
|
@@ -232772,6 +232998,7 @@ function runCrossParagraphPasteCommit(input, target, blocks, extras, inlineExtra
|
|
|
232772
232998
|
paragraphStartByte: start.byteStart,
|
|
232773
232999
|
mintParaId: () => mintParaId(state, state.packageRevision, start.ordinal + 1 + (mintSalt += 1)),
|
|
232774
233000
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
233001
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232775
233002
|
...extras.commentIdMap ? { commentIdMap: extras.commentIdMap } : {},
|
|
232776
233003
|
...extras.noteIdMap ? { noteIdMap: extras.noteIdMap } : {}
|
|
232777
233004
|
});
|
|
@@ -233418,6 +233645,7 @@ function runPasteSpliceCommit(input, target, resolvedBlocks, listExtras, imageEx
|
|
|
233418
233645
|
paragraphStartByte,
|
|
233419
233646
|
mintParaId: mintParaId3,
|
|
233420
233647
|
inlineSpecs: imageExtras.inlineSpecs,
|
|
233648
|
+
blockSdtIds: imageExtras.blockSdtIds,
|
|
233421
233649
|
...stamp ? { trackedStamp: stamp, wrapAllTracked } : {},
|
|
233422
233650
|
...listExtras.commentIdMap ? { commentIdMap: listExtras.commentIdMap } : {},
|
|
233423
233651
|
...listExtras.noteIdMap ? { noteIdMap: listExtras.noteIdMap } : {}
|
|
@@ -233654,6 +233882,8 @@ function validateImageFragment(fragment2) {
|
|
|
233654
233882
|
continue;
|
|
233655
233883
|
if (inline.kind === "footnoteRef" || inline.kind === "endnoteRef")
|
|
233656
233884
|
continue;
|
|
233885
|
+
if (inline.kind === "sdt")
|
|
233886
|
+
continue;
|
|
233657
233887
|
if (inline.kind === "hyperlink") {
|
|
233658
233888
|
if (inline.inlines.some((child) => child.kind === "image")) {
|
|
233659
233889
|
return { ok: false, reason: "paste-structure-unsupported" };
|
|
@@ -233674,7 +233904,7 @@ function validateImageFragment(fragment2) {
|
|
|
233674
233904
|
function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMode, relationshipHyperlinks, hyperlinkCharacterStyleId, preparedPackageXml) {
|
|
233675
233905
|
const inlineParagraphs = [];
|
|
233676
233906
|
for (const block of blocks) {
|
|
233677
|
-
if (block.kind === "paragraph" && block.inlines)
|
|
233907
|
+
if (block.kind === "paragraph" && (block.inlines || block.blockSdts?.length))
|
|
233678
233908
|
inlineParagraphs.push(block);
|
|
233679
233909
|
if (block.kind === "table") {
|
|
233680
233910
|
for (const row of block.rows) {
|
|
@@ -233687,7 +233917,7 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
|
|
|
233687
233917
|
}
|
|
233688
233918
|
}
|
|
233689
233919
|
if (inlineParagraphs.length === 0) {
|
|
233690
|
-
return { ok: true, value: { inlineSpecs: new Map, partUris: [], perPart: {}, preconditions: [], patchMaps: {} } };
|
|
233920
|
+
return { ok: true, value: { inlineSpecs: new Map, blockSdtIds: new Map, partUris: [], perPart: {}, preconditions: [], patchMaps: {} } };
|
|
233691
233921
|
}
|
|
233692
233922
|
const assets = new Map((fragment2.assets ?? []).map((asset) => [asset.id, asset]));
|
|
233693
233923
|
const hasImages = inlineParagraphs.some((paragraph) => paragraph.inlines?.some((inline) => inline.kind === "image"));
|
|
@@ -233782,6 +234012,43 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
|
|
|
233782
234012
|
}
|
|
233783
234013
|
let docPrId = allocateDocPrId(state, storyId);
|
|
233784
234014
|
const inlineSpecs = new Map;
|
|
234015
|
+
const hasControls = inlineParagraphs.some((paragraph) => paragraph.blockSdts?.length || paragraph.inlines?.some((inline) => inline.kind === "sdt"));
|
|
234016
|
+
const usedControlIds = new Set;
|
|
234017
|
+
if (hasControls) {
|
|
234018
|
+
for (const [uri, bytes] of state.packageBytes) {
|
|
234019
|
+
if (!uri.endsWith(".xml"))
|
|
234020
|
+
continue;
|
|
234021
|
+
const xml = TD64.decode(bytes);
|
|
234022
|
+
for (const match of xml.matchAll(/<w:sdtPr\b[^>]*>[\s\S]*?<w:id\b[^>]*\bw:val=(['"])(\d+)\1/g)) {
|
|
234023
|
+
const id = Number(match[2]);
|
|
234024
|
+
if (Number.isSafeInteger(id) && id > 0)
|
|
234025
|
+
usedControlIds.add(id);
|
|
234026
|
+
}
|
|
234027
|
+
}
|
|
234028
|
+
}
|
|
234029
|
+
let nextControlId = 1002;
|
|
234030
|
+
for (const id of usedControlIds)
|
|
234031
|
+
if (id >= nextControlId)
|
|
234032
|
+
nextControlId = id + 1;
|
|
234033
|
+
const mintControlId = () => {
|
|
234034
|
+
if (nextControlId > 2147483647)
|
|
234035
|
+
nextControlId = 1;
|
|
234036
|
+
while (usedControlIds.has(nextControlId)) {
|
|
234037
|
+
nextControlId += 1;
|
|
234038
|
+
if (nextControlId > 2147483647)
|
|
234039
|
+
nextControlId = 1;
|
|
234040
|
+
}
|
|
234041
|
+
const id = nextControlId++;
|
|
234042
|
+
usedControlIds.add(id);
|
|
234043
|
+
return String(id);
|
|
234044
|
+
};
|
|
234045
|
+
const blockSdtIds = new Map;
|
|
234046
|
+
for (const paragraph of inlineParagraphs) {
|
|
234047
|
+
for (const wrapper of paragraph.blockSdts ?? []) {
|
|
234048
|
+
if (!blockSdtIds.has(wrapper.sourceId))
|
|
234049
|
+
blockSdtIds.set(wrapper.sourceId, mintControlId());
|
|
234050
|
+
}
|
|
234051
|
+
}
|
|
233785
234052
|
const leafSpec = (inline) => {
|
|
233786
234053
|
if (inline.kind === "text")
|
|
233787
234054
|
return toPasteTextRunSpec(inline);
|
|
@@ -233802,37 +234069,68 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
|
|
|
233802
234069
|
})
|
|
233803
234070
|
};
|
|
233804
234071
|
};
|
|
234072
|
+
const sdtSpec = (inline) => ({
|
|
234073
|
+
kind: "sdt",
|
|
234074
|
+
id: mintControlId(),
|
|
234075
|
+
controlType: inline.controlType,
|
|
234076
|
+
...inline.tag !== undefined ? { tag: inline.tag } : {},
|
|
234077
|
+
...inline.alias !== undefined ? { alias: inline.alias } : {},
|
|
234078
|
+
...inline.lockMode !== undefined ? { lockMode: inline.lockMode } : {},
|
|
234079
|
+
...inline.multiline !== undefined ? { multiline: inline.multiline } : {},
|
|
234080
|
+
runs: inline.inlines.map((child) => child.kind === "sdt" ? sdtSpec(child) : leafSpec(child))
|
|
234081
|
+
});
|
|
234082
|
+
const inlineSpec = (inline) => {
|
|
234083
|
+
if (inline.kind === "sdt")
|
|
234084
|
+
return sdtSpec(inline);
|
|
234085
|
+
if (inline.kind === "footnoteRef" || inline.kind === "endnoteRef") {
|
|
234086
|
+
return { kind: inline.kind, noteId: inline.noteId };
|
|
234087
|
+
}
|
|
234088
|
+
if (inline.kind !== "hyperlink")
|
|
234089
|
+
return leafSpec(inline);
|
|
234090
|
+
const target = inline.target.kind === "external" ? {
|
|
234091
|
+
kind: "external",
|
|
234092
|
+
url: inline.target.url,
|
|
234093
|
+
...relationshipHyperlinks ? { relationshipId: hyperlinkRelationshipIds.get(inline) } : {}
|
|
234094
|
+
} : { kind: "anchor", anchor: inline.target.anchor };
|
|
234095
|
+
return {
|
|
234096
|
+
kind: "hyperlink",
|
|
234097
|
+
target,
|
|
234098
|
+
...inline.tooltip ? { tooltip: inline.tooltip } : {},
|
|
234099
|
+
...hyperlinkCharacterStyleId ? { characterStyleId: hyperlinkCharacterStyleId } : {},
|
|
234100
|
+
runs: inline.inlines.map(leafSpec)
|
|
234101
|
+
};
|
|
234102
|
+
};
|
|
233805
234103
|
for (const paragraph of inlineParagraphs) {
|
|
233806
|
-
|
|
233807
|
-
|
|
233808
|
-
return { kind: inline.kind, noteId: inline.noteId };
|
|
233809
|
-
}
|
|
233810
|
-
if (inline.kind !== "hyperlink")
|
|
233811
|
-
return leafSpec(inline);
|
|
233812
|
-
const target = inline.target.kind === "external" ? {
|
|
233813
|
-
kind: "external",
|
|
233814
|
-
url: inline.target.url,
|
|
233815
|
-
...relationshipHyperlinks ? { relationshipId: hyperlinkRelationshipIds.get(inline) } : {}
|
|
233816
|
-
} : { kind: "anchor", anchor: inline.target.anchor };
|
|
233817
|
-
return {
|
|
233818
|
-
kind: "hyperlink",
|
|
233819
|
-
target,
|
|
233820
|
-
...inline.tooltip ? { tooltip: inline.tooltip } : {},
|
|
233821
|
-
...hyperlinkCharacterStyleId ? { characterStyleId: hyperlinkCharacterStyleId } : {},
|
|
233822
|
-
runs: inline.inlines.map(leafSpec)
|
|
233823
|
-
};
|
|
233824
|
-
}));
|
|
234104
|
+
if (paragraph.inlines)
|
|
234105
|
+
inlineSpecs.set(paragraph, paragraph.inlines.map(inlineSpec));
|
|
233825
234106
|
}
|
|
233826
234107
|
const preconditions = [];
|
|
233827
234108
|
if (relsUri && relsBytes && (hasImages || hasExternalLinks))
|
|
233828
234109
|
preconditions.push(byteWindowPrecondition7(relsUri, relsBytes));
|
|
233829
234110
|
if (contentTypesChanged && contentTypesBytes)
|
|
233830
234111
|
preconditions.push(byteWindowPrecondition7(CONTENT_TYPES_PART_URI11, contentTypesBytes));
|
|
233831
|
-
return { ok: true, value: { inlineSpecs, partUris: packagePartUris, perPart, preconditions, patchMaps: {} } };
|
|
234112
|
+
return { ok: true, value: { inlineSpecs, blockSdtIds, partUris: packagePartUris, perPart, preconditions, patchMaps: {} } };
|
|
233832
234113
|
}
|
|
233833
234114
|
function validateBlocks(blocks) {
|
|
233834
234115
|
const budget = { totalChars: 0, hyperlinkRefs: 0, sourcePaths: new Set };
|
|
234116
|
+
const closedControls = new Set;
|
|
234117
|
+
let activeControls = [];
|
|
233835
234118
|
for (const block of blocks) {
|
|
234119
|
+
const controls = block.kind === "paragraph" || block.kind === "heading" ? block.blockSdts ?? [] : [];
|
|
234120
|
+
if (controls.length && (block.kind !== "paragraph" && block.kind !== "heading" || !block.complete || controls.length > 16)) {
|
|
234121
|
+
return { ok: false, reason: "paste-structure-unsupported" };
|
|
234122
|
+
}
|
|
234123
|
+
let common = 0;
|
|
234124
|
+
while (common < controls.length && common < activeControls.length && controls[common].sourceId === activeControls[common].sourceId && controls[common].controlType === activeControls[common].controlType && controls[common].tag === activeControls[common].tag && controls[common].alias === activeControls[common].alias)
|
|
234125
|
+
common += 1;
|
|
234126
|
+
for (const wrapper of activeControls.slice(common))
|
|
234127
|
+
closedControls.add(wrapper.sourceId);
|
|
234128
|
+
for (const wrapper of controls.slice(common)) {
|
|
234129
|
+
if (!/^[0-9]{1,10}$/.test(wrapper.sourceId) || closedControls.has(wrapper.sourceId) || controls.filter((candidate2) => candidate2.sourceId === wrapper.sourceId).length !== 1 || wrapper.controlType !== "text" && wrapper.controlType !== "richText" || !isValidOptionalXmlAttributeText(wrapper.tag, 255) || !isValidOptionalXmlAttributeText(wrapper.alias, 255)) {
|
|
234130
|
+
return { ok: false, reason: "paste-structure-unsupported" };
|
|
234131
|
+
}
|
|
234132
|
+
}
|
|
234133
|
+
activeControls = controls;
|
|
233836
234134
|
if (!recordSourcePath(block.sourcePath, budget.sourcePaths)) {
|
|
233837
234135
|
return { ok: false, reason: "paste-structure-unsupported" };
|
|
233838
234136
|
}
|
|
@@ -233896,6 +234194,9 @@ function validateBlocks(blocks) {
|
|
|
233896
234194
|
if (cellBlock.kind !== "paragraph") {
|
|
233897
234195
|
return { ok: false, reason: "paste-structure-unsupported" };
|
|
233898
234196
|
}
|
|
234197
|
+
if (cellBlock.blockSdts?.length) {
|
|
234198
|
+
return { ok: false, reason: "paste-structure-unsupported" };
|
|
234199
|
+
}
|
|
233899
234200
|
if (!recordSourcePath(cellBlock.sourcePath, budget.sourcePaths)) {
|
|
233900
234201
|
return { ok: false, reason: "paste-structure-unsupported" };
|
|
233901
234202
|
}
|
|
@@ -234029,9 +234330,14 @@ function validateParagraphBlock(block, budget) {
|
|
|
234029
234330
|
}
|
|
234030
234331
|
return { ok: true };
|
|
234031
234332
|
}
|
|
234032
|
-
function validatePasteInline(inline, budget) {
|
|
234333
|
+
function validatePasteInline(inline, budget, depth = 0) {
|
|
234334
|
+
if (depth > 32)
|
|
234335
|
+
return false;
|
|
234033
234336
|
if (!recordSourcePath(inline.sourcePath, budget.sourcePaths))
|
|
234034
234337
|
return false;
|
|
234338
|
+
if (inline.kind === "sdt") {
|
|
234339
|
+
return (inline.controlType === "text" || inline.controlType === "richText") && isValidOptionalXmlAttributeText(inline.tag, 255) && isValidOptionalXmlAttributeText(inline.alias, 255) && Array.isArray(inline.inlines) && inline.inlines.length > 0 && inline.inlines.every((child) => child.kind === "text" || child.kind === "lineBreak" || child.kind === "sdt") && inline.inlines.every((child) => validatePasteInline(child, budget, depth + 1));
|
|
234340
|
+
}
|
|
234035
234341
|
if (inline.kind === "text") {
|
|
234036
234342
|
return typeof inline.text === "string" && !hasUnsupportedControlChar(inline.text) && isValidPasteRunMarks(inline.marks);
|
|
234037
234343
|
}
|
|
@@ -234057,7 +234363,7 @@ function validatePasteInline(inline, budget) {
|
|
|
234057
234363
|
} else if (inline.target.kind !== "anchor" || typeof inline.target.anchor !== "string" || inline.target.anchor.length === 0 || inline.target.anchor.length > MAX_HYPERLINK_ANCHOR_CHARS || hasUnsupportedXmlAttributeChar(inline.target.anchor)) {
|
|
234058
234364
|
return false;
|
|
234059
234365
|
}
|
|
234060
|
-
return inline.inlines.every((child) => validatePasteInline(child, budget));
|
|
234366
|
+
return inline.inlines.every((child) => validatePasteInline(child, budget, depth + 1));
|
|
234061
234367
|
}
|
|
234062
234368
|
function rewritePastePPrStyleRef(pPrXml, styleId) {
|
|
234063
234369
|
const escaped = styleId.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -234069,7 +234375,13 @@ function rewritePastePPrStyleRef(pPrXml, styleId) {
|
|
|
234069
234375
|
function hasMatchingInlineTextProjection(block) {
|
|
234070
234376
|
if (!Array.isArray(block.inlines))
|
|
234071
234377
|
return false;
|
|
234072
|
-
const textInlines = block.inlines.flatMap((inline)
|
|
234378
|
+
const textInlines = block.inlines.flatMap(function project(inline) {
|
|
234379
|
+
if (inline.kind === "text")
|
|
234380
|
+
return [inline];
|
|
234381
|
+
if (inline.kind === "hyperlink" || inline.kind === "sdt")
|
|
234382
|
+
return inline.inlines.flatMap(project);
|
|
234383
|
+
return [];
|
|
234384
|
+
});
|
|
234073
234385
|
return textInlines.length === block.runs.length && textInlines.every((inline, index) => {
|
|
234074
234386
|
const run = block.runs[index];
|
|
234075
234387
|
return inline.text === run.text && haveEqualRunMarks(inline.marks, run.marks);
|
|
@@ -247145,12 +247457,13 @@ function prepareHistoryReplayMutation(state, entry, direction, patchGroup) {
|
|
|
247145
247457
|
const controlBytes = controlOwner && state.packageBytes.get(controlOwner.partUri);
|
|
247146
247458
|
const controlPatch = controlOwner && patchGroup.perPart[controlOwner.partUri];
|
|
247147
247459
|
const contentControlRewrite = patchGroup.source.kind === "storySurfaceRewrite" && patchGroup.source.contentControlRewrite && controlBytes && controlPatch ? prepareContentControlRewrite(controlBytes, controlPatch) : null;
|
|
247460
|
+
const declaredStorySurfaceTargetBlockIds = patchGroup.source.kind === "storySurfaceRewrite" ? [...new Set(patchGroup.source.targetBlockIds)] : [];
|
|
247148
247461
|
const targetBlockIds2 = contentControlRewrite ? [...new Set([
|
|
247149
247462
|
...contentControlRewrite.removedBlockIds,
|
|
247150
247463
|
...contentControlRewrite.addedBlockIds,
|
|
247151
247464
|
...contentControlRewrite.contentBlockIds,
|
|
247152
247465
|
...contentControlRewrite.leadingBlockIds
|
|
247153
|
-
])] : patchGroup.source.kind === "compareApply" ? [...new Set(patchGroup.source.bodySteps.map((step2) => step2.blockId))] : collectPatchGroupTargetBlockIds(patchGroup);
|
|
247466
|
+
])] : patchGroup.source.kind === "compareApply" ? [...new Set(patchGroup.source.bodySteps.map((step2) => step2.blockId))] : declaredStorySurfaceTargetBlockIds.length > 0 ? declaredStorySurfaceTargetBlockIds : collectPatchGroupTargetBlockIds(patchGroup);
|
|
247154
247467
|
const currentBaseRevisions = {
|
|
247155
247468
|
package: state.packageRevision,
|
|
247156
247469
|
perPart: {}
|
|
@@ -291329,7 +291642,7 @@ class V2SelectionMutationAdapter {
|
|
|
291329
291642
|
const buildResolutionMs = nowMs6() - buildResolutionStartedAt;
|
|
291330
291643
|
let replacements = resolved.coordinateSpace !== "tracked" && resolved.startOffset < resolved.endOffset && selectedText.length === resolved.endOffset - resolved.startOffset && isPlannableTextPayload(request.text) ? planTrackedRewriteReplacement(selectedText, request.text) : [{ start: 0, end: resolved.endOffset - resolved.startOffset, text: request.text }];
|
|
291331
291644
|
let structuralRewrite = false;
|
|
291332
|
-
if (options?.changeMode === "tracked" &&
|
|
291645
|
+
if (options?.changeMode === "tracked" && replacements.length > 1) {
|
|
291333
291646
|
const paragraphBytes = getSDDocumentSessionInternalPartRange(this.context.session, resolved.partUri, resolved.paragraphByteStart ?? resolved.startByte, resolved.paragraphByteEnd ?? resolved.endByte);
|
|
291334
291647
|
if (paragraphBytes) {
|
|
291335
291648
|
const scopedReplacements = planTrackedRewriteReplacement(selectedText, request.text, {
|
|
@@ -326296,8 +326609,8 @@ function lowerInline(inline, path7, images) {
|
|
|
326296
326609
|
}
|
|
326297
326610
|
function lowerHyperlinkChild(inline, path7, images) {
|
|
326298
326611
|
const lowered = lowerInline(inline, path7, images);
|
|
326299
|
-
if (lowered.kind === "hyperlink")
|
|
326300
|
-
unsupported4(path7, "Nested hyperlinks are not supported.");
|
|
326612
|
+
if (lowered.kind === "hyperlink" || lowered.kind === "sdt")
|
|
326613
|
+
unsupported4(path7, "Nested hyperlinks and content controls are not supported.");
|
|
326301
326614
|
if (lowered.kind === "footnoteRef" || lowered.kind === "endnoteRef") {
|
|
326302
326615
|
unsupported4(path7, "Note references cannot be nested inside hyperlinks.");
|
|
326303
326616
|
}
|
|
@@ -345491,40 +345804,63 @@ class V2ImagesAdapter {
|
|
|
345491
345804
|
return trackedTarget;
|
|
345492
345805
|
return this.createTrackedBodyImage(input, options, trackedTarget, decoded, requestedSize);
|
|
345493
345806
|
}
|
|
345494
|
-
const
|
|
345495
|
-
|
|
345496
|
-
|
|
345497
|
-
|
|
345498
|
-
|
|
345499
|
-
|
|
345500
|
-
|
|
345501
|
-
|
|
345502
|
-
|
|
345503
|
-
|
|
345504
|
-
|
|
345505
|
-
|
|
345506
|
-
|
|
345507
|
-
|
|
345508
|
-
|
|
345509
|
-
|
|
345510
|
-
|
|
345511
|
-
|
|
345512
|
-
|
|
345513
|
-
|
|
345514
|
-
|
|
345807
|
+
const abortCapture = Symbol("create.image.abort");
|
|
345808
|
+
const imageFormat = decoded.format;
|
|
345809
|
+
let capturedTxIds = [];
|
|
345810
|
+
let failure8 = null;
|
|
345811
|
+
let published = null;
|
|
345812
|
+
try {
|
|
345813
|
+
published = this.context.captureCommittedHistory((txIds) => {
|
|
345814
|
+
capturedTxIds = txIds;
|
|
345815
|
+
const resolved = this.resolveCreateImageTarget(input, options);
|
|
345816
|
+
if (!resolved.success) {
|
|
345817
|
+
failure8 = resolved;
|
|
345818
|
+
throw abortCapture;
|
|
345819
|
+
}
|
|
345820
|
+
const inserted = this.insertInline({
|
|
345821
|
+
storyId: resolved.storyId,
|
|
345822
|
+
paraId: resolved.paraId,
|
|
345823
|
+
offset: resolved.offset,
|
|
345824
|
+
binary: decoded.binary,
|
|
345825
|
+
format: imageFormat,
|
|
345826
|
+
widthPx: requestedSize.widthPx,
|
|
345827
|
+
heightPx: requestedSize.heightPx,
|
|
345828
|
+
name: input.alt ?? input.title
|
|
345829
|
+
});
|
|
345830
|
+
if (!inserted.success) {
|
|
345831
|
+
failure8 = createImageFailure(inserted.failure.code, inserted.failure.message);
|
|
345832
|
+
throw abortCapture;
|
|
345833
|
+
}
|
|
345834
|
+
let entry = this.findInsertedImageEntry(resolved.storyId, resolved.paraId, inserted.imageNodeId);
|
|
345835
|
+
if (entry && (input.title || input.alt)) {
|
|
345836
|
+
const metadata2 = this.setAltText({
|
|
345837
|
+
imageId: entry.publicId,
|
|
345838
|
+
description: input.title ?? input.alt ?? ""
|
|
345839
|
+
});
|
|
345840
|
+
if (!metadata2.success) {
|
|
345841
|
+
failure8 = createImageFailure(metadata2.failure.code, metadata2.failure.message);
|
|
345842
|
+
throw abortCapture;
|
|
345843
|
+
}
|
|
345844
|
+
entry = readBodyImageEntryById(this.context, entry.publicId) ?? entry;
|
|
345845
|
+
}
|
|
345846
|
+
return { imageNodeId: inserted.imageNodeId, entry };
|
|
345515
345847
|
});
|
|
345516
|
-
|
|
345517
|
-
|
|
345518
|
-
|
|
345848
|
+
} catch (error48) {
|
|
345849
|
+
rollbackCapturedHistory(this.context, capturedTxIds);
|
|
345850
|
+
if (error48 === abortCapture && failure8)
|
|
345851
|
+
return failure8;
|
|
345852
|
+
throw error48;
|
|
345519
345853
|
}
|
|
345854
|
+
const txId = publishImageCreateHistory(this.context, capturedTxIds);
|
|
345520
345855
|
return {
|
|
345521
345856
|
success: true,
|
|
345522
|
-
image: entry?.summary.address ?? {
|
|
345857
|
+
image: published?.entry?.summary.address ?? {
|
|
345523
345858
|
kind: "inline",
|
|
345524
345859
|
nodeType: "image",
|
|
345525
|
-
nodeId:
|
|
345860
|
+
nodeId: published?.imageNodeId ?? "(unknown)",
|
|
345526
345861
|
placement: "inline"
|
|
345527
|
-
}
|
|
345862
|
+
},
|
|
345863
|
+
...txId ? { txId } : {}
|
|
345528
345864
|
};
|
|
345529
345865
|
}
|
|
345530
345866
|
delete(input, options = {}) {
|
|
@@ -347542,6 +347878,16 @@ function validateImageDeleteTarget(context, entry) {
|
|
|
347542
347878
|
}
|
|
347543
347879
|
return null;
|
|
347544
347880
|
}
|
|
347881
|
+
function publishImageCreateHistory(context, txIds) {
|
|
347882
|
+
const uniqueTxIds = [...new Set(txIds)];
|
|
347883
|
+
if (uniqueTxIds.length === 0)
|
|
347884
|
+
return;
|
|
347885
|
+
const logicalGroup = { kind: "image-create", id: uniqueTxIds[0] };
|
|
347886
|
+
for (const txId of uniqueTxIds) {
|
|
347887
|
+
recordCommittedTxIdForHistory(context, txId, { logicalGroup });
|
|
347888
|
+
}
|
|
347889
|
+
return uniqueTxIds[uniqueTxIds.length - 1];
|
|
347890
|
+
}
|
|
347545
347891
|
function createImageFailure(code2, message) {
|
|
347546
347892
|
return { success: false, failure: { code: code2, message } };
|
|
347547
347893
|
}
|
|
@@ -349286,6 +349632,7 @@ var init_adapter17 = __esm(() => {
|
|
|
349286
349632
|
init_document_reader();
|
|
349287
349633
|
init_section_xml();
|
|
349288
349634
|
init_adapter();
|
|
349635
|
+
init_composite();
|
|
349289
349636
|
init_stories();
|
|
349290
349637
|
init_common();
|
|
349291
349638
|
init_tracked_pr_change();
|
|
@@ -353085,13 +353432,14 @@ function buildCompareSourceObservation(context) {
|
|
|
353085
353432
|
if (!bytes)
|
|
353086
353433
|
continue;
|
|
353087
353434
|
const xml = TD98.decode(bytes);
|
|
353435
|
+
const canonicalizeBookmarkIds = bookmarkIdsAreBalanced(xml);
|
|
353088
353436
|
for (const match of xml.matchAll(/<[\w.-]+:bookmarkStart\b([^>]*)>/g)) {
|
|
353089
353437
|
const name = tagAttr(match[1] ?? "", "name");
|
|
353090
353438
|
if (!name || name === "_GoBack")
|
|
353091
353439
|
continue;
|
|
353092
353440
|
acc["fields-references"].present = true;
|
|
353093
353441
|
acc["fields-references"].entityCount += 1;
|
|
353094
|
-
acc["fields-references"].fingerprintParts.push(`bookmark:${source.partUri}:${name}:${tagAttr(match[1] ?? "", "id") ?? ""}`);
|
|
353442
|
+
acc["fields-references"].fingerprintParts.push(`bookmark:${source.partUri}:${name}` + (canonicalizeBookmarkIds ? "" : `:unbalanced-id:${tagAttr(match[1] ?? "", "id") ?? ""}`));
|
|
353095
353443
|
}
|
|
353096
353444
|
for (const match of xml.matchAll(/<[\w.-]+:permStart\b([^>]*)>/g)) {
|
|
353097
353445
|
const id = tagAttr(match[1] ?? "", "id");
|
|
@@ -353133,6 +353481,24 @@ function buildCompareSourceObservation(context) {
|
|
|
353133
353481
|
}));
|
|
353134
353482
|
return { parts, familySignals };
|
|
353135
353483
|
}
|
|
353484
|
+
function bookmarkIdsAreBalanced(xml) {
|
|
353485
|
+
const starts = new Map;
|
|
353486
|
+
for (const match of xml.matchAll(/<[\w.-]+:bookmarkStart\b([^>]*)>/g)) {
|
|
353487
|
+
const id = tagAttr(match[1] ?? "", "id");
|
|
353488
|
+
if (id === null || starts.has(id))
|
|
353489
|
+
return false;
|
|
353490
|
+
starts.set(id, match.index);
|
|
353491
|
+
}
|
|
353492
|
+
const ends = new Set;
|
|
353493
|
+
for (const match of xml.matchAll(/<[\w.-]+:bookmarkEnd\b([^>]*)>/g)) {
|
|
353494
|
+
const id = tagAttr(match[1] ?? "", "id");
|
|
353495
|
+
const start = id === null ? undefined : starts.get(id);
|
|
353496
|
+
if (id === null || start === undefined || ends.has(id) || match.index < start)
|
|
353497
|
+
return false;
|
|
353498
|
+
ends.add(id);
|
|
353499
|
+
}
|
|
353500
|
+
return starts.size === ends.size;
|
|
353501
|
+
}
|
|
353136
353502
|
function captureCompareSourceInventory(context) {
|
|
353137
353503
|
return buildCompareSourceInventory(buildCompareSourceObservation(context));
|
|
353138
353504
|
}
|
|
@@ -353741,6 +354107,7 @@ function projectFieldsReferences(context) {
|
|
|
353741
354107
|
if (!bytes)
|
|
353742
354108
|
continue;
|
|
353743
354109
|
const xml = TD100.decode(bytes);
|
|
354110
|
+
const canonicalizeBookmarkIds = bookmarkIdsAreBalanced2(xml);
|
|
353744
354111
|
for (const match of xml.matchAll(/<[\w.-]+:bookmarkStart\b([^>]*)>/g)) {
|
|
353745
354112
|
const name = tagAttr3(match[1] ?? "", "name");
|
|
353746
354113
|
if (!name || name === "_GoBack")
|
|
@@ -353751,7 +354118,7 @@ function projectFieldsReferences(context) {
|
|
|
353751
354118
|
key: uniqueEntityKey(baseKey, keySeen),
|
|
353752
354119
|
stableKey: `bookmark:${name}`,
|
|
353753
354120
|
semanticKey: `bookmark:${name}`,
|
|
353754
|
-
contentSignature: digest3(`bookmark:${name}#id:${id ?? ""}
|
|
354121
|
+
contentSignature: digest3(`bookmark:${name}#part:${source.partUri}` + (canonicalizeBookmarkIds ? "" : `#unbalanced-id:${id ?? ""}`)),
|
|
353755
354122
|
ordinal: ordinal++,
|
|
353756
354123
|
label: source.scopeKey === "body" ? `bookmark ${name}` : `bookmark ${name} (${source.scopeKey})`
|
|
353757
354124
|
});
|
|
@@ -353759,6 +354126,24 @@ function projectFieldsReferences(context) {
|
|
|
353759
354126
|
}
|
|
353760
354127
|
return entries;
|
|
353761
354128
|
}
|
|
354129
|
+
function bookmarkIdsAreBalanced2(xml) {
|
|
354130
|
+
const starts = new Map;
|
|
354131
|
+
for (const match of xml.matchAll(/<[\w.-]+:bookmarkStart\b([^>]*)>/g)) {
|
|
354132
|
+
const id = tagAttr3(match[1] ?? "", "id");
|
|
354133
|
+
if (id === null || starts.has(id))
|
|
354134
|
+
return false;
|
|
354135
|
+
starts.set(id, match.index);
|
|
354136
|
+
}
|
|
354137
|
+
const ends = new Set;
|
|
354138
|
+
for (const match of xml.matchAll(/<[\w.-]+:bookmarkEnd\b([^>]*)>/g)) {
|
|
354139
|
+
const id = tagAttr3(match[1] ?? "", "id");
|
|
354140
|
+
const start = id === null ? undefined : starts.get(id);
|
|
354141
|
+
if (id === null || start === undefined || ends.has(id) || match.index < start)
|
|
354142
|
+
return false;
|
|
354143
|
+
ends.add(id);
|
|
354144
|
+
}
|
|
354145
|
+
return starts.size === ends.size;
|
|
354146
|
+
}
|
|
353762
354147
|
function projectContentControls(context) {
|
|
353763
354148
|
const entries = [];
|
|
353764
354149
|
let ordinal = 0;
|
|
@@ -358567,6 +358952,119 @@ var init_main_document_revision_closure = __esm(() => {
|
|
|
358567
358952
|
});
|
|
358568
358953
|
|
|
358569
358954
|
// ../../../v2/document-api-v2-adapter/dist/diff/tracked-table-row-replay.js
|
|
358955
|
+
function rowReplayCoversContentControls(baseAnnotations, targetAnnotations, steps, baseXml, targetXml) {
|
|
358956
|
+
if (steps.length === 0)
|
|
358957
|
+
return false;
|
|
358958
|
+
const base3 = baseAnnotations?.find((group) => group.family === "content-controls")?.entries;
|
|
358959
|
+
const target = targetAnnotations?.find((group) => group.family === "content-controls")?.entries;
|
|
358960
|
+
if (!base3 || !target)
|
|
358961
|
+
return false;
|
|
358962
|
+
const inserted = new Set;
|
|
358963
|
+
const deleted = new Set;
|
|
358964
|
+
for (const step3 of steps) {
|
|
358965
|
+
const identities = step3.kind === "insertRows" ? inserted : deleted;
|
|
358966
|
+
for (const rowXml of step3.rowsXml) {
|
|
358967
|
+
for (const match of rowXml.matchAll(/<[\w.-]+:sdtPr\b[^>]*>([\s\S]*?)<\/[\w.-]+:sdtPr>/g)) {
|
|
358968
|
+
const properties = match[1];
|
|
358969
|
+
if (/<[\w.-]+:dataBinding\b/.test(properties))
|
|
358970
|
+
return false;
|
|
358971
|
+
const tag = /<[\w.-]+:tag\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(properties)?.[1];
|
|
358972
|
+
const alias = /<[\w.-]+:alias\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(properties)?.[1];
|
|
358973
|
+
const id = /<[\w.-]+:id\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(properties)?.[1];
|
|
358974
|
+
const identity2 = tag ?? alias ?? id;
|
|
358975
|
+
const key2 = identity2 ? `sdt:${identity2}` : null;
|
|
358976
|
+
if (!key2 || identities.has(key2))
|
|
358977
|
+
return false;
|
|
358978
|
+
identities.add(key2);
|
|
358979
|
+
}
|
|
358980
|
+
}
|
|
358981
|
+
}
|
|
358982
|
+
const baseByKey = new Map(base3.map((entry) => [entry.key, entry]));
|
|
358983
|
+
const targetByKey = new Map(target.map((entry) => [entry.key, entry]));
|
|
358984
|
+
if (baseByKey.size !== base3.length || targetByKey.size !== target.length)
|
|
358985
|
+
return false;
|
|
358986
|
+
const survivingBaseKeys = base3.filter((entry) => targetByKey.has(entry.key)).map((entry) => entry.key);
|
|
358987
|
+
const survivingTargetKeys = target.filter((entry) => baseByKey.has(entry.key)).map((entry) => entry.key);
|
|
358988
|
+
if (survivingBaseKeys.some((key2, index2) => key2 !== survivingTargetKeys[index2]))
|
|
358989
|
+
return false;
|
|
358990
|
+
if ([...inserted, ...deleted].some((key2) => baseByKey.has(key2) && targetByKey.has(key2)))
|
|
358991
|
+
return false;
|
|
358992
|
+
const baseShapes = contentControlShapes(baseXml);
|
|
358993
|
+
const targetShapes = contentControlShapes(targetXml);
|
|
358994
|
+
if (!baseShapes || !targetShapes)
|
|
358995
|
+
return false;
|
|
358996
|
+
if (survivingBaseKeys.some((key2) => key2.startsWith("sdt:") && (!baseShapes.has(key2) || baseShapes.get(key2) !== targetShapes.get(key2))))
|
|
358997
|
+
return false;
|
|
358998
|
+
for (const entry of base3) {
|
|
358999
|
+
const other = targetByKey.get(entry.key);
|
|
359000
|
+
if (other) {
|
|
359001
|
+
if (entry.contentSignature !== other.contentSignature || entry.semanticKey !== other.semanticKey)
|
|
359002
|
+
return false;
|
|
359003
|
+
} else if (!deleted.has(entry.key))
|
|
359004
|
+
return false;
|
|
359005
|
+
}
|
|
359006
|
+
for (const entry of target) {
|
|
359007
|
+
if (!baseByKey.has(entry.key) && !inserted.has(entry.key))
|
|
359008
|
+
return false;
|
|
359009
|
+
}
|
|
359010
|
+
return [...inserted].every((key2) => targetByKey.has(key2) && !baseByKey.has(key2)) && [...deleted].every((key2) => baseByKey.has(key2) && !targetByKey.has(key2));
|
|
359011
|
+
}
|
|
359012
|
+
function contentControlShapes(xml) {
|
|
359013
|
+
const parsed = collectXmlElementRanges(xml);
|
|
359014
|
+
if (parsed.errors.length > 0)
|
|
359015
|
+
return null;
|
|
359016
|
+
const ranges = [...parsed.ranges].sort((first, second) => first.start - second.start || second.end - first.end);
|
|
359017
|
+
const parents = new Map;
|
|
359018
|
+
const paths = new Map;
|
|
359019
|
+
const siblingCounts = new Map;
|
|
359020
|
+
const stack = [];
|
|
359021
|
+
for (const range of ranges) {
|
|
359022
|
+
while (stack.length && stack[stack.length - 1].end <= range.start)
|
|
359023
|
+
stack.pop();
|
|
359024
|
+
const parent = stack[stack.length - 1] ?? null;
|
|
359025
|
+
if (parent && range.end > parent.end)
|
|
359026
|
+
return null;
|
|
359027
|
+
const siblingIndex = siblingCounts.get(parent) ?? 0;
|
|
359028
|
+
siblingCounts.set(parent, siblingIndex + 1);
|
|
359029
|
+
parents.set(range, parent);
|
|
359030
|
+
paths.set(range, `${parent ? paths.get(parent) : ""}/${range.tag.namespaceUri}:${range.tag.localName}[${siblingIndex}]`);
|
|
359031
|
+
stack.push(range);
|
|
359032
|
+
}
|
|
359033
|
+
const shapes = new Map;
|
|
359034
|
+
const identityCounts = new Map;
|
|
359035
|
+
for (const properties of ranges.filter((range) => range.tag.namespaceUri === WORDPROCESSINGML_NS4 && range.tag.localName === "sdtPr")) {
|
|
359036
|
+
const propertyXml = xml.slice(properties.start, properties.end);
|
|
359037
|
+
const tag = /<[^>]*:tag\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(propertyXml)?.[1];
|
|
359038
|
+
const alias = /<[^>]*:alias\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(propertyXml)?.[1];
|
|
359039
|
+
const id = /<[^>]*:id\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(propertyXml)?.[1];
|
|
359040
|
+
const key2 = tag ?? alias ?? id;
|
|
359041
|
+
if (!key2)
|
|
359042
|
+
return null;
|
|
359043
|
+
const control = parents.get(properties);
|
|
359044
|
+
if (!control || control.tag.namespaceUri !== WORDPROCESSINGML_NS4 || control.tag.localName !== "sdt")
|
|
359045
|
+
return null;
|
|
359046
|
+
const parent = parents.get(control);
|
|
359047
|
+
const content3 = ranges.find((range) => parents.get(range) === control && range.tag.namespaceUri === WORDPROCESSINGML_NS4 && range.tag.localName === "sdtContent");
|
|
359048
|
+
const firstChild = content3 && ranges.find((range) => parents.get(range) === content3);
|
|
359049
|
+
if (!parent || !content3 || !firstChild)
|
|
359050
|
+
return null;
|
|
359051
|
+
const identity2 = `sdt:${key2}`;
|
|
359052
|
+
const count = (identityCounts.get(identity2) ?? 0) + 1;
|
|
359053
|
+
identityCounts.set(identity2, count);
|
|
359054
|
+
const uniqueIdentity = count === 1 ? identity2 : `${identity2}#${count}`;
|
|
359055
|
+
let ancestor = parent;
|
|
359056
|
+
let insideRow = false;
|
|
359057
|
+
while (ancestor) {
|
|
359058
|
+
if (ancestor.tag.namespaceUri === WORDPROCESSINGML_NS4 && ancestor.tag.localName === "tr") {
|
|
359059
|
+
insideRow = true;
|
|
359060
|
+
break;
|
|
359061
|
+
}
|
|
359062
|
+
ancestor = parents.get(ancestor) ?? null;
|
|
359063
|
+
}
|
|
359064
|
+
shapes.set(uniqueIdentity, `${parent.tag.namespaceUri}:${parent.tag.localName}|${firstChild.tag.namespaceUri}:${firstChild.tag.localName}|${insideRow ? "row" : paths.get(control)}`);
|
|
359065
|
+
}
|
|
359066
|
+
return shapes;
|
|
359067
|
+
}
|
|
358570
359068
|
function buildTrackedTableRowReplayPlan(input) {
|
|
358571
359069
|
if (input.base.xml === input.target.xml) {
|
|
358572
359070
|
return { steps: [], bodyOperations: input.bodyOperations, unsafeReasons: [] };
|
|
@@ -358584,30 +359082,36 @@ function buildTrackedTableRowReplayPlan(input) {
|
|
|
358584
359082
|
}
|
|
358585
359083
|
const ownedBlockIds = new Set;
|
|
358586
359084
|
const steps = [];
|
|
359085
|
+
const usedParagraphIds = new Set([
|
|
359086
|
+
...input.base.xml.matchAll(/\bparaId="([0-9A-Fa-f]{8})"/g),
|
|
359087
|
+
...input.target.xml.matchAll(/\bparaId="([0-9A-Fa-f]{8})"/g)
|
|
359088
|
+
].map((match) => match[1].toUpperCase()));
|
|
359089
|
+
const baseParagraphIds = new Set([...input.base.xml.matchAll(/\bparaId="([0-9A-Fa-f]{8})"/g)].map((match) => match[1].toUpperCase()));
|
|
358587
359090
|
for (let tableIndex = 0;tableIndex < baseCatalog.tables.length; tableIndex += 1) {
|
|
358588
359091
|
const baseTable = baseCatalog.tables[tableIndex];
|
|
358589
359092
|
const targetTable = targetCatalog.tables[tableIndex];
|
|
358590
|
-
if (!isSimpleTable(baseTable) || !isSimpleTable(targetTable)) {
|
|
359093
|
+
if (!isSimpleTable(baseTable, baseBytes, baseRoot) || !isSimpleTable(targetTable, targetBytes, targetRoot)) {
|
|
358591
359094
|
return unsafe(`table ${baseTable.tableNodeId} has columns, merges, nesting, or unsupported cell content`);
|
|
358592
359095
|
}
|
|
358593
359096
|
if (baseTable.gridColumnCount !== targetTable.gridColumnCount) {
|
|
358594
359097
|
return unsafe(`table ${baseTable.tableNodeId} changes its column grid`);
|
|
358595
359098
|
}
|
|
358596
|
-
const
|
|
358597
|
-
const
|
|
358598
|
-
|
|
358599
|
-
|
|
358600
|
-
const
|
|
358601
|
-
|
|
358602
|
-
return
|
|
358603
|
-
|
|
358604
|
-
if (
|
|
359099
|
+
const rowKey = (row, bytes) => sliceBytes(bytes, row.rowByteStart, row.rowByteEnd).replace(/\s+w14:paraId="[0-9A-Fa-f]{8}"/g, "");
|
|
359100
|
+
const baseKeys = baseTable.rows.map((row) => rowKey(row, baseBytes));
|
|
359101
|
+
const targetKeys = targetTable.rows.map((row) => rowKey(row, targetBytes));
|
|
359102
|
+
const baseIsShorter = baseKeys.length <= targetKeys.length;
|
|
359103
|
+
const matched = matchRowSubsequence(baseIsShorter ? baseKeys : targetKeys, baseIsShorter ? targetKeys : baseKeys, (baseIsShorter ? baseTable.rows : targetTable.rows).map((row) => row.rowNodeId), (baseIsShorter ? targetTable.rows : baseTable.rows).map((row) => row.rowNodeId));
|
|
359104
|
+
if (!matched)
|
|
359105
|
+
return unsafe(`table ${baseTable.tableNodeId} modifies, reorders, or ambiguously matches rows`, new Set(baseKeys).size < baseKeys.length || new Set(targetKeys).size < targetKeys.length);
|
|
359106
|
+
const baseIndexByTarget = new Map([...matched].map(([shortIndex, longIndex]) => baseIsShorter ? [longIndex, shortIndex] : [shortIndex, longIndex]));
|
|
359107
|
+
if (baseIndexByTarget.size === 0)
|
|
358605
359108
|
return unsafe(`table ${baseTable.tableNodeId} has no surviving row`);
|
|
358606
|
-
if (
|
|
358607
|
-
return unsafe(`table ${baseTable.tableNodeId}
|
|
359109
|
+
if (hasInconsistentRowIdentity(baseTable.rows, targetTable.rows, baseIndexByTarget)) {
|
|
359110
|
+
return unsafe(`table ${baseTable.tableNodeId} reassigns a row identity outside its original position`, true);
|
|
358608
359111
|
}
|
|
358609
|
-
|
|
358610
|
-
|
|
359112
|
+
const targetIndexByBase = new Map([...baseIndexByTarget].map(([targetIndex, baseIndex]) => [baseIndex, targetIndex]));
|
|
359113
|
+
for (const [baseIndex, baseRow] of baseTable.rows.entries()) {
|
|
359114
|
+
const targetPosition = targetIndexByBase.get(baseIndex);
|
|
358611
359115
|
if (targetPosition === undefined) {
|
|
358612
359116
|
const rowXml = sliceBytes(baseBytes, baseRow.rowByteStart, baseRow.rowByteEnd);
|
|
358613
359117
|
if (containsWordprocessingRevisionMarkup(rowXml, baseRoot.namespaceBindings)) {
|
|
@@ -358631,26 +359135,27 @@ function buildTrackedTableRowReplayPlan(input) {
|
|
|
358631
359135
|
}
|
|
358632
359136
|
const targetRow = targetTable.rows[targetPosition];
|
|
358633
359137
|
if (sliceBytes(baseBytes, baseRow.rowByteStart, baseRow.rowByteEnd) !== sliceBytes(targetBytes, targetRow.rowByteStart, targetRow.rowByteEnd)) {
|
|
358634
|
-
|
|
359138
|
+
if (baseKeys[baseIndex] !== targetKeys[targetPosition]) {
|
|
359139
|
+
return unsafe(`table ${baseTable.tableNodeId} modifies an existing row`);
|
|
359140
|
+
}
|
|
358635
359141
|
}
|
|
358636
359142
|
}
|
|
358637
359143
|
if (tableSkeleton(baseBytes, baseTable) !== tableSkeleton(targetBytes, targetTable)) {
|
|
358638
359144
|
return unsafe(`table ${baseTable.tableNodeId} changes non-row table structure`);
|
|
358639
359145
|
}
|
|
358640
|
-
const baseIds = new Set(baseTable.rows.map((row) => row.rowNodeId));
|
|
358641
359146
|
let index2 = 0;
|
|
358642
359147
|
while (index2 < targetTable.rows.length) {
|
|
358643
|
-
if (
|
|
359148
|
+
if (baseIndexByTarget.has(index2)) {
|
|
358644
359149
|
index2 += 1;
|
|
358645
359150
|
continue;
|
|
358646
359151
|
}
|
|
358647
359152
|
const start = index2;
|
|
358648
|
-
while (index2 < targetTable.rows.length && !
|
|
359153
|
+
while (index2 < targetTable.rows.length && !baseIndexByTarget.has(index2))
|
|
358649
359154
|
index2 += 1;
|
|
358650
359155
|
const inserted = targetTable.rows.slice(start, index2);
|
|
358651
|
-
const
|
|
358652
|
-
const
|
|
358653
|
-
const anchor =
|
|
359156
|
+
const nextBaseIndex = baseIndexByTarget.get(index2);
|
|
359157
|
+
const previousBaseIndex = [...baseIndexByTarget.entries()].reverse().find(([targetIndex]) => targetIndex < start)?.[1];
|
|
359158
|
+
const anchor = baseTable.rows[nextBaseIndex ?? previousBaseIndex ?? -1];
|
|
358654
359159
|
if (!anchor)
|
|
358655
359160
|
return unsafe(`table ${baseTable.tableNodeId} has no stable insertion anchor`);
|
|
358656
359161
|
for (const row of inserted) {
|
|
@@ -358672,20 +359177,34 @@ function buildTrackedTableRowReplayPlan(input) {
|
|
|
358672
359177
|
const rowXml = transplantableRowPayload(sourceRowXml, baseRoot, targetRoot);
|
|
358673
359178
|
if (!rowXml)
|
|
358674
359179
|
return unsafe("inserted row uses a namespace that cannot be transplanted safely");
|
|
358675
|
-
|
|
359180
|
+
const identifiedRowXml = ensureInsertedParagraphIds(rowXml, baseRoot, baseParagraphIds, usedParagraphIds);
|
|
359181
|
+
if (!identifiedRowXml)
|
|
359182
|
+
return unsafe("inserted row cannot be assigned safe paragraph identities");
|
|
359183
|
+
rowsXml.push(identifiedRowXml);
|
|
358676
359184
|
}
|
|
358677
359185
|
steps.push({
|
|
358678
359186
|
kind: "insertRows",
|
|
358679
359187
|
storyId: STORY_ID2,
|
|
358680
359188
|
tableNodeId: baseTable.tableNodeId,
|
|
358681
359189
|
anchorRowNodeId: anchor.rowNodeId,
|
|
358682
|
-
placement:
|
|
359190
|
+
placement: nextBaseIndex !== undefined ? "before" : "after",
|
|
358683
359191
|
rowsXml
|
|
358684
359192
|
});
|
|
358685
359193
|
}
|
|
359194
|
+
if (steps.some((step3) => step3.tableNodeId === baseTable.tableNodeId)) {
|
|
359195
|
+
for (const entry of [...input.baseBody ?? [], ...input.targetBody]) {
|
|
359196
|
+
if (entry.structuralScope?.startsWith(`table:${baseTable.tableNodeId}:cell:`) || entry.structuralScope?.startsWith(`table:${targetTable.tableNodeId}:cell:`)) {
|
|
359197
|
+
ownedBlockIds.add(entry.blockId);
|
|
359198
|
+
}
|
|
359199
|
+
}
|
|
359200
|
+
}
|
|
358686
359201
|
}
|
|
358687
359202
|
if (steps.length === 0)
|
|
358688
359203
|
return unsafe("table topology changed without an inserted or deleted row");
|
|
359204
|
+
const ambiguousBodyOperation = input.bodyOperations.find((operation) => ownedBlockIds.has(operation.blockId) && (operation.kind === "insert" || operation.kind === "insertAtStart" ? input.targetBody.some((entry) => entry.blockId === operation.blockId && !entry.structuralScope?.startsWith("table:")) : input.baseBody?.some((entry) => entry.blockId === operation.blockId && !entry.structuralScope?.startsWith("table:"))));
|
|
359205
|
+
if (ambiguousBodyOperation) {
|
|
359206
|
+
return unsafe(`body operation ${ambiguousBodyOperation.blockId} shares a table-cell identity`, true);
|
|
359207
|
+
}
|
|
358689
359208
|
const bodyOperations = input.bodyOperations.filter((operation) => !ownedBlockIds.has(operation.blockId));
|
|
358690
359209
|
const unownedStructuralOperation = bodyOperations.find((operation) => {
|
|
358691
359210
|
const target = input.targetBody.find((entry) => entry.blockId === operation.blockId);
|
|
@@ -358715,21 +359234,135 @@ function containsWordprocessingRevisionMarkup(xml, namespaceBindings) {
|
|
|
358715
359234
|
}
|
|
358716
359235
|
return containsRevision;
|
|
358717
359236
|
}
|
|
358718
|
-
function unsafe(reason) {
|
|
358719
|
-
return { steps: [], bodyOperations: [], unsafeReasons: [reason] };
|
|
359237
|
+
function unsafe(reason, refuseBlockFallback = false) {
|
|
359238
|
+
return { steps: [], bodyOperations: [], unsafeReasons: [reason], refuseBlockFallback };
|
|
358720
359239
|
}
|
|
358721
|
-
function
|
|
358722
|
-
const
|
|
358723
|
-
|
|
358724
|
-
|
|
358725
|
-
|
|
359240
|
+
function matchRowSubsequence(shortKeys, longKeys, shortIds, longIds) {
|
|
359241
|
+
const remainingMatches = (shortStart, longStart) => {
|
|
359242
|
+
for (let shortIndex = shortStart;shortIndex < shortKeys.length; shortIndex += 1) {
|
|
359243
|
+
while (longStart < longKeys.length && longKeys[longStart] !== shortKeys[shortIndex])
|
|
359244
|
+
longStart += 1;
|
|
359245
|
+
if (longStart === longKeys.length)
|
|
359246
|
+
return false;
|
|
359247
|
+
longStart += 1;
|
|
359248
|
+
}
|
|
359249
|
+
return true;
|
|
359250
|
+
};
|
|
359251
|
+
const matches = new Map;
|
|
359252
|
+
let nextLongIndex = 0;
|
|
359253
|
+
for (let shortIndex = 0;shortIndex < shortKeys.length; shortIndex += 1) {
|
|
359254
|
+
const candidates = [];
|
|
359255
|
+
for (let longIndex = nextLongIndex;longIndex < longKeys.length; longIndex += 1) {
|
|
359256
|
+
if (shortKeys[shortIndex] === longKeys[longIndex] && remainingMatches(shortIndex + 1, longIndex + 1))
|
|
359257
|
+
candidates.push(longIndex);
|
|
359258
|
+
}
|
|
359259
|
+
if (candidates.length === 0)
|
|
358726
359260
|
return null;
|
|
358727
|
-
|
|
359261
|
+
const sameIdentity = candidates.filter((index2) => shortIds[shortIndex] === longIds[index2]);
|
|
359262
|
+
if (candidates.length > 1 && sameIdentity.length !== 1)
|
|
359263
|
+
return null;
|
|
359264
|
+
const selected = sameIdentity[0] ?? candidates[0];
|
|
359265
|
+
matches.set(shortIndex, selected);
|
|
359266
|
+
nextLongIndex = selected + 1;
|
|
358728
359267
|
}
|
|
358729
|
-
|
|
359268
|
+
for (const [shortIndex, longIndex] of matches) {
|
|
359269
|
+
const key2 = shortKeys[shortIndex];
|
|
359270
|
+
if (shortKeys.indexOf(key2) === shortKeys.lastIndexOf(key2) && longKeys.indexOf(key2) === longKeys.lastIndexOf(key2))
|
|
359271
|
+
continue;
|
|
359272
|
+
const sharedLongIndex = longIds.findIndex((id, index2) => id === shortIds[shortIndex] && longKeys[index2] === key2);
|
|
359273
|
+
const sharedShortIndex = shortIds.findIndex((id, index2) => id === longIds[longIndex] && shortKeys[index2] === key2);
|
|
359274
|
+
if (sharedLongIndex >= 0 && sharedLongIndex !== longIndex || sharedShortIndex >= 0 && sharedShortIndex !== shortIndex)
|
|
359275
|
+
return null;
|
|
359276
|
+
}
|
|
359277
|
+
return matches;
|
|
358730
359278
|
}
|
|
358731
|
-
function
|
|
358732
|
-
|
|
359279
|
+
function hasInconsistentRowIdentity(baseRows, targetRows, baseIndexByTarget) {
|
|
359280
|
+
const baseIndexById = new Map(baseRows.map((row, index2) => [row.rowNodeId, index2]));
|
|
359281
|
+
for (const [targetIndex, targetRow] of targetRows.entries()) {
|
|
359282
|
+
if (targetRow.identityProvenance !== "para-id")
|
|
359283
|
+
continue;
|
|
359284
|
+
const baseIndex = baseIndexById.get(targetRow.rowNodeId);
|
|
359285
|
+
if (baseIndex === undefined || baseRows[baseIndex].identityProvenance !== "para-id")
|
|
359286
|
+
continue;
|
|
359287
|
+
if (baseIndex !== targetIndex && baseIndexByTarget.get(targetIndex) !== baseIndex)
|
|
359288
|
+
return true;
|
|
359289
|
+
}
|
|
359290
|
+
return false;
|
|
359291
|
+
}
|
|
359292
|
+
function isSimpleTable(table, bytes, root) {
|
|
359293
|
+
return !table.containsNestedTable && !table.hasGridSpan && !table.hasVMerge && table.isRectangular && table.rows.every((row) => row.cells.every((cell) => !cell.containsUnsupportedContent || isSafeContentControlCell(sliceBytes(bytes, cell.bodyByteStart, cell.bodyByteEnd), root)));
|
|
359294
|
+
}
|
|
359295
|
+
function isSafeContentControlCell(xml, root) {
|
|
359296
|
+
let foundControl = false;
|
|
359297
|
+
let safe = true;
|
|
359298
|
+
const parser = createXmlSaxParser({
|
|
359299
|
+
namespaceAware: true,
|
|
359300
|
+
fragment: true,
|
|
359301
|
+
additionalNamespaces: { ...root.namespaceBindings }
|
|
359302
|
+
});
|
|
359303
|
+
parser.on("error", () => {
|
|
359304
|
+
safe = false;
|
|
359305
|
+
});
|
|
359306
|
+
parser.on("opentag", (tag) => {
|
|
359307
|
+
if (tag.namespaceUri !== WORDPROCESSINGML_NS4)
|
|
359308
|
+
return;
|
|
359309
|
+
if (tag.localName === "sdt")
|
|
359310
|
+
foundControl = true;
|
|
359311
|
+
if (["drawing", "object", "oMath", "oMathPara", "tbl"].includes(tag.localName) || tag.attributes.some((attribute2) => isRelationshipNamespace(attribute2.namespaceUri)))
|
|
359312
|
+
safe = false;
|
|
359313
|
+
});
|
|
359314
|
+
try {
|
|
359315
|
+
parser.write(xml);
|
|
359316
|
+
parser.close();
|
|
359317
|
+
} catch {
|
|
359318
|
+
return false;
|
|
359319
|
+
}
|
|
359320
|
+
return foundControl && safe;
|
|
359321
|
+
}
|
|
359322
|
+
function ensureInsertedParagraphIds(xml, root, baseIds, usedIds) {
|
|
359323
|
+
const parsed = collectXmlElementRanges(xml, {
|
|
359324
|
+
fragment: true,
|
|
359325
|
+
additionalNamespaces: { ...root.namespaceBindings }
|
|
359326
|
+
});
|
|
359327
|
+
if (parsed.errors.length > 0)
|
|
359328
|
+
return null;
|
|
359329
|
+
const insertions = [];
|
|
359330
|
+
for (const paragraph4 of parsed.ranges.filter((range) => range.tag.namespaceUri === WORDPROCESSINGML_NS4 && range.tag.localName === "p")) {
|
|
359331
|
+
const existingId = paragraph4.tag.attributes.find((attribute2) => attribute2.namespaceUri === WORDPROCESSINGML_2010_NS && attribute2.localName === "paraId");
|
|
359332
|
+
if (existingId && !baseIds.has(existingId.value.toUpperCase()))
|
|
359333
|
+
continue;
|
|
359334
|
+
let identifier;
|
|
359335
|
+
for (let candidate2 = 1879048192;candidate2 > 0; candidate2 -= 1) {
|
|
359336
|
+
const value2 = candidate2.toString(16).toUpperCase().padStart(8, "0");
|
|
359337
|
+
if (!usedIds.has(value2)) {
|
|
359338
|
+
identifier = value2;
|
|
359339
|
+
usedIds.add(value2);
|
|
359340
|
+
break;
|
|
359341
|
+
}
|
|
359342
|
+
}
|
|
359343
|
+
if (!identifier)
|
|
359344
|
+
return null;
|
|
359345
|
+
if (existingId) {
|
|
359346
|
+
const opening = xml.slice(paragraph4.start, paragraph4.openEnd);
|
|
359347
|
+
const attribute2 = new RegExp(`\\b${existingId.name}="${existingId.value}"`);
|
|
359348
|
+
const match = attribute2.exec(opening);
|
|
359349
|
+
if (!match)
|
|
359350
|
+
return null;
|
|
359351
|
+
insertions.push({
|
|
359352
|
+
offset: paragraph4.start + match.index,
|
|
359353
|
+
text: `${existingId.name}="${identifier}"`,
|
|
359354
|
+
end: paragraph4.start + match.index + match[0].length
|
|
359355
|
+
});
|
|
359356
|
+
} else {
|
|
359357
|
+
const localDeclaration = paragraph4.namespaceBindings.w14 === WORDPROCESSINGML_2010_NS ? "" : ` xmlns:w14="${WORDPROCESSINGML_2010_NS}"`;
|
|
359358
|
+
const opening = xml.slice(paragraph4.start, paragraph4.openEnd);
|
|
359359
|
+
insertions.push({
|
|
359360
|
+
offset: paragraph4.openEnd - (opening.endsWith("/>") ? 2 : 1),
|
|
359361
|
+
text: `${localDeclaration} w14:paraId="${identifier}"`
|
|
359362
|
+
});
|
|
359363
|
+
}
|
|
359364
|
+
}
|
|
359365
|
+
return insertions.reverse().reduce((result, insertion) => result.slice(0, insertion.offset) + insertion.text + result.slice(insertion.end ?? insertion.offset), xml);
|
|
358733
359366
|
}
|
|
358734
359367
|
function tableSkeleton(bytes, table) {
|
|
358735
359368
|
let cursor = table.tableByteStart;
|
|
@@ -361391,7 +362024,32 @@ function paragraphOpeningTag2(paragraphXml) {
|
|
|
361391
362024
|
return paragraphXml.slice(0, paragraphXml.indexOf(">") + 1);
|
|
361392
362025
|
}
|
|
361393
362026
|
function ownedStructuresEqual(leftXml, rightXml) {
|
|
361394
|
-
return arraysEqual2(collectElements(leftXml, "sectPr"), collectElements(rightXml, "sectPr")) &&
|
|
362027
|
+
return arraysEqual2(collectElements(leftXml, "sectPr"), collectElements(rightXml, "sectPr")) && bookmarkStructuresEqual(leftXml, rightXml) && arraysEqual2(collectElements(leftXml, "fldSimple"), collectElements(rightXml, "fldSimple")) && arraysEqual2(collectElements(leftXml, "instrText"), collectElements(rightXml, "instrText")) && arraysEqual2(collectEmptyElements(leftXml, "fldChar"), collectEmptyElements(rightXml, "fldChar"));
|
|
362028
|
+
}
|
|
362029
|
+
function bookmarkStructuresEqual(leftXml, rightXml) {
|
|
362030
|
+
const summarize = (xml) => {
|
|
362031
|
+
if (!bookmarkRangesArePaired(xml))
|
|
362032
|
+
return null;
|
|
362033
|
+
const nameById = new Map(collectWordElements(xml, "bookmarkStart", true).map((element) => {
|
|
362034
|
+
const id = readAttribute2(element, "id");
|
|
362035
|
+
const name = readAttribute2(element, "name");
|
|
362036
|
+
return [id, name];
|
|
362037
|
+
}));
|
|
362038
|
+
const starts = collectWordElements(xml, "bookmarkStart", true).map((element) => ({
|
|
362039
|
+
position: element.range.start,
|
|
362040
|
+
value: `start:${replaceAttribute(element, "id", "__bookmark_id__")}`
|
|
362041
|
+
}));
|
|
362042
|
+
const ends = collectWordElements(xml, "bookmarkEnd", true).map((element) => ({
|
|
362043
|
+
position: element.range.start,
|
|
362044
|
+
value: `end:${replaceAttribute(element, "id", `__bookmark_${nameById.get(readAttribute2(element, "id")) ?? "missing"}__`)}`
|
|
362045
|
+
}));
|
|
362046
|
+
return [...starts, ...ends].sort((a, b) => a.position - b.position).map((event) => event.value);
|
|
362047
|
+
};
|
|
362048
|
+
const left = summarize(leftXml);
|
|
362049
|
+
const right = summarize(rightXml);
|
|
362050
|
+
if (!left || !right || left.length !== right.length)
|
|
362051
|
+
return false;
|
|
362052
|
+
return left.every((value2, index2) => value2 === right[index2]);
|
|
361395
362053
|
}
|
|
361396
362054
|
function arraysEqual2(left, right) {
|
|
361397
362055
|
return left.length === right.length && left.every((value2, index2) => value2 === right[index2]);
|
|
@@ -361427,39 +362085,44 @@ function buildSectionSteps(baseXml, targetXml, unsafeReasons) {
|
|
|
361427
362085
|
function buildReferenceSteps(baseXml, targetXml, unsafeReasons) {
|
|
361428
362086
|
const baseBookmarks = collectWordElements(baseXml, "bookmarkStart", true);
|
|
361429
362087
|
const targetBookmarks = collectWordElements(targetXml, "bookmarkStart", true);
|
|
361430
|
-
if (baseBookmarks.length !== targetBookmarks.length) {
|
|
361431
|
-
unsafeReasons.push("bookmark topology changed");
|
|
361432
|
-
return [];
|
|
361433
|
-
}
|
|
361434
362088
|
if (!bookmarkRangesArePaired(baseXml) || !bookmarkRangesArePaired(targetXml)) {
|
|
361435
362089
|
unsafeReasons.push("bookmark topology is unbalanced or duplicated");
|
|
361436
362090
|
return [];
|
|
361437
362091
|
}
|
|
361438
362092
|
const renamedBookmarks = new Map;
|
|
361439
362093
|
const steps = [];
|
|
361440
|
-
|
|
361441
|
-
|
|
361442
|
-
|
|
361443
|
-
|
|
361444
|
-
|
|
361445
|
-
|
|
361446
|
-
|
|
361447
|
-
|
|
361448
|
-
|
|
361449
|
-
|
|
361450
|
-
|
|
361451
|
-
|
|
361452
|
-
|
|
361453
|
-
|
|
362094
|
+
if (baseBookmarks.length === targetBookmarks.length) {
|
|
362095
|
+
for (let index2 = 0;index2 < baseBookmarks.length; index2 += 1) {
|
|
362096
|
+
const before = baseBookmarks[index2];
|
|
362097
|
+
const after = targetBookmarks[index2];
|
|
362098
|
+
const beforeXml = before.xml;
|
|
362099
|
+
const afterXml = after.xml;
|
|
362100
|
+
if (beforeXml === afterXml)
|
|
362101
|
+
continue;
|
|
362102
|
+
const beforeId = readAttribute2(before, "id");
|
|
362103
|
+
const afterId = readAttribute2(after, "id");
|
|
362104
|
+
const beforeName = readAttribute2(before, "name");
|
|
362105
|
+
const afterName = readAttribute2(after, "name");
|
|
362106
|
+
if (beforeId && afterId && beforeName && beforeName === afterName && replaceAttribute(after, "id", beforeId) === beforeXml) {
|
|
362107
|
+
continue;
|
|
362108
|
+
}
|
|
362109
|
+
if (!beforeId || beforeId !== afterId || !beforeName || !afterName || replaceAttribute(before, "name", afterName) !== afterXml) {
|
|
362110
|
+
unsafeReasons.push(`bookmark ${index2} changed beyond a name-only rename or ID allocation`);
|
|
362111
|
+
continue;
|
|
362112
|
+
}
|
|
362113
|
+
renamedBookmarks.set(beforeName, afterName);
|
|
362114
|
+
steps.push({
|
|
362115
|
+
kind: "bookmark-start",
|
|
362116
|
+
beforeXml,
|
|
362117
|
+
afterXml,
|
|
362118
|
+
beforeNamespaceBindings: { ...before.range.namespaceBindings },
|
|
362119
|
+
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
362120
|
+
});
|
|
361454
362121
|
}
|
|
361455
|
-
|
|
361456
|
-
steps.push(
|
|
361457
|
-
|
|
361458
|
-
|
|
361459
|
-
afterXml,
|
|
361460
|
-
beforeNamespaceBindings: { ...before.range.namespaceBindings },
|
|
361461
|
-
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
361462
|
-
});
|
|
362122
|
+
} else if (targetBookmarks.length > baseBookmarks.length) {
|
|
362123
|
+
steps.push(...buildAddedBookmarkSteps(baseXml, targetXml, baseBookmarks, targetBookmarks, unsafeReasons));
|
|
362124
|
+
} else {
|
|
362125
|
+
unsafeReasons.push("bookmark removal is not supported");
|
|
361463
362126
|
}
|
|
361464
362127
|
const baseFields = collectWordElements(baseXml, "fldSimple");
|
|
361465
362128
|
const targetFields = collectWordElements(targetXml, "fldSimple");
|
|
@@ -361490,8 +362153,125 @@ function buildReferenceSteps(baseXml, targetXml, unsafeReasons) {
|
|
|
361490
362153
|
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
361491
362154
|
});
|
|
361492
362155
|
}
|
|
362156
|
+
steps.push(...buildAddedComplexFieldSteps(baseXml, targetXml, unsafeReasons));
|
|
361493
362157
|
return steps;
|
|
361494
362158
|
}
|
|
362159
|
+
function buildAddedBookmarkSteps(baseXml, targetXml, baseBookmarks, targetBookmarks, unsafeReasons) {
|
|
362160
|
+
const baseNames = new Set(baseBookmarks.map((element) => readAttribute2(element, "name")));
|
|
362161
|
+
const targetNames = targetBookmarks.map((element) => readAttribute2(element, "name"));
|
|
362162
|
+
if (baseNames.has(null) || targetNames.some((name) => name === null) || new Set(targetNames).size !== targetNames.length || [...baseNames].some((name) => !targetNames.includes(name))) {
|
|
362163
|
+
unsafeReasons.push("bookmark addition cannot be matched unambiguously by name");
|
|
362164
|
+
return [];
|
|
362165
|
+
}
|
|
362166
|
+
const baseParagraphs = collectWordElements(baseXml, "p");
|
|
362167
|
+
const targetParagraphs = collectWordElements(targetXml, "p");
|
|
362168
|
+
if (baseParagraphs.length !== targetParagraphs.length) {
|
|
362169
|
+
unsafeReasons.push("bookmark addition changed paragraph topology");
|
|
362170
|
+
return [];
|
|
362171
|
+
}
|
|
362172
|
+
const targetEnds = collectWordElements(targetXml, "bookmarkEnd", true);
|
|
362173
|
+
const steps = [];
|
|
362174
|
+
for (const start of targetBookmarks.filter((element) => !baseNames.has(readAttribute2(element, "name")))) {
|
|
362175
|
+
const id = readAttribute2(start, "id");
|
|
362176
|
+
const end = targetEnds.find((candidate2) => readAttribute2(candidate2, "id") === id);
|
|
362177
|
+
const paragraphIndex = targetParagraphs.findIndex((paragraph4) => paragraph4.range.start < start.range.start && paragraph4.range.end > (end?.range.end ?? Number.MAX_SAFE_INTEGER));
|
|
362178
|
+
if (!id || !end || paragraphIndex < 0) {
|
|
362179
|
+
unsafeReasons.push("added bookmark range is not contained in one paragraph");
|
|
362180
|
+
continue;
|
|
362181
|
+
}
|
|
362182
|
+
const before = baseParagraphs[paragraphIndex];
|
|
362183
|
+
const after = targetParagraphs[paragraphIndex];
|
|
362184
|
+
const beforeFragmentXml = targetXml.slice(start.range.end, end.range.start);
|
|
362185
|
+
const afterFragmentXml = targetXml.slice(start.range.start, end.range.end);
|
|
362186
|
+
if (replaceUnique(after.xml, afterFragmentXml, beforeFragmentXml) !== before.xml) {
|
|
362187
|
+
unsafeReasons.push("added bookmark range changes content beyond a balanced wrapper");
|
|
362188
|
+
continue;
|
|
362189
|
+
}
|
|
362190
|
+
steps.push({
|
|
362191
|
+
kind: "bookmark-range",
|
|
362192
|
+
beforeXml: before.xml,
|
|
362193
|
+
afterXml: after.xml,
|
|
362194
|
+
beforeFragmentXml,
|
|
362195
|
+
afterFragmentXml,
|
|
362196
|
+
beforeNamespaceBindings: { ...before.range.namespaceBindings },
|
|
362197
|
+
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
362198
|
+
});
|
|
362199
|
+
}
|
|
362200
|
+
return steps;
|
|
362201
|
+
}
|
|
362202
|
+
function buildAddedComplexFieldSteps(baseXml, targetXml, unsafeReasons) {
|
|
362203
|
+
const baseParagraphs = collectWordElements(baseXml, "p");
|
|
362204
|
+
const targetParagraphs = collectWordElements(targetXml, "p");
|
|
362205
|
+
if (baseParagraphs.length !== targetParagraphs.length)
|
|
362206
|
+
return [];
|
|
362207
|
+
const targetBookmarkNameCounts = new Map;
|
|
362208
|
+
for (const bookmark of collectWordElements(targetXml, "bookmarkStart", true)) {
|
|
362209
|
+
const name = readAttribute2(bookmark, "name");
|
|
362210
|
+
if (name !== null) {
|
|
362211
|
+
targetBookmarkNameCounts.set(name, (targetBookmarkNameCounts.get(name) ?? 0) + 1);
|
|
362212
|
+
}
|
|
362213
|
+
}
|
|
362214
|
+
const steps = [];
|
|
362215
|
+
for (let index2 = 0;index2 < targetParagraphs.length; index2 += 1) {
|
|
362216
|
+
const before = baseParagraphs[index2];
|
|
362217
|
+
const after = targetParagraphs[index2];
|
|
362218
|
+
if (before.xml === after.xml)
|
|
362219
|
+
continue;
|
|
362220
|
+
const candidate2 = addedComplexRefField(after, before.xml);
|
|
362221
|
+
if (!candidate2)
|
|
362222
|
+
continue;
|
|
362223
|
+
const targetCount = targetBookmarkNameCounts.get(candidate2.referenceName) ?? 0;
|
|
362224
|
+
if (targetCount === 0) {
|
|
362225
|
+
unsafeReasons.push(`complex REF field ${index2} targets a missing bookmark`);
|
|
362226
|
+
continue;
|
|
362227
|
+
}
|
|
362228
|
+
if (targetCount !== 1) {
|
|
362229
|
+
unsafeReasons.push(`complex REF field ${index2} targets an ambiguous bookmark`);
|
|
362230
|
+
continue;
|
|
362231
|
+
}
|
|
362232
|
+
steps.push({
|
|
362233
|
+
kind: "complex-field",
|
|
362234
|
+
beforeXml: before.xml,
|
|
362235
|
+
afterXml: after.xml,
|
|
362236
|
+
beforeFragmentXml: candidate2.resultXml,
|
|
362237
|
+
afterFragmentXml: candidate2.fieldXml,
|
|
362238
|
+
beforeNamespaceBindings: { ...before.range.namespaceBindings },
|
|
362239
|
+
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
362240
|
+
});
|
|
362241
|
+
}
|
|
362242
|
+
return steps;
|
|
362243
|
+
}
|
|
362244
|
+
function addedComplexRefField(targetParagraph, expectedBaseParagraphXml) {
|
|
362245
|
+
const fields = collectWordElements(targetParagraph.xml, "fldChar", true, targetParagraph.range.namespaceBindings);
|
|
362246
|
+
for (let beginIndex = 0;beginIndex < fields.length; beginIndex += 1) {
|
|
362247
|
+
const begin = fields[beginIndex];
|
|
362248
|
+
if (readAttribute2(begin, "fldCharType") !== "begin")
|
|
362249
|
+
continue;
|
|
362250
|
+
const separate = fields.slice(beginIndex + 1).find((field) => readAttribute2(field, "fldCharType") === "separate");
|
|
362251
|
+
const end = separate && fields.find((field) => field.range.start > separate.range.start && readAttribute2(field, "fldCharType") === "end");
|
|
362252
|
+
if (!separate || !end)
|
|
362253
|
+
continue;
|
|
362254
|
+
const runs = collectWordElements(targetParagraph.xml, "r", false, targetParagraph.range.namespaceBindings);
|
|
362255
|
+
const beginRun = runs.find((run) => run.range.start <= begin.range.start && run.range.end >= begin.range.end);
|
|
362256
|
+
const separateRun = runs.find((run) => run.range.start <= separate.range.start && run.range.end >= separate.range.end);
|
|
362257
|
+
const endRun = runs.find((run) => run.range.start <= end.range.start && run.range.end >= end.range.end);
|
|
362258
|
+
if (!beginRun || !separateRun || !endRun)
|
|
362259
|
+
continue;
|
|
362260
|
+
const instruction = collectWordElements(targetParagraph.xml, "instrText", false, targetParagraph.range.namespaceBindings).filter((element) => element.range.start > begin.range.end && element.range.end < separate.range.start).map((element) => element.xml.replace(/^<[^>]+>|<\/[^>]+>$/g, "")).join("");
|
|
362261
|
+
const parsed = parseRefInstruction(instruction);
|
|
362262
|
+
if (!parsed)
|
|
362263
|
+
continue;
|
|
362264
|
+
const fieldXml = targetParagraph.xml.slice(beginRun.range.start, endRun.range.end);
|
|
362265
|
+
const resultXml = targetParagraph.xml.slice(separateRun.range.end, endRun.range.start);
|
|
362266
|
+
const fieldChars = fields.filter((field) => field.range.start >= begin.range.start && field.range.end <= end.range.end);
|
|
362267
|
+
if (fieldChars.length !== 3 || fieldChars.map((field) => readAttribute2(field, "fldCharType")).join(",") !== "begin,separate,end")
|
|
362268
|
+
continue;
|
|
362269
|
+
if (!resultXml || replaceUnique(targetParagraph.xml, fieldXml, resultXml) !== expectedBaseParagraphXml)
|
|
362270
|
+
continue;
|
|
362271
|
+
return { fieldXml, resultXml, referenceName: parsed.name };
|
|
362272
|
+
}
|
|
362273
|
+
return null;
|
|
362274
|
+
}
|
|
361495
362275
|
function bookmarkRangesArePaired(xml) {
|
|
361496
362276
|
const startsById = new Map;
|
|
361497
362277
|
for (const element of collectWordElements(xml, "bookmarkStart", true)) {
|
|
@@ -361520,8 +362300,10 @@ function collectEmptyElements(xml, localName2) {
|
|
|
361520
362300
|
function collectElements(xml, localName2) {
|
|
361521
362301
|
return collectWordElements(xml, localName2).map((element) => element.xml);
|
|
361522
362302
|
}
|
|
361523
|
-
function collectWordElements(xml, localName2, selfClosingOnly = false) {
|
|
361524
|
-
const parsed = collectXmlElementRanges(xml, {
|
|
362303
|
+
function collectWordElements(xml, localName2, selfClosingOnly = false, additionalNamespaces = {}) {
|
|
362304
|
+
const parsed = collectXmlElementRanges(xml, {
|
|
362305
|
+
additionalNamespaces: { w: WORDPROCESSINGML_NS6, ...additionalNamespaces }
|
|
362306
|
+
});
|
|
361525
362307
|
if (parsed.errors.length > 0)
|
|
361526
362308
|
return [];
|
|
361527
362309
|
return parsed.ranges.filter((range) => range.tag.namespaceUri === WORDPROCESSINGML_NS6 && range.tag.localName === localName2 && (!selfClosingOnly || range.tag.isSelfClosing)).sort((left, right) => left.start - right.start).map((range) => ({ xml: xml.slice(range.start, range.end), range }));
|
|
@@ -361676,7 +362458,11 @@ class V2DiffAdapter {
|
|
|
361676
362458
|
try {
|
|
361677
362459
|
const engine = createV2CompareEngine(this.context);
|
|
361678
362460
|
const base3 = captureCompareSnapshotSync(this.context);
|
|
361679
|
-
const
|
|
362461
|
+
const baseMainDocument = projectDiffMainDocumentSource(this.context);
|
|
362462
|
+
const targetMainDocument = targetPayload.mainDocument ?? EMPTY_MAIN_DOCUMENT_SOURCE;
|
|
362463
|
+
const rawAnalysis = engine.analyzeSnapshots(base3, targetPayload.compareSnapshot);
|
|
362464
|
+
const comparisonTarget = paragraphIdentityOnlyComparisonTarget(base3, targetPayload.compareSnapshot, baseMainDocument, targetMainDocument, rawAnalysis.result);
|
|
362465
|
+
const analysis = comparisonTarget ? engine.analyzeSnapshots(base3, comparisonTarget) : rawAnalysis;
|
|
361680
362466
|
if (!analysis.plan) {
|
|
361681
362467
|
throw diffValidationError("INVALID_INPUT", "diff.compare: compare engine did not return a semantic analysis plan.");
|
|
361682
362468
|
}
|
|
@@ -361693,8 +362479,6 @@ class V2DiffAdapter {
|
|
|
361693
362479
|
const baseNumbering = projectDiffNumberingSource(this.context);
|
|
361694
362480
|
const targetNumbering = targetPayload.numbering ?? { xml: null };
|
|
361695
362481
|
const numberingPlan = buildNumberingApplyPlan(baseNumbering, targetNumbering);
|
|
361696
|
-
const baseMainDocument = projectDiffMainDocumentSource(this.context);
|
|
361697
|
-
const targetMainDocument = targetPayload.mainDocument ?? EMPTY_MAIN_DOCUMENT_SOURCE;
|
|
361698
362482
|
const sectionsReferencesPlan = buildSectionsReferencesReplayPlan(baseMainDocument, targetMainDocument);
|
|
361699
362483
|
const adapterApplySupportedFamilies = new Set;
|
|
361700
362484
|
if (sectionsReferencesPlan.unsafeReasons.length === 0) {
|
|
@@ -361967,8 +362751,9 @@ class V2DiffAdapter {
|
|
|
361967
362751
|
unsupportedReason: "section-reference-replay-unsafe"
|
|
361968
362752
|
});
|
|
361969
362753
|
}
|
|
361970
|
-
const
|
|
361971
|
-
|
|
362754
|
+
const usesLocalizedMainDocumentReplay = sectionsReferencesChanged && (sectionsReferencesPlan.sectionSteps.length > 0 || sectionsReferencesPlan.referenceSteps.length > 0);
|
|
362755
|
+
const localizedBodyOperations = usesLocalizedMainDocumentReplay ? buildLocalizedBodyOperations(payload.base.body, payload.target.body, sectionsReferencesPlan.sectionSteps, sectionsReferencesPlan.referenceSteps, { base: payload.base.definitions, target: payload.target.definitions }, canonicalBodyOperations) : [];
|
|
362756
|
+
if (usesLocalizedMainDocumentReplay) {
|
|
361972
362757
|
setRuntimeBodyOperationCounts(operationCounts, payload.applyPlan, localizedBodyOperations);
|
|
361973
362758
|
}
|
|
361974
362759
|
const localizedMainDocumentCovered = !sectionsReferencesPlan.hasUnownedMainDocumentChanges || localizedMainDocumentChangesAreCovered({
|
|
@@ -362014,19 +362799,23 @@ class V2DiffAdapter {
|
|
|
362014
362799
|
}
|
|
362015
362800
|
}
|
|
362016
362801
|
const mainDocumentPlan = tablesChanged && !reviewMarkup ? buildMainDocumentApplyPlan(liveBaseMainDocument, payloadMainDocument.target) : { steps: [], unsafeReasons: [] };
|
|
362017
|
-
const trackedTableBodyOperations = !tablesChanged || !reviewMarkup ? payload.applyPlan.bodyOperations :
|
|
362802
|
+
const trackedTableBodyOperations = !tablesChanged || !reviewMarkup ? payload.applyPlan.bodyOperations : usesLocalizedMainDocumentReplay ? localizedBodyOperations : mergeCanonicalRevisionReplay(computeCompareBodyOperations(payload.base.body, payload.target.body, {
|
|
362018
362803
|
base: payload.base.definitions,
|
|
362019
362804
|
target: payload.target.definitions
|
|
362020
362805
|
}), canonicalBodyOperations);
|
|
362021
362806
|
const trackedTablePropertyPlan = tablesChanged && reviewMarkup ? buildTrackedTablePropertyReplayPlan(liveBaseMainDocument, payloadMainDocument.target) : null;
|
|
362022
|
-
let
|
|
362023
|
-
let trackedTablePlan = tablesChanged && reviewMarkup && !trackedTableBlockPlan && !trackedTablePropertyPlan ? buildTrackedTableRowReplayPlan({
|
|
362807
|
+
let trackedTablePlan = tablesChanged && reviewMarkup && !trackedTablePropertyPlan ? buildTrackedTableRowReplayPlan({
|
|
362024
362808
|
base: liveBaseMainDocument,
|
|
362025
362809
|
target: payloadMainDocument.target,
|
|
362810
|
+
baseBody: payload.base.body,
|
|
362026
362811
|
targetBody: payload.target.body,
|
|
362027
362812
|
bodyOperations: trackedTableBodyOperations
|
|
362028
|
-
}) : { steps: [], bodyOperations:
|
|
362029
|
-
|
|
362813
|
+
}) : { steps: [], bodyOperations: trackedTablePropertyPlan ? trackedTableBodyOperations : payload.applyPlan.bodyOperations, unsafeReasons: [] };
|
|
362814
|
+
let trackedTableBlockPlan = tablesChanged && reviewMarkup && !trackedTablePropertyPlan && !trackedTablePlan.refuseBlockFallback && (trackedTablePlan.unsafeReasons.length > 0 || trackedTablePlan.steps.length === 0) ? buildTrackedTableBlockReplayPlan({ base: liveBaseMainDocument, target: payloadMainDocument.target, bodyOperations: trackedTableBodyOperations }) : null;
|
|
362815
|
+
if (trackedTableBlockPlan) {
|
|
362816
|
+
trackedTablePlan = { steps: [], bodyOperations: trackedTableBlockPlan.bodyOperations, unsafeReasons: [] };
|
|
362817
|
+
}
|
|
362818
|
+
if (trackedTablePlan.unsafeReasons.length > 0 && !trackedTablePlan.refuseBlockFallback) {
|
|
362030
362819
|
const replacement = buildTrackedTableBlockReplayPlan({
|
|
362031
362820
|
base: liveBaseMainDocument,
|
|
362032
362821
|
target: payloadMainDocument.target,
|
|
@@ -362081,7 +362870,7 @@ class V2DiffAdapter {
|
|
|
362081
362870
|
if (mainDocumentPlan.unsafeReasons.length > 0) {
|
|
362082
362871
|
throw diffValidationError("CAPABILITY_UNSUPPORTED", `diff.apply: main document replay is unsafe — [${mainDocumentPlan.unsafeReasons.join("; ")}]. ` + "No mutation was performed (full payloads are never partially applied).", { changedFamilies: ["tables"], unsupportedReason: "main-document-replay-unsafe" });
|
|
362083
362872
|
}
|
|
362084
|
-
const runtimeApplyPlan =
|
|
362873
|
+
const runtimeApplyPlan = usesLocalizedMainDocumentReplay ? {
|
|
362085
362874
|
...runtimeApplyPlanBase,
|
|
362086
362875
|
applyPlan: {
|
|
362087
362876
|
...runtimeApplyPlanBase.applyPlan,
|
|
@@ -362113,6 +362902,13 @@ class V2DiffAdapter {
|
|
|
362113
362902
|
handledFamilies.add("body");
|
|
362114
362903
|
}
|
|
362115
362904
|
}
|
|
362905
|
+
const rowControlsCovered = trackedTablePlan.steps.length > 0 && rowReplayCoversContentControls(payload.base.annotations, payload.target.annotations, trackedTablePlan.steps, liveBaseMainDocument.xml, payloadMainDocument.target.xml);
|
|
362906
|
+
if (trackedTablePlan.steps.length > 0 && !rowControlsCovered) {
|
|
362907
|
+
throw diffValidationError("CAPABILITY_UNSUPPORTED", "diff.apply: row replay cannot cover content-control structure. No mutation was performed.", { changedFamilies: ["content-controls"], unsupportedReason: "content-control-replay-unsafe" });
|
|
362908
|
+
}
|
|
362909
|
+
if (changedPolicies.some((policy) => policy.family === "content-controls") && rowControlsCovered) {
|
|
362910
|
+
handledFamilies.add("content-controls");
|
|
362911
|
+
}
|
|
362116
362912
|
if (mainRevisionChangesHandled)
|
|
362117
362913
|
handledFamilies.add("tracked-changes");
|
|
362118
362914
|
if (mainDocumentPlan.steps.length > 0)
|
|
@@ -362289,6 +363085,23 @@ function buildCompareApplyEligibility(context, payload, plans) {
|
|
|
362289
363085
|
direct.add("fields-references");
|
|
362290
363086
|
tracked.add("fields-references");
|
|
362291
363087
|
}
|
|
363088
|
+
const usesLocalizedMainDocumentReplay = plans.sectionsReferencesPlan.sectionSteps.length > 0 || plans.sectionsReferencesPlan.referenceSteps.length > 0;
|
|
363089
|
+
if (usesLocalizedMainDocumentReplay) {
|
|
363090
|
+
const localizedBodyOperations = buildLocalizedBodyOperations(payload.base.body, payload.target.body, plans.sectionsReferencesPlan.sectionSteps, plans.sectionsReferencesPlan.referenceSteps, { base: payload.base.definitions, target: payload.target.definitions }, payload.applyPlan.bodyOperations);
|
|
363091
|
+
const localizedMainDocumentCovered = !plans.sectionsReferencesPlan.hasUnownedMainDocumentChanges || localizedMainDocumentChangesAreCovered({
|
|
363092
|
+
base: payload.mainDocument?.base ?? EMPTY_MAIN_DOCUMENT_SOURCE,
|
|
363093
|
+
target: payload.mainDocument?.target ?? EMPTY_MAIN_DOCUMENT_SOURCE,
|
|
363094
|
+
baseBody: payload.base.body,
|
|
363095
|
+
targetBody: payload.target.body,
|
|
363096
|
+
sectionSteps: plans.sectionsReferencesPlan.sectionSteps,
|
|
363097
|
+
referenceSteps: plans.sectionsReferencesPlan.referenceSteps,
|
|
363098
|
+
bodyOperations: localizedBodyOperations
|
|
363099
|
+
});
|
|
363100
|
+
if (localizedMainDocumentCovered) {
|
|
363101
|
+
direct.add("body");
|
|
363102
|
+
tracked.add("body");
|
|
363103
|
+
}
|
|
363104
|
+
}
|
|
362292
363105
|
}
|
|
362293
363106
|
const slotsChanged = plans.physicalPlan.hasReferenceIdChanges || payload.familyPolicy.some((policy) => policy.family === "header-footer-slots" && policy.applyRequired);
|
|
362294
363107
|
const slotPlan = slotsChanged ? buildHeaderFooterSlotPackageRewrite(context, payload.base.slots ?? [], payload.target.slots ?? [], plans.physicalPlan.refByPart) : { rewrites: [], unsafeReasons: [], operationCount: 0 };
|
|
@@ -362350,13 +363163,19 @@ function buildCompareApplyEligibility(context, payload, plans) {
|
|
|
362350
363163
|
const trackedTablePlan = buildTrackedTableRowReplayPlan({
|
|
362351
363164
|
base: mainDocument.base,
|
|
362352
363165
|
target: mainDocument.target,
|
|
363166
|
+
baseBody: payload.base.body,
|
|
362353
363167
|
targetBody: payload.target.body,
|
|
362354
|
-
bodyOperations: payload.applyPlan.bodyOperations
|
|
363168
|
+
bodyOperations: payload.applyPlan.bodyOperations.length > 0 ? payload.applyPlan.bodyOperations : computeCompareBodyOperations(payload.base.body, payload.target.body, {
|
|
363169
|
+
base: payload.base.definitions,
|
|
363170
|
+
target: payload.target.definitions
|
|
363171
|
+
})
|
|
362355
363172
|
});
|
|
362356
363173
|
if (trackedTablePlan.unsafeReasons.length === 0 && trackedTablePlan.steps.length > 0) {
|
|
362357
363174
|
tracked.add("tables");
|
|
362358
363175
|
if (bodyDeferredToTableReplay)
|
|
362359
363176
|
tracked.add("body");
|
|
363177
|
+
if (rowReplayCoversContentControls(payload.base.annotations, payload.target.annotations, trackedTablePlan.steps, mainDocument.base.xml, mainDocument.target.xml))
|
|
363178
|
+
tracked.add("content-controls");
|
|
362360
363179
|
}
|
|
362361
363180
|
}
|
|
362362
363181
|
const packageGraphCoveredByComments = direct.has("comments") && packageGraphKeysNotCoveredByComments(context, payload.base, payload.target, plans.commentPlan.steps).length === 0;
|
|
@@ -362414,7 +363233,16 @@ function buildCompareApplyEligibility(context, payload, plans) {
|
|
|
362414
363233
|
});
|
|
362415
363234
|
}
|
|
362416
363235
|
for (const mode of ["direct", "tracked"]) {
|
|
362417
|
-
|
|
363236
|
+
let runtimePlan = buildHeaderFooterRuntimeApplyPlan(payload, slotPlan, plans.physicalPlan, mode === "tracked");
|
|
363237
|
+
if (plans.sectionsReferencesPlan.unsafeReasons.length === 0 && (plans.sectionsReferencesPlan.sectionSteps.length > 0 || plans.sectionsReferencesPlan.referenceSteps.length > 0)) {
|
|
363238
|
+
runtimePlan = {
|
|
363239
|
+
...runtimePlan,
|
|
363240
|
+
applyPlan: {
|
|
363241
|
+
...runtimePlan.applyPlan,
|
|
363242
|
+
bodyOperations: buildLocalizedBodyOperations(payload.base.body, payload.target.body, plans.sectionsReferencesPlan.sectionSteps, plans.sectionsReferencesPlan.referenceSteps, { base: payload.base.definitions, target: payload.target.definitions }, payload.applyPlan.bodyOperations)
|
|
363243
|
+
}
|
|
363244
|
+
};
|
|
363245
|
+
}
|
|
362418
363246
|
const unsupportedFamilies = findStructurallyUnsupportedOperationFamilies(context, runtimePlan, payload.mainDocument?.base ?? EMPTY_MAIN_DOCUMENT_SOURCE, mode === "tracked", plans.sectionsReferencesPlan.referenceSteps);
|
|
362419
363247
|
if (unsupportedFamilies.length > 0) {
|
|
362420
363248
|
hazards[mode].push({
|
|
@@ -362958,7 +363786,8 @@ function buildLocalizedBodyOperations(base3, target, sectionSteps, referenceStep
|
|
|
362958
363786
|
throwLocalizedBodyCorrespondenceError(sectionSteps, referenceSteps);
|
|
362959
363787
|
const neutralTarget = target.map((entry) => {
|
|
362960
363788
|
const baseEntry = correspondence.baseByTargetId.get(entry.blockId);
|
|
362961
|
-
const
|
|
363789
|
+
const reversedRunXml = baseEntry?.runXml && entry.runXml ? referenceSteps.reduce((xml, step3) => reverseReferenceAttribute(xml, step3), entry.runXml) : entry.runXml;
|
|
363790
|
+
const neutralRunXml = baseEntry?.runXml && reversedRunXml && stripReplayNamespaceDeclarations(reversedRunXml) === stripReplayNamespaceDeclarations(baseEntry.runXml) ? baseEntry.runXml : reversedRunXml;
|
|
362962
363791
|
const neutralParagraphPropertiesXml = baseEntry?.paragraphPropertiesXml !== undefined && entry.paragraphPropertiesXml !== undefined ? sectionSteps.reduce((xml, step3) => reverseSectionProperties(xml, baseEntry.paragraphPropertiesXml, step3), entry.paragraphPropertiesXml) : entry.paragraphPropertiesXml;
|
|
362963
363792
|
if (neutralRunXml === entry.runXml && neutralParagraphPropertiesXml === entry.paragraphPropertiesXml)
|
|
362964
363793
|
return entry;
|
|
@@ -363025,6 +363854,17 @@ function reverseSectionProperties(targetParagraphPropertiesXml, baseParagraphPro
|
|
|
363025
363854
|
return targetParagraphPropertiesXml.slice(0, targetStart) + step3.beforeXml + targetParagraphPropertiesXml.slice(targetStart + step3.afterXml.length);
|
|
363026
363855
|
}
|
|
363027
363856
|
function reverseReferenceAttribute(xml, step3) {
|
|
363857
|
+
if (step3.kind === "bookmark-range" || step3.kind === "complex-field") {
|
|
363858
|
+
if (step3.beforeFragmentXml === undefined || step3.afterFragmentXml === undefined)
|
|
363859
|
+
return xml;
|
|
363860
|
+
const normalizedXml = stripReplayNamespaceDeclarations(xml);
|
|
363861
|
+
const after = stripReplayNamespaceDeclarations(step3.afterFragmentXml);
|
|
363862
|
+
const before = stripReplayNamespaceDeclarations(step3.beforeFragmentXml);
|
|
363863
|
+
const start = normalizedXml.indexOf(after);
|
|
363864
|
+
if (start < 0 || normalizedXml.indexOf(after, start + after.length) >= 0)
|
|
363865
|
+
return xml;
|
|
363866
|
+
return normalizedXml.slice(0, start) + before + normalizedXml.slice(start + after.length);
|
|
363867
|
+
}
|
|
363028
363868
|
const elementName = step3.kind === "bookmark-start" ? "bookmarkStart" : "fldSimple";
|
|
363029
363869
|
const localName2 = step3.kind === "bookmark-start" ? "name" : "instr";
|
|
363030
363870
|
const afterValue = readReplayAttribute(step3.afterXml, localName2, step3.afterNamespaceBindings);
|
|
@@ -363094,7 +363934,9 @@ function validateFullDiffCanonicalArtifacts(engine, payload) {
|
|
|
363094
363934
|
const problems = [];
|
|
363095
363935
|
let canonicalAnalysis;
|
|
363096
363936
|
try {
|
|
363097
|
-
|
|
363937
|
+
const rawAnalysis = engine.analyzeSnapshots(payload.base, payload.target);
|
|
363938
|
+
const comparisonTarget = paragraphIdentityOnlyComparisonTarget(payload.base, payload.target, payload.mainDocument?.base ?? EMPTY_MAIN_DOCUMENT_SOURCE, payload.mainDocument?.target ?? EMPTY_MAIN_DOCUMENT_SOURCE, rawAnalysis.result);
|
|
363939
|
+
canonicalAnalysis = comparisonTarget ? engine.analyzeSnapshots(payload.base, comparisonTarget) : rawAnalysis;
|
|
363098
363940
|
} catch (error48) {
|
|
363099
363941
|
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
363100
363942
|
return { problems: [`payload.base/target could not be re-analyzed (${message})`] };
|
|
@@ -363114,6 +363956,25 @@ function validateFullDiffCanonicalArtifacts(engine, payload) {
|
|
|
363114
363956
|
}
|
|
363115
363957
|
return { problems };
|
|
363116
363958
|
}
|
|
363959
|
+
function paragraphIdentityOnlyComparisonTarget(base3, target, baseDocument, targetDocument, rawAnalysis) {
|
|
363960
|
+
if (!baseDocument.xml || !targetDocument.xml || baseDocument.xml === targetDocument.xml)
|
|
363961
|
+
return null;
|
|
363962
|
+
const withoutParagraphIds = (xml) => xml.includes("<!DOCTYPE") ? xml : xml.replace(/<!\[CDATA\[[\s\S]*?\]\]>|<!--[\s\S]*?-->|<\?[\s\S]*?\?>|<[A-Za-z_](?:[^>"']|"[^"]*"|'[^']*')*>/g, (token) => token.startsWith("<!") || token.startsWith("<?") ? token : token.replace(/("[^"]*"|'[^']*')|(\s+w14:paraId="[0-9A-Fa-f]{8}")/g, (part, quotedValue) => quotedValue ?? "").replace(/\s+\/>$/, "/>"));
|
|
363963
|
+
if (withoutParagraphIds(baseDocument.xml) !== withoutParagraphIds(targetDocument.xml))
|
|
363964
|
+
return null;
|
|
363965
|
+
if (validateMainDocumentSourceAgainstSnapshotPart(baseDocument, base3, "base").length > 0 || validateMainDocumentSourceAgainstSnapshotPart(targetDocument, target, "target").length > 0)
|
|
363966
|
+
return null;
|
|
363967
|
+
const levels = (source) => new Map(Object.entries(source.paragraphStyleOutlineLevels ?? {}));
|
|
363968
|
+
if (validateMainDocumentSourceAgainstBodySnapshot(baseDocument, base3.body, { paragraphStyleOutlineLevels: levels(baseDocument) }).length > 0 || validateMainDocumentSourceAgainstBodySnapshot(targetDocument, target.body, { paragraphStyleOutlineLevels: levels(targetDocument) }).length > 0)
|
|
363969
|
+
return null;
|
|
363970
|
+
const otherParts = (snapshot2) => snapshot2.sourceInventory?.parts.filter((part) => part.partUri !== DOCUMENT_PART_URI6);
|
|
363971
|
+
if (!base3.sourceInventory || !target.sourceInventory || !artifactEquals(otherParts(base3), otherParts(target)))
|
|
363972
|
+
return null;
|
|
363973
|
+
const changedFamilies3 = rawAnalysis.families.filter((family) => family.state === "changed-supported");
|
|
363974
|
+
if (!changedFamilies3.some((family) => family.family === "tables") || changedFamilies3.some((family) => family.family !== "body" && family.family !== "tables"))
|
|
363975
|
+
return null;
|
|
363976
|
+
return { ...base3, identity: target.identity };
|
|
363977
|
+
}
|
|
363117
363978
|
function artifactEquals(left, right) {
|
|
363118
363979
|
return JSON.stringify(normalizeArtifactForCompare(left)) === JSON.stringify(normalizeArtifactForCompare(right));
|
|
363119
363980
|
}
|
|
@@ -363293,8 +364154,14 @@ function containsStructuralParagraphTag(xml, blockKind) {
|
|
|
363293
364154
|
return errors4.length === 0 ? found : null;
|
|
363294
364155
|
}
|
|
363295
364156
|
function findUniqueReplayCarrier(xml, step3) {
|
|
364157
|
+
if (step3.kind === "bookmark-range" || step3.kind === "complex-field") {
|
|
364158
|
+
const fragment3 = step3.afterFragmentXml;
|
|
364159
|
+
if (!fragment3)
|
|
364160
|
+
return null;
|
|
364161
|
+
const start = xml.indexOf(fragment3);
|
|
364162
|
+
return start >= 0 && xml.indexOf(fragment3, start + fragment3.length) < 0 ? { start, end: start + fragment3.length } : null;
|
|
364163
|
+
}
|
|
363296
364164
|
const expectedName = step3.kind === "bookmark-start" ? "bookmarkStart" : "fldSimple";
|
|
363297
|
-
const localName2 = step3.kind === "bookmark-start" ? "name" : "instr";
|
|
363298
364165
|
const parsed = collectXmlElementRanges(xml, {
|
|
363299
364166
|
fragment: true,
|
|
363300
364167
|
additionalNamespaces: { ...step3.beforeNamespaceBindings }
|
|
@@ -377122,13 +377989,7 @@ function normalizeParagraphBlock(value2, path7, version2, allowHeading) {
|
|
|
377122
377989
|
return normalized;
|
|
377123
377990
|
inlines.push(normalized);
|
|
377124
377991
|
}
|
|
377125
|
-
const projected = inlines.flatMap(
|
|
377126
|
-
if (inline.kind === "text")
|
|
377127
|
-
return [inline];
|
|
377128
|
-
if (inline.kind === "hyperlink")
|
|
377129
|
-
return inline.inlines.filter((child) => child.kind === "text");
|
|
377130
|
-
return [];
|
|
377131
|
-
});
|
|
377992
|
+
const projected = inlines.flatMap(projectInlineText);
|
|
377132
377993
|
if (projected.length !== runs.length || projected.some((inline, runIndex) => inline.text !== runs[runIndex]?.text || JSON.stringify(inline.marks ?? {}) !== JSON.stringify(runs[runIndex]?.marks ?? {}))) {
|
|
377133
377994
|
return structureFailure("Paragraph runs must equal the text projection of inlines.", path7);
|
|
377134
377995
|
}
|
|
@@ -377153,6 +378014,12 @@ function normalizeParagraphBlock(value2, path7, version2, allowHeading) {
|
|
|
377153
378014
|
const paragraphProps = normalizeParagraphProperties(value2.paragraphProps, [...path7, "paragraphProps"]);
|
|
377154
378015
|
if (isPlanFailure(paragraphProps))
|
|
377155
378016
|
return paragraphProps;
|
|
378017
|
+
const blockSdts = normalizeBlockSdts(value2.blockSdts, [...path7, "blockSdts"]);
|
|
378018
|
+
if (isPlanFailure(blockSdts))
|
|
378019
|
+
return blockSdts;
|
|
378020
|
+
if (blockSdts && (version2 !== SUPERDOC_V22_CLIPBOARD_FRAGMENT_VERSION || value2.complete !== true)) {
|
|
378021
|
+
return structureFailure("Complete block content controls require a v2.2 paragraph.", [...path7, "blockSdts"]);
|
|
378022
|
+
}
|
|
377156
378023
|
const sourcePath = normalizeSourcePath(value2.sourcePath, [...path7, "sourcePath"]);
|
|
377157
378024
|
if (isPlanFailure(sourcePath))
|
|
377158
378025
|
return sourcePath;
|
|
@@ -377167,16 +378034,83 @@ function normalizeParagraphBlock(value2, path7, version2, allowHeading) {
|
|
|
377167
378034
|
...typeof continuation === "number" ? { listItemContinuationLevel: continuation } : {},
|
|
377168
378035
|
...typeof value2.pPrXml === "string" && value2.pPrXml.length > 0 ? { pPrXml: value2.pPrXml } : {},
|
|
377169
378036
|
...value2.complete === true ? { complete: true } : {},
|
|
378037
|
+
...blockSdts ? { blockSdts } : {},
|
|
377170
378038
|
...sourcePath ? { sourcePath } : {}
|
|
377171
378039
|
};
|
|
377172
378040
|
return isHeading ? { kind: "heading", level: value2.level, ...common } : { kind: "paragraph", ...common };
|
|
377173
378041
|
}
|
|
377174
|
-
function
|
|
378042
|
+
function normalizeBlockSdts(value2, path7) {
|
|
378043
|
+
if (value2 === undefined)
|
|
378044
|
+
return;
|
|
378045
|
+
if (!Array.isArray(value2) || value2.length === 0 || value2.length > 16) {
|
|
378046
|
+
return structureFailure("Block content-control ancestry must contain 1 to 16 wrappers.", path7);
|
|
378047
|
+
}
|
|
378048
|
+
const ids = new Set;
|
|
378049
|
+
const result = [];
|
|
378050
|
+
for (const [index2, wrapper] of value2.entries()) {
|
|
378051
|
+
if (!isRecord15(wrapper) || typeof wrapper.sourceId !== "string" || !/^[0-9]{1,10}$/.test(wrapper.sourceId) || ids.has(wrapper.sourceId) || wrapper.controlType !== "text" && wrapper.controlType !== "richText" || !validSdtMetadata(wrapper) || wrapper.tag !== undefined && (typeof wrapper.tag !== "string" || wrapper.tag.length > 255 || !isXml10SafeAttributeValue(wrapper.tag)) || wrapper.alias !== undefined && (typeof wrapper.alias !== "string" || wrapper.alias.length > 255 || !isXml10SafeAttributeValue(wrapper.alias))) {
|
|
378052
|
+
return structureFailure("Invalid block content-control wrapper.", [...path7, index2]);
|
|
378053
|
+
}
|
|
378054
|
+
ids.add(wrapper.sourceId);
|
|
378055
|
+
result.push({
|
|
378056
|
+
sourceId: wrapper.sourceId,
|
|
378057
|
+
controlType: wrapper.controlType,
|
|
378058
|
+
...wrapper.tag !== undefined ? { tag: wrapper.tag } : {},
|
|
378059
|
+
...wrapper.alias !== undefined ? { alias: wrapper.alias } : {},
|
|
378060
|
+
...wrapper.lockMode !== undefined ? { lockMode: wrapper.lockMode } : {},
|
|
378061
|
+
...wrapper.multiline !== undefined ? { multiline: wrapper.multiline } : {}
|
|
378062
|
+
});
|
|
378063
|
+
}
|
|
378064
|
+
return result;
|
|
378065
|
+
}
|
|
378066
|
+
function validSdtMetadata(value2) {
|
|
378067
|
+
return (value2.lockMode === undefined || value2.lockMode === "unlocked" || value2.lockMode === "sdtLocked" || value2.lockMode === "contentLocked" || value2.lockMode === "sdtContentLocked") && (value2.multiline === undefined || value2.controlType === "text" && typeof value2.multiline === "boolean");
|
|
378068
|
+
}
|
|
378069
|
+
function projectInlineText(inline) {
|
|
378070
|
+
if (inline.kind === "text")
|
|
378071
|
+
return [inline];
|
|
378072
|
+
if (inline.kind === "sdt" || inline.kind === "hyperlink")
|
|
378073
|
+
return inline.inlines.flatMap(projectInlineText);
|
|
378074
|
+
return [];
|
|
378075
|
+
}
|
|
378076
|
+
function normalizeInline(value2, path7, allowHyperlink, depth = 0) {
|
|
377175
378077
|
if (!isRecord15(value2))
|
|
377176
378078
|
return structureFailure("Paste inlines must be objects.", path7);
|
|
378079
|
+
if (depth > 32)
|
|
378080
|
+
return structureFailure("Paste inline nesting exceeds the allowed depth.", path7);
|
|
377177
378081
|
const sourcePath = normalizeSourcePath(value2.sourcePath, [...path7, "sourcePath"]);
|
|
377178
378082
|
if (isPlanFailure(sourcePath))
|
|
377179
378083
|
return sourcePath;
|
|
378084
|
+
if (value2.kind === "sdt") {
|
|
378085
|
+
if (value2.controlType !== "text" && value2.controlType !== "richText" || !validSdtMetadata(value2) || !Array.isArray(value2.inlines) || value2.inlines.length === 0) {
|
|
378086
|
+
return structureFailure("Content controls require a supported type and nonempty inlines.", path7);
|
|
378087
|
+
}
|
|
378088
|
+
for (const key2 of ["tag", "alias"]) {
|
|
378089
|
+
if (value2[key2] !== undefined && (typeof value2[key2] !== "string" || value2[key2].length > 255 || !isXml10SafeAttributeValue(value2[key2]))) {
|
|
378090
|
+
return structureFailure(`Content control ${key2} must be XML-safe and at most 255 characters.`, [...path7, key2]);
|
|
378091
|
+
}
|
|
378092
|
+
}
|
|
378093
|
+
const inlines = [];
|
|
378094
|
+
for (const [index2, child] of value2.inlines.entries()) {
|
|
378095
|
+
const normalized = normalizeInline(child, [...path7, "inlines", index2], false, depth + 1);
|
|
378096
|
+
if (isPlanFailure(normalized))
|
|
378097
|
+
return normalized;
|
|
378098
|
+
if (normalized.kind !== "text" && normalized.kind !== "lineBreak" && normalized.kind !== "sdt") {
|
|
378099
|
+
return structureFailure("Unsupported content inside a content control.", [...path7, "inlines", index2]);
|
|
378100
|
+
}
|
|
378101
|
+
inlines.push(normalized);
|
|
378102
|
+
}
|
|
378103
|
+
return {
|
|
378104
|
+
kind: "sdt",
|
|
378105
|
+
controlType: value2.controlType,
|
|
378106
|
+
inlines,
|
|
378107
|
+
...typeof value2.tag === "string" ? { tag: value2.tag } : {},
|
|
378108
|
+
...typeof value2.alias === "string" ? { alias: value2.alias } : {},
|
|
378109
|
+
...value2.lockMode !== undefined ? { lockMode: value2.lockMode } : {},
|
|
378110
|
+
...value2.multiline !== undefined ? { multiline: value2.multiline } : {},
|
|
378111
|
+
...sourcePath ? { sourcePath } : {}
|
|
378112
|
+
};
|
|
378113
|
+
}
|
|
377180
378114
|
if (value2.kind === "text" && typeof value2.text === "string" && isXml10SafeString(value2.text)) {
|
|
377181
378115
|
if (value2.marks !== undefined && (!isRecord15(value2.marks) || Array.isArray(value2.marks))) {
|
|
377182
378116
|
return structureFailure("Paste run marks must be an object.", [...path7, "marks"]);
|
|
@@ -377234,8 +378168,8 @@ function normalizeInline(value2, path7, allowHyperlink) {
|
|
|
377234
378168
|
const normalized = normalizeInline(child, [...path7, "inlines", childIndex], false);
|
|
377235
378169
|
if (isPlanFailure(normalized))
|
|
377236
378170
|
return normalized;
|
|
377237
|
-
if (normalized.kind === "hyperlink")
|
|
377238
|
-
return structureFailure("Nested hyperlinks are not supported.", [...path7, "inlines", childIndex]);
|
|
378171
|
+
if (normalized.kind === "hyperlink" || normalized.kind === "sdt")
|
|
378172
|
+
return structureFailure("Nested hyperlinks and content controls are not supported.", [...path7, "inlines", childIndex]);
|
|
377239
378173
|
if (normalized.kind === "footnoteRef" || normalized.kind === "endnoteRef") {
|
|
377240
378174
|
return structureFailure("Note references cannot be nested inside hyperlinks.", [...path7, "inlines", childIndex]);
|
|
377241
378175
|
}
|
|
@@ -377680,6 +378614,9 @@ function normalizeTableBlock(block, index2, version2) {
|
|
|
377680
378614
|
const paragraph4 = normalizeParagraphBlock(cellBlock, ["blocks", index2, "rows", rowIndex, "cells", cellIndex, "blocks", cellBlockIndex], version2, false);
|
|
377681
378615
|
if (isPlanFailure(paragraph4))
|
|
377682
378616
|
return paragraph4;
|
|
378617
|
+
if (paragraph4.blockSdts?.length) {
|
|
378618
|
+
return structureFailure("Block content controls inside table cells are not supported.", ["blocks", index2, "rows", rowIndex, "cells", cellIndex, "blocks", cellBlockIndex, "blockSdts"]);
|
|
378619
|
+
}
|
|
377683
378620
|
cellBlocks.push(paragraph4);
|
|
377684
378621
|
}
|
|
377685
378622
|
cells.push({
|
|
@@ -378437,7 +379374,8 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378437
379374
|
code: "PRECONDITION_FAILED",
|
|
378438
379375
|
message: "story part bytes are unavailable."
|
|
378439
379376
|
};
|
|
378440
|
-
const boundaryMap = buildStructuralBoundaryMap(bytes
|
|
379377
|
+
const boundaryMap = buildStructuralBoundaryMap(bytes);
|
|
379378
|
+
const blockSdtWrappers = scanBlockSdtWrappers(SERIALIZE_TD.decode(bytes));
|
|
378441
379379
|
const hyperlinkDescriptorResolver = new SelectionHyperlinkDescriptorResolver(context, resolved.storyId);
|
|
378442
379380
|
let tableCatalog;
|
|
378443
379381
|
const notes = new SerializeNotes;
|
|
@@ -378500,6 +379438,7 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378500
379438
|
loadCatalog: loadCommentsCatalog
|
|
378501
379439
|
};
|
|
378502
379440
|
const tableCellPath = boundaryMap.byBlockId(entry.blockId)?.tableCellPath ?? [];
|
|
379441
|
+
const blockSdtPath = boundaryMap.byBlockId(entry.blockId)?.blockSdtPath ?? [];
|
|
378503
379442
|
const properties = readParagraphProperties(paragraphXml);
|
|
378504
379443
|
const fullyCovered = from === 0 && to === map3.visibleLength && (options?.wholeParagraphs === true || startEntry.ordinal !== endEntry.ordinal || properties.styleRef !== undefined || properties.numbering !== undefined || hasParagraphProperties(paragraphXml));
|
|
378505
379444
|
const styleModel = copyStyleModel ?? (copyStyleModel = compileCopyStyleModel(context));
|
|
@@ -378508,7 +379447,23 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378508
379447
|
const semanticHeadingLevel = semanticStyleRole?.startsWith("heading-") ? Number(semanticStyleRole.slice("heading-".length)) : null;
|
|
378509
379448
|
const parts = [];
|
|
378510
379449
|
let objectOrdinal = 0;
|
|
378511
|
-
for (const piece of map3.
|
|
379450
|
+
for (const piece of copySelectionPieces(map3.pieces)) {
|
|
379451
|
+
if (piece.kind === "container" && piece.containerKind === "sdt") {
|
|
379452
|
+
const sdt = from <= piece.visibleStart && piece.visibleEnd <= to ? serializeSdtPart(piece, from, to, notes, styleContext, review) : null;
|
|
379453
|
+
if (sdt) {
|
|
379454
|
+
parts.push(sdt);
|
|
379455
|
+
continue;
|
|
379456
|
+
}
|
|
379457
|
+
for (const leaf of copySelectionPieces(piece.children, false)) {
|
|
379458
|
+
if (leaf.visibleStart >= to || leaf.visibleEnd <= from)
|
|
379459
|
+
continue;
|
|
379460
|
+
notes.add("fields", "Content-control and field structure is not preserved by copy; visible text was kept.");
|
|
379461
|
+
const leafParts = [];
|
|
379462
|
+
walkPieces([leaf], from, to, leafParts, notes, styleContext, review);
|
|
379463
|
+
parts.push(...leafParts);
|
|
379464
|
+
}
|
|
379465
|
+
continue;
|
|
379466
|
+
}
|
|
378512
379467
|
if (isVisibleZeroWidthObjectPiece(piece)) {
|
|
378513
379468
|
const selected = fullyCovered || selectedObjectOrdinals?.has(objectOrdinal);
|
|
378514
379469
|
objectOrdinal += 1;
|
|
@@ -378588,8 +379543,18 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378588
379543
|
}
|
|
378589
379544
|
const pPrXml = fullyCovered ? materializeEffectivePPrXml(capturedPPrXml, properties.styleRef, copyParagraphPropertyModel ?? (copyParagraphPropertyModel = compileCopyParagraphPropertyXmlModel(context)), inTable ? "table" : "full", resolveRunMarks(extractParagraphMarkRPrXml(capturedPPrXml), styleContext), numbering != null) : null;
|
|
378590
379545
|
const listLevel = numbering ? Number.parseInt(numbering.ilvl, 10) : undefined;
|
|
379546
|
+
const blockSdts = blockSdtPath.map((ordinal) => {
|
|
379547
|
+
const wrapper = blockSdtWrappers.get(ordinal);
|
|
379548
|
+
if (!wrapper || !fullyCovered || tableCellPath.length > 0 || !wrapper.supported || index2.entries.some((candidate2) => boundaryMap.byBlockId(candidate2.blockId)?.blockSdtPath.includes(ordinal) && (candidate2.ordinal < startEntry.ordinal || candidate2.ordinal > endEntry.ordinal || candidate2.ordinal === startEntry.ordinal && startPoint.offset !== 0 || candidate2.ordinal === endEntry.ordinal && endPoint.offset !== parseParagraphInlineMap(SERIALIZE_TD.decode(bytes.subarray(endEntry.byteStart, endEntry.byteEnd))).visibleLength)))
|
|
379549
|
+
return null;
|
|
379550
|
+
return wrapper.properties;
|
|
379551
|
+
});
|
|
379552
|
+
if (blockSdtPath.length > 0 && blockSdts.some((wrapper) => wrapper === null)) {
|
|
379553
|
+
notes.add("block-sdt", "A partial or unsupported block content control was copied as visible text without its wrapper.");
|
|
379554
|
+
}
|
|
378591
379555
|
blocks.push({
|
|
378592
379556
|
blockId: entry.blockId,
|
|
379557
|
+
...blockSdts.length > 0 && blockSdts.every((wrapper) => wrapper !== null) ? { blockSdts } : {},
|
|
378593
379558
|
runs: parts.flatMap(serializedPartRuns),
|
|
378594
379559
|
...fullyCovered && properties.styleRef ? { styleRef: properties.styleRef } : {},
|
|
378595
379560
|
...fullyCovered && semanticStyleRole ? { semanticStyleRole } : {},
|
|
@@ -378639,14 +379604,16 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378639
379604
|
})), notes.diagnostics());
|
|
378640
379605
|
plan = buildPlan(fallbackFragment, "plain-text", notes.diagnostics(), true);
|
|
378641
379606
|
} else {
|
|
378642
|
-
const
|
|
379607
|
+
const hasPreservedControls = blocks.some((block) => !!block.blockSdts?.length || block.parts.some((part) => part.kind === "sdt"));
|
|
379608
|
+
const legacyDiagnostics = hasPreservedControls ? [...notes.diagnostics(), diagnostic("paste-no-faithful-representation", "The v2.1 clipboard flavor retains visible text but not content-control structure; use the v2.2 flavor to preserve controls.", "superdoc-v2-fragment", "warning")] : notes.diagnostics();
|
|
379609
|
+
const fragment3 = withPasteComments(buildFragment(grouped.map(fragmentBlockFor), legacyDiagnostics), commentsById);
|
|
378643
379610
|
items.push({
|
|
378644
379611
|
type: SUPERDOC_V2_CLIPBOARD_MIME,
|
|
378645
379612
|
kind: "string",
|
|
378646
379613
|
data: JSON.stringify(fragment3)
|
|
378647
379614
|
});
|
|
378648
379615
|
const assets = [...rich.assetsByPartUri.values()];
|
|
378649
|
-
const hasRichInlineStructure = blocks.some((block) => block.parts.some((part) => part.kind === "hyperlink" || part.kind === "image"));
|
|
379616
|
+
const hasRichInlineStructure = blocks.some((block) => !!block.blockSdts?.length || block.parts.some((part) => part.kind === "hyperlink" || part.kind === "image" || part.kind === "sdt"));
|
|
378650
379617
|
if (!rich.invalid && hasRichInlineStructure) {
|
|
378651
379618
|
const richBlocks = grouped.map(richFragmentBlockFor);
|
|
378652
379619
|
const wireFragment = withPasteComments({
|
|
@@ -378670,6 +379637,84 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378670
379637
|
}
|
|
378671
379638
|
};
|
|
378672
379639
|
}
|
|
379640
|
+
function topLevelChildrenCoverXml(xml, children2) {
|
|
379641
|
+
let cursor = 0;
|
|
379642
|
+
for (const child of children2) {
|
|
379643
|
+
const start = xml.indexOf(child.xml, cursor);
|
|
379644
|
+
if (start < 0 || xml.slice(cursor, start).trim().length > 0)
|
|
379645
|
+
return false;
|
|
379646
|
+
cursor = start + child.xml.length;
|
|
379647
|
+
}
|
|
379648
|
+
return xml.slice(cursor).trim().length === 0;
|
|
379649
|
+
}
|
|
379650
|
+
function parseSupportedSdtProperties(xml) {
|
|
379651
|
+
const children2 = parseTopLevelChildren(xml);
|
|
379652
|
+
if (!topLevelChildrenCoverXml(xml, children2))
|
|
379653
|
+
return null;
|
|
379654
|
+
const properties = { controlType: "richText" };
|
|
379655
|
+
let seenControlType = false;
|
|
379656
|
+
for (const child of children2) {
|
|
379657
|
+
if (child.prefix !== "w")
|
|
379658
|
+
return null;
|
|
379659
|
+
if (child.localName === "id") {
|
|
379660
|
+
if (!/^<w:id\b[^>]*\/>$/.test(child.xml))
|
|
379661
|
+
return null;
|
|
379662
|
+
} else if (child.localName === "tag" || child.localName === "alias") {
|
|
379663
|
+
if (!/^<w:(?:tag|alias)\b[^>]*\/>$/.test(child.xml))
|
|
379664
|
+
return null;
|
|
379665
|
+
const value2 = readBareAttribute(child.xml, "w:val");
|
|
379666
|
+
if (value2 === null || value2.length > 255)
|
|
379667
|
+
return null;
|
|
379668
|
+
properties[child.localName] = value2;
|
|
379669
|
+
} else if (child.localName === "lock") {
|
|
379670
|
+
const match = /^<w:lock\s+w:val=(['"])(unlocked|sdtLocked|contentLocked|sdtContentLocked)\1\s*\/>$/.exec(child.xml);
|
|
379671
|
+
if (!match || properties.lockMode !== undefined)
|
|
379672
|
+
return null;
|
|
379673
|
+
properties.lockMode = match[2];
|
|
379674
|
+
} else if (child.localName === "text") {
|
|
379675
|
+
const match = /^<w:text(?:\s+w:multiLine=(['"])(1|0|true|false|on|off)\1)?\s*\/>$/.exec(child.xml);
|
|
379676
|
+
if (!match || seenControlType)
|
|
379677
|
+
return null;
|
|
379678
|
+
seenControlType = true;
|
|
379679
|
+
properties.controlType = "text";
|
|
379680
|
+
if (match[2] !== undefined)
|
|
379681
|
+
properties.multiline = match[2] === "1" || match[2] === "true" || match[2] === "on";
|
|
379682
|
+
} else if (child.localName === "richText") {
|
|
379683
|
+
if (!/^<w:richText\s*\/>$/.test(child.xml) || seenControlType)
|
|
379684
|
+
return null;
|
|
379685
|
+
seenControlType = true;
|
|
379686
|
+
} else {
|
|
379687
|
+
return null;
|
|
379688
|
+
}
|
|
379689
|
+
}
|
|
379690
|
+
return properties;
|
|
379691
|
+
}
|
|
379692
|
+
function scanBlockSdtWrappers(xml) {
|
|
379693
|
+
const wrappers = new Map;
|
|
379694
|
+
const stack = [];
|
|
379695
|
+
const tokens = /<w:p\b[^>]*>[\s\S]*?<\/w:p\s*>|<w:sdt\b[^>]*>|<\/w:sdt\s*>/g;
|
|
379696
|
+
let ordinal = 0;
|
|
379697
|
+
for (const token of xml.matchAll(tokens)) {
|
|
379698
|
+
if (token[0].startsWith("<w:p"))
|
|
379699
|
+
continue;
|
|
379700
|
+
if (token[0].startsWith("</")) {
|
|
379701
|
+
const frame = stack.pop();
|
|
379702
|
+
if (!frame)
|
|
379703
|
+
continue;
|
|
379704
|
+
const wrapperXml = xml.slice(frame.start, token.index + token[0].length);
|
|
379705
|
+
const propertiesXml = /<w:sdtPr\b[^>]*>([\s\S]*?)<\/w:sdtPr>/.exec(wrapperXml)?.[1];
|
|
379706
|
+
const contentXml = /<w:sdtContent\b[^>]*>([\s\S]*)<\/w:sdtContent>/.exec(wrapperXml)?.[1];
|
|
379707
|
+
const children2 = contentXml === undefined ? [] : parseTopLevelChildren(contentXml);
|
|
379708
|
+
const parsedProperties = propertiesXml === undefined ? null : parseSupportedSdtProperties(propertiesXml);
|
|
379709
|
+
const properties = { sourceId: String(frame.ordinal), ...parsedProperties ?? { controlType: "richText" } };
|
|
379710
|
+
const supported = parsedProperties !== null && contentXml !== undefined && children2.length > 0 && children2.every((child) => child.prefix === "w" && (child.localName === "p" || child.localName === "sdt")) && topLevelChildrenCoverXml(contentXml, children2);
|
|
379711
|
+
wrappers.set(frame.ordinal, { properties, supported });
|
|
379712
|
+
} else {
|
|
379713
|
+
stack.push({ ordinal: ordinal++, start: token.index });
|
|
379714
|
+
}
|
|
379715
|
+
}
|
|
379716
|
+
return wrappers;
|
|
379717
|
+
}
|
|
378673
379718
|
function serializeSelectedDrawing(input) {
|
|
378674
379719
|
const fail6 = (key2, message) => {
|
|
378675
379720
|
input.notes.add(key2, message);
|
|
@@ -378842,7 +379887,7 @@ function appendSerializedParts(out, parts, hyperlink) {
|
|
|
378842
379887
|
function serializedPartRuns(part) {
|
|
378843
379888
|
if (part.kind === "run")
|
|
378844
379889
|
return [part.run];
|
|
378845
|
-
if (part.kind === "hyperlink")
|
|
379890
|
+
if (part.kind === "hyperlink" || part.kind === "sdt")
|
|
378846
379891
|
return part.parts.flatMap(serializedPartRuns);
|
|
378847
379892
|
return [];
|
|
378848
379893
|
}
|
|
@@ -378868,6 +379913,48 @@ function noteContainingStructures(piece, notes, preservesHyperlink) {
|
|
|
378868
379913
|
}
|
|
378869
379914
|
return supported;
|
|
378870
379915
|
}
|
|
379916
|
+
function copySelectionPieces(pieces, stopAtSdt = true) {
|
|
379917
|
+
return pieces.flatMap((piece) => {
|
|
379918
|
+
if (piece.kind === "container" && piece.containerKind === "sdt" && stopAtSdt)
|
|
379919
|
+
return [piece];
|
|
379920
|
+
if (piece.kind === "container" || piece.kind === "tracked") {
|
|
379921
|
+
if (piece.kind === "container" && piece.policy === "atomic")
|
|
379922
|
+
return [piece];
|
|
379923
|
+
return copySelectionPieces(piece.children, stopAtSdt);
|
|
379924
|
+
}
|
|
379925
|
+
return [piece];
|
|
379926
|
+
});
|
|
379927
|
+
}
|
|
379928
|
+
function serializeSdtPart(piece, from, to, notes, styleContext, review) {
|
|
379929
|
+
const propertiesXml = /<w:sdtPr\b[^>]*>([\s\S]*?)<\/w:sdtPr>/.exec(piece.rawXml)?.[1];
|
|
379930
|
+
if (propertiesXml === undefined)
|
|
379931
|
+
return null;
|
|
379932
|
+
const properties = parseSupportedSdtProperties(propertiesXml);
|
|
379933
|
+
if (!properties)
|
|
379934
|
+
return null;
|
|
379935
|
+
const parts = [];
|
|
379936
|
+
for (const child of piece.children) {
|
|
379937
|
+
if (child.kind === "container" && child.containerKind === "sdt") {
|
|
379938
|
+
if (child.visibleStart < from || child.visibleEnd > to)
|
|
379939
|
+
return null;
|
|
379940
|
+
const nested = serializeSdtPart(child, from, to, notes, styleContext, review);
|
|
379941
|
+
if (!nested)
|
|
379942
|
+
return null;
|
|
379943
|
+
parts.push(nested);
|
|
379944
|
+
} else if (child.kind === "text" || child.kind === "control") {
|
|
379945
|
+
if (child.kind === "text" && child.textRole !== "visible")
|
|
379946
|
+
return null;
|
|
379947
|
+
const leaves = [];
|
|
379948
|
+
walkPieces([child], from, to, leaves, notes, styleContext, review);
|
|
379949
|
+
parts.push(...leaves);
|
|
379950
|
+
} else {
|
|
379951
|
+
return null;
|
|
379952
|
+
}
|
|
379953
|
+
}
|
|
379954
|
+
if (!parts.length)
|
|
379955
|
+
return null;
|
|
379956
|
+
return { kind: "sdt", ...properties, parts };
|
|
379957
|
+
}
|
|
378871
379958
|
|
|
378872
379959
|
class SerializeNotes {
|
|
378873
379960
|
constructor() {
|
|
@@ -379479,10 +380566,34 @@ function paragraphFragmentFor(block) {
|
|
|
379479
380566
|
function richParagraphFragmentFor(block) {
|
|
379480
380567
|
return {
|
|
379481
380568
|
...paragraphFragmentFor(block),
|
|
380569
|
+
...block.blockSdts ? { blockSdts: block.blockSdts } : {},
|
|
379482
380570
|
inlines: block.parts.flatMap(serializedPartInlines)
|
|
379483
380571
|
};
|
|
379484
380572
|
}
|
|
380573
|
+
function serializedSdtChildInline(part) {
|
|
380574
|
+
if (part.kind === "sdt")
|
|
380575
|
+
return {
|
|
380576
|
+
kind: "sdt",
|
|
380577
|
+
controlType: part.controlType,
|
|
380578
|
+
...part.tag !== undefined ? { tag: part.tag } : {},
|
|
380579
|
+
...part.alias !== undefined ? { alias: part.alias } : {},
|
|
380580
|
+
...part.lockMode !== undefined ? { lockMode: part.lockMode } : {},
|
|
380581
|
+
...part.multiline !== undefined ? { multiline: part.multiline } : {},
|
|
380582
|
+
inlines: part.parts.map(serializedSdtChildInline)
|
|
380583
|
+
};
|
|
380584
|
+
return serializedLeafPartInline(part);
|
|
380585
|
+
}
|
|
379485
380586
|
function serializedPartInlines(part) {
|
|
380587
|
+
if (part.kind === "sdt")
|
|
380588
|
+
return [{
|
|
380589
|
+
kind: "sdt",
|
|
380590
|
+
controlType: part.controlType,
|
|
380591
|
+
...part.tag !== undefined ? { tag: part.tag } : {},
|
|
380592
|
+
...part.alias !== undefined ? { alias: part.alias } : {},
|
|
380593
|
+
...part.lockMode !== undefined ? { lockMode: part.lockMode } : {},
|
|
380594
|
+
...part.multiline !== undefined ? { multiline: part.multiline } : {},
|
|
380595
|
+
inlines: part.parts.map(serializedSdtChildInline)
|
|
380596
|
+
}];
|
|
379486
380597
|
if (part.kind !== "hyperlink")
|
|
379487
380598
|
return [serializedLeafPartInline(part)];
|
|
379488
380599
|
return [
|
|
@@ -379540,7 +380651,7 @@ function serializedPartPlainText(part) {
|
|
|
379540
380651
|
`;
|
|
379541
380652
|
if (part.kind === "run")
|
|
379542
380653
|
return part.run.text;
|
|
379543
|
-
if (part.kind === "hyperlink")
|
|
380654
|
+
if (part.kind === "hyperlink" || part.kind === "sdt")
|
|
379544
380655
|
return part.parts.map(serializedPartPlainText).join("");
|
|
379545
380656
|
return "";
|
|
379546
380657
|
}
|
|
@@ -379564,6 +380675,8 @@ function renderHtmlPart(part) {
|
|
|
379564
380675
|
return renderHtmlRun(part.run);
|
|
379565
380676
|
if (part.kind === "image")
|
|
379566
380677
|
return "";
|
|
380678
|
+
if (part.kind === "sdt")
|
|
380679
|
+
return part.parts.map(renderHtmlPart).join("");
|
|
379567
380680
|
const href = part.target.kind === "external" ? part.target.url : `#${part.target.anchor}`;
|
|
379568
380681
|
const title = part.tooltip ? ` title="${escapeHtmlAttribute3(part.tooltip)}"` : "";
|
|
379569
380682
|
return `<a href="${escapeHtmlAttribute3(href)}"${title}>${part.parts.map(renderHtmlPart).join("")}</a>`;
|
|
@@ -380720,8 +381833,8 @@ function materializeMetadataAnchor(documentXml, sdt, id) {
|
|
|
380720
381833
|
const para = findParagraphContaining2(documentXml, sdt.start);
|
|
380721
381834
|
if (!para)
|
|
380722
381835
|
return null;
|
|
380723
|
-
const startOffset =
|
|
380724
|
-
const length =
|
|
381836
|
+
const startOffset = extractVisibleTextFromXml2(para.xml.slice(0, sdt.start - para.start)).length;
|
|
381837
|
+
const length = extractVisibleTextFromXml2(unwrapSdt(sdt.xml) ?? sdt.xml).length;
|
|
380725
381838
|
const endOffset = startOffset + length;
|
|
380726
381839
|
return {
|
|
380727
381840
|
id,
|
|
@@ -380906,7 +382019,7 @@ function wrapTextRangeWithMetadataSdt(paragraphXml, start, end, id, sdtId) {
|
|
|
380906
382019
|
}
|
|
380907
382020
|
function metadataSdtOpenXml(id, sdtId) {
|
|
380908
382021
|
return [
|
|
380909
|
-
|
|
382022
|
+
`<w:sdt xmlns:w15="${W15_NS}"><w:sdtPr>`,
|
|
380910
382023
|
`<w:id w:val="${sdtId}"/>`,
|
|
380911
382024
|
`<w:alias w:val="${xmlEscapeAttr(METADATA_ANCHOR_ALIAS)}"/>`,
|
|
380912
382025
|
`<w:tag w:val="${xmlEscapeAttr(id)}"/>`,
|
|
@@ -381003,13 +382116,6 @@ function unwrapSdt(sdtXml) {
|
|
|
381003
382116
|
}
|
|
381004
382117
|
return null;
|
|
381005
382118
|
}
|
|
381006
|
-
function extractText4(xml) {
|
|
381007
|
-
let out = "";
|
|
381008
|
-
const re = /<w:t\b[^>]*>([\s\S]*?)<\/w:t>/g;
|
|
381009
|
-
for (let match = re.exec(xml);match; match = re.exec(xml))
|
|
381010
|
-
out += decodeXmlEntities(match[1]);
|
|
381011
|
-
return out;
|
|
381012
|
-
}
|
|
381013
382119
|
function replaceRange3(xml, start, end, replacement) {
|
|
381014
382120
|
return `${xml.slice(0, start)}${replacement}${xml.slice(end)}`;
|
|
381015
382121
|
}
|
|
@@ -381042,6 +382148,7 @@ var TEXT_ENCODER2, METADATA_ANCHOR_ALIAS = "Anchored metadata", W15_NS = "http:/
|
|
|
381042
382148
|
var init_adapter38 = __esm(() => {
|
|
381043
382149
|
init_src3();
|
|
381044
382150
|
init_sd_document_session_internal();
|
|
382151
|
+
init_visible_text();
|
|
381045
382152
|
init_inline();
|
|
381046
382153
|
init_adapter2();
|
|
381047
382154
|
init_shared();
|