smartrte-core 0.2.1 → 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 (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 +24 -0
  19. package/dist/foundation/atom/formats.js +105 -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 +21 -0
  127. package/dist/foundation/list/formats.js +813 -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 +27 -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 +28 -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,205 @@
1
+ import { getNodeAtPath, } from "../model.js";
2
+ import { isSmartContainer } from "../tree.js";
3
+ import { createDeleteInlineAtomCommand } from "./inlineAtoms.js";
4
+ const blockTypes = new Set([
5
+ "paragraph", "heading", "list", "blockquote", "codeBlock", "image", "media", "table",
6
+ ]);
7
+ const isBlock = (node) => Boolean(node) && typeof node === "object" &&
8
+ blockTypes.has(String(node.type));
9
+ const canContainBlocks = (node) => {
10
+ const type = node?.type;
11
+ return type === "doc" || type === "listItem" || type === "blockquote" ||
12
+ type === "tableCell" || type === "tableHeaderCell";
13
+ };
14
+ const resolveInsertionPath = (context, explicit) => {
15
+ if (explicit) {
16
+ const parent = getNodeAtPath(context.document, explicit.slice(0, -1));
17
+ const index = explicit[explicit.length - 1];
18
+ return explicit.length > 0 && canContainBlocks(parent) && isSmartContainer(parent) &&
19
+ Number.isInteger(index) && index >= 0 && index <= parent.children.length
20
+ ? [...explicit]
21
+ : null;
22
+ }
23
+ if (context.selection.type === "all")
24
+ return [context.document.children.length];
25
+ let path;
26
+ if (context.selection.type === "node")
27
+ path = context.selection.path;
28
+ if (context.selection.type === "text")
29
+ path = context.selection.focus.path;
30
+ if (context.selection.type === "cell") {
31
+ path = [
32
+ ...context.selection.tablePath,
33
+ context.selection.start.row,
34
+ context.selection.start.column,
35
+ ];
36
+ }
37
+ if (!path)
38
+ return null;
39
+ for (let length = path.length; length > 0; length -= 1) {
40
+ const candidatePath = path.slice(0, length);
41
+ if (!isBlock(getNodeAtPath(context.document, candidatePath)))
42
+ continue;
43
+ const parent = getNodeAtPath(context.document, candidatePath.slice(0, -1));
44
+ if (!canContainBlocks(parent))
45
+ continue;
46
+ return [
47
+ ...candidatePath.slice(0, -1),
48
+ candidatePath[candidatePath.length - 1] + 1,
49
+ ];
50
+ }
51
+ const selected = getNodeAtPath(context.document, path);
52
+ if (canContainBlocks(selected) && isSmartContainer(selected)) {
53
+ return [...path, selected.children.length];
54
+ }
55
+ return null;
56
+ };
57
+ const insertBlockTransaction = (context, id, path, node) => ({
58
+ id,
59
+ source: "user",
60
+ operations: [{ type: "insertNode", path, node }],
61
+ selectionBefore: context.selection,
62
+ selectionAfter: { type: "node", path },
63
+ addToHistory: true,
64
+ timestamp: context.now?.() ?? Date.now(),
65
+ });
66
+ const validImageInput = (input) => Boolean(input?.src.trim()) &&
67
+ (input?.width === undefined || Number.isFinite(input.width) && input.width > 0) &&
68
+ (input?.height === undefined || Number.isFinite(input.height) && input.height > 0);
69
+ export const insertImage = {
70
+ id: "image.insert",
71
+ isEnabled: (context, input) => validImageInput(input) && Boolean(resolveInsertionPath(context, input?.path)),
72
+ execute: (context, input) => {
73
+ const path = input && resolveInsertionPath(context, input.path);
74
+ if (!input || !validImageInput(input) || !path) {
75
+ throw new Error("image.insert requires a valid image and block insertion path.");
76
+ }
77
+ return insertBlockTransaction(context, "image.insert", path, {
78
+ type: "image",
79
+ src: input.src.trim(),
80
+ ...(input.alt ? { alt: input.alt } : {}),
81
+ ...(input.title ? { title: input.title } : {}),
82
+ ...(input.width ? { width: input.width } : {}),
83
+ ...(input.height ? { height: input.height } : {}),
84
+ });
85
+ },
86
+ };
87
+ const resolveInlineImageTarget = (context) => {
88
+ if (context.selection.type !== "text")
89
+ return null;
90
+ const { anchor, focus } = context.selection;
91
+ if (anchor.offset !== focus.offset ||
92
+ anchor.path.length !== focus.path.length ||
93
+ !anchor.path.every((part, index) => focus.path[index] === part))
94
+ return null;
95
+ const node = getNodeAtPath(context.document, anchor.path);
96
+ const parentPath = anchor.path.slice(0, -1);
97
+ const parent = getNodeAtPath(context.document, parentPath);
98
+ if (node?.type !== "text" ||
99
+ !isSmartContainer(parent) ||
100
+ !["paragraph", "heading"].includes(String(parent.type)) ||
101
+ anchor.offset < 0 ||
102
+ anchor.offset > node.text.length)
103
+ return null;
104
+ return { node, parent, parentPath, index: anchor.path[anchor.path.length - 1], offset: anchor.offset };
105
+ };
106
+ export const insertInlineImage = {
107
+ id: "image.insert-inline",
108
+ isEnabled: (context, input) => validImageInput(input) && Boolean(resolveInlineImageTarget(context)),
109
+ execute: (context, input) => {
110
+ const target = resolveInlineImageTarget(context);
111
+ if (!input || !validImageInput(input) || !target) {
112
+ throw new Error("image.insert-inline requires a collapsed selection in paragraph or heading text.");
113
+ }
114
+ const image = {
115
+ type: "inlineImage",
116
+ src: input.src.trim(),
117
+ ...(input.alt ? { alt: input.alt } : {}),
118
+ ...(input.title ? { title: input.title } : {}),
119
+ ...(input.width ? { width: input.width } : {}),
120
+ ...(input.height ? { height: input.height } : {}),
121
+ };
122
+ const replacement = [];
123
+ if (target.offset > 0) {
124
+ replacement.push({ ...target.node, text: target.node.text.slice(0, target.offset) });
125
+ }
126
+ replacement.push(image);
127
+ replacement.push({ ...target.node, text: target.node.text.slice(target.offset) });
128
+ const imageIndex = target.index + (target.offset > 0 ? 1 : 0);
129
+ return {
130
+ id: "image.insert-inline",
131
+ source: "user",
132
+ operations: [{
133
+ type: "replaceNode",
134
+ path: target.parentPath,
135
+ node: {
136
+ ...target.parent,
137
+ children: [
138
+ ...target.parent.children.slice(0, target.index),
139
+ ...replacement,
140
+ ...target.parent.children.slice(target.index + 1),
141
+ ],
142
+ },
143
+ }],
144
+ selectionBefore: context.selection,
145
+ selectionAfter: {
146
+ type: "text",
147
+ anchor: { path: [...target.parentPath, imageIndex + 1], offset: 0 },
148
+ focus: { path: [...target.parentPath, imageIndex + 1], offset: 0 },
149
+ },
150
+ addToHistory: true,
151
+ timestamp: context.now?.() ?? Date.now(),
152
+ };
153
+ },
154
+ };
155
+ export const deleteInlineImage = createDeleteInlineAtomCommand("image.delete-inline", "inlineImage");
156
+ export const updateInlineImage = {
157
+ id: "image.update-inline",
158
+ isEnabled: (context, input) => {
159
+ const node = input && getNodeAtPath(context.document, input.path);
160
+ return Boolean(node && node.type === "inlineImage" &&
161
+ (input?.width === undefined || Number.isFinite(input.width) && input.width > 0) &&
162
+ (input?.height === undefined || Number.isFinite(input.height) && input.height > 0));
163
+ },
164
+ execute: (context, input) => {
165
+ if (!input || !updateInlineImage.isEnabled(context, input)) {
166
+ throw new Error("image.update-inline requires a valid inline image path and dimensions.");
167
+ }
168
+ return {
169
+ id: "image.update-inline",
170
+ source: "user",
171
+ operations: [{
172
+ type: "setNodeAttrs",
173
+ path: input.path,
174
+ attrs: {
175
+ alt: input.alt,
176
+ title: input.title,
177
+ width: input.width,
178
+ height: input.height,
179
+ },
180
+ }],
181
+ selectionBefore: context.selection,
182
+ selectionAfter: context.selection,
183
+ addToHistory: true,
184
+ timestamp: context.now?.() ?? Date.now(),
185
+ };
186
+ },
187
+ };
188
+ const validMediaInput = (input) => Boolean(input?.src.trim()) && Boolean(input && ["audio", "video", "file"].includes(input.mediaType));
189
+ export const insertMedia = {
190
+ id: "media.insert",
191
+ isEnabled: (context, input) => validMediaInput(input) && Boolean(resolveInsertionPath(context, input?.path)),
192
+ execute: (context, input) => {
193
+ const path = input && resolveInsertionPath(context, input.path);
194
+ if (!input || !validMediaInput(input) || !path) {
195
+ throw new Error("media.insert requires valid media and a block insertion path.");
196
+ }
197
+ return insertBlockTransaction(context, "media.insert", path, {
198
+ type: "media",
199
+ src: input.src.trim(),
200
+ mediaType: input.mediaType,
201
+ ...(input.title ? { title: input.title } : {}),
202
+ ...(input.mimeType ? { mimeType: input.mimeType } : {}),
203
+ });
204
+ },
205
+ };
@@ -0,0 +1,14 @@
1
+ import type { SmartCommand } from "../command.js";
2
+ import type { Path } from "../model.js";
3
+ export interface MoveBlocksInput {
4
+ parentPath: Path;
5
+ blockIndexes: readonly number[];
6
+ direction: "up" | "down";
7
+ }
8
+ export interface IndentBlocksInput {
9
+ parentPath: Path;
10
+ blockIndexes: readonly number[];
11
+ direction: "indent" | "outdent";
12
+ }
13
+ export declare const moveBlocks: SmartCommand<MoveBlocksInput>;
14
+ export declare const indentBlocks: SmartCommand<IndentBlocksInput>;
@@ -0,0 +1,91 @@
1
+ import { getNodeAtTreePath, isSmartContainer } from "../tree.js";
2
+ const normalizedIndexes = (indexes) => {
3
+ const result = [...new Set(indexes)].sort((left, right) => left - right);
4
+ if (!result.length || result.some((index) => !Number.isInteger(index) || index < 0))
5
+ return undefined;
6
+ if (result.some((index, position) => position > 0 && index !== result[position - 1] + 1))
7
+ return undefined;
8
+ return result;
9
+ };
10
+ const resolveSiblingRange = (context, parentPath, indexes) => {
11
+ const normalized = normalizedIndexes(indexes);
12
+ if (!normalized)
13
+ return undefined;
14
+ try {
15
+ const parent = getNodeAtTreePath(context.document, parentPath);
16
+ if (!isSmartContainer(parent) || normalized[normalized.length - 1] >= parent.children.length)
17
+ return undefined;
18
+ return { parent, indexes: normalized };
19
+ }
20
+ catch {
21
+ return undefined;
22
+ }
23
+ };
24
+ export const moveBlocks = {
25
+ id: "block.move",
26
+ isEnabled: (context, input) => {
27
+ if (!input)
28
+ return false;
29
+ const range = resolveSiblingRange(context, input.parentPath, input.blockIndexes);
30
+ if (!range)
31
+ return false;
32
+ return input.direction === "up"
33
+ ? range.indexes[0] > 0
34
+ : range.indexes[range.indexes.length - 1] < range.parent.children.length - 1;
35
+ },
36
+ execute: (context, input) => {
37
+ if (!input || !moveBlocks.isEnabled(context, input)) {
38
+ throw new Error("block.move requires a movable contiguous sibling range.");
39
+ }
40
+ const indexes = normalizedIndexes(input.blockIndexes);
41
+ const first = indexes[0];
42
+ const last = indexes[indexes.length - 1];
43
+ return {
44
+ id: "move-blocks",
45
+ source: "user",
46
+ operations: input.direction === "up"
47
+ ? [{ type: "moveNode", from: [...input.parentPath, first - 1], to: [...input.parentPath, last + 1] }]
48
+ : [{ type: "moveNode", from: [...input.parentPath, last + 1], to: [...input.parentPath, first] }],
49
+ selectionBefore: context.selection,
50
+ addToHistory: true,
51
+ timestamp: context.now?.() ?? Date.now(),
52
+ };
53
+ },
54
+ };
55
+ export const indentBlocks = {
56
+ id: "block.indent",
57
+ isEnabled: (context, input) => {
58
+ if (!input)
59
+ return false;
60
+ const range = resolveSiblingRange(context, input.parentPath, input.blockIndexes);
61
+ if (!range)
62
+ return false;
63
+ return range.indexes.some((index) => {
64
+ const indent = Number(range.parent.children[index].indent) || 0;
65
+ return input.direction === "indent" ? indent < 10 : indent > 0;
66
+ });
67
+ },
68
+ execute: (context, input) => {
69
+ if (!input || !indentBlocks.isEnabled(context, input)) {
70
+ throw new Error("block.indent requires a sibling range whose indentation can change.");
71
+ }
72
+ const range = resolveSiblingRange(context, input.parentPath, input.blockIndexes);
73
+ return {
74
+ id: "indent-blocks",
75
+ source: "user",
76
+ operations: range.indexes.flatMap((index) => {
77
+ const indent = Number(range.parent.children[index].indent) || 0;
78
+ const nextIndent = input.direction === "indent"
79
+ ? Math.min(indent + 1, 10)
80
+ : Math.max(indent - 1, 0);
81
+ return nextIndent === indent
82
+ ? []
83
+ : [{ type: "setNodeAttrs", path: [...input.parentPath, index], attrs: { indent: nextIndent || undefined } }];
84
+ }),
85
+ selectionBefore: context.selection,
86
+ selectionAfter: context.selection,
87
+ addToHistory: true,
88
+ timestamp: context.now?.() ?? Date.now(),
89
+ };
90
+ },
91
+ };
@@ -0,0 +1,91 @@
1
+ import type { SmartCommand } from "../command.js";
2
+ import { type Path } from "../model.js";
3
+ export interface InsertTableInput {
4
+ path: Path;
5
+ rows: number;
6
+ columns: number;
7
+ headerRow?: boolean;
8
+ }
9
+ export declare const insertTable: SmartCommand<InsertTableInput>;
10
+ export interface RemoveTableInput {
11
+ tablePath: Path;
12
+ }
13
+ export declare const removeTable: SmartCommand<RemoveTableInput>;
14
+ export interface TableHeaderInput {
15
+ tablePath: Path;
16
+ row: number;
17
+ column: number;
18
+ }
19
+ export type TableHeaderScope = "cell" | "row" | "column";
20
+ export declare const toggleTableHeaderCell: SmartCommand<TableHeaderInput>;
21
+ export declare const toggleTableHeaderRow: SmartCommand<TableHeaderInput>;
22
+ export declare const toggleTableHeaderColumn: SmartCommand<TableHeaderInput>;
23
+ export interface SetTableCellStyleInput {
24
+ tablePath: Path;
25
+ start: {
26
+ row: number;
27
+ column: number;
28
+ };
29
+ end?: {
30
+ row: number;
31
+ column: number;
32
+ };
33
+ backgroundColor?: string | null;
34
+ textColor?: string | null;
35
+ }
36
+ export declare const setTableCellStyle: SmartCommand<SetTableCellStyleInput>;
37
+ export interface ToggleTableCellBorderInput {
38
+ tablePath: Path;
39
+ start: {
40
+ row: number;
41
+ column: number;
42
+ };
43
+ end?: {
44
+ row: number;
45
+ column: number;
46
+ };
47
+ visibleBorder?: string;
48
+ }
49
+ export declare const toggleTableCellBorder: SmartCommand<ToggleTableCellBorderInput>;
50
+ export interface SetTableColumnWidthInput {
51
+ tablePath: Path;
52
+ index: number;
53
+ widthPx: number;
54
+ }
55
+ export declare const setTableColumnWidth: SmartCommand<SetTableColumnWidthInput>;
56
+ export interface SetTableRowHeightInput {
57
+ tablePath: Path;
58
+ index: number;
59
+ heightPx: number;
60
+ }
61
+ export declare const setTableRowHeight: SmartCommand<SetTableRowHeightInput>;
62
+ export interface TableRowInput {
63
+ tablePath: Path;
64
+ index: number;
65
+ }
66
+ export declare const addTableRow: SmartCommand<TableRowInput>;
67
+ export declare const removeTableRow: SmartCommand<TableRowInput>;
68
+ export interface TableColumnInput {
69
+ tablePath: Path;
70
+ index: number;
71
+ }
72
+ export declare const addTableColumn: SmartCommand<TableColumnInput>;
73
+ export declare const removeTableColumn: SmartCommand<TableColumnInput>;
74
+ export interface MergeTableCellsInput {
75
+ tablePath: Path;
76
+ start: {
77
+ row: number;
78
+ column: number;
79
+ };
80
+ end: {
81
+ row: number;
82
+ column: number;
83
+ };
84
+ }
85
+ export declare const mergeTableCells: SmartCommand<MergeTableCellsInput>;
86
+ export interface SplitTableCellInput {
87
+ tablePath: Path;
88
+ row: number;
89
+ column: number;
90
+ }
91
+ export declare const splitTableCell: SmartCommand<SplitTableCellInput>;