@superdoc-dev/cli 0.22.1 → 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-C_k6Kyxn.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("");
@@ -117295,7 +117402,134 @@ var isRegExp = (value) => {
117295
117402
  href = relAttributes["Target"];
117296
117403
  }
117297
117404
  return href;
117298
- }, config$38, translator$78, contextsByConverter, XML_NODE_NAME$38 = "w:ins", SD_ATTR_KEY$2 = "trackInsert", validXmlAttributes$12, encode$65 = (params3, encodedAttrs = {}) => {
117405
+ }, config$38, translator$78, contextsByConverter, TrackInsertMarkName = "trackInsert", TrackDeleteMarkName = "trackDelete", TrackFormatMarkName = "trackFormat", TrackedFormatMarkNames, cloneMark$1 = (mark) => {
117406
+ if (!mark)
117407
+ return mark;
117408
+ return {
117409
+ ...mark,
117410
+ attrs: mark.attrs ? { ...mark.attrs } : undefined
117411
+ };
117412
+ }, cloneNode = (node3) => {
117413
+ if (!node3 || typeof node3 !== "object")
117414
+ return node3;
117415
+ const cloned = { ...node3 };
117416
+ if (node3.marks)
117417
+ cloned.marks = node3.marks.map((mark) => cloneMark$1(mark));
117418
+ if (node3.content)
117419
+ cloned.content = node3.content.map((child) => cloneNode(child));
117420
+ if (node3.elements)
117421
+ cloned.elements = node3.elements.map((el) => cloneNode(el));
117422
+ if (node3.attributes)
117423
+ cloned.attributes = { ...node3.attributes };
117424
+ return cloned;
117425
+ }, cloneRuns = (runs = []) => runs.map((run$1) => cloneNode(run$1)), prepareRunTrackingContext = (node3 = {}) => {
117426
+ const marks = Array.isArray(node3.marks) ? node3.marks : [];
117427
+ const trackingMarks = marks.filter((mark) => mark?.type === "trackInsert" || mark?.type === "trackDelete");
117428
+ if (!trackingMarks.length)
117429
+ return {
117430
+ runNode: node3,
117431
+ trackingMarksByType: /* @__PURE__ */ new Map
117432
+ };
117433
+ const trackingMarksByType = /* @__PURE__ */ new Map;
117434
+ trackingMarks.forEach((mark) => {
117435
+ if (mark?.type)
117436
+ trackingMarksByType.set(mark.type, cloneMark$1(mark));
117437
+ });
117438
+ const preservedMarks = marks.filter((mark) => mark?.type !== "trackInsert" && mark?.type !== "trackDelete").map((mark) => cloneMark$1(mark));
117439
+ const clonedContent = Array.isArray(node3.content) ? node3.content.map((child) => {
117440
+ const childClone = cloneNode(child);
117441
+ const childMarks = Array.isArray(childClone.marks) ? childClone.marks.slice() : [];
117442
+ trackingMarks.forEach((mark) => {
117443
+ childMarks.push(cloneMark$1(mark));
117444
+ });
117445
+ childClone.marks = childMarks;
117446
+ return childClone;
117447
+ }) : [];
117448
+ return {
117449
+ runNode: {
117450
+ ...cloneNode(node3),
117451
+ marks: preservedMarks,
117452
+ content: clonedContent
117453
+ },
117454
+ trackingMarksByType
117455
+ };
117456
+ }, TRACKABLE_RUN_CONTENT_TYPES, TRACKABLE_WHOLE_NODE_TYPES, applyTrackedMarkToRunContent = (subElements = [], markType, attrs) => {
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
+ }
117465
+ subElement.marks = [];
117466
+ (Array.isArray(subElement?.content) ? subElement.content : []).forEach((child) => {
117467
+ if (!child || !TRACKABLE_RUN_CONTENT_TYPES.has(child.type))
117468
+ return;
117469
+ if (child.marks === undefined)
117470
+ child.marks = [];
117471
+ child.marks.push({
117472
+ type: markType,
117473
+ attrs
117474
+ });
117475
+ });
117476
+ });
117477
+ }, mapTrackingAttrs = (mark, attrMap) => {
117478
+ const source = mark?.attrs || {};
117479
+ const mapped = {};
117480
+ attrMap.forEach((targetKey, sourceKey) => {
117481
+ if (source[sourceKey] != null)
117482
+ mapped[targetKey] = source[sourceKey];
117483
+ });
117484
+ return mapped;
117485
+ }, renameTextElementsForDeletion = (node3) => {
117486
+ if (!node3 || typeof node3 !== "object")
117487
+ return;
117488
+ if (node3.name === "w:t")
117489
+ node3.name = "w:delText";
117490
+ if (node3.name === "w:instrText")
117491
+ node3.name = "w:delInstrText";
117492
+ if (Array.isArray(node3.elements))
117493
+ node3.elements.forEach(renameTextElementsForDeletion);
117494
+ }, ensureTrackedWrapper = (runs, trackingMarksByType = /* @__PURE__ */ new Map, options = {}) => {
117495
+ if (!Array.isArray(runs) || !runs.length)
117496
+ return runs;
117497
+ const { isFinalDoc = false } = options;
117498
+ const firstRun = runs[0];
117499
+ if (firstRun?.name === "w:ins" || firstRun?.name === "w:del")
117500
+ return runs;
117501
+ if (!trackingMarksByType.size)
117502
+ return runs;
117503
+ if (trackingMarksByType.has("trackInsert")) {
117504
+ if (isFinalDoc)
117505
+ return runs;
117506
+ const mark = trackingMarksByType.get(TrackInsertMarkName);
117507
+ const clonedRuns = cloneRuns(runs);
117508
+ return [{
117509
+ name: "w:ins",
117510
+ attributes: mapTrackingAttrs(mark, new Map([
117511
+ ["id", "w:id"],
117512
+ ["author", "w:author"],
117513
+ ["authorEmail", "w:authorEmail"],
117514
+ ["date", "w:date"]
117515
+ ])),
117516
+ elements: clonedRuns
117517
+ }];
117518
+ }
117519
+ if (trackingMarksByType.has("trackDelete")) {
117520
+ if (isFinalDoc)
117521
+ return [];
117522
+ const mark = trackingMarksByType.get(TrackDeleteMarkName);
117523
+ const clonedRuns = cloneRuns(runs);
117524
+ clonedRuns.forEach(renameTextElementsForDeletion);
117525
+ return [{
117526
+ name: "w:del",
117527
+ attributes: mapTrackingAttrs(mark, new Map([["id", "w:id"]])),
117528
+ elements: clonedRuns
117529
+ }];
117530
+ }
117531
+ return runs;
117532
+ }, XML_NODE_NAME$38 = "w:ins", SD_ATTR_KEY$2 = "trackInsert", validXmlAttributes$12, encode$65 = (params3, encodedAttrs = {}) => {
117299
117533
  const { nodeListHandler, extraParams = {} } = params3;
117300
117534
  const { node: node3 } = extraParams;
117301
117535
  const { partPath, sourceId, logicalId } = resolveTrackedChangeImportIds(params3, encodedAttrs.id);
@@ -117320,18 +117554,7 @@ var isRegExp = (value) => {
117320
117554
  const converter = params3.converter;
117321
117555
  if (converter?.documentOrigin)
117322
117556
  encodedAttrs.origin = converter.documentOrigin;
117323
- subs.forEach((subElement) => {
117324
- subElement.marks = [];
117325
- if (subElement?.content?.[0]) {
117326
- if (subElement.content[0].marks === undefined)
117327
- subElement.content[0].marks = [];
117328
- if (subElement.content[0].type === "text")
117329
- subElement.content[0].marks.push({
117330
- type: "trackInsert",
117331
- attrs: encodedAttrs
117332
- });
117333
- }
117334
- });
117557
+ applyTrackedMarkToRunContent(subs, "trackInsert", encodedAttrs);
117335
117558
  return subs;
117336
117559
  }, config$37, translator$84, XML_NODE_NAME$37 = "w:del", SD_ATTR_KEY$1 = "trackDelete", validXmlAttributes$11, encode$64 = (params3, encodedAttrs = {}) => {
117337
117560
  const { nodeListHandler, extraParams = {} } = params3;
@@ -117358,18 +117581,7 @@ var isRegExp = (value) => {
117358
117581
  const converter = params3.converter;
117359
117582
  if (converter?.documentOrigin)
117360
117583
  encodedAttrs.origin = converter.documentOrigin;
117361
- subs.forEach((subElement) => {
117362
- subElement.marks = [];
117363
- if (subElement?.content?.[0]) {
117364
- if (subElement.content[0].marks === undefined)
117365
- subElement.content[0].marks = [];
117366
- if (subElement.content[0].type === "text")
117367
- subElement.content[0].marks.push({
117368
- type: "trackDelete",
117369
- attrs: encodedAttrs
117370
- });
117371
- }
117372
- });
117584
+ applyTrackedMarkToRunContent(subs, "trackDelete", encodedAttrs);
117373
117585
  return subs;
117374
117586
  }, config$36, translator$59, XML_NODE_NAME$36 = "w:noBreakHyphen", SD_NODE_NAME$34 = "noBreakHyphen", encode$63 = (_, encodedAttrs = {}) => {
117375
117587
  const translated = { type: SD_NODE_NAME$34 };
@@ -117502,7 +117714,7 @@ var isRegExp = (value) => {
117502
117714
  return true;
117503
117715
  }, areAttrsEqual = (attrsA = {}, attrsB = {}) => {
117504
117716
  return objectIncludes(attrsA, attrsB);
117505
- }, TrackInsertMarkName = "trackInsert", TrackDeleteMarkName = "trackDelete", TrackFormatMarkName = "trackFormat", TrackedFormatMarkNames, TAB_POSITION_TOLERANCE_TWIPS = 20, OOXML_PCT_DIVISOR = 5000, TWIPS_PER_PX = 15, PT_075 = 1, PT_150 = 2, COMPOUND_PROFILES, isPlainObject$3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), OOXML_Z_INDEX_BASE = 251658240, resolveOuterShadowOffset = (shadow) => {
117717
+ }, TAB_POSITION_TOLERANCE_TWIPS = 20, OOXML_PCT_DIVISOR = 5000, TWIPS_PER_PX = 15, PT_075 = 1, PT_150 = 2, COMPOUND_PROFILES, isPlainObject$3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), OOXML_Z_INDEX_BASE = 251658240, resolveOuterShadowOffset = (shadow) => {
117506
117718
  const radians = shadow.direction * Math.PI / 180;
117507
117719
  return {
117508
117720
  dx: shadow.distance * Math.cos(radians),
@@ -117788,6 +118000,20 @@ var isRegExp = (value) => {
117788
118000
  schemaNode.attrs.paragraphProperties = inlineParagraphProperties;
117789
118001
  schemaNode.attrs.rsidRDefault = node3.attributes?.["w:rsidRDefault"];
117790
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
+ }
117791
118017
  const sectPr = pPr?.elements?.find((el) => el.name === "w:sectPr");
117792
118018
  if (sectPr) {
117793
118019
  schemaNode.attrs.paragraphProperties.sectPr = sectPr;
@@ -117932,111 +118158,7 @@ var isRegExp = (value) => {
117932
118158
  ...decodedAttrs
117933
118159
  };
117934
118160
  return translated;
117935
- }, config$33, translator, cloneMark$1 = (mark) => {
117936
- if (!mark)
117937
- return mark;
117938
- return {
117939
- ...mark,
117940
- attrs: mark.attrs ? { ...mark.attrs } : undefined
117941
- };
117942
- }, cloneNode = (node3) => {
117943
- if (!node3 || typeof node3 !== "object")
117944
- return node3;
117945
- const cloned = { ...node3 };
117946
- if (node3.marks)
117947
- cloned.marks = node3.marks.map((mark) => cloneMark$1(mark));
117948
- if (node3.content)
117949
- cloned.content = node3.content.map((child) => cloneNode(child));
117950
- if (node3.elements)
117951
- cloned.elements = node3.elements.map((el) => cloneNode(el));
117952
- if (node3.attributes)
117953
- cloned.attributes = { ...node3.attributes };
117954
- return cloned;
117955
- }, cloneRuns = (runs = []) => runs.map((run$1) => cloneNode(run$1)), prepareRunTrackingContext = (node3 = {}) => {
117956
- const marks = Array.isArray(node3.marks) ? node3.marks : [];
117957
- const trackingMarks = marks.filter((mark) => mark?.type === "trackInsert" || mark?.type === "trackDelete");
117958
- if (!trackingMarks.length)
117959
- return {
117960
- runNode: node3,
117961
- trackingMarksByType: /* @__PURE__ */ new Map
117962
- };
117963
- const trackingMarksByType = /* @__PURE__ */ new Map;
117964
- trackingMarks.forEach((mark) => {
117965
- if (mark?.type)
117966
- trackingMarksByType.set(mark.type, cloneMark$1(mark));
117967
- });
117968
- const preservedMarks = marks.filter((mark) => mark?.type !== "trackInsert" && mark?.type !== "trackDelete").map((mark) => cloneMark$1(mark));
117969
- const clonedContent = Array.isArray(node3.content) ? node3.content.map((child) => {
117970
- const childClone = cloneNode(child);
117971
- const childMarks = Array.isArray(childClone.marks) ? childClone.marks.slice() : [];
117972
- trackingMarks.forEach((mark) => {
117973
- childMarks.push(cloneMark$1(mark));
117974
- });
117975
- childClone.marks = childMarks;
117976
- return childClone;
117977
- }) : [];
117978
- return {
117979
- runNode: {
117980
- ...cloneNode(node3),
117981
- marks: preservedMarks,
117982
- content: clonedContent
117983
- },
117984
- trackingMarksByType
117985
- };
117986
- }, mapTrackingAttrs = (mark, attrMap) => {
117987
- const source = mark?.attrs || {};
117988
- const mapped = {};
117989
- attrMap.forEach((targetKey, sourceKey) => {
117990
- if (source[sourceKey] != null)
117991
- mapped[targetKey] = source[sourceKey];
117992
- });
117993
- return mapped;
117994
- }, renameTextElementsForDeletion = (node3) => {
117995
- if (!node3 || typeof node3 !== "object")
117996
- return;
117997
- if (node3.name === "w:t")
117998
- node3.name = "w:delText";
117999
- if (Array.isArray(node3.elements))
118000
- node3.elements.forEach(renameTextElementsForDeletion);
118001
- }, ensureTrackedWrapper = (runs, trackingMarksByType = /* @__PURE__ */ new Map, options = {}) => {
118002
- if (!Array.isArray(runs) || !runs.length)
118003
- return runs;
118004
- const { isFinalDoc = false } = options;
118005
- const firstRun = runs[0];
118006
- if (firstRun?.name === "w:ins" || firstRun?.name === "w:del")
118007
- return runs;
118008
- if (!trackingMarksByType.size)
118009
- return runs;
118010
- if (trackingMarksByType.has("trackInsert")) {
118011
- if (isFinalDoc)
118012
- return runs;
118013
- const mark = trackingMarksByType.get(TrackInsertMarkName);
118014
- const clonedRuns = cloneRuns(runs);
118015
- return [{
118016
- name: "w:ins",
118017
- attributes: mapTrackingAttrs(mark, new Map([
118018
- ["id", "w:id"],
118019
- ["author", "w:author"],
118020
- ["authorEmail", "w:authorEmail"],
118021
- ["date", "w:date"]
118022
- ])),
118023
- elements: clonedRuns
118024
- }];
118025
- }
118026
- if (trackingMarksByType.has("trackDelete")) {
118027
- if (isFinalDoc)
118028
- return [];
118029
- const mark = trackingMarksByType.get(TrackDeleteMarkName);
118030
- const clonedRuns = cloneRuns(runs);
118031
- clonedRuns.forEach(renameTextElementsForDeletion);
118032
- return [{
118033
- name: "w:del",
118034
- attributes: mapTrackingAttrs(mark, new Map([["id", "w:id"]])),
118035
- elements: clonedRuns
118036
- }];
118037
- }
118038
- return runs;
118039
- }, encode$52 = (attributes) => {
118161
+ }, config$33, translator, encode$52 = (attributes) => {
118040
118162
  return attributes["w:rsidR"];
118041
118163
  }, decode$54 = (attrs) => {
118042
118164
  return attrs.rsidR;
@@ -123513,7 +123635,7 @@ var isRegExp = (value) => {
123513
123635
  return;
123514
123636
  }
123515
123637
  const fldType = node3.elements?.find((el) => el.name === "w:fldChar")?.attributes?.["w:fldCharType"];
123516
- 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");
123517
123639
  if (node3.name === "w:fldSimple") {
123518
123640
  const instr = node3.attributes?.["w:instr"];
123519
123641
  if (typeof instr === "string") {
@@ -123755,7 +123877,7 @@ var isRegExp = (value) => {
123755
123877
  const elements = Array.isArray(node3?.elements) ? node3.elements : [];
123756
123878
  const tokens = [];
123757
123879
  elements.forEach((el) => {
123758
- if (el?.name === "w:instrText") {
123880
+ if (el?.name === "w:instrText" || el?.name === "w:delInstrText") {
123759
123881
  const text$2 = (el.elements || []).map((child) => typeof child?.text === "string" ? child.text : "").join("");
123760
123882
  tokens.push({
123761
123883
  type: "text",
@@ -129499,6 +129621,8 @@ var isRegExp = (value) => {
129499
129621
  };
129500
129622
  }, decode$21 = (params3) => {
129501
129623
  const { node: node3 } = params3;
129624
+ if (node3.marks?.find((m) => m.type === "trackDelete"))
129625
+ return translator$59.decode(params3);
129502
129626
  const outputMarks = processOutputMarks(node3.attrs?.marksAsAttrs || []);
129503
129627
  const contentNodes = buildFieldResultRuns(params3, outputMarks);
129504
129628
  const instructionElements = buildInstructionElements(node3.attrs?.instruction, node3.attrs?.instructionTokens);
@@ -136974,7 +137098,7 @@ Docs: https://docs.superdoc.dev/getting-started/fonts`);
136974
137098
  return out;
136975
137099
  }
136976
137100
  return out;
136977
- }, 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.0", 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 }) => {
136978
137102
  if (!runProps?.elements?.length || !state)
136979
137103
  return;
136980
137104
  const fontsNode = runProps.elements.find((el) => el.name === "w:rFonts");
@@ -137008,7 +137132,7 @@ Docs: https://docs.superdoc.dev/getting-started/fonts`);
137008
137132
  state.kern = kernNode.attributes["w:val"];
137009
137133
  }
137010
137134
  }, SuperConverter;
137011
- var init_SuperConverter_C_k6Kyxn_es = __esm(() => {
137135
+ var init_SuperConverter_DQRPJhx5_es = __esm(() => {
137012
137136
  init_rolldown_runtime_Bg48TavK_es();
137013
137137
  init_jszip_C49i9kUs_es();
137014
137138
  init_xml_js_CqGKpaft_es();
@@ -141395,6 +141519,17 @@ var init_SuperConverter_C_k6Kyxn_es = __esm(() => {
141395
141519
  };
141396
141520
  translator$78 = NodeTranslator.from(config$38);
141397
141521
  contextsByConverter = /* @__PURE__ */ new WeakMap;
141522
+ TrackedFormatMarkNames = [
141523
+ "bold",
141524
+ "italic",
141525
+ "strike",
141526
+ "underline",
141527
+ "textStyle",
141528
+ "highlight",
141529
+ "link"
141530
+ ];
141531
+ TRACKABLE_RUN_CONTENT_TYPES = new Set(["text", "noBreakHyphen"]);
141532
+ TRACKABLE_WHOLE_NODE_TYPES = new Set(["crossReference"]);
141398
141533
  validXmlAttributes$12 = [
141399
141534
  createAttributeHandler("w:id", "id"),
141400
141535
  createAttributeHandler("w:date", "date"),
@@ -141445,15 +141580,6 @@ var init_SuperConverter_C_k6Kyxn_es = __esm(() => {
141445
141580
  attributes: validXmlAttributes$10
141446
141581
  };
141447
141582
  translator$5 = NodeTranslator.from(config$1);
141448
- TrackedFormatMarkNames = [
141449
- "bold",
141450
- "italic",
141451
- "strike",
141452
- "underline",
141453
- "textStyle",
141454
- "highlight",
141455
- "link"
141456
- ];
141457
141583
  COMPOUND_PROFILES = {
141458
141584
  double: (w) => [
141459
141585
  w,
@@ -154107,7 +154233,11 @@ var init_SuperConverter_C_k6Kyxn_es = __esm(() => {
154107
154233
  CONSTRUCTIVE_TRACK_CHANGE_ELEMENT_NAMES = new Set(["w:ins", "w:moveTo"]);
154108
154234
  SKIP_FIELD_PROCESSING_NODE_NAMES$1 = new Set(["w:drawing", "w:pict"]);
154109
154235
  FIELD_CONTROL_ELEMENT_NAMES = new Set(["w:fldChar"]);
154110
- 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
+ ]);
154111
154241
  SKIP_FIELD_PROCESSING_NODE_NAMES = new Set(["w:drawing", "w:pict"]);
154112
154242
  HEADER_FOOTER_FILENAME_PATTERN = /^(header|footer)\d*\.xml$/i;
154113
154243
  CHART_TYPE_MAP = {
@@ -166019,7 +166149,7 @@ var init_SuperConverter_C_k6Kyxn_es = __esm(() => {
166019
166149
  };
166020
166150
  });
166021
166151
 
166022
- // ../../packages/superdoc/dist/chunks/create-headless-toolbar-Bk1DvH4C.es.js
166152
+ // ../../packages/superdoc/dist/chunks/create-headless-toolbar-pGC1aJVe.es.js
166023
166153
  function parseSizeUnit(val = "0") {
166024
166154
  const length3 = val.toString() || "0";
166025
166155
  const value = Number.parseFloat(length3);
@@ -176840,9 +176970,9 @@ var CSS_DIMENSION_REGEX, DOM_SIZE_UNITS, MARK_KEYS, STEP_OP_CATALOG_UNFROZEN2, P
176840
176970
  }
176841
176971
  };
176842
176972
  };
176843
- var init_create_headless_toolbar_Bk1DvH4C_es = __esm(() => {
176973
+ var init_create_headless_toolbar_pGC1aJVe_es = __esm(() => {
176844
176974
  init_rolldown_runtime_Bg48TavK_es();
176845
- init_SuperConverter_C_k6Kyxn_es();
176975
+ init_SuperConverter_DQRPJhx5_es();
176846
176976
  init_jszip_C49i9kUs_es();
176847
176977
  init_uuid_B2wVPhPi_es();
176848
176978
  init_constants_D9qj59G2_es();
@@ -226935,7 +227065,7 @@ var init_remark_gfm_DCND_V_3_es = __esm(() => {
226935
227065
  init_remark_gfm_BUJjZJLy_es();
226936
227066
  });
226937
227067
 
226938
- // ../../packages/superdoc/dist/chunks/src-BzR0d4AD.es.js
227068
+ // ../../packages/superdoc/dist/chunks/src-DdCAj9Jo.es.js
226939
227069
  function deleteProps(obj, propOrProps) {
226940
227070
  const props = typeof propOrProps === "string" ? [propOrProps] : propOrProps;
226941
227071
  const removeNested = (target, pathParts, index2 = 0) => {
@@ -227079,7 +227209,7 @@ function prosemirrorToYXmlFragment(doc$12, xmlFragment) {
227079
227209
  }
227080
227210
  function getSuperdocVersion() {
227081
227211
  try {
227082
- return "1.45.0";
227212
+ return "1.45.2";
227083
227213
  } catch {
227084
227214
  return "unknown";
227085
227215
  }
@@ -229091,7 +229221,29 @@ function collectSDTNodes(doc$12) {
229091
229221
  });
229092
229222
  return sdtNodes;
229093
229223
  }
229094
- 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) {
229095
229247
  for (const sdt of sdtNodes) {
229096
229248
  if (!(from$1 < sdt.end && to > sdt.pos))
229097
229249
  continue;
@@ -229103,7 +229255,7 @@ function checkLockViolation(sdtNodes, from$1, to) {
229103
229255
  const wouldModifyContent = insideSDT && !containsSDT;
229104
229256
  const isSdtLocked = sdt.lockMode === "sdtLocked" || sdt.lockMode === "sdtContentLocked";
229105
229257
  const isContentLocked = sdt.lockMode === "contentLocked" || sdt.lockMode === "sdtContentLocked";
229106
- if (isSdtLocked && wouldDamageWrapper)
229258
+ if (isSdtLocked && wouldDamageWrapper && !preservedSdtNodes?.has(sdt))
229107
229259
  return {
229108
229260
  blocked: true,
229109
229261
  reason: `Cannot delete SDT wrapper (${sdt.lockMode})`
@@ -229268,10 +229420,11 @@ function createStructuredContentLockPlugin() {
229268
229420
  const sdtNodes = STRUCTURED_CONTENT_LOCK_KEY.getState(state);
229269
229421
  if (sdtNodes.length === 0)
229270
229422
  return true;
229423
+ const preservedSdtNodes = tr.getMeta?.("structuredContentWrapperPreserving") ? collectPreservedSDTNodes(sdtNodes, tr.doc) : undefined;
229271
229424
  for (const step3 of tr.steps) {
229272
229425
  if (step3.from === undefined || step3.to === undefined)
229273
229426
  continue;
229274
- if (checkLockViolation(sdtNodes, step3.from, step3.to).blocked)
229427
+ if (checkLockViolation(sdtNodes, step3.from, step3.to, preservedSdtNodes).blocked)
229275
229428
  return false;
229276
229429
  }
229277
229430
  return true;
@@ -249478,11 +249631,17 @@ function blocksDeleteWrapper(editor, input2, options) {
249478
249631
  };
249479
249632
  checkRevision(editor, options?.expectedRevision);
249480
249633
  const tr = editor.state.tr;
249481
- tr.delete(candidate.pos, candidate.end);
249482
- if (mode === "tracked")
249483
- applyTrackedMutationMeta(tr);
249484
- 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" });
249485
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
+ }
249486
249645
  editor.dispatch(tr);
249487
249646
  clearIndexCache(editor);
249488
249647
  return {
@@ -249491,6 +249650,45 @@ function blocksDeleteWrapper(editor, input2, options) {
249491
249650
  deletedBlock
249492
249651
  };
249493
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
+ }
249494
249692
  function hasSectionBreak(candidate) {
249495
249693
  const pPr = candidate.node.attrs?.paragraphProperties;
249496
249694
  return pPr?.sectPr != null && typeof pPr.sectPr === "object";
@@ -259466,6 +259664,13 @@ function executeSdtMutation(editor, target, options, handler2) {
259466
259664
  return buildMutationFailure("NO_OP", "The mutation had no effect.");
259467
259665
  return buildMutationSuccess(target, updatedRef);
259468
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
+ }
259469
259674
  function dispatchTransaction$1(editor, tr) {
259470
259675
  if (editor.view?.dispatch) {
259471
259676
  editor.view.dispatch(tr);
@@ -259622,7 +259827,7 @@ function wrapWrapper(editor, input2, options) {
259622
259827
  nodeType: "sdt",
259623
259828
  nodeId: id2
259624
259829
  };
259625
- return executeSdtMutation(editor, input2.target, options, () => {
259830
+ return executeSdtWrappingMutation(editor, input2.target, options, () => {
259626
259831
  const resolved = resolveSdtByTarget(editor.state.doc, input2.target);
259627
259832
  const nodeTypeName = input2.kind === "block" ? SDT_BLOCK_NAME : "structuredContent";
259628
259833
  const nodeType = editor.schema.nodes[nodeTypeName];
@@ -259639,6 +259844,7 @@ function wrapWrapper(editor, input2, options) {
259639
259844
  }, resolved.node);
259640
259845
  const { tr } = editor.state;
259641
259846
  tr.replaceWith(resolved.pos, resolved.pos + resolved.node.nodeSize, wrapperNode);
259847
+ tr.setMeta(STRUCTURED_CONTENT_WRAPPER_PRESERVING_META, true);
259642
259848
  dispatchTransaction$1(editor, tr);
259643
259849
  return wrapperTarget;
259644
259850
  });
@@ -260521,7 +260727,7 @@ function repeatingSectionSetAllowInsertDeleteWrapper(editor, input2, options) {
260521
260727
  function groupWrapWrapper(editor, input2, options) {
260522
260728
  resolveSdtByTarget(editor.state.doc, input2.target);
260523
260729
  const target = input2.target;
260524
- return executeSdtMutation(editor, target, options, () => {
260730
+ return executeSdtWrappingMutation(editor, target, options, () => {
260525
260731
  const resolved = resolveSdtByTarget(editor.state.doc, input2.target);
260526
260732
  const groupNodeType = editor.schema.nodes[SDT_BLOCK_NAME];
260527
260733
  if (!groupNodeType)
@@ -260534,6 +260740,7 @@ function groupWrapWrapper(editor, input2, options) {
260534
260740
  }, resolved.node);
260535
260741
  const { tr } = editor.state;
260536
260742
  tr.replaceWith(resolved.pos, resolved.pos + resolved.node.nodeSize, groupNode);
260743
+ tr.setMeta(STRUCTURED_CONTENT_WRAPPER_PRESERVING_META, true);
260537
260744
  dispatchTransaction$1(editor, tr);
260538
260745
  return {
260539
260746
  kind: "block",
@@ -291428,7 +291635,7 @@ var Node$13 = class Node$14 {
291428
291635
  return !!(node3?.isBlock && node3?.type?.spec?.attrs?.[SD_BLOCK_REV_ATTRIBUTE_NAME]);
291429
291636
  }, nodeNeedsSdBlockId = (node3) => {
291430
291637
  return !node3?.attrs?.[SD_BLOCK_ID_ATTRIBUTE_NAME];
291431
- }, 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 }) => {
291432
291639
  const { selection } = state;
291433
291640
  if (!selection.empty)
291434
291641
  return false;
@@ -297754,16 +297961,43 @@ var Node$13 = class Node$14 {
297754
297961
  if (deterministicJson(a2.sourceIds) !== deterministicJson(b$1.sourceIds))
297755
297962
  return false;
297756
297963
  return true;
297757
- }, 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" }) => {
297758
297991
  return buildGraphFromSpans({
297759
297992
  spans: enumerateTrackedMarkSpans(state),
297760
297993
  structuralChanges: enumerateStructuralRowChanges(state),
297761
297994
  pprChanges: enumeratePprChanges(state),
297995
+ paragraphMarkChanges: enumerateParagraphMarkDeletions(state),
297762
297996
  doc: state?.doc ?? null,
297763
297997
  story,
297764
297998
  replacementsMode
297765
297999
  });
297766
- }, buildGraphFromSpans = ({ spans, structuralChanges = [], pprChanges = [], doc: doc$12, story, replacementsMode }) => {
298000
+ }, buildGraphFromSpans = ({ spans, structuralChanges = [], pprChanges = [], paragraphMarkChanges = [], doc: doc$12, story, replacementsMode }) => {
297767
298001
  const mergedSegments = mergeAdjacentSpans(spans.map((span) => ({
297768
298002
  attrs: readTrackedAttrs(span.mark, span.mark.type.name),
297769
298003
  span
@@ -297857,6 +298091,24 @@ var Node$13 = class Node$14 {
297857
298091
  changes.set(logical.id, logical);
297858
298092
  appendToMap(byRevisionGroupId, logical.revisionGroupId, logical.id);
297859
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
+ }
297860
298112
  const segments = mergedSegments.slice().sort((a2, b$1) => a2.from - b$1.from || a2.to - b$1.to);
297861
298113
  const graph = {
297862
298114
  changes,
@@ -298195,6 +298447,83 @@ var Node$13 = class Node$14 {
298195
298447
  enumerable: false
298196
298448
  });
298197
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;
298198
298527
  }, aggregateSourceIds = (segments) => {
298199
298528
  const out = {};
298200
298529
  const sorted = [...segments].sort((a2, b$1) => {
@@ -301346,7 +301675,7 @@ var Node$13 = class Node$14 {
301346
301675
  };
301347
301676
  }
301348
301677
  touched.add(change.id);
301349
- if (isFull && !change.pprChange)
301678
+ if (isFull && !change.pprChange && !change.paragraphMarkChange)
301350
301679
  for (const segment of change.segments)
301351
301680
  resolvedRanges.push({
301352
301681
  from: segment.from,
@@ -301365,6 +301694,18 @@ var Node$13 = class Node$14 {
301365
301694
  ok: false,
301366
301695
  failure: pprResult.failure
301367
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
+ };
301368
301709
  } else if (change.type === CanonicalChangeType.Structural) {
301369
301710
  const structuralResult = planStructuralDecision({
301370
301711
  ops,
@@ -301592,8 +301933,15 @@ var Node$13 = class Node$14 {
301592
301933
  cause: `accept-deletion:${change.id}`
301593
301934
  });
301594
301935
  }
301595
- if (isFull)
301936
+ if (isFull) {
301937
+ pushParagraphMarkOps({
301938
+ ops,
301939
+ change,
301940
+ decision: "accept",
301941
+ ranges: ranges$1
301942
+ });
301596
301943
  retired.add(change.id);
301944
+ }
301597
301945
  return;
301598
301946
  }
301599
301947
  const ranges = isFull ? change.deletedSegments.map((s2) => ({
@@ -301608,8 +301956,26 @@ var Node$13 = class Node$14 {
301608
301956
  changeId: change.id,
301609
301957
  side: SegmentSide.Deleted
301610
301958
  });
301611
- if (isFull)
301959
+ if (isFull) {
301960
+ pushParagraphMarkOps({
301961
+ ops,
301962
+ change,
301963
+ decision: "reject",
301964
+ ranges
301965
+ });
301612
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
+ });
301613
301979
  }, planStructuralDecision = ({ ops, change, decision, removedRanges, retired }) => {
301614
301980
  const structural = change.structural;
301615
301981
  if (!structural)
@@ -301666,6 +302032,22 @@ var Node$13 = class Node$14 {
301666
302032
  });
301667
302033
  retired.add(change.id);
301668
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 };
301669
302051
  }, planReplacementDecision = ({ ops, graph, change, decision, removedRanges, retired }) => {
301670
302052
  const inserted = change.insertedSegments;
301671
302053
  const deleted = change.deletedSegments;
@@ -302107,6 +302489,25 @@ var Node$13 = class Node$14 {
302107
302489
  };
302108
302490
  }
302109
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;
302110
302511
  }, rejectParagraphSplitAt = (tr, from$1, anchor = "inserted") => {
302111
302512
  const block = findTextblockAt(tr.doc, from$1);
302112
302513
  if (!block)
@@ -302123,6 +302524,7 @@ var Node$13 = class Node$14 {
302123
302524
  const markOps = sortedOps.filter((op) => op.kind !== "removeContent");
302124
302525
  const contentOps = sortedOps.filter((op) => op.kind === "removeContent").reverse();
302125
302526
  const splitJoinOps = sortedOps.filter((op) => op.kind === "rejectParagraphSplit").reverse();
302527
+ const paragraphMarkOps = sortedOps.filter((op) => op.kind === "collapseParagraphMark").reverse();
302126
302528
  try {
302127
302529
  for (const op of markOps) {
302128
302530
  if (op.kind === "removeMark" && op.mark) {
@@ -302167,6 +302569,15 @@ var Node$13 = class Node$14 {
302167
302569
  });
302168
302570
  continue;
302169
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
+ }
302170
302581
  if (op.kind === "resolvePprChange") {
302171
302582
  const mappedFrom = tr.mapping.map(op.from, 1);
302172
302583
  const node3 = tr.doc.nodeAt(mappedFrom);
@@ -302198,6 +302609,19 @@ var Node$13 = class Node$14 {
302198
302609
  for (const op of splitJoinOps)
302199
302610
  if (!rejectParagraphSplitAt(tr, tr.mapping.map(op.from, 1), op.anchor))
302200
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
+ }
302201
302625
  } catch (error3) {
302202
302626
  return {
302203
302627
  ok: false,
@@ -306428,7 +306852,7 @@ var Node$13 = class Node$14 {
306428
306852
  domAvailabilityCache = false;
306429
306853
  return false;
306430
306854
  }
306431
- }, summaryVersion = "1.45.0", nodeKeys, markKeys, transformListsInCopiedContent = (html3) => {
306855
+ }, summaryVersion = "1.45.2", nodeKeys, markKeys, transformListsInCopiedContent = (html3) => {
306432
306856
  const container = document.createElement("div");
306433
306857
  container.innerHTML = html3;
306434
306858
  const result = [];
@@ -307614,7 +308038,7 @@ var Node$13 = class Node$14 {
307614
308038
  return () => {};
307615
308039
  const handle3 = setInterval(callback, intervalMs);
307616
308040
  return () => clearInterval(handle3);
307617
- }, 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.0", 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) => {
307618
308042
  if (!isTrackedReviewMark(mark2))
307619
308043
  return null;
307620
308044
  const id2 = typeof mark2.attrs?.id === "string" ? mark2.attrs.id : "";
@@ -328501,13 +328925,13 @@ menclose::after {
328501
328925
  return;
328502
328926
  console.log(...args$1);
328503
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;
328504
- var init_src_BzR0d4AD_es = __esm(() => {
328928
+ var init_src_DdCAj9Jo_es = __esm(() => {
328505
328929
  init_rolldown_runtime_Bg48TavK_es();
328506
- init_SuperConverter_C_k6Kyxn_es();
328930
+ init_SuperConverter_DQRPJhx5_es();
328507
328931
  init_jszip_C49i9kUs_es();
328508
328932
  init_xml_js_CqGKpaft_es();
328509
328933
  init_uuid_B2wVPhPi_es();
328510
- init_create_headless_toolbar_Bk1DvH4C_es();
328934
+ init_create_headless_toolbar_pGC1aJVe_es();
328511
328935
  init_constants_D9qj59G2_es();
328512
328936
  init_unified_BDuVPlMu_es();
328513
328937
  init_remark_gfm_BUJjZJLy_es();
@@ -338193,6 +338617,11 @@ ${err.toString()}`);
338193
338617
  attributes: { rendered: false },
338194
338618
  filename: { rendered: false },
338195
338619
  paragraphProperties: { rendered: false },
338620
+ markTrackChange: {
338621
+ default: null,
338622
+ rendered: false,
338623
+ keepOnSplit: false
338624
+ },
338196
338625
  pageBreakSource: { rendered: false },
338197
338626
  tocSourceId: { rendered: false },
338198
338627
  sectionMargins: { rendered: false },
@@ -371827,11 +372256,11 @@ function print() { __p += __j.call(arguments, '') }
371827
372256
  ]);
371828
372257
  });
371829
372258
 
371830
- // ../../packages/superdoc/dist/chunks/create-super-doc-ui-BsfD9cQX.es.js
372259
+ // ../../packages/superdoc/dist/chunks/create-super-doc-ui-DFLkPFF8.es.js
371831
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;
371832
- var init_create_super_doc_ui_BsfD9cQX_es = __esm(() => {
371833
- init_SuperConverter_C_k6Kyxn_es();
371834
- init_create_headless_toolbar_Bk1DvH4C_es();
372261
+ var init_create_super_doc_ui_DFLkPFF8_es = __esm(() => {
372262
+ init_SuperConverter_DQRPJhx5_es();
372263
+ init_create_headless_toolbar_pGC1aJVe_es();
371835
372264
  DEFAULT_TEXT_ALIGN_OPTIONS = [
371836
372265
  {
371837
372266
  label: "Left",
@@ -372122,15 +372551,15 @@ var init_zipper_BxRAi0_5_es = __esm(() => {
372122
372551
 
372123
372552
  // ../../packages/superdoc/dist/super-editor.es.js
372124
372553
  var init_super_editor_es = __esm(() => {
372125
- init_src_BzR0d4AD_es();
372126
- init_SuperConverter_C_k6Kyxn_es();
372554
+ init_src_DdCAj9Jo_es();
372555
+ init_SuperConverter_DQRPJhx5_es();
372127
372556
  init_jszip_C49i9kUs_es();
372128
372557
  init_xml_js_CqGKpaft_es();
372129
- init_create_headless_toolbar_Bk1DvH4C_es();
372558
+ init_create_headless_toolbar_pGC1aJVe_es();
372130
372559
  init_constants_D9qj59G2_es();
372131
372560
  init_unified_BDuVPlMu_es();
372132
372561
  init_DocxZipper_BzS208BW_es();
372133
- init_create_super_doc_ui_BsfD9cQX_es();
372562
+ init_create_super_doc_ui_DFLkPFF8_es();
372134
372563
  init_ui_CGB3qmy3_es();
372135
372564
  init_eventemitter3_UwU_CLPU_es();
372136
372565
  init_errors_C_DoKMoN_es();
@@ -693461,6 +693890,112 @@ async function runDeleteText(doc3, args3) {
693461
693890
  return failedReceipt("delete_text", err, pre);
693462
693891
  }
693463
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
+ }
693464
693999
  async function runAppendList(doc3, args3) {
693465
694000
  const pre = await buildDocumentSnapshot(doc3);
693466
694001
  try {
@@ -696418,6 +696953,21 @@ async function superdocPerformAction(doc3, args3) {
696418
696953
  changeMode: parseChangeMode4(args3.changeMode)
696419
696954
  });
696420
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
+ }
696421
696971
  case "append_list": {
696422
696972
  const items2 = parseStringArray(args3.items);
696423
696973
  if (!items2 || items2.length === 0) {
@@ -697056,7 +697606,7 @@ function parseSelector2(value2) {
697056
697606
  }
697057
697607
  return;
697058
697608
  }
697059
- 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;
697060
697610
  var init_actions = __esm(() => {
697061
697611
  init_errors3();
697062
697612
  init_list_transform();
@@ -697068,6 +697618,7 @@ var init_actions = __esm(() => {
697068
697618
  "insert_heading",
697069
697619
  "replace_text",
697070
697620
  "delete_text",
697621
+ "delete_blocks",
697071
697622
  "append_list",
697072
697623
  "create_table",
697073
697624
  "comment_paragraphs",
@@ -697109,7 +697660,8 @@ var init_actions = __esm(() => {
697109
697660
  insert_paragraphs: "texts[] (or text for a single paragraph), placement?, headingLevel? (first item as heading 1-6), changeMode?",
697110
697661
  insert_heading: "text, level, placement?, changeMode?",
697111
697662
  replace_text: "edits[{find,replace}], optional selector to scope replacements to one inspected block, caseSensitive?, changeMode?",
697112
- 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',
697113
697665
  append_list: 'items[], kind?: ordered|bullet, headingText?, headingLevel?, placement? {at:"after"|"before",selector} builds the list at that block instead of document end',
697114
697666
  create_table: 'rows, columns, cellTexts?, placement?, changeMode? — changeMode:"tracked" makes the table insertion itself a tracked change',
697115
697667
  rewrite_block: "selector, text, changeMode?",
@@ -697155,6 +697707,7 @@ var init_actions = __esm(() => {
697155
697707
  "insert_heading",
697156
697708
  "replace_text",
697157
697709
  "delete_text",
697710
+ "delete_blocks",
697158
697711
  "append_list",
697159
697712
  "create_table",
697160
697713
  "rewrite_block",
@@ -697201,6 +697754,7 @@ var init_actions = __esm(() => {
697201
697754
  insert_heading: ["text", "level", "placement", "changeMode"],
697202
697755
  replace_text: ["edits", "selector", "caseSensitive", "changeMode"],
697203
697756
  delete_text: ["finds", "selector", "caseSensitive", "changeMode"],
697757
+ delete_blocks: ["selectors", "selector", "changeMode"],
697204
697758
  append_list: ["items", "kind", "headingText", "headingLevel", "placement", "changeMode"],
697205
697759
  create_table: ["rows", "columns", "cellTexts", "placement", "changeMode"],
697206
697760
  comment_paragraphs: ["commentText", "scope", "excludeBlockQuotes"],
@@ -697251,6 +697805,7 @@ var init_actions = __esm(() => {
697251
697805
  insert_page_break: ["selector"],
697252
697806
  add_hyperlink: ["text", "url", "tooltip"]
697253
697807
  };
697808
+ DELETABLE_BLOCK_NODE_TYPES3 = new Set(["paragraph", "heading", "listItem"]);
697254
697809
  NAMED_COLORS = {
697255
697810
  black: "000000",
697256
697811
  blue: "0000FF",
@@ -698703,7 +699258,8 @@ ACTIONS (superdoc_perform_action with flat args)
698703
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.
698704
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).
698705
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.
698706
- - 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.
698707
699263
  - rewrite_block: selector, text. Inspect first to gather current text; never ask the user to paste text already in the doc.
698708
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.
698709
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.