@superdoc/mcp 1.2.0-next.12 → 1.2.0-next.14
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 +1378 -208
- 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.14";
|
|
31318
31318
|
|
|
31319
31319
|
// ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
|
|
31320
31320
|
import { chmodSync, existsSync } from "node:fs";
|
|
@@ -134832,26 +134832,68 @@ function canonicalName(namespace, localName2) {
|
|
|
134832
134832
|
return `xml:${localName2}`;
|
|
134833
134833
|
return namespace ? `{${namespace}}${localName2}` : localName2;
|
|
134834
134834
|
}
|
|
134835
|
-
function
|
|
134836
|
-
const
|
|
134837
|
-
const
|
|
134838
|
-
|
|
134839
|
-
|
|
134840
|
-
|
|
134841
|
-
|
|
134842
|
-
|
|
134843
|
-
|
|
134844
|
-
|
|
134845
|
-
|
|
134846
|
-
|
|
134847
|
-
|
|
134848
|
-
|
|
134849
|
-
|
|
134850
|
-
|
|
134851
|
-
|
|
134852
|
-
|
|
134835
|
+
function normalizeBalancedBookmarkIds(canonicalXmls) {
|
|
134836
|
+
const starts = new Map;
|
|
134837
|
+
const ends = new Set;
|
|
134838
|
+
const names = new Set;
|
|
134839
|
+
for (const xml of canonicalXmls) {
|
|
134840
|
+
const tags = [...xml.matchAll(BOOKMARK_TAG_RE)];
|
|
134841
|
+
if (tags.length !== [...xml.matchAll(BOOKMARK_OPENING_RE)].length)
|
|
134842
|
+
return canonicalXmls;
|
|
134843
|
+
for (const tag of tags) {
|
|
134844
|
+
if (tag[1] || !tag[0].endsWith("/>"))
|
|
134845
|
+
return canonicalXmls;
|
|
134846
|
+
const attributes = [...tag[3].matchAll(ATTRIBUTE_RE)];
|
|
134847
|
+
const ids = attributes.filter((attribute) => attribute[1] === "w:id");
|
|
134848
|
+
const bookmarkNames = attributes.filter((attribute) => attribute[1] === "w:name");
|
|
134849
|
+
const id = ids[0]?.[2] ?? ids[0]?.[3];
|
|
134850
|
+
if (ids.length !== 1 || !id || !/^\d+$/u.test(id))
|
|
134851
|
+
return canonicalXmls;
|
|
134852
|
+
if (tag[2] === "Start") {
|
|
134853
|
+
const name = bookmarkNames[0]?.[2] ?? bookmarkNames[0]?.[3];
|
|
134854
|
+
if (bookmarkNames.length !== 1 || !name || starts.has(id) || names.has(name))
|
|
134855
|
+
return canonicalXmls;
|
|
134856
|
+
starts.set(id, name);
|
|
134857
|
+
names.add(name);
|
|
134858
|
+
} else {
|
|
134859
|
+
if (bookmarkNames.length > 0 || !starts.has(id) || ends.has(id))
|
|
134860
|
+
return canonicalXmls;
|
|
134861
|
+
ends.add(id);
|
|
134862
|
+
}
|
|
134863
|
+
}
|
|
134853
134864
|
}
|
|
134854
|
-
|
|
134865
|
+
if (starts.size !== ends.size)
|
|
134866
|
+
return canonicalXmls;
|
|
134867
|
+
return canonicalXmls.map((xml) => xml.replace(BOOKMARK_TAG_RE, (tag, _closing, _kind, attributes) => {
|
|
134868
|
+
const id = /\bw:id="([^"]*)"/u.exec(attributes)[1];
|
|
134869
|
+
return tag.replace(/\bw:id="[^"]*"/u, `w:id=${JSON.stringify(`bookmark:${starts.get(id)}`)}`);
|
|
134870
|
+
}));
|
|
134871
|
+
}
|
|
134872
|
+
function computeRunSignatures(runXmls) {
|
|
134873
|
+
const canonicalXmls = normalizeBalancedBookmarkIds(runXmls.map(canonicalizeXmlForSignature));
|
|
134874
|
+
return canonicalXmls.map((canonicalXml) => {
|
|
134875
|
+
const normalized = normalizeRunXmlForSignature(canonicalXml.replace(REVISION_ATTR_RE, (attribute, offset, xml) => {
|
|
134876
|
+
const precedingTag = xml.slice(xml.lastIndexOf("<", offset), offset);
|
|
134877
|
+
return /^<w:proofErr(?:\s|$)/.test(precedingTag) ? attribute : "";
|
|
134878
|
+
}).replace(REVISION_ELEMENT_RE, (markup) => markup.replace(REVISION_ID_ATTR_RE, "")).replace(COMMENT_MARKUP_RE, (markup, name, attributes) => isWordprocessingElement3(name, attributes, canonicalXml) ? "" : markup).replace(NOTE_REFERENCE_MARKUP_RE, (markup, runName, runAttributes, _rPrName, nestedName, nestedAttributes, standaloneName, standaloneAttributes) => {
|
|
134879
|
+
const name = nestedName ?? standaloneName;
|
|
134880
|
+
const attributes = nestedAttributes ?? standaloneAttributes;
|
|
134881
|
+
if (!isWordprocessingElement3(name, attributes, canonicalXml))
|
|
134882
|
+
return markup;
|
|
134883
|
+
if (runName && !isWordprocessingElement3(runName, runAttributes, canonicalXml))
|
|
134884
|
+
return markup;
|
|
134885
|
+
return "";
|
|
134886
|
+
}));
|
|
134887
|
+
let hash2 = 2166136261;
|
|
134888
|
+
for (let i = 0;i < normalized.length; i += 1) {
|
|
134889
|
+
hash2 ^= normalized.charCodeAt(i);
|
|
134890
|
+
hash2 = Math.imul(hash2, 16777619) >>> 0;
|
|
134891
|
+
}
|
|
134892
|
+
return `v2-run-${hash2.toString(16).padStart(8, "0")}`;
|
|
134893
|
+
});
|
|
134894
|
+
}
|
|
134895
|
+
function computeRunSignature(runXml) {
|
|
134896
|
+
return computeRunSignatures([runXml])[0];
|
|
134855
134897
|
}
|
|
134856
134898
|
function normalizeRunXmlForSignature(runXml) {
|
|
134857
134899
|
const pieces = [];
|
|
@@ -134934,7 +134976,7 @@ function isWordprocessingElement3(name, attributes, namespaceContext) {
|
|
|
134934
134976
|
return true;
|
|
134935
134977
|
return (declaration[2] ?? declaration[3] ?? "") === WORDPROCESSINGML_NAMESPACE2;
|
|
134936
134978
|
}
|
|
134937
|
-
var REVISION_ATTR_RE, REVISION_ELEMENT_RE, REVISION_ID_ATTR_RE, COMMENT_MARKUP_RE, PROOFING_BOUNDARY_MARKUP_RE, NOTE_REFERENCE_MARKUP_RE, RUN_RE, RUN_PROPERTIES_RE, EMPTY_RUN_PROPERTIES_RE, TEXTISH_RE, RUN_CONTROL_RE, ATTRIBUTE_RE, WORDPROCESSINGML_NAMESPACE2 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", WORDPROCESSINGML_2010_NAMESPACE = "http://schemas.microsoft.com/office/word/2010/wordml", MARKUP_COMPATIBILITY_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006", XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace", XML_TAG_RE;
|
|
134979
|
+
var REVISION_ATTR_RE, REVISION_ELEMENT_RE, REVISION_ID_ATTR_RE, COMMENT_MARKUP_RE, PROOFING_BOUNDARY_MARKUP_RE, NOTE_REFERENCE_MARKUP_RE, RUN_RE, RUN_PROPERTIES_RE, EMPTY_RUN_PROPERTIES_RE, TEXTISH_RE, RUN_CONTROL_RE, ATTRIBUTE_RE, WORDPROCESSINGML_NAMESPACE2 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", WORDPROCESSINGML_2010_NAMESPACE = "http://schemas.microsoft.com/office/word/2010/wordml", MARKUP_COMPATIBILITY_NAMESPACE = "http://schemas.openxmlformats.org/markup-compatibility/2006", XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace", XML_TAG_RE, BOOKMARK_OPENING_RE, BOOKMARK_TAG_RE;
|
|
134938
134980
|
var init_run_signature = __esm(() => {
|
|
134939
134981
|
REVISION_ATTR_RE = /\s+(?:w:rsid\w*|w14:paraId|w14:textId)="[^"]*"/g;
|
|
134940
134982
|
REVISION_ELEMENT_RE = /<w:(?:ins|del|moveFrom|moveTo)\b[^>]*>/g;
|
|
@@ -134949,6 +134991,8 @@ var init_run_signature = __esm(() => {
|
|
|
134949
134991
|
RUN_CONTROL_RE = /<((?:[\w.-]+:)?(tab|br|cr))\b([^>]*)\/>/g;
|
|
134950
134992
|
ATTRIBUTE_RE = /([\w.:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
134951
134993
|
XML_TAG_RE = /<(\/?)(([A-Za-z_][\w.-]*)(?::([A-Za-z_][\w.-]*))?)((?:(?:"[^"]*"|'[^']*'|[^>"'])*))>/g;
|
|
134994
|
+
BOOKMARK_OPENING_RE = /<\/?w:bookmark(?:Start|End)\b/g;
|
|
134995
|
+
BOOKMARK_TAG_RE = /<(\/?)w:bookmark(Start|End)\b((?:"[^"]*"|[^">])*)>/g;
|
|
134952
134996
|
});
|
|
134953
134997
|
|
|
134954
134998
|
// ../../../v2/document-compare/src/note-story-projection.ts
|
|
@@ -134960,7 +135004,7 @@ function projectCapturedNoteStoryEntries(value) {
|
|
|
134960
135004
|
const ranges = collectWordParagraphRanges(value.notePartXml);
|
|
134961
135005
|
if (!ranges)
|
|
134962
135006
|
return null;
|
|
134963
|
-
|
|
135007
|
+
const entries = ranges.flatMap((range, ordinal) => {
|
|
134964
135008
|
if (range.start < noteStart || range.end > noteEnd)
|
|
134965
135009
|
return [];
|
|
134966
135010
|
const paragraphXml = value.notePartXml.slice(range.start, range.end);
|
|
@@ -134974,12 +135018,13 @@ function projectCapturedNoteStoryEntries(value) {
|
|
|
134974
135018
|
text: visibleParagraphText(paragraphXml, range.namespaceBindings),
|
|
134975
135019
|
headingLevel: metadata2.headingLevel,
|
|
134976
135020
|
styleId: metadata2.styleId,
|
|
134977
|
-
runSignature: computeRunSignature(runXml),
|
|
134978
135021
|
runXml,
|
|
134979
135022
|
paragraphPropertiesXml,
|
|
134980
135023
|
paragraphPropertiesSignature: computeParagraphPropertiesSignature(paragraphPropertiesXml)
|
|
134981
135024
|
}];
|
|
134982
135025
|
});
|
|
135026
|
+
const runSignatures = computeRunSignatures(entries.map((entry) => entry.runXml ?? ""));
|
|
135027
|
+
return entries.map((entry, index) => ({ ...entry, runSignature: runSignatures[index] }));
|
|
134983
135028
|
}
|
|
134984
135029
|
function collectWordParagraphRanges(xml) {
|
|
134985
135030
|
let valid = true;
|
|
@@ -188376,6 +188421,8 @@ function renderPasteParagraphBlock(spec) {
|
|
|
188376
188421
|
return `<w:p${nsDecl} w14:paraId="${escapeXmlAttribute(spec.paraId)}">${pPr}${renderPasteRuns(spec.runs)}</w:p>`;
|
|
188377
188422
|
}
|
|
188378
188423
|
function renderReviewAwarePasteRun(run, stamp) {
|
|
188424
|
+
if (run.kind === "sdt")
|
|
188425
|
+
return renderPasteSdt(run, stamp);
|
|
188379
188426
|
let xml = renderPasteRun(run);
|
|
188380
188427
|
if (!("text" in run))
|
|
188381
188428
|
return xml;
|
|
@@ -188516,6 +188563,11 @@ function renderTrackedPasteRuns(runs, stamp) {
|
|
|
188516
188563
|
out.push(wrapTrackedInsertion(inner, stamp));
|
|
188517
188564
|
};
|
|
188518
188565
|
for (const run of runs) {
|
|
188566
|
+
if (run.kind === "sdt") {
|
|
188567
|
+
flushOrdinary();
|
|
188568
|
+
out.push(wrapTrackedInsertion(renderPasteSdt(run), stamp));
|
|
188569
|
+
continue;
|
|
188570
|
+
}
|
|
188519
188571
|
if (run.kind !== "hyperlink") {
|
|
188520
188572
|
if (run.kind === "footnoteRef" || run.kind === "endnoteRef") {
|
|
188521
188573
|
flushOrdinary();
|
|
@@ -188581,6 +188633,8 @@ function renderPasteTableCell(cell, renderParagraph = renderPasteParagraphBlock)
|
|
|
188581
188633
|
return `<w:tc>${tcPr}${cell.paragraphs.map(renderParagraph).join("")}</w:tc>`;
|
|
188582
188634
|
}
|
|
188583
188635
|
function renderPasteRun(run, options = {}) {
|
|
188636
|
+
if (run.kind === "sdt")
|
|
188637
|
+
return renderPasteSdt(run);
|
|
188584
188638
|
if (run.kind === "image")
|
|
188585
188639
|
return run.xml;
|
|
188586
188640
|
if (run.kind === "hyperlink")
|
|
@@ -188611,6 +188665,32 @@ function renderPasteRun(run, options = {}) {
|
|
|
188611
188665
|
}
|
|
188612
188666
|
return out.join("");
|
|
188613
188667
|
}
|
|
188668
|
+
function renderPasteSdt(run, stamp) {
|
|
188669
|
+
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}/>`);
|
|
188670
|
+
return `<w:sdt><w:sdtPr>${properties}</w:sdtPr><w:sdtContent>${renderPasteRuns(run.runs, stamp)}</w:sdtContent></w:sdt>`;
|
|
188671
|
+
}
|
|
188672
|
+
function renderBlockSdtSequence(blocks, xml, ids) {
|
|
188673
|
+
let result = "";
|
|
188674
|
+
let previous = [];
|
|
188675
|
+
for (let index = 0;index <= blocks.length; index += 1) {
|
|
188676
|
+
const block = blocks[index];
|
|
188677
|
+
const current = block && "blockSdts" in block ? block.blockSdts ?? [] : [];
|
|
188678
|
+
let shared = 0;
|
|
188679
|
+
while (shared < previous.length && shared < current.length && previous[shared].sourceId === current[shared].sourceId)
|
|
188680
|
+
shared += 1;
|
|
188681
|
+
for (let depth = previous.length - 1;depth >= shared; depth -= 1)
|
|
188682
|
+
result += "</w:sdtContent></w:sdt>";
|
|
188683
|
+
for (let depth = shared;depth < current.length; depth += 1) {
|
|
188684
|
+
const wrapper = current[depth];
|
|
188685
|
+
const id = ids.get(wrapper.sourceId);
|
|
188686
|
+
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>";
|
|
188687
|
+
}
|
|
188688
|
+
if (index < blocks.length)
|
|
188689
|
+
result += xml[index];
|
|
188690
|
+
previous = current;
|
|
188691
|
+
}
|
|
188692
|
+
return result;
|
|
188693
|
+
}
|
|
188614
188694
|
function renderPasteHyperlink(run) {
|
|
188615
188695
|
const targetAttribute = run.target.kind === "external" ? `r:id="${escapeXmlAttribute(run.target.relationshipId ?? "")}"` : `w:anchor="${escapeXmlAttribute(run.target.anchor)}"`;
|
|
188616
188696
|
const tooltipAttribute = run.tooltip ? ` w:tooltip="${escapeXmlAttribute(run.tooltip)}"` : "";
|
|
@@ -189891,6 +189971,18 @@ function compileParsedOverlapEdit(input, tokens, descendedEditableContainers) {
|
|
|
189891
189971
|
});
|
|
189892
189972
|
token._classification = input.existingRevisionOwnership === "foreign" ? "different-user" : classifyOwnership(current, wrapperAuthor);
|
|
189893
189973
|
}
|
|
189974
|
+
const commented = wrappers.filter((entry) => entry.token.kind === "ins" && entry.token.commentedBoundary != null);
|
|
189975
|
+
if (commented.length > 0) {
|
|
189976
|
+
const parent = commented[0].token;
|
|
189977
|
+
const following = touched.filter((entry) => entry.token.kind === "plain");
|
|
189978
|
+
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) {
|
|
189979
|
+
return {
|
|
189980
|
+
ok: false,
|
|
189981
|
+
reason: "text-range-in-unsupported-tracked-wrapper",
|
|
189982
|
+
detail: "overlap compiler: comment-bearing insertion requires a bounded foreign spanning replacement."
|
|
189983
|
+
};
|
|
189984
|
+
}
|
|
189985
|
+
}
|
|
189894
189986
|
if (input.newText.length > 0 && input.rangeStart < input.rangeEnd) {
|
|
189895
189987
|
const spanningReplacement = tryRangeReplacementAcrossTokens(input, tokens, touched);
|
|
189896
189988
|
if (spanningReplacement)
|
|
@@ -190531,8 +190623,21 @@ function authorTrackedPureDelete(input, allTokens, touched, touchedBreaks = [])
|
|
|
190531
190623
|
author: currentAuthor,
|
|
190532
190624
|
date: input.txTimestamp,
|
|
190533
190625
|
rsidDel: input.rsid,
|
|
190534
|
-
inner: { runOpen: token.inner.runOpen, runClose: token.inner.runClose, rPr: token.inner.rPr, text: removed }
|
|
190626
|
+
inner: { runOpen: token.inner.runOpen, runClose: token.inner.runClose, rPr: token.inner.rPr, text: removed },
|
|
190627
|
+
...token.commentedBoundary ? {
|
|
190628
|
+
innerXml: renderDelRun(removed, token.inner.runOpen, token.inner.runClose, token.inner.rPr) + token.commentedBoundary.endXml + token.commentedBoundary.referenceRunXml
|
|
190629
|
+
} : {}
|
|
190535
190630
|
});
|
|
190631
|
+
if (token.commentedBoundary) {
|
|
190632
|
+
if (!childIns || tail.length > 0)
|
|
190633
|
+
return null;
|
|
190634
|
+
pieces.push(token.commentedBoundary.startXml + token.openTag + nestedHead + childDel + token.closeTag + childIns);
|
|
190635
|
+
replacementInserted = true;
|
|
190636
|
+
if (!emittedRsids.includes(input.insRsid))
|
|
190637
|
+
emittedRsids.push(input.insRsid);
|
|
190638
|
+
emitDeletionRsid();
|
|
190639
|
+
continue;
|
|
190640
|
+
}
|
|
190536
190641
|
if (childIns) {
|
|
190537
190642
|
const headIns = head.length > 0 ? buildInsWrapperXml({
|
|
190538
190643
|
openTag: token.openTag,
|
|
@@ -191893,6 +191998,55 @@ function isSupportedStructuralDeletionChild(piece) {
|
|
|
191893
191998
|
}
|
|
191894
191999
|
return piece.containerKind === "unknown" && (piece.localName === "smartTag" || piece.localName === "dir" || piece.localName === "bdo");
|
|
191895
192000
|
}
|
|
192001
|
+
function readCommentedInsertionBoundary(piece) {
|
|
192002
|
+
const markers = piece.children.filter((child) => child.kind === "marker");
|
|
192003
|
+
if (markers.length !== 3 || piece.children.length !== 4)
|
|
192004
|
+
return null;
|
|
192005
|
+
const [start, end, reference] = markers;
|
|
192006
|
+
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)
|
|
192007
|
+
return null;
|
|
192008
|
+
const text = piece.children.find((child) => child.kind === "text");
|
|
192009
|
+
if (!text || !text.decodedText)
|
|
192010
|
+
return null;
|
|
192011
|
+
const source = piece.rawXml;
|
|
192012
|
+
const base2 = piece.charStart;
|
|
192013
|
+
const openEnd = findXmlTagEnd(source, 1);
|
|
192014
|
+
const closeStart = source.lastIndexOf(`</${piece.qname}>`);
|
|
192015
|
+
const outsideBindings = Object.fromEntries(piece.namespaceBindings);
|
|
192016
|
+
for (const attribute of scanRawXmlAttributes(source.slice(0, openEnd))) {
|
|
192017
|
+
if (attribute.name === "xmlns" || attribute.prefix === "xmlns") {
|
|
192018
|
+
delete outsideBindings[attribute.name === "xmlns" ? "" : attribute.localName];
|
|
192019
|
+
}
|
|
192020
|
+
}
|
|
192021
|
+
const startXml = closeNamespaceScope(start.rawXml, Object.fromEntries(start.namespaceBindings), outsideBindings, { referencedOnly: true });
|
|
192022
|
+
if (startXml == null)
|
|
192023
|
+
return null;
|
|
192024
|
+
const textRunStart = text.runCharStart - base2;
|
|
192025
|
+
const textRunEnd = text.runCharEnd - base2;
|
|
192026
|
+
const startStart = start.charStart - base2;
|
|
192027
|
+
const startEnd = start.charEnd - base2;
|
|
192028
|
+
const endStart = end.charStart - base2;
|
|
192029
|
+
const endEnd = end.charEnd - base2;
|
|
192030
|
+
if (openEnd < 0 || closeStart < 0 || startStart < openEnd || startEnd > textRunStart || textRunEnd > endStart || endEnd > reference.charStart - base2 || [
|
|
192031
|
+
source.slice(openEnd, startStart),
|
|
192032
|
+
source.slice(startEnd, textRunStart),
|
|
192033
|
+
source.slice(textRunEnd, endStart)
|
|
192034
|
+
].some((gap) => gap.trim().length > 0))
|
|
192035
|
+
return null;
|
|
192036
|
+
const textRun = source.slice(textRunStart, textRunEnd);
|
|
192037
|
+
if (textRun.replace(text.runOpenTag, "").replace(text.runProperties ?? "", "").replace(text.rawXml, "").replace(text.runCloseTag, "").trim().length > 0)
|
|
192038
|
+
return null;
|
|
192039
|
+
const referenceRunXml = source.slice(endEnd, closeStart).trim();
|
|
192040
|
+
const referenceOpenEnd = findXmlTagEnd(referenceRunXml, 1);
|
|
192041
|
+
const referenceCloseStart = referenceRunXml.lastIndexOf("</");
|
|
192042
|
+
if (referenceOpenEnd < 0 || referenceCloseStart < referenceOpenEnd || !/^<([\w.-]+:)?r(?=[\s>])/.test(referenceRunXml) || !/<\/[\w.-]+:r>$/.test(referenceRunXml) || referenceRunXml.slice(referenceOpenEnd, referenceCloseStart).trim() !== reference.rawXml)
|
|
192043
|
+
return null;
|
|
192044
|
+
return {
|
|
192045
|
+
startXml,
|
|
192046
|
+
endXml: end.rawXml,
|
|
192047
|
+
referenceRunXml
|
|
192048
|
+
};
|
|
192049
|
+
}
|
|
191896
192050
|
function trackedToken(piece, spanStart, spanEnd, allowComplexDeletions, allowStructuralDeletionPassThrough) {
|
|
191897
192051
|
const visibleStart = spanStart(piece);
|
|
191898
192052
|
const visibleEnd = spanEnd(piece);
|
|
@@ -191932,6 +192086,7 @@ function trackedToken(piece, spanStart, spanEnd, allowComplexDeletions, allowStr
|
|
|
191932
192086
|
rawXml: child.rawXml
|
|
191933
192087
|
})).sort((a, b) => a.localOffset - b.localOffset);
|
|
191934
192088
|
}
|
|
192089
|
+
const commentedBoundary = piece.trackedKind === "ins" && !nestedDeletions ? readCommentedInsertionBoundary(piece) : null;
|
|
191935
192090
|
if (allowComplexDeletions && piece.trackedKind === "del") {
|
|
191936
192091
|
const unsupportedChild = piece.children.find((child) => child.kind !== "text" && !(child.kind === "marker" && isCommentMarker2(child.markerKind)) && !(allowStructuralDeletionPassThrough && isSupportedStructuralDeletionChild(child)));
|
|
191937
192092
|
if (unsupportedChild) {
|
|
@@ -191994,7 +192149,7 @@ function trackedToken(piece, spanStart, spanEnd, allowComplexDeletions, allowStr
|
|
|
191994
192149
|
}
|
|
191995
192150
|
};
|
|
191996
192151
|
}
|
|
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");
|
|
192152
|
+
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
192153
|
if (foreignChild) {
|
|
191999
192154
|
if (foreignChild.kind === "container") {
|
|
192000
192155
|
return unsupported2(containerRejectionReason(foreignChild.containerKind), `overlap compiler: ${foreignChild.containerKind} inside w:${piece.trackedKind}`);
|
|
@@ -192059,7 +192214,13 @@ function trackedToken(piece, spanStart, spanEnd, allowComplexDeletions, allowStr
|
|
|
192059
192214
|
},
|
|
192060
192215
|
...innerRuns.length > 1 ? { innerRuns } : {}
|
|
192061
192216
|
};
|
|
192062
|
-
return piece.trackedKind === "ins" ? {
|
|
192217
|
+
return piece.trackedKind === "ins" ? {
|
|
192218
|
+
kind: "ins",
|
|
192219
|
+
...base2,
|
|
192220
|
+
rsidR,
|
|
192221
|
+
...nestedDeletions ? { nestedDeletions } : {},
|
|
192222
|
+
...commentedBoundary ? { commentedBoundary } : {}
|
|
192223
|
+
} : { kind: "del", ...base2, rsidDel };
|
|
192063
192224
|
}
|
|
192064
192225
|
function isCommentMarker2(markerKind) {
|
|
192065
192226
|
return markerKind === "commentRangeStart" || markerKind === "commentRangeEnd" || markerKind === "commentReference";
|
|
@@ -192110,6 +192271,7 @@ var init_overlap_edit_compiler = __esm(() => {
|
|
|
192110
192271
|
init_word_text_payload();
|
|
192111
192272
|
init_xml_text();
|
|
192112
192273
|
init_xml_sax();
|
|
192274
|
+
init_xml_namespace_scope();
|
|
192113
192275
|
init_word_text_names();
|
|
192114
192276
|
init_paragraph_inline_model();
|
|
192115
192277
|
init_comment_cascade();
|
|
@@ -206730,6 +206892,8 @@ function collectRetiredTrackedChangeCommentMetadataIds(op, logicalCatalog) {
|
|
|
206730
206892
|
return ids;
|
|
206731
206893
|
}
|
|
206732
206894
|
function applyRetiredTrackedChangeCommentMetadataCleanup(args) {
|
|
206895
|
+
if (args.perPart[COMMENTS_PART_URI]?.kind === "remove")
|
|
206896
|
+
return [];
|
|
206733
206897
|
const commentsBytes = args.state.packageBytes.get(COMMENTS_PART_URI);
|
|
206734
206898
|
if (!commentsBytes || args.retiredSourceIds.size === 0)
|
|
206735
206899
|
return [];
|
|
@@ -206831,16 +206995,45 @@ function applyCommentCascade(args) {
|
|
|
206831
206995
|
const next = removeCommentCatalogEntries(TD46.decode(commentsBytes), wids);
|
|
206832
206996
|
if (!next.ok)
|
|
206833
206997
|
return { ok: false, reason: next.reason };
|
|
206834
|
-
const
|
|
206835
|
-
|
|
206836
|
-
|
|
206837
|
-
|
|
206838
|
-
|
|
206839
|
-
|
|
206840
|
-
|
|
206841
|
-
|
|
206842
|
-
|
|
206843
|
-
|
|
206998
|
+
const parsedComments = collectXmlElementRanges(next.xml);
|
|
206999
|
+
const commentsRoot = parsedComments.ranges.find((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "comments");
|
|
207000
|
+
const emptyComments = parsedComments.errors.length === 0 && commentsRoot && next.xml.slice(commentsRoot.openEnd, commentsRoot.closeStart).trim().length === 0;
|
|
207001
|
+
const hasCommentSidecars = args.state.packageBytes.has(COMMENTS_EXTENDED_PART_URI) || args.state.packageBytes.has(COMMENTS_IDS_PART_URI);
|
|
207002
|
+
if (emptyComments && !hasCommentSidecars) {
|
|
207003
|
+
args.perPart[COMMENTS_PART_URI] = { kind: "remove" };
|
|
207004
|
+
args.preconditions.push(byteWindowPrecondition4(COMMENTS_PART_URI, commentsBytes));
|
|
207005
|
+
args.patchMaps[COMMENTS_PART_URI] = { partUri: COMMENTS_PART_URI, ranges: [] };
|
|
207006
|
+
const relsBytes = args.state.packageBytes.get(DOCUMENT_RELS_PART_URI3);
|
|
207007
|
+
if (relsBytes) {
|
|
207008
|
+
const relsXml = currentPartXml(args.state, args.perPart, DOCUMENT_RELS_PART_URI3, XML_TD) ?? XML_TD.decode(relsBytes);
|
|
207009
|
+
const removed = removeRelationshipForPartAndTypeXml({
|
|
207010
|
+
relsXml,
|
|
207011
|
+
ownerPartUri: DOCUMENT_PART_URI,
|
|
207012
|
+
partUri: COMMENTS_PART_URI,
|
|
207013
|
+
relationshipType: COMMENTS_RELATIONSHIP_TYPE
|
|
207014
|
+
});
|
|
207015
|
+
if (!removed.ok)
|
|
207016
|
+
return { ok: false, reason: "unsupported-context" };
|
|
207017
|
+
if (removed.value.xml !== relsXml) {
|
|
207018
|
+
setWholePartReplacement(args, DOCUMENT_RELS_PART_URI3, relsBytes, removed.value.xml);
|
|
207019
|
+
}
|
|
207020
|
+
}
|
|
207021
|
+
const contentTypesBytes = args.state.packageBytes.get(CONTENT_TYPES_PART_URI4);
|
|
207022
|
+
if (contentTypesBytes) {
|
|
207023
|
+
const contentTypesXml = currentPartXml(args.state, args.perPart, CONTENT_TYPES_PART_URI4, XML_TD) ?? XML_TD.decode(contentTypesBytes);
|
|
207024
|
+
const removed = removeContentTypeOverrideXml({
|
|
207025
|
+
contentTypesXml,
|
|
207026
|
+
partName: COMMENTS_PART_URI
|
|
207027
|
+
});
|
|
207028
|
+
if (!removed.ok)
|
|
207029
|
+
return { ok: false, reason: "unsupported-context" };
|
|
207030
|
+
if (removed.value.xml !== contentTypesXml) {
|
|
207031
|
+
setWholePartReplacement(args, CONTENT_TYPES_PART_URI4, contentTypesBytes, removed.value.xml);
|
|
207032
|
+
}
|
|
207033
|
+
}
|
|
207034
|
+
} else {
|
|
207035
|
+
setWholePartReplacement(args, COMMENTS_PART_URI, commentsBytes, next.xml);
|
|
207036
|
+
}
|
|
206844
207037
|
}
|
|
206845
207038
|
const extendedBytes = args.state.packageBytes.get(COMMENTS_EXTENDED_PART_URI);
|
|
206846
207039
|
if (extendedBytes && removedParaIds.size > 0) {
|
|
@@ -209038,7 +209231,7 @@ function dedupeRemappedRefs(refs) {
|
|
|
209038
209231
|
function refKey(ref3) {
|
|
209039
209232
|
return `${ref3.kind}|${ref3.entityId ?? ref3.commentId ?? ""}|${ref3.storyId ?? ""}`;
|
|
209040
209233
|
}
|
|
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";
|
|
209234
|
+
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
209235
|
var init_compile_tracked_change_decide = __esm(() => {
|
|
209043
209236
|
init_empty_paragraph_move();
|
|
209044
209237
|
init_native_sdt_ownership();
|
|
@@ -220127,6 +220320,18 @@ function collectProtectedReferenceTokens(xml, referenceSteps) {
|
|
|
220127
220320
|
const tokens = [];
|
|
220128
220321
|
for (let index = 0;index < referenceSteps.length; index += 1) {
|
|
220129
220322
|
const step2 = referenceSteps[index];
|
|
220323
|
+
if (step2.kind === "bookmark-range" || step2.kind === "complex-field") {
|
|
220324
|
+
const fragment2 = step2.beforeFragmentXml;
|
|
220325
|
+
if (!fragment2)
|
|
220326
|
+
return null;
|
|
220327
|
+
const start = xml.indexOf(fragment2);
|
|
220328
|
+
if (start >= 0) {
|
|
220329
|
+
if (xml.indexOf(fragment2, start + fragment2.length) >= 0)
|
|
220330
|
+
return null;
|
|
220331
|
+
tokens.push({ key: `reference:${index}`, start, end: start + fragment2.length, xml: fragment2 });
|
|
220332
|
+
}
|
|
220333
|
+
continue;
|
|
220334
|
+
}
|
|
220130
220335
|
const expectedLocalName = step2.kind === "bookmark-start" ? "bookmarkStart" : "fldSimple";
|
|
220131
220336
|
const parsed = collectXmlElementRanges(xml, {
|
|
220132
220337
|
fragment: true,
|
|
@@ -221281,7 +221486,7 @@ function validateLocalizedMainDocumentReplay(state, sectionSteps, referenceSteps
|
|
|
221281
221486
|
function uniqueLocalizedReplayStart(xml, step2, documentRanges, allowRootNamespaceDeclarations = false) {
|
|
221282
221487
|
const ranges = documentRanges ?? collectXmlElementRanges(xml).ranges;
|
|
221283
221488
|
if (allowRootNamespaceDeclarations && isReferenceReplayStep(step2)) {
|
|
221284
|
-
const expectedLocalName = step2
|
|
221489
|
+
const expectedLocalName = referenceReplayElementName(step2);
|
|
221285
221490
|
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
221491
|
return starts2.length === 1 ? starts2[0] : null;
|
|
221287
221492
|
}
|
|
@@ -221302,7 +221507,7 @@ function isInsideWordElement(ranges, position, localName2) {
|
|
|
221302
221507
|
return ranges.some((range) => range.tag.namespaceUri === NS_W && range.tag.localName === localName2 && range.start < position && range.end > position);
|
|
221303
221508
|
}
|
|
221304
221509
|
function localizedReplayContext(xml, step2, start, documentRanges, allowRootNamespaceDeclarations = false) {
|
|
221305
|
-
const expectedLocalName = isReferenceReplayStep(step2) ? step2
|
|
221510
|
+
const expectedLocalName = isReferenceReplayStep(step2) ? referenceReplayElementName(step2) : "sectPr";
|
|
221306
221511
|
const ranges = documentRanges ?? collectXmlElementRanges(xml).ranges;
|
|
221307
221512
|
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
221513
|
if (!before)
|
|
@@ -221336,8 +221541,55 @@ function isSafeReferenceReplayStep(step2, context) {
|
|
|
221336
221541
|
const afterName = readResolvedReplayAttribute(context.after, "name");
|
|
221337
221542
|
return afterName !== null && readResolvedReplayAttribute(context.before, "id") === readResolvedReplayAttribute(context.after, "id") && replaceReplayAttribute(step2.beforeXml, context.before, "name", afterName) === step2.afterXml;
|
|
221338
221543
|
}
|
|
221339
|
-
|
|
221340
|
-
|
|
221544
|
+
if (step2.kind === "simple-field") {
|
|
221545
|
+
const instruction = readResolvedReplayAttribute(context.after, "instr");
|
|
221546
|
+
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;
|
|
221547
|
+
}
|
|
221548
|
+
const beforeFragment = step2.beforeFragmentXml;
|
|
221549
|
+
const afterFragment = step2.afterFragmentXml;
|
|
221550
|
+
if (!beforeFragment || !afterFragment || replaceUniqueReplayFragment(step2.beforeXml, beforeFragment, afterFragment) !== step2.afterXml)
|
|
221551
|
+
return false;
|
|
221552
|
+
if (step2.kind === "bookmark-range") {
|
|
221553
|
+
return isBalancedAddedBookmarkFragment(afterFragment, beforeFragment, context.parentNamespaceBindings);
|
|
221554
|
+
}
|
|
221555
|
+
return isCompleteAddedRefFieldFragment(afterFragment, beforeFragment, context.parentNamespaceBindings);
|
|
221556
|
+
}
|
|
221557
|
+
function referenceReplayElementName(step2) {
|
|
221558
|
+
return step2.kind === "bookmark-start" ? "bookmarkStart" : step2.kind === "simple-field" ? "fldSimple" : "p";
|
|
221559
|
+
}
|
|
221560
|
+
function replaceUniqueReplayFragment(xml, before, after) {
|
|
221561
|
+
const start = xml.indexOf(before);
|
|
221562
|
+
if (start < 0 || xml.indexOf(before, start + before.length) >= 0)
|
|
221563
|
+
return null;
|
|
221564
|
+
return xml.slice(0, start) + after + xml.slice(start + before.length);
|
|
221565
|
+
}
|
|
221566
|
+
function isBalancedAddedBookmarkFragment(xml, expectedContent, namespaceBindings) {
|
|
221567
|
+
const parsed = collectXmlElementRanges(xml, { fragment: true, additionalNamespaces: { ...namespaceBindings } });
|
|
221568
|
+
if (parsed.errors.length > 0)
|
|
221569
|
+
return false;
|
|
221570
|
+
const starts = parsed.ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "bookmarkStart");
|
|
221571
|
+
const ends = parsed.ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "bookmarkEnd");
|
|
221572
|
+
if (starts.length !== 1 || ends.length !== 1 || !starts[0].tag.isSelfClosing || !ends[0].tag.isSelfClosing)
|
|
221573
|
+
return false;
|
|
221574
|
+
const id = readResolvedReplayAttribute(starts[0], "id");
|
|
221575
|
+
return id !== null && readResolvedReplayAttribute(starts[0], "name") !== null && readResolvedReplayAttribute(ends[0], "id") === id && xml.slice(starts[0].end, ends[0].start) === expectedContent;
|
|
221576
|
+
}
|
|
221577
|
+
function isCompleteAddedRefFieldFragment(xml, expectedResult, namespaceBindings) {
|
|
221578
|
+
const parsed = collectXmlElementRanges(xml, { fragment: true, additionalNamespaces: { ...namespaceBindings } });
|
|
221579
|
+
if (parsed.errors.length > 0)
|
|
221580
|
+
return false;
|
|
221581
|
+
const chars = parsed.ranges.filter((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "fldChar");
|
|
221582
|
+
const types4 = chars.map((range) => readResolvedReplayAttribute(range, "fldCharType"));
|
|
221583
|
+
if (types4.length !== 3 || types4.join(",") !== "begin,separate,end")
|
|
221584
|
+
return false;
|
|
221585
|
+
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("");
|
|
221586
|
+
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;
|
|
221587
|
+
}
|
|
221588
|
+
function parentRunStart(ranges, child) {
|
|
221589
|
+
return ranges.find((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "r" && range.start <= child.start && range.end >= child.end)?.start ?? -1;
|
|
221590
|
+
}
|
|
221591
|
+
function parentRunEnd(ranges, child) {
|
|
221592
|
+
return ranges.find((range) => range.tag.namespaceUri === NS_W && range.tag.localName === "r" && range.start <= child.start && range.end >= child.end)?.end ?? -1;
|
|
221341
221593
|
}
|
|
221342
221594
|
function isReferenceReplayStep(step2) {
|
|
221343
221595
|
return "kind" in step2;
|
|
@@ -221455,6 +221707,13 @@ function renderTrackedSectionReplay(step2, stamp, context) {
|
|
|
221455
221707
|
return step2.afterXml.slice(0, close) + marker + step2.afterXml.slice(close);
|
|
221456
221708
|
}
|
|
221457
221709
|
function renderTrackedReferenceReplay(step2, stamps, context) {
|
|
221710
|
+
if (step2.kind === "bookmark-range" || step2.kind === "complex-field") {
|
|
221711
|
+
const beforeFragment = step2.beforeFragmentXml;
|
|
221712
|
+
const afterFragment = step2.afterFragmentXml;
|
|
221713
|
+
const deletionXml2 = renameWordTextElementsToDeletedText(beforeFragment, context.parentNamespaceBindings);
|
|
221714
|
+
const tracked = renderTrackedWrapper("del", deletionXml2, stamps.del, context) + renderTrackedWrapper("ins", afterFragment, stamps.ins, context);
|
|
221715
|
+
return replaceUniqueReplayFragment(step2.beforeXml, beforeFragment, tracked) ?? step2.beforeXml;
|
|
221716
|
+
}
|
|
221458
221717
|
const deletionXml = step2.kind === "simple-field" ? renameWordTextElementsToDeletedText(step2.beforeXml, context.parentNamespaceBindings) : step2.beforeXml;
|
|
221459
221718
|
return renderTrackedWrapper("del", deletionXml, stamps.del, context) + renderTrackedWrapper("ins", step2.afterXml, stamps.ins, context);
|
|
221460
221719
|
}
|
|
@@ -221544,7 +221803,7 @@ function validateTableTopologySteps(state, changeMode, steps) {
|
|
|
221544
221803
|
if (deletedRows.has(key2) || step2.rowsXml.length !== 1 || table.rows.length <= 1)
|
|
221545
221804
|
return false;
|
|
221546
221805
|
const rowXml = TD58.decode(partBytes.subarray(anchor.row.rowByteStart, anchor.row.rowByteEnd));
|
|
221547
|
-
if (step2.rowsXml[0] !== rowXml || !
|
|
221806
|
+
if (step2.rowsXml[0] !== rowXml || !isNamespaceSafeWordprocessingRow(rowXml, namespaceBindings))
|
|
221548
221807
|
return false;
|
|
221549
221808
|
const parsed = collectXmlElementRanges(rowXml, { fragment: true, additionalNamespaces: { ...namespaceBindings } });
|
|
221550
221809
|
if (parsed.errors.length || parsed.ranges.some((range) => range.tag.namespaceUri === NS_W && [
|
|
@@ -221555,7 +221814,6 @@ function validateTableTopologySteps(state, changeMode, steps) {
|
|
|
221555
221814
|
"commentReference",
|
|
221556
221815
|
"footnoteReference",
|
|
221557
221816
|
"endnoteReference",
|
|
221558
|
-
"sdt",
|
|
221559
221817
|
"fldSimple",
|
|
221560
221818
|
"fldChar"
|
|
221561
221819
|
].includes(range.tag.localName)))
|
|
@@ -228918,7 +229176,7 @@ function planParagraphSplice(input) {
|
|
|
228918
229176
|
};
|
|
228919
229177
|
return input.trackedStamp ? renderTrackedPasteParagraphBlock(spec, input.trackedStamp) : renderPasteParagraphBlock(spec);
|
|
228920
229178
|
};
|
|
228921
|
-
const mergeable = (block) => block.kind === "paragraph" && !block.styleRef && !block.numbering && !block.listIntent && !block.paragraphProps && !block.pPrXml && !block.complete;
|
|
229179
|
+
const mergeable = (block) => block.kind === "paragraph" && !block.styleRef && !block.numbering && !block.listIntent && !block.paragraphProps && !block.pPrXml && !block.blockSdts?.length && !block.complete;
|
|
228922
229180
|
const paragraphs = [];
|
|
228923
229181
|
if (blocks.length === 1 && mergeable(blocks[0])) {
|
|
228924
229182
|
if (anchorParaId)
|
|
@@ -228937,10 +229195,13 @@ function planParagraphSplice(input) {
|
|
|
228937
229195
|
paragraphs.push(headOpen + headPPr + split.headXml + (mergeFirst ? runsOf(blocks[0]) : "") + envelope.close);
|
|
228938
229196
|
}
|
|
228939
229197
|
const middleStart = mergeFirst ? 1 : 0;
|
|
229198
|
+
const middleXml = [];
|
|
228940
229199
|
for (let middleIndex = 0;middleIndex < middleBlocks.length; middleIndex += 1) {
|
|
228941
229200
|
const block = middleBlocks[middleIndex];
|
|
228942
|
-
|
|
229201
|
+
middleXml.push(standalone(block, middleStart + middleIndex, mergeable(block) ? envelope.pPr : undefined));
|
|
228943
229202
|
}
|
|
229203
|
+
if (middleXml.length)
|
|
229204
|
+
paragraphs.push(renderBlockSdtSequence(middleBlocks, middleXml, input.blockSdtIds ?? new Map));
|
|
228944
229205
|
const tailRunsXml = (mergeLast ? runsOf(blocks[blocks.length - 1]) : "") + split.tailXml;
|
|
228945
229206
|
if (mergeLast || split.tailXml.length > 0) {
|
|
228946
229207
|
const tailOpen = relocateEmptyAnchor ? envelope.open : withParaId(envelope.open, mintId(), input.partBytes, input.paragraphStartByte);
|
|
@@ -231243,6 +231504,10 @@ function preflightFragmentApply(input) {
|
|
|
231243
231504
|
const target = resolveFragmentApplyTarget(state, op);
|
|
231244
231505
|
if (!target.ok)
|
|
231245
231506
|
return target;
|
|
231507
|
+
if (isTextTarget2(op.target) && op.formattingMode === "match-destination" && op.fragment.blocks.some((block) => (block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length))
|
|
231508
|
+
return { ok: false, reason: "paste-structure-unsupported" };
|
|
231509
|
+
if ((op.changeMode ?? "direct") === "tracked" && op.fragment.blocks.some((block) => (block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length))
|
|
231510
|
+
return { ok: false, reason: "paste-tracked-structural-unsupported" };
|
|
231246
231511
|
if ((op.changeMode ?? "direct") === "tracked" && target.target.kind === "block" && target.target.blockKind === "table" && !trackedWholeTableRowsAreDirectChildren(state, target.target)) {
|
|
231247
231512
|
return { ok: false, reason: "paste-tracked-structural-unsupported" };
|
|
231248
231513
|
}
|
|
@@ -231507,6 +231772,8 @@ function validateFragmentRangeIntegrity(input) {
|
|
|
231507
231772
|
}
|
|
231508
231773
|
function fragmentRequiresCommit5Materialization(blocks) {
|
|
231509
231774
|
for (const block of blocks) {
|
|
231775
|
+
if ((block.kind === "paragraph" || block.kind === "heading") && block.blockSdts?.length)
|
|
231776
|
+
return true;
|
|
231510
231777
|
if (block.kind === "heading" || block.kind === "horizontalRule")
|
|
231511
231778
|
return true;
|
|
231512
231779
|
if (block.kind === "table") {
|
|
@@ -231526,7 +231793,7 @@ function fragmentRequiresCommit5Materialization(blocks) {
|
|
|
231526
231793
|
return false;
|
|
231527
231794
|
}
|
|
231528
231795
|
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);
|
|
231796
|
+
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
231797
|
}
|
|
231531
231798
|
function collectFragmentSourcePaths(blocks) {
|
|
231532
231799
|
const paths = [];
|
|
@@ -232037,6 +232304,7 @@ function runWholeStoryReplaceCommit(input, target, blocks, extras, inlineExtras)
|
|
|
232037
232304
|
state,
|
|
232038
232305
|
blocks,
|
|
232039
232306
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
232307
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232040
232308
|
partBytes: bytes,
|
|
232041
232309
|
insertionByte: target.byteStart,
|
|
232042
232310
|
ordinalSeed: 0,
|
|
@@ -232275,7 +232543,7 @@ function renderCompletePasteFragment(input) {
|
|
|
232275
232543
|
renderedBlocks.push(xml);
|
|
232276
232544
|
}
|
|
232277
232545
|
return {
|
|
232278
|
-
xml: renderedBlocks.
|
|
232546
|
+
xml: renderBlockSdtSequence(input.blocks, renderedBlocks, input.blockSdtIds),
|
|
232279
232547
|
createdParaIds,
|
|
232280
232548
|
destinationParaIdsByBlock
|
|
232281
232549
|
};
|
|
@@ -232307,6 +232575,7 @@ function runParagraphBlockPasteCommit(input, target, blocks, extras, inlineExtra
|
|
|
232307
232575
|
state,
|
|
232308
232576
|
blocks,
|
|
232309
232577
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
232578
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232310
232579
|
partBytes: bytes,
|
|
232311
232580
|
insertionByte: target.placement === "after" ? anchor.byteEnd : anchor.byteStart,
|
|
232312
232581
|
ordinalSeed: anchor.ordinal,
|
|
@@ -232475,6 +232744,7 @@ function runWholeTableReplaceCommit(input, target, blocks, extras, inlineExtras)
|
|
|
232475
232744
|
state,
|
|
232476
232745
|
blocks,
|
|
232477
232746
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
232747
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232478
232748
|
partBytes: bytes,
|
|
232479
232749
|
insertionByte: target.byteStart,
|
|
232480
232750
|
ordinalSeed: replacedParagraphs[0]?.ordinal ?? 0,
|
|
@@ -232644,6 +232914,7 @@ function runCrossParagraphTrackedPasteCommit(input, target, blocks, extras, inli
|
|
|
232644
232914
|
paragraphStartByte: start.byteStart,
|
|
232645
232915
|
mintParaId: () => mintParaId(state, state.packageRevision, start.ordinal + 1 + (mintSalt += 1)),
|
|
232646
232916
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
232917
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232647
232918
|
trackedStamp: stamp,
|
|
232648
232919
|
wrapAllTracked: true,
|
|
232649
232920
|
...extras.commentIdMap ? { commentIdMap: extras.commentIdMap } : {},
|
|
@@ -232772,6 +233043,7 @@ function runCrossParagraphPasteCommit(input, target, blocks, extras, inlineExtra
|
|
|
232772
233043
|
paragraphStartByte: start.byteStart,
|
|
232773
233044
|
mintParaId: () => mintParaId(state, state.packageRevision, start.ordinal + 1 + (mintSalt += 1)),
|
|
232774
233045
|
inlineSpecs: inlineExtras.inlineSpecs,
|
|
233046
|
+
blockSdtIds: inlineExtras.blockSdtIds,
|
|
232775
233047
|
...extras.commentIdMap ? { commentIdMap: extras.commentIdMap } : {},
|
|
232776
233048
|
...extras.noteIdMap ? { noteIdMap: extras.noteIdMap } : {}
|
|
232777
233049
|
});
|
|
@@ -233418,6 +233690,7 @@ function runPasteSpliceCommit(input, target, resolvedBlocks, listExtras, imageEx
|
|
|
233418
233690
|
paragraphStartByte,
|
|
233419
233691
|
mintParaId: mintParaId3,
|
|
233420
233692
|
inlineSpecs: imageExtras.inlineSpecs,
|
|
233693
|
+
blockSdtIds: imageExtras.blockSdtIds,
|
|
233421
233694
|
...stamp ? { trackedStamp: stamp, wrapAllTracked } : {},
|
|
233422
233695
|
...listExtras.commentIdMap ? { commentIdMap: listExtras.commentIdMap } : {},
|
|
233423
233696
|
...listExtras.noteIdMap ? { noteIdMap: listExtras.noteIdMap } : {}
|
|
@@ -233654,6 +233927,8 @@ function validateImageFragment(fragment2) {
|
|
|
233654
233927
|
continue;
|
|
233655
233928
|
if (inline.kind === "footnoteRef" || inline.kind === "endnoteRef")
|
|
233656
233929
|
continue;
|
|
233930
|
+
if (inline.kind === "sdt")
|
|
233931
|
+
continue;
|
|
233657
233932
|
if (inline.kind === "hyperlink") {
|
|
233658
233933
|
if (inline.inlines.some((child) => child.kind === "image")) {
|
|
233659
233934
|
return { ok: false, reason: "paste-structure-unsupported" };
|
|
@@ -233674,7 +233949,7 @@ function validateImageFragment(fragment2) {
|
|
|
233674
233949
|
function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMode, relationshipHyperlinks, hyperlinkCharacterStyleId, preparedPackageXml) {
|
|
233675
233950
|
const inlineParagraphs = [];
|
|
233676
233951
|
for (const block of blocks) {
|
|
233677
|
-
if (block.kind === "paragraph" && block.inlines)
|
|
233952
|
+
if (block.kind === "paragraph" && (block.inlines || block.blockSdts?.length))
|
|
233678
233953
|
inlineParagraphs.push(block);
|
|
233679
233954
|
if (block.kind === "table") {
|
|
233680
233955
|
for (const row of block.rows) {
|
|
@@ -233687,7 +233962,7 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
|
|
|
233687
233962
|
}
|
|
233688
233963
|
}
|
|
233689
233964
|
if (inlineParagraphs.length === 0) {
|
|
233690
|
-
return { ok: true, value: { inlineSpecs: new Map, partUris: [], perPart: {}, preconditions: [], patchMaps: {} } };
|
|
233965
|
+
return { ok: true, value: { inlineSpecs: new Map, blockSdtIds: new Map, partUris: [], perPart: {}, preconditions: [], patchMaps: {} } };
|
|
233691
233966
|
}
|
|
233692
233967
|
const assets = new Map((fragment2.assets ?? []).map((asset) => [asset.id, asset]));
|
|
233693
233968
|
const hasImages = inlineParagraphs.some((paragraph) => paragraph.inlines?.some((inline) => inline.kind === "image"));
|
|
@@ -233782,6 +234057,43 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
|
|
|
233782
234057
|
}
|
|
233783
234058
|
let docPrId = allocateDocPrId(state, storyId);
|
|
233784
234059
|
const inlineSpecs = new Map;
|
|
234060
|
+
const hasControls = inlineParagraphs.some((paragraph) => paragraph.blockSdts?.length || paragraph.inlines?.some((inline) => inline.kind === "sdt"));
|
|
234061
|
+
const usedControlIds = new Set;
|
|
234062
|
+
if (hasControls) {
|
|
234063
|
+
for (const [uri, bytes] of state.packageBytes) {
|
|
234064
|
+
if (!uri.endsWith(".xml"))
|
|
234065
|
+
continue;
|
|
234066
|
+
const xml = TD64.decode(bytes);
|
|
234067
|
+
for (const match of xml.matchAll(/<w:sdtPr\b[^>]*>[\s\S]*?<w:id\b[^>]*\bw:val=(['"])(\d+)\1/g)) {
|
|
234068
|
+
const id = Number(match[2]);
|
|
234069
|
+
if (Number.isSafeInteger(id) && id > 0)
|
|
234070
|
+
usedControlIds.add(id);
|
|
234071
|
+
}
|
|
234072
|
+
}
|
|
234073
|
+
}
|
|
234074
|
+
let nextControlId = 1002;
|
|
234075
|
+
for (const id of usedControlIds)
|
|
234076
|
+
if (id >= nextControlId)
|
|
234077
|
+
nextControlId = id + 1;
|
|
234078
|
+
const mintControlId = () => {
|
|
234079
|
+
if (nextControlId > 2147483647)
|
|
234080
|
+
nextControlId = 1;
|
|
234081
|
+
while (usedControlIds.has(nextControlId)) {
|
|
234082
|
+
nextControlId += 1;
|
|
234083
|
+
if (nextControlId > 2147483647)
|
|
234084
|
+
nextControlId = 1;
|
|
234085
|
+
}
|
|
234086
|
+
const id = nextControlId++;
|
|
234087
|
+
usedControlIds.add(id);
|
|
234088
|
+
return String(id);
|
|
234089
|
+
};
|
|
234090
|
+
const blockSdtIds = new Map;
|
|
234091
|
+
for (const paragraph of inlineParagraphs) {
|
|
234092
|
+
for (const wrapper of paragraph.blockSdts ?? []) {
|
|
234093
|
+
if (!blockSdtIds.has(wrapper.sourceId))
|
|
234094
|
+
blockSdtIds.set(wrapper.sourceId, mintControlId());
|
|
234095
|
+
}
|
|
234096
|
+
}
|
|
233785
234097
|
const leafSpec = (inline) => {
|
|
233786
234098
|
if (inline.kind === "text")
|
|
233787
234099
|
return toPasteTextRunSpec(inline);
|
|
@@ -233802,37 +234114,68 @@ function prepareImageExtras(state, storyId, partUri, fragment2, blocks, changeMo
|
|
|
233802
234114
|
})
|
|
233803
234115
|
};
|
|
233804
234116
|
};
|
|
234117
|
+
const sdtSpec = (inline) => ({
|
|
234118
|
+
kind: "sdt",
|
|
234119
|
+
id: mintControlId(),
|
|
234120
|
+
controlType: inline.controlType,
|
|
234121
|
+
...inline.tag !== undefined ? { tag: inline.tag } : {},
|
|
234122
|
+
...inline.alias !== undefined ? { alias: inline.alias } : {},
|
|
234123
|
+
...inline.lockMode !== undefined ? { lockMode: inline.lockMode } : {},
|
|
234124
|
+
...inline.multiline !== undefined ? { multiline: inline.multiline } : {},
|
|
234125
|
+
runs: inline.inlines.map((child) => child.kind === "sdt" ? sdtSpec(child) : leafSpec(child))
|
|
234126
|
+
});
|
|
234127
|
+
const inlineSpec = (inline) => {
|
|
234128
|
+
if (inline.kind === "sdt")
|
|
234129
|
+
return sdtSpec(inline);
|
|
234130
|
+
if (inline.kind === "footnoteRef" || inline.kind === "endnoteRef") {
|
|
234131
|
+
return { kind: inline.kind, noteId: inline.noteId };
|
|
234132
|
+
}
|
|
234133
|
+
if (inline.kind !== "hyperlink")
|
|
234134
|
+
return leafSpec(inline);
|
|
234135
|
+
const target = inline.target.kind === "external" ? {
|
|
234136
|
+
kind: "external",
|
|
234137
|
+
url: inline.target.url,
|
|
234138
|
+
...relationshipHyperlinks ? { relationshipId: hyperlinkRelationshipIds.get(inline) } : {}
|
|
234139
|
+
} : { kind: "anchor", anchor: inline.target.anchor };
|
|
234140
|
+
return {
|
|
234141
|
+
kind: "hyperlink",
|
|
234142
|
+
target,
|
|
234143
|
+
...inline.tooltip ? { tooltip: inline.tooltip } : {},
|
|
234144
|
+
...hyperlinkCharacterStyleId ? { characterStyleId: hyperlinkCharacterStyleId } : {},
|
|
234145
|
+
runs: inline.inlines.map(leafSpec)
|
|
234146
|
+
};
|
|
234147
|
+
};
|
|
233805
234148
|
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
|
-
}));
|
|
234149
|
+
if (paragraph.inlines)
|
|
234150
|
+
inlineSpecs.set(paragraph, paragraph.inlines.map(inlineSpec));
|
|
233825
234151
|
}
|
|
233826
234152
|
const preconditions = [];
|
|
233827
234153
|
if (relsUri && relsBytes && (hasImages || hasExternalLinks))
|
|
233828
234154
|
preconditions.push(byteWindowPrecondition7(relsUri, relsBytes));
|
|
233829
234155
|
if (contentTypesChanged && contentTypesBytes)
|
|
233830
234156
|
preconditions.push(byteWindowPrecondition7(CONTENT_TYPES_PART_URI11, contentTypesBytes));
|
|
233831
|
-
return { ok: true, value: { inlineSpecs, partUris: packagePartUris, perPart, preconditions, patchMaps: {} } };
|
|
234157
|
+
return { ok: true, value: { inlineSpecs, blockSdtIds, partUris: packagePartUris, perPart, preconditions, patchMaps: {} } };
|
|
233832
234158
|
}
|
|
233833
234159
|
function validateBlocks(blocks) {
|
|
233834
234160
|
const budget = { totalChars: 0, hyperlinkRefs: 0, sourcePaths: new Set };
|
|
234161
|
+
const closedControls = new Set;
|
|
234162
|
+
let activeControls = [];
|
|
233835
234163
|
for (const block of blocks) {
|
|
234164
|
+
const controls = block.kind === "paragraph" || block.kind === "heading" ? block.blockSdts ?? [] : [];
|
|
234165
|
+
if (controls.length && (block.kind !== "paragraph" && block.kind !== "heading" || !block.complete || controls.length > 16)) {
|
|
234166
|
+
return { ok: false, reason: "paste-structure-unsupported" };
|
|
234167
|
+
}
|
|
234168
|
+
let common = 0;
|
|
234169
|
+
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)
|
|
234170
|
+
common += 1;
|
|
234171
|
+
for (const wrapper of activeControls.slice(common))
|
|
234172
|
+
closedControls.add(wrapper.sourceId);
|
|
234173
|
+
for (const wrapper of controls.slice(common)) {
|
|
234174
|
+
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)) {
|
|
234175
|
+
return { ok: false, reason: "paste-structure-unsupported" };
|
|
234176
|
+
}
|
|
234177
|
+
}
|
|
234178
|
+
activeControls = controls;
|
|
233836
234179
|
if (!recordSourcePath(block.sourcePath, budget.sourcePaths)) {
|
|
233837
234180
|
return { ok: false, reason: "paste-structure-unsupported" };
|
|
233838
234181
|
}
|
|
@@ -233896,6 +234239,9 @@ function validateBlocks(blocks) {
|
|
|
233896
234239
|
if (cellBlock.kind !== "paragraph") {
|
|
233897
234240
|
return { ok: false, reason: "paste-structure-unsupported" };
|
|
233898
234241
|
}
|
|
234242
|
+
if (cellBlock.blockSdts?.length) {
|
|
234243
|
+
return { ok: false, reason: "paste-structure-unsupported" };
|
|
234244
|
+
}
|
|
233899
234245
|
if (!recordSourcePath(cellBlock.sourcePath, budget.sourcePaths)) {
|
|
233900
234246
|
return { ok: false, reason: "paste-structure-unsupported" };
|
|
233901
234247
|
}
|
|
@@ -234029,9 +234375,14 @@ function validateParagraphBlock(block, budget) {
|
|
|
234029
234375
|
}
|
|
234030
234376
|
return { ok: true };
|
|
234031
234377
|
}
|
|
234032
|
-
function validatePasteInline(inline, budget) {
|
|
234378
|
+
function validatePasteInline(inline, budget, depth = 0) {
|
|
234379
|
+
if (depth > 32)
|
|
234380
|
+
return false;
|
|
234033
234381
|
if (!recordSourcePath(inline.sourcePath, budget.sourcePaths))
|
|
234034
234382
|
return false;
|
|
234383
|
+
if (inline.kind === "sdt") {
|
|
234384
|
+
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));
|
|
234385
|
+
}
|
|
234035
234386
|
if (inline.kind === "text") {
|
|
234036
234387
|
return typeof inline.text === "string" && !hasUnsupportedControlChar(inline.text) && isValidPasteRunMarks(inline.marks);
|
|
234037
234388
|
}
|
|
@@ -234057,7 +234408,7 @@ function validatePasteInline(inline, budget) {
|
|
|
234057
234408
|
} 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
234409
|
return false;
|
|
234059
234410
|
}
|
|
234060
|
-
return inline.inlines.every((child) => validatePasteInline(child, budget));
|
|
234411
|
+
return inline.inlines.every((child) => validatePasteInline(child, budget, depth + 1));
|
|
234061
234412
|
}
|
|
234062
234413
|
function rewritePastePPrStyleRef(pPrXml, styleId) {
|
|
234063
234414
|
const escaped = styleId.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -234069,7 +234420,13 @@ function rewritePastePPrStyleRef(pPrXml, styleId) {
|
|
|
234069
234420
|
function hasMatchingInlineTextProjection(block) {
|
|
234070
234421
|
if (!Array.isArray(block.inlines))
|
|
234071
234422
|
return false;
|
|
234072
|
-
const textInlines = block.inlines.flatMap((inline)
|
|
234423
|
+
const textInlines = block.inlines.flatMap(function project(inline) {
|
|
234424
|
+
if (inline.kind === "text")
|
|
234425
|
+
return [inline];
|
|
234426
|
+
if (inline.kind === "hyperlink" || inline.kind === "sdt")
|
|
234427
|
+
return inline.inlines.flatMap(project);
|
|
234428
|
+
return [];
|
|
234429
|
+
});
|
|
234073
234430
|
return textInlines.length === block.runs.length && textInlines.every((inline, index) => {
|
|
234074
234431
|
const run = block.runs[index];
|
|
234075
234432
|
return inline.text === run.text && haveEqualRunMarks(inline.marks, run.marks);
|
|
@@ -247145,12 +247502,13 @@ function prepareHistoryReplayMutation(state, entry, direction, patchGroup) {
|
|
|
247145
247502
|
const controlBytes = controlOwner && state.packageBytes.get(controlOwner.partUri);
|
|
247146
247503
|
const controlPatch = controlOwner && patchGroup.perPart[controlOwner.partUri];
|
|
247147
247504
|
const contentControlRewrite = patchGroup.source.kind === "storySurfaceRewrite" && patchGroup.source.contentControlRewrite && controlBytes && controlPatch ? prepareContentControlRewrite(controlBytes, controlPatch) : null;
|
|
247505
|
+
const declaredStorySurfaceTargetBlockIds = patchGroup.source.kind === "storySurfaceRewrite" ? [...new Set(patchGroup.source.targetBlockIds)] : [];
|
|
247148
247506
|
const targetBlockIds2 = contentControlRewrite ? [...new Set([
|
|
247149
247507
|
...contentControlRewrite.removedBlockIds,
|
|
247150
247508
|
...contentControlRewrite.addedBlockIds,
|
|
247151
247509
|
...contentControlRewrite.contentBlockIds,
|
|
247152
247510
|
...contentControlRewrite.leadingBlockIds
|
|
247153
|
-
])] : patchGroup.source.kind === "compareApply" ? [...new Set(patchGroup.source.bodySteps.map((step2) => step2.blockId))] : collectPatchGroupTargetBlockIds(patchGroup);
|
|
247511
|
+
])] : patchGroup.source.kind === "compareApply" ? [...new Set(patchGroup.source.bodySteps.map((step2) => step2.blockId))] : declaredStorySurfaceTargetBlockIds.length > 0 ? declaredStorySurfaceTargetBlockIds : collectPatchGroupTargetBlockIds(patchGroup);
|
|
247154
247512
|
const currentBaseRevisions = {
|
|
247155
247513
|
package: state.packageRevision,
|
|
247156
247514
|
perPart: {}
|
|
@@ -291329,7 +291687,7 @@ class V2SelectionMutationAdapter {
|
|
|
291329
291687
|
const buildResolutionMs = nowMs6() - buildResolutionStartedAt;
|
|
291330
291688
|
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
291689
|
let structuralRewrite = false;
|
|
291332
|
-
if (options?.changeMode === "tracked" &&
|
|
291690
|
+
if (options?.changeMode === "tracked" && replacements.length > 1) {
|
|
291333
291691
|
const paragraphBytes = getSDDocumentSessionInternalPartRange(this.context.session, resolved.partUri, resolved.paragraphByteStart ?? resolved.startByte, resolved.paragraphByteEnd ?? resolved.endByte);
|
|
291334
291692
|
if (paragraphBytes) {
|
|
291335
291693
|
const scopedReplacements = planTrackedRewriteReplacement(selectedText, request.text, {
|
|
@@ -326296,8 +326654,8 @@ function lowerInline(inline, path7, images) {
|
|
|
326296
326654
|
}
|
|
326297
326655
|
function lowerHyperlinkChild(inline, path7, images) {
|
|
326298
326656
|
const lowered = lowerInline(inline, path7, images);
|
|
326299
|
-
if (lowered.kind === "hyperlink")
|
|
326300
|
-
unsupported4(path7, "Nested hyperlinks are not supported.");
|
|
326657
|
+
if (lowered.kind === "hyperlink" || lowered.kind === "sdt")
|
|
326658
|
+
unsupported4(path7, "Nested hyperlinks and content controls are not supported.");
|
|
326301
326659
|
if (lowered.kind === "footnoteRef" || lowered.kind === "endnoteRef") {
|
|
326302
326660
|
unsupported4(path7, "Note references cannot be nested inside hyperlinks.");
|
|
326303
326661
|
}
|
|
@@ -345491,40 +345849,63 @@ class V2ImagesAdapter {
|
|
|
345491
345849
|
return trackedTarget;
|
|
345492
345850
|
return this.createTrackedBodyImage(input, options, trackedTarget, decoded, requestedSize);
|
|
345493
345851
|
}
|
|
345494
|
-
const
|
|
345495
|
-
|
|
345496
|
-
|
|
345497
|
-
|
|
345498
|
-
|
|
345499
|
-
|
|
345500
|
-
|
|
345501
|
-
|
|
345502
|
-
|
|
345503
|
-
|
|
345504
|
-
|
|
345505
|
-
|
|
345506
|
-
|
|
345507
|
-
|
|
345508
|
-
|
|
345509
|
-
|
|
345510
|
-
|
|
345511
|
-
|
|
345512
|
-
|
|
345513
|
-
|
|
345514
|
-
|
|
345852
|
+
const abortCapture = Symbol("create.image.abort");
|
|
345853
|
+
const imageFormat = decoded.format;
|
|
345854
|
+
let capturedTxIds = [];
|
|
345855
|
+
let failure8 = null;
|
|
345856
|
+
let published = null;
|
|
345857
|
+
try {
|
|
345858
|
+
published = this.context.captureCommittedHistory((txIds) => {
|
|
345859
|
+
capturedTxIds = txIds;
|
|
345860
|
+
const resolved = this.resolveCreateImageTarget(input, options);
|
|
345861
|
+
if (!resolved.success) {
|
|
345862
|
+
failure8 = resolved;
|
|
345863
|
+
throw abortCapture;
|
|
345864
|
+
}
|
|
345865
|
+
const inserted = this.insertInline({
|
|
345866
|
+
storyId: resolved.storyId,
|
|
345867
|
+
paraId: resolved.paraId,
|
|
345868
|
+
offset: resolved.offset,
|
|
345869
|
+
binary: decoded.binary,
|
|
345870
|
+
format: imageFormat,
|
|
345871
|
+
widthPx: requestedSize.widthPx,
|
|
345872
|
+
heightPx: requestedSize.heightPx,
|
|
345873
|
+
name: input.alt ?? input.title
|
|
345874
|
+
});
|
|
345875
|
+
if (!inserted.success) {
|
|
345876
|
+
failure8 = createImageFailure(inserted.failure.code, inserted.failure.message);
|
|
345877
|
+
throw abortCapture;
|
|
345878
|
+
}
|
|
345879
|
+
let entry = this.findInsertedImageEntry(resolved.storyId, resolved.paraId, inserted.imageNodeId);
|
|
345880
|
+
if (entry && (input.title || input.alt)) {
|
|
345881
|
+
const metadata2 = this.setAltText({
|
|
345882
|
+
imageId: entry.publicId,
|
|
345883
|
+
description: input.title ?? input.alt ?? ""
|
|
345884
|
+
});
|
|
345885
|
+
if (!metadata2.success) {
|
|
345886
|
+
failure8 = createImageFailure(metadata2.failure.code, metadata2.failure.message);
|
|
345887
|
+
throw abortCapture;
|
|
345888
|
+
}
|
|
345889
|
+
entry = readBodyImageEntryById(this.context, entry.publicId) ?? entry;
|
|
345890
|
+
}
|
|
345891
|
+
return { imageNodeId: inserted.imageNodeId, entry };
|
|
345515
345892
|
});
|
|
345516
|
-
|
|
345517
|
-
|
|
345518
|
-
|
|
345893
|
+
} catch (error48) {
|
|
345894
|
+
rollbackCapturedHistory(this.context, capturedTxIds);
|
|
345895
|
+
if (error48 === abortCapture && failure8)
|
|
345896
|
+
return failure8;
|
|
345897
|
+
throw error48;
|
|
345519
345898
|
}
|
|
345899
|
+
const txId = publishImageCreateHistory(this.context, capturedTxIds);
|
|
345520
345900
|
return {
|
|
345521
345901
|
success: true,
|
|
345522
|
-
image: entry?.summary.address ?? {
|
|
345902
|
+
image: published?.entry?.summary.address ?? {
|
|
345523
345903
|
kind: "inline",
|
|
345524
345904
|
nodeType: "image",
|
|
345525
|
-
nodeId:
|
|
345905
|
+
nodeId: published?.imageNodeId ?? "(unknown)",
|
|
345526
345906
|
placement: "inline"
|
|
345527
|
-
}
|
|
345907
|
+
},
|
|
345908
|
+
...txId ? { txId } : {}
|
|
345528
345909
|
};
|
|
345529
345910
|
}
|
|
345530
345911
|
delete(input, options = {}) {
|
|
@@ -347542,6 +347923,16 @@ function validateImageDeleteTarget(context, entry) {
|
|
|
347542
347923
|
}
|
|
347543
347924
|
return null;
|
|
347544
347925
|
}
|
|
347926
|
+
function publishImageCreateHistory(context, txIds) {
|
|
347927
|
+
const uniqueTxIds = [...new Set(txIds)];
|
|
347928
|
+
if (uniqueTxIds.length === 0)
|
|
347929
|
+
return;
|
|
347930
|
+
const logicalGroup = { kind: "image-create", id: uniqueTxIds[0] };
|
|
347931
|
+
for (const txId of uniqueTxIds) {
|
|
347932
|
+
recordCommittedTxIdForHistory(context, txId, { logicalGroup });
|
|
347933
|
+
}
|
|
347934
|
+
return uniqueTxIds[uniqueTxIds.length - 1];
|
|
347935
|
+
}
|
|
347545
347936
|
function createImageFailure(code2, message) {
|
|
347546
347937
|
return { success: false, failure: { code: code2, message } };
|
|
347547
347938
|
}
|
|
@@ -349286,6 +349677,7 @@ var init_adapter17 = __esm(() => {
|
|
|
349286
349677
|
init_document_reader();
|
|
349287
349678
|
init_section_xml();
|
|
349288
349679
|
init_adapter();
|
|
349680
|
+
init_composite();
|
|
349289
349681
|
init_stories();
|
|
349290
349682
|
init_common();
|
|
349291
349683
|
init_tracked_pr_change();
|
|
@@ -353085,13 +353477,14 @@ function buildCompareSourceObservation(context) {
|
|
|
353085
353477
|
if (!bytes)
|
|
353086
353478
|
continue;
|
|
353087
353479
|
const xml = TD98.decode(bytes);
|
|
353480
|
+
const canonicalizeBookmarkIds = bookmarkIdsAreBalanced(xml);
|
|
353088
353481
|
for (const match of xml.matchAll(/<[\w.-]+:bookmarkStart\b([^>]*)>/g)) {
|
|
353089
353482
|
const name = tagAttr(match[1] ?? "", "name");
|
|
353090
353483
|
if (!name || name === "_GoBack")
|
|
353091
353484
|
continue;
|
|
353092
353485
|
acc["fields-references"].present = true;
|
|
353093
353486
|
acc["fields-references"].entityCount += 1;
|
|
353094
|
-
acc["fields-references"].fingerprintParts.push(`bookmark:${source.partUri}:${name}:${tagAttr(match[1] ?? "", "id") ?? ""}`);
|
|
353487
|
+
acc["fields-references"].fingerprintParts.push(`bookmark:${source.partUri}:${name}` + (canonicalizeBookmarkIds ? "" : `:unbalanced-id:${tagAttr(match[1] ?? "", "id") ?? ""}`));
|
|
353095
353488
|
}
|
|
353096
353489
|
for (const match of xml.matchAll(/<[\w.-]+:permStart\b([^>]*)>/g)) {
|
|
353097
353490
|
const id = tagAttr(match[1] ?? "", "id");
|
|
@@ -353133,6 +353526,24 @@ function buildCompareSourceObservation(context) {
|
|
|
353133
353526
|
}));
|
|
353134
353527
|
return { parts, familySignals };
|
|
353135
353528
|
}
|
|
353529
|
+
function bookmarkIdsAreBalanced(xml) {
|
|
353530
|
+
const starts = new Map;
|
|
353531
|
+
for (const match of xml.matchAll(/<[\w.-]+:bookmarkStart\b([^>]*)>/g)) {
|
|
353532
|
+
const id = tagAttr(match[1] ?? "", "id");
|
|
353533
|
+
if (id === null || starts.has(id))
|
|
353534
|
+
return false;
|
|
353535
|
+
starts.set(id, match.index);
|
|
353536
|
+
}
|
|
353537
|
+
const ends = new Set;
|
|
353538
|
+
for (const match of xml.matchAll(/<[\w.-]+:bookmarkEnd\b([^>]*)>/g)) {
|
|
353539
|
+
const id = tagAttr(match[1] ?? "", "id");
|
|
353540
|
+
const start = id === null ? undefined : starts.get(id);
|
|
353541
|
+
if (id === null || start === undefined || ends.has(id) || match.index < start)
|
|
353542
|
+
return false;
|
|
353543
|
+
ends.add(id);
|
|
353544
|
+
}
|
|
353545
|
+
return starts.size === ends.size;
|
|
353546
|
+
}
|
|
353136
353547
|
function captureCompareSourceInventory(context) {
|
|
353137
353548
|
return buildCompareSourceInventory(buildCompareSourceObservation(context));
|
|
353138
353549
|
}
|
|
@@ -353741,6 +354152,7 @@ function projectFieldsReferences(context) {
|
|
|
353741
354152
|
if (!bytes)
|
|
353742
354153
|
continue;
|
|
353743
354154
|
const xml = TD100.decode(bytes);
|
|
354155
|
+
const canonicalizeBookmarkIds = bookmarkIdsAreBalanced2(xml);
|
|
353744
354156
|
for (const match of xml.matchAll(/<[\w.-]+:bookmarkStart\b([^>]*)>/g)) {
|
|
353745
354157
|
const name = tagAttr3(match[1] ?? "", "name");
|
|
353746
354158
|
if (!name || name === "_GoBack")
|
|
@@ -353751,7 +354163,7 @@ function projectFieldsReferences(context) {
|
|
|
353751
354163
|
key: uniqueEntityKey(baseKey, keySeen),
|
|
353752
354164
|
stableKey: `bookmark:${name}`,
|
|
353753
354165
|
semanticKey: `bookmark:${name}`,
|
|
353754
|
-
contentSignature: digest3(`bookmark:${name}#id:${id ?? ""}
|
|
354166
|
+
contentSignature: digest3(`bookmark:${name}#part:${source.partUri}` + (canonicalizeBookmarkIds ? "" : `#unbalanced-id:${id ?? ""}`)),
|
|
353755
354167
|
ordinal: ordinal++,
|
|
353756
354168
|
label: source.scopeKey === "body" ? `bookmark ${name}` : `bookmark ${name} (${source.scopeKey})`
|
|
353757
354169
|
});
|
|
@@ -353759,6 +354171,24 @@ function projectFieldsReferences(context) {
|
|
|
353759
354171
|
}
|
|
353760
354172
|
return entries;
|
|
353761
354173
|
}
|
|
354174
|
+
function bookmarkIdsAreBalanced2(xml) {
|
|
354175
|
+
const starts = new Map;
|
|
354176
|
+
for (const match of xml.matchAll(/<[\w.-]+:bookmarkStart\b([^>]*)>/g)) {
|
|
354177
|
+
const id = tagAttr3(match[1] ?? "", "id");
|
|
354178
|
+
if (id === null || starts.has(id))
|
|
354179
|
+
return false;
|
|
354180
|
+
starts.set(id, match.index);
|
|
354181
|
+
}
|
|
354182
|
+
const ends = new Set;
|
|
354183
|
+
for (const match of xml.matchAll(/<[\w.-]+:bookmarkEnd\b([^>]*)>/g)) {
|
|
354184
|
+
const id = tagAttr3(match[1] ?? "", "id");
|
|
354185
|
+
const start = id === null ? undefined : starts.get(id);
|
|
354186
|
+
if (id === null || start === undefined || ends.has(id) || match.index < start)
|
|
354187
|
+
return false;
|
|
354188
|
+
ends.add(id);
|
|
354189
|
+
}
|
|
354190
|
+
return starts.size === ends.size;
|
|
354191
|
+
}
|
|
353762
354192
|
function projectContentControls(context) {
|
|
353763
354193
|
const entries = [];
|
|
353764
354194
|
let ordinal = 0;
|
|
@@ -354619,8 +355049,12 @@ function projectStories(context, slots) {
|
|
|
354619
355049
|
if (family === "footnotes" || family === "endnotes")
|
|
354620
355050
|
requiredPartBytes(context, story.partUri);
|
|
354621
355051
|
const paragraphs = readStoryParagraphs(context, story.storyId).filter(isWordprocessingParagraph);
|
|
355052
|
+
const runXmls = paragraphs.map((p) => extractParagraphRunXml(p.rawXml, p.namespaceBindings ?? {}));
|
|
355053
|
+
const runSignatures = computeRunSignatures(runXmls);
|
|
355054
|
+
const runXmlByOrdinal = new Map(paragraphs.map((p, i2) => [p.ordinal, runXmls[i2]]));
|
|
355055
|
+
const runSignatureByOrdinal = new Map(paragraphs.map((p, i2) => [p.ordinal, runSignatures[i2]]));
|
|
354622
355056
|
const projectEntry2 = (p) => {
|
|
354623
|
-
const runXml =
|
|
355057
|
+
const runXml = runXmlByOrdinal.get(p.ordinal);
|
|
354624
355058
|
const paragraphPropertiesXml = extractParagraphPropertiesXml(p.rawXml, p.namespaceBindings ?? {});
|
|
354625
355059
|
const blockId = family === "header-footer-parts" && isStructurallyBlankStoryParagraph({ text: p.text, runXml }) ? `${slotKey}::blank:${p.ordinal}` : p.blockId;
|
|
354626
355060
|
return {
|
|
@@ -354629,7 +355063,7 @@ function projectStories(context, slots) {
|
|
|
354629
355063
|
text: p.text,
|
|
354630
355064
|
headingLevel: p.headingLevel,
|
|
354631
355065
|
styleId: p.styleId,
|
|
354632
|
-
runSignature:
|
|
355066
|
+
runSignature: runSignatureByOrdinal.get(p.ordinal),
|
|
354633
355067
|
runXml,
|
|
354634
355068
|
trackedChangeAnnotationKeys: trackedChangeAnnotationKeysForParagraph(context, p),
|
|
354635
355069
|
paragraphPropertiesXml,
|
|
@@ -354702,8 +355136,10 @@ function bodyParagraphStructuralScopes(context, paragraphs) {
|
|
|
354702
355136
|
function projectBody(context) {
|
|
354703
355137
|
const paragraphs = readBodyParagraphs(context).filter(isWordprocessingParagraph);
|
|
354704
355138
|
const scopes = bodyParagraphStructuralScopes(context, paragraphs);
|
|
355139
|
+
const runXmls = paragraphs.map((p) => extractParagraphRunXml(p.rawXml, p.namespaceBindings ?? {}));
|
|
355140
|
+
const runSignatures = computeRunSignatures(runXmls);
|
|
354705
355141
|
return paragraphs.map((p, ordinal) => {
|
|
354706
|
-
const runXml =
|
|
355142
|
+
const runXml = runXmls[ordinal];
|
|
354707
355143
|
const paragraphPropertiesXml = extractParagraphPropertiesXml(p.rawXml, p.namespaceBindings ?? {});
|
|
354708
355144
|
return {
|
|
354709
355145
|
blockId: p.blockId,
|
|
@@ -354712,7 +355148,7 @@ function projectBody(context) {
|
|
|
354712
355148
|
text: p.text,
|
|
354713
355149
|
headingLevel: p.headingLevel,
|
|
354714
355150
|
styleId: p.styleId,
|
|
354715
|
-
runSignature:
|
|
355151
|
+
runSignature: runSignatures[ordinal],
|
|
354716
355152
|
runXml,
|
|
354717
355153
|
trackedChangeAnnotationKeys: trackedChangeAnnotationKeysForParagraph(context, p),
|
|
354718
355154
|
paragraphPropertiesXml,
|
|
@@ -358567,6 +359003,119 @@ var init_main_document_revision_closure = __esm(() => {
|
|
|
358567
359003
|
});
|
|
358568
359004
|
|
|
358569
359005
|
// ../../../v2/document-api-v2-adapter/dist/diff/tracked-table-row-replay.js
|
|
359006
|
+
function rowReplayCoversContentControls(baseAnnotations, targetAnnotations, steps, baseXml, targetXml) {
|
|
359007
|
+
if (steps.length === 0)
|
|
359008
|
+
return false;
|
|
359009
|
+
const base3 = baseAnnotations?.find((group) => group.family === "content-controls")?.entries;
|
|
359010
|
+
const target = targetAnnotations?.find((group) => group.family === "content-controls")?.entries;
|
|
359011
|
+
if (!base3 || !target)
|
|
359012
|
+
return false;
|
|
359013
|
+
const inserted = new Set;
|
|
359014
|
+
const deleted = new Set;
|
|
359015
|
+
for (const step3 of steps) {
|
|
359016
|
+
const identities = step3.kind === "insertRows" ? inserted : deleted;
|
|
359017
|
+
for (const rowXml of step3.rowsXml) {
|
|
359018
|
+
for (const match of rowXml.matchAll(/<[\w.-]+:sdtPr\b[^>]*>([\s\S]*?)<\/[\w.-]+:sdtPr>/g)) {
|
|
359019
|
+
const properties = match[1];
|
|
359020
|
+
if (/<[\w.-]+:dataBinding\b/.test(properties))
|
|
359021
|
+
return false;
|
|
359022
|
+
const tag = /<[\w.-]+:tag\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(properties)?.[1];
|
|
359023
|
+
const alias = /<[\w.-]+:alias\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(properties)?.[1];
|
|
359024
|
+
const id = /<[\w.-]+:id\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(properties)?.[1];
|
|
359025
|
+
const identity2 = tag ?? alias ?? id;
|
|
359026
|
+
const key2 = identity2 ? `sdt:${identity2}` : null;
|
|
359027
|
+
if (!key2 || identities.has(key2))
|
|
359028
|
+
return false;
|
|
359029
|
+
identities.add(key2);
|
|
359030
|
+
}
|
|
359031
|
+
}
|
|
359032
|
+
}
|
|
359033
|
+
const baseByKey = new Map(base3.map((entry) => [entry.key, entry]));
|
|
359034
|
+
const targetByKey = new Map(target.map((entry) => [entry.key, entry]));
|
|
359035
|
+
if (baseByKey.size !== base3.length || targetByKey.size !== target.length)
|
|
359036
|
+
return false;
|
|
359037
|
+
const survivingBaseKeys = base3.filter((entry) => targetByKey.has(entry.key)).map((entry) => entry.key);
|
|
359038
|
+
const survivingTargetKeys = target.filter((entry) => baseByKey.has(entry.key)).map((entry) => entry.key);
|
|
359039
|
+
if (survivingBaseKeys.some((key2, index2) => key2 !== survivingTargetKeys[index2]))
|
|
359040
|
+
return false;
|
|
359041
|
+
if ([...inserted, ...deleted].some((key2) => baseByKey.has(key2) && targetByKey.has(key2)))
|
|
359042
|
+
return false;
|
|
359043
|
+
const baseShapes = contentControlShapes(baseXml);
|
|
359044
|
+
const targetShapes = contentControlShapes(targetXml);
|
|
359045
|
+
if (!baseShapes || !targetShapes)
|
|
359046
|
+
return false;
|
|
359047
|
+
if (survivingBaseKeys.some((key2) => key2.startsWith("sdt:") && (!baseShapes.has(key2) || baseShapes.get(key2) !== targetShapes.get(key2))))
|
|
359048
|
+
return false;
|
|
359049
|
+
for (const entry of base3) {
|
|
359050
|
+
const other = targetByKey.get(entry.key);
|
|
359051
|
+
if (other) {
|
|
359052
|
+
if (entry.contentSignature !== other.contentSignature || entry.semanticKey !== other.semanticKey)
|
|
359053
|
+
return false;
|
|
359054
|
+
} else if (!deleted.has(entry.key))
|
|
359055
|
+
return false;
|
|
359056
|
+
}
|
|
359057
|
+
for (const entry of target) {
|
|
359058
|
+
if (!baseByKey.has(entry.key) && !inserted.has(entry.key))
|
|
359059
|
+
return false;
|
|
359060
|
+
}
|
|
359061
|
+
return [...inserted].every((key2) => targetByKey.has(key2) && !baseByKey.has(key2)) && [...deleted].every((key2) => baseByKey.has(key2) && !targetByKey.has(key2));
|
|
359062
|
+
}
|
|
359063
|
+
function contentControlShapes(xml) {
|
|
359064
|
+
const parsed = collectXmlElementRanges(xml);
|
|
359065
|
+
if (parsed.errors.length > 0)
|
|
359066
|
+
return null;
|
|
359067
|
+
const ranges = [...parsed.ranges].sort((first, second) => first.start - second.start || second.end - first.end);
|
|
359068
|
+
const parents = new Map;
|
|
359069
|
+
const paths = new Map;
|
|
359070
|
+
const siblingCounts = new Map;
|
|
359071
|
+
const stack = [];
|
|
359072
|
+
for (const range of ranges) {
|
|
359073
|
+
while (stack.length && stack[stack.length - 1].end <= range.start)
|
|
359074
|
+
stack.pop();
|
|
359075
|
+
const parent = stack[stack.length - 1] ?? null;
|
|
359076
|
+
if (parent && range.end > parent.end)
|
|
359077
|
+
return null;
|
|
359078
|
+
const siblingIndex = siblingCounts.get(parent) ?? 0;
|
|
359079
|
+
siblingCounts.set(parent, siblingIndex + 1);
|
|
359080
|
+
parents.set(range, parent);
|
|
359081
|
+
paths.set(range, `${parent ? paths.get(parent) : ""}/${range.tag.namespaceUri}:${range.tag.localName}[${siblingIndex}]`);
|
|
359082
|
+
stack.push(range);
|
|
359083
|
+
}
|
|
359084
|
+
const shapes = new Map;
|
|
359085
|
+
const identityCounts = new Map;
|
|
359086
|
+
for (const properties of ranges.filter((range) => range.tag.namespaceUri === WORDPROCESSINGML_NS4 && range.tag.localName === "sdtPr")) {
|
|
359087
|
+
const propertyXml = xml.slice(properties.start, properties.end);
|
|
359088
|
+
const tag = /<[^>]*:tag\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(propertyXml)?.[1];
|
|
359089
|
+
const alias = /<[^>]*:alias\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(propertyXml)?.[1];
|
|
359090
|
+
const id = /<[^>]*:id\b[^>]*\b(?:[\w.-]+:)?val="([^"]*)"/.exec(propertyXml)?.[1];
|
|
359091
|
+
const key2 = tag ?? alias ?? id;
|
|
359092
|
+
if (!key2)
|
|
359093
|
+
return null;
|
|
359094
|
+
const control = parents.get(properties);
|
|
359095
|
+
if (!control || control.tag.namespaceUri !== WORDPROCESSINGML_NS4 || control.tag.localName !== "sdt")
|
|
359096
|
+
return null;
|
|
359097
|
+
const parent = parents.get(control);
|
|
359098
|
+
const content3 = ranges.find((range) => parents.get(range) === control && range.tag.namespaceUri === WORDPROCESSINGML_NS4 && range.tag.localName === "sdtContent");
|
|
359099
|
+
const firstChild = content3 && ranges.find((range) => parents.get(range) === content3);
|
|
359100
|
+
if (!parent || !content3 || !firstChild)
|
|
359101
|
+
return null;
|
|
359102
|
+
const identity2 = `sdt:${key2}`;
|
|
359103
|
+
const count = (identityCounts.get(identity2) ?? 0) + 1;
|
|
359104
|
+
identityCounts.set(identity2, count);
|
|
359105
|
+
const uniqueIdentity = count === 1 ? identity2 : `${identity2}#${count}`;
|
|
359106
|
+
let ancestor = parent;
|
|
359107
|
+
let insideRow = false;
|
|
359108
|
+
while (ancestor) {
|
|
359109
|
+
if (ancestor.tag.namespaceUri === WORDPROCESSINGML_NS4 && ancestor.tag.localName === "tr") {
|
|
359110
|
+
insideRow = true;
|
|
359111
|
+
break;
|
|
359112
|
+
}
|
|
359113
|
+
ancestor = parents.get(ancestor) ?? null;
|
|
359114
|
+
}
|
|
359115
|
+
shapes.set(uniqueIdentity, `${parent.tag.namespaceUri}:${parent.tag.localName}|${firstChild.tag.namespaceUri}:${firstChild.tag.localName}|${insideRow ? "row" : paths.get(control)}`);
|
|
359116
|
+
}
|
|
359117
|
+
return shapes;
|
|
359118
|
+
}
|
|
358570
359119
|
function buildTrackedTableRowReplayPlan(input) {
|
|
358571
359120
|
if (input.base.xml === input.target.xml) {
|
|
358572
359121
|
return { steps: [], bodyOperations: input.bodyOperations, unsafeReasons: [] };
|
|
@@ -358584,30 +359133,36 @@ function buildTrackedTableRowReplayPlan(input) {
|
|
|
358584
359133
|
}
|
|
358585
359134
|
const ownedBlockIds = new Set;
|
|
358586
359135
|
const steps = [];
|
|
359136
|
+
const usedParagraphIds = new Set([
|
|
359137
|
+
...input.base.xml.matchAll(/\bparaId="([0-9A-Fa-f]{8})"/g),
|
|
359138
|
+
...input.target.xml.matchAll(/\bparaId="([0-9A-Fa-f]{8})"/g)
|
|
359139
|
+
].map((match) => match[1].toUpperCase()));
|
|
359140
|
+
const baseParagraphIds = new Set([...input.base.xml.matchAll(/\bparaId="([0-9A-Fa-f]{8})"/g)].map((match) => match[1].toUpperCase()));
|
|
358587
359141
|
for (let tableIndex = 0;tableIndex < baseCatalog.tables.length; tableIndex += 1) {
|
|
358588
359142
|
const baseTable = baseCatalog.tables[tableIndex];
|
|
358589
359143
|
const targetTable = targetCatalog.tables[tableIndex];
|
|
358590
|
-
if (!isSimpleTable(baseTable) || !isSimpleTable(targetTable)) {
|
|
359144
|
+
if (!isSimpleTable(baseTable, baseBytes, baseRoot) || !isSimpleTable(targetTable, targetBytes, targetRoot)) {
|
|
358591
359145
|
return unsafe(`table ${baseTable.tableNodeId} has columns, merges, nesting, or unsupported cell content`);
|
|
358592
359146
|
}
|
|
358593
359147
|
if (baseTable.gridColumnCount !== targetTable.gridColumnCount) {
|
|
358594
359148
|
return unsafe(`table ${baseTable.tableNodeId} changes its column grid`);
|
|
358595
359149
|
}
|
|
358596
|
-
const
|
|
358597
|
-
const
|
|
358598
|
-
|
|
358599
|
-
|
|
358600
|
-
const
|
|
358601
|
-
|
|
358602
|
-
return
|
|
358603
|
-
|
|
358604
|
-
if (
|
|
359150
|
+
const rowKey = (row, bytes) => sliceBytes(bytes, row.rowByteStart, row.rowByteEnd).replace(/\s+w14:paraId="[0-9A-Fa-f]{8}"/g, "");
|
|
359151
|
+
const baseKeys = baseTable.rows.map((row) => rowKey(row, baseBytes));
|
|
359152
|
+
const targetKeys = targetTable.rows.map((row) => rowKey(row, targetBytes));
|
|
359153
|
+
const baseIsShorter = baseKeys.length <= targetKeys.length;
|
|
359154
|
+
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));
|
|
359155
|
+
if (!matched)
|
|
359156
|
+
return unsafe(`table ${baseTable.tableNodeId} modifies, reorders, or ambiguously matches rows`, new Set(baseKeys).size < baseKeys.length || new Set(targetKeys).size < targetKeys.length);
|
|
359157
|
+
const baseIndexByTarget = new Map([...matched].map(([shortIndex, longIndex]) => baseIsShorter ? [longIndex, shortIndex] : [shortIndex, longIndex]));
|
|
359158
|
+
if (baseIndexByTarget.size === 0)
|
|
358605
359159
|
return unsafe(`table ${baseTable.tableNodeId} has no surviving row`);
|
|
358606
|
-
if (
|
|
358607
|
-
return unsafe(`table ${baseTable.tableNodeId}
|
|
359160
|
+
if (hasInconsistentRowIdentity(baseTable.rows, targetTable.rows, baseIndexByTarget)) {
|
|
359161
|
+
return unsafe(`table ${baseTable.tableNodeId} reassigns a row identity outside its original position`, true);
|
|
358608
359162
|
}
|
|
358609
|
-
|
|
358610
|
-
|
|
359163
|
+
const targetIndexByBase = new Map([...baseIndexByTarget].map(([targetIndex, baseIndex]) => [baseIndex, targetIndex]));
|
|
359164
|
+
for (const [baseIndex, baseRow] of baseTable.rows.entries()) {
|
|
359165
|
+
const targetPosition = targetIndexByBase.get(baseIndex);
|
|
358611
359166
|
if (targetPosition === undefined) {
|
|
358612
359167
|
const rowXml = sliceBytes(baseBytes, baseRow.rowByteStart, baseRow.rowByteEnd);
|
|
358613
359168
|
if (containsWordprocessingRevisionMarkup(rowXml, baseRoot.namespaceBindings)) {
|
|
@@ -358631,26 +359186,27 @@ function buildTrackedTableRowReplayPlan(input) {
|
|
|
358631
359186
|
}
|
|
358632
359187
|
const targetRow = targetTable.rows[targetPosition];
|
|
358633
359188
|
if (sliceBytes(baseBytes, baseRow.rowByteStart, baseRow.rowByteEnd) !== sliceBytes(targetBytes, targetRow.rowByteStart, targetRow.rowByteEnd)) {
|
|
358634
|
-
|
|
359189
|
+
if (baseKeys[baseIndex] !== targetKeys[targetPosition]) {
|
|
359190
|
+
return unsafe(`table ${baseTable.tableNodeId} modifies an existing row`);
|
|
359191
|
+
}
|
|
358635
359192
|
}
|
|
358636
359193
|
}
|
|
358637
359194
|
if (tableSkeleton(baseBytes, baseTable) !== tableSkeleton(targetBytes, targetTable)) {
|
|
358638
359195
|
return unsafe(`table ${baseTable.tableNodeId} changes non-row table structure`);
|
|
358639
359196
|
}
|
|
358640
|
-
const baseIds = new Set(baseTable.rows.map((row) => row.rowNodeId));
|
|
358641
359197
|
let index2 = 0;
|
|
358642
359198
|
while (index2 < targetTable.rows.length) {
|
|
358643
|
-
if (
|
|
359199
|
+
if (baseIndexByTarget.has(index2)) {
|
|
358644
359200
|
index2 += 1;
|
|
358645
359201
|
continue;
|
|
358646
359202
|
}
|
|
358647
359203
|
const start = index2;
|
|
358648
|
-
while (index2 < targetTable.rows.length && !
|
|
359204
|
+
while (index2 < targetTable.rows.length && !baseIndexByTarget.has(index2))
|
|
358649
359205
|
index2 += 1;
|
|
358650
359206
|
const inserted = targetTable.rows.slice(start, index2);
|
|
358651
|
-
const
|
|
358652
|
-
const
|
|
358653
|
-
const anchor =
|
|
359207
|
+
const nextBaseIndex = baseIndexByTarget.get(index2);
|
|
359208
|
+
const previousBaseIndex = [...baseIndexByTarget.entries()].reverse().find(([targetIndex]) => targetIndex < start)?.[1];
|
|
359209
|
+
const anchor = baseTable.rows[nextBaseIndex ?? previousBaseIndex ?? -1];
|
|
358654
359210
|
if (!anchor)
|
|
358655
359211
|
return unsafe(`table ${baseTable.tableNodeId} has no stable insertion anchor`);
|
|
358656
359212
|
for (const row of inserted) {
|
|
@@ -358672,20 +359228,34 @@ function buildTrackedTableRowReplayPlan(input) {
|
|
|
358672
359228
|
const rowXml = transplantableRowPayload(sourceRowXml, baseRoot, targetRoot);
|
|
358673
359229
|
if (!rowXml)
|
|
358674
359230
|
return unsafe("inserted row uses a namespace that cannot be transplanted safely");
|
|
358675
|
-
|
|
359231
|
+
const identifiedRowXml = ensureInsertedParagraphIds(rowXml, baseRoot, baseParagraphIds, usedParagraphIds);
|
|
359232
|
+
if (!identifiedRowXml)
|
|
359233
|
+
return unsafe("inserted row cannot be assigned safe paragraph identities");
|
|
359234
|
+
rowsXml.push(identifiedRowXml);
|
|
358676
359235
|
}
|
|
358677
359236
|
steps.push({
|
|
358678
359237
|
kind: "insertRows",
|
|
358679
359238
|
storyId: STORY_ID2,
|
|
358680
359239
|
tableNodeId: baseTable.tableNodeId,
|
|
358681
359240
|
anchorRowNodeId: anchor.rowNodeId,
|
|
358682
|
-
placement:
|
|
359241
|
+
placement: nextBaseIndex !== undefined ? "before" : "after",
|
|
358683
359242
|
rowsXml
|
|
358684
359243
|
});
|
|
358685
359244
|
}
|
|
359245
|
+
if (steps.some((step3) => step3.tableNodeId === baseTable.tableNodeId)) {
|
|
359246
|
+
for (const entry of [...input.baseBody ?? [], ...input.targetBody]) {
|
|
359247
|
+
if (entry.structuralScope?.startsWith(`table:${baseTable.tableNodeId}:cell:`) || entry.structuralScope?.startsWith(`table:${targetTable.tableNodeId}:cell:`)) {
|
|
359248
|
+
ownedBlockIds.add(entry.blockId);
|
|
359249
|
+
}
|
|
359250
|
+
}
|
|
359251
|
+
}
|
|
358686
359252
|
}
|
|
358687
359253
|
if (steps.length === 0)
|
|
358688
359254
|
return unsafe("table topology changed without an inserted or deleted row");
|
|
359255
|
+
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:"))));
|
|
359256
|
+
if (ambiguousBodyOperation) {
|
|
359257
|
+
return unsafe(`body operation ${ambiguousBodyOperation.blockId} shares a table-cell identity`, true);
|
|
359258
|
+
}
|
|
358689
359259
|
const bodyOperations = input.bodyOperations.filter((operation) => !ownedBlockIds.has(operation.blockId));
|
|
358690
359260
|
const unownedStructuralOperation = bodyOperations.find((operation) => {
|
|
358691
359261
|
const target = input.targetBody.find((entry) => entry.blockId === operation.blockId);
|
|
@@ -358715,21 +359285,135 @@ function containsWordprocessingRevisionMarkup(xml, namespaceBindings) {
|
|
|
358715
359285
|
}
|
|
358716
359286
|
return containsRevision;
|
|
358717
359287
|
}
|
|
358718
|
-
function unsafe(reason) {
|
|
358719
|
-
return { steps: [], bodyOperations: [], unsafeReasons: [reason] };
|
|
359288
|
+
function unsafe(reason, refuseBlockFallback = false) {
|
|
359289
|
+
return { steps: [], bodyOperations: [], unsafeReasons: [reason], refuseBlockFallback };
|
|
358720
359290
|
}
|
|
358721
|
-
function
|
|
358722
|
-
const
|
|
358723
|
-
|
|
358724
|
-
|
|
358725
|
-
|
|
359291
|
+
function matchRowSubsequence(shortKeys, longKeys, shortIds, longIds) {
|
|
359292
|
+
const remainingMatches = (shortStart, longStart) => {
|
|
359293
|
+
for (let shortIndex = shortStart;shortIndex < shortKeys.length; shortIndex += 1) {
|
|
359294
|
+
while (longStart < longKeys.length && longKeys[longStart] !== shortKeys[shortIndex])
|
|
359295
|
+
longStart += 1;
|
|
359296
|
+
if (longStart === longKeys.length)
|
|
359297
|
+
return false;
|
|
359298
|
+
longStart += 1;
|
|
359299
|
+
}
|
|
359300
|
+
return true;
|
|
359301
|
+
};
|
|
359302
|
+
const matches = new Map;
|
|
359303
|
+
let nextLongIndex = 0;
|
|
359304
|
+
for (let shortIndex = 0;shortIndex < shortKeys.length; shortIndex += 1) {
|
|
359305
|
+
const candidates = [];
|
|
359306
|
+
for (let longIndex = nextLongIndex;longIndex < longKeys.length; longIndex += 1) {
|
|
359307
|
+
if (shortKeys[shortIndex] === longKeys[longIndex] && remainingMatches(shortIndex + 1, longIndex + 1))
|
|
359308
|
+
candidates.push(longIndex);
|
|
359309
|
+
}
|
|
359310
|
+
if (candidates.length === 0)
|
|
358726
359311
|
return null;
|
|
358727
|
-
|
|
359312
|
+
const sameIdentity = candidates.filter((index2) => shortIds[shortIndex] === longIds[index2]);
|
|
359313
|
+
if (candidates.length > 1 && sameIdentity.length !== 1)
|
|
359314
|
+
return null;
|
|
359315
|
+
const selected = sameIdentity[0] ?? candidates[0];
|
|
359316
|
+
matches.set(shortIndex, selected);
|
|
359317
|
+
nextLongIndex = selected + 1;
|
|
358728
359318
|
}
|
|
358729
|
-
|
|
359319
|
+
for (const [shortIndex, longIndex] of matches) {
|
|
359320
|
+
const key2 = shortKeys[shortIndex];
|
|
359321
|
+
if (shortKeys.indexOf(key2) === shortKeys.lastIndexOf(key2) && longKeys.indexOf(key2) === longKeys.lastIndexOf(key2))
|
|
359322
|
+
continue;
|
|
359323
|
+
const sharedLongIndex = longIds.findIndex((id, index2) => id === shortIds[shortIndex] && longKeys[index2] === key2);
|
|
359324
|
+
const sharedShortIndex = shortIds.findIndex((id, index2) => id === longIds[longIndex] && shortKeys[index2] === key2);
|
|
359325
|
+
if (sharedLongIndex >= 0 && sharedLongIndex !== longIndex || sharedShortIndex >= 0 && sharedShortIndex !== shortIndex)
|
|
359326
|
+
return null;
|
|
359327
|
+
}
|
|
359328
|
+
return matches;
|
|
359329
|
+
}
|
|
359330
|
+
function hasInconsistentRowIdentity(baseRows, targetRows, baseIndexByTarget) {
|
|
359331
|
+
const baseIndexById = new Map(baseRows.map((row, index2) => [row.rowNodeId, index2]));
|
|
359332
|
+
for (const [targetIndex, targetRow] of targetRows.entries()) {
|
|
359333
|
+
if (targetRow.identityProvenance !== "para-id")
|
|
359334
|
+
continue;
|
|
359335
|
+
const baseIndex = baseIndexById.get(targetRow.rowNodeId);
|
|
359336
|
+
if (baseIndex === undefined || baseRows[baseIndex].identityProvenance !== "para-id")
|
|
359337
|
+
continue;
|
|
359338
|
+
if (baseIndex !== targetIndex && baseIndexByTarget.get(targetIndex) !== baseIndex)
|
|
359339
|
+
return true;
|
|
359340
|
+
}
|
|
359341
|
+
return false;
|
|
359342
|
+
}
|
|
359343
|
+
function isSimpleTable(table, bytes, root) {
|
|
359344
|
+
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)));
|
|
359345
|
+
}
|
|
359346
|
+
function isSafeContentControlCell(xml, root) {
|
|
359347
|
+
let foundControl = false;
|
|
359348
|
+
let safe = true;
|
|
359349
|
+
const parser = createXmlSaxParser({
|
|
359350
|
+
namespaceAware: true,
|
|
359351
|
+
fragment: true,
|
|
359352
|
+
additionalNamespaces: { ...root.namespaceBindings }
|
|
359353
|
+
});
|
|
359354
|
+
parser.on("error", () => {
|
|
359355
|
+
safe = false;
|
|
359356
|
+
});
|
|
359357
|
+
parser.on("opentag", (tag) => {
|
|
359358
|
+
if (tag.namespaceUri !== WORDPROCESSINGML_NS4)
|
|
359359
|
+
return;
|
|
359360
|
+
if (tag.localName === "sdt")
|
|
359361
|
+
foundControl = true;
|
|
359362
|
+
if (["drawing", "object", "oMath", "oMathPara", "tbl"].includes(tag.localName) || tag.attributes.some((attribute2) => isRelationshipNamespace(attribute2.namespaceUri)))
|
|
359363
|
+
safe = false;
|
|
359364
|
+
});
|
|
359365
|
+
try {
|
|
359366
|
+
parser.write(xml);
|
|
359367
|
+
parser.close();
|
|
359368
|
+
} catch {
|
|
359369
|
+
return false;
|
|
359370
|
+
}
|
|
359371
|
+
return foundControl && safe;
|
|
358730
359372
|
}
|
|
358731
|
-
function
|
|
358732
|
-
|
|
359373
|
+
function ensureInsertedParagraphIds(xml, root, baseIds, usedIds) {
|
|
359374
|
+
const parsed = collectXmlElementRanges(xml, {
|
|
359375
|
+
fragment: true,
|
|
359376
|
+
additionalNamespaces: { ...root.namespaceBindings }
|
|
359377
|
+
});
|
|
359378
|
+
if (parsed.errors.length > 0)
|
|
359379
|
+
return null;
|
|
359380
|
+
const insertions = [];
|
|
359381
|
+
for (const paragraph4 of parsed.ranges.filter((range) => range.tag.namespaceUri === WORDPROCESSINGML_NS4 && range.tag.localName === "p")) {
|
|
359382
|
+
const existingId = paragraph4.tag.attributes.find((attribute2) => attribute2.namespaceUri === WORDPROCESSINGML_2010_NS && attribute2.localName === "paraId");
|
|
359383
|
+
if (existingId && !baseIds.has(existingId.value.toUpperCase()))
|
|
359384
|
+
continue;
|
|
359385
|
+
let identifier;
|
|
359386
|
+
for (let candidate2 = 1879048192;candidate2 > 0; candidate2 -= 1) {
|
|
359387
|
+
const value2 = candidate2.toString(16).toUpperCase().padStart(8, "0");
|
|
359388
|
+
if (!usedIds.has(value2)) {
|
|
359389
|
+
identifier = value2;
|
|
359390
|
+
usedIds.add(value2);
|
|
359391
|
+
break;
|
|
359392
|
+
}
|
|
359393
|
+
}
|
|
359394
|
+
if (!identifier)
|
|
359395
|
+
return null;
|
|
359396
|
+
if (existingId) {
|
|
359397
|
+
const opening = xml.slice(paragraph4.start, paragraph4.openEnd);
|
|
359398
|
+
const attribute2 = new RegExp(`\\b${existingId.name}="${existingId.value}"`);
|
|
359399
|
+
const match = attribute2.exec(opening);
|
|
359400
|
+
if (!match)
|
|
359401
|
+
return null;
|
|
359402
|
+
insertions.push({
|
|
359403
|
+
offset: paragraph4.start + match.index,
|
|
359404
|
+
text: `${existingId.name}="${identifier}"`,
|
|
359405
|
+
end: paragraph4.start + match.index + match[0].length
|
|
359406
|
+
});
|
|
359407
|
+
} else {
|
|
359408
|
+
const localDeclaration = paragraph4.namespaceBindings.w14 === WORDPROCESSINGML_2010_NS ? "" : ` xmlns:w14="${WORDPROCESSINGML_2010_NS}"`;
|
|
359409
|
+
const opening = xml.slice(paragraph4.start, paragraph4.openEnd);
|
|
359410
|
+
insertions.push({
|
|
359411
|
+
offset: paragraph4.openEnd - (opening.endsWith("/>") ? 2 : 1),
|
|
359412
|
+
text: `${localDeclaration} w14:paraId="${identifier}"`
|
|
359413
|
+
});
|
|
359414
|
+
}
|
|
359415
|
+
}
|
|
359416
|
+
return insertions.reverse().reduce((result, insertion) => result.slice(0, insertion.offset) + insertion.text + result.slice(insertion.end ?? insertion.offset), xml);
|
|
358733
359417
|
}
|
|
358734
359418
|
function tableSkeleton(bytes, table) {
|
|
358735
359419
|
let cursor = table.tableByteStart;
|
|
@@ -360034,10 +360718,16 @@ function projectMainDocumentBodyEntries(source, options = {}) {
|
|
|
360034
360718
|
});
|
|
360035
360719
|
const scopes = mapBodyParagraphStructuralScopes(tableCatalog, paragraphIndex.entries);
|
|
360036
360720
|
const namespaceBindingsByByteStart = scanParagraphNamespaceBindingsByByteStart(source.xml);
|
|
360037
|
-
|
|
360038
|
-
|
|
360721
|
+
const rawXmls = paragraphIndex.entries.map((entry) => TD107.decode(bytes.subarray(entry.byteStart, entry.byteEnd)));
|
|
360722
|
+
const runXmls = paragraphIndex.entries.map((entry, index2) => {
|
|
360723
|
+
const namespaceBindings = namespaceBindingsByByteStart.get(entry.byteStart) ?? {};
|
|
360724
|
+
return extractParagraphRunXml(rawXmls[index2], namespaceBindings);
|
|
360725
|
+
});
|
|
360726
|
+
const runSignatures = computeRunSignatures(runXmls);
|
|
360727
|
+
return paragraphIndex.entries.map((entry, index2) => {
|
|
360728
|
+
const rawXml = rawXmls[index2];
|
|
360039
360729
|
const namespaceBindings = namespaceBindingsByByteStart.get(entry.byteStart) ?? {};
|
|
360040
|
-
const runXml =
|
|
360730
|
+
const runXml = runXmls[index2];
|
|
360041
360731
|
const paragraphPropertiesXml = extractParagraphPropertiesXml(rawXml, namespaceBindings);
|
|
360042
360732
|
return {
|
|
360043
360733
|
blockId: entry.blockId,
|
|
@@ -360046,7 +360736,7 @@ function projectMainDocumentBodyEntries(source, options = {}) {
|
|
|
360046
360736
|
text: readVisibleParagraphText(rawXml),
|
|
360047
360737
|
headingLevel: paragraphHeadingLevel(rawXml, { paragraphStyleOutlineLevels }),
|
|
360048
360738
|
styleId: paragraphStyleId(rawXml),
|
|
360049
|
-
runSignature:
|
|
360739
|
+
runSignature: runSignatures[index2],
|
|
360050
360740
|
runXml,
|
|
360051
360741
|
paragraphPropertiesXml,
|
|
360052
360742
|
paragraphPropertiesSignature: computeParagraphPropertiesSignature2(paragraphPropertiesXml)
|
|
@@ -361391,7 +362081,32 @@ function paragraphOpeningTag2(paragraphXml) {
|
|
|
361391
362081
|
return paragraphXml.slice(0, paragraphXml.indexOf(">") + 1);
|
|
361392
362082
|
}
|
|
361393
362083
|
function ownedStructuresEqual(leftXml, rightXml) {
|
|
361394
|
-
return arraysEqual2(collectElements(leftXml, "sectPr"), collectElements(rightXml, "sectPr")) &&
|
|
362084
|
+
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"));
|
|
362085
|
+
}
|
|
362086
|
+
function bookmarkStructuresEqual(leftXml, rightXml) {
|
|
362087
|
+
const summarize = (xml) => {
|
|
362088
|
+
if (!bookmarkRangesArePaired(xml))
|
|
362089
|
+
return null;
|
|
362090
|
+
const nameById = new Map(collectWordElements(xml, "bookmarkStart", true).map((element) => {
|
|
362091
|
+
const id = readAttribute2(element, "id");
|
|
362092
|
+
const name = readAttribute2(element, "name");
|
|
362093
|
+
return [id, name];
|
|
362094
|
+
}));
|
|
362095
|
+
const starts = collectWordElements(xml, "bookmarkStart", true).map((element) => ({
|
|
362096
|
+
position: element.range.start,
|
|
362097
|
+
value: `start:${replaceAttribute(element, "id", "__bookmark_id__")}`
|
|
362098
|
+
}));
|
|
362099
|
+
const ends = collectWordElements(xml, "bookmarkEnd", true).map((element) => ({
|
|
362100
|
+
position: element.range.start,
|
|
362101
|
+
value: `end:${replaceAttribute(element, "id", `__bookmark_${nameById.get(readAttribute2(element, "id")) ?? "missing"}__`)}`
|
|
362102
|
+
}));
|
|
362103
|
+
return [...starts, ...ends].sort((a, b) => a.position - b.position).map((event) => event.value);
|
|
362104
|
+
};
|
|
362105
|
+
const left = summarize(leftXml);
|
|
362106
|
+
const right = summarize(rightXml);
|
|
362107
|
+
if (!left || !right || left.length !== right.length)
|
|
362108
|
+
return false;
|
|
362109
|
+
return left.every((value2, index2) => value2 === right[index2]);
|
|
361395
362110
|
}
|
|
361396
362111
|
function arraysEqual2(left, right) {
|
|
361397
362112
|
return left.length === right.length && left.every((value2, index2) => value2 === right[index2]);
|
|
@@ -361427,39 +362142,44 @@ function buildSectionSteps(baseXml, targetXml, unsafeReasons) {
|
|
|
361427
362142
|
function buildReferenceSteps(baseXml, targetXml, unsafeReasons) {
|
|
361428
362143
|
const baseBookmarks = collectWordElements(baseXml, "bookmarkStart", true);
|
|
361429
362144
|
const targetBookmarks = collectWordElements(targetXml, "bookmarkStart", true);
|
|
361430
|
-
if (baseBookmarks.length !== targetBookmarks.length) {
|
|
361431
|
-
unsafeReasons.push("bookmark topology changed");
|
|
361432
|
-
return [];
|
|
361433
|
-
}
|
|
361434
362145
|
if (!bookmarkRangesArePaired(baseXml) || !bookmarkRangesArePaired(targetXml)) {
|
|
361435
362146
|
unsafeReasons.push("bookmark topology is unbalanced or duplicated");
|
|
361436
362147
|
return [];
|
|
361437
362148
|
}
|
|
361438
362149
|
const renamedBookmarks = new Map;
|
|
361439
362150
|
const steps = [];
|
|
361440
|
-
|
|
361441
|
-
|
|
361442
|
-
|
|
361443
|
-
|
|
361444
|
-
|
|
361445
|
-
|
|
361446
|
-
|
|
361447
|
-
|
|
361448
|
-
|
|
361449
|
-
|
|
361450
|
-
|
|
361451
|
-
|
|
361452
|
-
|
|
361453
|
-
|
|
362151
|
+
if (baseBookmarks.length === targetBookmarks.length) {
|
|
362152
|
+
for (let index2 = 0;index2 < baseBookmarks.length; index2 += 1) {
|
|
362153
|
+
const before = baseBookmarks[index2];
|
|
362154
|
+
const after = targetBookmarks[index2];
|
|
362155
|
+
const beforeXml = before.xml;
|
|
362156
|
+
const afterXml = after.xml;
|
|
362157
|
+
if (beforeXml === afterXml)
|
|
362158
|
+
continue;
|
|
362159
|
+
const beforeId = readAttribute2(before, "id");
|
|
362160
|
+
const afterId = readAttribute2(after, "id");
|
|
362161
|
+
const beforeName = readAttribute2(before, "name");
|
|
362162
|
+
const afterName = readAttribute2(after, "name");
|
|
362163
|
+
if (beforeId && afterId && beforeName && beforeName === afterName && replaceAttribute(after, "id", beforeId) === beforeXml) {
|
|
362164
|
+
continue;
|
|
362165
|
+
}
|
|
362166
|
+
if (!beforeId || beforeId !== afterId || !beforeName || !afterName || replaceAttribute(before, "name", afterName) !== afterXml) {
|
|
362167
|
+
unsafeReasons.push(`bookmark ${index2} changed beyond a name-only rename or ID allocation`);
|
|
362168
|
+
continue;
|
|
362169
|
+
}
|
|
362170
|
+
renamedBookmarks.set(beforeName, afterName);
|
|
362171
|
+
steps.push({
|
|
362172
|
+
kind: "bookmark-start",
|
|
362173
|
+
beforeXml,
|
|
362174
|
+
afterXml,
|
|
362175
|
+
beforeNamespaceBindings: { ...before.range.namespaceBindings },
|
|
362176
|
+
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
362177
|
+
});
|
|
361454
362178
|
}
|
|
361455
|
-
|
|
361456
|
-
steps.push(
|
|
361457
|
-
|
|
361458
|
-
|
|
361459
|
-
afterXml,
|
|
361460
|
-
beforeNamespaceBindings: { ...before.range.namespaceBindings },
|
|
361461
|
-
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
361462
|
-
});
|
|
362179
|
+
} else if (targetBookmarks.length > baseBookmarks.length) {
|
|
362180
|
+
steps.push(...buildAddedBookmarkSteps(baseXml, targetXml, baseBookmarks, targetBookmarks, unsafeReasons));
|
|
362181
|
+
} else {
|
|
362182
|
+
unsafeReasons.push("bookmark removal is not supported");
|
|
361463
362183
|
}
|
|
361464
362184
|
const baseFields = collectWordElements(baseXml, "fldSimple");
|
|
361465
362185
|
const targetFields = collectWordElements(targetXml, "fldSimple");
|
|
@@ -361490,8 +362210,125 @@ function buildReferenceSteps(baseXml, targetXml, unsafeReasons) {
|
|
|
361490
362210
|
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
361491
362211
|
});
|
|
361492
362212
|
}
|
|
362213
|
+
steps.push(...buildAddedComplexFieldSteps(baseXml, targetXml, unsafeReasons));
|
|
362214
|
+
return steps;
|
|
362215
|
+
}
|
|
362216
|
+
function buildAddedBookmarkSteps(baseXml, targetXml, baseBookmarks, targetBookmarks, unsafeReasons) {
|
|
362217
|
+
const baseNames = new Set(baseBookmarks.map((element) => readAttribute2(element, "name")));
|
|
362218
|
+
const targetNames = targetBookmarks.map((element) => readAttribute2(element, "name"));
|
|
362219
|
+
if (baseNames.has(null) || targetNames.some((name) => name === null) || new Set(targetNames).size !== targetNames.length || [...baseNames].some((name) => !targetNames.includes(name))) {
|
|
362220
|
+
unsafeReasons.push("bookmark addition cannot be matched unambiguously by name");
|
|
362221
|
+
return [];
|
|
362222
|
+
}
|
|
362223
|
+
const baseParagraphs = collectWordElements(baseXml, "p");
|
|
362224
|
+
const targetParagraphs = collectWordElements(targetXml, "p");
|
|
362225
|
+
if (baseParagraphs.length !== targetParagraphs.length) {
|
|
362226
|
+
unsafeReasons.push("bookmark addition changed paragraph topology");
|
|
362227
|
+
return [];
|
|
362228
|
+
}
|
|
362229
|
+
const targetEnds = collectWordElements(targetXml, "bookmarkEnd", true);
|
|
362230
|
+
const steps = [];
|
|
362231
|
+
for (const start of targetBookmarks.filter((element) => !baseNames.has(readAttribute2(element, "name")))) {
|
|
362232
|
+
const id = readAttribute2(start, "id");
|
|
362233
|
+
const end = targetEnds.find((candidate2) => readAttribute2(candidate2, "id") === id);
|
|
362234
|
+
const paragraphIndex = targetParagraphs.findIndex((paragraph4) => paragraph4.range.start < start.range.start && paragraph4.range.end > (end?.range.end ?? Number.MAX_SAFE_INTEGER));
|
|
362235
|
+
if (!id || !end || paragraphIndex < 0) {
|
|
362236
|
+
unsafeReasons.push("added bookmark range is not contained in one paragraph");
|
|
362237
|
+
continue;
|
|
362238
|
+
}
|
|
362239
|
+
const before = baseParagraphs[paragraphIndex];
|
|
362240
|
+
const after = targetParagraphs[paragraphIndex];
|
|
362241
|
+
const beforeFragmentXml = targetXml.slice(start.range.end, end.range.start);
|
|
362242
|
+
const afterFragmentXml = targetXml.slice(start.range.start, end.range.end);
|
|
362243
|
+
if (replaceUnique(after.xml, afterFragmentXml, beforeFragmentXml) !== before.xml) {
|
|
362244
|
+
unsafeReasons.push("added bookmark range changes content beyond a balanced wrapper");
|
|
362245
|
+
continue;
|
|
362246
|
+
}
|
|
362247
|
+
steps.push({
|
|
362248
|
+
kind: "bookmark-range",
|
|
362249
|
+
beforeXml: before.xml,
|
|
362250
|
+
afterXml: after.xml,
|
|
362251
|
+
beforeFragmentXml,
|
|
362252
|
+
afterFragmentXml,
|
|
362253
|
+
beforeNamespaceBindings: { ...before.range.namespaceBindings },
|
|
362254
|
+
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
362255
|
+
});
|
|
362256
|
+
}
|
|
361493
362257
|
return steps;
|
|
361494
362258
|
}
|
|
362259
|
+
function buildAddedComplexFieldSteps(baseXml, targetXml, unsafeReasons) {
|
|
362260
|
+
const baseParagraphs = collectWordElements(baseXml, "p");
|
|
362261
|
+
const targetParagraphs = collectWordElements(targetXml, "p");
|
|
362262
|
+
if (baseParagraphs.length !== targetParagraphs.length)
|
|
362263
|
+
return [];
|
|
362264
|
+
const targetBookmarkNameCounts = new Map;
|
|
362265
|
+
for (const bookmark of collectWordElements(targetXml, "bookmarkStart", true)) {
|
|
362266
|
+
const name = readAttribute2(bookmark, "name");
|
|
362267
|
+
if (name !== null) {
|
|
362268
|
+
targetBookmarkNameCounts.set(name, (targetBookmarkNameCounts.get(name) ?? 0) + 1);
|
|
362269
|
+
}
|
|
362270
|
+
}
|
|
362271
|
+
const steps = [];
|
|
362272
|
+
for (let index2 = 0;index2 < targetParagraphs.length; index2 += 1) {
|
|
362273
|
+
const before = baseParagraphs[index2];
|
|
362274
|
+
const after = targetParagraphs[index2];
|
|
362275
|
+
if (before.xml === after.xml)
|
|
362276
|
+
continue;
|
|
362277
|
+
const candidate2 = addedComplexRefField(after, before.xml);
|
|
362278
|
+
if (!candidate2)
|
|
362279
|
+
continue;
|
|
362280
|
+
const targetCount = targetBookmarkNameCounts.get(candidate2.referenceName) ?? 0;
|
|
362281
|
+
if (targetCount === 0) {
|
|
362282
|
+
unsafeReasons.push(`complex REF field ${index2} targets a missing bookmark`);
|
|
362283
|
+
continue;
|
|
362284
|
+
}
|
|
362285
|
+
if (targetCount !== 1) {
|
|
362286
|
+
unsafeReasons.push(`complex REF field ${index2} targets an ambiguous bookmark`);
|
|
362287
|
+
continue;
|
|
362288
|
+
}
|
|
362289
|
+
steps.push({
|
|
362290
|
+
kind: "complex-field",
|
|
362291
|
+
beforeXml: before.xml,
|
|
362292
|
+
afterXml: after.xml,
|
|
362293
|
+
beforeFragmentXml: candidate2.resultXml,
|
|
362294
|
+
afterFragmentXml: candidate2.fieldXml,
|
|
362295
|
+
beforeNamespaceBindings: { ...before.range.namespaceBindings },
|
|
362296
|
+
afterNamespaceBindings: { ...after.range.namespaceBindings }
|
|
362297
|
+
});
|
|
362298
|
+
}
|
|
362299
|
+
return steps;
|
|
362300
|
+
}
|
|
362301
|
+
function addedComplexRefField(targetParagraph, expectedBaseParagraphXml) {
|
|
362302
|
+
const fields = collectWordElements(targetParagraph.xml, "fldChar", true, targetParagraph.range.namespaceBindings);
|
|
362303
|
+
for (let beginIndex = 0;beginIndex < fields.length; beginIndex += 1) {
|
|
362304
|
+
const begin = fields[beginIndex];
|
|
362305
|
+
if (readAttribute2(begin, "fldCharType") !== "begin")
|
|
362306
|
+
continue;
|
|
362307
|
+
const separate = fields.slice(beginIndex + 1).find((field) => readAttribute2(field, "fldCharType") === "separate");
|
|
362308
|
+
const end = separate && fields.find((field) => field.range.start > separate.range.start && readAttribute2(field, "fldCharType") === "end");
|
|
362309
|
+
if (!separate || !end)
|
|
362310
|
+
continue;
|
|
362311
|
+
const runs = collectWordElements(targetParagraph.xml, "r", false, targetParagraph.range.namespaceBindings);
|
|
362312
|
+
const beginRun = runs.find((run) => run.range.start <= begin.range.start && run.range.end >= begin.range.end);
|
|
362313
|
+
const separateRun = runs.find((run) => run.range.start <= separate.range.start && run.range.end >= separate.range.end);
|
|
362314
|
+
const endRun = runs.find((run) => run.range.start <= end.range.start && run.range.end >= end.range.end);
|
|
362315
|
+
if (!beginRun || !separateRun || !endRun)
|
|
362316
|
+
continue;
|
|
362317
|
+
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("");
|
|
362318
|
+
const parsed = parseRefInstruction(instruction);
|
|
362319
|
+
if (!parsed)
|
|
362320
|
+
continue;
|
|
362321
|
+
const fieldXml = targetParagraph.xml.slice(beginRun.range.start, endRun.range.end);
|
|
362322
|
+
const resultXml = targetParagraph.xml.slice(separateRun.range.end, endRun.range.start);
|
|
362323
|
+
const fieldChars = fields.filter((field) => field.range.start >= begin.range.start && field.range.end <= end.range.end);
|
|
362324
|
+
if (fieldChars.length !== 3 || fieldChars.map((field) => readAttribute2(field, "fldCharType")).join(",") !== "begin,separate,end")
|
|
362325
|
+
continue;
|
|
362326
|
+
if (!resultXml || replaceUnique(targetParagraph.xml, fieldXml, resultXml) !== expectedBaseParagraphXml)
|
|
362327
|
+
continue;
|
|
362328
|
+
return { fieldXml, resultXml, referenceName: parsed.name };
|
|
362329
|
+
}
|
|
362330
|
+
return null;
|
|
362331
|
+
}
|
|
361495
362332
|
function bookmarkRangesArePaired(xml) {
|
|
361496
362333
|
const startsById = new Map;
|
|
361497
362334
|
for (const element of collectWordElements(xml, "bookmarkStart", true)) {
|
|
@@ -361520,8 +362357,10 @@ function collectEmptyElements(xml, localName2) {
|
|
|
361520
362357
|
function collectElements(xml, localName2) {
|
|
361521
362358
|
return collectWordElements(xml, localName2).map((element) => element.xml);
|
|
361522
362359
|
}
|
|
361523
|
-
function collectWordElements(xml, localName2, selfClosingOnly = false) {
|
|
361524
|
-
const parsed = collectXmlElementRanges(xml, {
|
|
362360
|
+
function collectWordElements(xml, localName2, selfClosingOnly = false, additionalNamespaces = {}) {
|
|
362361
|
+
const parsed = collectXmlElementRanges(xml, {
|
|
362362
|
+
additionalNamespaces: { w: WORDPROCESSINGML_NS6, ...additionalNamespaces }
|
|
362363
|
+
});
|
|
361525
362364
|
if (parsed.errors.length > 0)
|
|
361526
362365
|
return [];
|
|
361527
362366
|
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 +362515,11 @@ class V2DiffAdapter {
|
|
|
361676
362515
|
try {
|
|
361677
362516
|
const engine = createV2CompareEngine(this.context);
|
|
361678
362517
|
const base3 = captureCompareSnapshotSync(this.context);
|
|
361679
|
-
const
|
|
362518
|
+
const baseMainDocument = projectDiffMainDocumentSource(this.context);
|
|
362519
|
+
const targetMainDocument = targetPayload.mainDocument ?? EMPTY_MAIN_DOCUMENT_SOURCE;
|
|
362520
|
+
const rawAnalysis = engine.analyzeSnapshots(base3, targetPayload.compareSnapshot);
|
|
362521
|
+
const comparisonTarget = paragraphIdentityOnlyComparisonTarget(base3, targetPayload.compareSnapshot, baseMainDocument, targetMainDocument, rawAnalysis.result);
|
|
362522
|
+
const analysis = comparisonTarget ? engine.analyzeSnapshots(base3, comparisonTarget) : rawAnalysis;
|
|
361680
362523
|
if (!analysis.plan) {
|
|
361681
362524
|
throw diffValidationError("INVALID_INPUT", "diff.compare: compare engine did not return a semantic analysis plan.");
|
|
361682
362525
|
}
|
|
@@ -361693,8 +362536,6 @@ class V2DiffAdapter {
|
|
|
361693
362536
|
const baseNumbering = projectDiffNumberingSource(this.context);
|
|
361694
362537
|
const targetNumbering = targetPayload.numbering ?? { xml: null };
|
|
361695
362538
|
const numberingPlan = buildNumberingApplyPlan(baseNumbering, targetNumbering);
|
|
361696
|
-
const baseMainDocument = projectDiffMainDocumentSource(this.context);
|
|
361697
|
-
const targetMainDocument = targetPayload.mainDocument ?? EMPTY_MAIN_DOCUMENT_SOURCE;
|
|
361698
362539
|
const sectionsReferencesPlan = buildSectionsReferencesReplayPlan(baseMainDocument, targetMainDocument);
|
|
361699
362540
|
const adapterApplySupportedFamilies = new Set;
|
|
361700
362541
|
if (sectionsReferencesPlan.unsafeReasons.length === 0) {
|
|
@@ -361967,8 +362808,9 @@ class V2DiffAdapter {
|
|
|
361967
362808
|
unsupportedReason: "section-reference-replay-unsafe"
|
|
361968
362809
|
});
|
|
361969
362810
|
}
|
|
361970
|
-
const
|
|
361971
|
-
|
|
362811
|
+
const usesLocalizedMainDocumentReplay = sectionsReferencesChanged && (sectionsReferencesPlan.sectionSteps.length > 0 || sectionsReferencesPlan.referenceSteps.length > 0);
|
|
362812
|
+
const localizedBodyOperations = usesLocalizedMainDocumentReplay ? buildLocalizedBodyOperations(payload.base.body, payload.target.body, sectionsReferencesPlan.sectionSteps, sectionsReferencesPlan.referenceSteps, { base: payload.base.definitions, target: payload.target.definitions }, canonicalBodyOperations) : [];
|
|
362813
|
+
if (usesLocalizedMainDocumentReplay) {
|
|
361972
362814
|
setRuntimeBodyOperationCounts(operationCounts, payload.applyPlan, localizedBodyOperations);
|
|
361973
362815
|
}
|
|
361974
362816
|
const localizedMainDocumentCovered = !sectionsReferencesPlan.hasUnownedMainDocumentChanges || localizedMainDocumentChangesAreCovered({
|
|
@@ -362014,19 +362856,23 @@ class V2DiffAdapter {
|
|
|
362014
362856
|
}
|
|
362015
362857
|
}
|
|
362016
362858
|
const mainDocumentPlan = tablesChanged && !reviewMarkup ? buildMainDocumentApplyPlan(liveBaseMainDocument, payloadMainDocument.target) : { steps: [], unsafeReasons: [] };
|
|
362017
|
-
const trackedTableBodyOperations = !tablesChanged || !reviewMarkup ? payload.applyPlan.bodyOperations :
|
|
362859
|
+
const trackedTableBodyOperations = !tablesChanged || !reviewMarkup ? payload.applyPlan.bodyOperations : usesLocalizedMainDocumentReplay ? localizedBodyOperations : mergeCanonicalRevisionReplay(computeCompareBodyOperations(payload.base.body, payload.target.body, {
|
|
362018
362860
|
base: payload.base.definitions,
|
|
362019
362861
|
target: payload.target.definitions
|
|
362020
362862
|
}), canonicalBodyOperations);
|
|
362021
362863
|
const trackedTablePropertyPlan = tablesChanged && reviewMarkup ? buildTrackedTablePropertyReplayPlan(liveBaseMainDocument, payloadMainDocument.target) : null;
|
|
362022
|
-
let
|
|
362023
|
-
let trackedTablePlan = tablesChanged && reviewMarkup && !trackedTableBlockPlan && !trackedTablePropertyPlan ? buildTrackedTableRowReplayPlan({
|
|
362864
|
+
let trackedTablePlan = tablesChanged && reviewMarkup && !trackedTablePropertyPlan ? buildTrackedTableRowReplayPlan({
|
|
362024
362865
|
base: liveBaseMainDocument,
|
|
362025
362866
|
target: payloadMainDocument.target,
|
|
362867
|
+
baseBody: payload.base.body,
|
|
362026
362868
|
targetBody: payload.target.body,
|
|
362027
362869
|
bodyOperations: trackedTableBodyOperations
|
|
362028
|
-
}) : { steps: [], bodyOperations:
|
|
362029
|
-
|
|
362870
|
+
}) : { steps: [], bodyOperations: trackedTablePropertyPlan ? trackedTableBodyOperations : payload.applyPlan.bodyOperations, unsafeReasons: [] };
|
|
362871
|
+
let trackedTableBlockPlan = tablesChanged && reviewMarkup && !trackedTablePropertyPlan && !trackedTablePlan.refuseBlockFallback && (trackedTablePlan.unsafeReasons.length > 0 || trackedTablePlan.steps.length === 0) ? buildTrackedTableBlockReplayPlan({ base: liveBaseMainDocument, target: payloadMainDocument.target, bodyOperations: trackedTableBodyOperations }) : null;
|
|
362872
|
+
if (trackedTableBlockPlan) {
|
|
362873
|
+
trackedTablePlan = { steps: [], bodyOperations: trackedTableBlockPlan.bodyOperations, unsafeReasons: [] };
|
|
362874
|
+
}
|
|
362875
|
+
if (trackedTablePlan.unsafeReasons.length > 0 && !trackedTablePlan.refuseBlockFallback) {
|
|
362030
362876
|
const replacement = buildTrackedTableBlockReplayPlan({
|
|
362031
362877
|
base: liveBaseMainDocument,
|
|
362032
362878
|
target: payloadMainDocument.target,
|
|
@@ -362081,7 +362927,7 @@ class V2DiffAdapter {
|
|
|
362081
362927
|
if (mainDocumentPlan.unsafeReasons.length > 0) {
|
|
362082
362928
|
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
362929
|
}
|
|
362084
|
-
const runtimeApplyPlan =
|
|
362930
|
+
const runtimeApplyPlan = usesLocalizedMainDocumentReplay ? {
|
|
362085
362931
|
...runtimeApplyPlanBase,
|
|
362086
362932
|
applyPlan: {
|
|
362087
362933
|
...runtimeApplyPlanBase.applyPlan,
|
|
@@ -362113,6 +362959,13 @@ class V2DiffAdapter {
|
|
|
362113
362959
|
handledFamilies.add("body");
|
|
362114
362960
|
}
|
|
362115
362961
|
}
|
|
362962
|
+
const rowControlsCovered = trackedTablePlan.steps.length > 0 && rowReplayCoversContentControls(payload.base.annotations, payload.target.annotations, trackedTablePlan.steps, liveBaseMainDocument.xml, payloadMainDocument.target.xml);
|
|
362963
|
+
if (trackedTablePlan.steps.length > 0 && !rowControlsCovered) {
|
|
362964
|
+
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" });
|
|
362965
|
+
}
|
|
362966
|
+
if (changedPolicies.some((policy) => policy.family === "content-controls") && rowControlsCovered) {
|
|
362967
|
+
handledFamilies.add("content-controls");
|
|
362968
|
+
}
|
|
362116
362969
|
if (mainRevisionChangesHandled)
|
|
362117
362970
|
handledFamilies.add("tracked-changes");
|
|
362118
362971
|
if (mainDocumentPlan.steps.length > 0)
|
|
@@ -362289,6 +363142,23 @@ function buildCompareApplyEligibility(context, payload, plans) {
|
|
|
362289
363142
|
direct.add("fields-references");
|
|
362290
363143
|
tracked.add("fields-references");
|
|
362291
363144
|
}
|
|
363145
|
+
const usesLocalizedMainDocumentReplay = plans.sectionsReferencesPlan.sectionSteps.length > 0 || plans.sectionsReferencesPlan.referenceSteps.length > 0;
|
|
363146
|
+
if (usesLocalizedMainDocumentReplay) {
|
|
363147
|
+
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);
|
|
363148
|
+
const localizedMainDocumentCovered = !plans.sectionsReferencesPlan.hasUnownedMainDocumentChanges || localizedMainDocumentChangesAreCovered({
|
|
363149
|
+
base: payload.mainDocument?.base ?? EMPTY_MAIN_DOCUMENT_SOURCE,
|
|
363150
|
+
target: payload.mainDocument?.target ?? EMPTY_MAIN_DOCUMENT_SOURCE,
|
|
363151
|
+
baseBody: payload.base.body,
|
|
363152
|
+
targetBody: payload.target.body,
|
|
363153
|
+
sectionSteps: plans.sectionsReferencesPlan.sectionSteps,
|
|
363154
|
+
referenceSteps: plans.sectionsReferencesPlan.referenceSteps,
|
|
363155
|
+
bodyOperations: localizedBodyOperations
|
|
363156
|
+
});
|
|
363157
|
+
if (localizedMainDocumentCovered) {
|
|
363158
|
+
direct.add("body");
|
|
363159
|
+
tracked.add("body");
|
|
363160
|
+
}
|
|
363161
|
+
}
|
|
362292
363162
|
}
|
|
362293
363163
|
const slotsChanged = plans.physicalPlan.hasReferenceIdChanges || payload.familyPolicy.some((policy) => policy.family === "header-footer-slots" && policy.applyRequired);
|
|
362294
363164
|
const slotPlan = slotsChanged ? buildHeaderFooterSlotPackageRewrite(context, payload.base.slots ?? [], payload.target.slots ?? [], plans.physicalPlan.refByPart) : { rewrites: [], unsafeReasons: [], operationCount: 0 };
|
|
@@ -362350,13 +363220,19 @@ function buildCompareApplyEligibility(context, payload, plans) {
|
|
|
362350
363220
|
const trackedTablePlan = buildTrackedTableRowReplayPlan({
|
|
362351
363221
|
base: mainDocument.base,
|
|
362352
363222
|
target: mainDocument.target,
|
|
363223
|
+
baseBody: payload.base.body,
|
|
362353
363224
|
targetBody: payload.target.body,
|
|
362354
|
-
bodyOperations: payload.applyPlan.bodyOperations
|
|
363225
|
+
bodyOperations: payload.applyPlan.bodyOperations.length > 0 ? payload.applyPlan.bodyOperations : computeCompareBodyOperations(payload.base.body, payload.target.body, {
|
|
363226
|
+
base: payload.base.definitions,
|
|
363227
|
+
target: payload.target.definitions
|
|
363228
|
+
})
|
|
362355
363229
|
});
|
|
362356
363230
|
if (trackedTablePlan.unsafeReasons.length === 0 && trackedTablePlan.steps.length > 0) {
|
|
362357
363231
|
tracked.add("tables");
|
|
362358
363232
|
if (bodyDeferredToTableReplay)
|
|
362359
363233
|
tracked.add("body");
|
|
363234
|
+
if (rowReplayCoversContentControls(payload.base.annotations, payload.target.annotations, trackedTablePlan.steps, mainDocument.base.xml, mainDocument.target.xml))
|
|
363235
|
+
tracked.add("content-controls");
|
|
362360
363236
|
}
|
|
362361
363237
|
}
|
|
362362
363238
|
const packageGraphCoveredByComments = direct.has("comments") && packageGraphKeysNotCoveredByComments(context, payload.base, payload.target, plans.commentPlan.steps).length === 0;
|
|
@@ -362414,7 +363290,16 @@ function buildCompareApplyEligibility(context, payload, plans) {
|
|
|
362414
363290
|
});
|
|
362415
363291
|
}
|
|
362416
363292
|
for (const mode of ["direct", "tracked"]) {
|
|
362417
|
-
|
|
363293
|
+
let runtimePlan = buildHeaderFooterRuntimeApplyPlan(payload, slotPlan, plans.physicalPlan, mode === "tracked");
|
|
363294
|
+
if (plans.sectionsReferencesPlan.unsafeReasons.length === 0 && (plans.sectionsReferencesPlan.sectionSteps.length > 0 || plans.sectionsReferencesPlan.referenceSteps.length > 0)) {
|
|
363295
|
+
runtimePlan = {
|
|
363296
|
+
...runtimePlan,
|
|
363297
|
+
applyPlan: {
|
|
363298
|
+
...runtimePlan.applyPlan,
|
|
363299
|
+
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)
|
|
363300
|
+
}
|
|
363301
|
+
};
|
|
363302
|
+
}
|
|
362418
363303
|
const unsupportedFamilies = findStructurallyUnsupportedOperationFamilies(context, runtimePlan, payload.mainDocument?.base ?? EMPTY_MAIN_DOCUMENT_SOURCE, mode === "tracked", plans.sectionsReferencesPlan.referenceSteps);
|
|
362419
363304
|
if (unsupportedFamilies.length > 0) {
|
|
362420
363305
|
hazards[mode].push({
|
|
@@ -362958,7 +363843,8 @@ function buildLocalizedBodyOperations(base3, target, sectionSteps, referenceStep
|
|
|
362958
363843
|
throwLocalizedBodyCorrespondenceError(sectionSteps, referenceSteps);
|
|
362959
363844
|
const neutralTarget = target.map((entry) => {
|
|
362960
363845
|
const baseEntry = correspondence.baseByTargetId.get(entry.blockId);
|
|
362961
|
-
const
|
|
363846
|
+
const reversedRunXml = baseEntry?.runXml && entry.runXml ? referenceSteps.reduce((xml, step3) => reverseReferenceAttribute(xml, step3), entry.runXml) : entry.runXml;
|
|
363847
|
+
const neutralRunXml = baseEntry?.runXml && reversedRunXml && stripReplayNamespaceDeclarations(reversedRunXml) === stripReplayNamespaceDeclarations(baseEntry.runXml) ? baseEntry.runXml : reversedRunXml;
|
|
362962
363848
|
const neutralParagraphPropertiesXml = baseEntry?.paragraphPropertiesXml !== undefined && entry.paragraphPropertiesXml !== undefined ? sectionSteps.reduce((xml, step3) => reverseSectionProperties(xml, baseEntry.paragraphPropertiesXml, step3), entry.paragraphPropertiesXml) : entry.paragraphPropertiesXml;
|
|
362963
363849
|
if (neutralRunXml === entry.runXml && neutralParagraphPropertiesXml === entry.paragraphPropertiesXml)
|
|
362964
363850
|
return entry;
|
|
@@ -363025,6 +363911,17 @@ function reverseSectionProperties(targetParagraphPropertiesXml, baseParagraphPro
|
|
|
363025
363911
|
return targetParagraphPropertiesXml.slice(0, targetStart) + step3.beforeXml + targetParagraphPropertiesXml.slice(targetStart + step3.afterXml.length);
|
|
363026
363912
|
}
|
|
363027
363913
|
function reverseReferenceAttribute(xml, step3) {
|
|
363914
|
+
if (step3.kind === "bookmark-range" || step3.kind === "complex-field") {
|
|
363915
|
+
if (step3.beforeFragmentXml === undefined || step3.afterFragmentXml === undefined)
|
|
363916
|
+
return xml;
|
|
363917
|
+
const normalizedXml = stripReplayNamespaceDeclarations(xml);
|
|
363918
|
+
const after = stripReplayNamespaceDeclarations(step3.afterFragmentXml);
|
|
363919
|
+
const before = stripReplayNamespaceDeclarations(step3.beforeFragmentXml);
|
|
363920
|
+
const start = normalizedXml.indexOf(after);
|
|
363921
|
+
if (start < 0 || normalizedXml.indexOf(after, start + after.length) >= 0)
|
|
363922
|
+
return xml;
|
|
363923
|
+
return normalizedXml.slice(0, start) + before + normalizedXml.slice(start + after.length);
|
|
363924
|
+
}
|
|
363028
363925
|
const elementName = step3.kind === "bookmark-start" ? "bookmarkStart" : "fldSimple";
|
|
363029
363926
|
const localName2 = step3.kind === "bookmark-start" ? "name" : "instr";
|
|
363030
363927
|
const afterValue = readReplayAttribute(step3.afterXml, localName2, step3.afterNamespaceBindings);
|
|
@@ -363094,7 +363991,9 @@ function validateFullDiffCanonicalArtifacts(engine, payload) {
|
|
|
363094
363991
|
const problems = [];
|
|
363095
363992
|
let canonicalAnalysis;
|
|
363096
363993
|
try {
|
|
363097
|
-
|
|
363994
|
+
const rawAnalysis = engine.analyzeSnapshots(payload.base, payload.target);
|
|
363995
|
+
const comparisonTarget = paragraphIdentityOnlyComparisonTarget(payload.base, payload.target, payload.mainDocument?.base ?? EMPTY_MAIN_DOCUMENT_SOURCE, payload.mainDocument?.target ?? EMPTY_MAIN_DOCUMENT_SOURCE, rawAnalysis.result);
|
|
363996
|
+
canonicalAnalysis = comparisonTarget ? engine.analyzeSnapshots(payload.base, comparisonTarget) : rawAnalysis;
|
|
363098
363997
|
} catch (error48) {
|
|
363099
363998
|
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
363100
363999
|
return { problems: [`payload.base/target could not be re-analyzed (${message})`] };
|
|
@@ -363114,6 +364013,25 @@ function validateFullDiffCanonicalArtifacts(engine, payload) {
|
|
|
363114
364013
|
}
|
|
363115
364014
|
return { problems };
|
|
363116
364015
|
}
|
|
364016
|
+
function paragraphIdentityOnlyComparisonTarget(base3, target, baseDocument, targetDocument, rawAnalysis) {
|
|
364017
|
+
if (!baseDocument.xml || !targetDocument.xml || baseDocument.xml === targetDocument.xml)
|
|
364018
|
+
return null;
|
|
364019
|
+
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+\/>$/, "/>"));
|
|
364020
|
+
if (withoutParagraphIds(baseDocument.xml) !== withoutParagraphIds(targetDocument.xml))
|
|
364021
|
+
return null;
|
|
364022
|
+
if (validateMainDocumentSourceAgainstSnapshotPart(baseDocument, base3, "base").length > 0 || validateMainDocumentSourceAgainstSnapshotPart(targetDocument, target, "target").length > 0)
|
|
364023
|
+
return null;
|
|
364024
|
+
const levels = (source) => new Map(Object.entries(source.paragraphStyleOutlineLevels ?? {}));
|
|
364025
|
+
if (validateMainDocumentSourceAgainstBodySnapshot(baseDocument, base3.body, { paragraphStyleOutlineLevels: levels(baseDocument) }).length > 0 || validateMainDocumentSourceAgainstBodySnapshot(targetDocument, target.body, { paragraphStyleOutlineLevels: levels(targetDocument) }).length > 0)
|
|
364026
|
+
return null;
|
|
364027
|
+
const otherParts = (snapshot2) => snapshot2.sourceInventory?.parts.filter((part) => part.partUri !== DOCUMENT_PART_URI6);
|
|
364028
|
+
if (!base3.sourceInventory || !target.sourceInventory || !artifactEquals(otherParts(base3), otherParts(target)))
|
|
364029
|
+
return null;
|
|
364030
|
+
const changedFamilies3 = rawAnalysis.families.filter((family) => family.state === "changed-supported");
|
|
364031
|
+
if (!changedFamilies3.some((family) => family.family === "tables") || changedFamilies3.some((family) => family.family !== "body" && family.family !== "tables"))
|
|
364032
|
+
return null;
|
|
364033
|
+
return { ...base3, identity: target.identity };
|
|
364034
|
+
}
|
|
363117
364035
|
function artifactEquals(left, right) {
|
|
363118
364036
|
return JSON.stringify(normalizeArtifactForCompare(left)) === JSON.stringify(normalizeArtifactForCompare(right));
|
|
363119
364037
|
}
|
|
@@ -363293,8 +364211,14 @@ function containsStructuralParagraphTag(xml, blockKind) {
|
|
|
363293
364211
|
return errors4.length === 0 ? found : null;
|
|
363294
364212
|
}
|
|
363295
364213
|
function findUniqueReplayCarrier(xml, step3) {
|
|
364214
|
+
if (step3.kind === "bookmark-range" || step3.kind === "complex-field") {
|
|
364215
|
+
const fragment3 = step3.afterFragmentXml;
|
|
364216
|
+
if (!fragment3)
|
|
364217
|
+
return null;
|
|
364218
|
+
const start = xml.indexOf(fragment3);
|
|
364219
|
+
return start >= 0 && xml.indexOf(fragment3, start + fragment3.length) < 0 ? { start, end: start + fragment3.length } : null;
|
|
364220
|
+
}
|
|
363296
364221
|
const expectedName = step3.kind === "bookmark-start" ? "bookmarkStart" : "fldSimple";
|
|
363297
|
-
const localName2 = step3.kind === "bookmark-start" ? "name" : "instr";
|
|
363298
364222
|
const parsed = collectXmlElementRanges(xml, {
|
|
363299
364223
|
fragment: true,
|
|
363300
364224
|
additionalNamespaces: { ...step3.beforeNamespaceBindings }
|
|
@@ -377122,13 +378046,7 @@ function normalizeParagraphBlock(value2, path7, version2, allowHeading) {
|
|
|
377122
378046
|
return normalized;
|
|
377123
378047
|
inlines.push(normalized);
|
|
377124
378048
|
}
|
|
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
|
-
});
|
|
378049
|
+
const projected = inlines.flatMap(projectInlineText);
|
|
377132
378050
|
if (projected.length !== runs.length || projected.some((inline, runIndex) => inline.text !== runs[runIndex]?.text || JSON.stringify(inline.marks ?? {}) !== JSON.stringify(runs[runIndex]?.marks ?? {}))) {
|
|
377133
378051
|
return structureFailure("Paragraph runs must equal the text projection of inlines.", path7);
|
|
377134
378052
|
}
|
|
@@ -377153,6 +378071,12 @@ function normalizeParagraphBlock(value2, path7, version2, allowHeading) {
|
|
|
377153
378071
|
const paragraphProps = normalizeParagraphProperties(value2.paragraphProps, [...path7, "paragraphProps"]);
|
|
377154
378072
|
if (isPlanFailure(paragraphProps))
|
|
377155
378073
|
return paragraphProps;
|
|
378074
|
+
const blockSdts = normalizeBlockSdts(value2.blockSdts, [...path7, "blockSdts"]);
|
|
378075
|
+
if (isPlanFailure(blockSdts))
|
|
378076
|
+
return blockSdts;
|
|
378077
|
+
if (blockSdts && (version2 !== SUPERDOC_V22_CLIPBOARD_FRAGMENT_VERSION || value2.complete !== true)) {
|
|
378078
|
+
return structureFailure("Complete block content controls require a v2.2 paragraph.", [...path7, "blockSdts"]);
|
|
378079
|
+
}
|
|
377156
378080
|
const sourcePath = normalizeSourcePath(value2.sourcePath, [...path7, "sourcePath"]);
|
|
377157
378081
|
if (isPlanFailure(sourcePath))
|
|
377158
378082
|
return sourcePath;
|
|
@@ -377167,16 +378091,83 @@ function normalizeParagraphBlock(value2, path7, version2, allowHeading) {
|
|
|
377167
378091
|
...typeof continuation === "number" ? { listItemContinuationLevel: continuation } : {},
|
|
377168
378092
|
...typeof value2.pPrXml === "string" && value2.pPrXml.length > 0 ? { pPrXml: value2.pPrXml } : {},
|
|
377169
378093
|
...value2.complete === true ? { complete: true } : {},
|
|
378094
|
+
...blockSdts ? { blockSdts } : {},
|
|
377170
378095
|
...sourcePath ? { sourcePath } : {}
|
|
377171
378096
|
};
|
|
377172
378097
|
return isHeading ? { kind: "heading", level: value2.level, ...common } : { kind: "paragraph", ...common };
|
|
377173
378098
|
}
|
|
377174
|
-
function
|
|
378099
|
+
function normalizeBlockSdts(value2, path7) {
|
|
378100
|
+
if (value2 === undefined)
|
|
378101
|
+
return;
|
|
378102
|
+
if (!Array.isArray(value2) || value2.length === 0 || value2.length > 16) {
|
|
378103
|
+
return structureFailure("Block content-control ancestry must contain 1 to 16 wrappers.", path7);
|
|
378104
|
+
}
|
|
378105
|
+
const ids = new Set;
|
|
378106
|
+
const result = [];
|
|
378107
|
+
for (const [index2, wrapper] of value2.entries()) {
|
|
378108
|
+
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))) {
|
|
378109
|
+
return structureFailure("Invalid block content-control wrapper.", [...path7, index2]);
|
|
378110
|
+
}
|
|
378111
|
+
ids.add(wrapper.sourceId);
|
|
378112
|
+
result.push({
|
|
378113
|
+
sourceId: wrapper.sourceId,
|
|
378114
|
+
controlType: wrapper.controlType,
|
|
378115
|
+
...wrapper.tag !== undefined ? { tag: wrapper.tag } : {},
|
|
378116
|
+
...wrapper.alias !== undefined ? { alias: wrapper.alias } : {},
|
|
378117
|
+
...wrapper.lockMode !== undefined ? { lockMode: wrapper.lockMode } : {},
|
|
378118
|
+
...wrapper.multiline !== undefined ? { multiline: wrapper.multiline } : {}
|
|
378119
|
+
});
|
|
378120
|
+
}
|
|
378121
|
+
return result;
|
|
378122
|
+
}
|
|
378123
|
+
function validSdtMetadata(value2) {
|
|
378124
|
+
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");
|
|
378125
|
+
}
|
|
378126
|
+
function projectInlineText(inline) {
|
|
378127
|
+
if (inline.kind === "text")
|
|
378128
|
+
return [inline];
|
|
378129
|
+
if (inline.kind === "sdt" || inline.kind === "hyperlink")
|
|
378130
|
+
return inline.inlines.flatMap(projectInlineText);
|
|
378131
|
+
return [];
|
|
378132
|
+
}
|
|
378133
|
+
function normalizeInline(value2, path7, allowHyperlink, depth = 0) {
|
|
377175
378134
|
if (!isRecord15(value2))
|
|
377176
378135
|
return structureFailure("Paste inlines must be objects.", path7);
|
|
378136
|
+
if (depth > 32)
|
|
378137
|
+
return structureFailure("Paste inline nesting exceeds the allowed depth.", path7);
|
|
377177
378138
|
const sourcePath = normalizeSourcePath(value2.sourcePath, [...path7, "sourcePath"]);
|
|
377178
378139
|
if (isPlanFailure(sourcePath))
|
|
377179
378140
|
return sourcePath;
|
|
378141
|
+
if (value2.kind === "sdt") {
|
|
378142
|
+
if (value2.controlType !== "text" && value2.controlType !== "richText" || !validSdtMetadata(value2) || !Array.isArray(value2.inlines) || value2.inlines.length === 0) {
|
|
378143
|
+
return structureFailure("Content controls require a supported type and nonempty inlines.", path7);
|
|
378144
|
+
}
|
|
378145
|
+
for (const key2 of ["tag", "alias"]) {
|
|
378146
|
+
if (value2[key2] !== undefined && (typeof value2[key2] !== "string" || value2[key2].length > 255 || !isXml10SafeAttributeValue(value2[key2]))) {
|
|
378147
|
+
return structureFailure(`Content control ${key2} must be XML-safe and at most 255 characters.`, [...path7, key2]);
|
|
378148
|
+
}
|
|
378149
|
+
}
|
|
378150
|
+
const inlines = [];
|
|
378151
|
+
for (const [index2, child] of value2.inlines.entries()) {
|
|
378152
|
+
const normalized = normalizeInline(child, [...path7, "inlines", index2], false, depth + 1);
|
|
378153
|
+
if (isPlanFailure(normalized))
|
|
378154
|
+
return normalized;
|
|
378155
|
+
if (normalized.kind !== "text" && normalized.kind !== "lineBreak" && normalized.kind !== "sdt") {
|
|
378156
|
+
return structureFailure("Unsupported content inside a content control.", [...path7, "inlines", index2]);
|
|
378157
|
+
}
|
|
378158
|
+
inlines.push(normalized);
|
|
378159
|
+
}
|
|
378160
|
+
return {
|
|
378161
|
+
kind: "sdt",
|
|
378162
|
+
controlType: value2.controlType,
|
|
378163
|
+
inlines,
|
|
378164
|
+
...typeof value2.tag === "string" ? { tag: value2.tag } : {},
|
|
378165
|
+
...typeof value2.alias === "string" ? { alias: value2.alias } : {},
|
|
378166
|
+
...value2.lockMode !== undefined ? { lockMode: value2.lockMode } : {},
|
|
378167
|
+
...value2.multiline !== undefined ? { multiline: value2.multiline } : {},
|
|
378168
|
+
...sourcePath ? { sourcePath } : {}
|
|
378169
|
+
};
|
|
378170
|
+
}
|
|
377180
378171
|
if (value2.kind === "text" && typeof value2.text === "string" && isXml10SafeString(value2.text)) {
|
|
377181
378172
|
if (value2.marks !== undefined && (!isRecord15(value2.marks) || Array.isArray(value2.marks))) {
|
|
377182
378173
|
return structureFailure("Paste run marks must be an object.", [...path7, "marks"]);
|
|
@@ -377234,8 +378225,8 @@ function normalizeInline(value2, path7, allowHyperlink) {
|
|
|
377234
378225
|
const normalized = normalizeInline(child, [...path7, "inlines", childIndex], false);
|
|
377235
378226
|
if (isPlanFailure(normalized))
|
|
377236
378227
|
return normalized;
|
|
377237
|
-
if (normalized.kind === "hyperlink")
|
|
377238
|
-
return structureFailure("Nested hyperlinks are not supported.", [...path7, "inlines", childIndex]);
|
|
378228
|
+
if (normalized.kind === "hyperlink" || normalized.kind === "sdt")
|
|
378229
|
+
return structureFailure("Nested hyperlinks and content controls are not supported.", [...path7, "inlines", childIndex]);
|
|
377239
378230
|
if (normalized.kind === "footnoteRef" || normalized.kind === "endnoteRef") {
|
|
377240
378231
|
return structureFailure("Note references cannot be nested inside hyperlinks.", [...path7, "inlines", childIndex]);
|
|
377241
378232
|
}
|
|
@@ -377680,6 +378671,9 @@ function normalizeTableBlock(block, index2, version2) {
|
|
|
377680
378671
|
const paragraph4 = normalizeParagraphBlock(cellBlock, ["blocks", index2, "rows", rowIndex, "cells", cellIndex, "blocks", cellBlockIndex], version2, false);
|
|
377681
378672
|
if (isPlanFailure(paragraph4))
|
|
377682
378673
|
return paragraph4;
|
|
378674
|
+
if (paragraph4.blockSdts?.length) {
|
|
378675
|
+
return structureFailure("Block content controls inside table cells are not supported.", ["blocks", index2, "rows", rowIndex, "cells", cellIndex, "blocks", cellBlockIndex, "blockSdts"]);
|
|
378676
|
+
}
|
|
377683
378677
|
cellBlocks.push(paragraph4);
|
|
377684
378678
|
}
|
|
377685
378679
|
cells.push({
|
|
@@ -378437,7 +379431,8 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378437
379431
|
code: "PRECONDITION_FAILED",
|
|
378438
379432
|
message: "story part bytes are unavailable."
|
|
378439
379433
|
};
|
|
378440
|
-
const boundaryMap = buildStructuralBoundaryMap(bytes
|
|
379434
|
+
const boundaryMap = buildStructuralBoundaryMap(bytes);
|
|
379435
|
+
const blockSdtWrappers = scanBlockSdtWrappers(SERIALIZE_TD.decode(bytes));
|
|
378441
379436
|
const hyperlinkDescriptorResolver = new SelectionHyperlinkDescriptorResolver(context, resolved.storyId);
|
|
378442
379437
|
let tableCatalog;
|
|
378443
379438
|
const notes = new SerializeNotes;
|
|
@@ -378500,6 +379495,7 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378500
379495
|
loadCatalog: loadCommentsCatalog
|
|
378501
379496
|
};
|
|
378502
379497
|
const tableCellPath = boundaryMap.byBlockId(entry.blockId)?.tableCellPath ?? [];
|
|
379498
|
+
const blockSdtPath = boundaryMap.byBlockId(entry.blockId)?.blockSdtPath ?? [];
|
|
378503
379499
|
const properties = readParagraphProperties(paragraphXml);
|
|
378504
379500
|
const fullyCovered = from === 0 && to === map3.visibleLength && (options?.wholeParagraphs === true || startEntry.ordinal !== endEntry.ordinal || properties.styleRef !== undefined || properties.numbering !== undefined || hasParagraphProperties(paragraphXml));
|
|
378505
379501
|
const styleModel = copyStyleModel ?? (copyStyleModel = compileCopyStyleModel(context));
|
|
@@ -378508,7 +379504,23 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378508
379504
|
const semanticHeadingLevel = semanticStyleRole?.startsWith("heading-") ? Number(semanticStyleRole.slice("heading-".length)) : null;
|
|
378509
379505
|
const parts = [];
|
|
378510
379506
|
let objectOrdinal = 0;
|
|
378511
|
-
for (const piece of map3.
|
|
379507
|
+
for (const piece of copySelectionPieces(map3.pieces)) {
|
|
379508
|
+
if (piece.kind === "container" && piece.containerKind === "sdt") {
|
|
379509
|
+
const sdt = from <= piece.visibleStart && piece.visibleEnd <= to ? serializeSdtPart(piece, from, to, notes, styleContext, review) : null;
|
|
379510
|
+
if (sdt) {
|
|
379511
|
+
parts.push(sdt);
|
|
379512
|
+
continue;
|
|
379513
|
+
}
|
|
379514
|
+
for (const leaf of copySelectionPieces(piece.children, false)) {
|
|
379515
|
+
if (leaf.visibleStart >= to || leaf.visibleEnd <= from)
|
|
379516
|
+
continue;
|
|
379517
|
+
notes.add("fields", "Content-control and field structure is not preserved by copy; visible text was kept.");
|
|
379518
|
+
const leafParts = [];
|
|
379519
|
+
walkPieces([leaf], from, to, leafParts, notes, styleContext, review);
|
|
379520
|
+
parts.push(...leafParts);
|
|
379521
|
+
}
|
|
379522
|
+
continue;
|
|
379523
|
+
}
|
|
378512
379524
|
if (isVisibleZeroWidthObjectPiece(piece)) {
|
|
378513
379525
|
const selected = fullyCovered || selectedObjectOrdinals?.has(objectOrdinal);
|
|
378514
379526
|
objectOrdinal += 1;
|
|
@@ -378588,8 +379600,18 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378588
379600
|
}
|
|
378589
379601
|
const pPrXml = fullyCovered ? materializeEffectivePPrXml(capturedPPrXml, properties.styleRef, copyParagraphPropertyModel ?? (copyParagraphPropertyModel = compileCopyParagraphPropertyXmlModel(context)), inTable ? "table" : "full", resolveRunMarks(extractParagraphMarkRPrXml(capturedPPrXml), styleContext), numbering != null) : null;
|
|
378590
379602
|
const listLevel = numbering ? Number.parseInt(numbering.ilvl, 10) : undefined;
|
|
379603
|
+
const blockSdts = blockSdtPath.map((ordinal) => {
|
|
379604
|
+
const wrapper = blockSdtWrappers.get(ordinal);
|
|
379605
|
+
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)))
|
|
379606
|
+
return null;
|
|
379607
|
+
return wrapper.properties;
|
|
379608
|
+
});
|
|
379609
|
+
if (blockSdtPath.length > 0 && blockSdts.some((wrapper) => wrapper === null)) {
|
|
379610
|
+
notes.add("block-sdt", "A partial or unsupported block content control was copied as visible text without its wrapper.");
|
|
379611
|
+
}
|
|
378591
379612
|
blocks.push({
|
|
378592
379613
|
blockId: entry.blockId,
|
|
379614
|
+
...blockSdts.length > 0 && blockSdts.every((wrapper) => wrapper !== null) ? { blockSdts } : {},
|
|
378593
379615
|
runs: parts.flatMap(serializedPartRuns),
|
|
378594
379616
|
...fullyCovered && properties.styleRef ? { styleRef: properties.styleRef } : {},
|
|
378595
379617
|
...fullyCovered && semanticStyleRole ? { semanticStyleRole } : {},
|
|
@@ -378639,14 +379661,16 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378639
379661
|
})), notes.diagnostics());
|
|
378640
379662
|
plan = buildPlan(fallbackFragment, "plain-text", notes.diagnostics(), true);
|
|
378641
379663
|
} else {
|
|
378642
|
-
const
|
|
379664
|
+
const hasPreservedControls = blocks.some((block) => !!block.blockSdts?.length || block.parts.some((part) => part.kind === "sdt"));
|
|
379665
|
+
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();
|
|
379666
|
+
const fragment3 = withPasteComments(buildFragment(grouped.map(fragmentBlockFor), legacyDiagnostics), commentsById);
|
|
378643
379667
|
items.push({
|
|
378644
379668
|
type: SUPERDOC_V2_CLIPBOARD_MIME,
|
|
378645
379669
|
kind: "string",
|
|
378646
379670
|
data: JSON.stringify(fragment3)
|
|
378647
379671
|
});
|
|
378648
379672
|
const assets = [...rich.assetsByPartUri.values()];
|
|
378649
|
-
const hasRichInlineStructure = blocks.some((block) => block.parts.some((part) => part.kind === "hyperlink" || part.kind === "image"));
|
|
379673
|
+
const hasRichInlineStructure = blocks.some((block) => !!block.blockSdts?.length || block.parts.some((part) => part.kind === "hyperlink" || part.kind === "image" || part.kind === "sdt"));
|
|
378650
379674
|
if (!rich.invalid && hasRichInlineStructure) {
|
|
378651
379675
|
const richBlocks = grouped.map(richFragmentBlockFor);
|
|
378652
379676
|
const wireFragment = withPasteComments({
|
|
@@ -378670,6 +379694,84 @@ function serializeSelectionRange(context, target, includeHtml, options) {
|
|
|
378670
379694
|
}
|
|
378671
379695
|
};
|
|
378672
379696
|
}
|
|
379697
|
+
function topLevelChildrenCoverXml(xml, children2) {
|
|
379698
|
+
let cursor = 0;
|
|
379699
|
+
for (const child of children2) {
|
|
379700
|
+
const start = xml.indexOf(child.xml, cursor);
|
|
379701
|
+
if (start < 0 || xml.slice(cursor, start).trim().length > 0)
|
|
379702
|
+
return false;
|
|
379703
|
+
cursor = start + child.xml.length;
|
|
379704
|
+
}
|
|
379705
|
+
return xml.slice(cursor).trim().length === 0;
|
|
379706
|
+
}
|
|
379707
|
+
function parseSupportedSdtProperties(xml) {
|
|
379708
|
+
const children2 = parseTopLevelChildren(xml);
|
|
379709
|
+
if (!topLevelChildrenCoverXml(xml, children2))
|
|
379710
|
+
return null;
|
|
379711
|
+
const properties = { controlType: "richText" };
|
|
379712
|
+
let seenControlType = false;
|
|
379713
|
+
for (const child of children2) {
|
|
379714
|
+
if (child.prefix !== "w")
|
|
379715
|
+
return null;
|
|
379716
|
+
if (child.localName === "id") {
|
|
379717
|
+
if (!/^<w:id\b[^>]*\/>$/.test(child.xml))
|
|
379718
|
+
return null;
|
|
379719
|
+
} else if (child.localName === "tag" || child.localName === "alias") {
|
|
379720
|
+
if (!/^<w:(?:tag|alias)\b[^>]*\/>$/.test(child.xml))
|
|
379721
|
+
return null;
|
|
379722
|
+
const value2 = readBareAttribute(child.xml, "w:val");
|
|
379723
|
+
if (value2 === null || value2.length > 255)
|
|
379724
|
+
return null;
|
|
379725
|
+
properties[child.localName] = value2;
|
|
379726
|
+
} else if (child.localName === "lock") {
|
|
379727
|
+
const match = /^<w:lock\s+w:val=(['"])(unlocked|sdtLocked|contentLocked|sdtContentLocked)\1\s*\/>$/.exec(child.xml);
|
|
379728
|
+
if (!match || properties.lockMode !== undefined)
|
|
379729
|
+
return null;
|
|
379730
|
+
properties.lockMode = match[2];
|
|
379731
|
+
} else if (child.localName === "text") {
|
|
379732
|
+
const match = /^<w:text(?:\s+w:multiLine=(['"])(1|0|true|false|on|off)\1)?\s*\/>$/.exec(child.xml);
|
|
379733
|
+
if (!match || seenControlType)
|
|
379734
|
+
return null;
|
|
379735
|
+
seenControlType = true;
|
|
379736
|
+
properties.controlType = "text";
|
|
379737
|
+
if (match[2] !== undefined)
|
|
379738
|
+
properties.multiline = match[2] === "1" || match[2] === "true" || match[2] === "on";
|
|
379739
|
+
} else if (child.localName === "richText") {
|
|
379740
|
+
if (!/^<w:richText\s*\/>$/.test(child.xml) || seenControlType)
|
|
379741
|
+
return null;
|
|
379742
|
+
seenControlType = true;
|
|
379743
|
+
} else {
|
|
379744
|
+
return null;
|
|
379745
|
+
}
|
|
379746
|
+
}
|
|
379747
|
+
return properties;
|
|
379748
|
+
}
|
|
379749
|
+
function scanBlockSdtWrappers(xml) {
|
|
379750
|
+
const wrappers = new Map;
|
|
379751
|
+
const stack = [];
|
|
379752
|
+
const tokens = /<w:p\b[^>]*>[\s\S]*?<\/w:p\s*>|<w:sdt\b[^>]*>|<\/w:sdt\s*>/g;
|
|
379753
|
+
let ordinal = 0;
|
|
379754
|
+
for (const token of xml.matchAll(tokens)) {
|
|
379755
|
+
if (token[0].startsWith("<w:p"))
|
|
379756
|
+
continue;
|
|
379757
|
+
if (token[0].startsWith("</")) {
|
|
379758
|
+
const frame = stack.pop();
|
|
379759
|
+
if (!frame)
|
|
379760
|
+
continue;
|
|
379761
|
+
const wrapperXml = xml.slice(frame.start, token.index + token[0].length);
|
|
379762
|
+
const propertiesXml = /<w:sdtPr\b[^>]*>([\s\S]*?)<\/w:sdtPr>/.exec(wrapperXml)?.[1];
|
|
379763
|
+
const contentXml = /<w:sdtContent\b[^>]*>([\s\S]*)<\/w:sdtContent>/.exec(wrapperXml)?.[1];
|
|
379764
|
+
const children2 = contentXml === undefined ? [] : parseTopLevelChildren(contentXml);
|
|
379765
|
+
const parsedProperties = propertiesXml === undefined ? null : parseSupportedSdtProperties(propertiesXml);
|
|
379766
|
+
const properties = { sourceId: String(frame.ordinal), ...parsedProperties ?? { controlType: "richText" } };
|
|
379767
|
+
const supported = parsedProperties !== null && contentXml !== undefined && children2.length > 0 && children2.every((child) => child.prefix === "w" && (child.localName === "p" || child.localName === "sdt")) && topLevelChildrenCoverXml(contentXml, children2);
|
|
379768
|
+
wrappers.set(frame.ordinal, { properties, supported });
|
|
379769
|
+
} else {
|
|
379770
|
+
stack.push({ ordinal: ordinal++, start: token.index });
|
|
379771
|
+
}
|
|
379772
|
+
}
|
|
379773
|
+
return wrappers;
|
|
379774
|
+
}
|
|
378673
379775
|
function serializeSelectedDrawing(input) {
|
|
378674
379776
|
const fail6 = (key2, message) => {
|
|
378675
379777
|
input.notes.add(key2, message);
|
|
@@ -378842,7 +379944,7 @@ function appendSerializedParts(out, parts, hyperlink) {
|
|
|
378842
379944
|
function serializedPartRuns(part) {
|
|
378843
379945
|
if (part.kind === "run")
|
|
378844
379946
|
return [part.run];
|
|
378845
|
-
if (part.kind === "hyperlink")
|
|
379947
|
+
if (part.kind === "hyperlink" || part.kind === "sdt")
|
|
378846
379948
|
return part.parts.flatMap(serializedPartRuns);
|
|
378847
379949
|
return [];
|
|
378848
379950
|
}
|
|
@@ -378868,6 +379970,48 @@ function noteContainingStructures(piece, notes, preservesHyperlink) {
|
|
|
378868
379970
|
}
|
|
378869
379971
|
return supported;
|
|
378870
379972
|
}
|
|
379973
|
+
function copySelectionPieces(pieces, stopAtSdt = true) {
|
|
379974
|
+
return pieces.flatMap((piece) => {
|
|
379975
|
+
if (piece.kind === "container" && piece.containerKind === "sdt" && stopAtSdt)
|
|
379976
|
+
return [piece];
|
|
379977
|
+
if (piece.kind === "container" || piece.kind === "tracked") {
|
|
379978
|
+
if (piece.kind === "container" && piece.policy === "atomic")
|
|
379979
|
+
return [piece];
|
|
379980
|
+
return copySelectionPieces(piece.children, stopAtSdt);
|
|
379981
|
+
}
|
|
379982
|
+
return [piece];
|
|
379983
|
+
});
|
|
379984
|
+
}
|
|
379985
|
+
function serializeSdtPart(piece, from, to, notes, styleContext, review) {
|
|
379986
|
+
const propertiesXml = /<w:sdtPr\b[^>]*>([\s\S]*?)<\/w:sdtPr>/.exec(piece.rawXml)?.[1];
|
|
379987
|
+
if (propertiesXml === undefined)
|
|
379988
|
+
return null;
|
|
379989
|
+
const properties = parseSupportedSdtProperties(propertiesXml);
|
|
379990
|
+
if (!properties)
|
|
379991
|
+
return null;
|
|
379992
|
+
const parts = [];
|
|
379993
|
+
for (const child of piece.children) {
|
|
379994
|
+
if (child.kind === "container" && child.containerKind === "sdt") {
|
|
379995
|
+
if (child.visibleStart < from || child.visibleEnd > to)
|
|
379996
|
+
return null;
|
|
379997
|
+
const nested = serializeSdtPart(child, from, to, notes, styleContext, review);
|
|
379998
|
+
if (!nested)
|
|
379999
|
+
return null;
|
|
380000
|
+
parts.push(nested);
|
|
380001
|
+
} else if (child.kind === "text" || child.kind === "control") {
|
|
380002
|
+
if (child.kind === "text" && child.textRole !== "visible")
|
|
380003
|
+
return null;
|
|
380004
|
+
const leaves = [];
|
|
380005
|
+
walkPieces([child], from, to, leaves, notes, styleContext, review);
|
|
380006
|
+
parts.push(...leaves);
|
|
380007
|
+
} else {
|
|
380008
|
+
return null;
|
|
380009
|
+
}
|
|
380010
|
+
}
|
|
380011
|
+
if (!parts.length)
|
|
380012
|
+
return null;
|
|
380013
|
+
return { kind: "sdt", ...properties, parts };
|
|
380014
|
+
}
|
|
378871
380015
|
|
|
378872
380016
|
class SerializeNotes {
|
|
378873
380017
|
constructor() {
|
|
@@ -379479,10 +380623,34 @@ function paragraphFragmentFor(block) {
|
|
|
379479
380623
|
function richParagraphFragmentFor(block) {
|
|
379480
380624
|
return {
|
|
379481
380625
|
...paragraphFragmentFor(block),
|
|
380626
|
+
...block.blockSdts ? { blockSdts: block.blockSdts } : {},
|
|
379482
380627
|
inlines: block.parts.flatMap(serializedPartInlines)
|
|
379483
380628
|
};
|
|
379484
380629
|
}
|
|
380630
|
+
function serializedSdtChildInline(part) {
|
|
380631
|
+
if (part.kind === "sdt")
|
|
380632
|
+
return {
|
|
380633
|
+
kind: "sdt",
|
|
380634
|
+
controlType: part.controlType,
|
|
380635
|
+
...part.tag !== undefined ? { tag: part.tag } : {},
|
|
380636
|
+
...part.alias !== undefined ? { alias: part.alias } : {},
|
|
380637
|
+
...part.lockMode !== undefined ? { lockMode: part.lockMode } : {},
|
|
380638
|
+
...part.multiline !== undefined ? { multiline: part.multiline } : {},
|
|
380639
|
+
inlines: part.parts.map(serializedSdtChildInline)
|
|
380640
|
+
};
|
|
380641
|
+
return serializedLeafPartInline(part);
|
|
380642
|
+
}
|
|
379485
380643
|
function serializedPartInlines(part) {
|
|
380644
|
+
if (part.kind === "sdt")
|
|
380645
|
+
return [{
|
|
380646
|
+
kind: "sdt",
|
|
380647
|
+
controlType: part.controlType,
|
|
380648
|
+
...part.tag !== undefined ? { tag: part.tag } : {},
|
|
380649
|
+
...part.alias !== undefined ? { alias: part.alias } : {},
|
|
380650
|
+
...part.lockMode !== undefined ? { lockMode: part.lockMode } : {},
|
|
380651
|
+
...part.multiline !== undefined ? { multiline: part.multiline } : {},
|
|
380652
|
+
inlines: part.parts.map(serializedSdtChildInline)
|
|
380653
|
+
}];
|
|
379486
380654
|
if (part.kind !== "hyperlink")
|
|
379487
380655
|
return [serializedLeafPartInline(part)];
|
|
379488
380656
|
return [
|
|
@@ -379540,7 +380708,7 @@ function serializedPartPlainText(part) {
|
|
|
379540
380708
|
`;
|
|
379541
380709
|
if (part.kind === "run")
|
|
379542
380710
|
return part.run.text;
|
|
379543
|
-
if (part.kind === "hyperlink")
|
|
380711
|
+
if (part.kind === "hyperlink" || part.kind === "sdt")
|
|
379544
380712
|
return part.parts.map(serializedPartPlainText).join("");
|
|
379545
380713
|
return "";
|
|
379546
380714
|
}
|
|
@@ -379564,6 +380732,8 @@ function renderHtmlPart(part) {
|
|
|
379564
380732
|
return renderHtmlRun(part.run);
|
|
379565
380733
|
if (part.kind === "image")
|
|
379566
380734
|
return "";
|
|
380735
|
+
if (part.kind === "sdt")
|
|
380736
|
+
return part.parts.map(renderHtmlPart).join("");
|
|
379567
380737
|
const href = part.target.kind === "external" ? part.target.url : `#${part.target.anchor}`;
|
|
379568
380738
|
const title = part.tooltip ? ` title="${escapeHtmlAttribute3(part.tooltip)}"` : "";
|
|
379569
380739
|
return `<a href="${escapeHtmlAttribute3(href)}"${title}>${part.parts.map(renderHtmlPart).join("")}</a>`;
|