@docen/docx 0.3.1 → 0.3.3

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 (114) hide show
  1. package/dist/converters/docx.d.mts +220 -1
  2. package/dist/converters/docx.mjs +1352 -1
  3. package/dist/converters/html.d.mts +28 -1
  4. package/dist/converters/html.mjs +103 -1
  5. package/dist/converters/markdown.d.mts +12 -1
  6. package/dist/converters/markdown.mjs +17 -1
  7. package/dist/converters/patch.d.mts +52 -1
  8. package/dist/converters/patch.mjs +35 -1
  9. package/dist/converters/prepare.d.mts +62 -1
  10. package/dist/converters/prepare.mjs +121 -1
  11. package/dist/converters/styles.d.mts +91 -2
  12. package/dist/converters/styles.mjs +308 -2
  13. package/dist/core-B8ba_FNi.mjs +717 -0
  14. package/dist/core-DRaLI8nd.d.mts +203 -0
  15. package/dist/core.d.mts +1 -1
  16. package/dist/core.mjs +1 -1
  17. package/dist/document-Cws7XTYL.d.mts +28 -0
  18. package/dist/editor.d.mts +20 -1
  19. package/dist/editor.mjs +20 -1
  20. package/dist/extensions/blockquote.d.mts +1 -1
  21. package/dist/extensions/blockquote.mjs +30 -2
  22. package/dist/extensions/code-block.d.mts +1 -1
  23. package/dist/extensions/code-block.mjs +22 -1
  24. package/dist/extensions/column-break.d.mts +1 -1
  25. package/dist/extensions/column-break.mjs +1 -1
  26. package/dist/extensions/details.d.mts +1 -1
  27. package/dist/extensions/details.mjs +17 -2
  28. package/dist/extensions/document.d.mts +1 -1
  29. package/dist/extensions/document.mjs +45 -1
  30. package/dist/extensions/extensions.d.mts +4 -5
  31. package/dist/extensions/extensions.mjs +13 -14
  32. package/dist/extensions/formatting-marks.d.mts +7 -1
  33. package/dist/extensions/formatting-marks.mjs +1 -1
  34. package/dist/extensions/heading.mjs +187 -1
  35. package/dist/extensions/image.d.mts +1 -1
  36. package/dist/extensions/image.mjs +395 -1
  37. package/dist/extensions/index.d.mts +4 -3
  38. package/dist/extensions/index.mjs +4 -3
  39. package/dist/extensions/mention.d.mts +1 -1
  40. package/dist/extensions/mention.mjs +43 -2
  41. package/dist/extensions/ordered-list.d.mts +1 -1
  42. package/dist/extensions/ordered-list.mjs +40 -2
  43. package/dist/extensions/page-break.d.mts +1 -33
  44. package/dist/extensions/page-break.mjs +1 -1
  45. package/dist/extensions/paragraph.mjs +145 -1
  46. package/dist/extensions/passthrough.d.mts +1 -1
  47. package/dist/extensions/passthrough.mjs +1 -1
  48. package/dist/extensions/section-break.d.mts +19 -2
  49. package/dist/extensions/section-break.mjs +1 -1
  50. package/dist/extensions/strike.mjs +45 -1
  51. package/dist/extensions/table-cell.mjs +106 -1
  52. package/dist/extensions/table-header.mjs +106 -1
  53. package/dist/extensions/table-row.mjs +78 -1
  54. package/dist/extensions/table.mjs +154 -1
  55. package/dist/extensions/task-item.d.mts +1 -1
  56. package/dist/extensions/task-item.mjs +36 -2
  57. package/dist/extensions/text-style.mjs +145 -1
  58. package/dist/extensions/tiptap.d.mts +2 -2
  59. package/dist/extensions/tiptap.mjs +31 -2
  60. package/dist/extensions/toc-field.d.mts +2 -0
  61. package/dist/extensions/toc-field.mjs +2 -0
  62. package/dist/extensions/utils.d.mts +2 -62
  63. package/dist/extensions/utils.mjs +508 -2
  64. package/dist/extensions/wpg-group.d.mts +2 -0
  65. package/dist/extensions/wpg-group.mjs +2 -0
  66. package/dist/extensions/wps-shape.d.mts +2 -0
  67. package/dist/extensions/wps-shape.mjs +2 -0
  68. package/dist/index.d.mts +101 -29
  69. package/dist/index.mjs +13 -10
  70. package/dist/{tiptap-TErPjuNJ.d.mts → tiptap-pZsNPsvV.d.mts} +1 -3
  71. package/dist/utils-BJwDQts7.d.mts +137 -0
  72. package/package.json +39 -40
  73. package/dist/blockquote-Ky9xD_Q-.mjs +0 -31
  74. package/dist/code-block-BgNjhADy.mjs +0 -23
  75. package/dist/core-DEqBHRzE.mjs +0 -406
  76. package/dist/core-fBMCCj4D.d.mts +0 -97
  77. package/dist/details-Dh8luWb2.mjs +0 -18
  78. package/dist/dist-B6B3HnVZ.mjs +0 -1838
  79. package/dist/document-BH1y4qHM.d.mts +0 -6
  80. package/dist/document-CvTym-FM.mjs +0 -50
  81. package/dist/docx-C5wyjI-0.d.mts +0 -200
  82. package/dist/docx-CONyAedl.mjs +0 -1231
  83. package/dist/editor-Bf3CxQnY.mjs +0 -21
  84. package/dist/editor-DReY3Rb9.d.mts +0 -21
  85. package/dist/emoji-BZ1dJD7d.d.mts +0 -17
  86. package/dist/emoji-C2OsTWR7.mjs +0 -27
  87. package/dist/extensions/emoji.d.mts +0 -2
  88. package/dist/extensions/emoji.mjs +0 -2
  89. package/dist/extensions/image-group.d.mts +0 -6
  90. package/dist/extensions/image-group.mjs +0 -2
  91. package/dist/heading-DAubgJJN.mjs +0 -166
  92. package/dist/html-DCC_DSHv.d.mts +0 -18
  93. package/dist/html-DedDWPoO.mjs +0 -66
  94. package/dist/image-CuEIXoZl.mjs +0 -334
  95. package/dist/markdown-BzJmRsBs.mjs +0 -18
  96. package/dist/markdown-D0k0sRYS.d.mts +0 -13
  97. package/dist/mention-C-dTR6MK.mjs +0 -44
  98. package/dist/ordered-list-V-3xFQmV.mjs +0 -41
  99. package/dist/paragraph-BrWH-BOV.mjs +0 -147
  100. package/dist/patch-Cdp5WKJz.d.mts +0 -53
  101. package/dist/patch-IZ13tXTu.mjs +0 -36
  102. package/dist/prepare-Bdk8Cjkf.mjs +0 -122
  103. package/dist/prepare-CPAvcv6q.d.mts +0 -63
  104. package/dist/strike-hWxShOgb.mjs +0 -50
  105. package/dist/styles-QSX3RhxK.mjs +0 -285
  106. package/dist/styles-ugspkrxz.d.mts +0 -85
  107. package/dist/table-DrA12lxX.mjs +0 -159
  108. package/dist/table-cell-DmkfYwDc.mjs +0 -112
  109. package/dist/table-header-Bwr5GKWg.mjs +0 -112
  110. package/dist/table-row-vew1y7WH.mjs +0 -84
  111. package/dist/task-item-BnlXGrIG.mjs +0 -37
  112. package/dist/text-style-tMeBq5XQ.mjs +0 -151
  113. package/dist/tiptap-D7pl4I5U.mjs +0 -33
  114. package/dist/utils-BPT4tjcn.mjs +0 -333
@@ -1,3 +1,41 @@
1
- import { w as OrderedList } from "../tiptap-D7pl4I5U.mjs";
2
- import { n as ORDERED_REFERENCE_PREFIX, r as buildOrderedLevels, t as ORDERED_LEVEL_TEXT } from "../ordered-list-V-3xFQmV.mjs";
1
+ import { OrderedList } from "./tiptap.mjs";
2
+ import { LevelFormat } from "@office-open/docx";
3
+ //#region src/extensions/ordered-list.ts
4
+ /**
5
+ * OrderedList extension — owns the DOCX expression of an ordered list.
6
+ *
7
+ * A Tiptap orderedList maps to a sequence of paragraphs referencing one
8
+ * abstractNum (decimal). The reference is keyed by `start` so lists with the
9
+ * same start share a definition; DocxManager gives each list its own instance
10
+ * for independent counting. This module owns that abstractNum shape; DocxManager
11
+ * owns the cross-paragraph tree walk, start recovery, and numbering-instance
12
+ * bookkeeping.
13
+ */
14
+ /** Reference prefix for generated ordered-list abstractNum definitions. */
15
+ const ORDERED_REFERENCE_PREFIX = "docen-ordered";
16
+ /** lvlText per nesting depth (level 0 → "%1.", … level 8 → "%9."). */
17
+ const ORDERED_LEVEL_TEXT = [
18
+ "%1.",
19
+ "%2.",
20
+ "%3.",
21
+ "%4.",
22
+ "%5.",
23
+ "%6.",
24
+ "%7.",
25
+ "%8.",
26
+ "%9."
27
+ ];
28
+ /**
29
+ * Build nine decimal numbering levels for an ordered list. Level 0 carries
30
+ * `start`; deeper levels restart at 1 (Word convention).
31
+ */
32
+ function buildOrderedLevels(start) {
33
+ return Array.from({ length: 9 }, (_, level) => ({
34
+ level,
35
+ format: LevelFormat.DECIMAL,
36
+ start: level === 0 ? start : 1,
37
+ text: ORDERED_LEVEL_TEXT[level]
38
+ }));
39
+ }
40
+ //#endregion
3
41
  export { ORDERED_LEVEL_TEXT, ORDERED_REFERENCE_PREFIX, OrderedList, buildOrderedLevels };
@@ -1,34 +1,2 @@
1
- import { s as Node } from "../core-fBMCCj4D.mjs";
2
-
3
- //#region src/extensions/page-break.d.ts
4
- /**
5
- * PageBreak — inline atom node for DOCX page breaks (`<w:br w:type="page"/>`).
6
- *
7
- * OOXML page breaks live inside a run (inline), so the Tiptap node is inline
8
- * too (group "inline"). This keeps a break inside its paragraph on round-trip
9
- * — a break mid-paragraph stays mid-paragraph instead of splitting the
10
- * paragraph into separate blocks (which would lose the original structure).
11
- * Sibling to HardBreak: both render `<w:br>`, differing only by type.
12
- *
13
- * The DOCX payload (`{ pageBreak: true }`) is inlined in DocxManager — a
14
- * one-liner with no per-node variance, so no extension helper for it.
15
- *
16
- * Inserting a page break must also visually reflow (the C-route paginator only
17
- * forces a new page after a block *containing* a pageBreak atom). So
18
- * `setPageBreak` inserts the atom then splits the paragraph — the atom lands at
19
- * the end of the first half, the trailing text becomes a fresh paragraph, and
20
- * the paginator's `forcesPageBreakAfter` moves it to the next page (matching
21
- * Word's Ctrl+Enter behavior).
22
- */
23
- declare const PageBreak: Node<any, any>;
24
- declare module "@tiptap/core" {
25
- interface Commands<ReturnType> {
26
- pageBreak: {
27
- /** Insert a page break at the cursor and split the paragraph so the
28
- * trailing content reflows to the next page. */
29
- setPageBreak: () => ReturnType;
30
- };
31
- }
32
- }
33
- //#endregion
1
+ import { c as PageBreak } from "../core-DRaLI8nd.mjs";
34
2
  export { PageBreak };
@@ -1,2 +1,2 @@
1
- import { f as PageBreak } from "../core-DEqBHRzE.mjs";
1
+ import { _ as PageBreak } from "../core-B8ba_FNi.mjs";
2
2
  export { PageBreak };
@@ -1,2 +1,146 @@
1
- import { n as parseDocx, r as renderDocx, t as Paragraph } from "../paragraph-BrWH-BOV.mjs";
1
+ import { Paragraph as Paragraph$1 } from "./tiptap.mjs";
2
+ import { alignmentFromElement, attrNative, bordersFromElement, indentFromElement, renderParagraphStyles, shadingFromElement, spacingFromElement } from "./utils.mjs";
3
+ //#region src/extensions/paragraph.ts
4
+ /**
5
+ * Paragraph extension with nested office-open attrs.
6
+ *
7
+ * Attrs mirror ParagraphPropertiesOptionsBase (alignment/indent/spacing/border/
8
+ * shading/frame as nested objects + scalar OOXML properties). DOCX round-trip is
9
+ * near-identity: renderDocx/parseDocx pass attrs through; CSS conversion happens
10
+ * only in renderHTML via utils mappers.
11
+ */
12
+ const SECTION_ATTR_KEYS = new Set([
13
+ "sectionProperties",
14
+ "sectionHeaders",
15
+ "sectionFooters"
16
+ ]);
17
+ function renderDocx(node) {
18
+ const attrs = node.attrs ?? {};
19
+ const opts = {};
20
+ for (const [key, value] of Object.entries(attrs)) {
21
+ if (value === null || value === void 0) continue;
22
+ if (SECTION_ATTR_KEYS.has(key)) continue;
23
+ if (key === "styleId") {
24
+ opts.style = value;
25
+ continue;
26
+ }
27
+ opts[key] = value;
28
+ }
29
+ return opts;
30
+ }
31
+ /**
32
+ * Structural/semantic keys handled elsewhere (heading ext, list handling, run/text
33
+ * children). NOTE: `run` is intentionally NOT skipped — ParagraphOptions.run (the
34
+ * paragraph's default run properties: font/size/color) is kept as an attr for
35
+ * lossless round-trip (e.g. header/footer paragraphs whose styling lives there).
36
+ */
37
+ const SKIP_KEYS = new Set([
38
+ "heading",
39
+ "style",
40
+ "bullet",
41
+ "numbering",
42
+ "children",
43
+ "text",
44
+ "thematicBreak"
45
+ ]);
46
+ function parseDocx(opts) {
47
+ const resolved = typeof opts === "string" ? { text: opts } : opts;
48
+ const attrs = {};
49
+ if (resolved.style) attrs.styleId = resolved.style;
50
+ for (const [key, value] of Object.entries(resolved)) {
51
+ if (SKIP_KEYS.has(key)) continue;
52
+ attrs[key] = value ?? null;
53
+ }
54
+ return attrs;
55
+ }
56
+ const Paragraph = Paragraph$1.extend({
57
+ addAttributes() {
58
+ return {
59
+ ...this.parent?.(),
60
+ styleId: {
61
+ default: null,
62
+ parseHTML: (el) => {
63
+ const m = (el.getAttribute("class") || "").match(/(?:^|\s)docx-style-(\S+)/);
64
+ return m ? m[1] : null;
65
+ }
66
+ },
67
+ alignment: {
68
+ default: null,
69
+ rendered: false,
70
+ parseHTML: (el) => alignmentFromElement(el)
71
+ },
72
+ indent: {
73
+ default: null,
74
+ rendered: false,
75
+ parseHTML: (el) => indentFromElement(el)
76
+ },
77
+ spacing: {
78
+ default: null,
79
+ rendered: false,
80
+ parseHTML: (el) => spacingFromElement(el)
81
+ },
82
+ shading: {
83
+ default: null,
84
+ rendered: false,
85
+ parseHTML: (el) => shadingFromElement(el)
86
+ },
87
+ border: {
88
+ default: null,
89
+ rendered: false,
90
+ parseHTML: (el) => bordersFromElement(el)
91
+ },
92
+ frame: attrNative(),
93
+ run: attrNative(),
94
+ sectionProperties: attrNative(),
95
+ sectionHeaders: attrNative(),
96
+ sectionFooters: attrNative(),
97
+ keepNext: attrNative(),
98
+ keepLines: attrNative(),
99
+ pageBreakBefore: attrNative(),
100
+ widowControl: attrNative(),
101
+ contextualSpacing: attrNative(),
102
+ bidirectional: attrNative(),
103
+ outlineLevel: attrNative(),
104
+ textDirection: attrNative(),
105
+ textAlignment: attrNative(),
106
+ suppressLineNumbers: attrNative(),
107
+ wordWrap: attrNative(),
108
+ overflowPunctuation: attrNative(),
109
+ autoSpaceEastAsianText: attrNative(),
110
+ suppressOverlap: attrNative(),
111
+ suppressAutoHyphens: attrNative(),
112
+ adjustRightInd: attrNative(),
113
+ snapToGrid: attrNative(),
114
+ mirrorIndents: attrNative(),
115
+ kinsoku: attrNative(),
116
+ topLinePunct: attrNative(),
117
+ autoSpaceDE: attrNative(),
118
+ textboxTightWrap: attrNative(),
119
+ rightTabStop: attrNative(),
120
+ leftTabStop: attrNative(),
121
+ divId: attrNative(),
122
+ tabStops: attrNative(),
123
+ cnfStyle: attrNative()
124
+ };
125
+ },
126
+ renderHTML({ node, HTMLAttributes }) {
127
+ let hasContent = false;
128
+ node.forEach?.((child) => {
129
+ if (child.isText || child.type?.name === "hardBreak" || child.type?.name === "image") hasContent = true;
130
+ });
131
+ const styles = renderParagraphStyles(node.attrs, { empty: !hasContent });
132
+ const attrs = { ...HTMLAttributes };
133
+ const styleId = node.attrs.styleId;
134
+ attrs.class = styleId ? `docx-style-${styleId}` : "docx-default";
135
+ if (styles.length > 0) attrs.style = styles.join(";");
136
+ return [
137
+ "p",
138
+ attrs,
139
+ 0
140
+ ];
141
+ },
142
+ renderDocx,
143
+ parseDocx
144
+ });
145
+ //#endregion
2
146
  export { Paragraph, parseDocx, renderDocx };
@@ -1,2 +1,2 @@
1
- import { m as Passthrough } from "../core-fBMCCj4D.mjs";
1
+ import { g as Passthrough } from "../core-DRaLI8nd.mjs";
2
2
  export { Passthrough };
@@ -1,2 +1,2 @@
1
- import { d as Passthrough } from "../core-DEqBHRzE.mjs";
1
+ import { g as Passthrough } from "../core-B8ba_FNi.mjs";
2
2
  export { Passthrough };
@@ -1,4 +1,4 @@
1
- import { r as Extension } from "../core-fBMCCj4D.mjs";
1
+ import { r as Extension } from "../core-DRaLI8nd.mjs";
2
2
 
3
3
  //#region src/extensions/section-break.d.ts
4
4
  /**
@@ -14,12 +14,29 @@ import { r as Extension } from "../core-fBMCCj4D.mjs";
14
14
  * The final section's sectPr rides on doc.attrs.sectionProperties (it lives at
15
15
  * <w:body>'s end in OOXML). Single-section documents have no section-carrying
16
16
  * paragraph at all.
17
+ *
18
+ * Next Page semantics: `setSectionBreak` stamps sectionProperties on the current
19
+ * paragraph (making it the section's last paragraph) AND inserts a fresh empty
20
+ * paragraph after it (the next section's first paragraph), then moves the
21
+ * selection into that new paragraph. The page-plugin's `forcesPageBreakAfter`
22
+ * treats a sectionProperties-bearing paragraph as a page break, so repaginate
23
+ * pushes the new paragraph onto the next page — and the caret follows. This
24
+ * mirrors Word's "Section Break (Next Page)".
25
+ *
26
+ * Split hygiene: pressing Enter inside a section-carrying paragraph must NOT
27
+ * split it. A split would place the new paragraph past the section boundary —
28
+ * forcesPageBreakAfter then pushes it onto the next page (next section), and
29
+ * splitBlock would copy sectionProperties onto it (a second break mark). Word
30
+ * instead inserts a fresh paragraph BEFORE the section's last paragraph, so the
31
+ * new paragraph stays in this section and the stamped paragraph remains last.
32
+ * The Enter shortcut does exactly that; non-section paragraphs fall through to
33
+ * the default Enter unchanged.
17
34
  */
18
35
  declare const SectionBreak: Extension<any, any>;
19
36
  declare module "@tiptap/core" {
20
37
  interface Commands<ReturnType> {
21
38
  sectionBreak: {
22
- /** Stamp sectionProperties on the current paragraph, ending a section. */setSectionBreak: () => ReturnType;
39
+ /** Insert a Next Page section break at the current paragraph. */setSectionBreak: () => ReturnType;
23
40
  };
24
41
  }
25
42
  }
@@ -1,2 +1,2 @@
1
- import { u as SectionBreak } from "../core-DEqBHRzE.mjs";
1
+ import { h as SectionBreak } from "../core-B8ba_FNi.mjs";
2
2
  export { SectionBreak };
@@ -1,2 +1,46 @@
1
- import { n as parseDocx, r as renderDocx, t as Strike } from "../strike-hWxShOgb.mjs";
1
+ import { Strike as Strike$1 } from "./tiptap.mjs";
2
+ import { attrNative } from "./utils.mjs";
3
+ //#region src/extensions/strike.ts
4
+ /**
5
+ * Strike mark extension with nested office-open attrs.
6
+ *
7
+ * OOXML represents strikethrough on a run via two mutually exclusive booleans:
8
+ * `strike` (single) and `doubleStrike` (double). The mark itself is "single
9
+ * strikethrough"; the `doubleStrike` attr flips it to double. DOCX round-trip
10
+ * is near-identity for the doubleStrike flag; `strike` itself is implied by the
11
+ * mark's presence and handled in renderDocx/parseDocx.
12
+ *
13
+ * Mark attribute-level renderHTML is delegated to the base Strike extension
14
+ * (renders `<s>`); only the DOCX flag needs custom handling.
15
+ */
16
+ /**
17
+ * attrs → run properties.
18
+ *
19
+ * The mark presence itself means single strikethrough. When `doubleStrike` is
20
+ * set, emit the OOXML double-strike flag instead (the two are mutually
21
+ * exclusive in OOXML). DocxManager calls this with `mark.attrs`.
22
+ */
23
+ function renderDocx(attrs) {
24
+ return attrs.doubleStrike ? { doubleStrike: true } : { strike: true };
25
+ }
26
+ /**
27
+ * run properties → attrs.
28
+ *
29
+ * Only the `doubleStrike` flag needs to round-trip; single strike is implied by
30
+ * the mark's existence. `strike` is structural/semantic (the mark) and skipped.
31
+ */
32
+ function parseDocx(runOpts) {
33
+ return { doubleStrike: runOpts.doubleStrike ?? null };
34
+ }
35
+ const Strike = Strike$1.extend({
36
+ addAttributes() {
37
+ return {
38
+ ...this.parent?.(),
39
+ doubleStrike: attrNative()
40
+ };
41
+ },
42
+ renderDocx,
43
+ parseDocx
44
+ });
45
+ //#endregion
2
46
  export { Strike, parseDocx, renderDocx };
@@ -1,2 +1,107 @@
1
- import { n as parseDocx, r as renderDocx, t as TableCell } from "../table-cell-DmkfYwDc.mjs";
1
+ import { TableCell as TableCell$1 } from "./tiptap.mjs";
2
+ import { attrNative, bordersFromElement, renderTableCellStyles, shadingFromElement } from "./utils.mjs";
3
+ //#region src/extensions/table-cell.ts
4
+ /**
5
+ * Table cell extension with nested office-open attrs.
6
+ *
7
+ * Attrs mirror TableCellPropertiesOptionsBase (shading/margins/borders/width as
8
+ * nested objects + scalar OOXML properties) plus the inherited Tiptap structural
9
+ * names colspan/rowspan/colwidth/align (rendered: false for the OOXML-named ones).
10
+ * DOCX round-trip is near-identity: renderDocx/parseDocx pass OOXML-native attrs
11
+ * through and only map the Tiptap structural names colspan/rowspan/colwidth to
12
+ * OOXML columnSpan/rowSpan/width. CSS conversion happens solely in renderHTML via
13
+ * utils.renderTableCellStyles (consuming nested shading/verticalAlign/noWrap).
14
+ */
15
+ /** Tiptap structural attrs expressed via OOXML structural fields, not passed through. */
16
+ const SKIP_KEYS = new Set([
17
+ "colspan",
18
+ "rowspan",
19
+ "colwidth",
20
+ "children"
21
+ ]);
22
+ function renderDocx(node) {
23
+ const attrs = node.attrs ?? {};
24
+ const opts = {};
25
+ const colspan = typeof attrs.colspan === "number" ? attrs.colspan : void 0;
26
+ if (colspan && colspan > 1) opts.columnSpan = colspan;
27
+ const rowspan = typeof attrs.rowspan === "number" ? attrs.rowspan : void 0;
28
+ if (rowspan && rowspan > 1) opts.rowSpan = rowspan;
29
+ const colwidth = attrs.colwidth;
30
+ if (colwidth && colwidth.length > 0) {
31
+ const totalPx = colwidth.reduce((sum, w) => sum + (w || 0), 0);
32
+ if (totalPx > 0) opts.width = {
33
+ size: totalPx * 15,
34
+ type: "dxa"
35
+ };
36
+ }
37
+ for (const [key, value] of Object.entries(attrs)) {
38
+ if (SKIP_KEYS.has(key)) continue;
39
+ if (value !== null && value !== void 0) opts[key] = value;
40
+ }
41
+ return opts;
42
+ }
43
+ function parseDocx(opts) {
44
+ const resolved = typeof opts === "string" ? { text: opts } : opts;
45
+ const attrs = {};
46
+ if (resolved.columnSpan != null) attrs.colspan = resolved.columnSpan;
47
+ if (resolved.rowSpan != null) attrs.rowspan = resolved.rowSpan;
48
+ if (resolved.width) {
49
+ const twips = resolved.width.size ?? 0;
50
+ if (twips) attrs.colwidth = [Math.round(twips / 15)];
51
+ }
52
+ for (const [key, value] of Object.entries(resolved)) {
53
+ if (key === "columnSpan" || key === "rowSpan" || key === "width" || key === "children") continue;
54
+ attrs[key] = value ?? null;
55
+ }
56
+ return attrs;
57
+ }
58
+ const TableCell = TableCell$1.extend({
59
+ addAttributes() {
60
+ return {
61
+ ...this.parent?.(),
62
+ shading: {
63
+ default: null,
64
+ rendered: false,
65
+ parseHTML: (el) => shadingFromElement(el)
66
+ },
67
+ borders: {
68
+ default: null,
69
+ rendered: false,
70
+ parseHTML: (el) => bordersFromElement(el)
71
+ },
72
+ verticalAlign: {
73
+ default: null,
74
+ rendered: false,
75
+ parseHTML: (el) => el.style.verticalAlign || null
76
+ },
77
+ textDirection: attrNative(),
78
+ width: attrNative(),
79
+ margins: attrNative(),
80
+ noWrap: {
81
+ default: null,
82
+ rendered: false,
83
+ parseHTML: (el) => el.style.whiteSpace === "nowrap" ? true : null
84
+ },
85
+ verticalMerge: attrNative(),
86
+ horizontalMerge: attrNative(),
87
+ fitText: attrNative(),
88
+ hideMark: attrNative(),
89
+ headers: attrNative(),
90
+ cnfStyle: attrNative()
91
+ };
92
+ },
93
+ renderHTML({ node, HTMLAttributes }) {
94
+ const styles = renderTableCellStyles(node.attrs);
95
+ const attrs = { ...HTMLAttributes };
96
+ if (styles.length > 0) attrs.style = styles.join(";");
97
+ return [
98
+ "td",
99
+ attrs,
100
+ 0
101
+ ];
102
+ },
103
+ renderDocx,
104
+ parseDocx
105
+ });
106
+ //#endregion
2
107
  export { TableCell, parseDocx, renderDocx };
@@ -1,2 +1,107 @@
1
- import { n as parseDocx, r as renderDocx, t as TableHeader } from "../table-header-Bwr5GKWg.mjs";
1
+ import { TableHeader as TableHeader$1 } from "./tiptap.mjs";
2
+ import { attrNative, bordersFromElement, renderTableCellStyles, shadingFromElement } from "./utils.mjs";
3
+ //#region src/extensions/table-header.ts
4
+ /**
5
+ * Table header extension with nested office-open attrs (mirrors TableCell).
6
+ *
7
+ * Attrs mirror TableCellPropertiesOptionsBase (shading/margins/borders/width as
8
+ * nested objects + scalar OOXML properties) plus the inherited Tiptap structural
9
+ * names colspan/rowspan/colwidth/align (rendered: false for the OOXML-named ones).
10
+ * DOCX round-trip is near-identity: renderDocx/parseDocx pass OOXML-native attrs
11
+ * through and only map the Tiptap structural names colspan/rowspan/colwidth to
12
+ * OOXML columnSpan/rowSpan/width. CSS conversion happens solely in renderHTML via
13
+ * utils.renderTableCellStyles (consuming nested shading/verticalAlign/noWrap).
14
+ */
15
+ /** Tiptap structural attrs expressed via OOXML structural fields, not passed through. */
16
+ const SKIP_KEYS = new Set([
17
+ "colspan",
18
+ "rowspan",
19
+ "colwidth",
20
+ "children"
21
+ ]);
22
+ function renderDocx(node) {
23
+ const attrs = node.attrs ?? {};
24
+ const opts = {};
25
+ const colspan = attrs.colspan;
26
+ if (colspan && colspan > 1) opts.columnSpan = colspan;
27
+ const rowspan = attrs.rowspan;
28
+ if (rowspan && rowspan > 1) opts.rowSpan = rowspan;
29
+ const colwidth = attrs.colwidth;
30
+ if (colwidth && colwidth.length > 0) {
31
+ const totalPx = colwidth.reduce((sum, w) => sum + (w || 0), 0);
32
+ if (totalPx > 0) opts.width = {
33
+ size: totalPx * 15,
34
+ type: "dxa"
35
+ };
36
+ }
37
+ for (const [key, value] of Object.entries(attrs)) {
38
+ if (SKIP_KEYS.has(key)) continue;
39
+ if (value !== null && value !== void 0) opts[key] = value;
40
+ }
41
+ return opts;
42
+ }
43
+ function parseDocx(opts) {
44
+ const resolved = typeof opts === "string" ? { text: opts } : opts;
45
+ const attrs = {};
46
+ if (resolved.columnSpan != null) attrs.colspan = resolved.columnSpan;
47
+ if (resolved.rowSpan != null) attrs.rowspan = resolved.rowSpan;
48
+ if (resolved.width) {
49
+ const twips = resolved.width.size ?? 0;
50
+ if (twips) attrs.colwidth = [Math.round(twips / 15)];
51
+ }
52
+ for (const [key, value] of Object.entries(resolved)) {
53
+ if (key === "columnSpan" || key === "rowSpan" || key === "width" || key === "children") continue;
54
+ attrs[key] = value ?? null;
55
+ }
56
+ return attrs;
57
+ }
58
+ const TableHeader = TableHeader$1.extend({
59
+ addAttributes() {
60
+ return {
61
+ ...this.parent?.(),
62
+ shading: {
63
+ default: null,
64
+ rendered: false,
65
+ parseHTML: (el) => shadingFromElement(el)
66
+ },
67
+ borders: {
68
+ default: null,
69
+ rendered: false,
70
+ parseHTML: (el) => bordersFromElement(el)
71
+ },
72
+ verticalAlign: {
73
+ default: null,
74
+ rendered: false,
75
+ parseHTML: (el) => el.style.verticalAlign || null
76
+ },
77
+ textDirection: attrNative(),
78
+ width: attrNative(),
79
+ margins: attrNative(),
80
+ noWrap: {
81
+ default: null,
82
+ rendered: false,
83
+ parseHTML: (el) => el.style.whiteSpace === "nowrap" ? true : null
84
+ },
85
+ verticalMerge: attrNative(),
86
+ horizontalMerge: attrNative(),
87
+ fitText: attrNative(),
88
+ hideMark: attrNative(),
89
+ headers: attrNative(),
90
+ cnfStyle: attrNative()
91
+ };
92
+ },
93
+ renderHTML({ node, HTMLAttributes }) {
94
+ const styles = renderTableCellStyles(node.attrs);
95
+ const attrs = { ...HTMLAttributes };
96
+ if (styles.length > 0) attrs.style = styles.join(";");
97
+ return [
98
+ "th",
99
+ attrs,
100
+ 0
101
+ ];
102
+ },
103
+ renderDocx,
104
+ parseDocx
105
+ });
106
+ //#endregion
2
107
  export { TableHeader, parseDocx, renderDocx };
@@ -1,2 +1,79 @@
1
- import { n as parseDocx, r as renderDocx, t as TableRow } from "../table-row-vew1y7WH.mjs";
1
+ import { TableRow as TableRow$1 } from "./tiptap.mjs";
2
+ import { attrNative, cssToTwip } from "./utils.mjs";
3
+ //#region src/extensions/table-row.ts
4
+ /**
5
+ * Table row extension with nested office-open attrs.
6
+ *
7
+ * Attrs mirror TableRowPropertiesOptionsBase (cantSplit/tableHeader/hidden as
8
+ * booleans; height as a nested { value, rule } object; cellSpacing as a native
9
+ * value; widthBefore/widthAfter as TableWidthProperties; etc.). DOCX round-trip
10
+ * is near-identity: renderDocx/parseDocx pass attrs through (omitting the
11
+ * `cells` structural key that DocxManager owns). CSS conversion happens only
12
+ * in renderHTML.
13
+ */
14
+ /** Structural keys filled by DocxManager (compileTableNode). */
15
+ const SKIP_KEYS = new Set(["cells"]);
16
+ function renderDocx(node) {
17
+ const attrs = node.attrs ?? {};
18
+ const opts = {};
19
+ for (const [key, value] of Object.entries(attrs)) {
20
+ if (SKIP_KEYS.has(key)) continue;
21
+ if (value !== null && value !== void 0) opts[key] = value;
22
+ }
23
+ return opts;
24
+ }
25
+ function parseDocx(opts) {
26
+ const attrs = {};
27
+ for (const [key, value] of Object.entries(opts)) {
28
+ if (SKIP_KEYS.has(key)) continue;
29
+ attrs[key] = value ?? null;
30
+ }
31
+ return attrs;
32
+ }
33
+ const TableRow = TableRow$1.extend({
34
+ addAttributes() {
35
+ return {
36
+ ...this.parent?.(),
37
+ height: {
38
+ default: null,
39
+ rendered: false,
40
+ parseHTML: (el) => {
41
+ const twips = cssToTwip(el.style.height || el.getAttribute("height") || "");
42
+ return twips != null ? {
43
+ value: twips,
44
+ rule: "atLeast"
45
+ } : null;
46
+ }
47
+ },
48
+ cantSplit: attrNative(),
49
+ tableHeader: attrNative(),
50
+ hidden: attrNative(),
51
+ divId: attrNative(),
52
+ gridBefore: attrNative(),
53
+ gridAfter: attrNative(),
54
+ rowAlignment: attrNative(),
55
+ cnfStyle: attrNative(),
56
+ cellSpacing: attrNative(),
57
+ widthBefore: attrNative(),
58
+ widthAfter: attrNative()
59
+ };
60
+ },
61
+ renderHTML({ node, HTMLAttributes }) {
62
+ const attrs = { ...HTMLAttributes };
63
+ const styles = [];
64
+ if (node.attrs.height && typeof node.attrs.height === "object") {
65
+ const h = node.attrs.height;
66
+ if (h.value != null) styles.push(`height:${h.value / 20}pt`);
67
+ }
68
+ if (styles.length > 0) attrs.style = styles.join(";");
69
+ return [
70
+ "tr",
71
+ attrs,
72
+ 0
73
+ ];
74
+ },
75
+ renderDocx,
76
+ parseDocx
77
+ });
78
+ //#endregion
2
79
  export { TableRow, parseDocx, renderDocx };