@doxi/core 0.11.0

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 (317) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/dist/collab/port.d.ts +46 -0
  4. package/dist/collab/port.d.ts.map +1 -0
  5. package/dist/collab/port.js +11 -0
  6. package/dist/collab/port.js.map +1 -0
  7. package/dist/commands/block-commands.d.ts +62 -0
  8. package/dist/commands/block-commands.d.ts.map +1 -0
  9. package/dist/commands/block-commands.js +208 -0
  10. package/dist/commands/block-commands.js.map +1 -0
  11. package/dist/commands/command.d.ts +13 -0
  12. package/dist/commands/command.d.ts.map +1 -0
  13. package/dist/commands/command.js +13 -0
  14. package/dist/commands/command.js.map +1 -0
  15. package/dist/commands/edit-commands.d.ts +5 -0
  16. package/dist/commands/edit-commands.d.ts.map +1 -0
  17. package/dist/commands/edit-commands.js +147 -0
  18. package/dist/commands/edit-commands.js.map +1 -0
  19. package/dist/commands/image-commands.d.ts +31 -0
  20. package/dist/commands/image-commands.d.ts.map +1 -0
  21. package/dist/commands/image-commands.js +130 -0
  22. package/dist/commands/image-commands.js.map +1 -0
  23. package/dist/commands/index.d.ts +11 -0
  24. package/dist/commands/index.d.ts.map +1 -0
  25. package/dist/commands/index.js +11 -0
  26. package/dist/commands/index.js.map +1 -0
  27. package/dist/commands/keymap.d.ts +34 -0
  28. package/dist/commands/keymap.d.ts.map +1 -0
  29. package/dist/commands/keymap.js +84 -0
  30. package/dist/commands/keymap.js.map +1 -0
  31. package/dist/commands/link-commands.d.ts +54 -0
  32. package/dist/commands/link-commands.d.ts.map +1 -0
  33. package/dist/commands/link-commands.js +151 -0
  34. package/dist/commands/link-commands.js.map +1 -0
  35. package/dist/commands/list-commands.d.ts +42 -0
  36. package/dist/commands/list-commands.d.ts.map +1 -0
  37. package/dist/commands/list-commands.js +316 -0
  38. package/dist/commands/list-commands.js.map +1 -0
  39. package/dist/commands/mark-commands.d.ts +53 -0
  40. package/dist/commands/mark-commands.d.ts.map +1 -0
  41. package/dist/commands/mark-commands.js +181 -0
  42. package/dist/commands/mark-commands.js.map +1 -0
  43. package/dist/commands/selection-commands.d.ts +3 -0
  44. package/dist/commands/selection-commands.d.ts.map +1 -0
  45. package/dist/commands/selection-commands.js +11 -0
  46. package/dist/commands/selection-commands.js.map +1 -0
  47. package/dist/commands/table-commands.d.ts +109 -0
  48. package/dist/commands/table-commands.d.ts.map +1 -0
  49. package/dist/commands/table-commands.js +884 -0
  50. package/dist/commands/table-commands.js.map +1 -0
  51. package/dist/history/history.d.ts +40 -0
  52. package/dist/history/history.d.ts.map +1 -0
  53. package/dist/history/history.js +139 -0
  54. package/dist/history/history.js.map +1 -0
  55. package/dist/history/index.d.ts +2 -0
  56. package/dist/history/index.d.ts.map +1 -0
  57. package/dist/history/index.js +2 -0
  58. package/dist/history/index.js.map +1 -0
  59. package/dist/html/index.d.ts +3 -0
  60. package/dist/html/index.d.ts.map +1 -0
  61. package/dist/html/index.js +3 -0
  62. package/dist/html/index.js.map +1 -0
  63. package/dist/html/parse.d.ts +4 -0
  64. package/dist/html/parse.d.ts.map +1 -0
  65. package/dist/html/parse.js +0 -0
  66. package/dist/html/parse.js.map +1 -0
  67. package/dist/html/serialize.d.ts +4 -0
  68. package/dist/html/serialize.d.ts.map +1 -0
  69. package/dist/html/serialize.js +75 -0
  70. package/dist/html/serialize.js.map +1 -0
  71. package/dist/index.d.ts +13 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +13 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/layout/index.d.ts +6 -0
  76. package/dist/layout/index.d.ts.map +1 -0
  77. package/dist/layout/index.js +6 -0
  78. package/dist/layout/index.js.map +1 -0
  79. package/dist/layout/layout-engine.d.ts +20 -0
  80. package/dist/layout/layout-engine.d.ts.map +1 -0
  81. package/dist/layout/layout-engine.js +198 -0
  82. package/dist/layout/layout-engine.js.map +1 -0
  83. package/dist/layout/measure.d.ts +9 -0
  84. package/dist/layout/measure.d.ts.map +1 -0
  85. package/dist/layout/measure.js +37 -0
  86. package/dist/layout/measure.js.map +1 -0
  87. package/dist/layout/split-paragraph.d.ts +28 -0
  88. package/dist/layout/split-paragraph.d.ts.map +1 -0
  89. package/dist/layout/split-paragraph.js +122 -0
  90. package/dist/layout/split-paragraph.js.map +1 -0
  91. package/dist/layout/split-table.d.ts +46 -0
  92. package/dist/layout/split-table.d.ts.map +1 -0
  93. package/dist/layout/split-table.js +84 -0
  94. package/dist/layout/split-table.js.map +1 -0
  95. package/dist/layout/types.d.ts +73 -0
  96. package/dist/layout/types.d.ts.map +1 -0
  97. package/dist/layout/types.js +36 -0
  98. package/dist/layout/types.js.map +1 -0
  99. package/dist/layout/widow-orphan.d.ts +15 -0
  100. package/dist/layout/widow-orphan.d.ts.map +1 -0
  101. package/dist/layout/widow-orphan.js +14 -0
  102. package/dist/layout/widow-orphan.js.map +1 -0
  103. package/dist/model/content-expr.d.ts +32 -0
  104. package/dist/model/content-expr.d.ts.map +1 -0
  105. package/dist/model/content-expr.js +106 -0
  106. package/dist/model/content-expr.js.map +1 -0
  107. package/dist/model/fragment.d.ts +17 -0
  108. package/dist/model/fragment.d.ts.map +1 -0
  109. package/dist/model/fragment.js +44 -0
  110. package/dist/model/fragment.js.map +1 -0
  111. package/dist/model/index.d.ts +10 -0
  112. package/dist/model/index.d.ts.map +1 -0
  113. package/dist/model/index.js +10 -0
  114. package/dist/model/index.js.map +1 -0
  115. package/dist/model/mark.d.ts +35 -0
  116. package/dist/model/mark.d.ts.map +1 -0
  117. package/dist/model/mark.js +89 -0
  118. package/dist/model/mark.js.map +1 -0
  119. package/dist/model/node-type.d.ts +36 -0
  120. package/dist/model/node-type.d.ts.map +1 -0
  121. package/dist/model/node-type.js +14 -0
  122. package/dist/model/node-type.js.map +1 -0
  123. package/dist/model/node.d.ts +36 -0
  124. package/dist/model/node.d.ts.map +1 -0
  125. package/dist/model/node.js +192 -0
  126. package/dist/model/node.js.map +1 -0
  127. package/dist/model/position.d.ts +66 -0
  128. package/dist/model/position.d.ts.map +1 -0
  129. package/dist/model/position.js +158 -0
  130. package/dist/model/position.js.map +1 -0
  131. package/dist/model/schema.d.ts +28 -0
  132. package/dist/model/schema.d.ts.map +1 -0
  133. package/dist/model/schema.js +195 -0
  134. package/dist/model/schema.js.map +1 -0
  135. package/dist/model/slice.d.ts +26 -0
  136. package/dist/model/slice.d.ts.map +1 -0
  137. package/dist/model/slice.js +56 -0
  138. package/dist/model/slice.js.map +1 -0
  139. package/dist/model/table-grid.d.ts +71 -0
  140. package/dist/model/table-grid.d.ts.map +1 -0
  141. package/dist/model/table-grid.js +130 -0
  142. package/dist/model/table-grid.js.map +1 -0
  143. package/dist/plugin/index.d.ts +3 -0
  144. package/dist/plugin/index.d.ts.map +1 -0
  145. package/dist/plugin/index.js +3 -0
  146. package/dist/plugin/index.js.map +1 -0
  147. package/dist/plugin/plugin-key.d.ts +13 -0
  148. package/dist/plugin/plugin-key.d.ts.map +1 -0
  149. package/dist/plugin/plugin-key.js +13 -0
  150. package/dist/plugin/plugin-key.js.map +1 -0
  151. package/dist/plugin/plugin-state.d.ts +2 -0
  152. package/dist/plugin/plugin-state.d.ts.map +1 -0
  153. package/dist/plugin/plugin-state.js +3 -0
  154. package/dist/plugin/plugin-state.js.map +1 -0
  155. package/dist/plugin/plugin.d.ts +39 -0
  156. package/dist/plugin/plugin.d.ts.map +1 -0
  157. package/dist/plugin/plugin.js +10 -0
  158. package/dist/plugin/plugin.js.map +1 -0
  159. package/dist/schema/default.d.ts +163 -0
  160. package/dist/schema/default.d.ts.map +1 -0
  161. package/dist/schema/default.js +94 -0
  162. package/dist/schema/default.js.map +1 -0
  163. package/dist/schema/index.d.ts +2 -0
  164. package/dist/schema/index.d.ts.map +1 -0
  165. package/dist/schema/index.js +2 -0
  166. package/dist/schema/index.js.map +1 -0
  167. package/dist/serialize/index.d.ts +2 -0
  168. package/dist/serialize/index.d.ts.map +1 -0
  169. package/dist/serialize/index.js +2 -0
  170. package/dist/serialize/index.js.map +1 -0
  171. package/dist/serialize/json.d.ts +15 -0
  172. package/dist/serialize/json.d.ts.map +1 -0
  173. package/dist/serialize/json.js +23 -0
  174. package/dist/serialize/json.js.map +1 -0
  175. package/dist/state/all-selection.d.ts +11 -0
  176. package/dist/state/all-selection.d.ts.map +1 -0
  177. package/dist/state/all-selection.js +17 -0
  178. package/dist/state/all-selection.js.map +1 -0
  179. package/dist/state/cell-selection.d.ts +30 -0
  180. package/dist/state/cell-selection.d.ts.map +1 -0
  181. package/dist/state/cell-selection.js +38 -0
  182. package/dist/state/cell-selection.js.map +1 -0
  183. package/dist/state/editor-state.d.ts +46 -0
  184. package/dist/state/editor-state.d.ts.map +1 -0
  185. package/dist/state/editor-state.js +211 -0
  186. package/dist/state/editor-state.js.map +1 -0
  187. package/dist/state/index.d.ts +7 -0
  188. package/dist/state/index.d.ts.map +1 -0
  189. package/dist/state/index.js +7 -0
  190. package/dist/state/index.js.map +1 -0
  191. package/dist/state/node-selection.d.ts +16 -0
  192. package/dist/state/node-selection.d.ts.map +1 -0
  193. package/dist/state/node-selection.js +51 -0
  194. package/dist/state/node-selection.js.map +1 -0
  195. package/dist/state/selection.d.ts +29 -0
  196. package/dist/state/selection.d.ts.map +1 -0
  197. package/dist/state/selection.js +24 -0
  198. package/dist/state/selection.js.map +1 -0
  199. package/dist/state/text-selection.d.ts +10 -0
  200. package/dist/state/text-selection.d.ts.map +1 -0
  201. package/dist/state/text-selection.js +26 -0
  202. package/dist/state/text-selection.js.map +1 -0
  203. package/dist/transform/attr-step.d.ts +16 -0
  204. package/dist/transform/attr-step.d.ts.map +1 -0
  205. package/dist/transform/attr-step.js +98 -0
  206. package/dist/transform/attr-step.js.map +1 -0
  207. package/dist/transform/index.d.ts +10 -0
  208. package/dist/transform/index.d.ts.map +1 -0
  209. package/dist/transform/index.js +10 -0
  210. package/dist/transform/index.js.map +1 -0
  211. package/dist/transform/mapping.d.ts +44 -0
  212. package/dist/transform/mapping.d.ts.map +1 -0
  213. package/dist/transform/mapping.js +101 -0
  214. package/dist/transform/mapping.js.map +1 -0
  215. package/dist/transform/mark-step.d.ts +27 -0
  216. package/dist/transform/mark-step.d.ts.map +1 -0
  217. package/dist/transform/mark-step.js +146 -0
  218. package/dist/transform/mark-step.js.map +1 -0
  219. package/dist/transform/replace-around-step.d.ts +35 -0
  220. package/dist/transform/replace-around-step.d.ts.map +1 -0
  221. package/dist/transform/replace-around-step.js +144 -0
  222. package/dist/transform/replace-around-step.js.map +1 -0
  223. package/dist/transform/replace-step.d.ts +17 -0
  224. package/dist/transform/replace-step.d.ts.map +1 -0
  225. package/dist/transform/replace-step.js +72 -0
  226. package/dist/transform/replace-step.js.map +1 -0
  227. package/dist/transform/replace.d.ts +18 -0
  228. package/dist/transform/replace.d.ts.map +1 -0
  229. package/dist/transform/replace.js +132 -0
  230. package/dist/transform/replace.js.map +1 -0
  231. package/dist/transform/set-page-meta-step.d.ts +42 -0
  232. package/dist/transform/set-page-meta-step.d.ts.map +1 -0
  233. package/dist/transform/set-page-meta-step.js +75 -0
  234. package/dist/transform/set-page-meta-step.js.map +1 -0
  235. package/dist/transform/step.d.ts +34 -0
  236. package/dist/transform/step.d.ts.map +1 -0
  237. package/dist/transform/step.js +23 -0
  238. package/dist/transform/step.js.map +1 -0
  239. package/dist/transform/transaction.d.ts +20 -0
  240. package/dist/transform/transaction.d.ts.map +1 -0
  241. package/dist/transform/transaction.js +38 -0
  242. package/dist/transform/transaction.js.map +1 -0
  243. package/dist/version.d.ts +2 -0
  244. package/dist/version.d.ts.map +1 -0
  245. package/dist/version.js +5 -0
  246. package/dist/version.js.map +1 -0
  247. package/dist/view/cell-drag.d.ts +33 -0
  248. package/dist/view/cell-drag.d.ts.map +1 -0
  249. package/dist/view/cell-drag.js +177 -0
  250. package/dist/view/cell-drag.js.map +1 -0
  251. package/dist/view/clipboard.d.ts +5 -0
  252. package/dist/view/clipboard.d.ts.map +1 -0
  253. package/dist/view/clipboard.js +97 -0
  254. package/dist/view/clipboard.js.map +1 -0
  255. package/dist/view/default-renderer.d.ts +3 -0
  256. package/dist/view/default-renderer.d.ts.map +1 -0
  257. package/dist/view/default-renderer.js +142 -0
  258. package/dist/view/default-renderer.js.map +1 -0
  259. package/dist/view/dom-spec.d.ts +11 -0
  260. package/dist/view/dom-spec.d.ts.map +1 -0
  261. package/dist/view/dom-spec.js +32 -0
  262. package/dist/view/dom-spec.js.map +1 -0
  263. package/dist/view/editor-view.d.ts +55 -0
  264. package/dist/view/editor-view.d.ts.map +1 -0
  265. package/dist/view/editor-view.js +143 -0
  266. package/dist/view/editor-view.js.map +1 -0
  267. package/dist/view/image-resize.d.ts +37 -0
  268. package/dist/view/image-resize.d.ts.map +1 -0
  269. package/dist/view/image-resize.js +191 -0
  270. package/dist/view/image-resize.js.map +1 -0
  271. package/dist/view/index.d.ts +15 -0
  272. package/dist/view/index.d.ts.map +1 -0
  273. package/dist/view/index.js +15 -0
  274. package/dist/view/index.js.map +1 -0
  275. package/dist/view/input-pipeline.d.ts +24 -0
  276. package/dist/view/input-pipeline.d.ts.map +1 -0
  277. package/dist/view/input-pipeline.js +226 -0
  278. package/dist/view/input-pipeline.js.map +1 -0
  279. package/dist/view/mutation-observer.d.ts +17 -0
  280. package/dist/view/mutation-observer.d.ts.map +1 -0
  281. package/dist/view/mutation-observer.js +62 -0
  282. package/dist/view/mutation-observer.js.map +1 -0
  283. package/dist/view/page-slots.d.ts +56 -0
  284. package/dist/view/page-slots.d.ts.map +1 -0
  285. package/dist/view/page-slots.js +230 -0
  286. package/dist/view/page-slots.js.map +1 -0
  287. package/dist/view/paginator.d.ts +17 -0
  288. package/dist/view/paginator.d.ts.map +1 -0
  289. package/dist/view/paginator.js +93 -0
  290. package/dist/view/paginator.js.map +1 -0
  291. package/dist/view/print.d.ts +42 -0
  292. package/dist/view/print.d.ts.map +1 -0
  293. package/dist/view/print.js +70 -0
  294. package/dist/view/print.js.map +1 -0
  295. package/dist/view/reconcile.d.ts +16 -0
  296. package/dist/view/reconcile.d.ts.map +1 -0
  297. package/dist/view/reconcile.js +158 -0
  298. package/dist/view/reconcile.js.map +1 -0
  299. package/dist/view/renderer.d.ts +31 -0
  300. package/dist/view/renderer.d.ts.map +1 -0
  301. package/dist/view/renderer.js +89 -0
  302. package/dist/view/renderer.js.map +1 -0
  303. package/dist/view/selection-sync.d.ts +35 -0
  304. package/dist/view/selection-sync.d.ts.map +1 -0
  305. package/dist/view/selection-sync.js +324 -0
  306. package/dist/view/selection-sync.js.map +1 -0
  307. package/dist/view/table-resize.d.ts +41 -0
  308. package/dist/view/table-resize.d.ts.map +1 -0
  309. package/dist/view/table-resize.js +216 -0
  310. package/dist/view/table-resize.js.map +1 -0
  311. package/package.json +93 -0
  312. package/styles/base.css +269 -0
  313. package/styles/dark.css +36 -0
  314. package/styles/light.css +13 -0
  315. package/styles/page.css +93 -0
  316. package/styles/print-a4.css +87 -0
  317. package/styles/print.css +88 -0
@@ -0,0 +1,230 @@
1
+ import { Fragment } from '../model/fragment.js';
2
+ import { DxNode } from '../model/node.js';
3
+ import { SetPageMetaStep } from '../transform/set-page-meta-step.js';
4
+ /** Internal: does this fragment look like "empty"? */
5
+ function isFragmentEmpty(frag) {
6
+ return frag.childCount === 0;
7
+ }
8
+ /**
9
+ * Read text content from a slot fragment. Used to debounce input-event
10
+ * dispatches and to skip re-rendering when text already matches.
11
+ *
12
+ * v0.4 schema: fragment is either empty or a single paragraph with
13
+ * inline content. We concatenate text from any depth as a best-effort
14
+ * read; `page_var` atoms contribute no text here (they substitute live
15
+ * per page in `renderFragmentInto`).
16
+ */
17
+ function fragmentToText(frag) {
18
+ let out = '';
19
+ const walk = (node) => {
20
+ if (node.isText) {
21
+ out += node.text ?? '';
22
+ return;
23
+ }
24
+ for (let i = 0; i < node.content.childCount; i++) {
25
+ walk(node.content.child(i));
26
+ }
27
+ };
28
+ for (let i = 0; i < frag.childCount; i++)
29
+ walk(frag.child(i));
30
+ return out;
31
+ }
32
+ /**
33
+ * Build a Fragment containing a single `paragraph` node with the given
34
+ * plain text (or an empty Fragment if `text` is empty). Throws if the
35
+ * schema doesn't declare a `paragraph` node — slots are inert in that
36
+ * case.
37
+ */
38
+ function buildParagraphFragment(view, text) {
39
+ if (text.length === 0)
40
+ return Fragment.empty;
41
+ const schema = view.state.schema;
42
+ const paragraphType = schema.nodes['paragraph'];
43
+ if (!paragraphType)
44
+ return Fragment.empty;
45
+ const para = schema.node('paragraph', null, [schema.text(text)]);
46
+ return Fragment.from([para]);
47
+ }
48
+ /**
49
+ * Render a slot fragment into the given DOM element, substituting
50
+ * `page_var` atoms with per-page values. Clears the element first.
51
+ *
52
+ * The fragment shape is documented at the top of this file (either
53
+ * empty or a single paragraph of inline content). We walk the
54
+ * paragraph's inline children and emit:
55
+ * - text leaf → TextNode with the leaf's `text`
56
+ * - page_var('pageNumber') → span with `pageNumber` (1-based, plus
57
+ * `pageNumberStartAt` offset).
58
+ * - page_var('totalPages') → span with `totalPages`.
59
+ * - anything else → skipped (defensive; the schema constrains valid
60
+ * contents but a richer fragment passed
61
+ * programmatically shouldn't crash the slot).
62
+ */
63
+ function renderFragmentInto(el, frag, pageNumber, totalPages) {
64
+ while (el.firstChild)
65
+ el.removeChild(el.firstChild);
66
+ if (isFragmentEmpty(frag))
67
+ return;
68
+ const doc = el.ownerDocument;
69
+ for (let i = 0; i < frag.childCount; i++) {
70
+ const para = frag.child(i);
71
+ if (para.isText) {
72
+ // Defensive: top-level text in the fragment (shouldn't happen for
73
+ // the v0.4 schema, but if it does we render it directly).
74
+ el.appendChild(doc.createTextNode(para.text ?? ''));
75
+ continue;
76
+ }
77
+ // Walk the paragraph's inline children.
78
+ for (let j = 0; j < para.content.childCount; j++) {
79
+ const inline = para.content.child(j);
80
+ if (inline.isText) {
81
+ el.appendChild(doc.createTextNode(inline.text ?? ''));
82
+ continue;
83
+ }
84
+ if (inline.type.name === 'page_var') {
85
+ const kind = inline.attrs.kind ?? '';
86
+ let valueText = '';
87
+ if (kind === 'pageNumber')
88
+ valueText = String(pageNumber);
89
+ else if (kind === 'totalPages')
90
+ valueText = String(totalPages);
91
+ const span = doc.createElement('span');
92
+ span.className = 'dx-page-var';
93
+ span.setAttribute('data-kind', kind);
94
+ span.textContent = valueText;
95
+ el.appendChild(span);
96
+ continue;
97
+ }
98
+ // Unknown inline type — skip silently.
99
+ }
100
+ }
101
+ }
102
+ /**
103
+ * Compute the slot's expected textContent for a given page index. Used
104
+ * to decide whether a refresh needs to clobber DOM — we always rebuild
105
+ * when slots contain page_var nodes because page numbers can shift when
106
+ * total pages or the start-at offset changes; but for fragments
107
+ * containing ONLY text we can early-out if the DOM already matches.
108
+ */
109
+ function computeSlotTextForPage(frag, pageNumber, totalPages) {
110
+ if (isFragmentEmpty(frag))
111
+ return '';
112
+ let out = '';
113
+ for (let i = 0; i < frag.childCount; i++) {
114
+ const para = frag.child(i);
115
+ if (para.isText) {
116
+ out += para.text ?? '';
117
+ continue;
118
+ }
119
+ for (let j = 0; j < para.content.childCount; j++) {
120
+ const inline = para.content.child(j);
121
+ if (inline.isText) {
122
+ out += inline.text ?? '';
123
+ continue;
124
+ }
125
+ if (inline.type.name === 'page_var') {
126
+ const kind = inline.attrs.kind ?? '';
127
+ if (kind === 'pageNumber')
128
+ out += String(pageNumber);
129
+ else if (kind === 'totalPages')
130
+ out += String(totalPages);
131
+ }
132
+ }
133
+ }
134
+ return out;
135
+ }
136
+ export function installPageSlots(view) {
137
+ let pages = [];
138
+ const bindings = [];
139
+ const tearDownBindings = () => {
140
+ for (const b of bindings) {
141
+ b.el.removeEventListener('input', b.inputListener);
142
+ b.el.removeAttribute('contenteditable');
143
+ b.el.removeAttribute('data-placeholder');
144
+ }
145
+ bindings.length = 0;
146
+ };
147
+ const dispatchSlotUpdate = (slot, text) => {
148
+ const fragment = buildParagraphFragment(view, text);
149
+ // Skip the dispatch if the fragment text equals what's already in
150
+ // state.pageMeta — avoids redundant history entries when the
151
+ // browser fires `input` for IME composition steps that don't
152
+ // actually change the visible text.
153
+ const currentText = fragmentToText(view.state.pageMeta[slot]);
154
+ if (currentText === text)
155
+ return;
156
+ const step = new SetPageMetaStep(slot, fragment);
157
+ const tr = view.state.tr.step(step);
158
+ view.dispatch(tr);
159
+ };
160
+ const mountEditableSlot = (el, slot) => {
161
+ el.setAttribute('contenteditable', 'true');
162
+ el.setAttribute('data-placeholder', slot === 'header' ? 'Header' : 'Footer');
163
+ const listener = () => {
164
+ const text = el.textContent ?? '';
165
+ dispatchSlotUpdate(slot, text);
166
+ };
167
+ el.addEventListener('input', listener);
168
+ bindings.push({ el, slot, inputListener: listener });
169
+ };
170
+ const refresh = () => {
171
+ if (pages.length === 0)
172
+ return;
173
+ const headerFragment = view.state.pageMeta.header;
174
+ const footerFragment = view.state.pageMeta.footer;
175
+ const startAt = view.state.pageMeta.pageNumberStartAt ?? 1;
176
+ const totalPages = pages.length;
177
+ const activeEl = view.dom.ownerDocument.activeElement;
178
+ for (let i = 0; i < pages.length; i++) {
179
+ const page = pages[i];
180
+ const pageNumber = i + startAt;
181
+ const headerEl = page.querySelector('.dx-page-header');
182
+ const footerEl = page.querySelector('.dx-page-footer');
183
+ if (headerEl) {
184
+ headerEl.setAttribute('data-dx-slot-page-index', String(i));
185
+ // Skip re-rendering when the user is currently typing in this
186
+ // slot — overwriting textContent destroys the caret and IME
187
+ // composition state. The browser already mutated the DOM to the
188
+ // text we'd render anyway. If the text has somehow diverged
189
+ // (e.g. focused but state changed from elsewhere), defer to the
190
+ // next un-focused refresh.
191
+ if (activeEl !== headerEl) {
192
+ const desiredText = computeSlotTextForPage(headerFragment, pageNumber, totalPages);
193
+ if (headerEl.textContent !== desiredText) {
194
+ renderFragmentInto(headerEl, headerFragment, pageNumber, totalPages);
195
+ }
196
+ }
197
+ }
198
+ if (footerEl) {
199
+ footerEl.setAttribute('data-dx-slot-page-index', String(i));
200
+ if (activeEl !== footerEl) {
201
+ const desiredText = computeSlotTextForPage(footerFragment, pageNumber, totalPages);
202
+ if (footerEl.textContent !== desiredText) {
203
+ renderFragmentInto(footerEl, footerFragment, pageNumber, totalPages);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ };
209
+ const attach = (newPages) => {
210
+ tearDownBindings();
211
+ pages = newPages;
212
+ if (pages.length === 0)
213
+ return;
214
+ // First page hosts the editable slots; all others mirror.
215
+ const first = pages[0];
216
+ const firstHeader = first.querySelector('.dx-page-header');
217
+ const firstFooter = first.querySelector('.dx-page-footer');
218
+ if (firstHeader)
219
+ mountEditableSlot(firstHeader, 'header');
220
+ if (firstFooter)
221
+ mountEditableSlot(firstFooter, 'footer');
222
+ refresh();
223
+ };
224
+ const destroy = () => {
225
+ tearDownBindings();
226
+ pages = [];
227
+ };
228
+ return { attach, refresh, destroy };
229
+ }
230
+ //# sourceMappingURL=page-slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-slots.js","sourceRoot":"","sources":["../../src/view/page-slots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { PageBreakModel } from '../layout/types.js';
2
+ import type { DxNode } from '../model/node.js';
3
+ import { type Renderer } from './renderer.js';
4
+ /**
5
+ * Render a paginated view into `host`.
6
+ *
7
+ * Clears the host, applies the .dx-page-host class, and emits one .dx-page
8
+ * element per PageBox in the model. Each .dx-page contains slot elements
9
+ * (.dx-page-header, .dx-page-content, .dx-page-footer) and a page-number
10
+ * badge. Doc-level block children are distributed across pages according to
11
+ * each PageBox's blockIndices.
12
+ *
13
+ * The host's existing contenteditable attribute (set by EditorView) is
14
+ * preserved — pages render INSIDE the contenteditable surface.
15
+ */
16
+ export declare function paginate(host: HTMLElement, doc: DxNode, model: PageBreakModel, renderer: Renderer): void;
17
+ //# sourceMappingURL=paginator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paginator.d.ts","sourceRoot":"","sources":["../../src/view/paginator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,oBAAoB,CAAA;AAExE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AAEzD;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,QAAQ,GACjB,IAAI,CAsFN"}
@@ -0,0 +1,93 @@
1
+ import { buildPartialTable } from '../layout/split-table.js';
2
+ import { renderNode } from './renderer.js';
3
+ /**
4
+ * Render a paginated view into `host`.
5
+ *
6
+ * Clears the host, applies the .dx-page-host class, and emits one .dx-page
7
+ * element per PageBox in the model. Each .dx-page contains slot elements
8
+ * (.dx-page-header, .dx-page-content, .dx-page-footer) and a page-number
9
+ * badge. Doc-level block children are distributed across pages according to
10
+ * each PageBox's blockIndices.
11
+ *
12
+ * The host's existing contenteditable attribute (set by EditorView) is
13
+ * preserved — pages render INSIDE the contenteditable surface.
14
+ */
15
+ export function paginate(host, doc, model, renderer) {
16
+ while (host.firstChild)
17
+ host.removeChild(host.firstChild);
18
+ host.classList.add('dx-page-host');
19
+ const dims = model.dimensions;
20
+ for (const box of model.pages) {
21
+ const page = host.ownerDocument.createElement('div');
22
+ page.className = 'dx-page';
23
+ page.style.width = `${dims.widthPx}px`;
24
+ page.style.height = `${dims.heightPx}px`;
25
+ page.dataset.pageIndex = String(box.index);
26
+ const header = host.ownerDocument.createElement('div');
27
+ header.className = 'dx-page-header';
28
+ page.appendChild(header);
29
+ const content = host.ownerDocument.createElement('div');
30
+ content.className = 'dx-page-content';
31
+ content.style.paddingTop = `${dims.margins.topPx}px`;
32
+ content.style.paddingRight = `${dims.margins.rightPx}px`;
33
+ content.style.paddingBottom = `${dims.margins.bottomPx}px`;
34
+ content.style.paddingLeft = `${dims.margins.leftPx}px`;
35
+ page.appendChild(content);
36
+ const footer = host.ownerDocument.createElement('div');
37
+ footer.className = 'dx-page-footer';
38
+ page.appendChild(footer);
39
+ const pageNumber = host.ownerDocument.createElement('div');
40
+ pageNumber.className = 'dx-page-number';
41
+ pageNumber.textContent = String(box.index + 1);
42
+ page.appendChild(pageNumber);
43
+ // Render the blocks assigned to this page. Honor splitBefore (first block
44
+ // is the tail half of a paragraph split on the previous page) and
45
+ // splitAfter (last block is the head half being split here). For tables
46
+ // a SplitPoint may carry `tableSplit` — a row-index list — instead of a
47
+ // char offset; build a partial table from those indices and render that.
48
+ let modelOffset = box.modelFrom;
49
+ const lastIdx = box.blockIndices.length - 1;
50
+ for (let i = 0; i < box.blockIndices.length; i++) {
51
+ const blockIdx = box.blockIndices[i];
52
+ const block = doc.content.child(blockIdx);
53
+ let renderBlock = block;
54
+ const splitBeforeHit = i === 0 && box.splitBefore && box.splitBefore.blockIndex === blockIdx
55
+ ? box.splitBefore
56
+ : undefined;
57
+ const splitAfterHit = i === lastIdx && box.splitAfter && box.splitAfter.blockIndex === blockIdx
58
+ ? box.splitAfter
59
+ : undefined;
60
+ // Table-split takes precedence: if either side carries a tableSplit,
61
+ // assemble the partial table from the row index list. splitAfter wins
62
+ // when the same block is the only block on the page (the "head" of a
63
+ // continuing split — bodyRowIndices already accounts for that).
64
+ const tableInfo = splitAfterHit?.tableSplit ?? splitBeforeHit?.tableSplit;
65
+ if (tableInfo) {
66
+ renderBlock = buildPartialTable(block, tableInfo.headerRowIndices, tableInfo.bodyRowIndices);
67
+ }
68
+ else {
69
+ if (splitBeforeHit) {
70
+ renderBlock = block.cut(splitBeforeHit.charOffset, block.content.size);
71
+ }
72
+ if (splitAfterHit) {
73
+ // Cut against the original block — charOffset is in original
74
+ // content-coordinates regardless of any preceding splitBefore trim.
75
+ const from = splitBeforeHit ? splitBeforeHit.charOffset : 0;
76
+ renderBlock = block.cut(from, splitAfterHit.charOffset);
77
+ }
78
+ }
79
+ const blockEl = renderNode(host.ownerDocument, renderer, renderBlock, modelOffset);
80
+ blockEl.dataset.blockIndex = String(blockIdx);
81
+ if (splitBeforeHit) {
82
+ blockEl.dataset.splitContinuation = 'true';
83
+ }
84
+ if (splitAfterHit) {
85
+ blockEl.dataset.splitBefore = 'true';
86
+ }
87
+ content.appendChild(blockEl);
88
+ modelOffset += renderBlock.nodeSize;
89
+ }
90
+ host.appendChild(page);
91
+ }
92
+ }
93
+ //# sourceMappingURL=paginator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paginator.js","sourceRoot":"","sources":["../../src/view/paginator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { EditorView } from './editor-view.js';
2
+ /**
3
+ * Options for {@link printDocument}.
4
+ * - `pageSize`: when present, a temporary `<style data-dx-print-size>` tag
5
+ * is injected before printing and removed after, overriding any
6
+ * `@page { size: … }` rule from `print.css`/`print-a4.css`.
7
+ * - `applyClass`: when omitted (or `true`), the helper toggles a
8
+ * `.dx-printing` class on `<html>` while the print dialog is open so
9
+ * callers can fine-tune layout/CSS for the printing window.
10
+ */
11
+ export interface PrintOptions {
12
+ readonly pageSize?: {
13
+ width: number;
14
+ height: number;
15
+ unit?: 'in' | 'mm' | 'cm';
16
+ };
17
+ readonly applyClass?: boolean;
18
+ }
19
+ /**
20
+ * Trigger native print. Resolves AFTER the user dismisses the print
21
+ * dialog (`afterprint` event), or after a 500ms fallback for browsers
22
+ * that don't fire `afterprint` reliably (some Safari/iOS builds).
23
+ *
24
+ * - When `pageSize` is provided, injects a temporary `<style>` with
25
+ * a matching `@page` rule before printing and removes it after.
26
+ * - Adds `.dx-printing` class to `<html>` for the duration of the
27
+ * dialog (unless `applyClass: false`).
28
+ *
29
+ * Safe to call from SSR — resolves immediately when no `document` or
30
+ * `window` is available.
31
+ */
32
+ export declare function printDocument(view: EditorView, opts?: PrintOptions): Promise<void>;
33
+ /**
34
+ * Inject (or replace) a `<style data-dx-print-size>` tag setting the
35
+ * `@page` size. Returns a cleanup function that removes the tag.
36
+ *
37
+ * Only one `<style data-dx-print-size>` tag exists in `<head>` at a
38
+ * time — repeated calls replace the prior tag. Safe to call from SSR
39
+ * — returns a no-op cleanup when `document` is unavailable.
40
+ */
41
+ export declare function setPrintPageSize(width: number, height: number, unit?: 'in' | 'mm' | 'cm'): () => void;
42
+ //# sourceMappingURL=print.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print.d.ts","sourceRoot":"","sources":["../../src/view/print.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;KAAE,CAAA;IAChF,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAC9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCtF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,IAAI,GAAG,IAAI,GAAG,IAAW,GAC9B,MAAM,IAAI,CAQZ"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Trigger native print. Resolves AFTER the user dismisses the print
3
+ * dialog (`afterprint` event), or after a 500ms fallback for browsers
4
+ * that don't fire `afterprint` reliably (some Safari/iOS builds).
5
+ *
6
+ * - When `pageSize` is provided, injects a temporary `<style>` with
7
+ * a matching `@page` rule before printing and removes it after.
8
+ * - Adds `.dx-printing` class to `<html>` for the duration of the
9
+ * dialog (unless `applyClass: false`).
10
+ *
11
+ * Safe to call from SSR — resolves immediately when no `document` or
12
+ * `window` is available.
13
+ */
14
+ export function printDocument(view, opts = {}) {
15
+ const doc = view.dom.ownerDocument;
16
+ if (!doc)
17
+ return Promise.resolve();
18
+ const win = doc.defaultView;
19
+ if (!win)
20
+ return Promise.resolve();
21
+ let cleanupSize = null;
22
+ if (opts.pageSize) {
23
+ cleanupSize = setPrintPageSize(opts.pageSize.width, opts.pageSize.height, opts.pageSize.unit ?? 'in');
24
+ }
25
+ const applyClass = opts.applyClass !== false;
26
+ if (applyClass)
27
+ doc.documentElement.classList.add('dx-printing');
28
+ return new Promise((resolve) => {
29
+ let resolved = false;
30
+ const onDone = () => {
31
+ if (resolved)
32
+ return;
33
+ resolved = true;
34
+ if (applyClass)
35
+ doc.documentElement.classList.remove('dx-printing');
36
+ if (cleanupSize)
37
+ cleanupSize();
38
+ win.removeEventListener('afterprint', onDone);
39
+ resolve();
40
+ };
41
+ win.addEventListener('afterprint', onDone);
42
+ // Fallback for browsers that don't fire afterprint (some Safari/iOS).
43
+ setTimeout(onDone, 500);
44
+ try {
45
+ win.print();
46
+ }
47
+ catch {
48
+ onDone();
49
+ }
50
+ });
51
+ }
52
+ /**
53
+ * Inject (or replace) a `<style data-dx-print-size>` tag setting the
54
+ * `@page` size. Returns a cleanup function that removes the tag.
55
+ *
56
+ * Only one `<style data-dx-print-size>` tag exists in `<head>` at a
57
+ * time — repeated calls replace the prior tag. Safe to call from SSR
58
+ * — returns a no-op cleanup when `document` is unavailable.
59
+ */
60
+ export function setPrintPageSize(width, height, unit = 'in') {
61
+ if (typeof document === 'undefined')
62
+ return () => { };
63
+ document.querySelectorAll('style[data-dx-print-size]').forEach((el) => el.remove());
64
+ const style = document.createElement('style');
65
+ style.setAttribute('data-dx-print-size', '');
66
+ style.textContent = `@page { size: ${width}${unit} ${height}${unit}; margin: 0 }`;
67
+ document.head.appendChild(style);
68
+ return () => style.remove();
69
+ }
70
+ //# sourceMappingURL=print.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print.js","sourceRoot":"","sources":["../../src/view/print.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,IAAgB,EAAE,OAAqB,EAAE;IACrE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAA;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAClC,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAA;IAC3B,IAAI,CAAC,GAAG;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAElC,IAAI,WAAW,GAAwB,IAAI,CAAA;IAC3C,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,WAAW,GAAG,gBAAgB,CAC5B,IAAI,CAAC,QAAQ,CAAC,KAAK,EACnB,IAAI,CAAC,QAAQ,CAAC,MAAM,EACpB,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAC3B,CAAA;IACH,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,KAAK,KAAK,CAAA;IAC5C,IAAI,UAAU;QAAE,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;IAEhE,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,IAAI,QAAQ,GAAG,KAAK,CAAA;QACpB,MAAM,MAAM,GAAG,GAAS,EAAE;YACxB,IAAI,QAAQ;gBAAE,OAAM;YACpB,QAAQ,GAAG,IAAI,CAAA;YACf,IAAI,UAAU;gBAAE,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;YACnE,IAAI,WAAW;gBAAE,WAAW,EAAE,CAAA;YAC9B,GAAG,CAAC,mBAAmB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;YAC7C,OAAO,EAAE,CAAA;QACX,CAAC,CAAA;QACD,GAAG,CAAC,gBAAgB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;QAC1C,sEAAsE;QACtE,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QACvB,IAAI,CAAC;YACH,GAAG,CAAC,KAAK,EAAE,CAAA;QACb,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,EAAE,CAAA;QACV,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAa,EACb,MAAc,EACd,OAA2B,IAAI;IAE/B,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IACpD,QAAQ,CAAC,gBAAgB,CAAC,2BAA2B,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAA;IACnF,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;IAC7C,KAAK,CAAC,YAAY,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAA;IAC5C,KAAK,CAAC,WAAW,GAAG,iBAAiB,KAAK,GAAG,IAAI,IAAI,MAAM,GAAG,IAAI,eAAe,CAAA;IACjF,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAChC,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;AAC7B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { DxNode } from '../model/node.js';
2
+ import { type Renderer } from './renderer.js';
3
+ /**
4
+ * Reconcile the DOM children of `domRoot` so they represent `newDoc`'s content,
5
+ * starting from a DOM that already represents `oldDoc`'s content.
6
+ *
7
+ * Algorithm (v0.1):
8
+ * - If oldDoc === newDoc (reference equality, which happens whenever the
9
+ * immutable model wasn't touched): no-op.
10
+ * - Otherwise walk children in parallel; if a child differs, replace it
11
+ * wholesale (re-render the differing subtree). More sophisticated diffing
12
+ * (Levenshtein on child arrays, in-place updates for same-type nodes)
13
+ * lands in Phase 7 polish.
14
+ */
15
+ export declare function reconcile(domRoot: HTMLElement, oldDoc: DxNode, newDoc: DxNode, renderer: Renderer): void;
16
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/view/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAE9C,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AAEzD;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GACjB,IAAI,CAGN"}