@superdoc-dev/mcp 0.11.0-next.10 → 0.11.0-next.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1676 -185
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -52211,7 +52211,7 @@ var init_remark_gfm_BhnWr3yf_es = __esm(() => {
52211
52211
  emptyOptions2 = {};
52212
52212
  });
52213
52213
 
52214
- // ../../packages/superdoc/dist/chunks/SuperConverter-D2zNnC50.es.js
52214
+ // ../../packages/superdoc/dist/chunks/SuperConverter-BBjNvGFh.es.js
52215
52215
  function getExtensionConfigField(extension$1, field, context = { name: "" }) {
52216
52216
  const fieldValue = extension$1.config[field];
52217
52217
  if (typeof fieldValue === "function")
@@ -56777,6 +56777,15 @@ function executeTrackChangesDecide(adapter, rawInput, options) {
56777
56777
  field: "target.story",
56778
56778
  value: rawStory
56779
56779
  });
56780
+ if (target.range !== undefined)
56781
+ return {
56782
+ success: false,
56783
+ failure: {
56784
+ code: "INVALID_INPUT",
56785
+ message: "trackChanges.decide does not support a partial range on an id target; the change is not safely divisible.",
56786
+ details: { target: input.target }
56787
+ }
56788
+ };
56780
56789
  if (typeof target.id !== "string" || target.id.length === 0)
56781
56790
  throw new DocumentApiValidationError("INVALID_TARGET", "trackChanges.decide id targets require a non-empty id.", {
56782
56791
  field: "target",
@@ -65228,6 +65237,61 @@ function decode$50(params, decodedAttrs) {
65228
65237
  };
65229
65238
  return translated;
65230
65239
  }
65240
+ function readRowTrackChange(trPr, params = {}) {
65241
+ const marker = trPr?.elements?.find((el) => el.name === "w:ins" || el.name === "w:del");
65242
+ if (!marker)
65243
+ return null;
65244
+ const side = marker.name === "w:ins" ? "insertion" : "deletion";
65245
+ const attributes = marker.attributes || {};
65246
+ const { sourceId, logicalId } = resolveTrackedChangeImportIds(params, attributes["w:id"]);
65247
+ const trackChange = {
65248
+ type: side === "insertion" ? "rowInsert" : "rowDelete",
65249
+ id: logicalId,
65250
+ sourceId,
65251
+ author: attributes["w:author"] || "",
65252
+ authorEmail: attributes["w:authorEmail"] || "",
65253
+ date: attributes["w:date"] || "",
65254
+ importedAuthor: `${attributes["w:author"] || ""} (imported)`
65255
+ };
65256
+ stampImportTrackingAttrs({
65257
+ params,
65258
+ attrs: trackChange,
65259
+ side,
65260
+ sourceId
65261
+ });
65262
+ return trackChange;
65263
+ }
65264
+ function buildRowTrackChangeElement(trackChange, params = {}) {
65265
+ if (!trackChange || trackChange.type !== "rowInsert" && trackChange.type !== "rowDelete")
65266
+ return null;
65267
+ const name = trackChange.type === "rowInsert" ? "w:ins" : "w:del";
65268
+ const wId = resolveExportRowWordId(params, trackChange);
65269
+ const attributes = { "w:id": wId };
65270
+ if (trackChange.author)
65271
+ attributes["w:author"] = trackChange.author;
65272
+ if (trackChange.authorEmail)
65273
+ attributes["w:authorEmail"] = trackChange.authorEmail;
65274
+ if (trackChange.date)
65275
+ attributes["w:date"] = trackChange.date;
65276
+ return {
65277
+ name,
65278
+ attributes
65279
+ };
65280
+ }
65281
+ function resolveExportRowWordId(params, trackChange) {
65282
+ const sourceId = trackChange.sourceId;
65283
+ const logicalId = typeof trackChange.id === "string" ? trackChange.id : "";
65284
+ const exportParams = params;
65285
+ const allocator = exportParams?.converter?.wordIdAllocator;
65286
+ const partPath = exportParams?.currentPartPath || (typeof exportParams?.filename === "string" && exportParams.filename.length > 0 ? `word/${exportParams.filename}` : "word/document.xml");
65287
+ if (allocator)
65288
+ return allocator.allocate({
65289
+ partPath,
65290
+ sourceId: sourceId === undefined ? undefined : sourceId === null ? null : String(sourceId),
65291
+ logicalId
65292
+ });
65293
+ return String(sourceId || logicalId || "");
65294
+ }
65231
65295
  function parseTagValueJSON(json2) {
65232
65296
  if (typeof json2 !== "string")
65233
65297
  return {};
@@ -89791,8 +89855,10 @@ function tableNodeToBlock(node2, { nextBlockId, positions, storyKey, trackedChan
89791
89855
  defaultCellPadding,
89792
89856
  tableProperties: tablePropertiesForCascade
89793
89857
  });
89794
- if (parsedRow)
89795
- rows.push(parsedRow);
89858
+ if (parsedRow) {
89859
+ if (!shouldHideTrackedNode(parsedRow.attrs?.trackedChange, parserDeps.trackedChangesConfig))
89860
+ rows.push(parsedRow);
89861
+ }
89796
89862
  });
89797
89863
  if (rows.length === 0)
89798
89864
  return null;
@@ -94682,6 +94748,8 @@ function deriveTrackedChangeId(change) {
94682
94748
  return change.rawId;
94683
94749
  }
94684
94750
  function resolveTrackedChangeType(change) {
94751
+ if (change.structural)
94752
+ return "structural";
94685
94753
  if (change.hasFormat)
94686
94754
  return "format";
94687
94755
  if (change.hasInsert && change.hasDelete)
@@ -94917,6 +94985,42 @@ function groupTrackedChanges(editor) {
94917
94985
  return a.id.localeCompare(b.id);
94918
94986
  });
94919
94987
  attachOverlapMetadata(grouped);
94988
+ for (const structural of enumerateStructuralRowChanges(editor.state)) {
94989
+ const excerpt = normalizeExcerpt(editor.state.doc.textBetween(structural.tableFrom, structural.tableTo, " ", ""));
94990
+ const stableRawId = structural.sourceId ? `word:structural:${structural.sourceId}` : structural.id;
94991
+ grouped.push({
94992
+ rawId: stableRawId,
94993
+ commandRawId: structural.id,
94994
+ id: stableRawId,
94995
+ from: structural.tableFrom,
94996
+ to: structural.tableTo,
94997
+ hasInsert: false,
94998
+ hasDelete: false,
94999
+ hasFormat: false,
95000
+ structural: {
95001
+ side: structural.side,
95002
+ subtype: structural.subtype
95003
+ },
95004
+ attrs: {
95005
+ id: structural.id,
95006
+ sourceId: structural.sourceId || undefined,
95007
+ author: structural.author || undefined,
95008
+ authorEmail: structural.authorEmail || undefined,
95009
+ authorImage: structural.authorImage || undefined,
95010
+ date: structural.date || undefined,
95011
+ importedAuthor: structural.importedAuthor || undefined,
95012
+ origin: structural.sourceId ? "word" : undefined,
95013
+ revisionGroupId: structural.revisionGroupId || undefined
95014
+ },
95015
+ excerpt,
95016
+ wordRevisionIds: structural.sourceId ? structural.side === "insertion" ? { insert: structural.sourceId } : { delete: structural.sourceId } : undefined
95017
+ });
95018
+ }
95019
+ grouped.sort((a, b) => {
95020
+ if (a.from !== b.from)
95021
+ return a.from - b.from;
95022
+ return a.id.localeCompare(b.id);
95023
+ });
94920
95024
  groupedCache.set(editor, {
94921
95025
  doc: currentDoc,
94922
95026
  grouped
@@ -98810,13 +98914,16 @@ var isRegExp = (value) => {
98810
98914
  stampBlockTrackedChangeColors(item.paragraph, resolve);
98811
98915
  break;
98812
98916
  case "table":
98813
- for (const row of block.rows)
98917
+ for (const row of block.rows) {
98918
+ if (row.attrs?.trackedChange)
98919
+ applyColorToLayer(row.attrs.trackedChange, resolve);
98814
98920
  for (const cell of row.cells) {
98815
98921
  stampBlockTrackedChangeColors(cell.paragraph, resolve);
98816
98922
  if (Array.isArray(cell.blocks))
98817
98923
  for (const nested of cell.blocks)
98818
98924
  stampBlockTrackedChangeColors(nested, resolve);
98819
98925
  }
98926
+ }
98820
98927
  break;
98821
98928
  default:
98822
98929
  break;
@@ -99773,6 +99880,9 @@ var isRegExp = (value) => {
99773
99880
  ...params,
99774
99881
  nodes: [tPr]
99775
99882
  });
99883
+ const trackChange = readRowTrackChange(tPr, params);
99884
+ if (trackChange)
99885
+ encodedAttrs["trackChange"] = trackChange;
99776
99886
  const gridBeforeRaw = tableRowProperties?.["gridBefore"];
99777
99887
  const safeGridBefore = typeof gridBeforeRaw === "number" && Number.isFinite(gridBeforeRaw) && gridBeforeRaw > 0 ? gridBeforeRaw : 0;
99778
99888
  const tblPrExBorders = row.elements?.find((el) => el.name === "w:tblPrEx")?.elements?.find((el) => el.name === "w:tblBorders");
@@ -99962,11 +100072,115 @@ var isRegExp = (value) => {
99962
100072
  if (trPr)
99963
100073
  elements.unshift(trPr);
99964
100074
  }
100075
+ applyRowTrackChangeOnDecode({
100076
+ node: node2,
100077
+ elements,
100078
+ params
100079
+ });
99965
100080
  return {
99966
100081
  name: "w:tr",
99967
100082
  attributes: decodedAttrs || {},
99968
100083
  elements
99969
100084
  };
100085
+ }, applyRowTrackChangeOnDecode = ({ node: node2, elements, params }) => {
100086
+ const marker = buildRowTrackChangeElement(node2.attrs?.trackChange, params);
100087
+ if (!marker)
100088
+ return;
100089
+ let trPr = elements.find((el) => el && el.name === "w:trPr");
100090
+ if (!trPr) {
100091
+ trPr = {
100092
+ name: "w:trPr",
100093
+ elements: []
100094
+ };
100095
+ elements.unshift(trPr);
100096
+ }
100097
+ if (!Array.isArray(trPr.elements))
100098
+ trPr.elements = [];
100099
+ const trPrChangeIndex = trPr.elements.findIndex((el) => el && el.name === "w:trPrChange");
100100
+ if (trPrChangeIndex === -1)
100101
+ trPr.elements.push(marker);
100102
+ else
100103
+ trPr.elements.splice(trPrChangeIndex, 0, marker);
100104
+ applyCellContentTrackChange({
100105
+ elements,
100106
+ markerName: marker.name,
100107
+ markerAttributes: marker.attributes
100108
+ });
100109
+ }, applyCellContentTrackChange = ({ elements, markerName, markerAttributes }) => {
100110
+ if (markerName !== "w:ins" && markerName !== "w:del")
100111
+ return;
100112
+ const isDelete = markerName === "w:del";
100113
+ const makeMarker = (children) => ({
100114
+ name: markerName,
100115
+ attributes: { ...markerAttributes },
100116
+ elements: children
100117
+ });
100118
+ const RUN_CONTAINERS = new Set([
100119
+ "w:hyperlink",
100120
+ "w:smartTag",
100121
+ "w:sdt",
100122
+ "w:sdtContent",
100123
+ "w:dir",
100124
+ "w:bdo"
100125
+ ]);
100126
+ const wrapRuns = (content$2) => (Array.isArray(content$2) ? content$2 : []).map((el) => {
100127
+ if (!el || typeof el !== "object")
100128
+ return el;
100129
+ if (el.name === "w:r") {
100130
+ if (isDelete && Array.isArray(el.elements))
100131
+ el.elements = el.elements.map((child) => child?.name === "w:t" ? {
100132
+ ...child,
100133
+ name: "w:delText"
100134
+ } : child);
100135
+ return makeMarker([el]);
100136
+ }
100137
+ if (RUN_CONTAINERS.has(el.name) && Array.isArray(el.elements))
100138
+ return {
100139
+ ...el,
100140
+ elements: wrapRuns(el.elements)
100141
+ };
100142
+ return el;
100143
+ });
100144
+ for (const tc of elements) {
100145
+ if (tc?.name !== "w:tc" || !Array.isArray(tc.elements))
100146
+ continue;
100147
+ for (const paragraph2 of tc.elements) {
100148
+ if (paragraph2?.name !== "w:p")
100149
+ continue;
100150
+ if (!Array.isArray(paragraph2.elements))
100151
+ paragraph2.elements = [];
100152
+ let pPr = paragraph2.elements.find((el) => el?.name === "w:pPr");
100153
+ if (!pPr) {
100154
+ pPr = {
100155
+ name: "w:pPr",
100156
+ elements: []
100157
+ };
100158
+ paragraph2.elements.unshift(pPr);
100159
+ }
100160
+ if (!Array.isArray(pPr.elements))
100161
+ pPr.elements = [];
100162
+ let rPr = pPr.elements.find((el) => el?.name === "w:rPr");
100163
+ if (!rPr) {
100164
+ rPr = {
100165
+ name: "w:rPr",
100166
+ elements: []
100167
+ };
100168
+ const terminalIdx = pPr.elements.findIndex((el) => el?.name === "w:sectPr" || el?.name === "w:pPrChange");
100169
+ if (terminalIdx === -1)
100170
+ pPr.elements.push(rPr);
100171
+ else
100172
+ pPr.elements.splice(terminalIdx, 0, rPr);
100173
+ }
100174
+ if (!Array.isArray(rPr.elements))
100175
+ rPr.elements = [];
100176
+ if (!rPr.elements.some((el) => el?.name === "w:ins" || el?.name === "w:del"))
100177
+ rPr.elements.unshift({
100178
+ name: markerName,
100179
+ attributes: { ...markerAttributes }
100180
+ });
100181
+ paragraph2.elements = wrapRuns(paragraph2.elements);
100182
+ }
100183
+ }
99970
100184
  }, config$30, translator$8, parseAnnotationMarks = (content$2 = {}) => {
99971
100185
  const rPr = content$2.elements?.find((el) => el.name === "w:r")?.elements?.find((el) => el.name === "w:rPr");
99972
100186
  if (!rPr)
@@ -113508,7 +113722,12 @@ var isRegExp = (value) => {
113508
113722
  writingMode,
113509
113723
  rtlGutter
113510
113724
  };
113511
- }, browser2, process5, cachedSetTimeout2, cachedClearTimeout2, queue2, draining2 = false, currentQueue2, queueIndex2 = -1, browserExports2, process$12, TWIPS_PER_INCH$1 = 1440, PX_PER_PT, VALID_TRACKED_MODES, DEFAULT_HYPERLINK_CONFIG, ATOMIC_INLINE_TYPES, TOKEN_INLINE_TYPES, isValidTrackedMode = (value) => {
113725
+ }, browser2, process5, cachedSetTimeout2, cachedClearTimeout2, queue2, draining2 = false, currentQueue2, queueIndex2 = -1, browserExports2, process$12, TWIPS_PER_INCH$1 = 1440, PX_PER_PT, VALID_TRACKED_MODES, DEFAULT_HYPERLINK_CONFIG, ATOMIC_INLINE_TYPES, TOKEN_INLINE_TYPES, RANDOM_ID_LENGTH$1 = 9, generateRandomBase36Id$1 = (length) => {
113726
+ let randomId = "";
113727
+ while (randomId.length < length)
113728
+ randomId += Math.random().toString(36).slice(2);
113729
+ return randomId.slice(0, length);
113730
+ }, isValidTrackedMode = (value) => {
113512
113731
  return typeof value === "string" && VALID_TRACKED_MODES.includes(value);
113513
113732
  }, isTextRun$2 = (run$1) => {
113514
113733
  return "text" in run$1 && run$1.kind !== "tab";
@@ -113517,6 +113736,10 @@ var isRegExp = (value) => {
113517
113736
  delete run$1.trackedChange;
113518
113737
  if ("trackedChanges" in run$1 && run$1.trackedChanges)
113519
113738
  delete run$1.trackedChanges;
113739
+ }, deriveTrackedChangeId$1 = (kind, attrs) => {
113740
+ if (attrs && typeof attrs.id === "string" && attrs.id.trim())
113741
+ return attrs.id;
113742
+ return `${kind}-${attrs && typeof attrs.authorEmail === "string" ? attrs.authorEmail : "unknown"}-${attrs && typeof attrs.date === "string" ? attrs.date : "unknown"}-${`${Date.now()}-${generateRandomBase36Id$1(RANDOM_ID_LENGTH$1)}`}`;
113520
113743
  }, normalizeTrackedChangeLayers$1 = (run$1) => {
113521
113744
  if (Array.isArray(run$1.trackedChanges) && run$1.trackedChanges.length > 0)
113522
113745
  return run$1.trackedChanges;
@@ -114862,7 +115085,7 @@ var isRegExp = (value) => {
114862
115085
  return normalized.length ? normalized : undefined;
114863
115086
  }, pickTrackedChangeKind = (markType) => {
114864
115087
  return TRACK_CHANGE_KIND_MAP[markType];
114865
- }, deriveTrackedChangeId$1 = (kind, attrs) => {
115088
+ }, deriveTrackedChangeId$2 = (kind, attrs) => {
114866
115089
  if (attrs && typeof attrs.id === "string" && attrs.id.trim())
114867
115090
  return attrs.id;
114868
115091
  return `${kind}-${attrs && typeof attrs.authorEmail === "string" ? attrs.authorEmail : "unknown"}-${attrs && typeof attrs.date === "string" ? attrs.date : "unknown"}-${`${Date.now()}-${generateRandomBase36Id(RANDOM_ID_LENGTH)}`}`;
@@ -114873,7 +115096,7 @@ var isRegExp = (value) => {
114873
115096
  const attrs = mark.attrs ?? {};
114874
115097
  const meta3 = {
114875
115098
  kind,
114876
- id: deriveTrackedChangeId$1(kind, attrs)
115099
+ id: deriveTrackedChangeId$2(kind, attrs)
114877
115100
  };
114878
115101
  if (typeof attrs.overlapParentId === "string" && attrs.overlapParentId) {
114879
115102
  meta3.overlapParentId = attrs.overlapParentId;
@@ -116267,6 +116490,27 @@ var isRegExp = (value) => {
116267
116490
  attrs: Object.keys(cellAttrs).length > 0 ? cellAttrs : undefined,
116268
116491
  sourceAnchor: sourceAnchorFromNode$1(cellNode)
116269
116492
  };
116493
+ }, buildRowTrackedChangeMeta = (rowNode, storyKey) => {
116494
+ const trackChange = rowNode.attrs?.trackChange;
116495
+ if (!trackChange || typeof trackChange !== "object")
116496
+ return;
116497
+ const rawType = trackChange.type;
116498
+ if (rawType !== "rowInsert" && rawType !== "rowDelete")
116499
+ return;
116500
+ const kind = rawType === "rowInsert" ? "insert" : "delete";
116501
+ const meta3 = {
116502
+ kind,
116503
+ id: deriveTrackedChangeId$1(kind, trackChange)
116504
+ };
116505
+ if (typeof trackChange.author === "string" && trackChange.author)
116506
+ meta3.author = trackChange.author;
116507
+ if (typeof trackChange.authorEmail === "string" && trackChange.authorEmail)
116508
+ meta3.authorEmail = trackChange.authorEmail;
116509
+ if (typeof trackChange.date === "string" && trackChange.date)
116510
+ meta3.date = trackChange.date;
116511
+ if (typeof storyKey === "string" && storyKey.length > 0)
116512
+ meta3.storyKey = storyKey;
116513
+ return meta3;
116270
116514
  }, parseTableRow = (args) => {
116271
116515
  const { rowNode, rowIndex, context, defaultCellPadding, tableProperties, numRows } = args;
116272
116516
  if (!isTableRowNode(rowNode) || !Array.isArray(rowNode.content))
@@ -116294,13 +116538,19 @@ var isRegExp = (value) => {
116294
116538
  return null;
116295
116539
  const rowProps = rowNode.attrs?.tableRowProperties;
116296
116540
  const rowHeight = normalizeRowHeight(rowProps);
116541
+ const trackedChangesConfig = context.trackedChangesConfig;
116542
+ const rowTrackedChange = trackedChangesConfig?.enabled && trackedChangesConfig.mode !== "off" ? buildRowTrackedChangeMeta(rowNode, context.storyKey) : undefined;
116297
116543
  const tblPrExBordersRaw = rowProps?.tblPrExBorders;
116298
116544
  const rowBorders = tblPrExBordersRaw && typeof tblPrExBordersRaw === "object" ? extractTableBorders(tblPrExBordersRaw, { unit: "eighthPoints" }) : undefined;
116299
116545
  const attrs = rowProps && typeof rowProps === "object" ? {
116300
116546
  tableRowProperties: rowProps,
116301
116547
  ...rowHeight ? { rowHeight } : {},
116548
+ ...rowTrackedChange ? { trackedChange: rowTrackedChange } : {},
116302
116549
  ...rowBorders ? { borders: rowBorders } : {}
116303
- } : rowHeight ? { rowHeight } : undefined;
116550
+ } : rowHeight || rowTrackedChange ? {
116551
+ ...rowHeight ? { rowHeight } : {},
116552
+ ...rowTrackedChange ? { trackedChange: rowTrackedChange } : {}
116553
+ } : undefined;
116304
116554
  return {
116305
116555
  id: context.nextBlockId(`row-${rowIndex}`),
116306
116556
  cells,
@@ -116582,7 +116832,109 @@ var isRegExp = (value) => {
116582
116832
  if (id)
116583
116833
  return trackedChanges.filter(({ mark }) => mark.attrs.id === id);
116584
116834
  return trackedChanges;
116585
- }, groupedCache, SDT_NODE_NAMES, SDT_BLOCK_NAME = "structuredContentBlock", SDT_INLINE_NAME = "structuredContent", SDT_NODE_TYPES, VALID_CONTROL_TYPES, VALID_LOCK_MODES, 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.38.0", SUPERDOC_DOCUMENT_ORIGIN_PROPERTY = "SuperdocDocumentOrigin", STORED_DOCUMENT_ORIGINS, collectRunDefaultProperties = (runProps, { allowOverrideTypeface = true, allowOverrideSize = true, themeResolver, state }) => {
116835
+ }, enumerateStructuralRowChanges = (state) => {
116836
+ const doc$2 = state?.doc;
116837
+ if (!doc$2)
116838
+ return [];
116839
+ const out = [];
116840
+ try {
116841
+ doc$2.descendants((node2, pos) => {
116842
+ if (node2.type?.name !== "table")
116843
+ return;
116844
+ collectTableStructuralChanges({
116845
+ table: node2,
116846
+ tablePos: pos,
116847
+ out
116848
+ });
116849
+ return true;
116850
+ });
116851
+ } catch {
116852
+ return out;
116853
+ }
116854
+ return out;
116855
+ }, collectTableStructuralChanges = ({ table, tablePos, out }) => {
116856
+ const tableFrom = tablePos;
116857
+ const tableTo = tablePos + table.nodeSize;
116858
+ const trackedRows = [];
116859
+ let totalRows = 0;
116860
+ let offset = 1;
116861
+ table.forEach((child) => {
116862
+ const childFrom = tablePos + offset;
116863
+ offset += child.nodeSize;
116864
+ if (child.type?.name !== "tableRow")
116865
+ return;
116866
+ totalRows += 1;
116867
+ const tc = child.attrs?.trackChange;
116868
+ if (!tc || tc.type !== "rowInsert" && tc.type !== "rowDelete")
116869
+ return;
116870
+ const side$1 = tc.type === "rowInsert" ? "insertion" : "deletion";
116871
+ trackedRows.push({
116872
+ ref: {
116873
+ pos: childFrom,
116874
+ from: childFrom,
116875
+ to: childFrom + child.nodeSize,
116876
+ node: child
116877
+ },
116878
+ side: side$1,
116879
+ tc
116880
+ });
116881
+ });
116882
+ if (trackedRows.length === 0)
116883
+ return;
116884
+ const sides = new Set(trackedRows.map((r) => r.side));
116885
+ const everyRowTracked = trackedRows.length === totalRows && totalRows > 0;
116886
+ const singleSide = sides.size === 1;
116887
+ if (everyRowTracked && singleSide) {
116888
+ const side$1 = trackedRows[0].side;
116889
+ const primary$1 = trackedRows[0].tc;
116890
+ const representativeRevisionId$1 = stringOf(primary$1.id) || stringOf(primary$1.sourceId);
116891
+ const publicId = stringOf(primary$1.sourceId) || representativeRevisionId$1 || `table:${tableFrom}:${side$1}`;
116892
+ out.push({
116893
+ id: publicId,
116894
+ revisionId: representativeRevisionId$1,
116895
+ side: side$1,
116896
+ subtype: side$1 === "insertion" ? "table-insert" : "table-delete",
116897
+ tableFrom,
116898
+ tableTo,
116899
+ tablePos,
116900
+ wholeTable: true,
116901
+ decidable: true,
116902
+ rows: trackedRows.map((r) => r.ref),
116903
+ author: stringOf(primary$1.author),
116904
+ authorEmail: stringOf(primary$1.authorEmail),
116905
+ authorImage: stringOf(primary$1.authorImage),
116906
+ date: stringOf(primary$1.date),
116907
+ importedAuthor: stringOf(primary$1.importedAuthor),
116908
+ sourceId: stringOf(primary$1.sourceId),
116909
+ revisionGroupId: stringOf(primary$1.revisionGroupId) || representativeRevisionId$1 || publicId
116910
+ });
116911
+ return;
116912
+ }
116913
+ const side = trackedRows[0].side;
116914
+ const primary = trackedRows[0].tc;
116915
+ const representativeRevisionId = stringOf(primary.id) || stringOf(primary.sourceId);
116916
+ const reason = !everyRowTracked ? "partial-rows" : "mixed-sides";
116917
+ out.push({
116918
+ id: stringOf(primary.sourceId) || representativeRevisionId || `table:${tableFrom}:${side}`,
116919
+ revisionId: representativeRevisionId,
116920
+ side,
116921
+ subtype: side === "insertion" ? "table-insert" : "table-delete",
116922
+ tableFrom,
116923
+ tableTo,
116924
+ tablePos,
116925
+ wholeTable: false,
116926
+ decidable: false,
116927
+ undecidableReason: reason,
116928
+ rows: trackedRows.map((r) => r.ref),
116929
+ author: stringOf(primary.author),
116930
+ authorEmail: stringOf(primary.authorEmail),
116931
+ authorImage: stringOf(primary.authorImage),
116932
+ date: stringOf(primary.date),
116933
+ importedAuthor: stringOf(primary.importedAuthor),
116934
+ sourceId: stringOf(primary.sourceId),
116935
+ revisionGroupId: stringOf(primary.revisionGroupId) || representativeRevisionId
116936
+ });
116937
+ }, stringOf = (value) => typeof value === "string" ? value : value == null ? "" : String(value), groupedCache, SDT_NODE_NAMES, SDT_BLOCK_NAME = "structuredContentBlock", SDT_INLINE_NAME = "structuredContent", SDT_NODE_TYPES, VALID_CONTROL_TYPES, VALID_LOCK_MODES, 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.38.0", SUPERDOC_DOCUMENT_ORIGIN_PROPERTY = "SuperdocDocumentOrigin", STORED_DOCUMENT_ORIGINS, collectRunDefaultProperties = (runProps, { allowOverrideTypeface = true, allowOverrideSize = true, themeResolver, state }) => {
116586
116938
  if (!runProps?.elements?.length || !state)
116587
116939
  return;
116588
116940
  const fontsNode = runProps.elements.find((el) => el.name === "w:rFonts");
@@ -116616,7 +116968,7 @@ var isRegExp = (value) => {
116616
116968
  state.kern = kernNode.attributes["w:val"];
116617
116969
  }
116618
116970
  }, SuperConverter;
116619
- var init_SuperConverter_D2zNnC50_es = __esm(() => {
116971
+ var init_SuperConverter_BBjNvGFh_es = __esm(() => {
116620
116972
  init_rolldown_runtime_Bg48TavK_es();
116621
116973
  init_jszip_C49i9kUs_es();
116622
116974
  init_xml_js_CqGKpaft_es();
@@ -121632,7 +121984,7 @@ var init_SuperConverter_D2zNnC50_es = __esm(() => {
121632
121984
  "trackChanges.list": {
121633
121985
  memberPath: "trackChanges.list",
121634
121986
  description: "List all tracked changes in the document.",
121635
- expectedResult: "Returns a TrackChangesListResult with tracked change entries (`insert`, `delete`, `replacement`, `format`), total count, and raw imported Word OOXML revision IDs (`w:id`) when available.",
121987
+ expectedResult: "Returns a TrackChangesListResult with tracked change entries (`insert`, `delete`, `replacement`, `format`, `structural`), total count, and raw imported Word OOXML revision IDs (`w:id`) when available. Structural changes (whole-table insert/delete) carry a `subtype` of `table-insert` or `table-delete`.",
121636
121988
  requiresDocumentContext: true,
121637
121989
  metadata: readOperation({
121638
121990
  idempotency: "idempotent",
@@ -121646,7 +121998,7 @@ var init_SuperConverter_D2zNnC50_es = __esm(() => {
121646
121998
  "trackChanges.get": {
121647
121999
  memberPath: "trackChanges.get",
121648
122000
  description: "Retrieve a single tracked change by ID.",
121649
- expectedResult: "Returns a TrackChangeInfo object with the change type (`insert`, `delete`, `replacement`, `format`), author, date, affected content, and raw imported Word OOXML revision IDs (`w:id`) when available.",
122001
+ expectedResult: "Returns a TrackChangeInfo object with the change type (`insert`, `delete`, `replacement`, `format`, `structural`), author, date, affected content, and raw imported Word OOXML revision IDs (`w:id`) when available. Structural changes (whole-table insert/delete) carry a `subtype` of `table-insert` or `table-delete`.",
121650
122002
  requiresDocumentContext: true,
121651
122003
  metadata: readOperation({
121652
122004
  idempotency: "idempotent",
@@ -126145,7 +126497,8 @@ var init_SuperConverter_D2zNnC50_es = __esm(() => {
126145
126497
  "insert",
126146
126498
  "delete",
126147
126499
  "replacement",
126148
- "format"
126500
+ "format",
126501
+ "structural"
126149
126502
  ];
126150
126503
  nodeTypeValues = NODE_TYPES;
126151
126504
  blockNodeTypeValues = BLOCK_NODE_TYPES;
@@ -127175,6 +127528,10 @@ var init_SuperConverter_D2zNnC50_es = __esm(() => {
127175
127528
  address: trackedChangeAddressSchema,
127176
127529
  id: { type: "string" },
127177
127530
  type: { enum: [...trackChangeTypeValues] },
127531
+ subtype: {
127532
+ enum: ["table-insert", "table-delete"],
127533
+ description: "Finer classification for structural changes (type === 'structural')."
127534
+ },
127178
127535
  grouping: { enum: [
127179
127536
  "standalone",
127180
127537
  "replacement-pair",
@@ -127197,6 +127554,10 @@ var init_SuperConverter_D2zNnC50_es = __esm(() => {
127197
127554
  discoveryResultSchema(discoveryItemSchema({
127198
127555
  address: trackedChangeAddressSchema,
127199
127556
  type: { enum: [...trackChangeTypeValues] },
127557
+ subtype: {
127558
+ enum: ["table-insert", "table-delete"],
127559
+ description: "Finer classification for structural changes (type === 'structural')."
127560
+ },
127200
127561
  grouping: { enum: [
127201
127562
  "standalone",
127202
127563
  "replacement-pair",
@@ -129691,7 +130052,7 @@ var init_SuperConverter_D2zNnC50_es = __esm(() => {
129691
130052
  },
129692
130053
  type: {
129693
130054
  enum: [...trackChangeTypeValues],
129694
- description: "Filter by change type: 'insert', 'delete', 'replacement', or 'format'."
130055
+ description: "Filter by change type: 'insert', 'delete', 'replacement', 'format', or 'structural'."
129695
130056
  },
129696
130057
  in: {
129697
130058
  oneOf: [storyLocatorSchema, { const: "all" }],
@@ -129702,7 +130063,11 @@ var init_SuperConverter_D2zNnC50_es = __esm(() => {
129702
130063
  story: storyLocatorSchema
129703
130064
  }, ["id"]), objectSchema({
129704
130065
  id: { type: "string" },
129705
- story: storyLocatorSchema
130066
+ story: storyLocatorSchema,
130067
+ range: {
130068
+ type: "object",
130069
+ description: "Partial-range qualifier on an id target. Rejected with INVALID_INPUT for indivisible (e.g. structural) revisions."
130070
+ }
129706
130071
  }, ["id"]), objectSchema({
129707
130072
  kind: { const: "range" },
129708
130073
  range: textTargetSchema,
@@ -155663,7 +156028,7 @@ var init_SuperConverter_D2zNnC50_es = __esm(() => {
155663
156028
  };
155664
156029
  });
155665
156030
 
155666
- // ../../packages/superdoc/dist/chunks/create-headless-toolbar-COmoIa5Q.es.js
156031
+ // ../../packages/superdoc/dist/chunks/create-headless-toolbar-s_kl3MP8.es.js
155667
156032
  function parseSizeUnit(val = "0") {
155668
156033
  const length = val.toString() || "0";
155669
156034
  const value = Number.parseFloat(length);
@@ -165996,8 +166361,8 @@ var CSS_DIMENSION_REGEX, DOM_SIZE_UNITS, normalizeActorId = (value) => {
165996
166361
  }
165997
166362
  };
165998
166363
  };
165999
- var init_create_headless_toolbar_COmoIa5Q_es = __esm(() => {
166000
- init_SuperConverter_D2zNnC50_es();
166364
+ var init_create_headless_toolbar_s_kl3MP8_es = __esm(() => {
166365
+ init_SuperConverter_BBjNvGFh_es();
166001
166366
  init_uuid_qzgm05fK_es();
166002
166367
  init_constants_D9qj59G2_es();
166003
166368
  init_dist_B8HfvhaK_es();
@@ -220681,7 +221046,7 @@ var init_remark_gfm_eZN6yzWQ_es = __esm(() => {
220681
221046
  init_remark_gfm_BhnWr3yf_es();
220682
221047
  });
220683
221048
 
220684
- // ../../packages/superdoc/dist/chunks/src-eTZqPcFn.es.js
221049
+ // ../../packages/superdoc/dist/chunks/src-DeS9kJS7.es.js
220685
221050
  function deleteProps(obj, propOrProps) {
220686
221051
  const props = typeof propOrProps === "string" ? [propOrProps] : propOrProps;
220687
221052
  const removeNested = (target, pathParts, index2 = 0) => {
@@ -237349,6 +237714,7 @@ function buildProjectedInfo(snapshot2, options = {}) {
237349
237714
  },
237350
237715
  id: id2,
237351
237716
  type,
237717
+ ...type === "structural" && snapshot2.subtype ? { subtype: snapshot2.subtype } : {},
237352
237718
  grouping: options.grouping,
237353
237719
  pairedWithChangeId: options.pairedWithChangeId ?? undefined,
237354
237720
  wordRevisionIds: normalizeWordRevisionIds(snapshot2.wordRevisionIds),
@@ -237604,10 +237970,11 @@ function trackChangesListWrapper(editor, input2) {
237604
237970
  const items = paged.items.map((row2) => {
237605
237971
  const info = row2.info;
237606
237972
  const handle3 = buildResolvedHandle(row2.handleKey, "stable", "trackedChange");
237607
- const { address, type, grouping, pairedWithChangeId, wordRevisionIds, overlap, author, authorEmail, authorImage, date: date6, excerpt, insertedText, deletedText, origin, imported } = info;
237973
+ const { address, type, subtype, grouping, pairedWithChangeId, wordRevisionIds, overlap, author, authorEmail, authorImage, date: date6, excerpt, insertedText, deletedText, origin, imported } = info;
237608
237974
  return buildDiscoveryItem(info.id, handle3, {
237609
237975
  address,
237610
237976
  type,
237977
+ ...subtype ? { subtype } : {},
237611
237978
  grouping,
237612
237979
  pairedWithChangeId,
237613
237980
  wordRevisionIds,
@@ -237670,6 +238037,7 @@ function trackChangesGetWrapper(editor, input2) {
237670
238037
  },
237671
238038
  id: resolved.change.id,
237672
238039
  type,
238040
+ ...type === "structural" && resolved.change.structural ? { subtype: resolved.change.structural.subtype } : {},
237673
238041
  grouping,
237674
238042
  wordRevisionIds: normalizeWordRevisionIds(resolved.change.wordRevisionIds),
237675
238043
  overlap: resolved.change.overlap,
@@ -282892,7 +283260,8 @@ var Node$13 = class Node$14 {
282892
283260
  if (!meta4) {
282893
283261
  let mightAffectTrackChanges = false;
282894
283262
  tr.steps.forEach((step2) => {
282895
- if (step2.slice || step2.from !== step2.to)
283263
+ const replaceStep$2 = step2;
283264
+ if (replaceStep$2.slice || replaceStep$2.from !== replaceStep$2.to)
282896
283265
  mightAffectTrackChanges = true;
282897
283266
  });
282898
283267
  if (mightAffectTrackChanges)
@@ -282923,8 +283292,9 @@ var Node$13 = class Node$14 {
282923
283292
  return DecorationSet.empty;
282924
283293
  const decorations = [];
282925
283294
  const trackedChanges = getTrackChanges(state);
283295
+ addStructuralRowDecorations(decorations, state, onlyOriginalShown, onlyModifiedShown);
282926
283296
  if (!trackedChanges.length)
282927
- return DecorationSet.empty;
283297
+ return decorations.length ? DecorationSet.create(state.doc, decorations) : DecorationSet.empty;
282928
283298
  trackedChanges.forEach(({ mark: mark2, from: from$1, to }) => {
282929
283299
  if (mark2.type.name === "trackInsert")
282930
283300
  if (onlyOriginalShown) {
@@ -282970,6 +283340,27 @@ var Node$13 = class Node$14 {
282970
283340
  }
282971
283341
  });
282972
283342
  return DecorationSet.create(state.doc, decorations);
283343
+ }, addStructuralRowDecorations = (decorations, state, onlyOriginalShown, onlyModifiedShown) => {
283344
+ const structuralChanges = enumerateStructuralRowChanges(state);
283345
+ if (!structuralChanges.length)
283346
+ return;
283347
+ for (const change of structuralChanges) {
283348
+ const isInsert = change.side === "insertion";
283349
+ const baseClass = isInsert ? "track-row-insert-dec" : "track-row-delete-dec";
283350
+ let mode = "highlighted";
283351
+ if (onlyOriginalShown)
283352
+ mode = isInsert ? "hidden" : "normal";
283353
+ else if (onlyModifiedShown)
283354
+ mode = isInsert ? "normal" : "hidden";
283355
+ for (const row2 of change.rows)
283356
+ decorations.push(Decoration.node(row2.from, row2.to, {
283357
+ class: `${baseClass} ${mode}`,
283358
+ "data-track-change-id": change.id,
283359
+ "data-track-change-kind": change.subtype,
283360
+ "data-track-change-author": change.author || "",
283361
+ "data-track-change-date": change.date || ""
283362
+ }));
283363
+ }
282973
283364
  }, resolveCommentMeta = ({ converter, importedId }) => {
282974
283365
  const matchingImportedComment = (converter?.comments || []).find((c) => c.importedId == importedId);
282975
283366
  const resolvedCommentId = matchingImportedComment?.commentId ?? (importedId ? String(importedId) : v4_default());
@@ -288962,11 +289353,12 @@ var Node$13 = class Node$14 {
288962
289353
  }, BODY_STORY, buildReviewGraph = ({ state, story = BODY_STORY, replacementsMode = "paired" }) => {
288963
289354
  return buildGraphFromSpans({
288964
289355
  spans: enumerateTrackedMarkSpans(state),
289356
+ structuralChanges: enumerateStructuralRowChanges(state),
288965
289357
  doc: state?.doc ?? null,
288966
289358
  story,
288967
289359
  replacementsMode
288968
289360
  });
288969
- }, buildGraphFromSpans = ({ spans, doc: doc$12, story, replacementsMode }) => {
289361
+ }, buildGraphFromSpans = ({ spans, structuralChanges = [], doc: doc$12, story, replacementsMode }) => {
288970
289362
  const mergedSegments = mergeAdjacentSpans(spans.map((span) => ({
288971
289363
  attrs: readTrackedAttrs(span.mark, span.mark.type.name),
288972
289364
  span
@@ -289025,7 +289417,26 @@ var Node$13 = class Node$14 {
289025
289417
  for (const segs of segmentsByChangeId.values())
289026
289418
  for (const seg of segs)
289027
289419
  bySegmentId.set(seg.segmentId, seg);
289028
- const segments = mergedSegments;
289420
+ for (const structural of structuralChanges) {
289421
+ const logical = buildStructuralLogicalChange({
289422
+ structural,
289423
+ doc: doc$12,
289424
+ story
289425
+ });
289426
+ if (!logical)
289427
+ continue;
289428
+ const internalKey = `structural:${structural.tablePos}:${structural.side}`;
289429
+ if (changes.has(internalKey))
289430
+ continue;
289431
+ changes.set(internalKey, logical);
289432
+ if (logical.id && logical.id !== internalKey && !changes.has(logical.id))
289433
+ changes.set(logical.id, logical);
289434
+ for (const seg of logical.segments)
289435
+ bySegmentId.set(seg.segmentId, seg);
289436
+ mergedSegments.push(...logical.segments);
289437
+ appendToMap(byRevisionGroupId, logical.revisionGroupId, logical.id);
289438
+ }
289439
+ const segments = mergedSegments.slice().sort((a2, b$1) => a2.from - b$1.from || a2.to - b$1.to);
289029
289440
  const graph = {
289030
289441
  changes,
289031
289442
  segments,
@@ -289189,6 +289600,90 @@ var Node$13 = class Node$14 {
289189
289600
  enumerable: false
289190
289601
  });
289191
289602
  return logical;
289603
+ }, buildStructuralLogicalChange = ({ structural, doc: doc$12, story }) => {
289604
+ const side = structural.side === "insertion" ? SegmentSide.Inserted : SegmentSide.Deleted;
289605
+ const from$1 = structural.tableFrom;
289606
+ const to = structural.tableTo;
289607
+ if (!(from$1 < to))
289608
+ return null;
289609
+ const attrs = {
289610
+ id: structural.id,
289611
+ revisionGroupId: structural.revisionGroupId,
289612
+ splitFromId: "",
289613
+ changeType: CanonicalChangeType.Structural,
289614
+ replacementGroupId: "",
289615
+ replacementSideId: "",
289616
+ overlapParentId: "",
289617
+ sourceIds: structural.sourceId ? { wordIdStructural: structural.sourceId } : {},
289618
+ sourceId: structural.sourceId,
289619
+ importedAuthor: structural.importedAuthor,
289620
+ origin: structural.sourceId ? "word" : "",
289621
+ author: structural.author,
289622
+ authorId: "",
289623
+ authorEmail: structural.authorEmail,
289624
+ authorImage: structural.authorImage,
289625
+ date: structural.date,
289626
+ markType: "",
289627
+ side,
289628
+ subtype: structural.subtype,
289629
+ explicitChangeType: CanonicalChangeType.Structural,
289630
+ hasReviewMetadata: true
289631
+ };
289632
+ const segment = {
289633
+ segmentId: `${structural.id}:structural:${from$1}:${to}:0`,
289634
+ changeId: structural.id,
289635
+ markType: "",
289636
+ side,
289637
+ from: from$1,
289638
+ to,
289639
+ text: "",
289640
+ mark: null,
289641
+ markRuns: [],
289642
+ attrs,
289643
+ parentId: "",
289644
+ parentSide: "",
289645
+ overlapRole: "standalone",
289646
+ structural: true
289647
+ };
289648
+ if (doc$12)
289649
+ try {
289650
+ segment.text = doc$12.textBetween(from$1, to, " ", "");
289651
+ } catch {
289652
+ segment.text = "";
289653
+ }
289654
+ const segments = [segment];
289655
+ const logical = {
289656
+ id: structural.id,
289657
+ type: CanonicalChangeType.Structural,
289658
+ subtype: structural.subtype,
289659
+ state: "open",
289660
+ segments,
289661
+ coverageSegments: [...segments],
289662
+ insertedSegments: side === SegmentSide.Inserted ? [...segments] : [],
289663
+ deletedSegments: side === SegmentSide.Deleted ? [...segments] : [],
289664
+ formattingSegments: [],
289665
+ replacement: null,
289666
+ author: structural.author,
289667
+ authorId: "",
289668
+ authorEmail: structural.authorEmail,
289669
+ authorImage: structural.authorImage,
289670
+ date: structural.date,
289671
+ sourceIds: attrs.sourceIds,
289672
+ revisionGroupId: structural.revisionGroupId,
289673
+ splitFromId: "",
289674
+ sourcePlatform: structural.sourceId ? "word" : "",
289675
+ story,
289676
+ parent: null,
289677
+ children: [],
289678
+ before: [],
289679
+ after: [],
289680
+ excerpt: segment.text.length > 200 ? `${segment.text.slice(0, 200)}…` : segment.text
289681
+ };
289682
+ Object.defineProperty(logical, "structural", {
289683
+ value: structural,
289684
+ enumerable: false
289685
+ });
289686
+ return logical;
289192
289687
  }, aggregateSourceIds = (segments) => {
289193
289688
  const out = {};
289194
289689
  const sorted = [...segments].sort((a2, b$1) => {
@@ -290629,7 +291124,170 @@ var Node$13 = class Node$14 {
290629
291124
  date: date6,
290630
291125
  source
290631
291126
  };
290632
- }, findDocPosByTextOffset = ({ doc: doc$12, from: from$1, to, textOffset }) => {
291127
+ }, collectWholeTablesInRange = ({ doc: doc$12, from: from$1, to }) => {
291128
+ if (!doc$12 || typeof from$1 !== "number" || typeof to !== "number" || to <= from$1)
291129
+ return [];
291130
+ const boundedFrom = Math.max(0, from$1);
291131
+ const boundedTo = Math.min(doc$12.content.size, to);
291132
+ if (boundedTo <= boundedFrom)
291133
+ return [];
291134
+ const tables = [];
291135
+ doc$12.nodesBetween(boundedFrom, boundedTo, (node2, pos) => {
291136
+ if (node2.type?.name !== "table")
291137
+ return true;
291138
+ if (pos >= boundedFrom && pos + node2.nodeSize <= boundedTo) {
291139
+ tables.push({
291140
+ pos,
291141
+ node: node2,
291142
+ from: pos,
291143
+ to: pos + node2.nodeSize
291144
+ });
291145
+ return false;
291146
+ }
291147
+ return true;
291148
+ });
291149
+ return tables;
291150
+ }, stampTableRows = ({ type, tr, from: from$1, to, user, date: date6 }) => {
291151
+ if (type !== "rowInsert" && type !== "rowDelete")
291152
+ return false;
291153
+ const tables = collectWholeTablesInRange({
291154
+ doc: tr.doc,
291155
+ from: from$1,
291156
+ to
291157
+ });
291158
+ if (!tables.length)
291159
+ return false;
291160
+ let stamped = false;
291161
+ for (const { pos: tablePos, node: tableNode } of tables) {
291162
+ const revisionGroupId = v4_default();
291163
+ let offset$1 = 1;
291164
+ const rowPositions = [];
291165
+ tableNode.forEach((child) => {
291166
+ const childPos = tablePos + offset$1;
291167
+ offset$1 += child.nodeSize;
291168
+ if (child.type?.name === "tableRow")
291169
+ rowPositions.push(childPos);
291170
+ });
291171
+ for (const rowPos of rowPositions) {
291172
+ const rowNode = tr.doc.nodeAt(rowPos);
291173
+ if (!rowNode || rowNode.type?.name !== "tableRow")
291174
+ continue;
291175
+ if (rowNode.attrs?.trackChange)
291176
+ continue;
291177
+ const trackChange = {
291178
+ type,
291179
+ id: v4_default(),
291180
+ author: user?.name || "",
291181
+ authorId: user?.id || "",
291182
+ authorEmail: user?.email || "",
291183
+ authorImage: user?.image || "",
291184
+ date: date6,
291185
+ revisionGroupId
291186
+ };
291187
+ tr.setNodeMarkup(rowPos, undefined, {
291188
+ ...rowNode.attrs,
291189
+ trackChange
291190
+ });
291191
+ stamped = true;
291192
+ }
291193
+ }
291194
+ return stamped;
291195
+ }, markDeletion = ({ tr, from: from$1, to, user, date: date6, id: providedId }) => {
291196
+ const currentIdentity = getCurrentUserIdentity({ options: { user } });
291197
+ const isOwnInsertion = (mark2) => {
291198
+ const changeIdentity = getChangeAuthorIdentity(mark2);
291199
+ if (matchesSameUserRefinement({
291200
+ currentUser: currentIdentity,
291201
+ change: changeIdentity
291202
+ }))
291203
+ return true;
291204
+ if (!changeIdentity.hasId && !changeIdentity.hasEmail)
291205
+ return shouldCollapseNoEmailInsertion({
291206
+ currentUser: user,
291207
+ insertionAttrs: mark2?.attrs
291208
+ });
291209
+ return false;
291210
+ };
291211
+ const trackedMark = findTrackedMarkBetween({
291212
+ tr,
291213
+ from: from$1,
291214
+ to,
291215
+ markName: TrackDeleteMarkName,
291216
+ predicate: (mark2) => matchesSameUserRefinement({
291217
+ currentUser: currentIdentity,
291218
+ change: getChangeAuthorIdentity(mark2)
291219
+ })
291220
+ });
291221
+ let id2;
291222
+ if (providedId)
291223
+ id2 = providedId;
291224
+ else if (trackedMark)
291225
+ id2 = trackedMark.mark.attrs.id;
291226
+ else
291227
+ id2 = v4_default();
291228
+ const deletionMark = tr.doc.type.schema.marks[TrackDeleteMarkName].create({
291229
+ id: id2,
291230
+ author: user.name || "",
291231
+ authorId: user.id || "",
291232
+ authorEmail: user.email || "",
291233
+ authorImage: user.image || "",
291234
+ date: date6
291235
+ });
291236
+ const deletionMap = new Mapping;
291237
+ const shouldReassignExistingDeletions = Boolean(providedId);
291238
+ let nodes = [];
291239
+ tr.doc.nodesBetween(from$1, to, (node2, pos) => {
291240
+ if (node2.type.name.includes("table"))
291241
+ return;
291242
+ if (!node2.isInline || !node2.isLeaf)
291243
+ return;
291244
+ const mappedFrom = deletionMap.map(Math.max(from$1, pos));
291245
+ const mappedTo = deletionMap.map(Math.min(to, pos + node2.nodeSize));
291246
+ if (mappedFrom >= mappedTo)
291247
+ return;
291248
+ const insertMark = node2.marks.find((mark2) => mark2.type.name === TrackInsertMarkName);
291249
+ const existingDeleteMarks = node2.marks.filter((mark2) => mark2.type.name === TrackDeleteMarkName);
291250
+ if (insertMark && isOwnInsertion(insertMark)) {
291251
+ const removeStep = new ReplaceStep(mappedFrom, mappedTo, Slice.empty);
291252
+ if (!tr.maybeStep(removeStep).failed)
291253
+ deletionMap.appendMap(removeStep.getMap());
291254
+ return;
291255
+ }
291256
+ if (existingDeleteMarks.length > 0) {
291257
+ if (shouldReassignExistingDeletions) {
291258
+ nodes.push(node2);
291259
+ existingDeleteMarks.forEach((existingDeleteMark) => {
291260
+ tr.removeMark(mappedFrom, mappedTo, existingDeleteMark);
291261
+ });
291262
+ tr.addMark(mappedFrom, mappedTo, deletionMark);
291263
+ }
291264
+ return;
291265
+ }
291266
+ nodes.push(node2);
291267
+ tr.addMark(mappedFrom, mappedTo, deletionMark);
291268
+ });
291269
+ return {
291270
+ deletionMark,
291271
+ deletionMap,
291272
+ nodes
291273
+ };
291274
+ }, sliceContainsTable = (slice2) => {
291275
+ const content3 = slice2?.content;
291276
+ if (!content3)
291277
+ return false;
291278
+ let found2 = false;
291279
+ content3.forEach((node2) => {
291280
+ if (found2)
291281
+ return;
291282
+ if (node2?.type?.name === "table")
291283
+ found2 = true;
291284
+ });
291285
+ return found2;
291286
+ }, rangeContainsWholeTable = ({ doc: doc$12, from: from$1, to }) => collectWholeTablesInRange({
291287
+ doc: doc$12,
291288
+ from: from$1,
291289
+ to
291290
+ }).length > 0, findDocPosByTextOffset = ({ doc: doc$12, from: from$1, to, textOffset }) => {
290633
291291
  let remaining = textOffset;
290634
291292
  let foundPos = null;
290635
291293
  doc$12.nodesBetween(from$1, to, (node2, pos) => {
@@ -290738,7 +291396,139 @@ var Node$13 = class Node$14 {
290738
291396
  return;
290739
291397
  }
290740
291398
  }
291399
+ }, tryStructuralTableInsert = ({ newTr, step: step2, map: map$12, user, date: date6 }) => {
291400
+ const beforeSteps = newTr.steps.length;
291401
+ const beforeSize = newTr.doc.content.size;
291402
+ const insertAt = step2.from;
291403
+ const replacedLength = step2.to - step2.from;
291404
+ if (step2.from !== step2.to) {
291405
+ let hasRealContent = false;
291406
+ newTr.doc.nodesBetween(step2.from, step2.to, (node2) => {
291407
+ if (hasRealContent)
291408
+ return false;
291409
+ if (node2.isText && node2.text || node2.isLeaf && !node2.isText)
291410
+ hasRealContent = true;
291411
+ return !hasRealContent;
291412
+ });
291413
+ if (hasRealContent)
291414
+ return { handled: false };
291415
+ }
291416
+ if (newTr.maybeStep(step2).failed)
291417
+ return { handled: false };
291418
+ const stepMap = newTr.steps[beforeSteps].getMap();
291419
+ map$12.appendMap(stepMap);
291420
+ const insertedFrom = insertAt;
291421
+ const insertedTo = insertAt + (newTr.doc.content.size - beforeSize) + replacedLength;
291422
+ if (insertedTo > insertedFrom) {
291423
+ let hasInlineText = false;
291424
+ newTr.doc.nodesBetween(insertedFrom, insertedTo, (node2) => {
291425
+ if (node2.isText && node2.text) {
291426
+ hasInlineText = true;
291427
+ return false;
291428
+ }
291429
+ });
291430
+ if (hasInlineText)
291431
+ markInsertion({
291432
+ tr: newTr,
291433
+ from: insertedFrom,
291434
+ to: insertedTo,
291435
+ user,
291436
+ date: date6
291437
+ });
291438
+ }
291439
+ stampTableRows({
291440
+ type: "rowInsert",
291441
+ tr: newTr,
291442
+ from: insertedFrom,
291443
+ to: insertedTo,
291444
+ user,
291445
+ date: date6
291446
+ });
291447
+ newTr.setMeta(TrackChangesBasePluginKey, { insertedTo });
291448
+ newTr.setMeta(CommentsPluginKey, { type: "force" });
291449
+ return { handled: true };
291450
+ }, tryStructuralTableDelete = ({ newTr, step: step2, map: map$12, originalStep, originalStepIndex, tr, user, date: date6 }) => {
291451
+ const from$1 = step2.from;
291452
+ const to = step2.to;
291453
+ const tableRanges = collectWholeTablesInRange({
291454
+ doc: newTr.doc,
291455
+ from: from$1,
291456
+ to
291457
+ });
291458
+ let hasOutsideText = false;
291459
+ newTr.doc.nodesBetween(from$1, to, (node2, pos) => {
291460
+ if (hasOutsideText)
291461
+ return false;
291462
+ if (node2.isText && node2.text && !tableRanges.some((r$1) => pos >= r$1.from && pos < r$1.to)) {
291463
+ hasOutsideText = true;
291464
+ return false;
291465
+ }
291466
+ });
291467
+ if (hasOutsideText)
291468
+ return { handled: false };
291469
+ let hasInlineText = false;
291470
+ newTr.doc.nodesBetween(from$1, to, (node2) => {
291471
+ if (node2.isText && node2.text) {
291472
+ hasInlineText = true;
291473
+ return false;
291474
+ }
291475
+ });
291476
+ if (hasInlineText)
291477
+ markDeletion({
291478
+ tr: newTr,
291479
+ from: from$1,
291480
+ to,
291481
+ user,
291482
+ date: date6
291483
+ });
291484
+ if (!stampTableRows({
291485
+ type: "rowDelete",
291486
+ tr: newTr,
291487
+ from: from$1,
291488
+ to,
291489
+ user,
291490
+ date: date6
291491
+ }) && !hasInlineText)
291492
+ return { handled: false };
291493
+ if (map$12 && originalStep && tr)
291494
+ try {
291495
+ const invertStep = originalStep.invert(tr.docs[originalStepIndex]).map(map$12);
291496
+ if (invertStep)
291497
+ map$12.appendMap(invertStep.getMap());
291498
+ } catch {}
291499
+ newTr.setMeta(TrackChangesBasePluginKey, {});
291500
+ newTr.setMeta(CommentsPluginKey, { type: "force" });
291501
+ return { handled: true };
290741
291502
  }, tryCompileStep = ({ state, tr, newTr, step: step2, stepWasNormalized, originalStep, originalStepIndex, map: map$12, user, date: date6, replacements }) => {
291503
+ if (step2.slice.content.size > 0 && sliceContainsTable(step2.slice)) {
291504
+ const structural = tryStructuralTableInsert({
291505
+ newTr,
291506
+ step: step2,
291507
+ map: map$12,
291508
+ user,
291509
+ date: date6
291510
+ });
291511
+ if (structural.handled)
291512
+ return structural;
291513
+ }
291514
+ if (step2.from !== step2.to && step2.slice.content.size === 0 && rangeContainsWholeTable({
291515
+ doc: newTr.doc,
291516
+ from: step2.from,
291517
+ to: step2.to
291518
+ })) {
291519
+ const structural = tryStructuralTableDelete({
291520
+ newTr,
291521
+ step: step2,
291522
+ map: map$12,
291523
+ originalStep,
291524
+ originalStepIndex,
291525
+ tr,
291526
+ user,
291527
+ date: date6
291528
+ });
291529
+ if (structural.handled)
291530
+ return structural;
291531
+ }
290742
291532
  if (step2.from !== step2.to && step2.slice.content.size === 0) {
290743
291533
  let hasInlineContent = false;
290744
291534
  newTr.doc.nodesBetween(step2.from, step2.to, (node2) => {
@@ -290842,6 +291632,15 @@ var Node$13 = class Node$14 {
290842
291632
  meta4.selectionPos = result.selection.pos;
290843
291633
  newTr.setMeta(TrackChangesBasePluginKey, meta4);
290844
291634
  newTr.setMeta(CommentsPluginKey, { type: "force" });
291635
+ if (typeof result.insertedTo === "number" && result.insertedTo > step2.from)
291636
+ stampTableRows({
291637
+ type: "rowInsert",
291638
+ tr: newTr,
291639
+ from: step2.from,
291640
+ to: result.insertedTo,
291641
+ user,
291642
+ date: date6
291643
+ });
290845
291644
  return {
290846
291645
  handled: true,
290847
291646
  sizeDelta: newTr.doc.content.size - beforeSize
@@ -291565,8 +292364,7 @@ var Node$13 = class Node$14 {
291565
292364
  state,
291566
292365
  graph,
291567
292366
  selections,
291568
- decision,
291569
- replacements
292367
+ decision
291570
292368
  });
291571
292369
  if (!planResult.ok)
291572
292370
  return planResult.failure;
@@ -291661,10 +292459,20 @@ var Node$13 = class Node$14 {
291661
292459
  ok: false,
291662
292460
  failure: failure$3("INVALID_TARGET", "decision target shape was not recognised.")
291663
292461
  };
292462
+ }, resolveLogicalChangeById = (graph, id2) => {
292463
+ const key2 = String(id2);
292464
+ for (const candidate of graph.changes.values())
292465
+ if (candidate?.type === CanonicalChangeType.Structural && String(candidate.id) === key2)
292466
+ return candidate;
292467
+ return graph.changes.get(id2);
291664
292468
  }, resolveTargetToSelections = ({ graph, normalized }) => {
291665
292469
  if (normalized.kind === "all") {
291666
292470
  const sel = [];
291667
- for (const change of graph.changes.values())
292471
+ const seen = /* @__PURE__ */ new Set;
292472
+ for (const change of graph.changes.values()) {
292473
+ if (seen.has(change))
292474
+ continue;
292475
+ seen.add(change);
291668
292476
  sel.push({
291669
292477
  change,
291670
292478
  coverage: "full",
@@ -291673,6 +292481,7 @@ var Node$13 = class Node$14 {
291673
292481
  to: s2.to
291674
292482
  }))
291675
292483
  });
292484
+ }
291676
292485
  sel.sort((a2, b$1) => firstFrom(a2) - firstFrom(b$1));
291677
292486
  return {
291678
292487
  ok: true,
@@ -291680,7 +292489,7 @@ var Node$13 = class Node$14 {
291680
292489
  };
291681
292490
  }
291682
292491
  if (normalized.kind === "id") {
291683
- const change = graph.changes.get(normalized.id);
292492
+ const change = resolveLogicalChangeById(graph, normalized.id);
291684
292493
  if (!change)
291685
292494
  return {
291686
292495
  ok: false,
@@ -291705,7 +292514,7 @@ var Node$13 = class Node$14 {
291705
292514
  const overlapTo = Math.min(segment.to, to);
291706
292515
  if (overlapFrom >= overlapTo) {
291707
292516
  if (from$1 === to && segment.from <= from$1 && segment.to > from$1) {
291708
- const change$1 = graph.changes.get(segment.changeId);
292517
+ const change$1 = resolveLogicalChangeById(graph, segment.changeId);
291709
292518
  if (!change$1)
291710
292519
  continue;
291711
292520
  const existing$1 = byId.get(change$1.id);
@@ -291727,7 +292536,7 @@ var Node$13 = class Node$14 {
291727
292536
  }
291728
292537
  continue;
291729
292538
  }
291730
- const change = graph.changes.get(segment.changeId);
292539
+ const change = resolveLogicalChangeById(graph, segment.changeId);
291731
292540
  if (!change)
291732
292541
  continue;
291733
292542
  const existing = byId.get(change.id);
@@ -291825,17 +292634,137 @@ var Node$13 = class Node$14 {
291825
292634
  };
291826
292635
  }
291827
292636
  return { ok: true };
291828
- }, buildMutationPlan = ({ state, graph, selections, decision, replacements }) => {
292637
+ }, buildMutationPlan = ({ state, graph, selections, decision }) => {
291829
292638
  const ops = [];
291830
292639
  const removedRanges = [];
291831
292640
  const resolvedRanges = [];
291832
292641
  const touched = /* @__PURE__ */ new Set;
291833
292642
  const retired = /* @__PURE__ */ new Set;
291834
292643
  const diagnostics = [];
292644
+ const structuralTableRemovals = [];
292645
+ for (const selection of selections) {
292646
+ const change = selection.change;
292647
+ if (change.type !== CanonicalChangeType.Structural)
292648
+ continue;
292649
+ const structural = change.structural;
292650
+ if (!structural || structural.wholeTable !== true || structural.decidable === false)
292651
+ continue;
292652
+ if (!(structural.side === "insertion" && decision === "reject" || structural.side === "deletion" && decision === "accept"))
292653
+ continue;
292654
+ structuralTableRemovals.push({
292655
+ from: structural.tableFrom,
292656
+ to: structural.tableTo,
292657
+ structuralId: change.id
292658
+ });
292659
+ }
292660
+ const suppressedInsideTable = /* @__PURE__ */ new Set;
292661
+ const isInsideRemovedTable = (change) => structuralTableRemovals.length > 0 && change.type !== CanonicalChangeType.Structural && change.segments.length > 0 && change.segments.every((seg) => structuralTableRemovals.some((range) => range.from <= seg.from && range.to >= seg.to));
292662
+ const structuralTableStays = [];
292663
+ for (const selection of selections) {
292664
+ const change = selection.change;
292665
+ if (change.type !== CanonicalChangeType.Structural)
292666
+ continue;
292667
+ const structural = change.structural;
292668
+ if (!structural || structural.wholeTable !== true || structural.decidable === false)
292669
+ continue;
292670
+ if (!(structural.side === "insertion" && decision === "accept" || structural.side === "deletion" && decision === "reject"))
292671
+ continue;
292672
+ structuralTableStays.push({
292673
+ from: structural.tableFrom,
292674
+ to: structural.tableTo,
292675
+ structuralId: change.id
292676
+ });
292677
+ }
292678
+ const isInsideStayingTable = (change) => structuralTableStays.length > 0 && change.type !== CanonicalChangeType.Structural && change.segments.length > 0 && change.segments.every((seg) => structuralTableStays.some((range) => range.from <= seg.from && range.to >= seg.to));
292679
+ const cascadedInsideStayingTable = /* @__PURE__ */ new Set;
292680
+ const planContainedInlineChild = (change) => {
292681
+ if (cascadedInsideStayingTable.has(change.id))
292682
+ return null;
292683
+ cascadedInsideStayingTable.add(change.id);
292684
+ touched.add(change.id);
292685
+ const fullSelection = {
292686
+ change,
292687
+ coverage: "full",
292688
+ ranges: change.segments.map((s2) => ({
292689
+ from: s2.from,
292690
+ to: s2.to
292691
+ }))
292692
+ };
292693
+ if (change.type === CanonicalChangeType.Insertion) {
292694
+ planInsertionDecision({
292695
+ ops,
292696
+ change,
292697
+ selection: fullSelection,
292698
+ decision,
292699
+ removedRanges,
292700
+ retired
292701
+ });
292702
+ return null;
292703
+ }
292704
+ if (change.type === CanonicalChangeType.Deletion) {
292705
+ planDeletionDecision({
292706
+ ops,
292707
+ change,
292708
+ selection: fullSelection,
292709
+ decision,
292710
+ removedRanges,
292711
+ retired
292712
+ });
292713
+ return null;
292714
+ }
292715
+ if (change.type === CanonicalChangeType.Replacement) {
292716
+ const repResult = planReplacementDecision({
292717
+ ops,
292718
+ graph,
292719
+ change,
292720
+ decision,
292721
+ removedRanges,
292722
+ retired
292723
+ });
292724
+ if (!repResult.ok)
292725
+ return repResult.failure;
292726
+ return null;
292727
+ }
292728
+ if (change.type === CanonicalChangeType.Formatting) {
292729
+ planFormattingDecision({
292730
+ ops,
292731
+ change,
292732
+ decision,
292733
+ retired
292734
+ });
292735
+ return null;
292736
+ }
292737
+ cascadedInsideStayingTable.delete(change.id);
292738
+ touched.delete(change.id);
292739
+ return null;
292740
+ };
291835
292741
  for (const selection of selections) {
291836
292742
  const { change } = selection;
292743
+ if (isInsideRemovedTable(change)) {
292744
+ retired.add(change.id);
292745
+ touched.add(change.id);
292746
+ suppressedInsideTable.add(change.id);
292747
+ continue;
292748
+ }
292749
+ if (isInsideStayingTable(change)) {
292750
+ const failureResult = planContainedInlineChild(change);
292751
+ if (failureResult)
292752
+ return {
292753
+ ok: false,
292754
+ failure: failureResult
292755
+ };
292756
+ continue;
292757
+ }
291837
292758
  const isFull = selection.coverage === "full";
291838
292759
  if (!isFull) {
292760
+ if (change.type === CanonicalChangeType.Structural)
292761
+ return {
292762
+ ok: false,
292763
+ failure: failure$3("INVALID_INPUT", "partial-range decisions are not valid on an indivisible structural revision.", { details: {
292764
+ changeId: change.id,
292765
+ subtype: change.subtype
292766
+ } })
292767
+ };
291839
292768
  if (change.type === CanonicalChangeType.Replacement)
291840
292769
  return {
291841
292770
  ok: false,
@@ -291855,7 +292784,20 @@ var Node$13 = class Node$14 {
291855
292784
  to: segment.to,
291856
292785
  cause: `${decision}:${change.id}`
291857
292786
  });
291858
- if (!isFull && (change.type === CanonicalChangeType.Insertion || change.type === CanonicalChangeType.Deletion)) {
292787
+ if (change.type === CanonicalChangeType.Structural) {
292788
+ const structuralResult = planStructuralDecision({
292789
+ ops,
292790
+ change,
292791
+ decision,
292792
+ removedRanges,
292793
+ retired
292794
+ });
292795
+ if (!structuralResult.ok)
292796
+ return {
292797
+ ok: false,
292798
+ failure: structuralResult.failure
292799
+ };
292800
+ } else if (!isFull && (change.type === CanonicalChangeType.Insertion || change.type === CanonicalChangeType.Deletion)) {
291859
292801
  const partialResult = planPartialTextDecision({
291860
292802
  ops,
291861
292803
  change,
@@ -291916,20 +292858,54 @@ var Node$13 = class Node$14 {
291916
292858
  failure: failure$3("CAPABILITY_UNAVAILABLE", `unsupported change type "${change.type}" for change "${change.id}".`)
291917
292859
  };
291918
292860
  }
292861
+ if (structuralTableStays.length > 0) {
292862
+ const decidedObjects = new Set(selections.map((selection) => selection.change));
292863
+ const seenStaying = /* @__PURE__ */ new Set;
292864
+ for (const change of graph.changes.values()) {
292865
+ if (seenStaying.has(change))
292866
+ continue;
292867
+ seenStaying.add(change);
292868
+ if (decidedObjects.has(change) || cascadedInsideStayingTable.has(change.id))
292869
+ continue;
292870
+ if (!isInsideStayingTable(change))
292871
+ continue;
292872
+ const failureResult = planContainedInlineChild(change);
292873
+ if (failureResult)
292874
+ return {
292875
+ ok: false,
292876
+ failure: failureResult
292877
+ };
292878
+ }
292879
+ }
291919
292880
  if (!ops.length)
291920
292881
  return {
291921
292882
  ok: false,
291922
292883
  failure: failure$3("NO_OP", "decision target produced no operations.", { details: { selections: selections.map((s2) => s2.change.id) } })
291923
292884
  };
291924
292885
  const affectedChildren = [];
292886
+ for (const id2 of suppressedInsideTable)
292887
+ affectedChildren.push({ changeId: id2 });
292888
+ for (const id2 of cascadedInsideStayingTable)
292889
+ affectedChildren.push({ changeId: id2 });
292890
+ const seenChange = /* @__PURE__ */ new Set;
291925
292891
  for (const change of graph.changes.values()) {
292892
+ if (seenChange.has(change))
292893
+ continue;
292894
+ seenChange.add(change);
291926
292895
  if (touched.has(change.id))
291927
292896
  continue;
292897
+ const insideRemoved = change.segments.length ? change.segments.every((seg) => removedRanges.some((r$1) => r$1.from <= seg.from && r$1.to >= seg.to)) : false;
292898
+ if (insideRemoved && isInsideRemovedTable(change)) {
292899
+ retired.add(change.id);
292900
+ touched.add(change.id);
292901
+ affectedChildren.push({ changeId: change.id });
292902
+ continue;
292903
+ }
291928
292904
  if (!change.parent)
291929
292905
  continue;
291930
292906
  if (!retired.has(change.parent) && !touched.has(change.parent))
291931
292907
  continue;
291932
- if (change.segments.every((seg) => removedRanges.some((r$1) => r$1.from <= seg.from && r$1.to >= seg.to))) {
292908
+ if (insideRemoved) {
291933
292909
  retired.add(change.id);
291934
292910
  touched.add(change.id);
291935
292911
  affectedChildren.push({ changeId: change.id });
@@ -292037,6 +293013,46 @@ var Node$13 = class Node$14 {
292037
293013
  });
292038
293014
  if (isFull)
292039
293015
  retired.add(change.id);
293016
+ }, planStructuralDecision = ({ ops, change, decision, removedRanges, retired }) => {
293017
+ const structural = change.structural;
293018
+ if (!structural)
293019
+ return {
293020
+ ok: false,
293021
+ failure: failure$3("PRECONDITION_FAILED", `structural change "${change.id}" is missing its structural payload.`)
293022
+ };
293023
+ if (structural.decidable === false || !structural.wholeTable)
293024
+ return {
293025
+ ok: false,
293026
+ failure: failure$3("CAPABILITY_UNAVAILABLE", "structural row-level revisions (partial rows or mixed sides) are not decidable; only whole-table insert/delete is supported.", { details: {
293027
+ changeId: change.id,
293028
+ reason: structural.undecidableReason ?? "not-whole-table"
293029
+ } })
293030
+ };
293031
+ if (structural.side === "insertion" && decision === "reject" || structural.side === "deletion" && decision === "accept") {
293032
+ ops.push({
293033
+ kind: "removeContent",
293034
+ from: structural.tableFrom,
293035
+ to: structural.tableTo,
293036
+ changeId: change.id,
293037
+ side: structural.side === "insertion" ? SegmentSide.Inserted : SegmentSide.Deleted
293038
+ });
293039
+ removedRanges.push({
293040
+ from: structural.tableFrom,
293041
+ to: structural.tableTo,
293042
+ cause: `${decision}-structural:${change.id}`
293043
+ });
293044
+ retired.add(change.id);
293045
+ return { ok: true };
293046
+ }
293047
+ for (const row2 of structural.rows)
293048
+ ops.push({
293049
+ kind: "clearRowTrackChange",
293050
+ from: row2.from,
293051
+ to: row2.to,
293052
+ changeId: change.id
293053
+ });
293054
+ retired.add(change.id);
293055
+ return { ok: true };
292040
293056
  }, planReplacementDecision = ({ ops, graph, change, decision, removedRanges, retired }) => {
292041
293057
  const inserted = change.insertedSegments;
292042
293058
  const deleted = change.deletedSegments;
@@ -292479,6 +293495,16 @@ var Node$13 = class Node$14 {
292479
293495
  tr.step(new RemoveMarkStep(op.from, op.to, op.mark));
292480
293496
  continue;
292481
293497
  }
293498
+ if (op.kind === "clearRowTrackChange") {
293499
+ const mappedFrom = tr.mapping.map(op.from, 1);
293500
+ const rowNode = tr.doc.nodeAt(mappedFrom);
293501
+ if (rowNode && rowNode.type.name === "tableRow")
293502
+ tr.setNodeMarkup(mappedFrom, undefined, {
293503
+ ...rowNode.attrs,
293504
+ trackChange: null
293505
+ });
293506
+ continue;
293507
+ }
292482
293508
  }
292483
293509
  for (const op of contentOps)
292484
293510
  tr.step(new ReplaceStep(op.from, op.to, Slice.empty));
@@ -297070,6 +298096,7 @@ var Node$13 = class Node$14 {
297070
298096
  runtimeRef,
297071
298097
  story: locator,
297072
298098
  type,
298099
+ subtype: type === "structural" && change.structural ? change.structural.subtype : undefined,
297073
298100
  author: toNonEmptyString(change.attrs.author),
297074
298101
  authorEmail: toNonEmptyString(change.attrs.authorEmail),
297075
298102
  authorImage: toNonEmptyString(change.attrs.authorImage),
@@ -299561,6 +300588,45 @@ var Node$13 = class Node$14 {
299561
300588
  .superdoc-layout .track-format-dec.highlighted.track-change-focused {
299562
300589
  background-color: var(--sd-tracked-changes-format-background-focused, #ffd70033);
299563
300590
  }
300591
+
300592
+ /*
300593
+ * Structural row-level tracked changes (inserted/deleted whole rows).
300594
+ *
300595
+ * The painter renders a row as absolutely-positioned cell <div>s (no <tr>), so
300596
+ * each cell of a tracked row carries the same base class (track-insert-dec /
300597
+ * track-delete-dec) + modifier (highlighted / hidden) as inline runs, plus the
300598
+ * block-context marker class track-row-cell-dec. These rules reuse the same
300599
+ * --sd-tracked-changes-insert-* / --sd-tracked-changes-delete-* CSS variables so
300600
+ * the per-author color flows through identically to the inline path.
300601
+ *
300602
+ * 'hidden' mode collapses the cell (and therefore the row) via the existing
300603
+ * .track-insert-dec.hidden / .track-delete-dec.hidden { display: none } rule
300604
+ * above: an inserted row in 'original' mode and a deleted row in 'final' mode
300605
+ * disappear, matching inline behavior.
300606
+ */
300607
+ .superdoc-layout .track-row-cell-dec.track-insert-dec.highlighted {
300608
+ background-color: var(--sd-tracked-changes-insert-background, #399c7222);
300609
+ border-top: var(--sd-tracked-changes-insert-border-width, 2px) solid
300610
+ var(--sd-tracked-changes-insert-border, #00853d);
300611
+ border-bottom: var(--sd-tracked-changes-insert-border-width, 2px) solid
300612
+ var(--sd-tracked-changes-insert-border, #00853d);
300613
+ }
300614
+
300615
+ .superdoc-layout .track-row-cell-dec.track-delete-dec.highlighted {
300616
+ background-color: var(--sd-tracked-changes-delete-background, #cb0e4722);
300617
+ border-top: var(--sd-tracked-changes-delete-border-width, 2px) solid
300618
+ var(--sd-tracked-changes-delete-border, #cb0e47);
300619
+ border-bottom: var(--sd-tracked-changes-delete-border-width, 2px) solid
300620
+ var(--sd-tracked-changes-delete-border, #cb0e47);
300621
+ }
300622
+
300623
+ .superdoc-layout .track-row-cell-dec.track-delete-dec.highlighted .superdoc-line {
300624
+ text-decoration:
300625
+ line-through
300626
+ solid
300627
+ var(--sd-tracked-changes-delete-text, #cb0e47)
300628
+ var(--sd-tracked-changes-delete-decoration-thickness, 2px);
300629
+ }
299564
300630
  `, FORMATTING_MARKS_STYLES = `
299565
300631
  .superdoc-formatting-space-mark,
299566
300632
  .superdoc-marker-suffix-space {
@@ -302941,6 +304007,125 @@ menclose::after {
302941
304007
  }
302942
304008
  }
302943
304009
  return { cellElement: cellEl };
304010
+ }, TRACK_CHANGE_BASE_CLASS, TRACK_CHANGE_OVERLAP_INSERT_DELETE_CLASS = "track-overlap-insert-delete-dec", TRACK_CHANGE_BACKGROUND_ALPHA = 34, TRACK_CHANGE_BACKGROUND_FOCUSED_ALPHA = 68, expandHexColor = (hex3) => {
304011
+ const normalized = hex3.replace("#", "");
304012
+ if (normalized.length === 3)
304013
+ return normalized.split("").map((char) => char + char).join("");
304014
+ if (normalized.length === 6 || normalized.length === 8)
304015
+ return normalized.slice(0, 6);
304016
+ return null;
304017
+ }, colorWithAlpha = (color2, alpha) => {
304018
+ const expanded = color2.trim().startsWith("#") ? expandHexColor(color2.trim()) : null;
304019
+ if (!expanded)
304020
+ return color2;
304021
+ return `#${expanded}${Math.max(0, Math.min(255, alpha)).toString(16).padStart(2, "0")}`;
304022
+ }, setColorVar = (elem, name, value) => {
304023
+ elem.style.setProperty(name, value);
304024
+ }, applyAuthorColorVariables = (elem, layer) => {
304025
+ const color2 = layer.color;
304026
+ if (!color2)
304027
+ return;
304028
+ const background = colorWithAlpha(color2, TRACK_CHANGE_BACKGROUND_ALPHA);
304029
+ const backgroundFocused = colorWithAlpha(color2, TRACK_CHANGE_BACKGROUND_FOCUSED_ALPHA);
304030
+ switch (layer.kind) {
304031
+ case "insert":
304032
+ setColorVar(elem, "--sd-tracked-changes-insert-border", color2);
304033
+ setColorVar(elem, "--sd-tracked-changes-insert-background", background);
304034
+ setColorVar(elem, "--sd-tracked-changes-insert-background-focused", backgroundFocused);
304035
+ break;
304036
+ case "delete":
304037
+ setColorVar(elem, "--sd-tracked-changes-delete-border", color2);
304038
+ setColorVar(elem, "--sd-tracked-changes-delete-background", background);
304039
+ setColorVar(elem, "--sd-tracked-changes-delete-background-focused", backgroundFocused);
304040
+ setColorVar(elem, "--sd-tracked-changes-delete-text", color2);
304041
+ break;
304042
+ case "format":
304043
+ setColorVar(elem, "--sd-tracked-changes-format-border", color2);
304044
+ setColorVar(elem, "--sd-tracked-changes-format-background", background);
304045
+ setColorVar(elem, "--sd-tracked-changes-format-background-focused", backgroundFocused);
304046
+ break;
304047
+ default:
304048
+ break;
304049
+ }
304050
+ }, TRACK_CHANGE_MODIFIER_CLASS, getTrackedChangeLayers$1 = (run2) => {
304051
+ if (Array.isArray(run2.trackedChanges) && run2.trackedChanges.length > 0)
304052
+ return run2.trackedChanges;
304053
+ return run2.trackedChange ? [run2.trackedChange] : [];
304054
+ }, resolveInsertDeleteOverlap = (layers) => {
304055
+ for (const parentInsert of layers) {
304056
+ if (parentInsert.kind !== "insert")
304057
+ continue;
304058
+ const childDelete = layers.find((layer) => layer.kind === "delete" && layer.overlapParentId === parentInsert.id);
304059
+ if (childDelete)
304060
+ return {
304061
+ parentInsert,
304062
+ childDelete
304063
+ };
304064
+ }
304065
+ }, resolveTrackedChangesConfig = (block) => {
304066
+ const attrs = block.attrs ?? {};
304067
+ return {
304068
+ mode: attrs.trackedChangesMode ?? "review",
304069
+ enabled: attrs.trackedChangesEnabled !== false
304070
+ };
304071
+ }, TRACK_CHANGE_ROW_CELL_CLASS = "track-row-cell-dec", applyRowTrackedChangeToCell = (elem, meta4, config3) => {
304072
+ if (!config3.enabled || config3.mode === "off")
304073
+ return;
304074
+ if (meta4.kind !== "insert" && meta4.kind !== "delete")
304075
+ return;
304076
+ const baseClass = TRACK_CHANGE_BASE_CLASS[meta4.kind];
304077
+ if (baseClass)
304078
+ elem.classList.add(baseClass);
304079
+ elem.classList.add(TRACK_CHANGE_ROW_CELL_CLASS);
304080
+ const modifier = TRACK_CHANGE_MODIFIER_CLASS[meta4.kind]?.[config3.mode];
304081
+ if (modifier)
304082
+ elem.classList.add(modifier);
304083
+ applyAuthorColorVariables(elem, meta4);
304084
+ elem.dataset.trackChangeId = meta4.id;
304085
+ elem.dataset.trackChangeKind = meta4.kind;
304086
+ elem.dataset.trackChangeStructural = "row";
304087
+ elem.dataset.storyKey = meta4.storyKey ?? "body";
304088
+ if (meta4.author)
304089
+ elem.dataset.trackChangeAuthor = meta4.author;
304090
+ if (meta4.authorEmail)
304091
+ elem.dataset.trackChangeAuthorEmail = meta4.authorEmail;
304092
+ if (meta4.date)
304093
+ elem.dataset.trackChangeDate = meta4.date;
304094
+ }, applyTrackedChangeDecorations = (elem, run2, config3) => {
304095
+ if (!config3.enabled || config3.mode === "off")
304096
+ return;
304097
+ const textRun = run2;
304098
+ const layers = getTrackedChangeLayers$1(textRun);
304099
+ if (layers.length === 0)
304100
+ return;
304101
+ const overlap = resolveInsertDeleteOverlap(layers);
304102
+ const meta4 = overlap?.parentInsert ?? textRun.trackedChange ?? layers[0];
304103
+ layers.forEach((layer) => {
304104
+ const baseClass = TRACK_CHANGE_BASE_CLASS[layer.kind];
304105
+ if (baseClass)
304106
+ elem.classList.add(baseClass);
304107
+ const modifier = TRACK_CHANGE_MODIFIER_CLASS[layer.kind]?.[config3.mode];
304108
+ if (modifier)
304109
+ elem.classList.add(modifier);
304110
+ applyAuthorColorVariables(elem, layer);
304111
+ });
304112
+ if (overlap) {
304113
+ elem.classList.add(TRACK_CHANGE_OVERLAP_INSERT_DELETE_CLASS);
304114
+ elem.dataset.trackChangePreferredTargetId = overlap.childDelete.id;
304115
+ }
304116
+ elem.dataset.trackChangeId = meta4.id;
304117
+ elem.dataset.trackChangeKind = meta4.kind;
304118
+ elem.dataset.trackChangeIds = layers.map((layer) => layer.id).join(",");
304119
+ elem.dataset.trackChangeKinds = layers.map((layer) => layer.kind).join(",");
304120
+ elem.dataset.storyKey = meta4.storyKey ?? "body";
304121
+ if (meta4.author)
304122
+ elem.dataset.trackChangeAuthor = meta4.author;
304123
+ if (meta4.authorEmail)
304124
+ elem.dataset.trackChangeAuthorEmail = meta4.authorEmail;
304125
+ if (meta4.authorImage)
304126
+ elem.dataset.trackChangeAuthorImage = meta4.authorImage;
304127
+ if (meta4.date)
304128
+ elem.dataset.trackChangeDate = meta4.date;
302944
304129
  }, hasAnyResolvedBorder = (borders) => Boolean(borders.top || borders.right || borders.bottom || borders.left), resolveRenderedCellBorders = ({ cellBorders, hasBordersAttribute, tableBorders, cellPosition, cellSpacingPx, continuesFromPrev, continuesOnNext, aboveCellBorders, leftCellBorders, rightCellBorders, nextRowLeavesRightGap, deferTopToAboveCell, nextRowSuppressesSharedTop }) => {
302945
304130
  const hasExplicitBorders = hasExplicitCellBorders(cellBorders);
302946
304131
  const cellBounds = getTableCellGridBounds(cellPosition);
@@ -302993,6 +304178,22 @@ menclose::after {
302993
304178
  }, renderTableRow = (deps) => {
302994
304179
  const { doc: doc$12, container, rowIndex, y: y$1, rowMeasure, row: row2, prevRow, prevRowMeasure, nextRow, nextRowMeasure, rowOccupiedRightCol, nextRowOccupiedRightCol, totalRows, tableBorders, columnWidths, allRowHeights, tableIndent, isRtl, context, renderLine: renderLine$1, captureLineSnapshot, renderDrawingContent, applySdtDataset: applySdtDataset$1, ancestorContainerKey, ancestorContainerSdt, ancestorContainerKeys, ancestorContainerSdts, onSdtContainerChrome, continuesFromPrev, continuesOnNext, partialRow, cellSpacingPx = 0, chrome: chrome2, resolvePhysical } = deps;
302995
304180
  const totalCols = columnWidths.length;
304181
+ const rowTrackedChange = row2?.attrs?.trackedChange;
304182
+ let rowTrackedChangeConfig;
304183
+ if (rowTrackedChange) {
304184
+ let representativeParagraph;
304185
+ for (const cell2 of row2?.cells ?? []) {
304186
+ const candidate = cell2.paragraph ?? cell2.blocks?.find((block) => block.kind === "paragraph");
304187
+ if (candidate) {
304188
+ representativeParagraph = candidate;
304189
+ break;
304190
+ }
304191
+ }
304192
+ rowTrackedChangeConfig = representativeParagraph ? resolveTrackedChangesConfig(representativeParagraph) : {
304193
+ mode: "review",
304194
+ enabled: true
304195
+ };
304196
+ }
302996
304197
  const rowRightEdgeCol = rowOccupiedRightCol != null && rowOccupiedRightCol > 0 ? Math.min(totalCols, rowOccupiedRightCol) : rowMeasure.cells.length ? Math.min(totalCols, Math.max(...rowMeasure.cells.map((c) => (c.gridColumnStart ?? 0) + (c.colSpan ?? 1)))) : totalCols;
302997
304198
  const rowBorderOverride = row2?.attrs?.borders;
302998
304199
  const effectiveTableBorders = rowBorderOverride ? {
@@ -303127,6 +304328,8 @@ menclose::after {
303127
304328
  chrome: chrome2,
303128
304329
  resolvePhysical
303129
304330
  });
304331
+ if (rowTrackedChange && rowTrackedChangeConfig)
304332
+ applyRowTrackedChangeToCell(cellElement, rowTrackedChange, rowTrackedChangeConfig);
303130
304333
  container.appendChild(cellElement);
303131
304334
  }
303132
304335
  }, renderTableFragment = (deps) => {
@@ -305441,102 +306644,6 @@ menclose::after {
305441
306644
  });
305442
306645
  return createErrorPlaceholder(fragment.blockId, error48);
305443
306646
  }
305444
- }, TRACK_CHANGE_BASE_CLASS, TRACK_CHANGE_OVERLAP_INSERT_DELETE_CLASS = "track-overlap-insert-delete-dec", TRACK_CHANGE_BACKGROUND_ALPHA = 34, TRACK_CHANGE_BACKGROUND_FOCUSED_ALPHA = 68, expandHexColor = (hex3) => {
305445
- const normalized = hex3.replace("#", "");
305446
- if (normalized.length === 3)
305447
- return normalized.split("").map((char) => char + char).join("");
305448
- if (normalized.length === 6 || normalized.length === 8)
305449
- return normalized.slice(0, 6);
305450
- return null;
305451
- }, colorWithAlpha = (color2, alpha) => {
305452
- const expanded = color2.trim().startsWith("#") ? expandHexColor(color2.trim()) : null;
305453
- if (!expanded)
305454
- return color2;
305455
- return `#${expanded}${Math.max(0, Math.min(255, alpha)).toString(16).padStart(2, "0")}`;
305456
- }, setColorVar = (elem, name, value) => {
305457
- elem.style.setProperty(name, value);
305458
- }, applyAuthorColorVariables = (elem, layer) => {
305459
- const color2 = layer.color;
305460
- if (!color2)
305461
- return;
305462
- const background = colorWithAlpha(color2, TRACK_CHANGE_BACKGROUND_ALPHA);
305463
- const backgroundFocused = colorWithAlpha(color2, TRACK_CHANGE_BACKGROUND_FOCUSED_ALPHA);
305464
- switch (layer.kind) {
305465
- case "insert":
305466
- setColorVar(elem, "--sd-tracked-changes-insert-border", color2);
305467
- setColorVar(elem, "--sd-tracked-changes-insert-background", background);
305468
- setColorVar(elem, "--sd-tracked-changes-insert-background-focused", backgroundFocused);
305469
- break;
305470
- case "delete":
305471
- setColorVar(elem, "--sd-tracked-changes-delete-border", color2);
305472
- setColorVar(elem, "--sd-tracked-changes-delete-background", background);
305473
- setColorVar(elem, "--sd-tracked-changes-delete-background-focused", backgroundFocused);
305474
- setColorVar(elem, "--sd-tracked-changes-delete-text", color2);
305475
- break;
305476
- case "format":
305477
- setColorVar(elem, "--sd-tracked-changes-format-border", color2);
305478
- setColorVar(elem, "--sd-tracked-changes-format-background", background);
305479
- setColorVar(elem, "--sd-tracked-changes-format-background-focused", backgroundFocused);
305480
- break;
305481
- default:
305482
- break;
305483
- }
305484
- }, TRACK_CHANGE_MODIFIER_CLASS, getTrackedChangeLayers$1 = (run2) => {
305485
- if (Array.isArray(run2.trackedChanges) && run2.trackedChanges.length > 0)
305486
- return run2.trackedChanges;
305487
- return run2.trackedChange ? [run2.trackedChange] : [];
305488
- }, resolveInsertDeleteOverlap = (layers) => {
305489
- for (const parentInsert of layers) {
305490
- if (parentInsert.kind !== "insert")
305491
- continue;
305492
- const childDelete = layers.find((layer) => layer.kind === "delete" && layer.overlapParentId === parentInsert.id);
305493
- if (childDelete)
305494
- return {
305495
- parentInsert,
305496
- childDelete
305497
- };
305498
- }
305499
- }, resolveTrackedChangesConfig = (block) => {
305500
- const attrs = block.attrs ?? {};
305501
- return {
305502
- mode: attrs.trackedChangesMode ?? "review",
305503
- enabled: attrs.trackedChangesEnabled !== false
305504
- };
305505
- }, applyTrackedChangeDecorations = (elem, run2, config3) => {
305506
- if (!config3.enabled || config3.mode === "off")
305507
- return;
305508
- const textRun = run2;
305509
- const layers = getTrackedChangeLayers$1(textRun);
305510
- if (layers.length === 0)
305511
- return;
305512
- const overlap = resolveInsertDeleteOverlap(layers);
305513
- const meta4 = overlap?.parentInsert ?? textRun.trackedChange ?? layers[0];
305514
- layers.forEach((layer) => {
305515
- const baseClass = TRACK_CHANGE_BASE_CLASS[layer.kind];
305516
- if (baseClass)
305517
- elem.classList.add(baseClass);
305518
- const modifier = TRACK_CHANGE_MODIFIER_CLASS[layer.kind]?.[config3.mode];
305519
- if (modifier)
305520
- elem.classList.add(modifier);
305521
- applyAuthorColorVariables(elem, layer);
305522
- });
305523
- if (overlap) {
305524
- elem.classList.add(TRACK_CHANGE_OVERLAP_INSERT_DELETE_CLASS);
305525
- elem.dataset.trackChangePreferredTargetId = overlap.childDelete.id;
305526
- }
305527
- elem.dataset.trackChangeId = meta4.id;
305528
- elem.dataset.trackChangeKind = meta4.kind;
305529
- elem.dataset.trackChangeIds = layers.map((layer) => layer.id).join(",");
305530
- elem.dataset.trackChangeKinds = layers.map((layer) => layer.kind).join(",");
305531
- elem.dataset.storyKey = meta4.storyKey ?? "body";
305532
- if (meta4.author)
305533
- elem.dataset.trackChangeAuthor = meta4.author;
305534
- if (meta4.authorEmail)
305535
- elem.dataset.trackChangeAuthorEmail = meta4.authorEmail;
305536
- if (meta4.authorImage)
305537
- elem.dataset.trackChangeAuthorImage = meta4.authorImage;
305538
- if (meta4.date)
305539
- elem.dataset.trackChangeDate = meta4.date;
305540
306647
  }, ACTIVE_HEADER_FOOTER_WATERMARK_PREVIEW_OPACITY = "1", INACTIVE_HEADER_FOOTER_WATERMARK_PREVIEW_OPACITY = "0.5", resolveOrBuildFragmentIdentity = (fragment, story, existing) => buildLayoutSourceIdentityForFragment(existing ? {
305541
306648
  ...fragment,
305542
306649
  layoutSourceIdentity: existing,
@@ -317310,13 +318417,13 @@ menclose::after {
317310
318417
  return;
317311
318418
  console.log(...args$1);
317312
318419
  }, 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;
317313
- var init_src_eTZqPcFn_es = __esm(() => {
318420
+ var init_src_DeS9kJS7_es = __esm(() => {
317314
318421
  init_rolldown_runtime_Bg48TavK_es();
317315
- init_SuperConverter_D2zNnC50_es();
318422
+ init_SuperConverter_BBjNvGFh_es();
317316
318423
  init_jszip_C49i9kUs_es();
317317
318424
  init_xml_js_CqGKpaft_es();
317318
318425
  init_uuid_qzgm05fK_es();
317319
- init_create_headless_toolbar_COmoIa5Q_es();
318426
+ init_create_headless_toolbar_s_kl3MP8_es();
317320
318427
  init_constants_D9qj59G2_es();
317321
318428
  init_dist_B8HfvhaK_es();
317322
318429
  init_unified_Dsuw2be5_es();
@@ -322533,7 +323640,12 @@ ${err.toString()}`);
322533
323640
  rsidRPr: { rendered: false },
322534
323641
  rsidTr: { rendered: false },
322535
323642
  paraId: { rendered: false },
322536
- textId: { rendered: false }
323643
+ textId: { rendered: false },
323644
+ trackChange: {
323645
+ default: null,
323646
+ keepOnSplit: true,
323647
+ rendered: false
323648
+ }
322537
323649
  };
322538
323650
  },
322539
323651
  parseDOM() {
@@ -329413,13 +330525,16 @@ ${err.toString()}`);
329413
330525
  Insertion: "insertion",
329414
330526
  Deletion: "deletion",
329415
330527
  Replacement: "replacement",
329416
- Formatting: "formatting"
330528
+ Formatting: "formatting",
330529
+ Structural: "structural"
329417
330530
  });
329418
330531
  ChangeSubtype = Object.freeze({
329419
330532
  TextInsertion: "text-insertion",
329420
330533
  TextDeletion: "text-deletion",
329421
330534
  TextReplacement: "text-replacement",
329422
- RunFormatting: "run-formatting"
330535
+ RunFormatting: "run-formatting",
330536
+ TableInsert: "table-insert",
330537
+ TableDelete: "table-delete"
329423
330538
  });
329424
330539
  SegmentSide = Object.freeze({
329425
330540
  Inserted: "inserted",
@@ -344537,6 +345652,31 @@ function print() { __p += __j.call(arguments, '') }
344537
345652
  RTL_DATE_LIKE_TOKEN_RE = /^-?\d+(?:[./-]\d+)+$/;
344538
345653
  STRONG_RTL_CHAR_RE = /[\u0590-\u08FF\p{Script=Hebrew}\p{Script=Arabic}]/u;
344539
345654
  LATIN_DIGIT_NEUTRAL_ONLY_RE = /^[\s0-9A-Za-z./\-_:,+()]+$/;
345655
+ TRACK_CHANGE_BASE_CLASS = {
345656
+ insert: "track-insert-dec",
345657
+ delete: "track-delete-dec",
345658
+ format: "track-format-dec"
345659
+ };
345660
+ TRACK_CHANGE_MODIFIER_CLASS = {
345661
+ insert: {
345662
+ review: "highlighted",
345663
+ original: "hidden",
345664
+ final: "normal",
345665
+ off: undefined
345666
+ },
345667
+ delete: {
345668
+ review: "highlighted",
345669
+ original: "normal",
345670
+ final: "hidden",
345671
+ off: undefined
345672
+ },
345673
+ format: {
345674
+ review: "highlighted",
345675
+ original: "before",
345676
+ final: "normal",
345677
+ off: undefined
345678
+ }
345679
+ };
344540
345680
  SDT_DATASET_KEYS = [
344541
345681
  "sdtType",
344542
345682
  "sdtId",
@@ -344705,31 +345845,6 @@ function print() { __p += __j.call(arguments, '') }
344705
345845
  "m:fName",
344706
345846
  "m:oMath"
344707
345847
  ]);
344708
- TRACK_CHANGE_BASE_CLASS = {
344709
- insert: "track-insert-dec",
344710
- delete: "track-delete-dec",
344711
- format: "track-format-dec"
344712
- };
344713
- TRACK_CHANGE_MODIFIER_CLASS = {
344714
- insert: {
344715
- review: "highlighted",
344716
- original: "hidden",
344717
- final: "normal",
344718
- off: undefined
344719
- },
344720
- delete: {
344721
- review: "highlighted",
344722
- original: "normal",
344723
- final: "hidden",
344724
- off: undefined
344725
- },
344726
- format: {
344727
- review: "highlighted",
344728
- original: "before",
344729
- final: "normal",
344730
- off: undefined
344731
- }
344732
- };
344733
345848
  CLIP_PATH_PREFIXES = [
344734
345849
  "inset(",
344735
345850
  "polygon(",
@@ -346848,9 +347963,43 @@ function print() { __p += __j.call(arguments, '') }
346848
347963
  storyKey: BODY_STORY_KEY
346849
347964
  }),
346850
347965
  ...this.#collectIndexedTrackedChangePositions(),
347966
+ ...this.#collectStructuralBodyTrackedChangePositions(),
346851
347967
  ...this.#collectRenderedTrackedChangePositions()
346852
347968
  };
346853
347969
  }
347970
+ #collectStructuralBodyTrackedChangePositions() {
347971
+ const positions = {};
347972
+ let snapshots = [];
347973
+ try {
347974
+ snapshots = getTrackedChangeIndex(this.#editor).getAll();
347975
+ } catch {
347976
+ return positions;
347977
+ }
347978
+ snapshots.forEach((snapshot2) => {
347979
+ if (snapshot2?.type !== "structural")
347980
+ return;
347981
+ const storyKey = typeof snapshot2?.runtimeRef?.storyKey === "string" ? snapshot2.runtimeRef.storyKey : BODY_STORY_KEY;
347982
+ if (storyKey !== "body")
347983
+ return;
347984
+ const key2 = typeof snapshot2?.anchorKey === "string" ? snapshot2.anchorKey : null;
347985
+ const rawId = snapshot2?.runtimeRef?.rawId;
347986
+ const threadId = rawId == null ? null : String(rawId);
347987
+ if (!key2 || !threadId || positions[key2])
347988
+ return;
347989
+ const start$1 = Number.isFinite(snapshot2?.range?.from) ? Number(snapshot2.range.from) : undefined;
347990
+ const end$1 = Number.isFinite(snapshot2?.range?.to) ? Number(snapshot2.range.to) : undefined;
347991
+ positions[key2] = {
347992
+ threadId,
347993
+ key: key2,
347994
+ storyKey,
347995
+ kind: "trackedChange",
347996
+ structural: true,
347997
+ ...start$1 !== undefined ? { start: start$1 } : {},
347998
+ ...end$1 !== undefined ? { end: end$1 } : {}
347999
+ };
348000
+ });
348001
+ return positions;
348002
+ }
346854
348003
  #collectIndexedTrackedChangePositions() {
346855
348004
  const positions = {};
346856
348005
  let snapshots = [];
@@ -352354,11 +353503,11 @@ function print() { __p += __j.call(arguments, '') }
352354
353503
  ]);
352355
353504
  });
352356
353505
 
352357
- // ../../packages/superdoc/dist/chunks/create-super-doc-ui-BOYlxpy0.es.js
353506
+ // ../../packages/superdoc/dist/chunks/create-super-doc-ui-CZZRzAFm.es.js
352358
353507
  var 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;
352359
- var init_create_super_doc_ui_BOYlxpy0_es = __esm(() => {
352360
- init_SuperConverter_D2zNnC50_es();
352361
- init_create_headless_toolbar_COmoIa5Q_es();
353508
+ var init_create_super_doc_ui_CZZRzAFm_es = __esm(() => {
353509
+ init_SuperConverter_BBjNvGFh_es();
353510
+ init_create_headless_toolbar_s_kl3MP8_es();
352362
353511
  MOD_ALIASES = new Set([
352363
353512
  "Mod",
352364
353513
  "Meta",
@@ -352400,16 +353549,16 @@ var init_zipper_yaJVJ4z9_es = __esm(() => {
352400
353549
 
352401
353550
  // ../../packages/superdoc/dist/super-editor.es.js
352402
353551
  var init_super_editor_es = __esm(() => {
352403
- init_src_eTZqPcFn_es();
352404
- init_SuperConverter_D2zNnC50_es();
353552
+ init_src_DeS9kJS7_es();
353553
+ init_SuperConverter_BBjNvGFh_es();
352405
353554
  init_jszip_C49i9kUs_es();
352406
353555
  init_xml_js_CqGKpaft_es();
352407
- init_create_headless_toolbar_COmoIa5Q_es();
353556
+ init_create_headless_toolbar_s_kl3MP8_es();
352408
353557
  init_constants_D9qj59G2_es();
352409
353558
  init_dist_B8HfvhaK_es();
352410
353559
  init_unified_Dsuw2be5_es();
352411
353560
  init_DocxZipper_Bu2Fhqkw_es();
352412
- init_create_super_doc_ui_BOYlxpy0_es();
353561
+ init_create_super_doc_ui_CZZRzAFm_es();
352413
353562
  init_ui_C5PAS9hY_es();
352414
353563
  init_eventemitter3_BnGqBE_Q_es();
352415
353564
  init_errors_CNaD6vcg_es();
@@ -356021,7 +357170,7 @@ More content with **bold** and *italic*.`
356021
357170
  "trackChanges.list": {
356022
357171
  memberPath: "trackChanges.list",
356023
357172
  description: "List all tracked changes in the document.",
356024
- expectedResult: "Returns a TrackChangesListResult with tracked change entries (`insert`, `delete`, `replacement`, `format`), total count, and raw imported Word OOXML revision IDs (`w:id`) when available.",
357173
+ expectedResult: "Returns a TrackChangesListResult with tracked change entries (`insert`, `delete`, `replacement`, `format`, `structural`), total count, and raw imported Word OOXML revision IDs (`w:id`) when available. Structural changes (whole-table insert/delete) carry a `subtype` of `table-insert` or `table-delete`.",
356025
357174
  requiresDocumentContext: true,
356026
357175
  metadata: readOperation2({
356027
357176
  idempotency: "idempotent",
@@ -356035,7 +357184,7 @@ More content with **bold** and *italic*.`
356035
357184
  "trackChanges.get": {
356036
357185
  memberPath: "trackChanges.get",
356037
357186
  description: "Retrieve a single tracked change by ID.",
356038
- expectedResult: "Returns a TrackChangeInfo object with the change type (`insert`, `delete`, `replacement`, `format`), author, date, affected content, and raw imported Word OOXML revision IDs (`w:id`) when available.",
357187
+ expectedResult: "Returns a TrackChangeInfo object with the change type (`insert`, `delete`, `replacement`, `format`, `structural`), author, date, affected content, and raw imported Word OOXML revision IDs (`w:id`) when available. Structural changes (whole-table insert/delete) carry a `subtype` of `table-insert` or `table-delete`.",
356039
357188
  requiresDocumentContext: true,
356040
357189
  metadata: readOperation2({
356041
357190
  idempotency: "idempotent",
@@ -361396,7 +362545,7 @@ var init_schemas4 = __esm(() => {
361396
362545
  init_style_policy_types();
361397
362546
  init_paragraphs();
361398
362547
  init_styles();
361399
- trackChangeTypeValues2 = ["insert", "delete", "replacement", "format"];
362548
+ trackChangeTypeValues2 = ["insert", "delete", "replacement", "format", "structural"];
361400
362549
  nodeTypeValues2 = NODE_TYPES2;
361401
362550
  blockNodeTypeValues2 = BLOCK_NODE_TYPES2;
361402
362551
  deletableBlockNodeTypeValues2 = DELETABLE_BLOCK_NODE_TYPES2;
@@ -362166,6 +363315,10 @@ var init_schemas4 = __esm(() => {
362166
363315
  address: trackedChangeAddressSchema2,
362167
363316
  id: { type: "string" },
362168
363317
  type: { enum: [...trackChangeTypeValues2] },
363318
+ subtype: {
363319
+ enum: ["table-insert", "table-delete"],
363320
+ description: "Finer classification for structural changes (type === 'structural')."
363321
+ },
362169
363322
  grouping: { enum: ["standalone", "replacement-pair", "unknown"] },
362170
363323
  pairedWithChangeId: { type: ["string", "null"] },
362171
363324
  wordRevisionIds: trackChangeWordRevisionIdsSchema2,
@@ -362180,6 +363333,10 @@ var init_schemas4 = __esm(() => {
362180
363333
  trackChangeDomainItemSchema = discoveryItemSchema2({
362181
363334
  address: trackedChangeAddressSchema2,
362182
363335
  type: { enum: [...trackChangeTypeValues2] },
363336
+ subtype: {
363337
+ enum: ["table-insert", "table-delete"],
363338
+ description: "Finer classification for structural changes (type === 'structural')."
363339
+ },
362183
363340
  grouping: { enum: ["standalone", "replacement-pair", "unknown"] },
362184
363341
  pairedWithChangeId: { type: ["string", "null"] },
362185
363342
  wordRevisionIds: trackChangeWordRevisionIdsSchema2,
@@ -364493,7 +365650,7 @@ var init_schemas4 = __esm(() => {
364493
365650
  offset: { type: "integer", description: "Number of tracked changes to skip for pagination." },
364494
365651
  type: {
364495
365652
  enum: [...trackChangeTypeValues2],
364496
- description: "Filter by change type: 'insert', 'delete', 'replacement', or 'format'."
365653
+ description: "Filter by change type: 'insert', 'delete', 'replacement', 'format', or 'structural'."
364497
365654
  },
364498
365655
  in: {
364499
365656
  oneOf: [storyLocatorSchema2, { const: "all" }],
@@ -364513,7 +365670,14 @@ var init_schemas4 = __esm(() => {
364513
365670
  decision: { enum: ["accept", "reject"] },
364514
365671
  target: {
364515
365672
  oneOf: [
364516
- objectSchema2({ id: { type: "string" }, story: storyLocatorSchema2 }, ["id"]),
365673
+ objectSchema2({
365674
+ id: { type: "string" },
365675
+ story: storyLocatorSchema2,
365676
+ range: {
365677
+ type: "object",
365678
+ description: "Partial-range qualifier on an id target. Rejected with INVALID_INPUT for indivisible (e.g. structural) revisions."
365679
+ }
365680
+ }, ["id"]),
364517
365681
  objectSchema2({
364518
365682
  kind: { const: "range" },
364519
365683
  range: textTargetSchema2,
@@ -369408,6 +370572,16 @@ function executeTrackChangesDecide2(adapter, rawInput, options) {
369408
370572
  if (rawStory === "all") {
369409
370573
  throw new DocumentApiValidationError3("INVALID_TARGET", 'trackChanges.decide id targets do not support story: "all".', { field: "target.story", value: rawStory });
369410
370574
  }
370575
+ if (target.range !== undefined) {
370576
+ return {
370577
+ success: false,
370578
+ failure: {
370579
+ code: "INVALID_INPUT",
370580
+ message: "trackChanges.decide does not support a partial range on an id target; the change is not safely divisible.",
370581
+ details: { target: input2.target }
370582
+ }
370583
+ };
370584
+ }
369411
370585
  if (typeof target.id !== "string" || target.id.length === 0) {
369412
370586
  throw new DocumentApiValidationError3("INVALID_TARGET", "trackChanges.decide id targets require a non-empty id.", {
369413
370587
  field: "target",
@@ -374542,7 +375716,21 @@ var init_constants = __esm(() => {
374542
375716
  });
374543
375717
 
374544
375718
  // ../../packages/super-editor/src/editors/v1/core/layout-adapter/tracked-changes.ts
374545
- var shouldHideTrackedNode2 = (meta4, config3) => {
375719
+ var RANDOM_ID_LENGTH2 = 9, generateRandomBase36Id2 = (length3) => {
375720
+ let randomId = "";
375721
+ while (randomId.length < length3) {
375722
+ randomId += Math.random().toString(36).slice(2);
375723
+ }
375724
+ return randomId.slice(0, length3);
375725
+ }, deriveTrackedChangeId2 = (kind, attrs) => {
375726
+ if (attrs && typeof attrs.id === "string" && attrs.id.trim()) {
375727
+ return attrs.id;
375728
+ }
375729
+ const authorEmail = attrs && typeof attrs.authorEmail === "string" ? attrs.authorEmail : "unknown";
375730
+ const date6 = attrs && typeof attrs.date === "string" ? attrs.date : "unknown";
375731
+ const unique2 = `${Date.now()}-${generateRandomBase36Id2(RANDOM_ID_LENGTH2)}`;
375732
+ return `${kind}-${authorEmail}-${date6}-${unique2}`;
375733
+ }, shouldHideTrackedNode2 = (meta4, config3) => {
374546
375734
  if (!meta4 || !config3 || !config3.enabled)
374547
375735
  return false;
374548
375736
  if (config3.mode === "original" && meta4.kind === "insert")
@@ -381652,7 +382840,7 @@ var parseThemePercentage2 = (value) => {
381652
382840
  };
381653
382841
 
381654
382842
  // ../../packages/super-editor/src/editors/v1/core/layout-adapter/marks/application.ts
381655
- var TRACK_INSERT_MARK3 = "trackInsert", TRACK_DELETE_MARK3 = "trackDelete", TRACK_FORMAT_MARK3 = "trackFormat", TRACK_CHANGE_KIND_MAP3, MAX_RUN_MARK_JSON_LENGTH3 = 1e4, MAX_RUN_MARK_ARRAY_LENGTH3 = 100, MAX_RUN_MARK_DEPTH3 = 5, RANDOM_ID_LENGTH2 = 9, generateRandomBase36Id2 = (length3) => {
382843
+ var TRACK_INSERT_MARK3 = "trackInsert", TRACK_DELETE_MARK3 = "trackDelete", TRACK_FORMAT_MARK3 = "trackFormat", TRACK_CHANGE_KIND_MAP3, MAX_RUN_MARK_JSON_LENGTH3 = 1e4, MAX_RUN_MARK_ARRAY_LENGTH3 = 100, MAX_RUN_MARK_DEPTH3 = 5, RANDOM_ID_LENGTH3 = 9, generateRandomBase36Id3 = (length3) => {
381656
382844
  let randomId = "";
381657
382845
  while (randomId.length < length3) {
381658
382846
  randomId += Math.random().toString(36).slice(2);
@@ -381827,13 +383015,13 @@ var TRACK_INSERT_MARK3 = "trackInsert", TRACK_DELETE_MARK3 = "trackDelete", TRAC
381827
383015
  return normalized.length ? normalized : undefined;
381828
383016
  }, pickTrackedChangeKind2 = (markType) => {
381829
383017
  return TRACK_CHANGE_KIND_MAP3[markType];
381830
- }, deriveTrackedChangeId2 = (kind, attrs) => {
383018
+ }, deriveTrackedChangeId3 = (kind, attrs) => {
381831
383019
  if (attrs && typeof attrs.id === "string" && attrs.id.trim()) {
381832
383020
  return attrs.id;
381833
383021
  }
381834
383022
  const authorEmail = attrs && typeof attrs.authorEmail === "string" ? attrs.authorEmail : "unknown";
381835
383023
  const date6 = attrs && typeof attrs.date === "string" ? attrs.date : "unknown";
381836
- const unique2 = `${Date.now()}-${generateRandomBase36Id2(RANDOM_ID_LENGTH2)}`;
383024
+ const unique2 = `${Date.now()}-${generateRandomBase36Id3(RANDOM_ID_LENGTH3)}`;
381837
383025
  return `${kind}-${authorEmail}-${date6}-${unique2}`;
381838
383026
  }, buildTrackedChangeMetaFromMark2 = (mark2, storyKey) => {
381839
383027
  const kind = pickTrackedChangeKind2(mark2.type);
@@ -381842,7 +383030,7 @@ var TRACK_INSERT_MARK3 = "trackInsert", TRACK_DELETE_MARK3 = "trackDelete", TRAC
381842
383030
  const attrs = mark2.attrs ?? {};
381843
383031
  const meta4 = {
381844
383032
  kind,
381845
- id: deriveTrackedChangeId2(kind, attrs)
383033
+ id: deriveTrackedChangeId3(kind, attrs)
381846
383034
  };
381847
383035
  if (typeof attrs.overlapParentId === "string" && attrs.overlapParentId) {
381848
383036
  meta4.overlapParentId = attrs.overlapParentId;
@@ -384723,7 +385911,9 @@ function tableNodeToBlock2(node3, {
384723
385911
  tableProperties: tablePropertiesForCascade
384724
385912
  });
384725
385913
  if (parsedRow) {
384726
- rows.push(parsedRow);
385914
+ if (!shouldHideTrackedNode2(parsedRow.attrs?.trackedChange, parserDeps.trackedChangesConfig)) {
385915
+ rows.push(parsedRow);
385916
+ }
384727
385917
  }
384728
385918
  });
384729
385919
  if (rows.length === 0)
@@ -385139,6 +386329,31 @@ var isTableRowNode2 = (node3) => node3.type === "tableRow" || node3.type === "ta
385139
386329
  attrs: Object.keys(cellAttrs).length > 0 ? cellAttrs : undefined,
385140
386330
  sourceAnchor: sourceAnchorFromNode2(cellNode)
385141
386331
  };
386332
+ }, buildRowTrackedChangeMeta2 = (rowNode, storyKey) => {
386333
+ const trackChange = rowNode.attrs?.trackChange;
386334
+ if (!trackChange || typeof trackChange !== "object")
386335
+ return;
386336
+ const rawType = trackChange.type;
386337
+ if (rawType !== "rowInsert" && rawType !== "rowDelete")
386338
+ return;
386339
+ const kind = rawType === "rowInsert" ? "insert" : "delete";
386340
+ const meta4 = {
386341
+ kind,
386342
+ id: deriveTrackedChangeId2(kind, trackChange)
386343
+ };
386344
+ if (typeof trackChange.author === "string" && trackChange.author) {
386345
+ meta4.author = trackChange.author;
386346
+ }
386347
+ if (typeof trackChange.authorEmail === "string" && trackChange.authorEmail) {
386348
+ meta4.authorEmail = trackChange.authorEmail;
386349
+ }
386350
+ if (typeof trackChange.date === "string" && trackChange.date) {
386351
+ meta4.date = trackChange.date;
386352
+ }
386353
+ if (typeof storyKey === "string" && storyKey.length > 0) {
386354
+ meta4.storyKey = storyKey;
386355
+ }
386356
+ return meta4;
385142
386357
  }, parseTableRow2 = (args3) => {
385143
386358
  const { rowNode, rowIndex, context, defaultCellPadding, tableProperties, numRows } = args3;
385144
386359
  if (!isTableRowNode2(rowNode) || !Array.isArray(rowNode.content)) {
@@ -385169,13 +386384,16 @@ var isTableRowNode2 = (node3) => node3.type === "tableRow" || node3.type === "ta
385169
386384
  return null;
385170
386385
  const rowProps = rowNode.attrs?.tableRowProperties;
385171
386386
  const rowHeight = normalizeRowHeight2(rowProps);
386387
+ const trackedChangesConfig = context.trackedChangesConfig;
386388
+ const rowTrackedChange = trackedChangesConfig?.enabled && trackedChangesConfig.mode !== "off" ? buildRowTrackedChangeMeta2(rowNode, context.storyKey) : undefined;
385172
386389
  const tblPrExBordersRaw = rowProps?.tblPrExBorders;
385173
386390
  const rowBorders = tblPrExBordersRaw && typeof tblPrExBordersRaw === "object" ? extractTableBorders2(tblPrExBordersRaw, { unit: "eighthPoints" }) : undefined;
385174
386391
  const attrs = rowProps && typeof rowProps === "object" ? {
385175
386392
  tableRowProperties: rowProps,
385176
386393
  ...rowHeight ? { rowHeight } : {},
386394
+ ...rowTrackedChange ? { trackedChange: rowTrackedChange } : {},
385177
386395
  ...rowBorders ? { borders: rowBorders } : {}
385178
- } : rowHeight ? { rowHeight } : undefined;
386396
+ } : rowHeight || rowTrackedChange ? { ...rowHeight ? { rowHeight } : {}, ...rowTrackedChange ? { trackedChange: rowTrackedChange } : {} } : undefined;
385179
386397
  return {
385180
386398
  id: context.nextBlockId(`row-${rowIndex}`),
385181
386399
  cells,
@@ -424005,6 +425223,60 @@ var createPlaceholderCell2 = (gridWidth, reason) => {
424005
425223
  return false;
424006
425224
  };
424007
425225
 
425226
+ // ../../packages/super-editor/src/editors/v1/core/super-converter/v3/handlers/w/tr/row-track-change.js
425227
+ function readRowTrackChange2(trPr, params3 = {}) {
425228
+ const marker = trPr?.elements?.find((el) => el.name === "w:ins" || el.name === "w:del");
425229
+ if (!marker)
425230
+ return null;
425231
+ const side = marker.name === "w:ins" ? "insertion" : "deletion";
425232
+ const attributes = marker.attributes || {};
425233
+ const { sourceId, logicalId } = resolveTrackedChangeImportIds2(params3, attributes["w:id"]);
425234
+ const trackChange = {
425235
+ type: side === "insertion" ? "rowInsert" : "rowDelete",
425236
+ id: logicalId,
425237
+ sourceId,
425238
+ author: attributes["w:author"] || "",
425239
+ authorEmail: attributes["w:authorEmail"] || "",
425240
+ date: attributes["w:date"] || "",
425241
+ importedAuthor: `${attributes["w:author"] || ""} (imported)`
425242
+ };
425243
+ stampImportTrackingAttrs2({ params: params3, attrs: trackChange, side, sourceId });
425244
+ return trackChange;
425245
+ }
425246
+ function buildRowTrackChangeElement2(trackChange, params3 = {}) {
425247
+ if (!trackChange || trackChange.type !== "rowInsert" && trackChange.type !== "rowDelete") {
425248
+ return null;
425249
+ }
425250
+ const name = trackChange.type === "rowInsert" ? "w:ins" : "w:del";
425251
+ const wId = resolveExportRowWordId2(params3, trackChange);
425252
+ const attributes = { "w:id": wId };
425253
+ if (trackChange.author)
425254
+ attributes["w:author"] = trackChange.author;
425255
+ if (trackChange.authorEmail)
425256
+ attributes["w:authorEmail"] = trackChange.authorEmail;
425257
+ if (trackChange.date)
425258
+ attributes["w:date"] = trackChange.date;
425259
+ return { name, attributes };
425260
+ }
425261
+ function resolveExportRowWordId2(params3, trackChange) {
425262
+ const sourceId = trackChange.sourceId;
425263
+ const logicalId = typeof trackChange.id === "string" ? trackChange.id : "";
425264
+ const exportParams = params3;
425265
+ const allocator = exportParams?.converter?.wordIdAllocator;
425266
+ const partPath = exportParams?.currentPartPath || (typeof exportParams?.filename === "string" && exportParams.filename.length > 0 ? `word/${exportParams.filename}` : "word/document.xml");
425267
+ if (allocator) {
425268
+ return allocator.allocate({
425269
+ partPath,
425270
+ sourceId: sourceId === undefined ? undefined : sourceId === null ? null : String(sourceId),
425271
+ logicalId
425272
+ });
425273
+ }
425274
+ return String(sourceId || logicalId || "");
425275
+ }
425276
+ var init_row_track_change = __esm(() => {
425277
+ init_importTrackingContext();
425278
+ });
425279
+
424008
425280
  // ../../packages/super-editor/src/editors/v1/core/super-converter/v3/handlers/w/tr/tr-translator.js
424009
425281
  var XML_NODE_NAME15 = "w:tr", SD_NODE_NAME10 = "tableRow", validXmlAttributes8, getColspan2 = (cell2) => {
424010
425282
  const rawColspan = cell2?.attrs?.colspan;
@@ -424020,6 +425292,10 @@ var XML_NODE_NAME15 = "w:tr", SD_NODE_NAME10 = "tableRow", validXmlAttributes8,
424020
425292
  nodes: [tPr]
424021
425293
  });
424022
425294
  }
425295
+ const trackChange = readRowTrackChange2(tPr, params3);
425296
+ if (trackChange) {
425297
+ encodedAttrs["trackChange"] = trackChange;
425298
+ }
424023
425299
  const gridBeforeRaw = tableRowProperties?.["gridBefore"];
424024
425300
  const safeGridBefore = typeof gridBeforeRaw === "number" && Number.isFinite(gridBeforeRaw) && gridBeforeRaw > 0 ? gridBeforeRaw : 0;
424025
425301
  const tblPrEx = row2.elements?.find((el) => el.name === "w:tblPrEx");
@@ -424193,11 +425469,82 @@ var XML_NODE_NAME15 = "w:tr", SD_NODE_NAME10 = "tableRow", validXmlAttributes8,
424193
425469
  if (trPr)
424194
425470
  elements.unshift(trPr);
424195
425471
  }
425472
+ applyRowTrackChangeOnDecode2({ node: node4, elements, params: params3 });
424196
425473
  return {
424197
425474
  name: "w:tr",
424198
425475
  attributes: decodedAttrs || {},
424199
425476
  elements
424200
425477
  };
425478
+ }, applyRowTrackChangeOnDecode2 = ({ node: node4, elements, params: params3 }) => {
425479
+ const marker = buildRowTrackChangeElement2(node4.attrs?.trackChange, params3);
425480
+ if (!marker)
425481
+ return;
425482
+ let trPr = elements.find((el) => el && el.name === "w:trPr");
425483
+ if (!trPr) {
425484
+ trPr = { name: "w:trPr", elements: [] };
425485
+ elements.unshift(trPr);
425486
+ }
425487
+ if (!Array.isArray(trPr.elements))
425488
+ trPr.elements = [];
425489
+ const trPrChangeIndex = trPr.elements.findIndex((el) => el && el.name === "w:trPrChange");
425490
+ if (trPrChangeIndex === -1) {
425491
+ trPr.elements.push(marker);
425492
+ } else {
425493
+ trPr.elements.splice(trPrChangeIndex, 0, marker);
425494
+ }
425495
+ applyCellContentTrackChange2({ elements, markerName: marker.name, markerAttributes: marker.attributes });
425496
+ }, applyCellContentTrackChange2 = ({ elements, markerName, markerAttributes }) => {
425497
+ if (markerName !== "w:ins" && markerName !== "w:del")
425498
+ return;
425499
+ const isDelete = markerName === "w:del";
425500
+ const makeMarker = (children) => ({ name: markerName, attributes: { ...markerAttributes }, elements: children });
425501
+ const RUN_CONTAINERS = new Set(["w:hyperlink", "w:smartTag", "w:sdt", "w:sdtContent", "w:dir", "w:bdo"]);
425502
+ const wrapRuns = (content4) => (Array.isArray(content4) ? content4 : []).map((el) => {
425503
+ if (!el || typeof el !== "object")
425504
+ return el;
425505
+ if (el.name === "w:r") {
425506
+ if (isDelete && Array.isArray(el.elements)) {
425507
+ el.elements = el.elements.map((child) => child?.name === "w:t" ? { ...child, name: "w:delText" } : child);
425508
+ }
425509
+ return makeMarker([el]);
425510
+ }
425511
+ if (RUN_CONTAINERS.has(el.name) && Array.isArray(el.elements)) {
425512
+ return { ...el, elements: wrapRuns(el.elements) };
425513
+ }
425514
+ return el;
425515
+ });
425516
+ for (const tc of elements) {
425517
+ if (tc?.name !== "w:tc" || !Array.isArray(tc.elements))
425518
+ continue;
425519
+ for (const paragraph4 of tc.elements) {
425520
+ if (paragraph4?.name !== "w:p")
425521
+ continue;
425522
+ if (!Array.isArray(paragraph4.elements))
425523
+ paragraph4.elements = [];
425524
+ let pPr = paragraph4.elements.find((el) => el?.name === "w:pPr");
425525
+ if (!pPr) {
425526
+ pPr = { name: "w:pPr", elements: [] };
425527
+ paragraph4.elements.unshift(pPr);
425528
+ }
425529
+ if (!Array.isArray(pPr.elements))
425530
+ pPr.elements = [];
425531
+ let rPr = pPr.elements.find((el) => el?.name === "w:rPr");
425532
+ if (!rPr) {
425533
+ rPr = { name: "w:rPr", elements: [] };
425534
+ const terminalIdx = pPr.elements.findIndex((el) => el?.name === "w:sectPr" || el?.name === "w:pPrChange");
425535
+ if (terminalIdx === -1)
425536
+ pPr.elements.push(rPr);
425537
+ else
425538
+ pPr.elements.splice(terminalIdx, 0, rPr);
425539
+ }
425540
+ if (!Array.isArray(rPr.elements))
425541
+ rPr.elements = [];
425542
+ const alreadyMarked = rPr.elements.some((el) => el?.name === "w:ins" || el?.name === "w:del");
425543
+ if (!alreadyMarked)
425544
+ rPr.elements.unshift({ name: markerName, attributes: { ...markerAttributes } });
425545
+ paragraph4.elements = wrapRuns(paragraph4.elements);
425546
+ }
425547
+ }
424201
425548
  }, config16, translator155;
424202
425549
  var init_tr_translator = __esm(() => {
424203
425550
  init_node_translator2();
@@ -424207,6 +425554,7 @@ var init_tr_translator = __esm(() => {
424207
425554
  init_tc();
424208
425555
  init_tblBorders();
424209
425556
  init_trPr();
425557
+ init_row_track_change();
424210
425558
  validXmlAttributes8 = ["w:rsidDel", "w:rsidR", "w:rsidRPr", "w:rsidTr", "w14:paraId", "w14:textId"].map((xmlName) => createAttributeHandler2(xmlName));
424211
425559
  config16 = {
424212
425560
  xmlName: XML_NODE_NAME15,
@@ -454347,6 +455695,103 @@ var init_getTrackChanges = __esm(() => {
454347
455695
  init_constants2();
454348
455696
  });
454349
455697
 
455698
+ // ../../packages/super-editor/src/editors/v1/extensions/track-changes/trackChangesHelpers/structuralRowChanges.js
455699
+ var enumerateStructuralRowChanges2 = (state) => {
455700
+ const doc6 = state?.doc;
455701
+ if (!doc6)
455702
+ return [];
455703
+ const out = [];
455704
+ try {
455705
+ doc6.descendants((node4, pos) => {
455706
+ if (node4.type?.name !== "table")
455707
+ return;
455708
+ collectTableStructuralChanges2({ table: node4, tablePos: pos, out });
455709
+ return true;
455710
+ });
455711
+ } catch {
455712
+ return out;
455713
+ }
455714
+ return out;
455715
+ }, collectTableStructuralChanges2 = ({ table: table2, tablePos, out }) => {
455716
+ const tableFrom = tablePos;
455717
+ const tableTo = tablePos + table2.nodeSize;
455718
+ const trackedRows = [];
455719
+ let totalRows = 0;
455720
+ let offset2 = 1;
455721
+ table2.forEach((child) => {
455722
+ const childFrom = tablePos + offset2;
455723
+ offset2 += child.nodeSize;
455724
+ if (child.type?.name !== "tableRow")
455725
+ return;
455726
+ totalRows += 1;
455727
+ const tc = child.attrs?.trackChange;
455728
+ if (!tc || tc.type !== "rowInsert" && tc.type !== "rowDelete")
455729
+ return;
455730
+ const side2 = tc.type === "rowInsert" ? "insertion" : "deletion";
455731
+ trackedRows.push({
455732
+ ref: { pos: childFrom, from: childFrom, to: childFrom + child.nodeSize, node: child },
455733
+ side: side2,
455734
+ tc
455735
+ });
455736
+ });
455737
+ if (trackedRows.length === 0)
455738
+ return;
455739
+ const sides = new Set(trackedRows.map((r2) => r2.side));
455740
+ const everyRowTracked = trackedRows.length === totalRows && totalRows > 0;
455741
+ const singleSide = sides.size === 1;
455742
+ const wholeTable = everyRowTracked && singleSide;
455743
+ if (wholeTable) {
455744
+ const side2 = trackedRows[0].side;
455745
+ const primary2 = trackedRows[0].tc;
455746
+ const representativeRevisionId2 = stringOf2(primary2.id) || stringOf2(primary2.sourceId);
455747
+ const publicId = stringOf2(primary2.sourceId) || representativeRevisionId2 || `table:${tableFrom}:${side2}`;
455748
+ out.push({
455749
+ id: publicId,
455750
+ revisionId: representativeRevisionId2,
455751
+ side: side2,
455752
+ subtype: side2 === "insertion" ? "table-insert" : "table-delete",
455753
+ tableFrom,
455754
+ tableTo,
455755
+ tablePos,
455756
+ wholeTable: true,
455757
+ decidable: true,
455758
+ rows: trackedRows.map((r2) => r2.ref),
455759
+ author: stringOf2(primary2.author),
455760
+ authorEmail: stringOf2(primary2.authorEmail),
455761
+ authorImage: stringOf2(primary2.authorImage),
455762
+ date: stringOf2(primary2.date),
455763
+ importedAuthor: stringOf2(primary2.importedAuthor),
455764
+ sourceId: stringOf2(primary2.sourceId),
455765
+ revisionGroupId: stringOf2(primary2.revisionGroupId) || representativeRevisionId2 || publicId
455766
+ });
455767
+ return;
455768
+ }
455769
+ const side = trackedRows[0].side;
455770
+ const primary = trackedRows[0].tc;
455771
+ const representativeRevisionId = stringOf2(primary.id) || stringOf2(primary.sourceId);
455772
+ const reason = !everyRowTracked ? "partial-rows" : "mixed-sides";
455773
+ out.push({
455774
+ id: stringOf2(primary.sourceId) || representativeRevisionId || `table:${tableFrom}:${side}`,
455775
+ revisionId: representativeRevisionId,
455776
+ side,
455777
+ subtype: side === "insertion" ? "table-insert" : "table-delete",
455778
+ tableFrom,
455779
+ tableTo,
455780
+ tablePos,
455781
+ wholeTable: false,
455782
+ decidable: false,
455783
+ undecidableReason: reason,
455784
+ rows: trackedRows.map((r2) => r2.ref),
455785
+ author: stringOf2(primary.author),
455786
+ authorEmail: stringOf2(primary.authorEmail),
455787
+ authorImage: stringOf2(primary.authorImage),
455788
+ date: stringOf2(primary.date),
455789
+ importedAuthor: stringOf2(primary.importedAuthor),
455790
+ sourceId: stringOf2(primary.sourceId),
455791
+ revisionGroupId: stringOf2(primary.revisionGroupId) || representativeRevisionId
455792
+ });
455793
+ }, stringOf2 = (value) => typeof value === "string" ? value : value == null ? "" : String(value);
455794
+
454350
455795
  // ../../packages/super-editor/src/editors/v1/document-api-adapters/helpers/tracked-change-resolver.ts
454351
455796
  function rangesOverlap3(a2, b2) {
454352
455797
  return a2[0] < b2[1] && b2[0] < a2[1];
@@ -454359,10 +455804,12 @@ function getRawTrackedMarks2(editor) {
454359
455804
  return [];
454360
455805
  }
454361
455806
  }
454362
- function deriveTrackedChangeId3(change) {
455807
+ function deriveTrackedChangeId4(change) {
454363
455808
  return change.rawId;
454364
455809
  }
454365
455810
  function resolveTrackedChangeType2(change) {
455811
+ if (change.structural)
455812
+ return "structural";
454366
455813
  if (change.hasFormat)
454367
455814
  return "format";
454368
455815
  if (change.hasInsert && change.hasDelete)
@@ -454603,7 +456050,7 @@ function groupTrackedChanges2(editor) {
454603
456050
  };
454604
456051
  return {
454605
456052
  ...withExcerpt,
454606
- id: deriveTrackedChangeId3(withExcerpt)
456053
+ id: deriveTrackedChangeId4(withExcerpt)
454607
456054
  };
454608
456055
  }).sort((a2, b2) => {
454609
456056
  if (a2.from !== b2.from)
@@ -454611,6 +456058,39 @@ function groupTrackedChanges2(editor) {
454611
456058
  return a2.id.localeCompare(b2.id);
454612
456059
  });
454613
456060
  attachOverlapMetadata2(grouped);
456061
+ for (const structural of enumerateStructuralRowChanges2(editor.state)) {
456062
+ const excerpt = normalizeExcerpt2(editor.state.doc.textBetween(structural.tableFrom, structural.tableTo, " ", ""));
456063
+ const stableRawId = structural.sourceId ? `word:structural:${structural.sourceId}` : structural.id;
456064
+ grouped.push({
456065
+ rawId: stableRawId,
456066
+ commandRawId: structural.id,
456067
+ id: stableRawId,
456068
+ from: structural.tableFrom,
456069
+ to: structural.tableTo,
456070
+ hasInsert: false,
456071
+ hasDelete: false,
456072
+ hasFormat: false,
456073
+ structural: { side: structural.side, subtype: structural.subtype },
456074
+ attrs: {
456075
+ id: structural.id,
456076
+ sourceId: structural.sourceId || undefined,
456077
+ author: structural.author || undefined,
456078
+ authorEmail: structural.authorEmail || undefined,
456079
+ authorImage: structural.authorImage || undefined,
456080
+ date: structural.date || undefined,
456081
+ importedAuthor: structural.importedAuthor || undefined,
456082
+ origin: structural.sourceId ? "word" : undefined,
456083
+ revisionGroupId: structural.revisionGroupId || undefined
456084
+ },
456085
+ excerpt,
456086
+ wordRevisionIds: structural.sourceId ? structural.side === "insertion" ? { insert: structural.sourceId } : { delete: structural.sourceId } : undefined
456087
+ });
456088
+ }
456089
+ grouped.sort((a2, b2) => {
456090
+ if (a2.from !== b2.from)
456091
+ return a2.from - b2.from;
456092
+ return a2.id.localeCompare(b2.id);
456093
+ });
454614
456094
  groupedCache2.set(editor, { doc: currentDoc, grouped });
454615
456095
  return grouped;
454616
456096
  }
@@ -468581,11 +470061,13 @@ class TrackedChangeIndexImpl2 {
468581
470061
  const address2 = buildTrackedChangeAddress2(locator, storyKey, change.id);
468582
470062
  const type = resolveTrackedChangeType2(change);
468583
470063
  const excerpt = (change.excerpt !== undefined ? change.excerpt : undefined) ?? normalizeExcerpt2(editor.state.doc.textBetween(change.from, change.to, " ", ""));
470064
+ const subtype = type === "structural" && change.structural ? change.structural.subtype : undefined;
468584
470065
  return {
468585
470066
  address: address2,
468586
470067
  runtimeRef,
468587
470068
  story: locator,
468588
470069
  type,
470070
+ subtype,
468589
470071
  author: toNonEmptyString2(change.attrs.author),
468590
470072
  authorEmail: toNonEmptyString2(change.attrs.authorEmail),
468591
470073
  authorImage: toNonEmptyString2(change.attrs.authorImage),
@@ -468781,6 +470263,7 @@ function buildProjectedInfo2(snapshot2, options = {}) {
468781
470263
  },
468782
470264
  id: id2,
468783
470265
  type,
470266
+ ...type === "structural" && snapshot2.subtype ? { subtype: snapshot2.subtype } : {},
468784
470267
  grouping: options.grouping,
468785
470268
  pairedWithChangeId: options.pairedWithChangeId ?? undefined,
468786
470269
  wordRevisionIds: normalizeWordRevisionIds2(snapshot2.wordRevisionIds),
@@ -469044,6 +470527,7 @@ function trackChangesListWrapper2(editor, input2) {
469044
470527
  const {
469045
470528
  address: address2,
469046
470529
  type,
470530
+ subtype,
469047
470531
  grouping,
469048
470532
  pairedWithChangeId,
469049
470533
  wordRevisionIds,
@@ -469061,6 +470545,7 @@ function trackChangesListWrapper2(editor, input2) {
469061
470545
  return buildDiscoveryItem2(info.id, handle4, {
469062
470546
  address: address2,
469063
470547
  type,
470548
+ ...subtype ? { subtype } : {},
469064
470549
  grouping,
469065
470550
  pairedWithChangeId,
469066
470551
  wordRevisionIds,
@@ -469118,6 +470603,7 @@ function trackChangesGetWrapper2(editor, input2) {
469118
470603
  },
469119
470604
  id: resolved.change.id,
469120
470605
  type,
470606
+ ...type === "structural" && resolved.change.structural ? { subtype: resolved.change.structural.subtype } : {},
469121
470607
  grouping,
469122
470608
  wordRevisionIds: normalizeWordRevisionIds2(resolved.change.wordRevisionIds),
469123
470609
  overlap: resolved.change.overlap,
@@ -505568,9 +507054,10 @@ EXAMPLES:
505568
507054
  "insert",
505569
507055
  "delete",
505570
507056
  "replacement",
505571
- "format"
507057
+ "format",
507058
+ "structural"
505572
507059
  ],
505573
- description: "Filter by change type: 'insert', 'delete', 'replacement', or 'format'. Only for action 'list'. Omit for other actions."
507060
+ description: "Filter by change type: 'insert', 'delete', 'replacement', 'format', or 'structural'. Only for action 'list'. Omit for other actions."
505574
507061
  },
505575
507062
  force: {
505576
507063
  type: "boolean",
@@ -505601,6 +507088,10 @@ EXAMPLES:
505601
507088
  },
505602
507089
  story: {
505603
507090
  $ref: "#/$defs/StoryLocator"
507091
+ },
507092
+ range: {
507093
+ type: "object",
507094
+ description: "Partial-range qualifier on an id target. Rejected with INVALID_INPUT for indivisible (e.g. structural) revisions."
505604
507095
  }
505605
507096
  },
505606
507097
  additionalProperties: false,