@superdoc/mcp 1.10.0-next.5 → 1.10.0-next.6
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 +210 -95
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -31630,7 +31630,7 @@ var init_host = __esm(() => {
|
|
|
31630
31630
|
});
|
|
31631
31631
|
|
|
31632
31632
|
// ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
|
|
31633
|
-
var SDK_VERSION = "2.23.0-next.
|
|
31633
|
+
var SDK_VERSION = "2.23.0-next.6";
|
|
31634
31634
|
|
|
31635
31635
|
// ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
|
|
31636
31636
|
import { accessSync, chmodSync, constants, existsSync, statSync } from "node:fs";
|
|
@@ -384950,7 +384950,7 @@ function bytesProveNoContentControlCarrier(bytes) {
|
|
|
384950
384950
|
}
|
|
384951
384951
|
return true;
|
|
384952
384952
|
}
|
|
384953
|
-
function listContentControlPartSources(context) {
|
|
384953
|
+
function listContentControlPartSources(context, rangeCache) {
|
|
384954
384954
|
const body = context.resolveFullStoryLocator({ kind: "story", storyType: "body" });
|
|
384955
384955
|
if ("error" in body)
|
|
384956
384956
|
throw operationError("TARGET_NOT_FOUND", "body story is not available.");
|
|
@@ -384970,8 +384970,83 @@ function listContentControlPartSources(context) {
|
|
|
384970
384970
|
story
|
|
384971
384971
|
});
|
|
384972
384972
|
}
|
|
384973
|
+
const textboxes = listSDDocumentSessionInternalStories(context.session).filter((textbox) => textbox.storyKind === "textbox" && textbox.textboxId && textbox.storyByteRange);
|
|
384974
|
+
const registry3 = getSDDocumentSessionInternalTextboxRegistry(context.session);
|
|
384975
|
+
const progress = getSDDocumentSessionInternalTextboxRegistryProgressFingerprint(context.session);
|
|
384976
|
+
for (const partUri of rangeCache.keys())
|
|
384977
|
+
if (!seen.has(partUri))
|
|
384978
|
+
rangeCache.delete(partUri);
|
|
384979
|
+
for (const owner of [...sources]) {
|
|
384980
|
+
const owned = textboxes.filter((textbox) => textbox.partUri === owner.partUri);
|
|
384981
|
+
const bytes = owned.length ? readPartBytes2(context, owner.partUri) : null;
|
|
384982
|
+
if (!bytes) {
|
|
384983
|
+
rangeCache.delete(owner.partUri);
|
|
384984
|
+
continue;
|
|
384985
|
+
}
|
|
384986
|
+
const inactive = owned.flatMap((textbox) => {
|
|
384987
|
+
const [start, end] = textbox.storyByteRange;
|
|
384988
|
+
return (registry3.byTextboxId.get(textbox.textboxId)?.alternateContentCounterparts ?? []).filter((range) => !(range[0] <= start && range[1] >= end));
|
|
384989
|
+
});
|
|
384990
|
+
const boundaries = [...new Set([
|
|
384991
|
+
...owned.flatMap((textbox) => [...textbox.storyByteRange]),
|
|
384992
|
+
...inactive.flatMap((range) => [...range])
|
|
384993
|
+
])].sort((left, right) => left - right);
|
|
384994
|
+
let cached2 = rangeCache.get(owner.partUri);
|
|
384995
|
+
if (!cached2 || cached2.bytes !== bytes || cached2.registry !== registry3 || cached2.progress !== progress || cached2.boundaries.length !== boundaries.length || cached2.boundaries.some((boundary, index2) => boundary !== boundaries[index2])) {
|
|
384996
|
+
const offsets2 = new Map;
|
|
384997
|
+
let byteOffset = 0;
|
|
384998
|
+
let charOffset = 0;
|
|
384999
|
+
for (const boundary of boundaries) {
|
|
385000
|
+
charOffset += decodeXml(bytes.subarray(byteOffset, boundary)).length;
|
|
385001
|
+
offsets2.set(boundary, charOffset);
|
|
385002
|
+
byteOffset = boundary;
|
|
385003
|
+
}
|
|
385004
|
+
cached2 = { bytes, registry: registry3, progress, boundaries, offsets: offsets2 };
|
|
385005
|
+
rangeCache.set(owner.partUri, cached2);
|
|
385006
|
+
}
|
|
385007
|
+
const { offsets } = cached2;
|
|
385008
|
+
const characterRange = ([start, end]) => [offsets.get(start), offsets.get(end)];
|
|
385009
|
+
if (inactive.length)
|
|
385010
|
+
owner.excludedXmlRanges = inactive.map(characterRange);
|
|
385011
|
+
for (const textbox of owned) {
|
|
385012
|
+
sources.push({
|
|
385013
|
+
partUri: textbox.partUri,
|
|
385014
|
+
storyId: textbox.storyId,
|
|
385015
|
+
story: { kind: "story", storyType: "textbox", textboxId: textbox.textboxId },
|
|
385016
|
+
xmlRange: characterRange(textbox.storyByteRange)
|
|
385017
|
+
});
|
|
385018
|
+
}
|
|
385019
|
+
}
|
|
384973
385020
|
return sources;
|
|
384974
385021
|
}
|
|
385022
|
+
function partitionContentControlScan(xml, sources) {
|
|
385023
|
+
const hiddenControls = collectHiddenNativeContentControlStarts(xml);
|
|
385024
|
+
const trackedWrapperRanges = buildTrackedWrapperRanges(xml);
|
|
385025
|
+
const scans = new Map(sources.map((source) => [source, { ranges: [], hiddenControls, trackedWrapperRanges }]));
|
|
385026
|
+
const owner = sources.find((source) => !source.xmlRange);
|
|
385027
|
+
const textboxes = sources.filter((source) => source.xmlRange).sort((left, right) => left.xmlRange[0] - right.xmlRange[0]);
|
|
385028
|
+
const inactive = [...owner.excludedXmlRanges ?? []].sort((left, right) => left[0] - right[0]);
|
|
385029
|
+
const containing = (items, rangeOf, start, end) => {
|
|
385030
|
+
let low = 0;
|
|
385031
|
+
let high = items.length;
|
|
385032
|
+
while (low < high) {
|
|
385033
|
+
const middle = low + high >>> 1;
|
|
385034
|
+
if (rangeOf(items[middle])[0] <= start)
|
|
385035
|
+
low = middle + 1;
|
|
385036
|
+
else
|
|
385037
|
+
high = middle;
|
|
385038
|
+
}
|
|
385039
|
+
const candidate2 = items[low - 1];
|
|
385040
|
+
return candidate2 !== undefined && rangeOf(candidate2)[1] >= end ? candidate2 : undefined;
|
|
385041
|
+
};
|
|
385042
|
+
for (const range of collectContentControlRanges(xml)) {
|
|
385043
|
+
const textbox = containing(textboxes, (source) => source.xmlRange, range.start, range.end);
|
|
385044
|
+
if (!textbox && containing(inactive, (range2) => range2, range.start, range.end))
|
|
385045
|
+
continue;
|
|
385046
|
+
scans.get(textbox ?? owner).ranges.push(range);
|
|
385047
|
+
}
|
|
385048
|
+
return scans;
|
|
385049
|
+
}
|
|
384975
385050
|
|
|
384976
385051
|
class V2ContentControlsAdapter {
|
|
384977
385052
|
constructor(context) {
|
|
@@ -385062,17 +385137,23 @@ class V2ContentControlsAdapter {
|
|
|
385062
385137
|
ungroup: (input, options) => this.unwrap(input, options)
|
|
385063
385138
|
};
|
|
385064
385139
|
this.loadedCache = null;
|
|
385140
|
+
this.textboxCharacterRanges = new Map;
|
|
385065
385141
|
this.readCatalog = null;
|
|
385066
385142
|
this.partsWithoutControlCarriers = new WeakSet;
|
|
385067
385143
|
}
|
|
385144
|
+
hasCurrentLoadedCache(revision) {
|
|
385145
|
+
return this.loadedCache?.revision === revision && this.loadedCache.registry === getSDDocumentSessionInternalTextboxRegistry(this.context.session) && this.loadedCache.registryProgress === getSDDocumentSessionInternalTextboxRegistryProgressFingerprint(this.context.session);
|
|
385146
|
+
}
|
|
385068
385147
|
currentReadCatalog() {
|
|
385069
385148
|
const cached2 = this.readCatalog;
|
|
385070
385149
|
const session = this.context.session;
|
|
385071
385150
|
if (!cached2 || getSDDocumentSessionInternalSourceCompletePosture(session) !== "source-complete" || cached2.identity !== getSDDocumentSessionInternalResidentMainControlInventoryIdentity(session))
|
|
385072
385151
|
return null;
|
|
385073
|
-
const sources = listContentControlPartSources(this.context);
|
|
385074
|
-
if (JSON.stringify(sources) !== JSON.stringify(cached2.sources) || sources.some((source, i2) => i2 > 0 && getSDDocumentSessionInternalPartBytes(session, source.partUri) !== cached2.secondaryBytes[i2]))
|
|
385152
|
+
const sources = listContentControlPartSources(this.context, this.textboxCharacterRanges);
|
|
385153
|
+
if (JSON.stringify(sources) !== JSON.stringify(cached2.sources) || sources.some((source, i2) => i2 > 0 && getSDDocumentSessionInternalPartBytes(session, source.partUri) !== cached2.secondaryBytes[i2])) {
|
|
385154
|
+
this.loadedCache = null;
|
|
385075
385155
|
return null;
|
|
385156
|
+
}
|
|
385076
385157
|
if (this.loadedCache?.revision !== this.context.currentPublicRevision())
|
|
385077
385158
|
this.loadedCache = null;
|
|
385078
385159
|
return cached2;
|
|
@@ -385084,7 +385165,7 @@ class V2ContentControlsAdapter {
|
|
|
385084
385165
|
this.readCatalog = null;
|
|
385085
385166
|
return;
|
|
385086
385167
|
}
|
|
385087
|
-
const sources = listContentControlPartSources(this.context);
|
|
385168
|
+
const sources = listContentControlPartSources(this.context, this.textboxCharacterRanges);
|
|
385088
385169
|
this.readCatalog = {
|
|
385089
385170
|
identity,
|
|
385090
385171
|
sources,
|
|
@@ -385113,7 +385194,7 @@ class V2ContentControlsAdapter {
|
|
|
385113
385194
|
const relationships = listSDDocumentSessionInternalHeaderFooterRels(session);
|
|
385114
385195
|
if (bodyDescriptor.relationships.status === "missing" && relationships.length > 0)
|
|
385115
385196
|
return false;
|
|
385116
|
-
const sources = listContentControlPartSources(this.context);
|
|
385197
|
+
const sources = listContentControlPartSources(this.context, this.textboxCharacterRanges);
|
|
385117
385198
|
if (relationships.some((rel) => !sources.some((source) => source.story && source.partUri === rel.partUri))) {
|
|
385118
385199
|
return false;
|
|
385119
385200
|
}
|
|
@@ -385165,8 +385246,17 @@ class V2ContentControlsAdapter {
|
|
|
385165
385246
|
throw error48;
|
|
385166
385247
|
return { success: false, failure: { code: error48.code, message: error48.message } };
|
|
385167
385248
|
}
|
|
385249
|
+
if (part.story?.storyType === "textbox") {
|
|
385250
|
+
const textbox = getSDDocumentSessionInternalTextboxRegistry(this.context.session).byTextboxId.get(part.story.textboxId);
|
|
385251
|
+
if (textbox && textbox.alternateContentCounterparts.length > 1) {
|
|
385252
|
+
return { success: false, failure: {
|
|
385253
|
+
code: "CAPABILITY_UNSUPPORTED",
|
|
385254
|
+
message: "Content-control creation in mirrored AlternateContent textbox stories is unsupported; no changes were made."
|
|
385255
|
+
} };
|
|
385256
|
+
}
|
|
385257
|
+
}
|
|
385168
385258
|
if (structuralReplacementXml !== undefined && input.at?.start.kind === "text") {
|
|
385169
|
-
const anchor = findParagraphById3(part.xml, input.at.start.blockId);
|
|
385259
|
+
const anchor = findParagraphById3(part.xml, input.at.start.blockId, part.xmlRange);
|
|
385170
385260
|
const ranges = collectXmlElementRanges(part.xml).ranges;
|
|
385171
385261
|
const paragraph4 = anchor && ranges.find((range) => range.start === anchor.start && range.end === anchor.end);
|
|
385172
385262
|
const parent = paragraph4 && ranges.filter((range) => range.start < paragraph4.start && range.end > paragraph4.end).sort((left, right) => left.end - left.start - (right.end - right.start))[0];
|
|
@@ -385236,7 +385326,7 @@ class V2ContentControlsAdapter {
|
|
|
385236
385326
|
if (!trackedStamp) {
|
|
385237
385327
|
return { success: false, failure: { code: "PRECONDITION_FAILED", message: "no-author-configured" } };
|
|
385238
385328
|
}
|
|
385239
|
-
const preview = wrapSelectionInXml(this.context, part.xml, input.at, wrapTrackedStructuralXml({ innerXml: baseSdtXml, kind: "ins", stamp: trackedStamp }), input.kind, input.content ?? "", input.content !== undefined);
|
|
385329
|
+
const preview = wrapSelectionInXml(this.context, part.xml, input.at, wrapTrackedStructuralXml({ innerXml: baseSdtXml, kind: "ins", stamp: trackedStamp }), input.kind, input.content ?? "", input.content !== undefined, undefined, false, part.xmlRange);
|
|
385240
385330
|
if (!preview.ok)
|
|
385241
385331
|
return { success: false, failure: preview.failure };
|
|
385242
385332
|
if (!dryRun) {
|
|
@@ -385257,7 +385347,7 @@ class V2ContentControlsAdapter {
|
|
|
385257
385347
|
}
|
|
385258
385348
|
}
|
|
385259
385349
|
if (input.at) {
|
|
385260
|
-
const anchor = input.at.start.kind === "text" ? findParagraphById3(part.xml, input.at.start.blockId) : null;
|
|
385350
|
+
const anchor = input.at.start.kind === "text" ? findParagraphById3(part.xml, input.at.start.blockId, part.xmlRange) : null;
|
|
385261
385351
|
const hasPendingRevisions = anchor && /<(?:[\w.-]+:)?(?:ins|del|moveFrom|moveTo)\b/.test(anchor.xml);
|
|
385262
385352
|
const pendingRevisionFailure = {
|
|
385263
385353
|
success: false,
|
|
@@ -385268,7 +385358,7 @@ class V2ContentControlsAdapter {
|
|
|
385268
385358
|
};
|
|
385269
385359
|
if (hasPendingRevisions && !supportsTrackedInlineTextCreate(input))
|
|
385270
385360
|
return pendingRevisionFailure;
|
|
385271
|
-
const preview = wrapSelectionInXml(this.context, part.xml, input.at, baseSdtXml, "inline", input.content ?? "", input.content !== undefined);
|
|
385361
|
+
const preview = wrapSelectionInXml(this.context, part.xml, input.at, baseSdtXml, "inline", input.content ?? "", input.content !== undefined, undefined, false, part.xmlRange);
|
|
385272
385362
|
if (!preview.ok)
|
|
385273
385363
|
return { success: false, failure: preview.failure };
|
|
385274
385364
|
if (hasPendingRevisions) {
|
|
@@ -385280,10 +385370,10 @@ class V2ContentControlsAdapter {
|
|
|
385280
385370
|
let beforeXml = "";
|
|
385281
385371
|
let namespaceBindings = new Map(Object.entries(collectXmlElementRanges(part.xml).ranges[0]?.namespaceBindings ?? {}));
|
|
385282
385372
|
if (input.at?.start.kind === "text") {
|
|
385283
|
-
const anchor = findParagraphById3(part.xml, input.at.start.blockId);
|
|
385373
|
+
const anchor = findParagraphById3(part.xml, input.at.start.blockId, part.xmlRange);
|
|
385284
385374
|
if (anchor) {
|
|
385285
385375
|
namespaceBindings = new Map(contentControlNamespaceBindings(part.xml, anchor.start, true));
|
|
385286
|
-
if (input.kind === "block" &&
|
|
385376
|
+
if (input.kind === "block" && isReplaceableEmptyParagraph(anchor.xml)) {
|
|
385287
385377
|
beforeXml = anchor.xml;
|
|
385288
385378
|
}
|
|
385289
385379
|
}
|
|
@@ -385322,7 +385412,7 @@ class V2ContentControlsAdapter {
|
|
|
385322
385412
|
if (wholeBlocks.kind === "failure") {
|
|
385323
385413
|
return { success: false, failure: { code: wholeBlocks.code, message: wholeBlocks.message } };
|
|
385324
385414
|
}
|
|
385325
|
-
const anchor = at.start.kind === "text" ? findParagraphById3(part.xml, at.start.blockId) : null;
|
|
385415
|
+
const anchor = at.start.kind === "text" ? findParagraphById3(part.xml, at.start.blockId, part.xmlRange) : null;
|
|
385326
385416
|
if (wholeBlocks.kind === "ok") {
|
|
385327
385417
|
const selectedXml = part.xml.slice(wholeBlocks.start, wholeBlocks.end);
|
|
385328
385418
|
const wrapped = replaceSdtContentInTemplate(sdtXml, buildInnerXml(selectedXml));
|
|
@@ -385354,8 +385444,8 @@ class V2ContentControlsAdapter {
|
|
|
385354
385444
|
})();
|
|
385355
385445
|
let left = split.slice(0, splitAt) + "</w:p>";
|
|
385356
385446
|
let right = anchor.xml.slice(0, openEnd) + properties2 + split.slice(splitAt + splitMarker.length);
|
|
385357
|
-
const keepLeft = parseParagraphInlineMap(left).visibleLength > 0;
|
|
385358
|
-
const keepRight = parseParagraphInlineMap(right).visibleLength > 0;
|
|
385447
|
+
const keepLeft = parseParagraphInlineMap(left).visibleLength > 0 || hasParagraphObjects(left);
|
|
385448
|
+
const keepRight = parseParagraphInlineMap(right).visibleLength > 0 || hasParagraphObjects(right);
|
|
385359
385449
|
const allocateNextSplitId = createParaIdAllocator(this.context);
|
|
385360
385450
|
const reservedReplacementIds = new Set(structuralReplacementXml === undefined ? [] : Array.from(structuralReplacementXml.matchAll(/\bw14:paraId="([^"]+)"/g), (match) => match[1]));
|
|
385361
385451
|
const allocateSplitId = () => {
|
|
@@ -385406,7 +385496,7 @@ class V2ContentControlsAdapter {
|
|
|
385406
385496
|
targetBlockIds2 = [at.start.blockId];
|
|
385407
385497
|
}
|
|
385408
385498
|
} else {
|
|
385409
|
-
const wrapped = wrapSelectionInXml(this.context, part.xml, input.at, sdtXml, input.kind, input.content ?? "", input.content !== undefined, repeatingSectionItemId ? (text4) => buildInnerXml(buildContentXml(text4, input.kind, createParaIdAllocator(this.context))) : undefined, !tracked && !part.story && input.html === undefined && input.json === undefined && structuralReplacementXml === undefined);
|
|
385499
|
+
const wrapped = wrapSelectionInXml(this.context, part.xml, input.at, sdtXml, input.kind, input.content ?? "", input.content !== undefined, repeatingSectionItemId ? (text4) => buildInnerXml(buildContentXml(text4, input.kind, createParaIdAllocator(this.context))) : undefined, !tracked && !part.story && input.html === undefined && input.json === undefined && structuralReplacementXml === undefined, part.xmlRange);
|
|
385410
385500
|
if (!wrapped.ok) {
|
|
385411
385501
|
return { success: false, failure: wrapped.failure };
|
|
385412
385502
|
}
|
|
@@ -385436,7 +385526,7 @@ class V2ContentControlsAdapter {
|
|
|
385436
385526
|
}))
|
|
385437
385527
|
};
|
|
385438
385528
|
}
|
|
385439
|
-
nextXml = insertAtDocumentEnd(part.xml, wrapped);
|
|
385529
|
+
nextXml = insertAtDocumentEnd(part.xml, wrapped, part.xmlRange);
|
|
385440
385530
|
}
|
|
385441
385531
|
if (dryRun)
|
|
385442
385532
|
return this.validateDryRun(input, options, target);
|
|
@@ -386219,7 +386309,7 @@ class V2ContentControlsAdapter {
|
|
|
386219
386309
|
if (at.start.kind !== "text" || at.end.kind !== "text" || at.start.blockId !== at.end.blockId) {
|
|
386220
386310
|
throw operationError("CAPABILITY_UNAVAILABLE", "Content-control creation requires a selection within one paragraph.");
|
|
386221
386311
|
}
|
|
386222
|
-
const paragraph4 = findParagraphById3(part.xml, at.start.blockId);
|
|
386312
|
+
const paragraph4 = findParagraphById3(part.xml, at.start.blockId, part.xmlRange);
|
|
386223
386313
|
if (!paragraph4)
|
|
386224
386314
|
throw operationError("TARGET_NOT_FOUND", `Paragraph ${at.start.blockId} was not found in the target story.`);
|
|
386225
386315
|
if (![at.start.offset, at.end.offset].every((offset) => Number.isInteger(offset) && offset >= 0 && offset <= parseParagraphInlineMap(paragraph4.xml).visibleLength) || at.start.offset > at.end.offset) {
|
|
@@ -386742,22 +386832,30 @@ class V2ContentControlsAdapter {
|
|
|
386742
386832
|
}
|
|
386743
386833
|
load() {
|
|
386744
386834
|
const revision = this.context.currentPublicRevision();
|
|
386745
|
-
if (this.
|
|
386835
|
+
if (this.hasCurrentLoadedCache(revision))
|
|
386746
386836
|
return this.loadedCache.value;
|
|
386747
386837
|
const documentXml = readPartXml(this.context, DOCUMENT_PART_URI5);
|
|
386748
386838
|
if (!documentXml)
|
|
386749
386839
|
throw operationError("PRECONDITION_FAILED", "document.xml bytes are unavailable.");
|
|
386750
386840
|
const parts = [];
|
|
386751
|
-
|
|
386752
|
-
|
|
386841
|
+
const sources = listContentControlPartSources(this.context, this.textboxCharacterRanges);
|
|
386842
|
+
const captures = new Map;
|
|
386843
|
+
for (const partUri of new Set(sources.map((source) => source.partUri))) {
|
|
386844
|
+
const xml = partUri === DOCUMENT_PART_URI5 ? documentXml : readPartXml(this.context, partUri);
|
|
386753
386845
|
if (!xml)
|
|
386754
386846
|
continue;
|
|
386755
|
-
|
|
386847
|
+
captures.set(partUri, { xml, scans: partitionContentControlScan(xml, sources.filter((source) => source.partUri === partUri)) });
|
|
386848
|
+
}
|
|
386849
|
+
for (const source of sources) {
|
|
386850
|
+
const capture = captures.get(source.partUri);
|
|
386851
|
+
if (!capture)
|
|
386852
|
+
continue;
|
|
386853
|
+
const paragraphs2 = parseParagraphWindows(capture.xml, source.xmlRange);
|
|
386756
386854
|
parts.push({
|
|
386757
386855
|
...source,
|
|
386758
|
-
xml,
|
|
386856
|
+
xml: capture.xml,
|
|
386759
386857
|
paragraphs: paragraphs2,
|
|
386760
|
-
controls: parseContentControls(xml, paragraphs2, source.storyId, source.story)
|
|
386858
|
+
controls: parseContentControls(capture.xml, paragraphs2, source.storyId, source.story, capture.scans.get(source))
|
|
386761
386859
|
});
|
|
386762
386860
|
}
|
|
386763
386861
|
const body = parts.find((part) => part.partUri === DOCUMENT_PART_URI5);
|
|
@@ -386767,7 +386865,12 @@ class V2ContentControlsAdapter {
|
|
|
386767
386865
|
controls: parts.flatMap((part) => part.controls),
|
|
386768
386866
|
parts
|
|
386769
386867
|
};
|
|
386770
|
-
this.loadedCache = {
|
|
386868
|
+
this.loadedCache = {
|
|
386869
|
+
revision,
|
|
386870
|
+
value: value3,
|
|
386871
|
+
registry: getSDDocumentSessionInternalTextboxRegistry(this.context.session),
|
|
386872
|
+
registryProgress: getSDDocumentSessionInternalTextboxRegistryProgressFingerprint(this.context.session)
|
|
386873
|
+
};
|
|
386771
386874
|
this.captureReadCatalog(value3);
|
|
386772
386875
|
return value3;
|
|
386773
386876
|
}
|
|
@@ -386776,29 +386879,45 @@ class V2ContentControlsAdapter {
|
|
|
386776
386879
|
return;
|
|
386777
386880
|
for (let attempt = 0;attempt <= maxRestarts; attempt += 1) {
|
|
386778
386881
|
const revision = this.context.currentPublicRevision();
|
|
386779
|
-
if (this.
|
|
386882
|
+
if (this.hasCurrentLoadedCache(revision))
|
|
386780
386883
|
return;
|
|
386884
|
+
const registry3 = getSDDocumentSessionInternalTextboxRegistry(this.context.session);
|
|
386885
|
+
const registryProgress = getSDDocumentSessionInternalTextboxRegistryProgressFingerprint(this.context.session);
|
|
386886
|
+
const captureIsCurrent = () => this.context.currentPublicRevision() === revision && getSDDocumentSessionInternalTextboxRegistry(this.context.session) === registry3 && getSDDocumentSessionInternalTextboxRegistryProgressFingerprint(this.context.session) === registryProgress;
|
|
386781
386887
|
const documentXml = readPartXml(this.context, DOCUMENT_PART_URI5);
|
|
386782
386888
|
if (!documentXml)
|
|
386783
386889
|
return;
|
|
386784
|
-
const
|
|
386785
|
-
|
|
386786
|
-
|
|
386890
|
+
const sources = listContentControlPartSources(this.context, this.textboxCharacterRanges);
|
|
386891
|
+
const physicalParts = new Map;
|
|
386892
|
+
for (const partUri of new Set(sources.map((source) => source.partUri))) {
|
|
386893
|
+
const xml = partUri === DOCUMENT_PART_URI5 ? documentXml : readPartXml(this.context, partUri);
|
|
386894
|
+
if (!xml)
|
|
386895
|
+
continue;
|
|
386896
|
+
physicalParts.set(partUri, { xml, scans: partitionContentControlScan(xml, sources.filter((source) => source.partUri === partUri)) });
|
|
386897
|
+
}
|
|
386898
|
+
const captures = sources.flatMap((source) => {
|
|
386899
|
+
const part = physicalParts.get(source.partUri);
|
|
386900
|
+
return part ? [{ source, xml: part.xml, scan: part.scans.get(source) }] : [];
|
|
386787
386901
|
});
|
|
386788
386902
|
const parts = [];
|
|
386789
386903
|
let preempted = false;
|
|
386790
386904
|
for (const capture of captures) {
|
|
386791
|
-
const paragraphs2 = await parseParagraphWindowsCooperatively(capture.xml, yieldPoint);
|
|
386792
|
-
if (
|
|
386905
|
+
const paragraphs2 = await parseParagraphWindowsCooperatively(capture.xml, yieldPoint, capture.source.xmlRange);
|
|
386906
|
+
if (!captureIsCurrent()) {
|
|
386793
386907
|
preempted = true;
|
|
386794
386908
|
break;
|
|
386795
386909
|
}
|
|
386796
|
-
const controls = await parseContentControlsCooperatively(capture.xml, paragraphs2, capture.source.storyId, capture.source.story, yieldPoint);
|
|
386797
|
-
if (
|
|
386910
|
+
const controls = await parseContentControlsCooperatively(capture.xml, paragraphs2, capture.source.storyId, capture.source.story, yieldPoint, capture.scan);
|
|
386911
|
+
if (!captureIsCurrent()) {
|
|
386798
386912
|
preempted = true;
|
|
386799
386913
|
break;
|
|
386800
386914
|
}
|
|
386801
|
-
parts.push({
|
|
386915
|
+
parts.push({
|
|
386916
|
+
...capture.source,
|
|
386917
|
+
xml: capture.xml,
|
|
386918
|
+
paragraphs: paragraphs2,
|
|
386919
|
+
controls
|
|
386920
|
+
});
|
|
386802
386921
|
}
|
|
386803
386922
|
if (preempted)
|
|
386804
386923
|
continue;
|
|
@@ -386811,7 +386930,7 @@ class V2ContentControlsAdapter {
|
|
|
386811
386930
|
controls: parts.flatMap((part) => part.controls),
|
|
386812
386931
|
parts
|
|
386813
386932
|
};
|
|
386814
|
-
this.loadedCache = { revision, value: value3 };
|
|
386933
|
+
this.loadedCache = { revision, value: value3, registry: registry3, registryProgress };
|
|
386815
386934
|
this.captureReadCatalog(value3);
|
|
386816
386935
|
return;
|
|
386817
386936
|
}
|
|
@@ -386880,7 +386999,7 @@ class V2ContentControlsAdapter {
|
|
|
386880
386999
|
semanticStyleDependencies: commitOptions.semanticStyleDependencies,
|
|
386881
387000
|
storySurface: commitOptions.storySurface,
|
|
386882
387001
|
signalLanesToRebuild: commitOptions.signalLanesToRebuild,
|
|
386883
|
-
storyIds: commitOptions.storySurface?.contentControlRewrite ? this.load().parts.filter((part) => part.partUri === partUri).map((part) => part.storyId) : undefined,
|
|
387002
|
+
storyIds: commitOptions.storySurface?.contentControlRewrite ? this.load().parts.filter((part) => part.partUri === partUri && !part.xmlRange).map((part) => part.storyId) : undefined,
|
|
386884
387003
|
createdRefs: commitOptions.createdRefs
|
|
386885
387004
|
});
|
|
386886
387005
|
if (!committed.ok)
|
|
@@ -386913,53 +387032,42 @@ function contentControlTextBlockIds(info) {
|
|
|
386913
387032
|
return [];
|
|
386914
387033
|
return [...new Set([target.start.blockId, target.end.blockId])];
|
|
386915
387034
|
}
|
|
386916
|
-
function
|
|
386917
|
-
const
|
|
386918
|
-
|
|
386919
|
-
for (let match =
|
|
386920
|
-
const
|
|
386921
|
-
|
|
387035
|
+
function* iterateParagraphWindows(documentXml, xmlRange) {
|
|
387036
|
+
const paragraphStart = /<w:p(?=[\s/>])/g;
|
|
387037
|
+
paragraphStart.lastIndex = xmlRange?.[0] ?? 0;
|
|
387038
|
+
for (let match = paragraphStart.exec(documentXml);match && match.index < (xmlRange?.[1] ?? documentXml.length); match = paragraphStart.exec(documentXml)) {
|
|
387039
|
+
const node4 = readXmlNodeAt(documentXml, match.index);
|
|
387040
|
+
if (!node4 || node4.kind !== "element" || node4.end > (xmlRange?.[1] ?? documentXml.length))
|
|
387041
|
+
continue;
|
|
387042
|
+
paragraphStart.lastIndex = node4.end;
|
|
387043
|
+
const blockId = readAttrs(documentXml.slice(match.index, node4.openEnd))["w14:paraId"];
|
|
386922
387044
|
if (!blockId)
|
|
386923
387045
|
continue;
|
|
386924
|
-
|
|
386925
|
-
|
|
386926
|
-
start: match.index,
|
|
386927
|
-
end: paragraphRe.lastIndex,
|
|
386928
|
-
xml,
|
|
386929
|
-
textLength: extractVisibleTextFromXml(xml).length
|
|
386930
|
-
});
|
|
387046
|
+
const xml = documentXml.slice(match.index, node4.end);
|
|
387047
|
+
yield { blockId, start: match.index, end: node4.end, xml, textLength: extractVisibleTextFromXml(xml).length };
|
|
386931
387048
|
}
|
|
386932
|
-
return paragraphs2;
|
|
386933
387049
|
}
|
|
386934
|
-
|
|
387050
|
+
function parseParagraphWindows(documentXml, xmlRange) {
|
|
387051
|
+
return [...iterateParagraphWindows(documentXml, xmlRange)].filter((paragraph4) => /^[0-9A-Fa-f]{8}$/.test(paragraph4.blockId));
|
|
387052
|
+
}
|
|
387053
|
+
async function parseParagraphWindowsCooperatively(documentXml, yieldPoint, xmlRange) {
|
|
386935
387054
|
const paragraphs2 = [];
|
|
386936
|
-
const paragraphRe = /<w:p\b[^>]*?(?:\/>|>[\s\S]*?<\/w:p>)/g;
|
|
386937
387055
|
let sinceYield = 0;
|
|
386938
|
-
for (
|
|
386939
|
-
|
|
386940
|
-
const blockId = /w14:paraId="([0-9A-Fa-f]{8})"/.exec(xml)?.[1];
|
|
386941
|
-
if (!blockId)
|
|
387056
|
+
for (const paragraph4 of iterateParagraphWindows(documentXml, xmlRange)) {
|
|
387057
|
+
if (!/^[0-9A-Fa-f]{8}$/.test(paragraph4.blockId))
|
|
386942
387058
|
continue;
|
|
386943
|
-
paragraphs2.push(
|
|
386944
|
-
blockId,
|
|
386945
|
-
start: match.index,
|
|
386946
|
-
end: paragraphRe.lastIndex,
|
|
386947
|
-
xml,
|
|
386948
|
-
textLength: extractVisibleTextFromXml(xml).length
|
|
386949
|
-
});
|
|
387059
|
+
paragraphs2.push(paragraph4);
|
|
386950
387060
|
if ((sinceYield += 1) >= COOPERATIVE_PARSE_SLICE_PARAGRAPHS) {
|
|
386951
387061
|
sinceYield = 0;
|
|
386952
|
-
const resumeFrom = paragraphRe.lastIndex;
|
|
386953
387062
|
await yieldPoint();
|
|
386954
|
-
paragraphRe.lastIndex = resumeFrom;
|
|
386955
387063
|
}
|
|
386956
387064
|
}
|
|
386957
387065
|
return paragraphs2;
|
|
386958
387066
|
}
|
|
386959
|
-
function parseContentControls(documentXml, paragraphs2, storyId, story) {
|
|
386960
|
-
const ranges = collectContentControlRanges(documentXml);
|
|
386961
|
-
const hiddenControls = collectHiddenNativeContentControlStarts(documentXml);
|
|
386962
|
-
const trackedWrapperRanges = buildTrackedWrapperRanges(documentXml);
|
|
387067
|
+
function parseContentControls(documentXml, paragraphs2, storyId, story, scan) {
|
|
387068
|
+
const ranges = scan?.ranges ?? collectContentControlRanges(documentXml);
|
|
387069
|
+
const hiddenControls = scan?.hiddenControls ?? collectHiddenNativeContentControlStarts(documentXml);
|
|
387070
|
+
const trackedWrapperRanges = scan?.trackedWrapperRanges ?? buildTrackedWrapperRanges(documentXml);
|
|
386963
387071
|
const parsed = ranges.filter((range) => {
|
|
386964
387072
|
if (hiddenControls.has(range.start))
|
|
386965
387073
|
return false;
|
|
@@ -386985,10 +387093,10 @@ function collectContentControlRanges(documentXml) {
|
|
|
386985
387093
|
ranges.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
386986
387094
|
return ranges;
|
|
386987
387095
|
}
|
|
386988
|
-
async function parseContentControlsCooperatively(documentXml, paragraphs2, storyId, story, yieldPoint) {
|
|
386989
|
-
const ranges = collectContentControlRanges(documentXml);
|
|
386990
|
-
const hiddenControls = collectHiddenNativeContentControlStarts(documentXml);
|
|
386991
|
-
const trackedWrapperRanges = buildTrackedWrapperRanges(documentXml);
|
|
387096
|
+
async function parseContentControlsCooperatively(documentXml, paragraphs2, storyId, story, yieldPoint, scan) {
|
|
387097
|
+
const ranges = scan?.ranges ?? collectContentControlRanges(documentXml);
|
|
387098
|
+
const hiddenControls = scan?.hiddenControls ?? collectHiddenNativeContentControlStarts(documentXml);
|
|
387099
|
+
const trackedWrapperRanges = scan?.trackedWrapperRanges ?? buildTrackedWrapperRanges(documentXml);
|
|
386992
387100
|
const parsed = [];
|
|
386993
387101
|
let sinceYield = 0;
|
|
386994
387102
|
for (const range of ranges) {
|
|
@@ -388026,8 +388134,9 @@ function buildContentXml(text4, kind, allocParaId) {
|
|
|
388026
388134
|
function buildAdjacentContent(text4, kind, allocParaId) {
|
|
388027
388135
|
return kind === "inline" ? `<w:r><w:t>${xmlEscapeText(text4)}</w:t></w:r>` : buildParaIdParagraphXml(allocParaId(), `<w:r><w:t>${xmlEscapeText(text4)}</w:t></w:r>`);
|
|
388028
388136
|
}
|
|
388029
|
-
function insertAtDocumentEnd(documentXml, fragment4) {
|
|
388030
|
-
const
|
|
388137
|
+
function insertAtDocumentEnd(documentXml, fragment4, xmlRange) {
|
|
388138
|
+
const container = xmlRange ? readXmlNodeAt(documentXml, xmlRange[0]) : null;
|
|
388139
|
+
const offset = container?.kind === "element" ? container.closeStart : documentEndInsertionOffset(documentXml);
|
|
388031
388140
|
return `${documentXml.slice(0, offset)}${fragment4}${documentXml.slice(offset)}`;
|
|
388032
388141
|
}
|
|
388033
388142
|
function replaceSdtPrXml(sdtXml, prXml) {
|
|
@@ -388218,6 +388327,7 @@ function controlPlacement(xml, control2) {
|
|
|
388218
388327
|
case "body":
|
|
388219
388328
|
case "hdr":
|
|
388220
388329
|
case "ftr":
|
|
388330
|
+
case "txbxContent":
|
|
388221
388331
|
return "block";
|
|
388222
388332
|
case "sdtContent":
|
|
388223
388333
|
case "sdt":
|
|
@@ -388625,11 +388735,11 @@ function supportsTrackedInlineTextCreate(input) {
|
|
|
388625
388735
|
const at = input.at;
|
|
388626
388736
|
return input.kind === "inline" && input.controlType === "text" && input.content !== undefined && input.html === undefined && input.json === undefined && input.ooxml === undefined && at?.kind === "selection" && at.coordinateSpace !== "tracked" && at.start.kind === "text" && at.end.kind === "text" && at.start.blockId === at.end.blockId && at.start.offset === at.end.offset;
|
|
388627
388737
|
}
|
|
388628
|
-
function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacementContent, hasReplacementContent, buildReplacementContentXml2 = (text4) => buildContentXml(text4, kind, createParaIdAllocator(context)), allowBoundarySelection = false) {
|
|
388738
|
+
function wrapSelectionInXml(context, documentXml, target, sdtXml, kind, replacementContent, hasReplacementContent, buildReplacementContentXml2 = (text4) => buildContentXml(text4, kind, createParaIdAllocator(context)), allowBoundarySelection = false, xmlRange) {
|
|
388629
388739
|
if (target?.kind !== "selection" || target.start?.kind !== "text" || target.end?.kind !== "text") {
|
|
388630
388740
|
return { ok: false, failure: { code: "INVALID_TARGET", message: "A text selection is required." } };
|
|
388631
388741
|
}
|
|
388632
|
-
const para = findParagraphById3(documentXml, target.start.blockId);
|
|
388742
|
+
const para = findParagraphById3(documentXml, target.start.blockId, xmlRange);
|
|
388633
388743
|
if (!para)
|
|
388634
388744
|
return { ok: false, failure: { code: "TARGET_NOT_FOUND", message: "Target paragraph was not found." } };
|
|
388635
388745
|
if (kind === "inline" && target.start.offset === target.end.offset) {
|
|
@@ -388769,11 +388879,17 @@ function insertBlockContentControlAtSelection(documentXml, paragraphs2, target,
|
|
|
388769
388879
|
if (!anchor)
|
|
388770
388880
|
throw operationError("TARGET_NOT_FOUND", "Target paragraph was not found.");
|
|
388771
388881
|
const collapsed = target.start.blockId === target.end.blockId && target.start.offset === target.end.offset;
|
|
388772
|
-
if (collapsed &&
|
|
388882
|
+
if (collapsed && isReplaceableEmptyParagraph(anchor.xml)) {
|
|
388773
388883
|
return replaceRange3(documentXml, anchor.start, anchor.end, sdtXml);
|
|
388774
388884
|
}
|
|
388775
388885
|
return `${documentXml.slice(0, anchor.end)}${sdtXml}${documentXml.slice(anchor.end)}`;
|
|
388776
388886
|
}
|
|
388887
|
+
function isReplaceableEmptyParagraph(paragraphXml) {
|
|
388888
|
+
return extractVisibleTextFromXml(paragraphXml).trim().length === 0 && !hasParagraphObjects(paragraphXml);
|
|
388889
|
+
}
|
|
388890
|
+
function hasParagraphObjects(paragraphXml) {
|
|
388891
|
+
return /<(?:[\w.-]+:)?(?:drawing|pict|object)\b/.test(paragraphXml);
|
|
388892
|
+
}
|
|
388777
388893
|
function resolveWholeBlockSelection(documentXml, paragraphs2, target) {
|
|
388778
388894
|
let startBlockId;
|
|
388779
388895
|
let endBlockId;
|
|
@@ -388899,12 +389015,10 @@ function findFirstSdtElementRange(xml) {
|
|
|
388899
389015
|
}
|
|
388900
389016
|
return null;
|
|
388901
389017
|
}
|
|
388902
|
-
function findParagraphById3(documentXml, blockId) {
|
|
388903
|
-
const
|
|
388904
|
-
|
|
388905
|
-
|
|
388906
|
-
return { start: match.index, end: paraRe.lastIndex, xml: match[0] };
|
|
388907
|
-
}
|
|
389018
|
+
function findParagraphById3(documentXml, blockId, xmlRange) {
|
|
389019
|
+
for (const paragraph4 of iterateParagraphWindows(documentXml, xmlRange)) {
|
|
389020
|
+
if (paragraph4.blockId === blockId)
|
|
389021
|
+
return paragraph4;
|
|
388908
389022
|
}
|
|
388909
389023
|
return null;
|
|
388910
389024
|
}
|
|
@@ -388991,26 +389105,27 @@ function splitTextRunAtVisibleOffset(paragraphXml, piece, localOffset, insertXml
|
|
|
388991
389105
|
return `${paragraphXml.slice(0, piece.runCharStart)}${beforeRun}${insertXml}${afterRun}${paragraphXml.slice(piece.runCharEnd)}`;
|
|
388992
389106
|
}
|
|
388993
389107
|
function replaceTextRangeInParagraph2(paragraphXml, start, end, replacement2) {
|
|
388994
|
-
const
|
|
388995
|
-
|
|
388996
|
-
|
|
388997
|
-
|
|
388998
|
-
|
|
388999
|
-
|
|
389000
|
-
|
|
389001
|
-
const
|
|
389108
|
+
const pieces = Array.from(parseParagraphInlineMap(paragraphXml).leaves());
|
|
389109
|
+
for (const piece of pieces) {
|
|
389110
|
+
if (!isSplittableText(piece))
|
|
389111
|
+
continue;
|
|
389112
|
+
if (start >= piece.visibleStart && end <= piece.visibleEnd) {
|
|
389113
|
+
if (hasRunNeighborBefore(pieces, piece) || hasRunNeighborAfter(pieces, piece))
|
|
389114
|
+
return paragraphXml;
|
|
389115
|
+
const text4 = piece.decodedText;
|
|
389116
|
+
const localStart = start - piece.visibleStart;
|
|
389117
|
+
const localEnd = end - piece.visibleStart;
|
|
389002
389118
|
const before = text4.slice(0, localStart);
|
|
389003
389119
|
const selected = text4.slice(localStart, localEnd);
|
|
389004
389120
|
const after = text4.slice(localEnd);
|
|
389005
|
-
const runStart =
|
|
389006
|
-
const runEnd =
|
|
389121
|
+
const runStart = piece.runCharStart;
|
|
389122
|
+
const runEnd = piece.runCharEnd;
|
|
389007
389123
|
const { runOpenTag, runProperties } = readRunOpenTagAndProperties(paragraphXml, runStart);
|
|
389008
389124
|
const mkRun = (segment) => `${runOpenTag}${runProperties}<w:t xml:space="preserve">${xmlEscapeText(segment)}</w:t></w:r>`;
|
|
389009
389125
|
const beforeRun = before ? mkRun(before) : "";
|
|
389010
389126
|
const afterRun = after ? mkRun(after) : "";
|
|
389011
389127
|
return `${paragraphXml.slice(0, runStart)}${beforeRun}${replacement2(selected)}${afterRun}${paragraphXml.slice(runEnd)}`;
|
|
389012
389128
|
}
|
|
389013
|
-
offset = nextOffset;
|
|
389014
389129
|
}
|
|
389015
389130
|
return paragraphXml;
|
|
389016
389131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc/mcp",
|
|
3
|
-
"version": "1.10.0-next.
|
|
3
|
+
"version": "1.10.0-next.6",
|
|
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.23.0-next.
|
|
27
|
+
"@superdoc/sdk": "2.23.0-next.6",
|
|
28
28
|
"debug": "^4.4.3",
|
|
29
29
|
"zod": "^4.3.6"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"superdoc": "2.26.0-next.
|
|
33
|
-
"@superdoc/docx-engine": "0.25.0-next.
|
|
32
|
+
"superdoc": "2.26.0-next.7",
|
|
33
|
+
"@superdoc/docx-engine": "0.25.0-next.7",
|
|
34
34
|
"@superdoc/document-api": "0.1.0-alpha.0",
|
|
35
35
|
"@types/bun": "^1.3.8",
|
|
36
36
|
"@types/node": "22.19.2",
|