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.
- package/CHANGELOG.md +14 -0
- package/README.md +106 -14
- package/dist/adapters/domChecklistCommandBridge.js +1 -1
- package/dist/adapters/domCommandBridge.d.ts +2 -2
- package/dist/adapters/domCommandBridge.js +2 -2
- package/dist/adapters/domInlineAtomCommandBridge.d.ts +10 -9
- package/dist/adapters/domInlineAtomCommandBridge.js +154 -50
- package/dist/adapters/domInlineImageCommandBridge.d.ts +7 -7
- package/dist/adapters/domInlineImageCommandBridge.js +6 -72
- package/dist/adapters/domMoveCommandBridge.js +1 -1
- package/dist/adapters/domSelectionBridge.d.ts +3 -3
- package/dist/adapters/domSmartDocument.d.ts +4 -4
- package/dist/adapters/domSmartDocument.js +2 -2
- package/dist/adapters/domTableCommandBridge.d.ts +42 -16
- package/dist/adapters/domTableCommandBridge.js +203 -173
- package/dist/adapters/internalFlags.d.ts +0 -8
- package/dist/adapters/internalFlags.js +0 -24
- package/dist/adapters/legacyListShadowComparator.d.ts +1 -1
- package/dist/adapters/legacyListShadowComparator.js +1 -1
- package/dist/adapters/pdfPrint.d.ts +8 -0
- package/dist/adapters/pdfPrint.js +22 -0
- package/dist/adapters/shadowMode.d.ts +3 -3
- package/dist/adapters/shadowMode.js +1 -1
- package/dist/canonicalEditorRuntime.d.ts +53 -1
- package/dist/canonicalEditorRuntime.js +61 -4
- package/dist/capabilityPresets.d.ts +27 -0
- package/dist/capabilityPresets.js +21 -0
- package/dist/collabTransport.d.ts +66 -0
- package/dist/collabTransport.js +1 -0
- package/dist/commentProvider.d.ts +24 -0
- package/dist/commentProvider.js +1 -0
- package/dist/components/CanonicalAuthorityEditor.d.ts +35 -1
- package/dist/components/CanonicalAuthorityEditor.js +1086 -112
- package/dist/components/ClassicEditorAuthority.d.ts +93 -22
- package/dist/components/ClassicEditorAuthority.js +11 -43
- package/dist/components/ColorPickerPopover.d.ts +39 -0
- package/dist/components/ColorPickerPopover.js +285 -0
- package/dist/components/CommentMarkers.d.ts +25 -0
- package/dist/components/CommentMarkers.js +105 -0
- package/dist/components/CommentThreadPanel.d.ts +26 -0
- package/dist/components/CommentThreadPanel.js +47 -0
- package/dist/components/ContextMenu.d.ts +23 -0
- package/dist/components/ContextMenu.js +141 -0
- package/dist/components/FormulaLibraryPopover.d.ts +16 -0
- package/dist/components/FormulaLibraryPopover.js +107 -0
- package/dist/components/LinkEditorPopover.d.ts +3 -1
- package/dist/components/LinkEditorPopover.js +22 -6
- package/dist/components/MediaManager.d.ts +4 -20
- package/dist/components/MediaManager.js +35 -6
- package/dist/components/MediaOverlay.d.ts +36 -0
- package/dist/components/MediaOverlay.js +163 -0
- package/dist/components/SpecialCharacterPopover.d.ts +18 -0
- package/dist/components/SpecialCharacterPopover.js +99 -0
- package/dist/components/StructuralSuggestionMarkers.d.ts +20 -0
- package/dist/components/StructuralSuggestionMarkers.js +56 -0
- package/dist/components/SuggestionPanel.d.ts +26 -0
- package/dist/components/SuggestionPanel.js +33 -0
- package/dist/components/TableBorderPopover.d.ts +59 -0
- package/dist/components/TableBorderPopover.js +147 -0
- package/dist/components/TableResizeHandles.d.ts +25 -0
- package/dist/components/TableResizeHandles.js +301 -0
- package/dist/components/TableSizePickerPopover.d.ts +16 -0
- package/dist/components/TableSizePickerPopover.js +126 -0
- package/dist/components/ToolbarPrimitives.d.ts +129 -0
- package/dist/components/ToolbarPrimitives.js +146 -0
- package/dist/components/VersionHistoryPanel.d.ts +9 -0
- package/dist/components/VersionHistoryPanel.js +157 -0
- package/dist/formulaLibrary.d.ts +31 -0
- package/dist/formulaLibrary.js +90 -0
- package/dist/index.d.ts +22 -24
- package/dist/index.js +14 -11
- package/dist/mediaManagerAdapter.d.ts +12 -0
- package/dist/mediaManagerAdapter.js +34 -0
- package/dist/mediaProvider.d.ts +21 -1
- package/dist/specialCharacters.d.ts +22 -0
- package/dist/specialCharacters.js +86 -0
- package/dist/standalone/classic-editor-embed.js +19 -12
- package/dist/suggestionProvider.d.ts +17 -0
- package/dist/suggestionProvider.js +1 -0
- package/dist/theme.d.ts +1 -1
- package/dist/theme.js +150 -20
- package/dist/versionProvider.d.ts +29 -0
- package/dist/versionProvider.js +1 -0
- package/package.json +28 -14
- package/dist/adapters/canonicalInlineCommandBridge.d.ts +0 -15
- package/dist/adapters/canonicalInlineCommandBridge.js +0 -269
- package/dist/adapters/canonicalListCommandBridge.d.ts +0 -26
- package/dist/adapters/canonicalListCommandBridge.js +0 -430
- package/dist/adapters/coreBold.d.ts +0 -5
- package/dist/adapters/coreBold.js +0 -3
- package/dist/adapters/documentFormats.d.ts +0 -26
- package/dist/adapters/documentFormats.js +0 -49
- package/dist/adapters/docxFormat.d.ts +0 -5
- package/dist/adapters/docxFormat.js +0 -272
- package/dist/adapters/domBlockCommandBridge.d.ts +0 -19
- package/dist/adapters/domBlockCommandBridge.js +0 -79
- package/dist/adapters/inlineMarkCoreExecution.d.ts +0 -9
- package/dist/adapters/inlineMarkCoreExecution.js +0 -25
- package/dist/adapters/pdfFormat.d.ts +0 -23
- package/dist/adapters/pdfFormat.js +0 -204
- package/dist/adapters/portableDocxAtoms.d.ts +0 -4
- package/dist/adapters/portableDocxAtoms.js +0 -58
- package/dist/adapters/styledDocxFormat.d.ts +0 -8
- package/dist/adapters/styledDocxFormat.js +0 -190
- package/dist/builtInFormatDefinitions.d.ts +0 -5
- package/dist/builtInFormatDefinitions.js +0 -82
- package/dist/canonicalAuthorityFlag.d.ts +0 -32
- package/dist/canonicalAuthorityFlag.js +0 -49
- package/dist/canonicalClipboardRuntime.d.ts +0 -15
- package/dist/canonicalClipboardRuntime.js +0 -76
- package/dist/components/ClassicEditor.d.ts +0 -76
- package/dist/components/ClassicEditor.js +0 -6729
- package/dist/editorController.d.ts +0 -78
- package/dist/editorController.js +0 -298
- package/dist/formatFidelity.d.ts +0 -14
- package/dist/formatFidelity.js +0 -107
- package/dist/formatRuntime.d.ts +0 -50
- package/dist/formatRuntime.js +0 -20
- package/dist/pluginRuntime.d.ts +0 -68
- package/dist/pluginRuntime.js +0 -78
- package/dist/standalone/editor.js +0 -1068
- package/dist/test-harness/atomShadowComparator.d.ts +0 -14
- package/dist/test-harness/atomShadowComparator.js +0 -63
- package/dist/test-harness/blockShadowComparator.d.ts +0 -30
- package/dist/test-harness/blockShadowComparator.js +0 -140
- package/dist/test-harness/clipboardShadowComparator.d.ts +0 -12
- package/dist/test-harness/clipboardShadowComparator.js +0 -46
- package/dist/test-harness/inlineShadowComparator.d.ts +0 -32
- package/dist/test-harness/inlineShadowComparator.js +0 -152
- package/dist/test-harness/legacyAtomEngine.d.ts +0 -10
- package/dist/test-harness/legacyAtomEngine.js +0 -15
- package/dist/test-harness/legacyBlockEngine.d.ts +0 -31
- package/dist/test-harness/legacyBlockEngine.js +0 -31
- package/dist/test-harness/legacyClipboardEngine.d.ts +0 -14
- package/dist/test-harness/legacyClipboardEngine.js +0 -67
- package/dist/test-harness/legacyInlineEngine.d.ts +0 -19
- package/dist/test-harness/legacyInlineEngine.js +0 -49
- package/dist/test-harness/legacyTableEngine.d.ts +0 -12
- package/dist/test-harness/legacyTableEngine.js +0 -25
- package/dist/test-harness/tableShadowComparator.d.ts +0 -29
- package/dist/test-harness/tableShadowComparator.js +0 -101
|
@@ -1,35 +1,61 @@
|
|
|
1
|
-
|
|
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:
|
|
10
|
+
input: {
|
|
11
|
+
index: number;
|
|
12
|
+
};
|
|
5
13
|
} | {
|
|
6
14
|
id: "table.column.add" | "table.column.remove";
|
|
7
|
-
input:
|
|
15
|
+
input: {
|
|
16
|
+
index: number;
|
|
17
|
+
};
|
|
8
18
|
} | {
|
|
9
19
|
id: "table.cell.merge";
|
|
10
|
-
input:
|
|
20
|
+
input: {
|
|
21
|
+
start: Point;
|
|
22
|
+
end: Point;
|
|
23
|
+
};
|
|
11
24
|
} | {
|
|
12
25
|
id: "table.cell.split";
|
|
13
|
-
input:
|
|
26
|
+
input: Point;
|
|
14
27
|
} | {
|
|
15
28
|
id: "table.header.cell.toggle" | "table.header.row.toggle" | "table.header.column.toggle";
|
|
16
|
-
input:
|
|
29
|
+
input: Point;
|
|
17
30
|
} | {
|
|
18
31
|
id: "table.cell.style.set";
|
|
19
|
-
input:
|
|
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:
|
|
40
|
+
input: {
|
|
41
|
+
index: number;
|
|
42
|
+
widthPx: number;
|
|
43
|
+
};
|
|
23
44
|
} | {
|
|
24
45
|
id: "table.row.height.set";
|
|
25
|
-
input:
|
|
46
|
+
input: {
|
|
47
|
+
index: number;
|
|
48
|
+
heightPx: number;
|
|
49
|
+
};
|
|
26
50
|
} | {
|
|
27
51
|
id: "table.cell.border.toggle";
|
|
28
|
-
input:
|
|
52
|
+
input: {
|
|
53
|
+
start: Point;
|
|
54
|
+
end?: Point;
|
|
55
|
+
visibleBorder?: string;
|
|
56
|
+
};
|
|
29
57
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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 {
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
while (grid[rowIndex][column])
|
|
29
|
+
Array.from(row.cells).forEach((cell) => {
|
|
30
|
+
while (slots[rowIndex][column])
|
|
13
31
|
column += 1;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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 +=
|
|
37
|
+
column += Math.max(1, cell.colSpan);
|
|
23
38
|
});
|
|
24
39
|
});
|
|
25
|
-
return
|
|
40
|
+
return slots;
|
|
26
41
|
};
|
|
27
42
|
const copyVisualAttributes = (from, to) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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 =
|
|
68
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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 =
|
|
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
|
|
154
|
-
const
|
|
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
|
-
|
|
176
|
-
if (!
|
|
107
|
+
afterGrid.forEach((row, rowIndex) => row.forEach((cell, column) => {
|
|
108
|
+
if (!cell || copied.has(cell))
|
|
177
109
|
return;
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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(
|
|
126
|
+
copied.add(cell);
|
|
185
127
|
}));
|
|
186
128
|
table.replaceWith(replacement);
|
|
187
129
|
return replacement;
|
|
188
130
|
};
|
|
189
|
-
export const
|
|
190
|
-
|
|
191
|
-
|
|
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
|
|
194
|
-
|
|
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
|
-
|
|
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 { 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
|
|
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:
|
|
18
|
+
context: LegacyCommandContext;
|
|
19
19
|
input?: Input;
|
|
20
20
|
state: SmartEditorState;
|
|
21
21
|
legacyHtml: string;
|
|
22
22
|
serialize: (state: SmartEditorState) => string;
|
|
23
|
-
}) =>
|
|
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")
|