smartrte-core 0.2.0 → 1.0.0-beta.1

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 (329) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +23 -0
  3. package/dist/command.d.ts +8 -8
  4. package/dist/editor.d.ts +32 -0
  5. package/dist/editor.js +121 -0
  6. package/dist/foundation/annotations/index.d.ts +2 -0
  7. package/dist/foundation/annotations/index.js +2 -0
  8. package/dist/foundation/annotations/range.d.ts +54 -0
  9. package/dist/foundation/annotations/range.js +158 -0
  10. package/dist/foundation/annotations/types.d.ts +33 -0
  11. package/dist/foundation/annotations/types.js +1 -0
  12. package/dist/foundation/atom/commands.d.ts +11 -0
  13. package/dist/foundation/atom/commands.js +118 -0
  14. package/dist/foundation/atom/composition.d.ts +8 -0
  15. package/dist/foundation/atom/composition.js +22 -0
  16. package/dist/foundation/atom/declarations.d.ts +2 -0
  17. package/dist/foundation/atom/declarations.js +17 -0
  18. package/dist/foundation/atom/formats.d.ts +21 -0
  19. package/dist/foundation/atom/formats.js +77 -0
  20. package/dist/foundation/atom/index.d.ts +10 -0
  21. package/dist/foundation/atom/index.js +10 -0
  22. package/dist/foundation/atom/lifecycle.d.ts +12 -0
  23. package/dist/foundation/atom/lifecycle.js +41 -0
  24. package/dist/foundation/atom/persistence.d.ts +3 -0
  25. package/dist/foundation/atom/persistence.js +20 -0
  26. package/dist/foundation/atom/plugin.d.ts +20 -0
  27. package/dist/foundation/atom/plugin.js +55 -0
  28. package/dist/foundation/atom/schema.d.ts +3 -0
  29. package/dist/foundation/atom/schema.js +29 -0
  30. package/dist/foundation/atom/security.d.ts +10 -0
  31. package/dist/foundation/atom/security.js +20 -0
  32. package/dist/foundation/atom/selection.d.ts +3 -0
  33. package/dist/foundation/atom/selection.js +4 -0
  34. package/dist/foundation/atom/types.d.ts +47 -0
  35. package/dist/foundation/atom/types.js +1 -0
  36. package/dist/foundation/block/commands.d.ts +17 -0
  37. package/dist/foundation/block/commands.js +197 -0
  38. package/dist/foundation/block/formats.d.ts +33 -0
  39. package/dist/foundation/block/formats.js +57 -0
  40. package/dist/foundation/block/index.d.ts +5 -0
  41. package/dist/foundation/block/index.js +5 -0
  42. package/dist/foundation/block/input.d.ts +19 -0
  43. package/dist/foundation/block/input.js +67 -0
  44. package/dist/foundation/block/plugin.d.ts +26 -0
  45. package/dist/foundation/block/plugin.js +79 -0
  46. package/dist/foundation/block/schema.d.ts +49 -0
  47. package/dist/foundation/block/schema.js +27 -0
  48. package/dist/foundation/block/types.d.ts +40 -0
  49. package/dist/foundation/block/types.js +1 -0
  50. package/dist/foundation/boundaries.d.ts +11 -0
  51. package/dist/foundation/boundaries.js +117 -0
  52. package/dist/foundation/clipboard/detection.d.ts +3 -0
  53. package/dist/foundation/clipboard/detection.js +29 -0
  54. package/dist/foundation/clipboard/diagnostics.d.ts +24 -0
  55. package/dist/foundation/clipboard/diagnostics.js +59 -0
  56. package/dist/foundation/clipboard/index.d.ts +8 -0
  57. package/dist/foundation/clipboard/index.js +8 -0
  58. package/dist/foundation/clipboard/insertion.d.ts +22 -0
  59. package/dist/foundation/clipboard/insertion.js +210 -0
  60. package/dist/foundation/clipboard/normalizers.d.ts +8 -0
  61. package/dist/foundation/clipboard/normalizers.js +229 -0
  62. package/dist/foundation/clipboard/pipeline.d.ts +13 -0
  63. package/dist/foundation/clipboard/pipeline.js +58 -0
  64. package/dist/foundation/clipboard/sanitizer.d.ts +3 -0
  65. package/dist/foundation/clipboard/sanitizer.js +58 -0
  66. package/dist/foundation/clipboard/serialization.d.ts +5 -0
  67. package/dist/foundation/clipboard/serialization.js +33 -0
  68. package/dist/foundation/clipboard/transfer.d.ts +11 -0
  69. package/dist/foundation/clipboard/transfer.js +108 -0
  70. package/dist/foundation/clipboard/types.d.ts +65 -0
  71. package/dist/foundation/clipboard/types.js +1 -0
  72. package/dist/foundation/collab/index.d.ts +3 -0
  73. package/dist/foundation/collab/index.js +3 -0
  74. package/dist/foundation/collab/rebase.d.ts +28 -0
  75. package/dist/foundation/collab/rebase.js +82 -0
  76. package/dist/foundation/collab/transform.d.ts +73 -0
  77. package/dist/foundation/collab/transform.js +251 -0
  78. package/dist/foundation/collab/types.d.ts +52 -0
  79. package/dist/foundation/collab/types.js +1 -0
  80. package/dist/foundation/comments/fromSelection.d.ts +16 -0
  81. package/dist/foundation/comments/fromSelection.js +24 -0
  82. package/dist/foundation/comments/index.d.ts +3 -0
  83. package/dist/foundation/comments/index.js +3 -0
  84. package/dist/foundation/comments/rebase.d.ts +31 -0
  85. package/dist/foundation/comments/rebase.js +43 -0
  86. package/dist/foundation/comments/types.d.ts +37 -0
  87. package/dist/foundation/comments/types.js +1 -0
  88. package/dist/foundation/diff/documentDiff.d.ts +12 -0
  89. package/dist/foundation/diff/documentDiff.js +148 -0
  90. package/dist/foundation/diff/index.d.ts +3 -0
  91. package/dist/foundation/diff/index.js +3 -0
  92. package/dist/foundation/diff/textDiff.d.ts +12 -0
  93. package/dist/foundation/diff/textDiff.js +114 -0
  94. package/dist/foundation/diff/types.d.ts +74 -0
  95. package/dist/foundation/diff/types.js +1 -0
  96. package/dist/foundation/editor.d.ts +138 -0
  97. package/dist/foundation/editor.js +398 -0
  98. package/dist/foundation/formats/codec.d.ts +45 -0
  99. package/dist/foundation/formats/codec.js +1 -0
  100. package/dist/foundation/formats/docx/export.d.ts +4 -0
  101. package/dist/foundation/formats/docx/export.js +285 -0
  102. package/dist/foundation/formats/docx/import.d.ts +9 -0
  103. package/dist/foundation/formats/docx/import.js +37 -0
  104. package/dist/foundation/formats/docx/nestingGuard.d.ts +40 -0
  105. package/dist/foundation/formats/docx/nestingGuard.js +66 -0
  106. package/dist/foundation/formats/docx/portableAtoms.d.ts +4 -0
  107. package/dist/foundation/formats/docx/portableAtoms.js +66 -0
  108. package/dist/foundation/formats/docx/styledImport.d.ts +10 -0
  109. package/dist/foundation/formats/docx/styledImport.js +205 -0
  110. package/dist/foundation/formats/featureCodecs.d.ts +37 -0
  111. package/dist/foundation/formats/featureCodecs.js +69 -0
  112. package/dist/foundation/formats/fidelity.d.ts +31 -0
  113. package/dist/foundation/formats/fidelity.js +123 -0
  114. package/dist/foundation/formats/index.d.ts +7 -0
  115. package/dist/foundation/formats/index.js +7 -0
  116. package/dist/foundation/formats/pdf/format.d.ts +29 -0
  117. package/dist/foundation/formats/pdf/format.js +190 -0
  118. package/dist/foundation/history.d.ts +20 -0
  119. package/dist/foundation/history.js +121 -0
  120. package/dist/foundation/identity.d.ts +8 -0
  121. package/dist/foundation/identity.js +30 -0
  122. package/dist/foundation/index.d.ts +30 -0
  123. package/dist/foundation/index.js +30 -0
  124. package/dist/foundation/list/commands.d.ts +28 -0
  125. package/dist/foundation/list/commands.js +422 -0
  126. package/dist/foundation/list/formats.d.ts +20 -0
  127. package/dist/foundation/list/formats.js +795 -0
  128. package/dist/foundation/list/index.d.ts +8 -0
  129. package/dist/foundation/list/index.js +8 -0
  130. package/dist/foundation/list/input.d.ts +35 -0
  131. package/dist/foundation/list/input.js +320 -0
  132. package/dist/foundation/list/plugin.d.ts +21 -0
  133. package/dist/foundation/list/plugin.js +71 -0
  134. package/dist/foundation/list/presets.d.ts +16 -0
  135. package/dist/foundation/list/presets.js +21 -0
  136. package/dist/foundation/list/schema.d.ts +35 -0
  137. package/dist/foundation/list/schema.js +29 -0
  138. package/dist/foundation/list/shadow.d.ts +54 -0
  139. package/dist/foundation/list/shadow.js +75 -0
  140. package/dist/foundation/list/shadowCorpus.d.ts +10 -0
  141. package/dist/foundation/list/shadowCorpus.js +41 -0
  142. package/dist/foundation/list/types.d.ts +50 -0
  143. package/dist/foundation/list/types.js +1 -0
  144. package/dist/foundation/mapping.d.ts +11 -0
  145. package/dist/foundation/mapping.js +40 -0
  146. package/dist/foundation/marks/canonical.d.ts +9 -0
  147. package/dist/foundation/marks/canonical.js +72 -0
  148. package/dist/foundation/marks/commands.d.ts +21 -0
  149. package/dist/foundation/marks/commands.js +136 -0
  150. package/dist/foundation/marks/dom.d.ts +2 -0
  151. package/dist/foundation/marks/dom.js +46 -0
  152. package/dist/foundation/marks/editor.d.ts +8 -0
  153. package/dist/foundation/marks/editor.js +50 -0
  154. package/dist/foundation/marks/formats.d.ts +37 -0
  155. package/dist/foundation/marks/formats.js +49 -0
  156. package/dist/foundation/marks/hardBreak.d.ts +8 -0
  157. package/dist/foundation/marks/hardBreak.js +80 -0
  158. package/dist/foundation/marks/index.d.ts +11 -0
  159. package/dist/foundation/marks/index.js +11 -0
  160. package/dist/foundation/marks/normalization.d.ts +2 -0
  161. package/dist/foundation/marks/normalization.js +49 -0
  162. package/dist/foundation/marks/plugin.d.ts +14 -0
  163. package/dist/foundation/marks/plugin.js +63 -0
  164. package/dist/foundation/marks/resolveMarkRun.d.ts +8 -0
  165. package/dist/foundation/marks/resolveMarkRun.js +47 -0
  166. package/dist/foundation/marks/schema.d.ts +167 -0
  167. package/dist/foundation/marks/schema.js +50 -0
  168. package/dist/foundation/marks/stored.d.ts +2 -0
  169. package/dist/foundation/marks/stored.js +31 -0
  170. package/dist/foundation/marks/types.d.ts +40 -0
  171. package/dist/foundation/marks/types.js +1 -0
  172. package/dist/foundation/modelDom.d.ts +38 -0
  173. package/dist/foundation/modelDom.js +327 -0
  174. package/dist/foundation/normalization.d.ts +22 -0
  175. package/dist/foundation/normalization.js +132 -0
  176. package/dist/foundation/operations.d.ts +28 -0
  177. package/dist/foundation/operations.js +568 -0
  178. package/dist/foundation/plugin/builtins.d.ts +10 -0
  179. package/dist/foundation/plugin/builtins.js +27 -0
  180. package/dist/foundation/plugin/dispatch.d.ts +33 -0
  181. package/dist/foundation/plugin/dispatch.js +34 -0
  182. package/dist/foundation/plugin/index.d.ts +4 -0
  183. package/dist/foundation/plugin/index.js +4 -0
  184. package/dist/foundation/plugin/registry.d.ts +36 -0
  185. package/dist/foundation/plugin/registry.js +115 -0
  186. package/dist/foundation/plugin/types.d.ts +141 -0
  187. package/dist/foundation/plugin/types.js +13 -0
  188. package/dist/foundation/positions.d.ts +20 -0
  189. package/dist/foundation/positions.js +121 -0
  190. package/dist/foundation/schema.d.ts +57 -0
  191. package/dist/foundation/schema.js +371 -0
  192. package/dist/foundation/schemaBuilder.d.ts +41 -0
  193. package/dist/foundation/schemaBuilder.js +96 -0
  194. package/dist/foundation/scope/index.d.ts +2 -0
  195. package/dist/foundation/scope/index.js +2 -0
  196. package/dist/foundation/scope/resolveScope.d.ts +13 -0
  197. package/dist/foundation/scope/resolveScope.js +860 -0
  198. package/dist/foundation/scope/types.d.ts +122 -0
  199. package/dist/foundation/scope/types.js +1 -0
  200. package/dist/foundation/security/urlPolicy.d.ts +21 -0
  201. package/dist/foundation/security/urlPolicy.js +75 -0
  202. package/dist/foundation/structural/contentTarget.d.ts +21 -0
  203. package/dist/foundation/structural/contentTarget.js +51 -0
  204. package/dist/foundation/structural/index.d.ts +2 -0
  205. package/dist/foundation/structural/index.js +2 -0
  206. package/dist/foundation/structural/move.d.ts +7 -0
  207. package/dist/foundation/structural/move.js +35 -0
  208. package/dist/foundation/suggestions/index.d.ts +3 -0
  209. package/dist/foundation/suggestions/index.js +3 -0
  210. package/dist/foundation/suggestions/inline.d.ts +64 -0
  211. package/dist/foundation/suggestions/inline.js +116 -0
  212. package/dist/foundation/suggestions/structural.d.ts +40 -0
  213. package/dist/foundation/suggestions/structural.js +47 -0
  214. package/dist/foundation/suggestions/types.d.ts +19 -0
  215. package/dist/foundation/suggestions/types.js +1 -0
  216. package/dist/foundation/surface/index.d.ts +3 -0
  217. package/dist/foundation/surface/index.js +3 -0
  218. package/dist/foundation/surface/input.d.ts +127 -0
  219. package/dist/foundation/surface/input.js +1761 -0
  220. package/dist/foundation/surface/renderer.d.ts +84 -0
  221. package/dist/foundation/surface/renderer.js +974 -0
  222. package/dist/foundation/surface/types.d.ts +48 -0
  223. package/dist/foundation/surface/types.js +1 -0
  224. package/dist/foundation/table/commands.d.ts +31 -0
  225. package/dist/foundation/table/commands.js +470 -0
  226. package/dist/foundation/table/formats.d.ts +26 -0
  227. package/dist/foundation/table/formats.js +40 -0
  228. package/dist/foundation/table/grid.d.ts +8 -0
  229. package/dist/foundation/table/grid.js +178 -0
  230. package/dist/foundation/table/index.d.ts +6 -0
  231. package/dist/foundation/table/index.js +6 -0
  232. package/dist/foundation/table/plugin.d.ts +23 -0
  233. package/dist/foundation/table/plugin.js +119 -0
  234. package/dist/foundation/table/schema.d.ts +2 -0
  235. package/dist/foundation/table/schema.js +38 -0
  236. package/dist/foundation/table/selection.d.ts +7 -0
  237. package/dist/foundation/table/selection.js +35 -0
  238. package/dist/foundation/table/types.d.ts +109 -0
  239. package/dist/foundation/table/types.js +1 -0
  240. package/dist/foundation/transactions.d.ts +41 -0
  241. package/dist/foundation/transactions.js +90 -0
  242. package/dist/foundation/types.d.ts +261 -0
  243. package/dist/foundation/types.js +1 -0
  244. package/dist/foundation/versioning/diffVersions.d.ts +5 -0
  245. package/dist/foundation/versioning/diffVersions.js +3 -0
  246. package/dist/foundation/versioning/index.d.ts +2 -0
  247. package/dist/foundation/versioning/index.js +2 -0
  248. package/dist/foundation/versioning/types.d.ts +17 -0
  249. package/dist/foundation/versioning/types.js +1 -0
  250. package/dist/history.d.ts +20 -0
  251. package/dist/history.js +165 -0
  252. package/dist/html/compatibility.js +7 -1
  253. package/dist/index.d.ts +1 -14
  254. package/dist/index.js +9 -14
  255. package/dist/legacy/index.d.ts +45 -0
  256. package/dist/legacy/index.js +45 -0
  257. package/dist/legacyCommands/alignment.d.ts +20 -0
  258. package/dist/{commands → legacyCommands}/alignment.js +17 -0
  259. package/dist/legacyCommands/blocks.d.ts +14 -0
  260. package/dist/legacyCommands/blocks.js +105 -0
  261. package/dist/legacyCommands/checklist.d.ts +11 -0
  262. package/dist/legacyCommands/checklist.js +45 -0
  263. package/dist/legacyCommands/code.d.ts +15 -0
  264. package/dist/{commands → legacyCommands}/code.js +25 -1
  265. package/dist/legacyCommands/formula.d.ts +7 -0
  266. package/dist/legacyCommands/formula.js +67 -0
  267. package/dist/legacyCommands/inlineAtoms.d.ts +7 -0
  268. package/dist/legacyCommands/inlineAtoms.js +58 -0
  269. package/dist/legacyCommands/list.d.ts +38 -0
  270. package/dist/legacyCommands/list.js +477 -0
  271. package/dist/{commands → legacyCommands}/marks.d.ts +3 -0
  272. package/dist/{commands → legacyCommands}/marks.js +45 -11
  273. package/dist/legacyCommands/media.d.ts +31 -0
  274. package/dist/legacyCommands/media.js +205 -0
  275. package/dist/legacyCommands/move.d.ts +14 -0
  276. package/dist/legacyCommands/move.js +91 -0
  277. package/dist/legacyCommands/table.d.ts +91 -0
  278. package/dist/legacyCommands/table.js +547 -0
  279. package/dist/listPresets.d.ts +12 -0
  280. package/dist/listPresets.js +6 -0
  281. package/dist/listScope.d.ts +27 -0
  282. package/dist/listScope.js +104 -0
  283. package/dist/markdown/compatibility.d.ts +2 -0
  284. package/dist/markdown/compatibility.js +94 -2
  285. package/dist/marks.d.ts +5 -5
  286. package/dist/model.d.ts +65 -9
  287. package/dist/plugin.d.ts +15 -0
  288. package/dist/plugin.js +31 -0
  289. package/dist/plugins/alignment.d.ts +3 -0
  290. package/dist/plugins/alignment.js +6 -0
  291. package/dist/plugins/basicFormatting.d.ts +9 -0
  292. package/dist/plugins/basicFormatting.js +24 -0
  293. package/dist/plugins/blockType.d.ts +3 -0
  294. package/dist/plugins/blockType.js +6 -0
  295. package/dist/plugins/blockquote.d.ts +3 -0
  296. package/dist/plugins/blockquote.js +6 -0
  297. package/dist/plugins/checklist.d.ts +3 -0
  298. package/dist/plugins/checklist.js +10 -0
  299. package/dist/plugins/codeBlock.d.ts +3 -0
  300. package/dist/plugins/codeBlock.js +6 -0
  301. package/dist/plugins/formula.d.ts +3 -0
  302. package/dist/plugins/formula.js +9 -0
  303. package/dist/plugins/list.d.ts +3 -0
  304. package/dist/plugins/list.js +10 -0
  305. package/dist/plugins/media.d.ts +3 -0
  306. package/dist/plugins/media.js +12 -0
  307. package/dist/plugins/move.d.ts +3 -0
  308. package/dist/plugins/move.js +9 -0
  309. package/dist/plugins/table.d.ts +3 -0
  310. package/dist/plugins/table.js +22 -0
  311. package/dist/preset.d.ts +12 -0
  312. package/dist/preset.js +40 -0
  313. package/dist/schema.d.ts +22 -0
  314. package/dist/schema.js +333 -0
  315. package/dist/security/urlPolicy.d.ts +1 -17
  316. package/dist/security/urlPolicy.js +3 -69
  317. package/dist/selection.d.ts +1 -1
  318. package/dist/selectionMapping.d.ts +4 -0
  319. package/dist/selectionMapping.js +222 -0
  320. package/dist/table.d.ts +3 -3
  321. package/dist/transaction.d.ts +35 -12
  322. package/dist/transaction.js +174 -28
  323. package/dist/tree.d.ts +8 -2
  324. package/dist/tree.js +44 -0
  325. package/package.json +27 -8
  326. package/dist/commands/alignment.d.ts +0 -18
  327. package/dist/commands/code.d.ts +0 -13
  328. package/dist/commands/list.d.ts +0 -20
  329. package/dist/commands/list.js +0 -52
@@ -0,0 +1,547 @@
1
+ import { getNodeAtPath, paragraph, } from "../model.js";
2
+ import { isSmartContainer } from "../tree.js";
3
+ const cell = (header = false) => ({
4
+ type: header ? "tableHeaderCell" : "tableCell",
5
+ children: [paragraph()],
6
+ });
7
+ const tableAt = (document, path) => {
8
+ const node = getNodeAtPath(document, path);
9
+ return node?.type === "table" ? node : null;
10
+ };
11
+ const buildTableGrid = (table) => {
12
+ var _a;
13
+ const placements = [];
14
+ const slots = [];
15
+ let width = 0;
16
+ for (let rowIndex = 0; rowIndex < table.children.length; rowIndex += 1) {
17
+ const row = table.children[rowIndex];
18
+ slots[rowIndex] || (slots[rowIndex] = []);
19
+ let column = 0;
20
+ for (let cellIndex = 0; cellIndex < row.children.length; cellIndex += 1) {
21
+ while (slots[rowIndex][column])
22
+ column += 1;
23
+ const current = row.children[cellIndex];
24
+ const rowspan = current.rowspan || 1;
25
+ const colspan = current.colspan || 1;
26
+ if (rowIndex + rowspan > table.children.length)
27
+ return null;
28
+ const placement = { rowIndex, cellIndex, row: rowIndex, column, rowspan, colspan, cell: current };
29
+ for (let rowOffset = 0; rowOffset < rowspan; rowOffset += 1) {
30
+ slots[_a = rowIndex + rowOffset] || (slots[_a] = []);
31
+ for (let columnOffset = 0; columnOffset < colspan; columnOffset += 1) {
32
+ const slotRow = rowIndex + rowOffset;
33
+ const slotColumn = column + columnOffset;
34
+ if (slots[slotRow][slotColumn])
35
+ return null;
36
+ slots[slotRow][slotColumn] = placement;
37
+ }
38
+ }
39
+ placements.push(placement);
40
+ column += colspan;
41
+ }
42
+ width = Math.max(width, slots[rowIndex].length);
43
+ }
44
+ if (!width || slots.some((row) => row.length !== width || row.some((slot) => !slot)))
45
+ return null;
46
+ return { placements, slots, width };
47
+ };
48
+ const withSpan = (source, rowspan, colspan) => {
49
+ const { rowspan: _rowspan, colspan: _colspan, ...rest } = source;
50
+ return {
51
+ ...rest,
52
+ ...(rowspan > 1 ? { rowspan } : {}),
53
+ ...(colspan > 1 ? { colspan } : {}),
54
+ };
55
+ };
56
+ const tableFromPlacements = (source, rowCount, placements) => ({
57
+ ...source,
58
+ children: Array.from({ length: rowCount }, (_, row) => ({
59
+ type: "tableRow",
60
+ children: placements
61
+ .filter((placement) => placement.row === row)
62
+ .sort((left, right) => left.column - right.column)
63
+ .map((placement) => withSpan(placement.cell, placement.rowspan, placement.colspan)),
64
+ })),
65
+ });
66
+ const replaceTableTransaction = (context, id, tablePath, table) => ({
67
+ id,
68
+ source: "user",
69
+ operations: [{ type: "replaceNode", path: tablePath, node: table }],
70
+ selectionBefore: context.selection,
71
+ selectionAfter: { type: "node", path: tablePath },
72
+ addToHistory: true,
73
+ timestamp: context.now?.() ?? Date.now(),
74
+ });
75
+ export const insertTable = {
76
+ id: "table.insert",
77
+ isEnabled: (context, input) => {
78
+ if (!input || !Number.isInteger(input.rows) || !Number.isInteger(input.columns) ||
79
+ input.rows < 1 || input.columns < 1)
80
+ return false;
81
+ const parent = getNodeAtPath(context.document, input.path.slice(0, -1));
82
+ const index = input.path[input.path.length - 1];
83
+ const type = parent?.type;
84
+ return input.path.length > 0 && isSmartContainer(parent) &&
85
+ ["doc", "listItem", "blockquote", "tableCell", "tableHeaderCell"].includes(type || "") &&
86
+ index >= 0 && index <= parent.children.length;
87
+ },
88
+ execute: (context, input) => {
89
+ if (!input || !insertTable.isEnabled(context, input)) {
90
+ throw new Error("table.insert requires positive dimensions and a block insertion path.");
91
+ }
92
+ const node = {
93
+ type: "table",
94
+ children: Array.from({ length: input.rows }, (_, row) => ({
95
+ type: "tableRow",
96
+ children: Array.from({ length: input.columns }, () => cell(Boolean(input.headerRow && row === 0))),
97
+ })),
98
+ };
99
+ return {
100
+ id: "table.insert",
101
+ source: "user",
102
+ operations: [{ type: "insertNode", path: input.path, node }],
103
+ selectionBefore: context.selection,
104
+ selectionAfter: {
105
+ type: "text",
106
+ anchor: { path: [...input.path, 0, 0, 0, 0], offset: 0 },
107
+ focus: { path: [...input.path, 0, 0, 0, 0], offset: 0 },
108
+ },
109
+ addToHistory: true,
110
+ timestamp: context.now?.() ?? Date.now(),
111
+ };
112
+ },
113
+ };
114
+ export const removeTable = {
115
+ id: "table.remove",
116
+ isEnabled: (context, input) => Boolean(input && tableAt(context.document, input.tablePath)),
117
+ execute: (context, input) => {
118
+ if (!input || !removeTable.isEnabled(context, input)) {
119
+ throw new Error("table.remove requires a valid table path.");
120
+ }
121
+ return {
122
+ id: "table.remove",
123
+ source: "user",
124
+ operations: [{ type: "removeNode", path: input.tablePath }],
125
+ selectionBefore: context.selection,
126
+ addToHistory: true,
127
+ timestamp: context.now?.() ?? Date.now(),
128
+ };
129
+ },
130
+ };
131
+ const headerTarget = (context, input, scope) => {
132
+ const table = input && tableAt(context.document, input.tablePath);
133
+ const grid = table && buildTableGrid(table);
134
+ if (!input || !table || !grid || !grid.slots[input.row]?.[input.column])
135
+ return null;
136
+ const placements = scope === "cell"
137
+ ? [grid.slots[input.row][input.column]]
138
+ : scope === "row"
139
+ ? grid.placements.filter((placement) => placement.row <= input.row && placement.row + placement.rowspan > input.row)
140
+ : grid.placements.filter((placement) => placement.column <= input.column && placement.column + placement.colspan > input.column);
141
+ return { table, grid, placements: [...new Set(placements)] };
142
+ };
143
+ const createToggleTableHeader = (id, scope) => ({
144
+ id,
145
+ isEnabled: (context, input) => Boolean(headerTarget(context, input, scope)),
146
+ execute: (context, input) => {
147
+ const target = headerTarget(context, input, scope);
148
+ if (!input || !target)
149
+ throw new Error(`${id} requires a valid logical table cell.`);
150
+ const selected = new Set(target.placements);
151
+ const makeHeader = target.placements.some(({ cell }) => cell.type !== "tableHeaderCell");
152
+ const placements = target.grid.placements.map((placement) => ({
153
+ row: placement.row,
154
+ column: placement.column,
155
+ rowspan: placement.rowspan,
156
+ colspan: placement.colspan,
157
+ cell: selected.has(placement)
158
+ ? { ...placement.cell, type: makeHeader ? "tableHeaderCell" : "tableCell" }
159
+ : placement.cell,
160
+ }));
161
+ return replaceTableTransaction(context, id, input.tablePath, tableFromPlacements(target.table, target.table.children.length, placements));
162
+ },
163
+ });
164
+ export const toggleTableHeaderCell = createToggleTableHeader("table.header.cell.toggle", "cell");
165
+ export const toggleTableHeaderRow = createToggleTableHeader("table.header.row.toggle", "row");
166
+ export const toggleTableHeaderColumn = createToggleTableHeader("table.header.column.toggle", "column");
167
+ const cellStyleTarget = (context, input) => {
168
+ const table = input && tableAt(context.document, input.tablePath);
169
+ const grid = table && buildTableGrid(table);
170
+ if (!input || !table || !grid)
171
+ return null;
172
+ const end = input.end || input.start;
173
+ const top = Math.min(input.start.row, end.row);
174
+ const bottom = Math.max(input.start.row, end.row);
175
+ const left = Math.min(input.start.column, end.column);
176
+ const right = Math.max(input.start.column, end.column);
177
+ if (top < 0 || left < 0 || bottom >= table.children.length || right >= grid.width)
178
+ return null;
179
+ const placements = grid.placements.filter((placement) => placement.row <= bottom &&
180
+ placement.row + placement.rowspan > top &&
181
+ placement.column <= right &&
182
+ placement.column + placement.colspan > left);
183
+ return placements.length ? { table, grid, placements } : null;
184
+ };
185
+ export const setTableCellStyle = {
186
+ id: "table.cell.style.set",
187
+ isEnabled: (context, input) => Boolean(cellStyleTarget(context, input) &&
188
+ (input?.backgroundColor !== undefined || input?.textColor !== undefined)),
189
+ execute: (context, input) => {
190
+ const target = cellStyleTarget(context, input);
191
+ if (!input || !target || !setTableCellStyle.isEnabled(context, input)) {
192
+ throw new Error("table.cell.style.set requires a valid logical cell range and style.");
193
+ }
194
+ const selected = new Set(target.placements);
195
+ const placements = target.grid.placements.map((placement) => {
196
+ if (!selected.has(placement))
197
+ return placement;
198
+ const styled = { ...placement.cell };
199
+ if (input.backgroundColor !== undefined) {
200
+ if (input.backgroundColor)
201
+ styled.backgroundColor = input.backgroundColor;
202
+ else
203
+ delete styled.backgroundColor;
204
+ }
205
+ if (input.textColor !== undefined) {
206
+ if (input.textColor)
207
+ styled.textColor = input.textColor;
208
+ else
209
+ delete styled.textColor;
210
+ }
211
+ return { ...placement, cell: styled };
212
+ });
213
+ return replaceTableTransaction(context, "table.cell.style.set", input.tablePath, tableFromPlacements(target.table, target.table.children.length, placements));
214
+ },
215
+ };
216
+ export const toggleTableCellBorder = {
217
+ id: "table.cell.border.toggle",
218
+ isEnabled: (context, input) => Boolean(cellStyleTarget(context, input)),
219
+ execute: (context, input) => {
220
+ const target = cellStyleTarget(context, input);
221
+ if (!input || !target) {
222
+ throw new Error("table.cell.border.toggle requires a valid logical cell range.");
223
+ }
224
+ const selected = new Set(target.placements);
225
+ const placements = target.grid.placements.map((placement) => {
226
+ if (!selected.has(placement))
227
+ return placement;
228
+ const border = placement.cell.border && placement.cell.border !== "none"
229
+ ? "none"
230
+ : input.visibleBorder || "1px solid #d1d5db";
231
+ return { ...placement, cell: { ...placement.cell, border } };
232
+ });
233
+ return replaceTableTransaction(context, "table.cell.border.toggle", input.tablePath, tableFromPlacements(target.table, target.table.children.length, placements));
234
+ },
235
+ };
236
+ export const setTableColumnWidth = {
237
+ id: "table.column.width.set",
238
+ isEnabled: (context, input) => {
239
+ const table = input && tableAt(context.document, input.tablePath);
240
+ const width = table ? buildTableGrid(table)?.width || 0 : 0;
241
+ return Boolean(input && table && Number.isInteger(input.index) && input.index >= 0 &&
242
+ input.index < width && Number.isFinite(input.widthPx) && input.widthPx >= 60);
243
+ },
244
+ execute: (context, input) => {
245
+ const table = input && tableAt(context.document, input.tablePath);
246
+ if (!input || !table || !setTableColumnWidth.isEnabled(context, input)) {
247
+ throw new Error("table.column.width.set requires a valid logical column and width.");
248
+ }
249
+ const gridWidth = buildTableGrid(table).width;
250
+ const widths = Array.from({ length: gridWidth }, (_, index) => table.columnWidths?.[index] || 60);
251
+ widths[input.index] = input.widthPx;
252
+ return replaceTableTransaction(context, "table.column.width.set", input.tablePath, {
253
+ ...table,
254
+ columnWidths: widths,
255
+ });
256
+ },
257
+ };
258
+ export const setTableRowHeight = {
259
+ id: "table.row.height.set",
260
+ isEnabled: (context, input) => {
261
+ const table = input && tableAt(context.document, input.tablePath);
262
+ return Boolean(input && table && Number.isInteger(input.index) && input.index >= 0 &&
263
+ input.index < table.children.length && Number.isFinite(input.heightPx) && input.heightPx >= 30);
264
+ },
265
+ execute: (context, input) => {
266
+ const table = input && tableAt(context.document, input.tablePath);
267
+ if (!input || !table || !setTableRowHeight.isEnabled(context, input)) {
268
+ throw new Error("table.row.height.set requires a valid row and height.");
269
+ }
270
+ return replaceTableTransaction(context, "table.row.height.set", input.tablePath, {
271
+ ...table,
272
+ children: table.children.map((row, index) => index === input.index ? { ...row, heightPx: input.heightPx } : row),
273
+ });
274
+ },
275
+ };
276
+ export const addTableRow = {
277
+ id: "table.row.add",
278
+ isEnabled: (context, input) => {
279
+ const table = input && tableAt(context.document, input.tablePath);
280
+ return Boolean(table && Number.isInteger(input.index) && input.index >= 0 && input.index <= table.children.length);
281
+ },
282
+ execute: (context, input) => {
283
+ const table = input && tableAt(context.document, input.tablePath);
284
+ if (!input || !table || !addTableRow.isEnabled(context, input))
285
+ throw new Error("table.row.add requires a valid table row index.");
286
+ const grid = buildTableGrid(table);
287
+ if (!grid)
288
+ throw new Error("table.row.add requires a valid rectangular table grid.");
289
+ const crossing = new Set(grid.placements.filter((placement) => placement.row < input.index && placement.row + placement.rowspan > input.index));
290
+ const placements = grid.placements.map((placement) => ({
291
+ row: placement.row >= input.index ? placement.row + 1 : placement.row,
292
+ column: placement.column,
293
+ rowspan: placement.rowspan + (crossing.has(placement) ? 1 : 0),
294
+ colspan: placement.colspan,
295
+ cell: placement.cell,
296
+ }));
297
+ const covered = new Set();
298
+ crossing.forEach((placement) => {
299
+ for (let column = placement.column; column < placement.column + placement.colspan; column += 1) {
300
+ covered.add(column);
301
+ }
302
+ });
303
+ const header = input.index === 0 && table.children[0]?.children.every((candidate) => candidate.type === "tableHeaderCell");
304
+ for (let column = 0; column < grid.width; column += 1) {
305
+ if (!covered.has(column)) {
306
+ placements.push({ row: input.index, column, rowspan: 1, colspan: 1, cell: cell(header) });
307
+ }
308
+ }
309
+ return replaceTableTransaction(context, "table.row.add", input.tablePath, tableFromPlacements(table, table.children.length + 1, placements));
310
+ },
311
+ };
312
+ export const removeTableRow = {
313
+ id: "table.row.remove",
314
+ isEnabled: (context, input) => {
315
+ const table = input && tableAt(context.document, input.tablePath);
316
+ return Boolean(table && table.children.length > 1 && Number.isInteger(input.index) &&
317
+ input.index >= 0 && input.index < table.children.length);
318
+ },
319
+ execute: (context, input) => {
320
+ const table = input && tableAt(context.document, input.tablePath);
321
+ if (!input || !table || !removeTableRow.isEnabled(context, input)) {
322
+ throw new Error("table.row.remove cannot remove this row.");
323
+ }
324
+ const grid = buildTableGrid(table);
325
+ if (!grid)
326
+ throw new Error("table.row.remove requires a valid rectangular table grid.");
327
+ const placements = grid.placements.flatMap((placement) => {
328
+ const bottom = placement.row + placement.rowspan;
329
+ if (placement.row === input.index && placement.rowspan === 1)
330
+ return [];
331
+ const crosses = placement.row < input.index && bottom > input.index;
332
+ const startsOnRemovedRow = placement.row === input.index && placement.rowspan > 1;
333
+ return [{
334
+ row: placement.row > input.index ? placement.row - 1 : placement.row,
335
+ column: placement.column,
336
+ rowspan: placement.rowspan - (crosses || startsOnRemovedRow ? 1 : 0),
337
+ colspan: placement.colspan,
338
+ cell: placement.cell,
339
+ }];
340
+ });
341
+ return replaceTableTransaction(context, "table.row.remove", input.tablePath, tableFromPlacements(table, table.children.length - 1, placements));
342
+ },
343
+ };
344
+ export const addTableColumn = {
345
+ id: "table.column.add",
346
+ isEnabled: (context, input) => {
347
+ const table = input && tableAt(context.document, input.tablePath);
348
+ const width = table ? buildTableGrid(table)?.width || 0 : 0;
349
+ return Boolean(table && Number.isInteger(input.index) && input.index >= 0 && input.index <= width);
350
+ },
351
+ execute: (context, input) => {
352
+ const table = input && tableAt(context.document, input.tablePath);
353
+ if (!input || !table || !addTableColumn.isEnabled(context, input)) {
354
+ throw new Error("table.column.add requires a valid table column index.");
355
+ }
356
+ const grid = buildTableGrid(table);
357
+ if (!grid)
358
+ throw new Error("table.column.add requires a valid rectangular table grid.");
359
+ const crossing = new Set(grid.placements.filter((placement) => placement.column < input.index && placement.column + placement.colspan > input.index));
360
+ const placements = grid.placements.map((placement) => ({
361
+ row: placement.row,
362
+ column: placement.column >= input.index ? placement.column + 1 : placement.column,
363
+ rowspan: placement.rowspan,
364
+ colspan: placement.colspan + (crossing.has(placement) ? 1 : 0),
365
+ cell: placement.cell,
366
+ }));
367
+ for (let row = 0; row < table.children.length; row += 1) {
368
+ const occupied = grid.slots[row][input.index];
369
+ if (occupied && crossing.has(occupied))
370
+ continue;
371
+ const header = table.children[row].children.every((candidate) => candidate.type === "tableHeaderCell");
372
+ placements.push({ row, column: input.index, rowspan: 1, colspan: 1, cell: cell(header) });
373
+ }
374
+ return replaceTableTransaction(context, "table.column.add", input.tablePath, tableFromPlacements({
375
+ ...table,
376
+ columnWidths: table.columnWidths
377
+ ? [
378
+ ...table.columnWidths.slice(0, input.index),
379
+ table.columnWidths[Math.max(0, input.index - 1)] || 60,
380
+ ...table.columnWidths.slice(input.index),
381
+ ]
382
+ : undefined,
383
+ }, table.children.length, placements));
384
+ },
385
+ };
386
+ export const removeTableColumn = {
387
+ id: "table.column.remove",
388
+ isEnabled: (context, input) => {
389
+ const table = input && tableAt(context.document, input.tablePath);
390
+ const width = table ? buildTableGrid(table)?.width || 0 : 0;
391
+ return Boolean(table && width > 1 && Number.isInteger(input.index) &&
392
+ input.index >= 0 && input.index < width);
393
+ },
394
+ execute: (context, input) => {
395
+ const table = input && tableAt(context.document, input.tablePath);
396
+ if (!input || !table || !removeTableColumn.isEnabled(context, input)) {
397
+ throw new Error("table.column.remove cannot remove this column.");
398
+ }
399
+ const grid = buildTableGrid(table);
400
+ if (!grid)
401
+ throw new Error("table.column.remove requires a valid rectangular table grid.");
402
+ const placements = grid.placements.flatMap((placement) => {
403
+ const right = placement.column + placement.colspan;
404
+ if (input.index >= placement.column && input.index < right) {
405
+ if (placement.colspan === 1)
406
+ return [];
407
+ return [{
408
+ row: placement.row,
409
+ column: placement.column,
410
+ rowspan: placement.rowspan,
411
+ colspan: placement.colspan - 1,
412
+ cell: placement.cell,
413
+ }];
414
+ }
415
+ return [{
416
+ row: placement.row,
417
+ column: placement.column > input.index ? placement.column - 1 : placement.column,
418
+ rowspan: placement.rowspan,
419
+ colspan: placement.colspan,
420
+ cell: placement.cell,
421
+ }];
422
+ });
423
+ return replaceTableTransaction(context, "table.column.remove", input.tablePath, tableFromPlacements({
424
+ ...table,
425
+ columnWidths: table.columnWidths
426
+ ? table.columnWidths.filter((_, index) => index !== input.index)
427
+ : undefined,
428
+ }, table.children.length, placements));
429
+ },
430
+ };
431
+ const mergeRegion = (input) => ({
432
+ top: Math.min(input.start.row, input.end.row),
433
+ bottom: Math.max(input.start.row, input.end.row),
434
+ left: Math.min(input.start.column, input.end.column),
435
+ right: Math.max(input.start.column, input.end.column),
436
+ });
437
+ const mergeTarget = (context, input) => {
438
+ const table = input && tableAt(context.document, input.tablePath);
439
+ const grid = table && buildTableGrid(table);
440
+ if (!input || !table || !grid)
441
+ return null;
442
+ const region = mergeRegion(input);
443
+ if (region.top < 0 || region.left < 0 ||
444
+ region.bottom >= table.children.length || region.right >= grid.width ||
445
+ region.top === region.bottom && region.left === region.right)
446
+ return null;
447
+ const selected = grid.placements.filter((placement) => placement.row <= region.bottom &&
448
+ placement.row + placement.rowspan - 1 >= region.top &&
449
+ placement.column <= region.right &&
450
+ placement.column + placement.colspan - 1 >= region.left);
451
+ if (!selected.length || selected.some((placement) => placement.row < region.top ||
452
+ placement.column < region.left ||
453
+ placement.row + placement.rowspan - 1 > region.bottom ||
454
+ placement.column + placement.colspan - 1 > region.right))
455
+ return null;
456
+ const anchor = grid.slots[region.top]?.[region.left];
457
+ if (!anchor || anchor.row !== region.top || anchor.column !== region.left)
458
+ return null;
459
+ return { table, grid, region, selected, anchor };
460
+ };
461
+ export const mergeTableCells = {
462
+ id: "table.cell.merge",
463
+ isEnabled: (context, input) => Boolean(mergeTarget(context, input)),
464
+ execute: (context, input) => {
465
+ const target = mergeTarget(context, input);
466
+ if (!input || !target) {
467
+ throw new Error("table.cell.merge requires a valid rectangular cell selection.");
468
+ }
469
+ const selectedKeys = new Set(target.selected.map(({ rowIndex, cellIndex }) => `${rowIndex}:${cellIndex}`));
470
+ const ordered = [...target.selected].sort((left, right) => left.row - right.row || left.column - right.column);
471
+ const mergedCell = {
472
+ ...target.anchor.cell,
473
+ colspan: target.region.right - target.region.left + 1,
474
+ rowspan: target.region.bottom - target.region.top + 1,
475
+ children: ordered.flatMap((placement) => placement.cell.children),
476
+ };
477
+ if (mergedCell.colspan === 1)
478
+ delete mergedCell.colspan;
479
+ if (mergedCell.rowspan === 1)
480
+ delete mergedCell.rowspan;
481
+ const rows = target.table.children.map((row, rowIndex) => ({
482
+ ...row,
483
+ children: row.children.flatMap((current, cellIndex) => {
484
+ const key = `${rowIndex}:${cellIndex}`;
485
+ if (!selectedKeys.has(key))
486
+ return [current];
487
+ return rowIndex === target.anchor.rowIndex && cellIndex === target.anchor.cellIndex
488
+ ? [mergedCell]
489
+ : [];
490
+ }),
491
+ }));
492
+ return replaceTableTransaction(context, "table.cell.merge", input.tablePath, {
493
+ ...target.table,
494
+ children: rows,
495
+ });
496
+ },
497
+ };
498
+ const splitTarget = (context, input) => {
499
+ const table = input && tableAt(context.document, input.tablePath);
500
+ const grid = table && buildTableGrid(table);
501
+ const placement = input && grid?.slots[input.row]?.[input.column];
502
+ return table && grid && placement && (placement.rowspan > 1 || placement.colspan > 1)
503
+ ? { table, grid, placement }
504
+ : null;
505
+ };
506
+ export const splitTableCell = {
507
+ id: "table.cell.split",
508
+ isEnabled: (context, input) => Boolean(splitTarget(context, input)),
509
+ execute: (context, input) => {
510
+ const target = splitTarget(context, input);
511
+ if (!input || !target)
512
+ throw new Error("table.cell.split requires a merged cell.");
513
+ const replacementPlacements = [];
514
+ for (let row = target.placement.row; row < target.placement.row + target.placement.rowspan; row += 1) {
515
+ for (let column = target.placement.column; column < target.placement.column + target.placement.colspan; column += 1) {
516
+ replacementPlacements.push({
517
+ rowIndex: row,
518
+ cellIndex: 0,
519
+ row,
520
+ column,
521
+ rowspan: 1,
522
+ colspan: 1,
523
+ cell: row === target.placement.row && column === target.placement.column
524
+ ? {
525
+ type: target.placement.cell.type,
526
+ children: target.placement.cell.children,
527
+ }
528
+ : cell(target.placement.cell.type === "tableHeaderCell"),
529
+ });
530
+ }
531
+ }
532
+ const placements = target.grid.placements
533
+ .filter((placement) => placement !== target.placement)
534
+ .concat(replacementPlacements);
535
+ const rows = target.table.children.map((row, rowIndex) => ({
536
+ ...row,
537
+ children: placements
538
+ .filter((placement) => placement.row === rowIndex)
539
+ .sort((left, right) => left.column - right.column)
540
+ .map((placement) => placement.cell),
541
+ }));
542
+ return replaceTableTransaction(context, "table.cell.split", input.tablePath, {
543
+ ...target.table,
544
+ children: rows,
545
+ });
546
+ },
547
+ };
@@ -0,0 +1,12 @@
1
+ import type { SmartListPreset, SmartListStyle } from "./model.js";
2
+ import { type FoundationSmartListKind, type FoundationSmartListPresetDefinition } from "./foundation/list/presets.js";
3
+ export type SmartListKind = FoundationSmartListKind;
4
+ /** Public compatibility shape for the canonical foundation preset catalog. */
5
+ export type SmartListPresetDefinition = Omit<FoundationSmartListPresetDefinition, "id" | "styles"> & {
6
+ id: SmartListPreset;
7
+ styles: readonly SmartListStyle[];
8
+ };
9
+ export declare const SMART_LIST_PRESETS: readonly SmartListPresetDefinition[];
10
+ export declare const isSmartListPreset: (value: unknown) => value is SmartListPreset;
11
+ export declare const getSmartListPreset: (id: SmartListPreset) => SmartListPresetDefinition;
12
+ export declare const listStyleForPresetDepth: (id: SmartListPreset, depth: number) => SmartListStyle;
@@ -0,0 +1,6 @@
1
+ import { FOUNDATION_SMART_LIST_PRESETS, foundationListStyleForPresetDepth, isFoundationSmartListPreset, } from "./foundation/list/presets.js";
2
+ export const SMART_LIST_PRESETS = FOUNDATION_SMART_LIST_PRESETS;
3
+ export const isSmartListPreset = (value) => isFoundationSmartListPreset(value);
4
+ const presetMap = new Map(SMART_LIST_PRESETS.map((preset) => [preset.id, preset]));
5
+ export const getSmartListPreset = (id) => presetMap.get(id);
6
+ export const listStyleForPresetDepth = (id, depth) => foundationListStyleForPresetDepth(id, depth);
@@ -0,0 +1,27 @@
1
+ import { type Path, type LegacySmartDocument } from "./model.js";
2
+ import type { LegacySmartSelection } from "./selection.js";
3
+ export type LegacyListSelectionScope = {
4
+ kind: "all";
5
+ containerPath: Path;
6
+ } | {
7
+ kind: "blocks";
8
+ containerPath: Path;
9
+ start: number;
10
+ end: number;
11
+ } | {
12
+ kind: "list";
13
+ listPath: Path;
14
+ start: number;
15
+ end: number;
16
+ } | {
17
+ kind: "mixed";
18
+ containerPath: Path;
19
+ blockIndex: number;
20
+ listPath: Path;
21
+ itemStart: number;
22
+ itemEnd: number;
23
+ } | {
24
+ kind: "none";
25
+ };
26
+ /** Resolves the semantic list scope without inspecting DOM details. */
27
+ export declare const resolveListSelectionScope: (document: LegacySmartDocument, selection: LegacySmartSelection) => LegacyListSelectionScope;