smartrte-react 0.3.5 → 1.0.0-beta.2

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 (141) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +106 -14
  3. package/dist/adapters/domChecklistCommandBridge.js +1 -1
  4. package/dist/adapters/domCommandBridge.d.ts +2 -2
  5. package/dist/adapters/domCommandBridge.js +2 -2
  6. package/dist/adapters/domInlineAtomCommandBridge.d.ts +10 -9
  7. package/dist/adapters/domInlineAtomCommandBridge.js +154 -50
  8. package/dist/adapters/domInlineImageCommandBridge.d.ts +7 -7
  9. package/dist/adapters/domInlineImageCommandBridge.js +6 -72
  10. package/dist/adapters/domMoveCommandBridge.js +1 -1
  11. package/dist/adapters/domSelectionBridge.d.ts +3 -3
  12. package/dist/adapters/domSmartDocument.d.ts +4 -4
  13. package/dist/adapters/domSmartDocument.js +2 -2
  14. package/dist/adapters/domTableCommandBridge.d.ts +42 -16
  15. package/dist/adapters/domTableCommandBridge.js +203 -173
  16. package/dist/adapters/internalFlags.d.ts +0 -8
  17. package/dist/adapters/internalFlags.js +0 -24
  18. package/dist/adapters/legacyListShadowComparator.d.ts +1 -1
  19. package/dist/adapters/legacyListShadowComparator.js +1 -1
  20. package/dist/adapters/pdfPrint.d.ts +8 -0
  21. package/dist/adapters/pdfPrint.js +22 -0
  22. package/dist/adapters/shadowMode.d.ts +3 -3
  23. package/dist/adapters/shadowMode.js +1 -1
  24. package/dist/canonicalEditorRuntime.d.ts +53 -1
  25. package/dist/canonicalEditorRuntime.js +61 -4
  26. package/dist/capabilityPresets.d.ts +27 -0
  27. package/dist/capabilityPresets.js +21 -0
  28. package/dist/collabTransport.d.ts +66 -0
  29. package/dist/collabTransport.js +1 -0
  30. package/dist/commentProvider.d.ts +24 -0
  31. package/dist/commentProvider.js +1 -0
  32. package/dist/components/CanonicalAuthorityEditor.d.ts +35 -1
  33. package/dist/components/CanonicalAuthorityEditor.js +1086 -112
  34. package/dist/components/ClassicEditorAuthority.d.ts +93 -22
  35. package/dist/components/ClassicEditorAuthority.js +11 -43
  36. package/dist/components/ColorPickerPopover.d.ts +39 -0
  37. package/dist/components/ColorPickerPopover.js +285 -0
  38. package/dist/components/CommentMarkers.d.ts +25 -0
  39. package/dist/components/CommentMarkers.js +105 -0
  40. package/dist/components/CommentThreadPanel.d.ts +26 -0
  41. package/dist/components/CommentThreadPanel.js +47 -0
  42. package/dist/components/ContextMenu.d.ts +23 -0
  43. package/dist/components/ContextMenu.js +141 -0
  44. package/dist/components/FormulaLibraryPopover.d.ts +16 -0
  45. package/dist/components/FormulaLibraryPopover.js +107 -0
  46. package/dist/components/LinkEditorPopover.d.ts +3 -1
  47. package/dist/components/LinkEditorPopover.js +22 -6
  48. package/dist/components/MediaManager.d.ts +4 -20
  49. package/dist/components/MediaManager.js +35 -6
  50. package/dist/components/MediaOverlay.d.ts +36 -0
  51. package/dist/components/MediaOverlay.js +163 -0
  52. package/dist/components/SpecialCharacterPopover.d.ts +18 -0
  53. package/dist/components/SpecialCharacterPopover.js +99 -0
  54. package/dist/components/StructuralSuggestionMarkers.d.ts +20 -0
  55. package/dist/components/StructuralSuggestionMarkers.js +56 -0
  56. package/dist/components/SuggestionPanel.d.ts +26 -0
  57. package/dist/components/SuggestionPanel.js +33 -0
  58. package/dist/components/TableBorderPopover.d.ts +59 -0
  59. package/dist/components/TableBorderPopover.js +147 -0
  60. package/dist/components/TableResizeHandles.d.ts +25 -0
  61. package/dist/components/TableResizeHandles.js +301 -0
  62. package/dist/components/TableSizePickerPopover.d.ts +16 -0
  63. package/dist/components/TableSizePickerPopover.js +126 -0
  64. package/dist/components/ToolbarPrimitives.d.ts +129 -0
  65. package/dist/components/ToolbarPrimitives.js +146 -0
  66. package/dist/components/VersionHistoryPanel.d.ts +9 -0
  67. package/dist/components/VersionHistoryPanel.js +157 -0
  68. package/dist/formulaLibrary.d.ts +31 -0
  69. package/dist/formulaLibrary.js +90 -0
  70. package/dist/index.d.ts +22 -24
  71. package/dist/index.js +14 -11
  72. package/dist/mediaManagerAdapter.d.ts +12 -0
  73. package/dist/mediaManagerAdapter.js +34 -0
  74. package/dist/mediaProvider.d.ts +21 -1
  75. package/dist/specialCharacters.d.ts +22 -0
  76. package/dist/specialCharacters.js +86 -0
  77. package/dist/standalone/classic-editor-embed.js +19 -12
  78. package/dist/suggestionProvider.d.ts +17 -0
  79. package/dist/suggestionProvider.js +1 -0
  80. package/dist/theme.d.ts +1 -1
  81. package/dist/theme.js +150 -20
  82. package/dist/versionProvider.d.ts +29 -0
  83. package/dist/versionProvider.js +1 -0
  84. package/package.json +28 -14
  85. package/dist/adapters/canonicalInlineCommandBridge.d.ts +0 -15
  86. package/dist/adapters/canonicalInlineCommandBridge.js +0 -269
  87. package/dist/adapters/canonicalListCommandBridge.d.ts +0 -26
  88. package/dist/adapters/canonicalListCommandBridge.js +0 -430
  89. package/dist/adapters/coreBold.d.ts +0 -5
  90. package/dist/adapters/coreBold.js +0 -3
  91. package/dist/adapters/documentFormats.d.ts +0 -26
  92. package/dist/adapters/documentFormats.js +0 -49
  93. package/dist/adapters/docxFormat.d.ts +0 -5
  94. package/dist/adapters/docxFormat.js +0 -272
  95. package/dist/adapters/domBlockCommandBridge.d.ts +0 -19
  96. package/dist/adapters/domBlockCommandBridge.js +0 -79
  97. package/dist/adapters/inlineMarkCoreExecution.d.ts +0 -9
  98. package/dist/adapters/inlineMarkCoreExecution.js +0 -25
  99. package/dist/adapters/pdfFormat.d.ts +0 -23
  100. package/dist/adapters/pdfFormat.js +0 -204
  101. package/dist/adapters/portableDocxAtoms.d.ts +0 -4
  102. package/dist/adapters/portableDocxAtoms.js +0 -58
  103. package/dist/adapters/styledDocxFormat.d.ts +0 -8
  104. package/dist/adapters/styledDocxFormat.js +0 -190
  105. package/dist/builtInFormatDefinitions.d.ts +0 -5
  106. package/dist/builtInFormatDefinitions.js +0 -82
  107. package/dist/canonicalAuthorityFlag.d.ts +0 -32
  108. package/dist/canonicalAuthorityFlag.js +0 -49
  109. package/dist/canonicalClipboardRuntime.d.ts +0 -15
  110. package/dist/canonicalClipboardRuntime.js +0 -76
  111. package/dist/components/ClassicEditor.d.ts +0 -76
  112. package/dist/components/ClassicEditor.js +0 -6729
  113. package/dist/editorController.d.ts +0 -78
  114. package/dist/editorController.js +0 -298
  115. package/dist/formatFidelity.d.ts +0 -14
  116. package/dist/formatFidelity.js +0 -107
  117. package/dist/formatRuntime.d.ts +0 -50
  118. package/dist/formatRuntime.js +0 -20
  119. package/dist/pluginRuntime.d.ts +0 -68
  120. package/dist/pluginRuntime.js +0 -78
  121. package/dist/standalone/editor.js +0 -1068
  122. package/dist/test-harness/atomShadowComparator.d.ts +0 -14
  123. package/dist/test-harness/atomShadowComparator.js +0 -63
  124. package/dist/test-harness/blockShadowComparator.d.ts +0 -30
  125. package/dist/test-harness/blockShadowComparator.js +0 -140
  126. package/dist/test-harness/clipboardShadowComparator.d.ts +0 -12
  127. package/dist/test-harness/clipboardShadowComparator.js +0 -46
  128. package/dist/test-harness/inlineShadowComparator.d.ts +0 -32
  129. package/dist/test-harness/inlineShadowComparator.js +0 -152
  130. package/dist/test-harness/legacyAtomEngine.d.ts +0 -10
  131. package/dist/test-harness/legacyAtomEngine.js +0 -15
  132. package/dist/test-harness/legacyBlockEngine.d.ts +0 -31
  133. package/dist/test-harness/legacyBlockEngine.js +0 -31
  134. package/dist/test-harness/legacyClipboardEngine.d.ts +0 -14
  135. package/dist/test-harness/legacyClipboardEngine.js +0 -67
  136. package/dist/test-harness/legacyInlineEngine.d.ts +0 -19
  137. package/dist/test-harness/legacyInlineEngine.js +0 -49
  138. package/dist/test-harness/legacyTableEngine.d.ts +0 -12
  139. package/dist/test-harness/legacyTableEngine.js +0 -25
  140. package/dist/test-harness/tableShadowComparator.d.ts +0 -29
  141. package/dist/test-harness/tableShadowComparator.js +0 -101
@@ -1,35 +1,61 @@
1
- import { type MergeTableCellsInput, type SetTableCellStyleInput, type SetTableColumnWidthInput, type SetTableRowHeightInput, type TableHeaderInput, type SplitTableCellInput, type TableColumnInput, type TableRowInput, type ToggleTableCellBorderInput } from "smartrte-core";
1
+ type Point = {
2
+ row: number;
3
+ column: number;
4
+ };
2
5
  export type DomTableCommand = {
6
+ id: "table.remove";
7
+ input?: Record<string, never>;
8
+ } | {
3
9
  id: "table.row.add" | "table.row.remove";
4
- input: Omit<TableRowInput, "tablePath">;
10
+ input: {
11
+ index: number;
12
+ };
5
13
  } | {
6
14
  id: "table.column.add" | "table.column.remove";
7
- input: Omit<TableColumnInput, "tablePath">;
15
+ input: {
16
+ index: number;
17
+ };
8
18
  } | {
9
19
  id: "table.cell.merge";
10
- input: Omit<MergeTableCellsInput, "tablePath">;
20
+ input: {
21
+ start: Point;
22
+ end: Point;
23
+ };
11
24
  } | {
12
25
  id: "table.cell.split";
13
- input: Omit<SplitTableCellInput, "tablePath">;
26
+ input: Point;
14
27
  } | {
15
28
  id: "table.header.cell.toggle" | "table.header.row.toggle" | "table.header.column.toggle";
16
- input: Omit<TableHeaderInput, "tablePath">;
29
+ input: Point;
17
30
  } | {
18
31
  id: "table.cell.style.set";
19
- input: Omit<SetTableCellStyleInput, "tablePath">;
32
+ input: {
33
+ start: Point;
34
+ end?: Point;
35
+ backgroundColor?: string | null;
36
+ textColor?: string | null;
37
+ };
20
38
  } | {
21
39
  id: "table.column.width.set";
22
- input: Omit<SetTableColumnWidthInput, "tablePath">;
40
+ input: {
41
+ index: number;
42
+ widthPx: number;
43
+ };
23
44
  } | {
24
45
  id: "table.row.height.set";
25
- input: Omit<SetTableRowHeightInput, "tablePath">;
46
+ input: {
47
+ index: number;
48
+ heightPx: number;
49
+ };
26
50
  } | {
27
51
  id: "table.cell.border.toggle";
28
- input: Omit<ToggleTableCellBorderInput, "tablePath">;
52
+ input: {
53
+ start: Point;
54
+ end?: Point;
55
+ visibleBorder?: string;
56
+ };
29
57
  };
30
- /**
31
- * Executes a core table command while replacing only the affected table.
32
- * Visual table/cell attributes are transferred by logical grid position.
33
- */
34
- export declare const executeDomTableCommand: (table: HTMLTableElement, command: DomTableCommand) => HTMLTableElement | null;
35
- export declare const executeDomTableRemoval: (table: HTMLTableElement) => boolean;
58
+ export declare const executeDomTableCommand: (element: HTMLTableElement, command: DomTableCommand) => HTMLTableElement | null;
59
+ export declare const executeDomTableRemoval: (element: HTMLTableElement) => boolean;
60
+ export declare const executeDomTableInsert: (root: HTMLElement, afterBlockIndex: number, rows: number, columns: number, withHeader?: boolean) => HTMLTableElement | null;
61
+ export {};
@@ -1,201 +1,231 @@
1
- import { createSmartEditor, tablePlugin, } from "smartrte-core";
2
- import { serializeSmartDocument, smartDocumentFromHtml } from "./domSmartDocument.js";
3
- const cellsOf = (row) => Array.from(row.children).filter((node) => node instanceof HTMLTableCellElement);
4
- const cellGrid = (table) => {
5
- const rows = Array.from(table.rows);
6
- const grid = [];
7
- rows.forEach((row, rowIndex) => {
8
- grid[rowIndex] || (grid[rowIndex] = []);
1
+ import { applyOperations, createNodeId, createScopeIndex, foundationSchema, insertTableColumnCommand, insertTableCommand, insertTableRowCommand, mergeTableCellsCommand, occupancyGridFor, parseCanonicalTableHtml, removeTableColumnCommand, removeTableRowCommand, removeTableCommand, repair, serializeCanonicalTableHtml, setTableCellAttributesCommand, setTableColumnWidthCommand, setTableHeaderCommand, setTableRowHeightCommand, splitTableCellCommand, } from "smartrte-core/foundation";
2
+ const canonicalTable = (element) => {
3
+ const repaired = repair(parseCanonicalTableHtml(element.outerHTML)).doc;
4
+ const table = repaired.children[0];
5
+ return table && table.type === "table" ? { document: repaired, table: table } : null;
6
+ };
7
+ const tableScope = (table, start, end = start) => {
8
+ const grid = occupancyGridFor(table);
9
+ const top = Math.max(0, Math.min(start.row, end.row));
10
+ const bottom = Math.min(grid.rows - 1, Math.max(start.row, end.row));
11
+ const left = Math.max(0, Math.min(start.column, end.column));
12
+ const right = Math.min(grid.columns - 1, Math.max(start.column, end.column));
13
+ const exclusive = { top, left, bottom: bottom + 1, right: right + 1 };
14
+ return {
15
+ kind: "table-grid", tableId: table.id, rect: { top, left, bottom, right },
16
+ cellIds: grid.anchors.filter((cell) => cell.top <= bottom && cell.bottom > top && cell.left <= right && cell.right > left).map((cell) => cell.cellId),
17
+ coveredCellIds: grid.coveredIn(exclusive).map((cell) => cell.cellId),
18
+ rectangular: grid.isRectangular(exclusive), range: { from: { path: [0], offset: 0 }, to: { path: [0], offset: 1 } },
19
+ isolatingAncestorId: null, clamped: false,
20
+ };
21
+ };
22
+ const commandContext = (document) => ({ schema: foundationSchema, positions: createScopeIndex().positions(document, foundationSchema) });
23
+ const generated = (count, prefix) => Array.from({ length: count }, () => `${prefix}-${createNodeId()}`);
24
+ const domGrid = (table) => {
25
+ const slots = [];
26
+ Array.from(table.rows).forEach((row, rowIndex) => {
27
+ slots[rowIndex] || (slots[rowIndex] = []);
9
28
  let column = 0;
10
- cellsOf(row).forEach((cell) => {
11
- var _a;
12
- while (grid[rowIndex][column])
29
+ Array.from(row.cells).forEach((cell) => {
30
+ while (slots[rowIndex][column])
13
31
  column += 1;
14
- const rowspan = Math.max(1, cell.rowSpan || 1);
15
- const colspan = Math.max(1, cell.colSpan || 1);
16
- for (let rowOffset = 0; rowOffset < rowspan; rowOffset += 1) {
17
- grid[_a = rowIndex + rowOffset] || (grid[_a] = []);
18
- for (let columnOffset = 0; columnOffset < colspan; columnOffset += 1) {
19
- grid[rowIndex + rowOffset][column + columnOffset] = cell;
20
- }
32
+ for (let r = rowIndex; r < rowIndex + Math.max(1, cell.rowSpan); r += 1) {
33
+ slots[r] || (slots[r] = []);
34
+ for (let c = column; c < column + Math.max(1, cell.colSpan); c += 1)
35
+ slots[r][c] = cell;
21
36
  }
22
- column += colspan;
37
+ column += Math.max(1, cell.colSpan);
23
38
  });
24
39
  });
25
- return grid;
40
+ return slots;
26
41
  };
27
42
  const copyVisualAttributes = (from, to) => {
28
- const style = from.getAttribute("style");
29
- const className = from.getAttribute("class");
30
- if (style)
31
- to.setAttribute("style", style);
32
- if (className)
33
- to.setAttribute("class", className);
34
- };
35
- const reconcileHeaderStyle = (from, to) => {
36
- if (from.tagName === to.tagName)
37
- return;
38
- if (to.tagName === "TH") {
39
- to.style.fontWeight = "700";
40
- to.style.background = to.style.background || "#f3f4f6";
41
- to.style.textAlign = to.style.textAlign || "left";
42
- return;
43
- }
44
- if (to.style.fontWeight === "700" || to.style.fontWeight === "bold")
45
- to.style.fontWeight = "";
46
- if (to.style.background === "rgb(243, 244, 246)" || to.style.background === "#f3f4f6") {
47
- to.style.background = "";
48
- }
43
+ if (from.className)
44
+ to.className = from.className;
45
+ const retained = from.getAttribute("style");
46
+ if (retained)
47
+ for (const declaration of retained.split(";")) {
48
+ const separator = declaration.indexOf(":");
49
+ if (separator > 0)
50
+ to.style.setProperty(declaration.slice(0, separator).trim(), declaration.slice(separator + 1).trim());
51
+ }
49
52
  };
50
- /**
51
- * Executes a core table command while replacing only the affected table.
52
- * Visual table/cell attributes are transferred by logical grid position.
53
- */
54
- export const executeDomTableCommand = (table, command) => {
55
- const document = smartDocumentFromHtml(table.outerHTML, table.ownerDocument);
56
- if (document.children.length !== 1 || document.children[0].type !== "table")
57
- return null;
58
- const editor = createSmartEditor({
59
- state: { document, selection: { type: "node", path: [0] } },
60
- plugins: [tablePlugin],
61
- });
62
- if (!editor.execute(command.id, { ...command.input, tablePath: [0] }))
63
- return null;
64
- if (command.id === "table.column.width.set") {
65
- let group = table.querySelector(":scope > colgroup");
53
+ const projectAttributesInPlace = (element, after) => {
54
+ const table = after.children[0];
55
+ const modelGrid = occupancyGridFor(table);
56
+ const grid = domGrid(element);
57
+ const widths = Array.isArray(table.attrs?.columnWidths) ? table.attrs.columnWidths : [];
58
+ if (widths.length) {
59
+ let group = element.querySelector(":scope > colgroup");
66
60
  if (!group) {
67
- group = table.ownerDocument.createElement("colgroup");
68
- table.insertBefore(group, table.firstChild);
69
- }
70
- const logicalWidth = Math.max(...cellGrid(table).map((row) => row.length));
71
- while (group.children.length < logicalWidth) {
72
- group.appendChild(table.ownerDocument.createElement("col"));
73
- }
74
- const column = group.children[command.input.index];
75
- if (!column)
76
- return null;
77
- column.style.width = `${command.input.widthPx}px`;
78
- const seen = new Set();
79
- cellGrid(table).forEach((row) => {
80
- const target = row[command.input.index];
81
- if (!target || seen.has(target))
82
- return;
83
- seen.add(target);
84
- target.style.width = `${command.input.widthPx}px`;
85
- target.style.minWidth = `${command.input.widthPx}px`;
86
- target.style.maxWidth = `${command.input.widthPx}px`;
87
- });
88
- return table;
89
- }
90
- if (command.id === "table.row.height.set") {
91
- const row = table.rows[command.input.index];
92
- if (!row)
93
- return null;
94
- row.style.height = `${command.input.heightPx}px`;
95
- cellsOf(row).forEach((target) => {
96
- target.style.height = `${command.input.heightPx}px`;
97
- });
98
- return table;
99
- }
100
- if (command.id === "table.cell.style.set") {
101
- const end = command.input.end || command.input.start;
102
- const top = Math.min(command.input.start.row, end.row);
103
- const bottom = Math.max(command.input.start.row, end.row);
104
- const left = Math.min(command.input.start.column, end.column);
105
- const right = Math.max(command.input.start.column, end.column);
106
- const grid = cellGrid(table);
107
- const targets = new Set();
108
- for (let row = top; row <= bottom; row += 1) {
109
- for (let column = left; column <= right; column += 1) {
110
- const target = grid[row]?.[column];
111
- if (target)
112
- targets.add(target);
113
- }
61
+ group = element.ownerDocument.createElement("colgroup");
62
+ element.prepend(group);
114
63
  }
115
- targets.forEach((target) => {
116
- if (command.input.backgroundColor !== undefined) {
117
- target.style.backgroundColor = command.input.backgroundColor || "";
118
- }
119
- if (command.input.textColor !== undefined) {
120
- target.style.color = command.input.textColor || "";
121
- }
122
- });
123
- return table;
64
+ while (group.children.length < widths.length)
65
+ group.appendChild(element.ownerDocument.createElement("col"));
66
+ while (group.children.length > widths.length)
67
+ group.lastElementChild?.remove();
68
+ widths.forEach((width, index) => { group.children[index].style.width = `${width}px`; });
124
69
  }
125
- if (command.id === "table.cell.border.toggle") {
126
- const end = command.input.end || command.input.start;
127
- const top = Math.min(command.input.start.row, end.row);
128
- const bottom = Math.max(command.input.start.row, end.row);
129
- const left = Math.min(command.input.start.column, end.column);
130
- const right = Math.max(command.input.start.column, end.column);
131
- const grid = cellGrid(table);
132
- const targets = new Set();
133
- for (let row = top; row <= bottom; row += 1) {
134
- for (let column = left; column <= right; column += 1) {
135
- const target = grid[row]?.[column];
136
- if (target)
137
- targets.add(target);
138
- }
70
+ (table.children || []).forEach((row, rowIndex) => {
71
+ if (row.type !== "table_row")
72
+ return;
73
+ const height = Number(row.attrs?.height);
74
+ if (Number.isFinite(height) && height > 0)
75
+ element.rows[rowIndex].style.height = `${height}px`;
76
+ });
77
+ modelGrid.anchors.forEach((cell) => {
78
+ const target = grid[cell.top]?.[cell.left];
79
+ if (!target)
80
+ return;
81
+ target.style.background = cell.node.attrs?.background ? String(cell.node.attrs.background) : "";
82
+ target.style.color = cell.node.attrs?.textColor ? String(cell.node.attrs.textColor) : "";
83
+ target.style.border = cell.node.attrs?.borders ? String(cell.node.attrs.borders) : "";
84
+ target.style.verticalAlign = cell.node.attrs?.verticalAlign ? String(cell.node.attrs.verticalAlign) : "";
85
+ if (widths.length) {
86
+ const width = widths.slice(cell.left, cell.right).reduce((sum, value) => sum + value, 0);
87
+ target.style.width = `${width}px`;
88
+ target.style.minWidth = `${width}px`;
89
+ target.style.maxWidth = `${width}px`;
139
90
  }
140
- targets.forEach((target) => {
141
- target.style.border = target.style.border && target.style.border !== "none"
142
- ? "none"
143
- : command.input.visibleBorder || "1px solid #d1d5db";
144
- });
145
- return table;
146
- }
91
+ const rowHeight = Number(table.children?.[cell.top]?.attrs?.height);
92
+ if (Number.isFinite(rowHeight) && rowHeight > 0)
93
+ target.style.height = `${rowHeight}px`;
94
+ });
95
+ return element;
96
+ };
97
+ const replaceDomTable = (table, document) => {
147
98
  const container = table.ownerDocument.createElement("div");
148
- container.innerHTML = serializeSmartDocument(editor.state.document);
99
+ container.innerHTML = serializeCanonicalTableHtml(document, { fragment: true });
149
100
  const replacement = container.querySelector("table");
150
101
  if (!(replacement instanceof HTMLTableElement))
151
102
  return null;
152
103
  copyVisualAttributes(table, replacement);
153
- const previousGrid = cellGrid(table);
154
- const nextGrid = cellGrid(replacement);
155
- const previousPosition = (row, column) => {
156
- if (command.id === "table.row.add") {
157
- if (row === command.input.index)
158
- return null;
159
- return { row: row > command.input.index ? row - 1 : row, column };
160
- }
161
- if (command.id === "table.row.remove") {
162
- return { row: row >= command.input.index ? row + 1 : row, column };
163
- }
164
- if (command.id === "table.column.add") {
165
- if (column === command.input.index)
166
- return null;
167
- return { row, column: column > command.input.index ? column - 1 : column };
168
- }
169
- if (command.id === "table.column.remove") {
170
- return { row, column: column >= command.input.index ? column + 1 : column };
171
- }
172
- return { row, column };
173
- };
104
+ const beforeGrid = domGrid(table);
105
+ const afterGrid = domGrid(replacement);
174
106
  const copied = new Set();
175
- nextGrid.forEach((row, rowIndex) => row.forEach((nextCell, column) => {
176
- if (!nextCell || copied.has(nextCell))
107
+ afterGrid.forEach((row, rowIndex) => row.forEach((cell, column) => {
108
+ if (!cell || copied.has(cell))
177
109
  return;
178
- const position = previousPosition(rowIndex, column);
179
- const previousCell = position ? previousGrid[position.row]?.[position.column] : undefined;
180
- if (previousCell) {
181
- copyVisualAttributes(previousCell, nextCell);
182
- reconcileHeaderStyle(previousCell, nextCell);
110
+ const source = beforeGrid[rowIndex]?.[column];
111
+ if (source)
112
+ copyVisualAttributes(source, cell);
113
+ if (cell.tagName === "TH" && source?.tagName !== "TH") {
114
+ cell.style.fontWeight = "700";
115
+ cell.style.background = cell.style.background || "#f3f4f6";
116
+ cell.style.textAlign = cell.style.textAlign || "left";
117
+ }
118
+ else if (cell.tagName === "TD" && source?.tagName === "TH") {
119
+ if (["700", "bold"].includes(cell.style.fontWeight))
120
+ cell.style.fontWeight = "";
121
+ if (["rgb(243, 244, 246)", "#f3f4f6"].includes(cell.style.background))
122
+ cell.style.background = "";
123
+ if (cell.style.textAlign === "left")
124
+ cell.style.textAlign = "";
183
125
  }
184
- copied.add(nextCell);
126
+ copied.add(cell);
185
127
  }));
186
128
  table.replaceWith(replacement);
187
129
  return replacement;
188
130
  };
189
- export const executeDomTableRemoval = (table) => {
190
- const document = smartDocumentFromHtml(table.outerHTML, table.ownerDocument);
191
- if (document.children.length !== 1 || document.children[0].type !== "table")
131
+ export const executeDomTableCommand = (element, command) => {
132
+ if (command.id === "table.remove")
133
+ return null;
134
+ const parsed = canonicalTable(element);
135
+ if (!parsed)
136
+ return null;
137
+ const { document, table } = parsed;
138
+ const grid = occupancyGridFor(table);
139
+ const start = "start" in command.input ? command.input.start : "row" in command.input ? command.input : { row: "index" in command.input ? command.input.index : 0, column: 0 };
140
+ const end = "end" in command.input && command.input.end ? command.input.end : start;
141
+ const scope = tableScope(table, start, end);
142
+ const ctx = commandContext(document);
143
+ let operations = [];
144
+ if (command.id === "table.row.add")
145
+ operations = insertTableRowCommand(document, scope, {
146
+ rowIndex: command.input.index, rowId: `row-${createNodeId()}`,
147
+ cellIds: generated(grid.columns, "cell"), paragraphIds: generated(grid.columns, "paragraph"),
148
+ }, ctx);
149
+ else if (command.id === "table.row.remove")
150
+ operations = removeTableRowCommand(document, scope, { rowIndex: command.input.index }, ctx);
151
+ else if (command.id === "table.column.add")
152
+ operations = insertTableColumnCommand(document, scope, {
153
+ columnIndex: command.input.index, cellIds: generated(grid.rows, "cell"), paragraphIds: generated(grid.rows, "paragraph"),
154
+ }, ctx);
155
+ else if (command.id === "table.column.remove")
156
+ operations = removeTableColumnCommand(document, scope, { columnIndex: command.input.index }, ctx);
157
+ else if (command.id === "table.cell.merge")
158
+ operations = mergeTableCellsCommand(document, scope, {}, ctx);
159
+ else if (command.id === "table.cell.split") {
160
+ const target = grid.at(command.input.row, command.input.column);
161
+ const count = target ? (target.bottom - target.top) * (target.right - target.left) - 1 : 0;
162
+ operations = splitTableCellCommand(document, scope, { cellIds: generated(count, "cell"), paragraphIds: generated(count, "paragraph") }, ctx);
163
+ }
164
+ else if (command.id.startsWith("table.header.")) {
165
+ const point = command.input;
166
+ const targetCells = command.id === "table.header.cell.toggle" ? [grid.at(point.row, point.column)].filter(Boolean)
167
+ : command.id === "table.header.row.toggle" ? grid.anchors.filter((cell) => cell.top <= point.row && cell.bottom > point.row)
168
+ : grid.anchors.filter((cell) => cell.left <= point.column && cell.right > point.column);
169
+ const makeHeader = targetCells.some((cell) => cell?.node.attrs?.header !== true);
170
+ if (command.id === "table.header.cell.toggle" && point.row > 0 && point.column > 0)
171
+ return null;
172
+ const headerScope = { ...scope, cellIds: targetCells.map((cell) => cell.cellId) };
173
+ operations = command.id === "table.header.cell.toggle"
174
+ ? setTableCellAttributesCommand(document, headerScope, { attrs: { header: makeHeader } }, ctx)
175
+ : setTableHeaderCommand(document, scope, { target: makeHeader ? command.id === "table.header.row.toggle" ? "row" : "column" : "none" }, ctx);
176
+ }
177
+ else if (command.id === "table.cell.style.set")
178
+ operations = setTableCellAttributesCommand(document, scope, { attrs: {
179
+ ...(command.input.backgroundColor !== undefined ? { background: command.input.backgroundColor || undefined } : {}),
180
+ ...(command.input.textColor !== undefined ? { textColor: command.input.textColor || undefined } : {}),
181
+ } }, ctx);
182
+ else if (command.id === "table.cell.border.toggle") {
183
+ const visible = scope.cellIds.some((id) => grid.anchors.find((cell) => cell.cellId === id)?.node.attrs?.borders && grid.anchors.find((cell) => cell.cellId === id)?.node.attrs?.borders !== "none");
184
+ operations = setTableCellAttributesCommand(document, scope, { attrs: { borders: visible ? "none" : command.input.visibleBorder || "1px solid #d1d5db" } }, ctx);
185
+ }
186
+ else if (command.id === "table.column.width.set")
187
+ operations = setTableColumnWidthCommand(document, scope, { index: command.input.index, width: command.input.widthPx }, ctx);
188
+ else if (command.id === "table.row.height.set")
189
+ operations = setTableRowHeightCommand(document, scope, { index: command.input.index, height: command.input.heightPx }, ctx);
190
+ if (!operations.length)
191
+ return null;
192
+ const after = applyOperations(document, operations);
193
+ if (["table.cell.style.set", "table.cell.border.toggle", "table.column.width.set", "table.row.height.set"].includes(command.id)) {
194
+ return projectAttributesInPlace(element, after);
195
+ }
196
+ return replaceDomTable(element, after);
197
+ };
198
+ export const executeDomTableRemoval = (element) => {
199
+ const parsed = canonicalTable(element);
200
+ if (!parsed)
192
201
  return false;
193
- const editor = createSmartEditor({
194
- state: { document, selection: { type: "node", path: [0] } },
195
- plugins: [tablePlugin],
196
- });
197
- if (!editor.execute("table.remove", { tablePath: [0] }))
202
+ const scope = tableScope(parsed.table, { row: 0, column: 0 });
203
+ if (!removeTableCommand(parsed.document, scope, {}, commandContext(parsed.document)).length)
198
204
  return false;
199
- table.remove();
205
+ element.remove();
200
206
  return true;
201
207
  };
208
+ export const executeDomTableInsert = (root, afterBlockIndex, rows, columns, withHeader = false) => {
209
+ if (rows < 1 || columns < 1)
210
+ return null;
211
+ const document = repair(parseCanonicalTableHtml(root.innerHTML)).doc;
212
+ const index = Math.max(0, Math.min(afterBlockIndex, document.children.length - 1));
213
+ const target = document.children[index];
214
+ if (!target || !("id" in target))
215
+ return null;
216
+ const blockScope = {
217
+ kind: "block-range", blockIds: [target.id], promotedFromPartial: false,
218
+ commonParentId: document.id, range: { from: { path: [], offset: index }, to: { path: [], offset: index + 1 } },
219
+ isolatingAncestorId: null, clamped: false,
220
+ };
221
+ const total = rows * columns;
222
+ const tableId = `table-${createNodeId()}`;
223
+ const operations = insertTableCommand(document, blockScope, {
224
+ rows, columns, withHeader, placement: "after",
225
+ ids: { tableId, rowIds: generated(rows, "row"), cellIds: generated(total, "cell"), paragraphIds: generated(total, "paragraph") },
226
+ }, commandContext(document));
227
+ if (!operations.length)
228
+ return null;
229
+ root.innerHTML = serializeCanonicalTableHtml(applyOperations(document, operations), { fragment: true });
230
+ return root.querySelector(`table[data-smart-id="${tableId}"]`);
231
+ };
@@ -1,13 +1,5 @@
1
- import type { CoreInlineMark } from "./inlineMarkCoreExecution.js";
2
1
  export interface SmartRteInternalFlags {
3
- coreBold?: boolean;
4
- coreItalic?: boolean;
5
- coreUnderline?: boolean;
6
- coreSuperscript?: boolean;
7
- coreSubscript?: boolean;
8
- coreInlineMarks?: boolean;
9
2
  shadowMode?: boolean;
10
3
  }
11
4
  export declare const getSmartRteInternalFlags: () => SmartRteInternalFlags;
12
- export declare const isCoreInlineMarkFlagEnabled: (mark: CoreInlineMark) => boolean;
13
5
  export declare const isShadowModeFlagEnabled: () => boolean;
@@ -1,30 +1,6 @@
1
- const markFlagNames = {
2
- bold: "coreBold",
3
- italic: "coreItalic",
4
- underline: "coreUnderline",
5
- superscript: "coreSuperscript",
6
- subscript: "coreSubscript",
7
- };
8
- const legacyMarkFlagNames = {
9
- bold: "__SMART_RTE_CORE_BOLD__",
10
- italic: "__SMART_RTE_CORE_ITALIC__",
11
- underline: "__SMART_RTE_CORE_UNDERLINE__",
12
- superscript: "__SMART_RTE_CORE_SUPERSCRIPT__",
13
- subscript: "__SMART_RTE_CORE_SUBSCRIPT__",
14
- };
15
1
  const getGlobal = () => globalThis;
16
2
  const readBoolean = (value) => typeof value === "boolean" ? value : undefined;
17
3
  export const getSmartRteInternalFlags = () => getGlobal().__SMART_RTE_INTERNAL_FLAGS__ || {};
18
- export const isCoreInlineMarkFlagEnabled = (mark) => {
19
- const flags = getSmartRteInternalFlags();
20
- const individual = readBoolean(flags[markFlagNames[mark]]);
21
- if (individual !== undefined)
22
- return individual;
23
- const grouped = readBoolean(flags.coreInlineMarks);
24
- if (grouped !== undefined)
25
- return grouped;
26
- return getGlobal()[legacyMarkFlagNames[mark]] === true;
27
- };
28
4
  export const isShadowModeFlagEnabled = () => {
29
5
  const configured = readBoolean(getSmartRteInternalFlags().shadowMode);
30
6
  if (configured !== undefined)
@@ -1,4 +1,4 @@
1
- import { shadowLogRecord } from "smartrte-core";
1
+ import { shadowLogRecord } from "smartrte-core/foundation";
2
2
  export interface NamedListIntentReplay {
3
3
  readonly intent: string;
4
4
  readonly equivalent: boolean;
@@ -1,4 +1,4 @@
1
- import { applyOperations, compareShadowDocuments, createTransactionMap, createList, createScopeIndex, foundationSchema, indentList, moveListItems, outdentList, setListChecked, setListPreset, setListStyle, shadowLogRecord, unwrapList, isTextNode, } from "smartrte-core";
1
+ import { applyOperations, compareShadowDocuments, createTransactionMap, createList, createScopeIndex, foundationSchema, indentList, moveListItems, outdentList, setListChecked, setListPreset, setListStyle, shadowLogRecord, unwrapList, isTextNode, } from "smartrte-core/foundation";
2
2
  import { applyTransaction as applyLegacyTransaction, indentListItems as legacyIndentListItems, moveBlocks as legacyMoveBlocks, outdentListItems as legacyOutdentListItems, setChecklistItemChecked as legacySetChecklistItemChecked, toggleList as legacyToggleList, } from "smartrte-core/legacy";
3
3
  const p = (id, text) => ({ type: "paragraph", id, children: [{ type: "text", text }] });
4
4
  const item = (id, text, nested) => ({ type: "list_item", id, children: [p(`${id}-p`, text), ...(nested ? [nested] : [])] });
@@ -0,0 +1,8 @@
1
+ import type { SmartDocument } from "smartrte-core/foundation";
2
+ /**
3
+ * The only genuinely browser-specific piece of PDF export: opening a print
4
+ * window is a windowing operation, not format logic, so it stays here
5
+ * rather than in packages/core. buildPdfPrintDocument (the actual HTML
6
+ * content) is framework-agnostic and lives in core.
7
+ */
8
+ export declare const printSmartDocumentAsPdf: (document: SmartDocument, hostWindow: Window, delayMs?: number) => boolean;
@@ -0,0 +1,22 @@
1
+ import { buildPdfPrintDocument } from "smartrte-core/foundation";
2
+ /**
3
+ * The only genuinely browser-specific piece of PDF export: opening a print
4
+ * window is a windowing operation, not format logic, so it stays here
5
+ * rather than in packages/core. buildPdfPrintDocument (the actual HTML
6
+ * content) is framework-agnostic and lives in core.
7
+ */
8
+ export const printSmartDocumentAsPdf = (document, hostWindow, delayMs = 150) => {
9
+ const printWindow = hostWindow.open("", "_blank", "width=900,height=700");
10
+ if (!printWindow)
11
+ return false;
12
+ printWindow.addEventListener("load", () => {
13
+ printWindow.setTimeout(() => {
14
+ printWindow.focus();
15
+ printWindow.print();
16
+ }, delayMs);
17
+ }, { once: true });
18
+ printWindow.document.open();
19
+ printWindow.document.write(buildPdfPrintDocument(document));
20
+ printWindow.document.close();
21
+ return true;
22
+ };
@@ -1,4 +1,4 @@
1
- import { type CommandContext, type SmartCommand, type SmartEditorState, type SmartTransaction } from "smartrte-core";
1
+ import { type LegacyCommandContext, type SmartCommand, type SmartEditorState, type LegacySmartTransaction } from "smartrte-core/legacy";
2
2
  export interface ShadowComparison {
3
3
  commandId: string;
4
4
  matches: boolean;
@@ -15,9 +15,9 @@ export declare const reportShadowDifference: (comparison: ShadowComparison) => v
15
15
  */
16
16
  export declare const runShadowCommand: <Input>(args: {
17
17
  command: SmartCommand<Input>;
18
- context: CommandContext;
18
+ context: LegacyCommandContext;
19
19
  input?: Input;
20
20
  state: SmartEditorState;
21
21
  legacyHtml: string;
22
22
  serialize: (state: SmartEditorState) => string;
23
- }) => SmartTransaction | null;
23
+ }) => LegacySmartTransaction | null;
@@ -1,4 +1,4 @@
1
- import { applyTransaction, normalizeCompatibilityHtml, } from "smartrte-core";
1
+ import { applyTransaction, normalizeCompatibilityHtml, } from "smartrte-core/legacy";
2
2
  import { isShadowModeFlagEnabled } from "./internalFlags.js";
3
3
  const semanticHtml = (html) => normalizeCompatibilityHtml(html)
4
4
  .replace(/<(\/?)b(?=[\s>])/g, "<$1strong")