@superdoc/mcp 1.2.0-next.13 → 1.2.0-next.15
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 +283 -51
- 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.15";
|
|
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;
|
|
@@ -142136,6 +142181,12 @@ function visitNumericXmlIds(xml, visit) {
|
|
|
142136
142181
|
if (value !== null)
|
|
142137
142182
|
visit(value);
|
|
142138
142183
|
}
|
|
142184
|
+
CONTENT_CONTROL_ID_RE.lastIndex = 0;
|
|
142185
|
+
while (match = CONTENT_CONTROL_ID_RE.exec(xml)) {
|
|
142186
|
+
const value = parseRevisionWId(decodeXmlTextPreservingInvalidNumericEntities(match[2] ?? ""));
|
|
142187
|
+
if (value !== null)
|
|
142188
|
+
visit(value);
|
|
142189
|
+
}
|
|
142139
142190
|
}
|
|
142140
142191
|
function scanMaxNumericXmlId(xml) {
|
|
142141
142192
|
let max = 0;
|
|
@@ -142164,12 +142215,13 @@ function observeRevisionWIdsFromXml(state, xml) {
|
|
|
142164
142215
|
if (max > reservation.max)
|
|
142165
142216
|
reservation.max = max;
|
|
142166
142217
|
}
|
|
142167
|
-
var TD8, NUMERIC_XML_ID_RE;
|
|
142218
|
+
var TD8, NUMERIC_XML_ID_RE, CONTENT_CONTROL_ID_RE;
|
|
142168
142219
|
var init_revision_wid_scan = __esm(() => {
|
|
142169
142220
|
init_src2();
|
|
142170
142221
|
init_xml_text();
|
|
142171
142222
|
TD8 = new TextDecoder;
|
|
142172
142223
|
NUMERIC_XML_ID_RE = /\b(?:[\w.-]+:)?id\s*=\s*(["'])([^"']*)\1/g;
|
|
142224
|
+
CONTENT_CONTROL_ID_RE = /<(?:[\w.-]+:)?id(?=[\s/>])[^>]*?\b(?:[\w.-]+:)?val\s*=\s*(["'])([^"']*)\1/g;
|
|
142173
142225
|
});
|
|
142174
142226
|
|
|
142175
142227
|
// ../../../v2/editor-core/dist/document/internal/part-wml-bookmark-start-cache.js
|
|
@@ -209365,6 +209417,17 @@ function planCut(pieces, levelStart, input, rootPieces, chain = []) {
|
|
|
209365
209417
|
{ close: chunks.close, reopen: chunks.open }
|
|
209366
209418
|
]);
|
|
209367
209419
|
}
|
|
209420
|
+
if (strict.kind === "container" && strict.containerKind === "sdt" && input.allowMetadataAnchorSplit) {
|
|
209421
|
+
if (input.space === "tracked")
|
|
209422
|
+
return { kind: "reject", reason: "paragraph-split-point-unsupported" };
|
|
209423
|
+
const chunks = anchoredMetadataChunks(strict, input.allocateWId);
|
|
209424
|
+
if (!chunks)
|
|
209425
|
+
return { kind: "reject", reason: "paragraph-split-point-unsupported" };
|
|
209426
|
+
return planCut(strict.children, chunks.contentStart, input, rootPieces, [
|
|
209427
|
+
...chain,
|
|
209428
|
+
{ close: chunks.close, reopen: chunks.reopen }
|
|
209429
|
+
]);
|
|
209430
|
+
}
|
|
209368
209431
|
return { kind: "reject", reason: "paragraph-split-point-unsupported" };
|
|
209369
209432
|
}
|
|
209370
209433
|
let boundaryChar = levelStart;
|
|
@@ -209413,6 +209476,32 @@ function wrapperChunks(piece) {
|
|
|
209413
209476
|
contentStart: piece.charStart + openEnd
|
|
209414
209477
|
};
|
|
209415
209478
|
}
|
|
209479
|
+
function anchoredMetadataChunks(piece, allocateWId) {
|
|
209480
|
+
if (piece.children.length === 0)
|
|
209481
|
+
return null;
|
|
209482
|
+
const raw = piece.rawXml;
|
|
209483
|
+
const prefix = /^(<w:sdt\b[^>]*>)\s*(<w:sdtPr>[\s\S]*?<\/w:sdtPr>)\s*(<w:sdtContent\b[^>]*>)/.exec(raw);
|
|
209484
|
+
const close = /<\/w:sdtContent>\s*<\/w:sdt>$/.exec(raw)?.[0];
|
|
209485
|
+
if (!prefix || !close)
|
|
209486
|
+
return null;
|
|
209487
|
+
const properties = prefix[2];
|
|
209488
|
+
const normalizedProperties = properties.replace(/\s+\/>/g, "/>").replace(/>\s+</g, "><");
|
|
209489
|
+
const id = /<w:id w:val="\d+"\/>/.exec(normalizedProperties)?.[0];
|
|
209490
|
+
const originalId = /<w:id w:val="\d+"\s*\/>/.exec(properties)?.[0];
|
|
209491
|
+
const alias = '<w:alias w:val="Anchored metadata"/>';
|
|
209492
|
+
const tag = /<w:tag w:val="[^"]+"\/>/.exec(normalizedProperties)?.[0];
|
|
209493
|
+
const appearance = '<w15:appearance w15:val="hidden"/>';
|
|
209494
|
+
const plainText = "<w:text/>";
|
|
209495
|
+
if (!id || !originalId || !tag || !normalizedProperties.includes(alias) || !normalizedProperties.includes(appearance) || !normalizedProperties.includes(plainText) || normalizedProperties !== `<w:sdtPr>${id}${alias}${tag}${appearance}${plainText}</w:sdtPr>`) {
|
|
209496
|
+
return null;
|
|
209497
|
+
}
|
|
209498
|
+
const originalPrefix = prefix[0];
|
|
209499
|
+
return {
|
|
209500
|
+
contentStart: piece.charStart + originalPrefix.length,
|
|
209501
|
+
close,
|
|
209502
|
+
reopen: () => originalPrefix.replace(originalId, originalId.replace(/(w:val=")\d+/, (_match, attribute) => `${attribute}${allocateWId()}`))
|
|
209503
|
+
};
|
|
209504
|
+
}
|
|
209416
209505
|
function openTagEnd(raw) {
|
|
209417
209506
|
let quote = null;
|
|
209418
209507
|
for (let i2 = 0;i2 < raw.length; i2 += 1) {
|
|
@@ -209439,7 +209528,7 @@ function refreshRevisionId(openChunk, allocateWId) {
|
|
|
209439
209528
|
}
|
|
209440
209529
|
function assembleHalves(src, regionStart, regionEnd, plan) {
|
|
209441
209530
|
const closes = [...plan.chain].reverse().map((element) => element.close).join("");
|
|
209442
|
-
const reopens = plan.chain.map((element) => element.reopen).join("");
|
|
209531
|
+
const reopens = plan.chain.map((element) => typeof element.reopen === "function" ? element.reopen() : element.reopen).join("");
|
|
209443
209532
|
if (plan.kind === "boundary") {
|
|
209444
209533
|
const boundaryChar = snapBoundaryPastRunClose(src, plan.boundaryChar, regionEnd);
|
|
209445
209534
|
return {
|
|
@@ -213704,7 +213793,8 @@ function prepareParagraphSplit(input) {
|
|
|
213704
213793
|
offset: input.offset,
|
|
213705
213794
|
space: input.coordinateSpace,
|
|
213706
213795
|
allocateWId: input.allocateWId,
|
|
213707
|
-
atomicObjectsAsCaretSlots: true
|
|
213796
|
+
atomicObjectsAsCaretSlots: true,
|
|
213797
|
+
allowMetadataAnchorSplit: true
|
|
213708
213798
|
});
|
|
213709
213799
|
if (!slice.ok)
|
|
213710
213800
|
return slice;
|
|
@@ -213727,6 +213817,14 @@ function prepareParagraphSplit(input) {
|
|
|
213727
213817
|
const headXml = openTag + headProperties + slice.head + closeTag;
|
|
213728
213818
|
return { ok: true, headXml, tailXml };
|
|
213729
213819
|
}
|
|
213820
|
+
function previewParagraphSplit(input) {
|
|
213821
|
+
const result = prepareParagraphSplit({
|
|
213822
|
+
...input,
|
|
213823
|
+
tailParaId: "00000000",
|
|
213824
|
+
allocateWId: () => 0
|
|
213825
|
+
});
|
|
213826
|
+
return result.ok ? { ok: true } : result;
|
|
213827
|
+
}
|
|
213730
213828
|
function renderPreparedParagraphSplit(split, trackedStamp) {
|
|
213731
213829
|
const head = trackedStamp ? injectParagraphMarkTrackedMarker(split.headXml, "ins", trackedStamp) : split.headXml;
|
|
213732
213830
|
return head + split.tailXml;
|
|
@@ -267771,6 +267869,10 @@ var init_registry3 = __esm(() => {
|
|
|
267771
267869
|
"blocks.move": {
|
|
267772
267870
|
supportsDryRun: true,
|
|
267773
267871
|
dryRunOverrideReason: "The V2 block adapter validates move previews without committing package or history state."
|
|
267872
|
+
},
|
|
267873
|
+
"blocks.split": {
|
|
267874
|
+
supportsDryRun: true,
|
|
267875
|
+
dryRunOverrideReason: "The V2 block adapter validates split previews without committing package or history state."
|
|
267774
267876
|
}
|
|
267775
267877
|
};
|
|
267776
267878
|
COLLABORATIVE_TABLE_REPRESENTED_OPERATIONS = new Set([
|
|
@@ -303647,17 +303749,35 @@ class V2BlocksAdapter {
|
|
|
303647
303749
|
const resolved = resolveParagraphTarget(this.context, input.target);
|
|
303648
303750
|
if ("error" in resolved)
|
|
303649
303751
|
return failure4(resolved.error, resolved.message);
|
|
303650
|
-
const begun = this.context.beginMutation({ expectedRevision: options?.expectedRevision });
|
|
303651
|
-
if ("failure" in begun)
|
|
303652
|
-
return failure4(begun.failure.code, begun.failure.message);
|
|
303653
|
-
const tx = begun.tx;
|
|
303654
303752
|
const partBytes = getSDDocumentSessionInternalPartBytes(this.context.session, storyPartUriFromId5(resolved.storyId));
|
|
303655
303753
|
const paraXml = partBytes ? TD90.decode(partBytes.subarray(resolved.entry.byteStart, resolved.entry.byteEnd)) : "";
|
|
303656
303754
|
const objectSlack = (paraXml.match(/<[\w.-]+:(?:drawing|pict|object)\b/g) ?? []).length;
|
|
303657
303755
|
const coordinateSpace = input.coordinateSpace ?? "visible";
|
|
303756
|
+
const offset = coordinateSpace === "tracked" ? Math.max(0, Math.trunc(Number.isFinite(input.offset) ? input.offset : 0)) : clampStructuralOffset(input.offset, resolved.entry.textLength + objectSlack);
|
|
303757
|
+
if (options?.dryRun) {
|
|
303758
|
+
const policy = this.context.validateMutation(options);
|
|
303759
|
+
if (policy)
|
|
303760
|
+
return failure4(policy.code, policy.message);
|
|
303761
|
+
if (!partBytes)
|
|
303762
|
+
return failure4("INVALID_CONTEXT", "paragraph-target-not-found");
|
|
303763
|
+
const planned = previewParagraphSplit({
|
|
303764
|
+
paragraphXml: paraXml,
|
|
303765
|
+
partBytes,
|
|
303766
|
+
paragraphByteStart: resolved.entry.byteStart,
|
|
303767
|
+
offset,
|
|
303768
|
+
coordinateSpace
|
|
303769
|
+
});
|
|
303770
|
+
if (!planned.ok)
|
|
303771
|
+
return failure4(mapRejectionReason(planned.reason), planned.reason);
|
|
303772
|
+
return { success: true, inserted: input.target, affectedStories: [] };
|
|
303773
|
+
}
|
|
303774
|
+
const begun = this.context.beginMutation({ expectedRevision: options?.expectedRevision });
|
|
303775
|
+
if ("failure" in begun)
|
|
303776
|
+
return failure4(begun.failure.code, begun.failure.message);
|
|
303777
|
+
const tx = begun.tx;
|
|
303658
303778
|
tx.paragraphSplit({
|
|
303659
303779
|
target: { storyId: resolved.storyId, paraId: input.target.nodeId },
|
|
303660
|
-
offset
|
|
303780
|
+
offset,
|
|
303661
303781
|
coordinateSpace,
|
|
303662
303782
|
changeMode: options?.changeMode ?? "direct"
|
|
303663
303783
|
});
|
|
@@ -355004,8 +355124,12 @@ function projectStories(context, slots) {
|
|
|
355004
355124
|
if (family === "footnotes" || family === "endnotes")
|
|
355005
355125
|
requiredPartBytes(context, story.partUri);
|
|
355006
355126
|
const paragraphs = readStoryParagraphs(context, story.storyId).filter(isWordprocessingParagraph);
|
|
355127
|
+
const runXmls = paragraphs.map((p) => extractParagraphRunXml(p.rawXml, p.namespaceBindings ?? {}));
|
|
355128
|
+
const runSignatures = computeRunSignatures(runXmls);
|
|
355129
|
+
const runXmlByOrdinal = new Map(paragraphs.map((p, i2) => [p.ordinal, runXmls[i2]]));
|
|
355130
|
+
const runSignatureByOrdinal = new Map(paragraphs.map((p, i2) => [p.ordinal, runSignatures[i2]]));
|
|
355007
355131
|
const projectEntry2 = (p) => {
|
|
355008
|
-
const runXml =
|
|
355132
|
+
const runXml = runXmlByOrdinal.get(p.ordinal);
|
|
355009
355133
|
const paragraphPropertiesXml = extractParagraphPropertiesXml(p.rawXml, p.namespaceBindings ?? {});
|
|
355010
355134
|
const blockId = family === "header-footer-parts" && isStructurallyBlankStoryParagraph({ text: p.text, runXml }) ? `${slotKey}::blank:${p.ordinal}` : p.blockId;
|
|
355011
355135
|
return {
|
|
@@ -355014,7 +355138,7 @@ function projectStories(context, slots) {
|
|
|
355014
355138
|
text: p.text,
|
|
355015
355139
|
headingLevel: p.headingLevel,
|
|
355016
355140
|
styleId: p.styleId,
|
|
355017
|
-
runSignature:
|
|
355141
|
+
runSignature: runSignatureByOrdinal.get(p.ordinal),
|
|
355018
355142
|
runXml,
|
|
355019
355143
|
trackedChangeAnnotationKeys: trackedChangeAnnotationKeysForParagraph(context, p),
|
|
355020
355144
|
paragraphPropertiesXml,
|
|
@@ -355087,8 +355211,10 @@ function bodyParagraphStructuralScopes(context, paragraphs) {
|
|
|
355087
355211
|
function projectBody(context) {
|
|
355088
355212
|
const paragraphs = readBodyParagraphs(context).filter(isWordprocessingParagraph);
|
|
355089
355213
|
const scopes = bodyParagraphStructuralScopes(context, paragraphs);
|
|
355214
|
+
const runXmls = paragraphs.map((p) => extractParagraphRunXml(p.rawXml, p.namespaceBindings ?? {}));
|
|
355215
|
+
const runSignatures = computeRunSignatures(runXmls);
|
|
355090
355216
|
return paragraphs.map((p, ordinal) => {
|
|
355091
|
-
const runXml =
|
|
355217
|
+
const runXml = runXmls[ordinal];
|
|
355092
355218
|
const paragraphPropertiesXml = extractParagraphPropertiesXml(p.rawXml, p.namespaceBindings ?? {});
|
|
355093
355219
|
return {
|
|
355094
355220
|
blockId: p.blockId,
|
|
@@ -355097,7 +355223,7 @@ function projectBody(context) {
|
|
|
355097
355223
|
text: p.text,
|
|
355098
355224
|
headingLevel: p.headingLevel,
|
|
355099
355225
|
styleId: p.styleId,
|
|
355100
|
-
runSignature:
|
|
355226
|
+
runSignature: runSignatures[ordinal],
|
|
355101
355227
|
runXml,
|
|
355102
355228
|
trackedChangeAnnotationKeys: trackedChangeAnnotationKeysForParagraph(context, p),
|
|
355103
355229
|
paragraphPropertiesXml,
|
|
@@ -359096,9 +359222,14 @@ function buildTrackedTableRowReplayPlan(input) {
|
|
|
359096
359222
|
if (baseTable.gridColumnCount !== targetTable.gridColumnCount) {
|
|
359097
359223
|
return unsafe(`table ${baseTable.tableNodeId} changes its column grid`);
|
|
359098
359224
|
}
|
|
359099
|
-
const rowKey = (row, bytes) => sliceBytes(bytes, row.rowByteStart, row.rowByteEnd)
|
|
359100
|
-
const
|
|
359101
|
-
const
|
|
359225
|
+
const rowKey = (row, bytes, root) => rowWithoutParagraphIdentities(sliceBytes(bytes, row.rowByteStart, row.rowByteEnd), root.namespaceBindings);
|
|
359226
|
+
const baseKeysWithInvalid = baseTable.rows.map((row) => rowKey(row, baseBytes, baseRoot));
|
|
359227
|
+
const targetKeysWithInvalid = targetTable.rows.map((row) => rowKey(row, targetBytes, targetRoot));
|
|
359228
|
+
if (baseKeysWithInvalid.includes(null) || targetKeysWithInvalid.includes(null)) {
|
|
359229
|
+
return unsafe(`table ${baseTable.tableNodeId} has invalid paragraph identity markup`);
|
|
359230
|
+
}
|
|
359231
|
+
const baseKeys = baseKeysWithInvalid.map((key2) => key2);
|
|
359232
|
+
const targetKeys = targetKeysWithInvalid.map((key2) => key2);
|
|
359102
359233
|
const baseIsShorter = baseKeys.length <= targetKeys.length;
|
|
359103
359234
|
const matched = matchRowSubsequence(baseIsShorter ? baseKeys : targetKeys, baseIsShorter ? targetKeys : baseKeys, (baseIsShorter ? baseTable.rows : targetTable.rows).map((row) => row.rowNodeId), (baseIsShorter ? targetTable.rows : baseTable.rows).map((row) => row.rowNodeId));
|
|
359104
359235
|
if (!matched)
|
|
@@ -359376,6 +359507,66 @@ function tableSkeleton(bytes, table) {
|
|
|
359376
359507
|
function sliceBytes(bytes, start, end) {
|
|
359377
359508
|
return new TextDecoder().decode(bytes.subarray(start, end));
|
|
359378
359509
|
}
|
|
359510
|
+
function rowWithoutParagraphIdentities(rowXml, namespaceBindings) {
|
|
359511
|
+
const parsed = collectXmlElementRanges(rowXml, {
|
|
359512
|
+
fragment: true,
|
|
359513
|
+
additionalNamespaces: xmlFragmentAdditionalNamespaces(rowXml, new Map(Object.entries(namespaceBindings)))
|
|
359514
|
+
});
|
|
359515
|
+
if (parsed.errors.length > 0)
|
|
359516
|
+
return null;
|
|
359517
|
+
const deletions = [];
|
|
359518
|
+
for (const paragraph4 of parsed.ranges) {
|
|
359519
|
+
if (paragraph4.tag.namespaceUri !== WORDPROCESSINGML_NS4 || paragraph4.tag.localName !== "p")
|
|
359520
|
+
continue;
|
|
359521
|
+
for (const attribute2 of paragraph4.tag.attributes) {
|
|
359522
|
+
if (attribute2.namespaceUri !== WORDPROCESSINGML_2010_NS || attribute2.localName !== "paraId" || !/^[0-9A-Fa-f]{8}$/.test(attribute2.value))
|
|
359523
|
+
continue;
|
|
359524
|
+
const opening = rowXml.slice(paragraph4.start, paragraph4.openEnd);
|
|
359525
|
+
const span = rawStartTagAttributeSpan(opening, attribute2.name, attribute2.value);
|
|
359526
|
+
if (!span)
|
|
359527
|
+
return null;
|
|
359528
|
+
deletions.push({ start: paragraph4.start + span.start, end: paragraph4.start + span.end });
|
|
359529
|
+
}
|
|
359530
|
+
}
|
|
359531
|
+
return deletions.sort((left, right) => right.start - left.start).reduce((xml, deletion) => xml.slice(0, deletion.start) + xml.slice(deletion.end), rowXml);
|
|
359532
|
+
}
|
|
359533
|
+
function rawStartTagAttributeSpan(opening, expectedName, expectedValue) {
|
|
359534
|
+
const whitespace = (character) => character !== undefined && /[\x20\t\r\n]/.test(character);
|
|
359535
|
+
let index2 = 1;
|
|
359536
|
+
while (index2 < opening.length && !whitespace(opening[index2]) && opening[index2] !== ">" && opening[index2] !== "/")
|
|
359537
|
+
index2 += 1;
|
|
359538
|
+
while (index2 < opening.length) {
|
|
359539
|
+
const start = index2;
|
|
359540
|
+
while (whitespace(opening[index2]))
|
|
359541
|
+
index2 += 1;
|
|
359542
|
+
if (opening[index2] === ">" || opening[index2] === "/")
|
|
359543
|
+
break;
|
|
359544
|
+
const nameStart = index2;
|
|
359545
|
+
while (index2 < opening.length && !whitespace(opening[index2]) && !["=", ">", "/"].includes(opening[index2]))
|
|
359546
|
+
index2 += 1;
|
|
359547
|
+
const name = opening.slice(nameStart, index2);
|
|
359548
|
+
while (whitespace(opening[index2]))
|
|
359549
|
+
index2 += 1;
|
|
359550
|
+
if (opening[index2] !== "=")
|
|
359551
|
+
return null;
|
|
359552
|
+
index2 += 1;
|
|
359553
|
+
while (whitespace(opening[index2]))
|
|
359554
|
+
index2 += 1;
|
|
359555
|
+
const quote = opening[index2];
|
|
359556
|
+
if (quote !== '"' && quote !== "'")
|
|
359557
|
+
return null;
|
|
359558
|
+
const valueStart = ++index2;
|
|
359559
|
+
while (index2 < opening.length && opening[index2] !== quote)
|
|
359560
|
+
index2 += 1;
|
|
359561
|
+
if (index2 === opening.length)
|
|
359562
|
+
return null;
|
|
359563
|
+
const value2 = opening.slice(valueStart, index2);
|
|
359564
|
+
index2 += 1;
|
|
359565
|
+
if (name === expectedName && value2 === expectedValue)
|
|
359566
|
+
return { start, end: index2 };
|
|
359567
|
+
}
|
|
359568
|
+
return null;
|
|
359569
|
+
}
|
|
359379
359570
|
function documentRootContext(xml) {
|
|
359380
359571
|
const roots = [];
|
|
359381
359572
|
let valid = true;
|
|
@@ -360667,10 +360858,16 @@ function projectMainDocumentBodyEntries(source, options = {}) {
|
|
|
360667
360858
|
});
|
|
360668
360859
|
const scopes = mapBodyParagraphStructuralScopes(tableCatalog, paragraphIndex.entries);
|
|
360669
360860
|
const namespaceBindingsByByteStart = scanParagraphNamespaceBindingsByByteStart(source.xml);
|
|
360670
|
-
|
|
360671
|
-
|
|
360861
|
+
const rawXmls = paragraphIndex.entries.map((entry) => TD107.decode(bytes.subarray(entry.byteStart, entry.byteEnd)));
|
|
360862
|
+
const runXmls = paragraphIndex.entries.map((entry, index2) => {
|
|
360863
|
+
const namespaceBindings = namespaceBindingsByByteStart.get(entry.byteStart) ?? {};
|
|
360864
|
+
return extractParagraphRunXml(rawXmls[index2], namespaceBindings);
|
|
360865
|
+
});
|
|
360866
|
+
const runSignatures = computeRunSignatures(runXmls);
|
|
360867
|
+
return paragraphIndex.entries.map((entry, index2) => {
|
|
360868
|
+
const rawXml = rawXmls[index2];
|
|
360672
360869
|
const namespaceBindings = namespaceBindingsByByteStart.get(entry.byteStart) ?? {};
|
|
360673
|
-
const runXml =
|
|
360870
|
+
const runXml = runXmls[index2];
|
|
360674
360871
|
const paragraphPropertiesXml = extractParagraphPropertiesXml(rawXml, namespaceBindings);
|
|
360675
360872
|
return {
|
|
360676
360873
|
blockId: entry.blockId,
|
|
@@ -360679,7 +360876,7 @@ function projectMainDocumentBodyEntries(source, options = {}) {
|
|
|
360679
360876
|
text: readVisibleParagraphText(rawXml),
|
|
360680
360877
|
headingLevel: paragraphHeadingLevel(rawXml, { paragraphStyleOutlineLevels }),
|
|
360681
360878
|
styleId: paragraphStyleId(rawXml),
|
|
360682
|
-
runSignature:
|
|
360879
|
+
runSignature: runSignatures[index2],
|
|
360683
360880
|
runXml,
|
|
360684
360881
|
paragraphPropertiesXml,
|
|
360685
360882
|
paragraphPropertiesSignature: computeParagraphPropertiesSignature2(paragraphPropertiesXml)
|
|
@@ -363160,22 +363357,32 @@ function buildCompareApplyEligibility(context, payload, plans) {
|
|
|
363160
363357
|
if (bodyDeferredToTableReplay)
|
|
363161
363358
|
direct.add("body");
|
|
363162
363359
|
}
|
|
363360
|
+
const trackedBodyOperations = payload.applyPlan.bodyOperations.length > 0 ? payload.applyPlan.bodyOperations : computeCompareBodyOperations(payload.base.body, payload.target.body, {
|
|
363361
|
+
base: payload.base.definitions,
|
|
363362
|
+
target: payload.target.definitions
|
|
363363
|
+
});
|
|
363163
363364
|
const trackedTablePlan = buildTrackedTableRowReplayPlan({
|
|
363164
363365
|
base: mainDocument.base,
|
|
363165
363366
|
target: mainDocument.target,
|
|
363166
363367
|
baseBody: payload.base.body,
|
|
363167
363368
|
targetBody: payload.target.body,
|
|
363168
|
-
bodyOperations:
|
|
363169
|
-
base: payload.base.definitions,
|
|
363170
|
-
target: payload.target.definitions
|
|
363171
|
-
})
|
|
363369
|
+
bodyOperations: trackedBodyOperations
|
|
363172
363370
|
});
|
|
363371
|
+
const trackedBlockPlan = trackedTablePlan.unsafeReasons.length > 0 && !trackedTablePlan.refuseBlockFallback ? buildTrackedTableBlockReplayPlan({
|
|
363372
|
+
base: mainDocument.base,
|
|
363373
|
+
target: mainDocument.target,
|
|
363374
|
+
bodyOperations: trackedBodyOperations,
|
|
363375
|
+
allowTopologyReplacement: true
|
|
363376
|
+
}) : null;
|
|
363173
363377
|
if (trackedTablePlan.unsafeReasons.length === 0 && trackedTablePlan.steps.length > 0) {
|
|
363174
363378
|
tracked.add("tables");
|
|
363175
363379
|
if (bodyDeferredToTableReplay)
|
|
363176
363380
|
tracked.add("body");
|
|
363177
363381
|
if (rowReplayCoversContentControls(payload.base.annotations, payload.target.annotations, trackedTablePlan.steps, mainDocument.base.xml, mainDocument.target.xml))
|
|
363178
363382
|
tracked.add("content-controls");
|
|
363383
|
+
} else if (trackedBlockPlan && trackedBlockPlan.steps.length > 0) {
|
|
363384
|
+
tracked.add("tables");
|
|
363385
|
+
tracked.add("body");
|
|
363179
363386
|
}
|
|
363180
363387
|
}
|
|
363181
363388
|
const packageGraphCoveredByComments = direct.has("comments") && packageGraphKeysNotCoveredByComments(context, payload.base, payload.target, plans.commentPlan.steps).length === 0;
|
|
@@ -381859,10 +382066,27 @@ function groupMetadataAnchor(documentXml, id, knownIds) {
|
|
|
381859
382066
|
const kept = contiguousAnchorPrefix(documentXml, matches);
|
|
381860
382067
|
if (kept.length === 1)
|
|
381861
382068
|
return { id, segments: kept, target: kept[0].target };
|
|
381862
|
-
const textSegments =
|
|
381863
|
-
|
|
381864
|
-
|
|
381865
|
-
|
|
382069
|
+
const textSegments = [];
|
|
382070
|
+
for (const anchor of kept) {
|
|
382071
|
+
const previous3 = textSegments.at(-1);
|
|
382072
|
+
if (previous3?.blockId === anchor.blockId && previous3.range.end === anchor.startOffset) {
|
|
382073
|
+
previous3.range.end = anchor.endOffset;
|
|
382074
|
+
} else {
|
|
382075
|
+
textSegments.push({ blockId: anchor.blockId, range: { start: anchor.startOffset, end: anchor.endOffset } });
|
|
382076
|
+
}
|
|
382077
|
+
}
|
|
382078
|
+
if (textSegments.length === 1) {
|
|
382079
|
+
const range = textSegments[0];
|
|
382080
|
+
return {
|
|
382081
|
+
id,
|
|
382082
|
+
segments: kept,
|
|
382083
|
+
target: {
|
|
382084
|
+
kind: "selection",
|
|
382085
|
+
start: { kind: "text", blockId: range.blockId, offset: range.range.start, story: bodyStoryLocator2() },
|
|
382086
|
+
end: { kind: "text", blockId: range.blockId, offset: range.range.end, story: bodyStoryLocator2() }
|
|
382087
|
+
}
|
|
382088
|
+
};
|
|
382089
|
+
}
|
|
381866
382090
|
return {
|
|
381867
382091
|
id,
|
|
381868
382092
|
segments: kept,
|
|
@@ -381882,7 +382106,12 @@ function contiguousAnchorPrefix(documentXml, matches) {
|
|
|
381882
382106
|
const context = map3.byBlockId(matches[i2].blockId);
|
|
381883
382107
|
if (!context)
|
|
381884
382108
|
break;
|
|
381885
|
-
|
|
382109
|
+
const sameParagraph = context.ordinal === prev.ordinal;
|
|
382110
|
+
if (sameParagraph) {
|
|
382111
|
+
const previousAnchor = kept.at(-1);
|
|
382112
|
+
if (context.blockId !== previousAnchor.blockId || matches[i2].startOffset !== previousAnchor.endOffset || !isMetadataCarrierGap(documentXml.slice(previousAnchor.end, matches[i2].start)))
|
|
382113
|
+
break;
|
|
382114
|
+
} else if (context.ordinal !== prev.ordinal + 1)
|
|
381886
382115
|
break;
|
|
381887
382116
|
if (!sameTableCellPath(context.tableCellPath, first.tableCellPath))
|
|
381888
382117
|
break;
|
|
@@ -381899,6 +382128,9 @@ function contiguousAnchorPrefix(documentXml, matches) {
|
|
|
381899
382128
|
}
|
|
381900
382129
|
return kept;
|
|
381901
382130
|
}
|
|
382131
|
+
function isMetadataCarrierGap(xml) {
|
|
382132
|
+
return /^(?:\s*<w:proofErr\s+w:type="(?:spellStart|spellEnd|gramStart|gramEnd)"\s*\/>)*\s*$/.test(xml);
|
|
382133
|
+
}
|
|
381902
382134
|
function sameOrdinalPath2(left, right) {
|
|
381903
382135
|
return left.length === right.length && left.every((value2, index2) => value2 === right[index2]);
|
|
381904
382136
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc/mcp",
|
|
3
|
-
"version": "1.2.0-next.
|
|
3
|
+
"version": "1.2.0-next.15",
|
|
4
4
|
"description": "Model Context Protocol server for SuperDoc, giving an AI agent tools to read and edit .docx files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
27
|
-
"@superdoc/sdk": "2.15.0-next.
|
|
27
|
+
"@superdoc/sdk": "2.15.0-next.15",
|
|
28
28
|
"debug": "^4.4.3",
|
|
29
29
|
"zod": "^4.3.6"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"superdoc": "2.18.0-next.
|
|
33
|
-
"@superdoc/docx-engine": "0.17.0-next.
|
|
32
|
+
"superdoc": "2.18.0-next.15",
|
|
33
|
+
"@superdoc/docx-engine": "0.17.0-next.17",
|
|
34
34
|
"@superdoc/document-api": "0.1.0-alpha.0",
|
|
35
35
|
"@types/bun": "^1.3.8",
|
|
36
36
|
"@types/node": "22.19.2",
|