@superdoc/mcp 1.7.1-next.5 → 1.7.1-next.7

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.
Files changed (2) hide show
  1. package/dist/index.js +98 -11
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -31600,7 +31600,7 @@ var init_host = __esm(() => {
31600
31600
  });
31601
31601
 
31602
31602
  // ../../packages/sdk/langs/node/src/runtime/sdk-version.generated.ts
31603
- var SDK_VERSION = "2.20.1-next.5";
31603
+ var SDK_VERSION = "2.20.1-next.7";
31604
31604
 
31605
31605
  // ../../packages/sdk/langs/node/src/runtime/embedded-platform.ts
31606
31606
  import { accessSync, chmodSync, constants, existsSync, statSync } from "node:fs";
@@ -138920,6 +138920,9 @@ function validateRunContents(xml, options) {
138920
138920
  }
138921
138921
  if (runs === "")
138922
138922
  return { ok: true };
138923
+ if (/^[\t\n\r ]+$/.test(runs)) {
138924
+ return { ok: false, reason: "target runs contain only XML whitespace; clearing this representation is not supported" };
138925
+ }
138923
138926
  const replayXml = stripAllowedNoteReferences(runs, options);
138924
138927
  const withoutCarriers = replayXml !== null && options.baseRunXml ? stripRetainedCarrier(replayXml, options.baseRunXml, options.allowNamespaceDeclarationDifference === true) : replayXml;
138925
138928
  const withoutBookmarks = withoutCarriers !== null && /<(?:[\w.-]+:)?bookmark(?:Start|End)\b/.test(withoutCarriers) ? preservedBookmarkRunTokens(withoutCarriers)?.strippedXml ?? null : withoutCarriers;
@@ -205791,6 +205794,7 @@ function parsePlainRun(runXml, textStart, byteStart, byteEnd, options = {}) {
205791
205794
  runClose
205792
205795
  });
205793
205796
  const childRe = /<([\w.-]+):([\w.-]+)\b([^>]*)>/g;
205797
+ const pairedNoBreakHyphenCloseRe = /\s*<\/([\w.-]+):noBreakHyphen>/y;
205794
205798
  childRe.lastIndex = runOpen.length;
205795
205799
  let tMatch = null;
205796
205800
  let controlKind = null;
@@ -205835,7 +205839,18 @@ function parsePlainRun(runXml, textStart, byteStart, byteEnd, options = {}) {
205835
205839
  childRe.lastIndex = closeMatch.index + closeMatch[0].length;
205836
205840
  continue;
205837
205841
  }
205838
- if (isSelfClose && (local === "tab" || local === "br" || local === "cr")) {
205842
+ let supportedControlXml = m[0];
205843
+ let isPairedNoBreakHyphen = false;
205844
+ if (local === "noBreakHyphen" && !isSelfClose) {
205845
+ pairedNoBreakHyphenCloseRe.lastIndex = childRe.lastIndex;
205846
+ const close = pairedNoBreakHyphenCloseRe.exec(without);
205847
+ if (!close || close[1] !== ns)
205848
+ return fail4("invalid-range");
205849
+ childRe.lastIndex = pairedNoBreakHyphenCloseRe.lastIndex;
205850
+ supportedControlXml += close[0];
205851
+ isPairedNoBreakHyphen = true;
205852
+ }
205853
+ if ((isSelfClose || isPairedNoBreakHyphen) && (local === "tab" || local === "br" || local === "cr" || local === "noBreakHyphen")) {
205839
205854
  if (!options.allowReplaceableInlineControls) {
205840
205855
  if (!tMatch && !controlKind) {
205841
205856
  const trailing = matchSingleTrailingTextRun(without, childRe.lastIndex, without.length - runClose.length);
@@ -205853,7 +205868,7 @@ function parsePlainRun(runXml, textStart, byteStart, byteEnd, options = {}) {
205853
205868
  text: text2,
205854
205869
  rPr,
205855
205870
  runOpen,
205856
- leadingControlXml: m[0],
205871
+ leadingControlXml: supportedControlXml,
205857
205872
  runClose,
205858
205873
  ...leadingTransparentXml ? { leadingTransparentXml } : {}
205859
205874
  }
@@ -205867,7 +205882,7 @@ function parsePlainRun(runXml, textStart, byteStart, byteEnd, options = {}) {
205867
205882
  if (tMatch || controlKind)
205868
205883
  return fail4("invalid-range");
205869
205884
  controlKind = local;
205870
- controlXml = m[0];
205885
+ controlXml = supportedControlXml;
205871
205886
  continue;
205872
205887
  }
205873
205888
  if (local === "drawing" || local === "pict" || local === "object") {
@@ -206014,7 +206029,7 @@ function rewriteRunSpanText(paragraphXml, startOffset, endOffset, newText) {
206014
206029
  if (collected.runs.length === 0) {
206015
206030
  return rewriteEmptyParagraphInsert(paragraphXml, newText, startOffset, endOffset);
206016
206031
  }
206017
- const boundaryInsert = rewriteCollapsedBoundaryAfterAnchorGapInsert(paragraphXml, collected.runs, startOffset, endOffset, (carrier) => newText.length > 0 ? renderTextRun(newText, carrier.runOpen, carrier.runClose, carrier.rPr) : "");
206032
+ const boundaryInsert = rewriteCollapsedRunBoundaryInsert(paragraphXml, collected.runs, startOffset, endOffset, (carrier) => newText.length > 0 ? renderTextRun(newText, carrier.runOpen, carrier.runClose, carrier.rPr) : "");
206018
206033
  if (boundaryInsert)
206019
206034
  return { ok: true, xml: boundaryInsert };
206020
206035
  const tailInsert = rewriteCollapsedParagraphTailInsert(paragraphXml, collected.runs, startOffset, endOffset, (carrier) => newText.length > 0 ? renderTextRun(newText, carrier.runOpen, carrier.runClose, carrier.rPr) : "");
@@ -206154,7 +206169,7 @@ function rewriteRunSpanTrackedReplace(paragraphXml, startOffset, endOffset, stam
206154
206169
  if (!paragraphMarkFallback.ok)
206155
206170
  return paragraphMarkFallback;
206156
206171
  const carrierRPr = (carrier) => carrier.rPr || paragraphMarkFallback.rPr;
206157
- const boundaryInsert = rewriteCollapsedBoundaryAfterAnchorGapInsert(paragraphXml, collected.runs, startOffset, endOffset, (carrier) => stamp.newText.length > 0 ? buildInsWrapper(stamp.newText, carrier.runOpen, carrier.runClose, carrierRPr(carrier), {
206172
+ const boundaryInsert = rewriteCollapsedRunBoundaryInsert(paragraphXml, collected.runs, startOffset, endOffset, (carrier) => stamp.newText.length > 0 ? buildInsWrapper(stamp.newText, carrier.runOpen, carrier.runClose, carrierRPr(carrier), {
206158
206173
  rsid: stamp.insRsid,
206159
206174
  wId: stamp.wId,
206160
206175
  author: stamp.author,
@@ -206322,7 +206337,7 @@ function rewriteRunSpanTrackedReplacePreservingMarkers(paragraphXml, span, stamp
206322
206337
  function visibleTextLength(xml) {
206323
206338
  let len = 0;
206324
206339
  const visibleXml = stripElements(stripElements(xml, "del"), "moveFrom");
206325
- for (const match of visibleXml.matchAll(/<[\w.-]+:t\b[^>]*>([\s\S]*?)<\/[\w.-]+:t>|<[\w.-]+:(tab|br|cr|footnoteReference|endnoteReference)\b[^>]*\/>/g)) {
206340
+ for (const match of visibleXml.matchAll(/<[\w.-]+:t\b[^>]*>([\s\S]*?)<\/[\w.-]+:t>|<[\w.-]+:(tab|br|cr|noBreakHyphen|footnoteReference|endnoteReference)\b[^>]*\/>|<[\w.-]+:noBreakHyphen\b[^>]*>\s*<\/[\w.-]+:noBreakHyphen>/g)) {
206326
206341
  if (match[1] != null) {
206327
206342
  len += decodeXmlText6(match[1]).length;
206328
206343
  continue;
@@ -206655,9 +206670,23 @@ function preserveTextElementAttributes(attributes, text) {
206655
206670
  }
206656
206671
  return `${attributes} xml:space="preserve"`;
206657
206672
  }
206658
- function rewriteCollapsedBoundaryAfterAnchorGapInsert(paragraphXml, runs, startOffset, endOffset, buildContent) {
206673
+ function rewriteCollapsedRunBoundaryInsert(paragraphXml, runs, startOffset, endOffset, buildContent) {
206659
206674
  if (startOffset !== endOffset || runs.length === 0)
206660
206675
  return null;
206676
+ const first = runs[0];
206677
+ if (startOffset === 0) {
206678
+ let beforeControl = first.leadingControlXml != null && first.textStart === 1;
206679
+ if (first.kind === "control" && first.textStart === 0) {
206680
+ const parsed = parsePlainRun(first.xml, 0, first.byteStart, first.byteEnd, {
206681
+ allowReplaceableInlineControls: true
206682
+ });
206683
+ beforeControl = parsed.ok && parsed.run.controlKind != null;
206684
+ }
206685
+ if (beforeControl) {
206686
+ const content = buildContent(first);
206687
+ return `${paragraphXml.slice(0, first.byteStart)}${content}${paragraphXml.slice(first.byteStart)}`;
206688
+ }
206689
+ }
206661
206690
  const closeTagMatch = paragraphXml.match(/<\/[\w.-]+:p>\s*$/);
206662
206691
  if (!closeTagMatch || closeTagMatch.index == null)
206663
206692
  return null;
@@ -214994,6 +215023,12 @@ function runTrackedChangeDecideCommitWithLookupContext(lookupContext, input, xml
214994
215023
  const existingPatch = firstReplacePatch(perPart[partUri]);
214995
215024
  const workingBytes = existingPatch && existingPatch.kind === "replaceBytes" ? existingPatch.bytes : baseBytes;
214996
215025
  let workingXml = TD52.decode(workingBytes);
215026
+ let commentFreeMarkerIndex;
215027
+ const currentCommentMarkerIndex = () => {
215028
+ if (/commentRangeStart|commentRangeEnd|commentReference/.test(workingXml))
215029
+ return;
215030
+ return commentFreeMarkerIndex ?? (commentFreeMarkerIndex = buildCommentMarkerIndex(workingXml));
215031
+ };
214997
215032
  const sortedGroups = [...groups].sort((left, right) => {
214998
215033
  const leftOwnership = left.fragments.some((fragment3) => fragment3.nativeSdtOwnership);
214999
215034
  const rightOwnership = right.fragments.some((fragment3) => fragment3.nativeSdtOwnership);
@@ -215088,7 +215123,8 @@ function runTrackedChangeDecideCommitWithLookupContext(lookupContext, input, xml
215088
215123
  structuralHyperlinkRemovalParts.add(partUri);
215089
215124
  }
215090
215125
  const classification = classifyDroppedCommentMarkers(workingXml, result.deletedRange, {
215091
- preserveAdjacentEndBoundaryWIds
215126
+ preserveAdjacentEndBoundaryWIds,
215127
+ markerIndex: currentCommentMarkerIndex()
215092
215128
  });
215093
215129
  for (const wId of classification.delete) {
215094
215130
  cascadeCommentWIds.add(wId);
@@ -389256,6 +389292,29 @@ function requiredPartBytes(context, partUri) {
389256
389292
  throw new SDCompareError("SOURCE_NOT_COMPLETE", `compare capture could not read required part ${partUri}.`);
389257
389293
  return bytes;
389258
389294
  }
389295
+ function assertInspectableTablePlacement(context) {
389296
+ const partUris = new Set(listSDDocumentSessionInternalStories(context.session).map((story) => story.partUri));
389297
+ for (const partUri of partUris) {
389298
+ const parents = [];
389299
+ let inlineContainer;
389300
+ walkXmlElements(new TextDecoder().decode(requiredPartBytes(context, partUri)), {
389301
+ onOpenTag({ tag }) {
389302
+ const parent = parents.at(-1);
389303
+ if (tag.namespaceUri === WORDPROCESSINGML_NAMESPACE8 && tag.localName === "tbl" && parent?.namespaceUri === WORDPROCESSINGML_NAMESPACE8 && (parent.localName === "p" || parent.localName === "r"))
389304
+ inlineContainer = parent.localName === "p" ? "paragraph" : "run";
389305
+ if (!tag.isSelfClosing)
389306
+ parents.push(tag);
389307
+ },
389308
+ onCloseTag({ tag }) {
389309
+ if (!tag.isSelfClosing)
389310
+ parents.pop();
389311
+ }
389312
+ });
389313
+ if (inlineContainer) {
389314
+ throw new SDCompareError("INVALID_INPUT", `compare capture found an uninspectable WordprocessingML table inside a ${inlineContainer} in ${partUri}. ` + "Tables must be block content; no comparison snapshot was produced.");
389315
+ }
389316
+ }
389317
+ }
389259
389318
  function contentTypeRegistrationForPart(context, partUri) {
389260
389319
  const registry2 = parseContentTypes(new TextDecoder().decode(requiredPartBytes(context, CONTENT_TYPES_URI)));
389261
389320
  if (registry2.parseError)
@@ -389542,6 +389601,7 @@ function captureCompareSnapshotSync(context, options = {}) {
389542
389601
  return projectCompareSnapshot(context, "source-complete", options);
389543
389602
  }
389544
389603
  function projectCompareSnapshot(context, posture, options) {
389604
+ assertInspectableTablePlacement(context);
389545
389605
  const body = projectBody(context);
389546
389606
  const slots = projectSlots(context);
389547
389607
  const { stories, noteParts } = projectStories(context, slots);
@@ -391539,6 +391599,13 @@ function buildCommentApplyPlan(base3, target) {
391539
391599
  }
391540
391600
  function buildExactCommentApplyPlan(base3, target, baseSource, targetSource) {
391541
391601
  const fallback = buildCommentApplyPlan(base3, target);
391602
+ if (fallback.steps.filter((step3) => step3.kind === "create").length > 1) {
391603
+ return {
391604
+ steps: [],
391605
+ partRewrites: [],
391606
+ unsafeReasons: ["multiple comment creations require revision-stable anchor replay"]
391607
+ };
391608
+ }
391542
391609
  const baseById = new Map(base3.map((record3) => [record3.commentId, record3]));
391543
391610
  const targetById = new Map(target.map((record3) => [record3.commentId, record3]));
391544
391611
  const topologyCompatible = base3.length === target.length && base3.every((record3) => {
@@ -395291,7 +395358,11 @@ class V2DiffAdapter {
395291
395358
  base: payload.base.definitions,
395292
395359
  target: payload.target.definitions
395293
395360
  }), canonicalBodyOperations);
395294
- const trackedTablePropertyPlan = tablesChanged && reviewMarkup ? buildTrackedTablePropertyReplayPlan(liveBaseMainDocument, payloadMainDocument.target) : null;
395361
+ const tablePropertyPlan = tablesChanged ? buildTrackedTablePropertyReplayPlan(liveBaseMainDocument, payloadMainDocument.target) : null;
395362
+ if (tablePropertyPlan && this.context.isCollaborativeSession()) {
395363
+ throw diffValidationError("CAPABILITY_UNSUPPORTED", "diff.apply: table property replay is unavailable in a joined collaboration session; use a standalone session for this input. No mutation was performed.", { changedFamilies: ["tables"], unsupportedReason: "collaborative-table-property-replay-unsupported" });
395364
+ }
395365
+ const trackedTablePropertyPlan = reviewMarkup ? tablePropertyPlan : null;
395295
395366
  let trackedTablePlan = tablesChanged && reviewMarkup && !trackedTablePropertyPlan ? buildTrackedTableRowReplayPlan({
395296
395367
  base: liveBaseMainDocument,
395297
395368
  target: payloadMainDocument.target,
@@ -395762,6 +395833,7 @@ function buildCompareApplyEligibility(context, payload, plans, styleChangeMode)
395762
395833
  }
395763
395834
  const tablesChanged = payload.familyPolicy.some((policy) => policy.family === "tables" && policy.applyRequired);
395764
395835
  let wholeMainDirectReplay = false;
395836
+ let tablePropertyReplayRequiresStandalone = false;
395765
395837
  if (tablesChanged) {
395766
395838
  const bodyDeferredToTableReplay = payload.familyPolicy.some((policy) => policy.family === "body" && policy.applyRequired && policy.disposition === "deferred");
395767
395839
  const mainDocument = payload.mainDocument ?? { base: EMPTY_MAIN_DOCUMENT_SOURCE, target: EMPTY_MAIN_DOCUMENT_SOURCE };
@@ -395793,7 +395865,13 @@ function buildCompareApplyEligibility(context, payload, plans, styleChangeMode)
395793
395865
  bodyOperations: trackedBodyOperations,
395794
395866
  allowTopologyReplacement: true
395795
395867
  }) : null;
395796
- if (trackedTablePlan.unsafeReasons.length === 0 && trackedTablePlan.steps.length > 0) {
395868
+ const trackedPropertyPlan = buildTrackedTablePropertyReplayPlan(mainDocument.base, mainDocument.target);
395869
+ tablePropertyReplayRequiresStandalone = trackedPropertyPlan !== null && context.isCollaborativeSession();
395870
+ if (trackedPropertyPlan) {
395871
+ tracked.add("tables");
395872
+ if (bodyDeferredToTableReplay)
395873
+ tracked.add("body");
395874
+ } else if (trackedTablePlan.unsafeReasons.length === 0 && trackedTablePlan.steps.length > 0) {
395797
395875
  tracked.add("tables");
395798
395876
  if (bodyDeferredToTableReplay)
395799
395877
  tracked.add("body");
@@ -395814,6 +395892,15 @@ function buildCompareApplyEligibility(context, payload, plans, styleChangeMode)
395814
395892
  if (metadataPartPlan.rewrites.length > 0)
395815
395893
  direct.add("package-graph");
395816
395894
  const hazards = { direct: [], tracked: [] };
395895
+ if (tablePropertyReplayRequiresStandalone) {
395896
+ const hazard = {
395897
+ code: "family-apply-lane-unavailable",
395898
+ message: "Table property replay is unavailable in a joined collaboration session; use a standalone session for this input.",
395899
+ families: ["tables"]
395900
+ };
395901
+ hazards.direct.push(hazard);
395902
+ hazards.tracked.push(hazard);
395903
+ }
395817
395904
  if (metadataPartPlan.unsafeReasons.length > 0) {
395818
395905
  hazards.direct.push({
395819
395906
  code: "family-apply-lane-unavailable",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdoc/mcp",
3
- "version": "1.7.1-next.5",
3
+ "version": "1.7.1-next.7",
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.20.1-next.5",
27
+ "@superdoc/sdk": "2.20.1-next.7",
28
28
  "debug": "^4.4.3",
29
29
  "zod": "^4.3.6"
30
30
  },
31
31
  "devDependencies": {
32
- "superdoc": "2.23.1-next.5",
33
- "@superdoc/docx-engine": "0.22.1-next.5",
32
+ "superdoc": "2.23.1-next.7",
33
+ "@superdoc/docx-engine": "0.22.1-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",