@superdoc-dev/cli 0.22.2 → 0.23.0

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 CHANGED
@@ -68358,7 +68358,7 @@ var init_remark_gfm_BUJjZJLy_es = __esm(() => {
68358
68358
  emptyOptions2 = {};
68359
68359
  });
68360
68360
 
68361
- // ../../packages/superdoc/dist/chunks/SuperConverter-C3RaGqYm.es.js
68361
+ // ../../packages/superdoc/dist/chunks/SuperConverter-DQRPJhx5.es.js
68362
68362
  function getExtensionConfigField(extension$1, field, context = { name: "" }) {
68363
68363
  const fieldValue = extension$1.config[field];
68364
68364
  if (typeof fieldValue === "function")
@@ -77361,6 +77361,29 @@ function stampImportTrackingAttrs(input) {
77361
77361
  } : null
77362
77362
  };
77363
77363
  }
77364
+ function resolveExportWordId(params3, attrs) {
77365
+ const sourceId = attrs?.sourceId;
77366
+ let exportSourceId;
77367
+ if (typeof sourceId === "string" || typeof sourceId === "number")
77368
+ exportSourceId = sourceId;
77369
+ else if (sourceId === null)
77370
+ exportSourceId = null;
77371
+ else if (sourceId === undefined)
77372
+ exportSourceId = undefined;
77373
+ else
77374
+ exportSourceId = String(sourceId);
77375
+ const logicalId = typeof attrs?.id === "string" ? attrs.id : "";
77376
+ const exportParams = params3;
77377
+ const allocator = exportParams?.converter?.wordIdAllocator;
77378
+ const partPath = exportParams?.currentPartPath || (typeof exportParams?.filename === "string" && exportParams.filename.length > 0 ? `word/${exportParams.filename}` : "word/document.xml");
77379
+ if (allocator)
77380
+ return allocator.allocate({
77381
+ partPath,
77382
+ sourceId: exportSourceId,
77383
+ logicalId
77384
+ });
77385
+ return sourceId || logicalId;
77386
+ }
77364
77387
  function decode$67(params3) {
77365
77388
  const { node: node3 } = params3;
77366
77389
  if (!node3 || !node3.type)
@@ -77379,7 +77402,7 @@ function decode$67(params3) {
77379
77402
  return {
77380
77403
  name: "w:ins",
77381
77404
  attributes: {
77382
- "w:id": resolveExportWordId$1(params3, trackedMark.attrs),
77405
+ "w:id": resolveExportWordId(params3, trackedMark.attrs),
77383
77406
  "w:author": trackedMark.attrs.author,
77384
77407
  "w:authorEmail": trackedMark.attrs.authorEmail,
77385
77408
  "w:date": trackedMark.attrs.date
@@ -77387,29 +77410,6 @@ function decode$67(params3) {
77387
77410
  elements: [translatedTextNode]
77388
77411
  };
77389
77412
  }
77390
- function resolveExportWordId$1(params3, attrs) {
77391
- const sourceId = attrs?.sourceId;
77392
- let exportSourceId;
77393
- if (typeof sourceId === "string" || typeof sourceId === "number")
77394
- exportSourceId = sourceId;
77395
- else if (sourceId === null)
77396
- exportSourceId = null;
77397
- else if (sourceId === undefined)
77398
- exportSourceId = undefined;
77399
- else
77400
- exportSourceId = String(sourceId);
77401
- const logicalId = typeof attrs?.id === "string" ? attrs.id : "";
77402
- const exportParams = params3;
77403
- const allocator = exportParams?.converter?.wordIdAllocator;
77404
- const partPath = exportParams?.currentPartPath || (typeof exportParams?.filename === "string" && exportParams.filename.length > 0 ? `word/${exportParams.filename}` : "word/document.xml");
77405
- if (allocator)
77406
- return allocator.allocate({
77407
- partPath,
77408
- sourceId: exportSourceId,
77409
- logicalId
77410
- });
77411
- return sourceId || logicalId;
77412
- }
77413
77413
  function decode$66(params3) {
77414
77414
  const { node: node3 } = params3;
77415
77415
  if (!node3 || !node3.type)
@@ -77419,15 +77419,14 @@ function decode$66(params3) {
77419
77419
  if (!trackedMark)
77420
77420
  return null;
77421
77421
  node3.marks = marks.filter((m) => m.type !== "trackDelete");
77422
- const translatedTextNode = exportSchemaToJson({
77422
+ const translatedResult = exportSchemaToJson({
77423
77423
  ...params3,
77424
77424
  node: node3
77425
77425
  });
77426
77426
  if (params3.isFinalDoc)
77427
77427
  return null;
77428
- (translatedTextNode.elements || []).filter((n) => n.name === "w:t").forEach((n) => {
77429
- n.name = "w:delText";
77430
- });
77428
+ const translatedNodes = Array.isArray(translatedResult) ? translatedResult : [translatedResult];
77429
+ translatedNodes.forEach(renameTextElementsForDeletion);
77431
77430
  return {
77432
77431
  name: "w:del",
77433
77432
  attributes: {
@@ -77436,32 +77435,9 @@ function decode$66(params3) {
77436
77435
  "w:authorEmail": trackedMark.attrs.authorEmail,
77437
77436
  "w:date": trackedMark.attrs.date
77438
77437
  },
77439
- elements: [translatedTextNode]
77438
+ elements: translatedNodes
77440
77439
  };
77441
77440
  }
77442
- function resolveExportWordId(params3, attrs) {
77443
- const sourceId = attrs?.sourceId;
77444
- let exportSourceId;
77445
- if (typeof sourceId === "string" || typeof sourceId === "number")
77446
- exportSourceId = sourceId;
77447
- else if (sourceId === null)
77448
- exportSourceId = null;
77449
- else if (sourceId === undefined)
77450
- exportSourceId = undefined;
77451
- else
77452
- exportSourceId = String(sourceId);
77453
- const logicalId = typeof attrs?.id === "string" ? attrs.id : "";
77454
- const exportParams = params3;
77455
- const allocator = exportParams?.converter?.wordIdAllocator;
77456
- const partPath = exportParams?.currentPartPath || (typeof exportParams?.filename === "string" && exportParams.filename.length > 0 ? `word/${exportParams.filename}` : "word/document.xml");
77457
- if (allocator)
77458
- return allocator.allocate({
77459
- partPath,
77460
- sourceId: exportSourceId,
77461
- logicalId
77462
- });
77463
- return sourceId || logicalId;
77464
- }
77465
77441
  function decode$65(params3, decodedAttrs = {}) {
77466
77442
  const { node: node3 } = params3 || {};
77467
77443
  if (!node3)
@@ -80861,6 +80837,37 @@ function insertRunPropertiesInOrder(pPr, runProperties) {
80861
80837
  else
80862
80838
  pPr.elements.splice(terminalIdx, 0, runProperties);
80863
80839
  }
80840
+ function appendParagraphMarkDeletion(pPr, markTrackChange, wordId) {
80841
+ if (!pPr || !markTrackChange)
80842
+ return pPr;
80843
+ if (!Array.isArray(pPr.elements))
80844
+ pPr.elements = [];
80845
+ const existingRunProperties = pPr.elements.find((element) => element?.name === "w:rPr");
80846
+ const runProperties = existingRunProperties || {
80847
+ type: "element",
80848
+ name: "w:rPr",
80849
+ elements: []
80850
+ };
80851
+ if (!Array.isArray(runProperties.elements))
80852
+ runProperties.elements = [];
80853
+ if (runProperties.elements.some((element) => element?.name === "w:del"))
80854
+ return pPr;
80855
+ const attributes = { "w:id": String(wordId ?? markTrackChange.sourceId ?? markTrackChange.id ?? "") };
80856
+ if (markTrackChange.author)
80857
+ attributes["w:author"] = markTrackChange.author;
80858
+ if (markTrackChange.authorEmail)
80859
+ attributes["w:authorEmail"] = markTrackChange.authorEmail;
80860
+ if (markTrackChange.date)
80861
+ attributes["w:date"] = markTrackChange.date;
80862
+ runProperties.elements.push({
80863
+ type: "element",
80864
+ name: "w:del",
80865
+ attributes
80866
+ });
80867
+ if (!existingRunProperties)
80868
+ insertRunPropertiesInOrder(pPr, runProperties);
80869
+ return pPr;
80870
+ }
80864
80871
  function prependParagraphSplitInsertion(pPr, insertionElement) {
80865
80872
  if (!pPr || !insertionElement)
80866
80873
  return pPr;
@@ -80915,6 +80922,9 @@ function generateParagraphProperties(params3) {
80915
80922
  if (insertionElement)
80916
80923
  pPr = prependParagraphSplitInsertion(ensureParagraphPropertiesNode(pPr), insertionElement);
80917
80924
  }
80925
+ const markTrackChange = node3.attrs?.markTrackChange;
80926
+ if (!params3?.isFinalDoc && markTrackChange?.type === "paragraphMarkDelete")
80927
+ pPr = appendParagraphMarkDeletion(ensureParagraphPropertiesNode(pPr), markTrackChange, resolveExportWordId(params3, markTrackChange));
80918
80928
  const sectPr = node3.attrs?.paragraphProperties?.sectPr;
80919
80929
  if (sectPr) {
80920
80930
  if (!pPr)
@@ -81047,6 +81057,8 @@ function translateParagraphNode(params3) {
81047
81057
  if (htmlAnnotationChild)
81048
81058
  return htmlAnnotationChild.elements;
81049
81059
  const pPr = generateParagraphProperties(params3);
81060
+ if (params3.isFinalDoc && params3.node?.attrs?.markTrackChange?.type === "paragraphMarkDelete" && !elements.length)
81061
+ return;
81050
81062
  if (pPr)
81051
81063
  elements.unshift(pPr);
81052
81064
  let attributes = {};
@@ -81300,6 +81312,11 @@ function translateTableCell(params3) {
81300
81312
  ...params3,
81301
81313
  tableCell: params3.node
81302
81314
  });
81315
+ if (!elements.length)
81316
+ elements.push({
81317
+ name: "w:p",
81318
+ elements: []
81319
+ });
81303
81320
  const cellProps = generateTableCellProperties(params3.node);
81304
81321
  elements.unshift(cellProps);
81305
81322
  return {
@@ -100782,6 +100799,9 @@ function importCommentData({ docx, editor, converter }) {
100782
100799
  function isReplacementPair(previous$1, current) {
100783
100800
  return previous$1.type !== current.type && previous$1.author === current.author && previous$1.date === current.date;
100784
100801
  }
100802
+ function isSameTypeChainContinuation(previous$1, current) {
100803
+ return previous$1.type === current.type && previous$1.author === current.author && previous$1.date === current.date;
100804
+ }
100785
100805
  function trackedChangeEntryFromElement(element) {
100786
100806
  return {
100787
100807
  type: element.name,
@@ -100820,21 +100840,40 @@ function assignInternalId(element, idMap, context, insideTrackedChange, nextTrac
100820
100840
  const current = trackedChangeEntryFromElement(element);
100821
100841
  const shouldPair = context.replacements === "paired";
100822
100842
  const shouldKeepChildSides = context.lastTrackedChange && isChildReplacementInsideDeletion(context.beforeLastTrackedChange, context.lastTrackedChange, current, nextTrackedChange);
100823
- if (shouldPair && context.lastTrackedChange && !shouldKeepChildSides && isReplacementPair(context.lastTrackedChange, current)) {
100843
+ const canPair = shouldPair && context.lastTrackedChange && !context.lastTrackedChange.chained && !shouldKeepChildSides && isReplacementPair(context.lastTrackedChange, current);
100844
+ const canChain = !canPair && context.lastTrackedChange && context.lastTrackedChange.chainable !== false && isSameTypeChainContinuation(context.lastTrackedChange, current) && !idMap.has(wordId);
100845
+ if (canPair) {
100824
100846
  if (!idMap.has(wordId))
100825
100847
  idMap.set(wordId, context.lastTrackedChange.internalId);
100826
100848
  context.lastTrackedChange = null;
100827
100849
  context.beforeLastTrackedChange = null;
100850
+ } else if (canChain) {
100851
+ const internalId = context.lastTrackedChange.internalId;
100852
+ idMap.set(wordId, internalId);
100853
+ context.beforeLastTrackedChange = context.lastTrackedChange;
100854
+ context.lastTrackedChange = {
100855
+ ...current,
100856
+ internalId,
100857
+ chained: true,
100858
+ chainable: true
100859
+ };
100828
100860
  } else {
100861
+ const wasAlreadyMapped = idMap.has(wordId);
100829
100862
  const internalId = idMap.get(wordId) ?? v4_default();
100830
100863
  idMap.set(wordId, internalId);
100831
100864
  context.beforeLastTrackedChange = context.lastTrackedChange;
100832
100865
  context.lastTrackedChange = {
100833
100866
  ...current,
100834
- internalId
100867
+ internalId,
100868
+ chainable: !wasAlreadyMapped
100835
100869
  };
100836
100870
  }
100837
100871
  }
100872
+ function getParagraphMarkTrackedChangeElement(pElement) {
100873
+ if (pElement?.name !== "w:p")
100874
+ return null;
100875
+ return pElement.elements?.find((el) => el.name === "w:pPr")?.elements?.find((el) => el.name === "w:rPr")?.elements?.find((el) => TRACKED_CHANGE_NAMES.has(el.name)) ?? null;
100876
+ }
100838
100877
  function walkElements(elements, idMap, context, insideTrackedChange = false) {
100839
100878
  if (!Array.isArray(elements))
100840
100879
  return;
@@ -100848,6 +100887,32 @@ function walkElements(elements, idMap, context, insideTrackedChange = false) {
100848
100887
  lastTrackedChange: null,
100849
100888
  replacements: context.replacements
100850
100889
  }, true);
100890
+ } else if (element.name === "w:p" && !insideTrackedChange) {
100891
+ const paragraphMarkElement = getParagraphMarkTrackedChangeElement(element);
100892
+ if (!(paragraphMarkElement && context.lastTrackedChange && isSameTypeChainContinuation(context.lastTrackedChange, trackedChangeEntryFromElement(paragraphMarkElement)))) {
100893
+ context.lastTrackedChange = null;
100894
+ context.beforeLastTrackedChange = null;
100895
+ if (element.elements)
100896
+ walkElements(element.elements, idMap, context, insideTrackedChange);
100897
+ } else {
100898
+ const pPr = element.elements.find((el) => el.name === "w:pPr");
100899
+ const rPr = pPr?.elements?.find((el) => el.name === "w:rPr");
100900
+ assignInternalId(paragraphMarkElement, idMap, context, false, null);
100901
+ if (pPr?.elements) {
100902
+ walkElements(pPr.elements.filter((el) => el !== rPr), idMap, {
100903
+ beforeLastTrackedChange: null,
100904
+ lastTrackedChange: null,
100905
+ replacements: context.replacements
100906
+ }, insideTrackedChange);
100907
+ if (rPr?.elements)
100908
+ walkElements(rPr.elements.filter((el) => el !== paragraphMarkElement), idMap, {
100909
+ beforeLastTrackedChange: null,
100910
+ lastTrackedChange: null,
100911
+ replacements: context.replacements
100912
+ }, insideTrackedChange);
100913
+ }
100914
+ walkElements(element.elements.filter((el) => el !== pPr), idMap, context, insideTrackedChange);
100915
+ }
100851
100916
  } else {
100852
100917
  if (!PAIRING_TRANSPARENT_NAMES.has(element.name)) {
100853
100918
  context.lastTrackedChange = null;
@@ -113315,6 +113380,47 @@ function getTrackedChangeGroupKey(attrs, markType, fallbackId) {
113315
113380
  const sourceId = toNonEmptyString(attrs.sourceId);
113316
113381
  return sourceId ? `word:${markType}:${sourceId}` : fallbackId;
113317
113382
  }
113383
+ function coalesceSameTypeImportedChains(byRawId, segmentsByRawId) {
113384
+ const canonicalKeyByChain = /* @__PURE__ */ new Map;
113385
+ for (const [groupKey, draft] of byRawId) {
113386
+ const id2 = toNonEmptyString(draft.attrs.id);
113387
+ const sourceId = toNonEmptyString(draft.attrs.sourceId);
113388
+ if (!id2 || !sourceId)
113389
+ continue;
113390
+ const isPureInsert = draft.hasInsert && !draft.hasDelete && !draft.hasFormat;
113391
+ const isPureDelete = draft.hasDelete && !draft.hasInsert && !draft.hasFormat;
113392
+ if (!isPureInsert && !isPureDelete)
113393
+ continue;
113394
+ const chainKey = `${isPureInsert ? TrackInsertMarkName : TrackDeleteMarkName}:${id2}`;
113395
+ const canonicalKey = canonicalKeyByChain.get(chainKey);
113396
+ if (!canonicalKey) {
113397
+ canonicalKeyByChain.set(chainKey, groupKey);
113398
+ continue;
113399
+ }
113400
+ if (canonicalKey === groupKey)
113401
+ continue;
113402
+ const canonical = byRawId.get(canonicalKey);
113403
+ if (!canonical)
113404
+ continue;
113405
+ canonical.from = Math.min(canonical.from, draft.from);
113406
+ canonical.to = Math.max(canonical.to, draft.to);
113407
+ for (let i$1 = 0;i$1 < draft.excerptParts.length; i$1 += 1) {
113408
+ const range = draft.excerptRanges[i$1];
113409
+ if (!canonical.excerptRanges.some((counted) => rangesOverlap(counted, range))) {
113410
+ canonical.excerptRanges.push(range);
113411
+ canonical.excerptParts.push(draft.excerptParts[i$1]);
113412
+ }
113413
+ }
113414
+ if (draft.wordRevisionIds)
113415
+ for (const key of Object.keys(draft.wordRevisionIds))
113416
+ canonical.wordRevisionIds = mergeWordRevisionId(canonical.wordRevisionIds, key, draft.wordRevisionIds[key]);
113417
+ const canonicalSegments = segmentsByRawId.get(canonicalKey) ?? [];
113418
+ const draftSegments = segmentsByRawId.get(groupKey) ?? [];
113419
+ segmentsByRawId.set(canonicalKey, canonicalSegments.concat(draftSegments));
113420
+ segmentsByRawId.delete(groupKey);
113421
+ byRawId.delete(groupKey);
113422
+ }
113423
+ }
113318
113424
  function isTrackedMarkName(markType) {
113319
113425
  return markType === "trackInsert" || markType === "trackDelete" || markType === "trackFormat";
113320
113426
  }
@@ -113598,6 +113704,7 @@ function groupTrackedChanges(editor) {
113598
113704
  if (wordRevisionIdKey)
113599
113705
  existing.wordRevisionIds = mergeWordRevisionId(existing.wordRevisionIds, wordRevisionIdKey, wordRevisionId ?? undefined);
113600
113706
  }
113707
+ coalesceSameTypeImportedChains(byRawId, segmentsByRawId);
113601
113708
  const grouped = Array.from(byRawId.values()).map(({ excerptParts, excerptRanges: _excerptRanges, ...change }) => {
113602
113709
  const hasWordSourceId = Boolean(toNonEmptyString(change.attrs.sourceId));
113603
113710
  const rawExcerpt = excerptParts.join("");
@@ -117346,8 +117453,15 @@ var isRegExp = (value) => {
117346
117453
  },
117347
117454
  trackingMarksByType
117348
117455
  };
117349
- }, TRACKABLE_RUN_CONTENT_TYPES, applyTrackedMarkToRunContent = (subElements = [], markType, attrs) => {
117456
+ }, TRACKABLE_RUN_CONTENT_TYPES, TRACKABLE_WHOLE_NODE_TYPES, applyTrackedMarkToRunContent = (subElements = [], markType, attrs) => {
117350
117457
  subElements.forEach((subElement) => {
117458
+ if (subElement && TRACKABLE_WHOLE_NODE_TYPES.has(subElement.type)) {
117459
+ subElement.marks = [...Array.isArray(subElement.marks) ? subElement.marks : [], {
117460
+ type: markType,
117461
+ attrs
117462
+ }];
117463
+ return;
117464
+ }
117351
117465
  subElement.marks = [];
117352
117466
  (Array.isArray(subElement?.content) ? subElement.content : []).forEach((child) => {
117353
117467
  if (!child || !TRACKABLE_RUN_CONTENT_TYPES.has(child.type))
@@ -117373,6 +117487,8 @@ var isRegExp = (value) => {
117373
117487
  return;
117374
117488
  if (node3.name === "w:t")
117375
117489
  node3.name = "w:delText";
117490
+ if (node3.name === "w:instrText")
117491
+ node3.name = "w:delInstrText";
117376
117492
  if (Array.isArray(node3.elements))
117377
117493
  node3.elements.forEach(renameTextElementsForDeletion);
117378
117494
  }, ensureTrackedWrapper = (runs, trackingMarksByType = /* @__PURE__ */ new Map, options = {}) => {
@@ -117884,6 +118000,20 @@ var isRegExp = (value) => {
117884
118000
  schemaNode.attrs.paragraphProperties = inlineParagraphProperties;
117885
118001
  schemaNode.attrs.rsidRDefault = node3.attributes?.["w:rsidRDefault"];
117886
118002
  schemaNode.attrs.filename = filename;
118003
+ const markDeletionElement = pPr?.elements?.find((el) => el.name === "w:rPr")?.elements?.find((el) => el.name === "w:del");
118004
+ if (markDeletionElement) {
118005
+ const markAttributes = markDeletionElement.attributes || {};
118006
+ const { sourceId, logicalId } = resolveTrackedChangeImportIds(params3, markAttributes["w:id"]);
118007
+ schemaNode.attrs.markTrackChange = {
118008
+ type: "paragraphMarkDelete",
118009
+ id: logicalId || (sourceId ? String(sourceId) : ""),
118010
+ sourceId: sourceId ? String(sourceId) : undefined,
118011
+ author: markAttributes["w:author"] || "",
118012
+ authorEmail: markAttributes["w:authorEmail"] || "",
118013
+ date: markAttributes["w:date"] || "",
118014
+ importedAuthor: `${markAttributes["w:author"] || ""} (imported)`
118015
+ };
118016
+ }
117887
118017
  const sectPr = pPr?.elements?.find((el) => el.name === "w:sectPr");
117888
118018
  if (sectPr) {
117889
118019
  schemaNode.attrs.paragraphProperties.sectPr = sectPr;
@@ -123505,7 +123635,7 @@ var isRegExp = (value) => {
123505
123635
  return;
123506
123636
  }
123507
123637
  const fldType = node3.elements?.find((el) => el.name === "w:fldChar")?.attributes?.["w:fldCharType"];
123508
- const instrTextEl = node3.elements?.find((el) => el.name === "w:instrText");
123638
+ const instrTextEl = node3.elements?.find((el) => el.name === "w:instrText" || el.name === "w:delInstrText");
123509
123639
  if (node3.name === "w:fldSimple") {
123510
123640
  const instr = node3.attributes?.["w:instr"];
123511
123641
  if (typeof instr === "string") {
@@ -123747,7 +123877,7 @@ var isRegExp = (value) => {
123747
123877
  const elements = Array.isArray(node3?.elements) ? node3.elements : [];
123748
123878
  const tokens = [];
123749
123879
  elements.forEach((el) => {
123750
- if (el?.name === "w:instrText") {
123880
+ if (el?.name === "w:instrText" || el?.name === "w:delInstrText") {
123751
123881
  const text$2 = (el.elements || []).map((child) => typeof child?.text === "string" ? child.text : "").join("");
123752
123882
  tokens.push({
123753
123883
  type: "text",
@@ -129491,6 +129621,8 @@ var isRegExp = (value) => {
129491
129621
  };
129492
129622
  }, decode$21 = (params3) => {
129493
129623
  const { node: node3 } = params3;
129624
+ if (node3.marks?.find((m) => m.type === "trackDelete"))
129625
+ return translator$59.decode(params3);
129494
129626
  const outputMarks = processOutputMarks(node3.attrs?.marksAsAttrs || []);
129495
129627
  const contentNodes = buildFieldResultRuns(params3, outputMarks);
129496
129628
  const instructionElements = buildInstructionElements(node3.attrs?.instruction, node3.attrs?.instructionTokens);
@@ -136966,7 +137098,7 @@ Docs: https://docs.superdoc.dev/getting-started/fonts`);
136966
137098
  return out;
136967
137099
  }
136968
137100
  return out;
136969
- }, groupedCache, SDT_NODE_NAMES, SDT_BLOCK_NAME = "structuredContentBlock", SDT_INLINE_NAME = "structuredContent", SDT_NODE_TYPES, VALID_CONTROL_TYPES, VALID_LOCK_MODES2, VALID_APPEARANCES, FIELD_LIKE_SDT_TYPES, liveDocumentCountsCache, BIBLIOGRAPHY_NAMESPACE_URI = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", CUSTOM_XML_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml", CUSTOM_XML_PROPS_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps", DEFAULT_SELECTED_STYLE = "/APA.XSL", DEFAULT_STYLE_NAME = "APA", DEFAULT_VERSION = "6", API_TO_OOXML_SOURCE_TYPE, OOXML_TO_API_SOURCE_TYPE, SIMPLE_FIELD_TO_XML_TAG, XML_TAG_TO_SIMPLE_FIELD, import_lib2, FONT_FAMILY_FALLBACKS, DEFAULT_GENERIC_FALLBACK = "sans-serif", DEFAULT_FONT_SIZE_PT = 10, CURRENT_APP_VERSION = "1.45.1", SUPERDOC_DOCUMENT_ORIGIN_PROPERTY = "SuperdocDocumentOrigin", STORED_DOCUMENT_ORIGINS, collectRunDefaultProperties = (runProps, { allowOverrideTypeface = true, allowOverrideSize = true, themeResolver, state }) => {
137101
+ }, groupedCache, SDT_NODE_NAMES, SDT_BLOCK_NAME = "structuredContentBlock", SDT_INLINE_NAME = "structuredContent", SDT_NODE_TYPES, VALID_CONTROL_TYPES, VALID_LOCK_MODES2, VALID_APPEARANCES, FIELD_LIKE_SDT_TYPES, liveDocumentCountsCache, BIBLIOGRAPHY_NAMESPACE_URI = "http://schemas.openxmlformats.org/officeDocument/2006/bibliography", CUSTOM_XML_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml", CUSTOM_XML_PROPS_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps", DEFAULT_SELECTED_STYLE = "/APA.XSL", DEFAULT_STYLE_NAME = "APA", DEFAULT_VERSION = "6", API_TO_OOXML_SOURCE_TYPE, OOXML_TO_API_SOURCE_TYPE, SIMPLE_FIELD_TO_XML_TAG, XML_TAG_TO_SIMPLE_FIELD, import_lib2, FONT_FAMILY_FALLBACKS, DEFAULT_GENERIC_FALLBACK = "sans-serif", DEFAULT_FONT_SIZE_PT = 10, CURRENT_APP_VERSION = "1.45.2", SUPERDOC_DOCUMENT_ORIGIN_PROPERTY = "SuperdocDocumentOrigin", STORED_DOCUMENT_ORIGINS, collectRunDefaultProperties = (runProps, { allowOverrideTypeface = true, allowOverrideSize = true, themeResolver, state }) => {
136970
137102
  if (!runProps?.elements?.length || !state)
136971
137103
  return;
136972
137104
  const fontsNode = runProps.elements.find((el) => el.name === "w:rFonts");
@@ -137000,7 +137132,7 @@ Docs: https://docs.superdoc.dev/getting-started/fonts`);
137000
137132
  state.kern = kernNode.attributes["w:val"];
137001
137133
  }
137002
137134
  }, SuperConverter;
137003
- var init_SuperConverter_C3RaGqYm_es = __esm(() => {
137135
+ var init_SuperConverter_DQRPJhx5_es = __esm(() => {
137004
137136
  init_rolldown_runtime_Bg48TavK_es();
137005
137137
  init_jszip_C49i9kUs_es();
137006
137138
  init_xml_js_CqGKpaft_es();
@@ -141397,6 +141529,7 @@ var init_SuperConverter_C3RaGqYm_es = __esm(() => {
141397
141529
  "link"
141398
141530
  ];
141399
141531
  TRACKABLE_RUN_CONTENT_TYPES = new Set(["text", "noBreakHyphen"]);
141532
+ TRACKABLE_WHOLE_NODE_TYPES = new Set(["crossReference"]);
141400
141533
  validXmlAttributes$12 = [
141401
141534
  createAttributeHandler("w:id", "id"),
141402
141535
  createAttributeHandler("w:date", "date"),
@@ -154100,7 +154233,11 @@ var init_SuperConverter_C3RaGqYm_es = __esm(() => {
154100
154233
  CONSTRUCTIVE_TRACK_CHANGE_ELEMENT_NAMES = new Set(["w:ins", "w:moveTo"]);
154101
154234
  SKIP_FIELD_PROCESSING_NODE_NAMES$1 = new Set(["w:drawing", "w:pict"]);
154102
154235
  FIELD_CONTROL_ELEMENT_NAMES = new Set(["w:fldChar"]);
154103
- INSTRUCTION_ELEMENT_NAMES = new Set(["w:instrText", "w:tab"]);
154236
+ INSTRUCTION_ELEMENT_NAMES = new Set([
154237
+ "w:instrText",
154238
+ "w:delInstrText",
154239
+ "w:tab"
154240
+ ]);
154104
154241
  SKIP_FIELD_PROCESSING_NODE_NAMES = new Set(["w:drawing", "w:pict"]);
154105
154242
  HEADER_FOOTER_FILENAME_PATTERN = /^(header|footer)\d*\.xml$/i;
154106
154243
  CHART_TYPE_MAP = {
@@ -166012,7 +166149,7 @@ var init_SuperConverter_C3RaGqYm_es = __esm(() => {
166012
166149
  };
166013
166150
  });
166014
166151
 
166015
- // ../../packages/superdoc/dist/chunks/create-headless-toolbar-BHTMK7GC.es.js
166152
+ // ../../packages/superdoc/dist/chunks/create-headless-toolbar-pGC1aJVe.es.js
166016
166153
  function parseSizeUnit(val = "0") {
166017
166154
  const length3 = val.toString() || "0";
166018
166155
  const value = Number.parseFloat(length3);
@@ -176833,9 +176970,9 @@ var CSS_DIMENSION_REGEX, DOM_SIZE_UNITS, MARK_KEYS, STEP_OP_CATALOG_UNFROZEN2, P
176833
176970
  }
176834
176971
  };
176835
176972
  };
176836
- var init_create_headless_toolbar_BHTMK7GC_es = __esm(() => {
176973
+ var init_create_headless_toolbar_pGC1aJVe_es = __esm(() => {
176837
176974
  init_rolldown_runtime_Bg48TavK_es();
176838
- init_SuperConverter_C3RaGqYm_es();
176975
+ init_SuperConverter_DQRPJhx5_es();
176839
176976
  init_jszip_C49i9kUs_es();
176840
176977
  init_uuid_B2wVPhPi_es();
176841
176978
  init_constants_D9qj59G2_es();
@@ -226928,7 +227065,7 @@ var init_remark_gfm_DCND_V_3_es = __esm(() => {
226928
227065
  init_remark_gfm_BUJjZJLy_es();
226929
227066
  });
226930
227067
 
226931
- // ../../packages/superdoc/dist/chunks/src-DESpQKJd.es.js
227068
+ // ../../packages/superdoc/dist/chunks/src-DdCAj9Jo.es.js
226932
227069
  function deleteProps(obj, propOrProps) {
226933
227070
  const props = typeof propOrProps === "string" ? [propOrProps] : propOrProps;
226934
227071
  const removeNested = (target, pathParts, index2 = 0) => {
@@ -227072,7 +227209,7 @@ function prosemirrorToYXmlFragment(doc$12, xmlFragment) {
227072
227209
  }
227073
227210
  function getSuperdocVersion() {
227074
227211
  try {
227075
- return "1.45.1";
227212
+ return "1.45.2";
227076
227213
  } catch {
227077
227214
  return "unknown";
227078
227215
  }
@@ -229084,7 +229221,29 @@ function collectSDTNodes(doc$12) {
229084
229221
  });
229085
229222
  return sdtNodes;
229086
229223
  }
229087
- function checkLockViolation(sdtNodes, from$1, to) {
229224
+ function collectPreservedSDTNodes(previousSdtNodes, nextDoc) {
229225
+ const nextNodesById = /* @__PURE__ */ new Map;
229226
+ for (const nextSdt of collectSDTNodes(nextDoc)) {
229227
+ const id2 = nextSdt.node.attrs.id;
229228
+ if (id2 == null)
229229
+ continue;
229230
+ const key2 = String(id2);
229231
+ const matches2 = nextNodesById.get(key2) ?? [];
229232
+ matches2.push(nextSdt.node);
229233
+ nextNodesById.set(key2, matches2);
229234
+ }
229235
+ const preserved = /* @__PURE__ */ new Set;
229236
+ for (const previousSdt of previousSdtNodes) {
229237
+ const id2 = previousSdt.node.attrs.id;
229238
+ if (id2 == null)
229239
+ continue;
229240
+ const matches2 = nextNodesById.get(String(id2));
229241
+ if (matches2?.length === 1 && matches2[0].eq(previousSdt.node))
229242
+ preserved.add(previousSdt);
229243
+ }
229244
+ return preserved;
229245
+ }
229246
+ function checkLockViolation(sdtNodes, from$1, to, preservedSdtNodes) {
229088
229247
  for (const sdt of sdtNodes) {
229089
229248
  if (!(from$1 < sdt.end && to > sdt.pos))
229090
229249
  continue;
@@ -229096,7 +229255,7 @@ function checkLockViolation(sdtNodes, from$1, to) {
229096
229255
  const wouldModifyContent = insideSDT && !containsSDT;
229097
229256
  const isSdtLocked = sdt.lockMode === "sdtLocked" || sdt.lockMode === "sdtContentLocked";
229098
229257
  const isContentLocked = sdt.lockMode === "contentLocked" || sdt.lockMode === "sdtContentLocked";
229099
- if (isSdtLocked && wouldDamageWrapper)
229258
+ if (isSdtLocked && wouldDamageWrapper && !preservedSdtNodes?.has(sdt))
229100
229259
  return {
229101
229260
  blocked: true,
229102
229261
  reason: `Cannot delete SDT wrapper (${sdt.lockMode})`
@@ -229261,10 +229420,11 @@ function createStructuredContentLockPlugin() {
229261
229420
  const sdtNodes = STRUCTURED_CONTENT_LOCK_KEY.getState(state);
229262
229421
  if (sdtNodes.length === 0)
229263
229422
  return true;
229423
+ const preservedSdtNodes = tr.getMeta?.("structuredContentWrapperPreserving") ? collectPreservedSDTNodes(sdtNodes, tr.doc) : undefined;
229264
229424
  for (const step3 of tr.steps) {
229265
229425
  if (step3.from === undefined || step3.to === undefined)
229266
229426
  continue;
229267
- if (checkLockViolation(sdtNodes, step3.from, step3.to).blocked)
229427
+ if (checkLockViolation(sdtNodes, step3.from, step3.to, preservedSdtNodes).blocked)
229268
229428
  return false;
229269
229429
  }
229270
229430
  return true;
@@ -249471,11 +249631,17 @@ function blocksDeleteWrapper(editor, input2, options) {
249471
249631
  };
249472
249632
  checkRevision(editor, options?.expectedRevision);
249473
249633
  const tr = editor.state.tr;
249474
- tr.delete(candidate.pos, candidate.end);
249475
- if (mode === "tracked")
249476
- applyTrackedMutationMeta(tr);
249477
- else
249634
+ if (mode === "tracked" && isParagraphShaped(candidate)) {
249635
+ if (!authorTrackedBlockDeletion(editor, tr, candidate))
249636
+ throw new DocumentApiAdapterError("CAPABILITY_UNAVAILABLE", "blocks.delete could not record a tracked deletion for this block.", { reason: "tracked_authoring_failed" });
249478
249637
  applyDirectMutationMeta(tr);
249638
+ } else {
249639
+ tr.delete(candidate.pos, candidate.end);
249640
+ if (mode === "tracked")
249641
+ applyTrackedMutationMeta(tr);
249642
+ else
249643
+ applyDirectMutationMeta(tr);
249644
+ }
249479
249645
  editor.dispatch(tr);
249480
249646
  clearIndexCache(editor);
249481
249647
  return {
@@ -249484,6 +249650,45 @@ function blocksDeleteWrapper(editor, input2, options) {
249484
249650
  deletedBlock
249485
249651
  };
249486
249652
  }
249653
+ function isParagraphShaped(candidate) {
249654
+ return candidate.node?.type?.name === "paragraph" || candidate.node?.type?.name === "heading";
249655
+ }
249656
+ function authorTrackedBlockDeletion(editor, tr, candidate) {
249657
+ const user = editor.options.user;
249658
+ if (!user)
249659
+ return false;
249660
+ const node3 = candidate.node;
249661
+ if (!node3 || !node3.isTextblock)
249662
+ return false;
249663
+ const id2 = v4_default();
249664
+ const date = (/* @__PURE__ */ new Date()).toISOString();
249665
+ const from$1 = candidate.pos + 1;
249666
+ const to = candidate.pos + node3.nodeSize - 1;
249667
+ if (to > from$1)
249668
+ markDeletion({
249669
+ tr,
249670
+ from: from$1,
249671
+ to,
249672
+ user,
249673
+ date,
249674
+ id: id2
249675
+ });
249676
+ const markedPos = tr.mapping.map(candidate.pos, 1);
249677
+ const markedNode = tr.doc.nodeAt(markedPos);
249678
+ if (!markedNode || !markedNode.isTextblock)
249679
+ return false;
249680
+ tr.setNodeMarkup(markedPos, undefined, {
249681
+ ...markedNode.attrs,
249682
+ markTrackChange: {
249683
+ type: "paragraphMarkDelete",
249684
+ id: id2,
249685
+ author: user.name || "",
249686
+ authorEmail: user.email || "",
249687
+ date
249688
+ }
249689
+ });
249690
+ return true;
249691
+ }
249487
249692
  function hasSectionBreak(candidate) {
249488
249693
  const pPr = candidate.node.attrs?.paragraphProperties;
249489
249694
  return pPr?.sectPr != null && typeof pPr.sectPr === "object";
@@ -259459,6 +259664,13 @@ function executeSdtMutation(editor, target, options, handler2) {
259459
259664
  return buildMutationFailure("NO_OP", "The mutation had no effect.");
259460
259665
  return buildMutationSuccess(target, updatedRef);
259461
259666
  }
259667
+ function executeSdtWrappingMutation(editor, target, options, handler2) {
259668
+ const documentBefore = editor.state.doc;
259669
+ const result = executeSdtMutation(editor, target, options, handler2);
259670
+ if (!options?.dryRun && result.success && editor.state.doc === documentBefore)
259671
+ return buildMutationFailure("NO_OP", "The mutation reported success without changing the document.");
259672
+ return result;
259673
+ }
259462
259674
  function dispatchTransaction$1(editor, tr) {
259463
259675
  if (editor.view?.dispatch) {
259464
259676
  editor.view.dispatch(tr);
@@ -259615,7 +259827,7 @@ function wrapWrapper(editor, input2, options) {
259615
259827
  nodeType: "sdt",
259616
259828
  nodeId: id2
259617
259829
  };
259618
- return executeSdtMutation(editor, input2.target, options, () => {
259830
+ return executeSdtWrappingMutation(editor, input2.target, options, () => {
259619
259831
  const resolved = resolveSdtByTarget(editor.state.doc, input2.target);
259620
259832
  const nodeTypeName = input2.kind === "block" ? SDT_BLOCK_NAME : "structuredContent";
259621
259833
  const nodeType = editor.schema.nodes[nodeTypeName];
@@ -259632,6 +259844,7 @@ function wrapWrapper(editor, input2, options) {
259632
259844
  }, resolved.node);
259633
259845
  const { tr } = editor.state;
259634
259846
  tr.replaceWith(resolved.pos, resolved.pos + resolved.node.nodeSize, wrapperNode);
259847
+ tr.setMeta(STRUCTURED_CONTENT_WRAPPER_PRESERVING_META, true);
259635
259848
  dispatchTransaction$1(editor, tr);
259636
259849
  return wrapperTarget;
259637
259850
  });
@@ -260514,7 +260727,7 @@ function repeatingSectionSetAllowInsertDeleteWrapper(editor, input2, options) {
260514
260727
  function groupWrapWrapper(editor, input2, options) {
260515
260728
  resolveSdtByTarget(editor.state.doc, input2.target);
260516
260729
  const target = input2.target;
260517
- return executeSdtMutation(editor, target, options, () => {
260730
+ return executeSdtWrappingMutation(editor, target, options, () => {
260518
260731
  const resolved = resolveSdtByTarget(editor.state.doc, input2.target);
260519
260732
  const groupNodeType = editor.schema.nodes[SDT_BLOCK_NAME];
260520
260733
  if (!groupNodeType)
@@ -260527,6 +260740,7 @@ function groupWrapWrapper(editor, input2, options) {
260527
260740
  }, resolved.node);
260528
260741
  const { tr } = editor.state;
260529
260742
  tr.replaceWith(resolved.pos, resolved.pos + resolved.node.nodeSize, groupNode);
260743
+ tr.setMeta(STRUCTURED_CONTENT_WRAPPER_PRESERVING_META, true);
260530
260744
  dispatchTransaction$1(editor, tr);
260531
260745
  return {
260532
260746
  kind: "block",
@@ -291421,7 +291635,7 @@ var Node$13 = class Node$14 {
291421
291635
  return !!(node3?.isBlock && node3?.type?.spec?.attrs?.[SD_BLOCK_REV_ATTRIBUTE_NAME]);
291422
291636
  }, nodeNeedsSdBlockId = (node3) => {
291423
291637
  return !node3?.attrs?.[SD_BLOCK_ID_ATTRIBUTE_NAME];
291424
- }, STRUCTURED_CONTENT_LOCK_KEY, SELECT_INLINE_SDT_BEFORE_RUN_START_META = "selectInlineSdtBeforeRunStart", selectInlineSdtBeforeRunStart = () => ({ state, dispatch }) => {
291638
+ }, STRUCTURED_CONTENT_LOCK_KEY, STRUCTURED_CONTENT_WRAPPER_PRESERVING_META = "structuredContentWrapperPreserving", SELECT_INLINE_SDT_BEFORE_RUN_START_META = "selectInlineSdtBeforeRunStart", selectInlineSdtBeforeRunStart = () => ({ state, dispatch }) => {
291425
291639
  const { selection } = state;
291426
291640
  if (!selection.empty)
291427
291641
  return false;
@@ -297747,16 +297961,43 @@ var Node$13 = class Node$14 {
297747
297961
  if (deterministicJson(a2.sourceIds) !== deterministicJson(b$1.sourceIds))
297748
297962
  return false;
297749
297963
  return true;
297750
- }, BODY_STORY, buildReviewGraph = ({ state, story = BODY_STORY, replacementsMode = "paired" }) => {
297964
+ }, BODY_STORY, enumerateParagraphMarkDeletions = (state) => {
297965
+ const doc$12 = state?.doc;
297966
+ if (!doc$12)
297967
+ return [];
297968
+ const out = [];
297969
+ try {
297970
+ doc$12.descendants((node3, pos) => {
297971
+ if (node3.isText)
297972
+ return false;
297973
+ const record = node3?.attrs?.markTrackChange;
297974
+ if (record && record.type === "paragraphMarkDelete" && typeof record.id === "string" && record.id)
297975
+ out.push({
297976
+ id: record.id,
297977
+ from: pos,
297978
+ to: pos + node3.nodeSize,
297979
+ author: record.author || "",
297980
+ authorEmail: record.authorEmail || "",
297981
+ authorImage: record.authorImage || "",
297982
+ date: record.date || "",
297983
+ subtype: "paragraph-mark-deletion"
297984
+ });
297985
+ });
297986
+ } catch {
297987
+ return out;
297988
+ }
297989
+ return out;
297990
+ }, buildReviewGraph = ({ state, story = BODY_STORY, replacementsMode = "paired" }) => {
297751
297991
  return buildGraphFromSpans({
297752
297992
  spans: enumerateTrackedMarkSpans(state),
297753
297993
  structuralChanges: enumerateStructuralRowChanges(state),
297754
297994
  pprChanges: enumeratePprChanges(state),
297995
+ paragraphMarkChanges: enumerateParagraphMarkDeletions(state),
297755
297996
  doc: state?.doc ?? null,
297756
297997
  story,
297757
297998
  replacementsMode
297758
297999
  });
297759
- }, buildGraphFromSpans = ({ spans, structuralChanges = [], pprChanges = [], doc: doc$12, story, replacementsMode }) => {
298000
+ }, buildGraphFromSpans = ({ spans, structuralChanges = [], pprChanges = [], paragraphMarkChanges = [], doc: doc$12, story, replacementsMode }) => {
297760
298001
  const mergedSegments = mergeAdjacentSpans(spans.map((span) => ({
297761
298002
  attrs: readTrackedAttrs(span.mark, span.mark.type.name),
297762
298003
  span
@@ -297850,6 +298091,24 @@ var Node$13 = class Node$14 {
297850
298091
  changes.set(logical.id, logical);
297851
298092
  appendToMap(byRevisionGroupId, logical.revisionGroupId, logical.id);
297852
298093
  }
298094
+ for (const mark2 of paragraphMarkChanges) {
298095
+ if (changes.has(mark2.id))
298096
+ continue;
298097
+ const logical = buildParagraphMarkLogicalChange({
298098
+ mark: mark2,
298099
+ doc: doc$12,
298100
+ story
298101
+ });
298102
+ if (!logical)
298103
+ continue;
298104
+ const internalKey = `paragraphmark:${mark2.from}`;
298105
+ if (changes.has(internalKey))
298106
+ continue;
298107
+ changes.set(internalKey, logical);
298108
+ if (logical.id && logical.id !== internalKey && !changes.has(logical.id))
298109
+ changes.set(logical.id, logical);
298110
+ appendToMap(byRevisionGroupId, logical.revisionGroupId, logical.id);
298111
+ }
297853
298112
  const segments = mergedSegments.slice().sort((a2, b$1) => a2.from - b$1.from || a2.to - b$1.to);
297854
298113
  const graph = {
297855
298114
  changes,
@@ -298188,6 +298447,83 @@ var Node$13 = class Node$14 {
298188
298447
  enumerable: false
298189
298448
  });
298190
298449
  return logical;
298450
+ }, buildParagraphMarkLogicalChange = ({ mark: mark2, doc: doc$12, story }) => {
298451
+ const from$1 = mark2.from;
298452
+ const to = mark2.to;
298453
+ if (!(from$1 < to))
298454
+ return null;
298455
+ const side = SegmentSide.Deleted;
298456
+ const attrs = {
298457
+ id: mark2.id,
298458
+ revisionGroupId: mark2.id,
298459
+ splitFromId: "",
298460
+ changeType: CanonicalChangeType.Deletion,
298461
+ replacementGroupId: "",
298462
+ replacementSideId: "",
298463
+ overlapParentId: "",
298464
+ sourceIds: {},
298465
+ sourceId: "",
298466
+ importedAuthor: "",
298467
+ origin: "",
298468
+ author: mark2.author,
298469
+ authorId: "",
298470
+ authorEmail: mark2.authorEmail,
298471
+ authorImage: mark2.authorImage,
298472
+ date: mark2.date,
298473
+ markType: "",
298474
+ side,
298475
+ subtype: mark2.subtype,
298476
+ explicitChangeType: CanonicalChangeType.Deletion,
298477
+ hasReviewMetadata: true
298478
+ };
298479
+ const segments = [{
298480
+ segmentId: `${mark2.id}:paragraphmark:${from$1}:${to}:0`,
298481
+ changeId: mark2.id,
298482
+ markType: "",
298483
+ side,
298484
+ from: from$1,
298485
+ to,
298486
+ text: "",
298487
+ mark: null,
298488
+ markRuns: [],
298489
+ attrs,
298490
+ parentId: "",
298491
+ parentSide: "",
298492
+ overlapRole: "standalone",
298493
+ paragraphMarkChange: true
298494
+ }];
298495
+ const logical = {
298496
+ id: mark2.id,
298497
+ type: CanonicalChangeType.Deletion,
298498
+ subtype: mark2.subtype,
298499
+ state: "open",
298500
+ segments,
298501
+ coverageSegments: [...segments],
298502
+ insertedSegments: [],
298503
+ deletedSegments: [...segments],
298504
+ formattingSegments: [],
298505
+ replacement: null,
298506
+ author: mark2.author,
298507
+ authorId: "",
298508
+ authorEmail: mark2.authorEmail,
298509
+ authorImage: mark2.authorImage,
298510
+ date: mark2.date,
298511
+ sourceIds: {},
298512
+ revisionGroupId: mark2.id,
298513
+ splitFromId: "",
298514
+ sourcePlatform: "",
298515
+ story,
298516
+ parent: null,
298517
+ children: [],
298518
+ before: [],
298519
+ after: [],
298520
+ excerpt: ""
298521
+ };
298522
+ Object.defineProperty(logical, "paragraphMarkChange", {
298523
+ value: mark2,
298524
+ enumerable: false
298525
+ });
298526
+ return logical;
298191
298527
  }, aggregateSourceIds = (segments) => {
298192
298528
  const out = {};
298193
298529
  const sorted = [...segments].sort((a2, b$1) => {
@@ -301339,7 +301675,7 @@ var Node$13 = class Node$14 {
301339
301675
  };
301340
301676
  }
301341
301677
  touched.add(change.id);
301342
- if (isFull && !change.pprChange)
301678
+ if (isFull && !change.pprChange && !change.paragraphMarkChange)
301343
301679
  for (const segment of change.segments)
301344
301680
  resolvedRanges.push({
301345
301681
  from: segment.from,
@@ -301358,6 +301694,18 @@ var Node$13 = class Node$14 {
301358
301694
  ok: false,
301359
301695
  failure: pprResult.failure
301360
301696
  };
301697
+ } else if (change.paragraphMarkChange) {
301698
+ const markResult = planParagraphMarkDecision({
301699
+ ops,
301700
+ change,
301701
+ decision,
301702
+ retired
301703
+ });
301704
+ if (!markResult.ok)
301705
+ return {
301706
+ ok: false,
301707
+ failure: markResult.failure
301708
+ };
301361
301709
  } else if (change.type === CanonicalChangeType.Structural) {
301362
301710
  const structuralResult = planStructuralDecision({
301363
301711
  ops,
@@ -301585,8 +301933,15 @@ var Node$13 = class Node$14 {
301585
301933
  cause: `accept-deletion:${change.id}`
301586
301934
  });
301587
301935
  }
301588
- if (isFull)
301936
+ if (isFull) {
301937
+ pushParagraphMarkOps({
301938
+ ops,
301939
+ change,
301940
+ decision: "accept",
301941
+ ranges: ranges$1
301942
+ });
301589
301943
  retired.add(change.id);
301944
+ }
301590
301945
  return;
301591
301946
  }
301592
301947
  const ranges = isFull ? change.deletedSegments.map((s2) => ({
@@ -301601,8 +301956,26 @@ var Node$13 = class Node$14 {
301601
301956
  changeId: change.id,
301602
301957
  side: SegmentSide.Deleted
301603
301958
  });
301604
- if (isFull)
301959
+ if (isFull) {
301960
+ pushParagraphMarkOps({
301961
+ ops,
301962
+ change,
301963
+ decision: "reject",
301964
+ ranges
301965
+ });
301605
301966
  retired.add(change.id);
301967
+ }
301968
+ }, pushParagraphMarkOps = ({ ops, change, decision, ranges }) => {
301969
+ const anchor = ranges[0];
301970
+ if (!anchor)
301971
+ return;
301972
+ ops.push({
301973
+ kind: decision === "accept" ? "collapseParagraphMark" : "clearParagraphMark",
301974
+ from: anchor.from,
301975
+ to: anchor.to,
301976
+ changeId: change.id,
301977
+ side: SegmentSide.Deleted
301978
+ });
301606
301979
  }, planStructuralDecision = ({ ops, change, decision, removedRanges, retired }) => {
301607
301980
  const structural = change.structural;
301608
301981
  if (!structural)
@@ -301659,6 +302032,22 @@ var Node$13 = class Node$14 {
301659
302032
  });
301660
302033
  retired.add(change.id);
301661
302034
  return { ok: true };
302035
+ }, planParagraphMarkDecision = ({ ops, change, decision, retired }) => {
302036
+ const mark2 = change.paragraphMarkChange;
302037
+ if (!mark2)
302038
+ return {
302039
+ ok: false,
302040
+ failure: failure$3("CAPABILITY_UNAVAILABLE", `change "${change.id}" is not a paragraph-mark deletion.`)
302041
+ };
302042
+ ops.push({
302043
+ kind: decision === "accept" ? "collapseParagraphMark" : "clearParagraphMark",
302044
+ from: mark2.from,
302045
+ to: mark2.to,
302046
+ changeId: change.id,
302047
+ side: SegmentSide.Deleted
302048
+ });
302049
+ retired.add(change.id);
302050
+ return { ok: true };
301662
302051
  }, planReplacementDecision = ({ ops, graph, change, decision, removedRanges, retired }) => {
301663
302052
  const inserted = change.insertedSegments;
301664
302053
  const deleted = change.deletedSegments;
@@ -302100,6 +302489,25 @@ var Node$13 = class Node$14 {
302100
302489
  };
302101
302490
  }
302102
302491
  return null;
302492
+ }, findParagraphMarkChangeAt = (tr, pos, changeId) => {
302493
+ const carries = (node3) => node3?.attrs?.markTrackChange?.id === changeId;
302494
+ const clamped = Math.max(0, Math.min(pos, tr.doc.content.size));
302495
+ const block = findTextblockAt(tr.doc, clamped);
302496
+ if (block && carries(block.node))
302497
+ return block;
302498
+ let found2 = null;
302499
+ tr.doc.descendants((node3, nodePos) => {
302500
+ if (found2)
302501
+ return false;
302502
+ if (node3.isTextblock && carries(node3)) {
302503
+ found2 = {
302504
+ pos: nodePos,
302505
+ node: node3
302506
+ };
302507
+ return false;
302508
+ }
302509
+ });
302510
+ return found2;
302103
302511
  }, rejectParagraphSplitAt = (tr, from$1, anchor = "inserted") => {
302104
302512
  const block = findTextblockAt(tr.doc, from$1);
302105
302513
  if (!block)
@@ -302116,6 +302524,7 @@ var Node$13 = class Node$14 {
302116
302524
  const markOps = sortedOps.filter((op) => op.kind !== "removeContent");
302117
302525
  const contentOps = sortedOps.filter((op) => op.kind === "removeContent").reverse();
302118
302526
  const splitJoinOps = sortedOps.filter((op) => op.kind === "rejectParagraphSplit").reverse();
302527
+ const paragraphMarkOps = sortedOps.filter((op) => op.kind === "collapseParagraphMark").reverse();
302119
302528
  try {
302120
302529
  for (const op of markOps) {
302121
302530
  if (op.kind === "removeMark" && op.mark) {
@@ -302160,6 +302569,15 @@ var Node$13 = class Node$14 {
302160
302569
  });
302161
302570
  continue;
302162
302571
  }
302572
+ if (op.kind === "clearParagraphMark") {
302573
+ const target = findParagraphMarkChangeAt(tr, tr.mapping.map(op.from, 1), op.changeId);
302574
+ if (target)
302575
+ tr.setNodeMarkup(target.pos, undefined, {
302576
+ ...target.node.attrs,
302577
+ markTrackChange: null
302578
+ });
302579
+ continue;
302580
+ }
302163
302581
  if (op.kind === "resolvePprChange") {
302164
302582
  const mappedFrom = tr.mapping.map(op.from, 1);
302165
302583
  const node3 = tr.doc.nodeAt(mappedFrom);
@@ -302191,6 +302609,19 @@ var Node$13 = class Node$14 {
302191
302609
  for (const op of splitJoinOps)
302192
302610
  if (!rejectParagraphSplitAt(tr, tr.mapping.map(op.from, 1), op.anchor))
302193
302611
  throw new Error(`could not join paragraph split for tracked change "${op.changeId ?? ""}".`);
302612
+ for (const op of paragraphMarkOps) {
302613
+ const target = findParagraphMarkChangeAt(tr, tr.mapping.map(op.from, 1), op.changeId);
302614
+ if (!target)
302615
+ continue;
302616
+ tr.setNodeMarkup(target.pos, undefined, {
302617
+ ...target.node.attrs,
302618
+ markTrackChange: null
302619
+ });
302620
+ const joinPos = target.pos + tr.doc.nodeAt(target.pos).nodeSize;
302621
+ if (joinPos <= 0 || joinPos >= tr.doc.content.size || !canJoin(tr.doc, joinPos))
302622
+ continue;
302623
+ tr.join(joinPos);
302624
+ }
302194
302625
  } catch (error3) {
302195
302626
  return {
302196
302627
  ok: false,
@@ -306421,7 +306852,7 @@ var Node$13 = class Node$14 {
306421
306852
  domAvailabilityCache = false;
306422
306853
  return false;
306423
306854
  }
306424
- }, summaryVersion = "1.45.1", nodeKeys, markKeys, transformListsInCopiedContent = (html3) => {
306855
+ }, summaryVersion = "1.45.2", nodeKeys, markKeys, transformListsInCopiedContent = (html3) => {
306425
306856
  const container = document.createElement("div");
306426
306857
  container.innerHTML = html3;
306427
306858
  const result = [];
@@ -307607,7 +308038,7 @@ var Node$13 = class Node$14 {
307607
308038
  return () => {};
307608
308039
  const handle3 = setInterval(callback, intervalMs);
307609
308040
  return () => clearInterval(handle3);
307610
- }, HISTORY_UNSAFE_OPS, CANONICAL_COMMENT_IGNORED_KEYS, INITIAL_HASH, ROUND_CONSTANTS, V1_COVERAGE, V2_COVERAGE, SNAPSHOT_VERSION_V2 = "sd-diff-snapshot/v2", PAYLOAD_VERSION_V1 = "sd-diff-payload/v1", PAYLOAD_VERSION_V2 = "sd-diff-payload/v2", ENGINE_ID = "super-editor", STAGED_CONVERTER_KEYS, DiffServiceError, TC_LEVEL_MIN = 1, TC_LEVEL_MAX = 9, ALLOWED_WRAP_ATTRS, WRAP_TYPES_SUPPORTING_SIDE, WRAP_TYPES_SUPPORTING_DISTANCES, RELATIVE_HEIGHT_MIN = 0, RELATIVE_HEIGHT_MAX = 4294967295, FORBIDDEN_RAW_PATCH_NAMES, CONTROL_TYPE_SDT_PR_ELEMENTS, DEFAULT_CHECKBOX_SYMBOL_FONT2 = "MS Gothic", DEFAULT_CHECKBOX_CHECKED_HEX2 = "2612", DEFAULT_CHECKBOX_UNCHECKED_HEX2 = "2610", VARIANT_ORDER, KIND_ORDER, HEADER_RELATIONSHIP_TYPE3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", FOOTER_RELATIONSHIP_TYPE3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", DOCUMENT_RELS_PATH2 = "word/_rels/document.xml.rels", HEADER_FILE_PATTERN2, FOOTER_FILE_PATTERN2, BOOKMARK_SCAN_REVISION_PREFIX = "bookmark-scan:", SETTINGS_PART, VALID_DISPLAYS, REFERENCE_BLOCK_PREFIX, CAPTION_STYLE_NAMES, CAPTION_PARAGRAPH_STYLE_ID = "Caption", CAPTION_FORMAT_TO_OOXML, DOCUMENT_STAT_FIELD_TYPES, TOA_LEADER_REVERSE_MAP, EDGE_NODE_TYPES, CONTENT_TYPES_PART_ID = "[Content_Types].xml", CONTENT_TYPES_NS = "http://schemas.openxmlformats.org/package/2006/content-types", contentTypesPartDescriptor, empty_exports, init_empty, CURRENT_APP_VERSION2 = "1.45.1", PIXELS_PER_INCH2 = 96, MAX_HEIGHT_BUFFER_PX = 50, MAX_WIDTH_BUFFER_PX = 20, TRACKED_REVIEW_MARK_NAMES2, isTrackedReviewMark = (mark2) => Boolean(mark2?.type?.name && TRACKED_REVIEW_MARK_NAMES2.has(mark2.type.name)), trackedReviewMarkKey = (mark2) => {
308041
+ }, HISTORY_UNSAFE_OPS, CANONICAL_COMMENT_IGNORED_KEYS, INITIAL_HASH, ROUND_CONSTANTS, V1_COVERAGE, V2_COVERAGE, SNAPSHOT_VERSION_V2 = "sd-diff-snapshot/v2", PAYLOAD_VERSION_V1 = "sd-diff-payload/v1", PAYLOAD_VERSION_V2 = "sd-diff-payload/v2", ENGINE_ID = "super-editor", STAGED_CONVERTER_KEYS, DiffServiceError, TC_LEVEL_MIN = 1, TC_LEVEL_MAX = 9, ALLOWED_WRAP_ATTRS, WRAP_TYPES_SUPPORTING_SIDE, WRAP_TYPES_SUPPORTING_DISTANCES, RELATIVE_HEIGHT_MIN = 0, RELATIVE_HEIGHT_MAX = 4294967295, FORBIDDEN_RAW_PATCH_NAMES, CONTROL_TYPE_SDT_PR_ELEMENTS, DEFAULT_CHECKBOX_SYMBOL_FONT2 = "MS Gothic", DEFAULT_CHECKBOX_CHECKED_HEX2 = "2612", DEFAULT_CHECKBOX_UNCHECKED_HEX2 = "2610", VARIANT_ORDER, KIND_ORDER, HEADER_RELATIONSHIP_TYPE3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", FOOTER_RELATIONSHIP_TYPE3 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", DOCUMENT_RELS_PATH2 = "word/_rels/document.xml.rels", HEADER_FILE_PATTERN2, FOOTER_FILE_PATTERN2, BOOKMARK_SCAN_REVISION_PREFIX = "bookmark-scan:", SETTINGS_PART, VALID_DISPLAYS, REFERENCE_BLOCK_PREFIX, CAPTION_STYLE_NAMES, CAPTION_PARAGRAPH_STYLE_ID = "Caption", CAPTION_FORMAT_TO_OOXML, DOCUMENT_STAT_FIELD_TYPES, TOA_LEADER_REVERSE_MAP, EDGE_NODE_TYPES, CONTENT_TYPES_PART_ID = "[Content_Types].xml", CONTENT_TYPES_NS = "http://schemas.openxmlformats.org/package/2006/content-types", contentTypesPartDescriptor, empty_exports, init_empty, CURRENT_APP_VERSION2 = "1.45.2", PIXELS_PER_INCH2 = 96, MAX_HEIGHT_BUFFER_PX = 50, MAX_WIDTH_BUFFER_PX = 20, TRACKED_REVIEW_MARK_NAMES2, isTrackedReviewMark = (mark2) => Boolean(mark2?.type?.name && TRACKED_REVIEW_MARK_NAMES2.has(mark2.type.name)), trackedReviewMarkKey = (mark2) => {
307611
308042
  if (!isTrackedReviewMark(mark2))
307612
308043
  return null;
307613
308044
  const id2 = typeof mark2.attrs?.id === "string" ? mark2.attrs.id : "";
@@ -328494,13 +328925,13 @@ menclose::after {
328494
328925
  return;
328495
328926
  console.log(...args$1);
328496
328927
  }, HEADER_FOOTER_INIT_BUDGET_MS = 200, MAX_ZOOM_WARNING_THRESHOLD = 10, MAX_SELECTION_RECTS_PER_USER = 100, SEMANTIC_RESIZE_DEBOUNCE_MS = 120, MIN_SEMANTIC_CONTENT_WIDTH_PX = 1, GLOBAL_PERFORMANCE, PresentationEditor, ICONS, TEXTS, tableActionsOptions, TRACKED_MARK_NAMES;
328497
- var init_src_DESpQKJd_es = __esm(() => {
328928
+ var init_src_DdCAj9Jo_es = __esm(() => {
328498
328929
  init_rolldown_runtime_Bg48TavK_es();
328499
- init_SuperConverter_C3RaGqYm_es();
328930
+ init_SuperConverter_DQRPJhx5_es();
328500
328931
  init_jszip_C49i9kUs_es();
328501
328932
  init_xml_js_CqGKpaft_es();
328502
328933
  init_uuid_B2wVPhPi_es();
328503
- init_create_headless_toolbar_BHTMK7GC_es();
328934
+ init_create_headless_toolbar_pGC1aJVe_es();
328504
328935
  init_constants_D9qj59G2_es();
328505
328936
  init_unified_BDuVPlMu_es();
328506
328937
  init_remark_gfm_BUJjZJLy_es();
@@ -338186,6 +338617,11 @@ ${err.toString()}`);
338186
338617
  attributes: { rendered: false },
338187
338618
  filename: { rendered: false },
338188
338619
  paragraphProperties: { rendered: false },
338620
+ markTrackChange: {
338621
+ default: null,
338622
+ rendered: false,
338623
+ keepOnSplit: false
338624
+ },
338189
338625
  pageBreakSource: { rendered: false },
338190
338626
  tocSourceId: { rendered: false },
338191
338627
  sectionMargins: { rendered: false },
@@ -371820,11 +372256,11 @@ function print() { __p += __j.call(arguments, '') }
371820
372256
  ]);
371821
372257
  });
371822
372258
 
371823
- // ../../packages/superdoc/dist/chunks/create-super-doc-ui-DEUyIO6F.es.js
372259
+ // ../../packages/superdoc/dist/chunks/create-super-doc-ui-DFLkPFF8.es.js
371824
372260
  var DEFAULT_TEXT_ALIGN_OPTIONS, DEFAULT_LINE_HEIGHT_OPTIONS, DEFAULT_ZOOM_OPTIONS, DEFAULT_DOCUMENT_MODE_OPTIONS, DEFAULT_FONT_SIZE_OPTIONS, headlessToolbarConstants, MOD_ALIASES, ALT_ALIASES, CTRL_ALIASES, SHIFT_ALIASES, BUILTIN_CONTEXT_MENU_GROUPS, BUILTIN_GROUP_ORDER, RESERVED_PROXY_PROPERTY_NAMES, ALL_TOOLBAR_COMMAND_IDS, EMPTY_ACTIVE_IDS, FONT_SIZE_OPTIONS;
371825
- var init_create_super_doc_ui_DEUyIO6F_es = __esm(() => {
371826
- init_SuperConverter_C3RaGqYm_es();
371827
- init_create_headless_toolbar_BHTMK7GC_es();
372261
+ var init_create_super_doc_ui_DFLkPFF8_es = __esm(() => {
372262
+ init_SuperConverter_DQRPJhx5_es();
372263
+ init_create_headless_toolbar_pGC1aJVe_es();
371828
372264
  DEFAULT_TEXT_ALIGN_OPTIONS = [
371829
372265
  {
371830
372266
  label: "Left",
@@ -372115,15 +372551,15 @@ var init_zipper_BxRAi0_5_es = __esm(() => {
372115
372551
 
372116
372552
  // ../../packages/superdoc/dist/super-editor.es.js
372117
372553
  var init_super_editor_es = __esm(() => {
372118
- init_src_DESpQKJd_es();
372119
- init_SuperConverter_C3RaGqYm_es();
372554
+ init_src_DdCAj9Jo_es();
372555
+ init_SuperConverter_DQRPJhx5_es();
372120
372556
  init_jszip_C49i9kUs_es();
372121
372557
  init_xml_js_CqGKpaft_es();
372122
- init_create_headless_toolbar_BHTMK7GC_es();
372558
+ init_create_headless_toolbar_pGC1aJVe_es();
372123
372559
  init_constants_D9qj59G2_es();
372124
372560
  init_unified_BDuVPlMu_es();
372125
372561
  init_DocxZipper_BzS208BW_es();
372126
- init_create_super_doc_ui_DEUyIO6F_es();
372562
+ init_create_super_doc_ui_DFLkPFF8_es();
372127
372563
  init_ui_CGB3qmy3_es();
372128
372564
  init_eventemitter3_UwU_CLPU_es();
372129
372565
  init_errors_C_DoKMoN_es();
@@ -693454,6 +693890,112 @@ async function runDeleteText(doc3, args3) {
693454
693890
  return failedReceipt("delete_text", err, pre);
693455
693891
  }
693456
693892
  }
693893
+ async function runDeleteBlocks(doc3, args3) {
693894
+ const domains = new Set(["blocks", "trackedChanges"]);
693895
+ for (const selector of args3.selectors) {
693896
+ for (const domain2 of snapshotDomainsForSelector(selector))
693897
+ domains.add(domain2);
693898
+ }
693899
+ const pre = await buildDocumentSnapshot(doc3, { includeDomains: [...domains] });
693900
+ try {
693901
+ if (args3.selectors.length === 0) {
693902
+ return failedReceipt("delete_blocks", new Error("selectors must be non-empty"), pre);
693903
+ }
693904
+ const deleteFn = maybeMethod2(doc3, ["blocks", "delete"]);
693905
+ if (!deleteFn) {
693906
+ throw new SuperDocCliError("doc.blocks.delete is not available on the document handle.", {
693907
+ code: "TOOL_DISPATCH_NOT_FOUND"
693908
+ });
693909
+ }
693910
+ const targets = [];
693911
+ const unresolved = [];
693912
+ const wrongShape = [];
693913
+ const seen = new Set;
693914
+ for (const selector of args3.selectors) {
693915
+ const target2 = selectorToBlockTarget(selector, pre);
693916
+ if (!target2) {
693917
+ unresolved.push(selector);
693918
+ continue;
693919
+ }
693920
+ if (!DELETABLE_BLOCK_NODE_TYPES3.has(target2.nodeType)) {
693921
+ wrongShape.push({ selector, nodeType: target2.nodeType });
693922
+ continue;
693923
+ }
693924
+ if (seen.has(target2.nodeId))
693925
+ continue;
693926
+ seen.add(target2.nodeId);
693927
+ targets.push({ selector, nodeId: target2.nodeId, nodeType: target2.nodeType });
693928
+ }
693929
+ const errors2 = [];
693930
+ for (const selector of unresolved) {
693931
+ errors2.push({
693932
+ code: "ACTION_FAILED",
693933
+ message: `selector did not resolve to a unique body block: ${JSON.stringify(selector)}`,
693934
+ recovery: { kind: "reinspect" }
693935
+ });
693936
+ }
693937
+ for (const entry of wrongShape) {
693938
+ errors2.push({
693939
+ code: "INVALID_ARGUMENT",
693940
+ message: `delete_blocks removes paragraph-shaped blocks (list items, paragraphs, headings); ` + `${JSON.stringify(entry.selector)} resolved to a "${entry.nodeType}"` + (entry.nodeType === "table" ? " — use delete_table for a whole table." : "."),
693941
+ recovery: { kind: "reinspect" }
693942
+ });
693943
+ }
693944
+ if (targets.length === 0) {
693945
+ return {
693946
+ status: "failed",
693947
+ intent: "delete_blocks",
693948
+ preSnapshot: { revision: pre.revision, counts: pre.counts },
693949
+ selectedTargets: [],
693950
+ executedOperations: [],
693951
+ verification: [],
693952
+ errors: errors2
693953
+ };
693954
+ }
693955
+ const changeMode = parseChangeMode4(args3.changeMode);
693956
+ const executedOperations = [];
693957
+ const deleted = [];
693958
+ for (const target2 of targets) {
693959
+ try {
693960
+ const result2 = await deleteFn({
693961
+ target: { kind: "block", nodeType: target2.nodeType, nodeId: target2.nodeId },
693962
+ ...changeMode ? { changeMode } : {}
693963
+ });
693964
+ executedOperations.push({ operationId: "doc.blocks.delete", result: compactOpResult(result2) });
693965
+ deleted.push({ nodeId: target2.nodeId, nodeType: target2.nodeType });
693966
+ } catch (err) {
693967
+ errors2.push({
693968
+ code: "ACTION_FAILED",
693969
+ message: `blocks.delete failed for ${target2.nodeType} ${target2.nodeId}: ${err instanceof Error ? err.message : String(err)}`,
693970
+ recovery: { kind: "reinspect" }
693971
+ });
693972
+ }
693973
+ }
693974
+ const post = await buildDocumentSnapshot(doc3, { includeDomains: [...domains] });
693975
+ const checks2 = changeMode === "tracked" ? [{ kind: "tracked-change-count-delta", delta: deleted.length }] : [...new Set(deleted.map((entry) => entry.nodeType))].map((nodeType2) => ({
693976
+ kind: "block-count-delta",
693977
+ nodeType: nodeType2,
693978
+ delta: -deleted.filter((entry) => entry.nodeType === nodeType2).length
693979
+ }));
693980
+ const verification = evaluateChecks(pre, post, checks2);
693981
+ const allApplied = deleted.length === args3.selectors.length && errors2.length === 0;
693982
+ const verified = verification.every((v) => v.passed);
693983
+ return {
693984
+ status: !verified || deleted.length === 0 ? "failed" : allApplied ? "ok" : "partial",
693985
+ intent: `delete_blocks: ${deleted.length} block(s)`,
693986
+ preSnapshot: { revision: pre.revision, counts: pre.counts },
693987
+ postSnapshot: { revision: post.revision, counts: post.counts },
693988
+ selectedTargets: targets.map((target2) => ({ selector: target2.selector, matched: [target2.nodeId] })),
693989
+ executedOperations,
693990
+ verification,
693991
+ deletedBlocks: deleted,
693992
+ ...errors2.length ? { errors: errors2 } : {},
693993
+ ...errors2.length ? { nextStep: "Re-inspect the document and retry the selectors that did not resolve to one block." } : {}
693994
+ };
693995
+ } catch (err) {
693996
+ return failedReceipt("delete_blocks", err, pre);
693997
+ }
693998
+ }
693457
693999
  async function runAppendList(doc3, args3) {
693458
694000
  const pre = await buildDocumentSnapshot(doc3);
693459
694001
  try {
@@ -696411,6 +696953,21 @@ async function superdocPerformAction(doc3, args3) {
696411
696953
  changeMode: parseChangeMode4(args3.changeMode)
696412
696954
  });
696413
696955
  }
696956
+ case "delete_blocks": {
696957
+ const rawSelectors = Array.isArray(args3.selectors) ? args3.selectors : args3.selectors != null ? [args3.selectors] : args3.selector != null ? [args3.selector] : [];
696958
+ if (rawSelectors.length === 0) {
696959
+ throw new SuperDocCliError('delete_blocks requires a non-empty "selectors" array, each entry resolving to one block (e.g. {kind:"nodeId",nodeId:"…"})', { code: "INVALID_ARGUMENT" });
696960
+ }
696961
+ const selectors = [];
696962
+ for (const [index2, raw] of rawSelectors.entries()) {
696963
+ const parsed = parseSelector2(raw);
696964
+ if (!parsed) {
696965
+ throw new SuperDocCliError(`delete_blocks selectors[${index2}] is not a valid selector (e.g. {kind:"nodeId",nodeId:"…"}); no blocks were deleted`, { code: "INVALID_ARGUMENT" });
696966
+ }
696967
+ selectors.push(parsed);
696968
+ }
696969
+ return runDeleteBlocks(doc3, { action, selectors, changeMode: parseChangeMode4(args3.changeMode) });
696970
+ }
696414
696971
  case "append_list": {
696415
696972
  const items2 = parseStringArray(args3.items);
696416
696973
  if (!items2 || items2.length === 0) {
@@ -697049,7 +697606,7 @@ function parseSelector2(value2) {
697049
697606
  }
697050
697607
  return;
697051
697608
  }
697052
- var ACTION_NAMES, ACTION_HINTS, ACTION_GROUPS, ACTION_ARGS, NAMED_COLORS, HEX_COLOR_PATTERN, normMarker = (m2) => m2.trim().replace(/\.$/, ""), ACTION_NAMES_LIST;
697609
+ var ACTION_NAMES, ACTION_HINTS, ACTION_GROUPS, ACTION_ARGS, DELETABLE_BLOCK_NODE_TYPES3, NAMED_COLORS, HEX_COLOR_PATTERN, normMarker = (m2) => m2.trim().replace(/\.$/, ""), ACTION_NAMES_LIST;
697053
697610
  var init_actions = __esm(() => {
697054
697611
  init_errors3();
697055
697612
  init_list_transform();
@@ -697061,6 +697618,7 @@ var init_actions = __esm(() => {
697061
697618
  "insert_heading",
697062
697619
  "replace_text",
697063
697620
  "delete_text",
697621
+ "delete_blocks",
697064
697622
  "append_list",
697065
697623
  "create_table",
697066
697624
  "comment_paragraphs",
@@ -697102,7 +697660,8 @@ var init_actions = __esm(() => {
697102
697660
  insert_paragraphs: "texts[] (or text for a single paragraph), placement?, headingLevel? (first item as heading 1-6), changeMode?",
697103
697661
  insert_heading: "text, level, placement?, changeMode?",
697104
697662
  replace_text: "edits[{find,replace}], optional selector to scope replacements to one inspected block, caseSensitive?, changeMode?",
697105
- delete_text: "finds[], optional selector to scope deletions to ONE inspected block (required to delete stray whitespace — an unscoped whitespace find matches document-wide), caseSensitive?, changeMode?",
697663
+ delete_text: "finds[], optional selector to scope deletions to ONE inspected block (required to delete stray whitespace — an unscoped whitespace find matches document-wide), caseSensitive?, changeMode? — deletes TEXT ONLY, leaving the block (and a list item's bullet/number) in place. To remove a whole list item, paragraph or heading use delete_blocks",
697664
+ delete_blocks: 'selectors[] (each resolving to ONE inspected block: list item, paragraph or heading), changeMode? — THE way to DELETE a whole LIST ITEM, paragraph or heading, bullet/number included. Use for "remove the first item under Article II" / "delete that clause". delete_text only strikes the text and leaves an empty numbered item behind. Deletes several blocks in ONE call; use delete_table for a whole table',
697106
697665
  append_list: 'items[], kind?: ordered|bullet, headingText?, headingLevel?, placement? {at:"after"|"before",selector} builds the list at that block instead of document end',
697107
697666
  create_table: 'rows, columns, cellTexts?, placement?, changeMode? — changeMode:"tracked" makes the table insertion itself a tracked change',
697108
697667
  rewrite_block: "selector, text, changeMode?",
@@ -697148,6 +697707,7 @@ var init_actions = __esm(() => {
697148
697707
  "insert_heading",
697149
697708
  "replace_text",
697150
697709
  "delete_text",
697710
+ "delete_blocks",
697151
697711
  "append_list",
697152
697712
  "create_table",
697153
697713
  "rewrite_block",
@@ -697194,6 +697754,7 @@ var init_actions = __esm(() => {
697194
697754
  insert_heading: ["text", "level", "placement", "changeMode"],
697195
697755
  replace_text: ["edits", "selector", "caseSensitive", "changeMode"],
697196
697756
  delete_text: ["finds", "selector", "caseSensitive", "changeMode"],
697757
+ delete_blocks: ["selectors", "selector", "changeMode"],
697197
697758
  append_list: ["items", "kind", "headingText", "headingLevel", "placement", "changeMode"],
697198
697759
  create_table: ["rows", "columns", "cellTexts", "placement", "changeMode"],
697199
697760
  comment_paragraphs: ["commentText", "scope", "excludeBlockQuotes"],
@@ -697244,6 +697805,7 @@ var init_actions = __esm(() => {
697244
697805
  insert_page_break: ["selector"],
697245
697806
  add_hyperlink: ["text", "url", "tooltip"]
697246
697807
  };
697808
+ DELETABLE_BLOCK_NODE_TYPES3 = new Set(["paragraph", "heading", "listItem"]);
697247
697809
  NAMED_COLORS = {
697248
697810
  black: "000000",
697249
697811
  blue: "0000FF",
@@ -698696,7 +699258,8 @@ ACTIONS (superdoc_perform_action with flat args)
698696
699258
  - redo_changes: steps (1-25, default 1). Steps history FORWARD to re-apply edits a prior undo removed — THE recovery for an undo overshoot. Only reaches the forward branch until a NEW edit is made.
698697
699259
  - attach_numbering: anchorText (text of the block) or nodeId, likeMarker (rendered marker of a sibling clause, e.g. "10."). Makes an EXISTING block a numbered clause at the same scheme/level — "make this the section 11 heading" in a clause-numbered document is exactly this (it will render as the next number).
698698
699260
  - replace_text: edits:[{find,replace}], caseSensitive default false. selector to scope. changeMode:"tracked" if asked. The receipt reports editsApplied and editsSkipped per find — READ IT: a skipped find is not in the selected block; re-target instead of assuming success.
698699
- - delete_text: finds:[string]. selector to scope deletions to ONE block — REQUIRED for whitespace-only finds (unscoped whitespace matches document-wide and is refused). changeMode:"tracked" if asked.
699261
+ - delete_text: finds:[string]. selector to scope deletions to ONE block — REQUIRED for whitespace-only finds (unscoped whitespace matches document-wide and is refused). changeMode:"tracked" if asked. Deletes TEXT ONLY: the block survives, so a list item keeps its bullet/number and an accepted tracked deletion leaves an empty numbered item behind. To remove the item itself use delete_blocks.
699262
+ - delete_blocks: selectors:[…], each resolving to ONE block (list item, paragraph or heading). changeMode:"tracked" if asked. THE way to DELETE a whole LIST ITEM, paragraph or heading — the bullet/number goes with it and the remaining items renumber. "Delete the first item under Article II" / "remove that clause" is exactly this, NOT delete_text. Pass every target in ONE call. Use delete_table for a whole table.
698700
699263
  - rewrite_block: selector, text. Inspect first to gather current text; never ask the user to paste text already in the doc.
698701
699264
  - create_table: rows, columns, optional cellTexts (2D array). rows counts ALL rows INCLUDING the header — header plus one data row is rows:2. placement defaults to document end. changeMode:"tracked" if asked ("track-changes table") — the insertion itself becomes a tracked change.
698702
699265
  - comment_paragraphs: commentText. excludeBlockQuotes:true to skip block quotes. Applies the SAME text to every BODY paragraph (it does NOT comment the title/heading) — broadcast notes only, never review feedback (see REVIEW rule). To comment a heading too, add_comments on it explicitly.
@@ -49,7 +49,8 @@ ACTIONS (superdoc_perform_action with flat args)
49
49
  - redo_changes: steps (1-25, default 1). Steps history FORWARD to re-apply edits a prior undo removed — THE recovery for an undo overshoot. Only reaches the forward branch until a NEW edit is made.
50
50
  - attach_numbering: anchorText (text of the block) or nodeId, likeMarker (rendered marker of a sibling clause, e.g. "10."). Makes an EXISTING block a numbered clause at the same scheme/level — "make this the section 11 heading" in a clause-numbered document is exactly this (it will render as the next number).
51
51
  - replace_text: edits:[{find,replace}], caseSensitive default false. selector to scope. changeMode:"tracked" if asked. The receipt reports editsApplied and editsSkipped per find — READ IT: a skipped find is not in the selected block; re-target instead of assuming success.
52
- - delete_text: finds:[string]. selector to scope deletions to ONE block — REQUIRED for whitespace-only finds (unscoped whitespace matches document-wide and is refused). changeMode:"tracked" if asked.
52
+ - delete_text: finds:[string]. selector to scope deletions to ONE block — REQUIRED for whitespace-only finds (unscoped whitespace matches document-wide and is refused). changeMode:"tracked" if asked. Deletes TEXT ONLY: the block survives, so a list item keeps its bullet/number and an accepted tracked deletion leaves an empty numbered item behind. To remove the item itself use delete_blocks.
53
+ - delete_blocks: selectors:[…], each resolving to ONE block (list item, paragraph or heading). changeMode:"tracked" if asked. THE way to DELETE a whole LIST ITEM, paragraph or heading — the bullet/number goes with it and the remaining items renumber. "Delete the first item under Article II" / "remove that clause" is exactly this, NOT delete_text. Pass every target in ONE call. Use delete_table for a whole table.
53
54
  - rewrite_block: selector, text. Inspect first to gather current text; never ask the user to paste text already in the doc.
54
55
  - create_table: rows, columns, optional cellTexts (2D array). rows counts ALL rows INCLUDING the header — header plus one data row is rows:2. placement defaults to document end. changeMode:"tracked" if asked ("track-changes table") — the insertion itself becomes a tracked change.
55
56
  - comment_paragraphs: commentText. excludeBlockQuotes:true to skip block quotes. Applies the SAME text to every BODY paragraph (it does NOT comment the title/heading) — broadcast notes only, never review feedback (see REVIEW rule). To comment a heading too, add_comments on it explicitly.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdoc-dev/cli",
3
- "version": "0.22.2",
3
+ "version": "0.23.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "superdoc": "./dist/index.js"
@@ -26,21 +26,21 @@
26
26
  "lib0": "^0.2.114",
27
27
  "typescript": "^5.9.2",
28
28
  "y-protocols": "^1.0.6",
29
+ "@superdoc-dev/sdk": "1.21.3",
29
30
  "@superdoc/document-api": "0.1.0-alpha.0",
30
- "@superdoc-dev/sdk": "1.21.2",
31
31
  "@superdoc/super-editor": "0.0.1",
32
- "superdoc": "1.45.1"
32
+ "superdoc": "1.45.2"
33
33
  },
34
34
  "module": "src/index.ts",
35
35
  "publishConfig": {
36
36
  "access": "public"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@superdoc-dev/cli-darwin-arm64": "0.22.2",
40
- "@superdoc-dev/cli-linux-x64": "0.22.2",
41
- "@superdoc-dev/cli-linux-arm64": "0.22.2",
42
- "@superdoc-dev/cli-darwin-x64": "0.22.2",
43
- "@superdoc-dev/cli-windows-x64": "0.22.2"
39
+ "@superdoc-dev/cli-darwin-arm64": "0.23.0",
40
+ "@superdoc-dev/cli-darwin-x64": "0.23.0",
41
+ "@superdoc-dev/cli-linux-x64": "0.23.0",
42
+ "@superdoc-dev/cli-linux-arm64": "0.23.0",
43
+ "@superdoc-dev/cli-windows-x64": "0.23.0"
44
44
  },
45
45
  "scripts": {
46
46
  "predev": "node scripts/ensure-superdoc-build.js",