@portone/docx-editor 0.2.1 → 0.4.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 (253) hide show
  1. package/CHANGELOG.md +155 -0
  2. package/CONTRIBUTING.md +5 -1
  3. package/dist/DocxEditor.d.ts +6 -0
  4. package/dist/DocxEditor.js +13 -29
  5. package/dist/core.d.ts +23 -8
  6. package/dist/core.js +9 -4
  7. package/dist/docx/cloning.d.ts +38 -0
  8. package/dist/docx/cloning.js +74 -0
  9. package/dist/docx/commentOnlyChange.d.ts +12 -7
  10. package/dist/docx/commentOnlyChange.js +9 -156
  11. package/dist/docx/comments/constants.d.ts +0 -1
  12. package/dist/docx/comments/constants.js +0 -2
  13. package/dist/docx/comments/grammar.d.ts +10 -4
  14. package/dist/docx/comments/grammar.js +12 -2
  15. package/dist/docx/comments/{verifying.d.ts → parts.d.ts} +26 -18
  16. package/dist/docx/comments/parts.js +279 -0
  17. package/dist/docx/comments/people.d.ts +11 -2
  18. package/dist/docx/comments/people.js +16 -92
  19. package/dist/docx/comments/policy.d.ts +7 -0
  20. package/dist/docx/comments/policy.js +43 -0
  21. package/dist/docx/comments/reading.js +8 -10
  22. package/dist/docx/comments/writing.d.ts +19 -7
  23. package/dist/docx/comments/writing.js +59 -112
  24. package/dist/docx/documentSettings.d.ts +7 -0
  25. package/dist/docx/documentSettings.js +10 -2
  26. package/dist/docx/exportDocx.d.ts +40 -5
  27. package/dist/docx/exportDocx.js +88 -74
  28. package/dist/docx/exportRefs.d.ts +5 -2
  29. package/dist/docx/exportRefs.js +3 -1
  30. package/dist/docx/fidelity.d.ts +43 -0
  31. package/dist/docx/fidelity.js +64 -0
  32. package/dist/docx/formatting/attrs.d.ts +45 -0
  33. package/dist/docx/formatting/attrs.js +86 -0
  34. package/dist/docx/formatting/context.d.ts +39 -0
  35. package/dist/docx/formatting/context.js +60 -0
  36. package/dist/docx/formatting/direct.d.ts +6 -5
  37. package/dist/docx/formatting/direct.js +52 -78
  38. package/dist/docx/formatting/resolve.d.ts +51 -0
  39. package/dist/docx/formatting/resolve.js +160 -0
  40. package/dist/docx/formatting/runProperties.d.ts +93 -0
  41. package/dist/docx/formatting/runProperties.js +316 -0
  42. package/dist/docx/formatting/styles.d.ts +25 -2
  43. package/dist/docx/formatting/styles.js +87 -6
  44. package/dist/docx/formatting/tabStops.js +7 -22
  45. package/dist/docx/formatting.d.ts +4 -1
  46. package/dist/docx/formatting.js +4 -1
  47. package/dist/docx/headersFooters.js +6 -13
  48. package/dist/docx/hyperlink.d.ts +14 -4
  49. package/dist/docx/hyperlink.js +4 -1
  50. package/dist/docx/identities.d.ts +67 -0
  51. package/dist/docx/identities.js +174 -0
  52. package/dist/docx/importDocx.d.ts +12 -1
  53. package/dist/docx/importDocx.js +90 -88
  54. package/dist/docx/importParagraph.d.ts +1 -1
  55. package/dist/docx/importParagraph.js +4 -3
  56. package/dist/docx/importTable.d.ts +2 -2
  57. package/dist/docx/importTable.js +69 -56
  58. package/dist/docx/invariants.d.ts +33 -0
  59. package/dist/docx/invariants.js +269 -0
  60. package/dist/docx/media.d.ts +6 -4
  61. package/dist/docx/media.js +6 -37
  62. package/dist/docx/newLists.d.ts +50 -0
  63. package/dist/docx/newLists.js +59 -0
  64. package/dist/docx/notes.js +3 -7
  65. package/dist/docx/numberingPlanner.d.ts +11 -0
  66. package/dist/docx/numberingPlanner.js +50 -0
  67. package/dist/docx/packageParts.d.ts +42 -0
  68. package/dist/docx/packageParts.js +135 -0
  69. package/dist/docx/pageGeometry.d.ts +2 -0
  70. package/dist/docx/pageGeometry.js +18 -9
  71. package/dist/docx/paraProps.d.ts +10 -22
  72. package/dist/docx/paraProps.js +47 -76
  73. package/dist/docx/partPlan.d.ts +36 -0
  74. package/dist/docx/partPlan.js +59 -0
  75. package/dist/docx/protectionPolicy.d.ts +127 -0
  76. package/dist/docx/protectionPolicy.js +169 -0
  77. package/dist/docx/relationships.d.ts +1 -1
  78. package/dist/docx/relationships.js +8 -13
  79. package/dist/docx/runProps.d.ts +9 -22
  80. package/dist/docx/runProps.js +15 -168
  81. package/dist/docx/scan.js +20 -52
  82. package/dist/docx/sdt.js +9 -34
  83. package/dist/docx/sdtProps.d.ts +8 -1
  84. package/dist/docx/sdtProps.js +10 -0
  85. package/dist/docx/serializeBlock.d.ts +2 -0
  86. package/dist/docx/serializeBlock.js +8 -5
  87. package/dist/docx/serializeTable.js +32 -15
  88. package/dist/docx/session.d.ts +42 -14
  89. package/dist/docx/session.js +53 -17
  90. package/dist/docx/tableFormatting/conditions.d.ts +76 -0
  91. package/dist/docx/tableFormatting/conditions.js +196 -0
  92. package/dist/docx/tableFormatting/editing.d.ts +7 -3
  93. package/dist/docx/tableFormatting/editing.js +111 -143
  94. package/dist/docx/tableFormatting/reading.d.ts +63 -23
  95. package/dist/docx/tableFormatting/reading.js +132 -38
  96. package/dist/docx/tableFormatting.d.ts +1 -0
  97. package/dist/docx/tableFormatting.js +1 -0
  98. package/dist/docx/tableTemplate.js +30 -19
  99. package/dist/download.d.ts +8 -5
  100. package/dist/download.js +2 -0
  101. package/dist/editor/clipboard/inlineFormatting.js +19 -30
  102. package/dist/editor/commands/comments/editing.d.ts +6 -2
  103. package/dist/editor/commands/comments/editing.js +19 -31
  104. package/dist/editor/commands/exportQueries.d.ts +15 -0
  105. package/dist/editor/commands/exportQueries.js +14 -0
  106. package/dist/editor/commands/fidelityQueries.d.ts +12 -0
  107. package/dist/editor/commands/fidelityQueries.js +8 -0
  108. package/dist/editor/commands/formatting/editing.d.ts +2 -2
  109. package/dist/editor/commands/formatting/editing.js +26 -108
  110. package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
  111. package/dist/editor/commands/formatting/propertyCommands.js +108 -0
  112. package/dist/editor/commands/formatting/shared.d.ts +3 -3
  113. package/dist/editor/commands/formatting/shared.js +5 -2
  114. package/dist/editor/commands/indentCommands.js +5 -4
  115. package/dist/editor/commands/index.d.ts +11 -0
  116. package/dist/editor/commands/index.js +5 -0
  117. package/dist/editor/commands/linkCommands.js +5 -6
  118. package/dist/editor/commands/listCommands.d.ts +6 -3
  119. package/dist/editor/commands/listCommands.js +73 -30
  120. package/dist/editor/commands/lockCommands.d.ts +7 -1
  121. package/dist/editor/commands/lockCommands.js +35 -46
  122. package/dist/editor/commands/paragraphCommands.js +33 -31
  123. package/dist/editor/commands/spacingCommands.js +1 -1
  124. package/dist/editor/createEditor.d.ts +17 -29
  125. package/dist/editor/createEditor.js +58 -58
  126. package/dist/editor/documentStyles.d.ts +11 -35
  127. package/dist/editor/documentStyles.js +9 -52
  128. package/dist/editor/editorDocument.d.ts +57 -0
  129. package/dist/editor/editorDocument.js +86 -0
  130. package/dist/editor/externalClipboard.d.ts +13 -2
  131. package/dist/editor/externalClipboard.js +76 -75
  132. package/dist/editor/insertTable.js +4 -3
  133. package/dist/editor/paragraphEdits.d.ts +27 -19
  134. package/dist/editor/paragraphEdits.js +18 -19
  135. package/dist/editor/paragraphPlacement.d.ts +11 -0
  136. package/dist/editor/paragraphPlacement.js +18 -0
  137. package/dist/editor/plugins/displayDerivation.d.ts +47 -0
  138. package/dist/editor/plugins/displayDerivation.js +78 -0
  139. package/dist/editor/plugins/imagePaste.js +11 -7
  140. package/dist/editor/plugins/keymap.js +18 -3
  141. package/dist/editor/plugins/numberingDecorations.d.ts +14 -14
  142. package/dist/editor/plugins/numberingDecorations.js +50 -19
  143. package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
  144. package/dist/editor/plugins/paragraphDisplay.js +57 -0
  145. package/dist/editor/plugins/tabLayout.js +1 -1
  146. package/dist/editor/plugins/tableDisplay.d.ts +6 -0
  147. package/dist/editor/plugins/tableDisplay.js +30 -0
  148. package/dist/index.d.ts +2 -0
  149. package/dist/model/format.d.ts +80 -8
  150. package/dist/model/format.js +100 -22
  151. package/dist/model/tabStops.d.ts +9 -0
  152. package/dist/model/tabStops.js +18 -0
  153. package/dist/numbering/listRegistry.d.ts +37 -0
  154. package/dist/numbering/listRegistry.js +112 -0
  155. package/dist/numbering/listTemplate.d.ts +26 -17
  156. package/dist/numbering/listTemplate.js +88 -25
  157. package/dist/numbering/markers.d.ts +15 -6
  158. package/dist/numbering/markers.js +26 -59
  159. package/dist/numbering/parseNumbering.d.ts +84 -6
  160. package/dist/numbering/parseNumbering.js +131 -44
  161. package/dist/numbering/spellers.d.ts +15 -0
  162. package/dist/numbering/spellers.js +96 -0
  163. package/dist/numbering/writeNumbering.d.ts +8 -7
  164. package/dist/numbering/writeNumbering.js +28 -39
  165. package/dist/ooxml/childOrder.d.ts +34 -0
  166. package/dist/ooxml/childOrder.js +496 -0
  167. package/dist/ooxml/conformance.d.ts +28 -0
  168. package/dist/ooxml/conformance.js +20 -0
  169. package/dist/ooxml/element.d.ts +24 -11
  170. package/dist/ooxml/element.js +31 -12
  171. package/dist/ooxml/errors.d.ts +6 -5
  172. package/dist/ooxml/image.d.ts +4 -0
  173. package/dist/ooxml/image.js +2 -5
  174. package/dist/ooxml/names.d.ts +9 -0
  175. package/dist/ooxml/names.js +8 -1
  176. package/dist/ooxml/partSplice.d.ts +67 -0
  177. package/dist/ooxml/partSplice.js +176 -0
  178. package/dist/ooxml/props.d.ts +112 -0
  179. package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
  180. package/dist/ooxml/simpleTypes.d.ts +103 -0
  181. package/dist/ooxml/simpleTypes.js +182 -0
  182. package/dist/ooxml/tabStops.js +8 -27
  183. package/dist/ooxml/tagScan.d.ts +34 -0
  184. package/dist/ooxml/tagScan.js +108 -0
  185. package/dist/ooxml/units.d.ts +25 -13
  186. package/dist/ooxml/units.js +65 -31
  187. package/dist/ooxml/xml.d.ts +35 -15
  188. package/dist/ooxml/xml.js +43 -11
  189. package/dist/page/PageGuides.d.ts +1 -1
  190. package/dist/page/PageGuides.js +0 -13
  191. package/dist/page/blockKinds.d.ts +61 -0
  192. package/dist/page/blockKinds.js +11 -0
  193. package/dist/page/kinds/index.d.ts +6 -0
  194. package/dist/page/kinds/index.js +10 -0
  195. package/dist/page/kinds/paragraphKind.d.ts +10 -0
  196. package/dist/page/kinds/paragraphKind.js +71 -0
  197. package/dist/page/kinds/tableKind.d.ts +10 -0
  198. package/dist/page/kinds/tableKind.js +178 -0
  199. package/dist/page/measureBlocks.d.ts +3 -14
  200. package/dist/page/measureBlocks.js +24 -45
  201. package/dist/page/pageDecorations.d.ts +27 -44
  202. package/dist/page/pageDecorations.js +70 -152
  203. package/dist/page/pageLayout.d.ts +2 -29
  204. package/dist/page/pageLayout.js +39 -16
  205. package/dist/page/usePageLayout.d.ts +2 -24
  206. package/dist/page/usePageLayout.js +5 -48
  207. package/dist/schema/attrRoles.d.ts +25 -18
  208. package/dist/schema/attrRoles.js +110 -68
  209. package/dist/schema/displayDerivation.d.ts +82 -0
  210. package/dist/schema/displayDerivation.js +130 -0
  211. package/dist/schema/docxSchema.d.ts +3 -0
  212. package/dist/schema/docxSchema.js +58 -17
  213. package/dist/schema/editGuard.d.ts +1 -1
  214. package/dist/schema/guards.d.ts +37 -14
  215. package/dist/schema/guards.js +29 -3
  216. package/dist/schema/index.d.ts +2 -0
  217. package/dist/schema/index.js +2 -0
  218. package/dist/schema/locks.d.ts +11 -44
  219. package/dist/schema/locks.js +0 -9
  220. package/dist/schema/preservedGuards.d.ts +26 -6
  221. package/dist/schema/preservedGuards.js +31 -1
  222. package/dist/schema/protection.d.ts +7 -1
  223. package/dist/schema/protection.js +2 -1
  224. package/dist/schema/sourceEquality.d.ts +1 -9
  225. package/dist/schema/sourceEquality.js +1 -27
  226. package/dist/styles/classNames.d.ts +13 -2
  227. package/dist/styles/classNames.js +13 -2
  228. package/dist/styles/inlineStyle.js +15 -6
  229. package/dist/styles.css +16 -18
  230. package/dist/table/cellFormatting.d.ts +8 -1
  231. package/dist/table/cellFormatting.js +11 -20
  232. package/dist/table/commands.js +20 -18
  233. package/dist/table/format.d.ts +3 -0
  234. package/dist/table/format.js +3 -9
  235. package/dist/table/gridBorders.d.ts +24 -30
  236. package/dist/table/gridBorders.js +35 -59
  237. package/dist/table/merge.d.ts +2 -6
  238. package/dist/table/merge.js +5 -5
  239. package/package.json +7 -3
  240. package/dist/docx/comments/contentTypes.d.ts +0 -7
  241. package/dist/docx/comments/contentTypes.js +0 -38
  242. package/dist/docx/comments/verifying.js +0 -206
  243. package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
  244. package/dist/docx/formatting/effectiveParagraph.js +0 -81
  245. package/dist/docx/propsXml.d.ts +0 -67
  246. package/dist/docx/uniqueControls.d.ts +0 -14
  247. package/dist/docx/uniqueControls.js +0 -62
  248. package/dist/editor/plugins/commentReservations.d.ts +0 -5
  249. package/dist/editor/plugins/commentReservations.js +0 -26
  250. package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
  251. package/dist/editor/plugins/styledParagraphs.js +0 -65
  252. package/dist/page/tableMeasurements.d.ts +0 -18
  253. package/dist/page/tableMeasurements.js +0 -119
@@ -0,0 +1,71 @@
1
+ // src/page/kinds/paragraphKind.ts
2
+ import { Decoration } from "prosemirror-view";
3
+ import { toParagraphFormat } from "../../model/format.js";
4
+ import { docxSchema, isPageBreak } from "../../schema/index.js";
5
+ import { editorAttributes } from "../../styles/classNames.js";
6
+ var PAGE_BREAK_BR = `br[${editorAttributes.breakType}="page"]`;
7
+ var BREAK_SPACE = `[${editorAttributes.pageBreakSpace}]`;
8
+ function spaceStyle(height) {
9
+ return `display:block;height:${height}px`;
10
+ }
11
+ function isPageBreakNode(node) {
12
+ return node?.type === docxSchema.nodes.hardBreak && isPageBreak(node.attrs.brAttrs);
13
+ }
14
+ function pageBreaksIn(block, blockPos) {
15
+ const found = [];
16
+ if (block.type !== docxSchema.nodes.paragraph) return found;
17
+ block.forEach((child, offset) => {
18
+ if (isPageBreakNode(child)) {
19
+ found.push({ at: blockPos + 1 + offset, size: child.nodeSize });
20
+ }
21
+ });
22
+ return found;
23
+ }
24
+ var paragraphKind = {
25
+ name: "paragraph",
26
+ matches: () => true,
27
+ measure({ node, pos, dom, sheetY, top, scale }) {
28
+ const breaks = pageBreaksIn(node, pos);
29
+ const candidates = [];
30
+ let appliedHeight = 0;
31
+ dom.querySelectorAll(BREAK_SPACE).forEach((space, index) => {
32
+ const box = space.getBoundingClientRect();
33
+ const found = breaks.at(index);
34
+ if (found) {
35
+ candidates.push({
36
+ at: found.at,
37
+ offset: sheetY(box.top) - appliedHeight - top,
38
+ forced: true,
39
+ repeatHeight: 0
40
+ });
41
+ }
42
+ appliedHeight += box.height / scale;
43
+ });
44
+ return {
45
+ candidates,
46
+ minFirstPiece: candidates[0]?.offset ?? dom.getBoundingClientRect().height / scale - appliedHeight,
47
+ // A break with no space of its own sits somewhere the space could not be opened. Those
48
+ // still start a new page, but only after the whole block
49
+ breakAfter: dom.querySelectorAll(PAGE_BREAK_BR).length > candidates.length,
50
+ appliedHeight,
51
+ keepWithNext: toParagraphFormat(node.attrs.format)?.keepNext === true
52
+ };
53
+ },
54
+ holdsCut: (doc, at) => isPageBreakNode(doc.nodeAt(at)),
55
+ decorate(pos, node, cuts, into) {
56
+ const heights = new Map(cuts.map((cut) => [cut.at, cut.height]));
57
+ for (const { at, size } of pageBreaksIn(node, pos)) {
58
+ const height = heights.get(at) ?? 0;
59
+ into.push(
60
+ Decoration.inline(at, at + size, {
61
+ nodeName: "span",
62
+ style: spaceStyle(height),
63
+ [editorAttributes.pageBreakSpace]: `${height}`
64
+ })
65
+ );
66
+ }
67
+ }
68
+ };
69
+ export {
70
+ paragraphKind
71
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The kind of a table: it is parted between rows, and a continued page opens a spacer row and
3
+ * repeats the headers the table opens with.
4
+ *
5
+ * Both sides read the table as it stands on screen without treating the rows this very engine
6
+ * drew as content: the measurement takes their heights back off, and the projection is derived
7
+ * again from the document, so an edit to a header row redraws it with nothing measured anew.
8
+ */
9
+ import type { BlockKind } from "../blockKinds";
10
+ export declare const tableKind: BlockKind;
@@ -0,0 +1,178 @@
1
+ // src/page/kinds/tableKind.ts
2
+ import { Decoration } from "prosemirror-view";
3
+ import { toRowFormat } from "../../model/format.js";
4
+ import { editorAttributes } from "../../styles/classNames.js";
5
+ var PAGE_BREAK_BR = `br[${editorAttributes.breakType}="page"]`;
6
+ function span(value) {
7
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : 1;
8
+ }
9
+ function paginationRows(table) {
10
+ return Array.from(
11
+ table.querySelectorAll(
12
+ `[${editorAttributes.tablePageSpace}],[${editorAttributes.tableRepeatedHeader}]`
13
+ )
14
+ );
15
+ }
16
+ function before(candidate, row) {
17
+ return Boolean(
18
+ candidate.compareDocumentPosition(row) & Node.DOCUMENT_POSITION_FOLLOWING
19
+ );
20
+ }
21
+ function rowEntries(view, tableNode, tablePos, tableDom, appliedRows, scale) {
22
+ const entries = [];
23
+ const tableTop = tableDom.getBoundingClientRect().top;
24
+ tableNode.forEach((row, offset) => {
25
+ const pos = tablePos + 1 + offset;
26
+ const dom = view.nodeDOM(pos);
27
+ if (!(dom instanceof HTMLElement)) return;
28
+ const rect = dom.getBoundingClientRect();
29
+ const appliedBefore = appliedRows.reduce(
30
+ (total, candidate) => total + (before(candidate, dom) ? candidate.getBoundingClientRect().height / scale : 0),
31
+ 0
32
+ );
33
+ entries.push({
34
+ node: row,
35
+ pos,
36
+ top: (rect.top - tableTop) / scale - appliedBefore,
37
+ height: rect.height / scale
38
+ });
39
+ });
40
+ return entries;
41
+ }
42
+ function unsafeBoundaries(rows) {
43
+ const unsafe = /* @__PURE__ */ new Set();
44
+ rows.forEach((row, rowIndex) => {
45
+ row.node.forEach((cell) => {
46
+ const bottom = Math.min(rows.length, rowIndex + span(cell.attrs.rowspan));
47
+ for (let boundary = rowIndex + 1; boundary < bottom; boundary += 1) {
48
+ unsafe.add(boundary);
49
+ }
50
+ });
51
+ });
52
+ return unsafe;
53
+ }
54
+ function repeatsHeader(row) {
55
+ return toRowFormat(row?.attrs.format)?.repeatHeader === true;
56
+ }
57
+ function headerCount(rows) {
58
+ let count = 0;
59
+ while (count < rows.length && repeatsHeader(rows[count]?.node)) {
60
+ count += 1;
61
+ }
62
+ return count;
63
+ }
64
+ function headerRowsOf(tableNode, tablePos) {
65
+ const found = [];
66
+ let offset = 0;
67
+ for (let index = 0; index < tableNode.childCount; index += 1) {
68
+ const row = tableNode.child(index);
69
+ if (!repeatsHeader(row)) break;
70
+ found.push(tablePos + 1 + offset);
71
+ offset += row.nodeSize;
72
+ }
73
+ return found;
74
+ }
75
+ function columnCount(tableNode) {
76
+ const grid = tableNode.attrs.gridCols;
77
+ if (Array.isArray(grid) && grid.length > 0) return grid.length;
78
+ const first = tableNode.firstChild;
79
+ if (!first) return 1;
80
+ let columns = 0;
81
+ first.forEach((cell) => {
82
+ columns += span(cell.attrs.colspan);
83
+ });
84
+ return Math.max(1, columns);
85
+ }
86
+ function tableSpace(height, columns) {
87
+ const row = document.createElement("tr");
88
+ row.setAttribute(editorAttributes.tablePageSpace, `${height}`);
89
+ row.setAttribute("aria-hidden", "true");
90
+ row.setAttribute("contenteditable", "false");
91
+ row.style.height = `${height}px`;
92
+ const cell = document.createElement("td");
93
+ cell.colSpan = columns;
94
+ cell.style.height = `${height}px`;
95
+ row.append(cell);
96
+ return row;
97
+ }
98
+ function repeatedHeader(view, rowPos) {
99
+ const source = view.nodeDOM(rowPos);
100
+ const row = source instanceof HTMLElement && source.tagName === "TR" ? source.cloneNode(true) : document.createElement("tr");
101
+ row.setAttribute(editorAttributes.tableRepeatedHeader, "");
102
+ row.setAttribute("aria-hidden", "true");
103
+ row.setAttribute("contenteditable", "false");
104
+ row.removeAttribute("id");
105
+ row.querySelectorAll("[id]").forEach((element) => {
106
+ element.removeAttribute("id");
107
+ });
108
+ return row;
109
+ }
110
+ var tableKind = {
111
+ name: "table",
112
+ matches: (node) => node.type.spec.tableRole === "table",
113
+ measure({ view, node, pos, dom, scale }) {
114
+ const appliedRows = paginationRows(dom);
115
+ const rows = rowEntries(view, node, pos, dom, appliedRows, scale);
116
+ const headers = headerCount(rows);
117
+ const unsafe = unsafeBoundaries(rows);
118
+ const headerRows = rows.slice(0, headers);
119
+ const repeatHeaderHeight = headerRows.reduce(
120
+ (total, row) => total + row.height,
121
+ 0
122
+ );
123
+ const candidates = [];
124
+ for (let rowIndex = Math.max(1, headers); rowIndex < rows.length; rowIndex += 1) {
125
+ const row = rows[rowIndex];
126
+ if (row && !unsafe.has(rowIndex)) {
127
+ candidates.push({
128
+ at: row.pos,
129
+ offset: row.top,
130
+ forced: false,
131
+ repeatHeight: repeatHeaderHeight
132
+ });
133
+ }
134
+ }
135
+ const firstBodyBoundary = candidates.find(
136
+ (candidate) => candidate.offset > repeatHeaderHeight + 0.5
137
+ );
138
+ const appliedHeight = appliedRows.reduce(
139
+ (total, row) => total + row.getBoundingClientRect().height / scale,
140
+ 0
141
+ );
142
+ return {
143
+ candidates,
144
+ // The smallest useful first piece: the headers followed by one body row group
145
+ minFirstPiece: firstBodyBoundary?.offset ?? dom.getBoundingClientRect().height / scale - appliedHeight,
146
+ // A space cannot be opened inside a cell, so a break standing in one is answered after the
147
+ // whole table
148
+ breakAfter: dom.querySelectorAll(PAGE_BREAK_BR).length > 0,
149
+ appliedHeight
150
+ };
151
+ },
152
+ holdsCut: (doc, at) => doc.nodeAt(at)?.type.spec.tableRole === "row",
153
+ decorate(pos, node, cuts, into) {
154
+ if (cuts.length === 0) return;
155
+ const headerRows = headerRowsOf(node, pos);
156
+ const columns = columnCount(node);
157
+ for (const cut of cuts) {
158
+ into.push(
159
+ Decoration.widget(cut.at, () => tableSpace(cut.height, columns), {
160
+ key: `table-page-space-${cut.at}-${cut.height}-${columns}`,
161
+ side: -100
162
+ })
163
+ );
164
+ headerRows.forEach((rowPos, headerIndex) => {
165
+ into.push(
166
+ // No `key`: a keyed widget is held to be the same one and left alone, and this one is a
167
+ // copy of a row that the very edit rebuilding these decorations may have just changed
168
+ Decoration.widget(cut.at, (view) => repeatedHeader(view, rowPos), {
169
+ side: -90 + headerIndex
170
+ })
171
+ );
172
+ });
173
+ }
174
+ }
175
+ };
176
+ export {
177
+ tableKind
178
+ };
@@ -2,21 +2,15 @@
2
2
  * Measures the sheet as drawn on screen: the height of each body block, the gap above it, and
3
3
  * where the page breaks inside it stand, with nothing computed line by line.
4
4
  *
5
- * Every place a block may be parted at is read as a break candidate (`page/blockKinds`), whatever
6
- * shape of block it is: a page break for a paragraph, a safe row boundary for a table.
5
+ * Every place a block may be parted at is read as a break candidate (`page/blockKinds`) by the
6
+ * block's own kind (`page/kinds`), so this pass names no shape of block itself.
7
7
  * The engine's own marks are taken back off as they are read, so a block already pushed and a
8
8
  * break already given its space read as they would with neither applied. A measurement that read
9
9
  * them in would add to what is already there, and the layout would creep on every pass.
10
10
  * Where there is no layout (in tests) everything is 0, so the result is a single page.
11
11
  */
12
12
  import type { EditorView } from "prosemirror-view";
13
- import type { MeasuredBlock } from "./blockKinds";
14
- /** What a table continuation still needs from the measurement to be drawn */
15
- export interface TableHeaderProjection {
16
- headerRows: readonly number[];
17
- headerSignature: string;
18
- columns: number;
19
- }
13
+ import { type MeasuredBlock } from "./blockKinds";
20
14
  /**
21
15
  * The measurements taken in order to draw the page overlay. Positions are relative to
22
16
  * the overlay box
@@ -29,10 +23,5 @@ export interface SheetMeasure {
29
23
  contentTop: number;
30
24
  contentBottom: number;
31
25
  blocks: MeasuredBlock[];
32
- /**
33
- * The header facts of every table block, by the table's position, for the adapter that turns
34
- * cuts back into table continuations (`page/usePageLayout`)
35
- */
36
- tables: ReadonlyMap<number, TableHeaderProjection>;
37
26
  }
38
27
  export declare function measureSheet(view: EditorView, layer: HTMLElement): SheetMeasure;
@@ -1,9 +1,7 @@
1
1
  // src/page/measureBlocks.ts
2
2
  import { editorAttributes } from "../styles/classNames.js";
3
- import { pageBreaksIn } from "./pageDecorations.js";
4
- import { measureTable } from "./tableMeasurements.js";
5
- var PAGE_BREAK_BR = `br[${editorAttributes.breakType}="page"]`;
6
- var BREAK_SPACE = `[${editorAttributes.pageBreakSpace}]`;
3
+ import { blockKindFor } from "./blockKinds.js";
4
+ import { blockKindsOf } from "./pageDecorations.js";
7
5
  function pixels(value) {
8
6
  const parsed = Number.parseFloat(value);
9
7
  return Number.isFinite(parsed) ? parsed : 0;
@@ -17,17 +15,14 @@ function appliedPush(element) {
17
15
  }
18
16
  function drawnBlocks(view) {
19
17
  const found = [];
20
- view.state.doc.forEach((_node, offset) => {
18
+ view.state.doc.forEach((node, offset) => {
21
19
  const dom = view.nodeDOM(offset);
22
20
  if (dom instanceof HTMLElement && dom.getBoundingClientRect().height > 0) {
23
- found.push({ pos: offset, dom });
21
+ found.push({ node, pos: offset, dom });
24
22
  }
25
23
  });
26
24
  return found;
27
25
  }
28
- function breakWithoutSpace(dom, spaces) {
29
- return dom.querySelectorAll(PAGE_BREAK_BR).length > spaces;
30
- }
31
26
  function measureSheet(view, layer) {
32
27
  const sheet = view.dom;
33
28
  const sheetRect = sheet.getBoundingClientRect();
@@ -37,51 +32,36 @@ function measureSheet(view, layer) {
37
32
  const contentTop = pixels(style.paddingTop);
38
33
  const contentBottom = pixels(style.paddingBottom);
39
34
  const sheetY = (viewportY) => (viewportY - sheetRect.top) / scale;
35
+ const kinds = blockKindsOf(view.state);
40
36
  const blocks = [];
41
- const tables = /* @__PURE__ */ new Map();
42
37
  let previousBottom = contentTop;
43
38
  let applied = 0;
44
- for (const { pos, dom } of drawnBlocks(view)) {
45
- const node = view.state.doc.nodeAt(pos);
39
+ for (const { node, pos, dom } of drawnBlocks(view)) {
46
40
  const rect = dom.getBoundingClientRect();
47
41
  applied += appliedPush(dom);
48
- const top = sheetY(rect.top) - applied;
49
- const measuredTable = node ? measureTable(view, node, pos, dom, scale) : null;
50
- const breaks = node ? pageBreaksIn(node, pos) : [];
51
- const spaces = Array.from(dom.querySelectorAll(BREAK_SPACE));
52
- const forced = [];
53
- spaces.forEach((space, index) => {
54
- const box = space.getBoundingClientRect();
55
- const found = breaks.at(index);
56
- if (found) {
57
- forced.push({
58
- at: found.at,
59
- offset: sheetY(box.top) - applied - top,
60
- forced: true,
61
- repeatHeight: 0
62
- });
63
- }
64
- applied += box.height / scale;
42
+ const above = applied;
43
+ const blockY = (viewportY) => sheetY(viewportY) - above;
44
+ const top = blockY(rect.top);
45
+ const measured = blockKindFor(kinds, node).measure({
46
+ view,
47
+ node,
48
+ pos,
49
+ dom,
50
+ sheetY: blockY,
51
+ top,
52
+ scale
65
53
  });
66
- applied += measuredTable?.appliedHeight ?? 0;
54
+ applied += measured.appliedHeight;
67
55
  const bottom = sheetY(rect.bottom) - applied;
68
- const height = bottom - top;
69
- if (measuredTable) {
70
- tables.set(pos, {
71
- headerRows: measuredTable.headerRows,
72
- headerSignature: measuredTable.headerSignature,
73
- columns: measuredTable.columns
74
- });
75
- }
76
56
  blocks.push({
77
57
  pos,
78
58
  gap: top - previousBottom,
79
- height,
59
+ height: bottom - top,
80
60
  breakBefore: dom.hasAttribute(editorAttributes.pageBreakBefore),
81
- breakAfter: breakWithoutSpace(dom, spaces.length),
82
- // A space is never opened inside a table, so at most one of the two lists holds anything
83
- candidates: [...forced, ...measuredTable?.candidates ?? []],
84
- minFirstPiece: measuredTable?.minFirstPiece ?? forced[0]?.offset ?? height
61
+ breakAfter: measured.breakAfter,
62
+ candidates: measured.candidates,
63
+ minFirstPiece: measured.minFirstPiece,
64
+ keepWithNext: measured.keepWithNext ?? false
85
65
  });
86
66
  previousBottom = bottom;
87
67
  }
@@ -91,8 +71,7 @@ function measureSheet(view, layer) {
91
71
  width: sheetRect.width / scale,
92
72
  contentTop,
93
73
  contentBottom,
94
- blocks,
95
- tables
74
+ blocks
96
75
  };
97
76
  }
98
77
  export {
@@ -1,52 +1,35 @@
1
1
  /**
2
- * Decorations that move content to the next page: block pushes, page-break spaces, and table
3
- * continuation rows.
2
+ * Decorations that move content to the next page: the push above a block, and whatever the block's
3
+ * own kind draws the cuts inside it as (`page/kinds`).
4
4
  *
5
- * The document model is left untouched, so no trace of them is left in
6
- * the exported XML or in the edit history.
5
+ * The kinds the editor was built with are held here, so the measurement and the decorations read
6
+ * one registry and a block is measured by the same kind that draws it.
7
+ * The document model is left untouched, so no trace of any of it is left in the exported XML or
8
+ * in the edit history.
7
9
  */
8
- import type { Node as PMNode } from "prosemirror-model";
9
- import { Plugin } from "prosemirror-state";
10
+ import { type EditorState, Plugin } from "prosemirror-state";
10
11
  import { DecorationSet, type EditorView } from "prosemirror-view";
11
- import type { BlockPush, BreakSpace, TableContinuation } from "./pageLayout";
12
- /**
13
- * One break's space while the document changes under it.
14
- *
15
- * The layout counts breaks inside the block it measured (`page/pageLayout`), and an edit anywhere
16
- * before a break shifts that count, so what is kept here is the position of the `br` the space
17
- * belongs to: a position maps through an edit, an ordinal does not.
18
- */
19
- interface SpaceMark {
20
- /** Where the `br` this space is put on stands */
21
- at: number;
22
- height: number;
23
- }
24
- interface PageMarks {
12
+ import { type BlockKind, type PageCut } from "./blockKinds";
13
+ import type { BlockPush } from "./pageLayout";
14
+ /** Everything one measurement has to say about the page (`page/pageLayout`) */
15
+ export interface PageMarksInput {
25
16
  pushes: readonly BlockPush[];
26
- spaces: readonly SpaceMark[];
27
- tableContinuations: readonly TableContinuation[];
28
- decorations: DecorationSet;
17
+ /**
18
+ * Where the layout parted a block, keyed by the position the continued piece starts at.
19
+ *
20
+ * The layout counts within the block it measured, and an edit anywhere before a cut shifts that
21
+ * count, so what is kept here is a position: a position maps through an edit, an ordinal does
22
+ * not.
23
+ */
24
+ cuts: readonly PageCut[];
29
25
  }
30
- /** One page break inside a block, where it stands and how much room the `br` itself takes */
31
- interface BreakAt {
32
- at: number;
33
- size: number;
26
+ interface PageMarks extends PageMarksInput {
27
+ kinds: readonly BlockKind[];
28
+ decorations: DecorationSet;
34
29
  }
35
- /**
36
- * Every page break inside this block, in document order.
37
- * A space is put on the breaks of a top-level paragraph alone: inside a table cell it would grow
38
- * the cell rather than the page, so a break there is left to the whole-block rule in
39
- * `page/measureBlocks`, and none is found here.
40
- *
41
- * The measurement reads the same list to pair each space element it finds with the break it
42
- * belongs to (`page/measureBlocks`).
43
- */
44
- export declare function pageBreaksIn(block: PMNode, blockPos: number): BreakAt[];
45
- export declare function pageDecorations(): Plugin<PageMarks>;
46
- /** Does nothing when the same values are already applied */
47
- export declare function setPagePushes(view: EditorView, pushes: readonly BlockPush[]): void;
48
- /** Does nothing when the same values are already applied */
49
- export declare function setPageBreakSpaces(view: EditorView, spaces: readonly BreakSpace[]): void;
50
- /** Does nothing when the same table continuations are already applied */
51
- export declare function setTableContinuations(view: EditorView, continuations: readonly TableContinuation[]): void;
30
+ export declare function pageDecorations(kinds?: readonly BlockKind[]): Plugin<PageMarks>;
31
+ /** The kinds the editor was built with, which the measurement reads to match them */
32
+ export declare function blockKindsOf(state: EditorState): readonly BlockKind[];
33
+ /** One transaction, or none when the same marks are already applied */
34
+ export declare function setPageMarks(view: EditorView, next: PageMarksInput): void;
52
35
  export {};