@docen/docx 0.3.5 → 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 (102) hide show
  1. package/README.md +1 -1
  2. package/dist/{blockquote-DY80QC06.d.mts → blockquote-D-1aSxEn.d.mts} +5 -1
  3. package/dist/converters/docx.d.mts +40 -66
  4. package/dist/converters/docx.mjs +248 -665
  5. package/dist/converters/html.d.mts +1 -1
  6. package/dist/converters/html.mjs +3 -4
  7. package/dist/converters/markdown.d.mts +1 -1
  8. package/dist/converters/markdown.mjs +1 -1
  9. package/dist/converters/patch.d.mts +1 -1
  10. package/dist/converters/prepare.d.mts +1 -1
  11. package/dist/converters/styles.d.mts +58 -14
  12. package/dist/converters/styles.mjs +124 -16
  13. package/dist/{core-DC0_-WcE.d.mts → core-BqyLL84S.d.mts} +34 -13
  14. package/dist/{core-BnF8XhVE.mjs → core-wNNPJiKr.mjs} +357 -25
  15. package/dist/core.d.mts +1 -1
  16. package/dist/core.mjs +1 -1
  17. package/dist/details-DsJhDP5K.d.mts +31 -0
  18. package/dist/editor.d.mts +1 -1
  19. package/dist/editor.mjs +1 -1
  20. package/dist/extensions/blockquote.d.mts +2 -3
  21. package/dist/extensions/blockquote.mjs +50 -2
  22. package/dist/extensions/bullet-list.mjs +1 -1
  23. package/dist/extensions/code-block.d.mts +2 -2
  24. package/dist/extensions/code-block.mjs +51 -5
  25. package/dist/extensions/column-break.d.mts +2 -2
  26. package/dist/extensions/column-break.mjs +2 -2
  27. package/dist/extensions/details.d.mts +2 -3
  28. package/dist/extensions/details.mjs +48 -2
  29. package/dist/extensions/document.mjs +1 -1
  30. package/dist/extensions/extensions.d.mts +13 -9
  31. package/dist/extensions/extensions.mjs +7 -3
  32. package/dist/extensions/formatting-marks.d.mts +1 -1
  33. package/dist/extensions/formatting-marks.mjs +1 -1
  34. package/dist/extensions/heading.d.mts +2 -2
  35. package/dist/extensions/heading.mjs +61 -5
  36. package/dist/extensions/image.d.mts +2 -2
  37. package/dist/extensions/image.mjs +23 -4
  38. package/dist/extensions/index.d.mts +14 -10
  39. package/dist/extensions/index.mjs +8 -4
  40. package/dist/extensions/link.d.mts +2 -2
  41. package/dist/extensions/link.mjs +30 -2
  42. package/dist/extensions/list-aggregator.d.mts +8 -0
  43. package/dist/extensions/list-aggregator.mjs +2 -0
  44. package/dist/extensions/marks.d.mts +2 -0
  45. package/dist/extensions/marks.mjs +41 -0
  46. package/dist/extensions/mention.d.mts +2 -3
  47. package/dist/extensions/mention.mjs +16 -2
  48. package/dist/extensions/ordered-list.mjs +1 -1
  49. package/dist/extensions/page-break.d.mts +2 -2
  50. package/dist/extensions/page-break.mjs +2 -2
  51. package/dist/extensions/paragraph.mjs +3 -3
  52. package/dist/extensions/passthrough.d.mts +1 -1
  53. package/dist/extensions/passthrough.mjs +1 -1
  54. package/dist/extensions/scroll.d.mts +1 -1
  55. package/dist/extensions/scroll.mjs +30 -5
  56. package/dist/extensions/section-break.d.mts +1 -1
  57. package/dist/extensions/section-break.mjs +1 -1
  58. package/dist/extensions/strike.d.mts +2 -2
  59. package/dist/extensions/strike.mjs +5 -24
  60. package/dist/extensions/tab.d.mts +2 -2
  61. package/dist/extensions/tab.mjs +2 -2
  62. package/dist/extensions/table-cell.mjs +2 -2
  63. package/dist/extensions/table-header.mjs +2 -2
  64. package/dist/extensions/table-row.mjs +2 -2
  65. package/dist/extensions/table.d.mts +2 -2
  66. package/dist/extensions/table.mjs +122 -11
  67. package/dist/extensions/task-item.d.mts +2 -3
  68. package/dist/extensions/task-item.mjs +2 -2
  69. package/dist/extensions/text-style.d.mts +2 -2
  70. package/dist/extensions/text-style.mjs +27 -28
  71. package/dist/extensions/toc-field.d.mts +2 -2
  72. package/dist/extensions/toc-field.mjs +2 -2
  73. package/dist/extensions/track-change.d.mts +2 -0
  74. package/dist/extensions/track-change.mjs +2 -0
  75. package/dist/extensions/types.d.mts +127 -8
  76. package/dist/extensions/utils.d.mts +2 -2
  77. package/dist/extensions/utils.mjs +74 -1
  78. package/dist/extensions/wpg-group.d.mts +2 -2
  79. package/dist/extensions/wpg-group.mjs +2 -2
  80. package/dist/extensions/wps-shape.d.mts +2 -2
  81. package/dist/extensions/wps-shape.mjs +2 -2
  82. package/dist/heading-Bwpa8iZY.d.mts +24 -0
  83. package/dist/index.d.mts +29 -11
  84. package/dist/index.mjs +9 -5
  85. package/dist/{link-BawPjQZR.d.mts → link-gUqW45mE.d.mts} +3 -1
  86. package/dist/marks-Dz9Vb22Q.d.mts +10 -0
  87. package/dist/{mention-BGLzLVYw.d.mts → mention-CkONDrw9.d.mts} +5 -1
  88. package/dist/{scroll-ZNeThJsJ.d.mts → scroll-BARiZ5Gm.d.mts} +9 -3
  89. package/dist/strike-Brn9sWFy.d.mts +16 -0
  90. package/dist/table-CdcjR6HD.d.mts +18 -0
  91. package/dist/{task-item-B0ntvQ1Y.d.mts → task-item-CCAC4QLi.d.mts} +3 -1
  92. package/dist/text-style-BzfcbufI.d.mts +4 -0
  93. package/dist/{utils-BJwDQts7.d.mts → utils-CfwwOowz.d.mts} +25 -1
  94. package/package.json +1 -1
  95. package/dist/details-Dd5MqqmR.d.mts +0 -17
  96. package/dist/extensions/tiptap.d.mts +0 -2
  97. package/dist/extensions/tiptap.mjs +0 -31
  98. package/dist/heading-BvqBD2zX.d.mts +0 -8
  99. package/dist/strike-BgWGvjKr.d.mts +0 -33
  100. package/dist/table-BFkfeRp9.d.mts +0 -9
  101. package/dist/text-style-BHdtXkMb.d.mts +0 -8
  102. package/dist/tiptap-BKqn41uT.d.mts +0 -31
@@ -1,4 +1,4 @@
1
- import { a as JSONContent, i as Extensions } from "../core-DC0_-WcE.mjs";
1
+ import { a as JSONContent, i as Extensions } from "../core-BqyLL84S.mjs";
2
2
  import { ParseOptions } from "@tiptap/pm/model";
3
3
 
4
4
  //#region src/converters/html.d.ts
@@ -1,11 +1,10 @@
1
- import { o as docxExtensions } from "../core-BnF8XhVE.mjs";
2
1
  import { sectionLinePitchCss, sectionMarginCss } from "../extensions/utils.mjs";
2
+ import { h as docxExtensions } from "../core-wNNPJiKr.mjs";
3
3
  import { getSchema } from "@tiptap/core";
4
4
  import { encodeBase64 } from "@office-open/core";
5
5
  import { DOMParser, DOMSerializer, Node } from "@tiptap/pm/model";
6
6
  import { parseHTML as parseHTML$1 } from "linkedom";
7
7
  //#region src/converters/html.ts
8
- const defaultExtensions = docxExtensions;
9
8
  /** JSON round-trips byte arrays as plain objects ({0:byte,…}); rebuild here. */
10
9
  function toBytes(data) {
11
10
  if (!data) return null;
@@ -61,7 +60,7 @@ function splitJsonSections(doc) {
61
60
  * document: happy-dom drops calc(var(…)) when re-serializing the style
62
61
  * attribute, so DOCX line-spacing survives only with linkedom.
63
62
  */
64
- function generateHTML(doc, extensions = defaultExtensions) {
63
+ function generateHTML(doc, extensions = docxExtensions) {
65
64
  const schema = getSchema(extensions);
66
65
  const { document } = parseHTML$1("<!DOCTYPE html><html><body></body></html>");
67
66
  const serializer = DOMSerializer.fromSchema(schema);
@@ -95,7 +94,7 @@ function generateHTML(doc, extensions = defaultExtensions) {
95
94
  * (linePitch/margins) and the page background are section/doc-level metadata,
96
95
  * not content — they round-trip losslessly via DOCX, not HTML.
97
96
  */
98
- function parseHTML(html, extensions = defaultExtensions, options) {
97
+ function parseHTML(html, extensions = docxExtensions, options) {
99
98
  const schema = getSchema(extensions);
100
99
  const { document } = parseHTML$1(`<!DOCTYPE html><html><body>${html}</body></html>`);
101
100
  return DOMParser.fromSchema(schema).parse(document.body, options).toJSON();
@@ -1,4 +1,4 @@
1
- import { a as JSONContent } from "../core-DC0_-WcE.mjs";
1
+ import { a as JSONContent } from "../core-BqyLL84S.mjs";
2
2
 
3
3
  //#region src/converters/markdown.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { o as docxExtensions } from "../core-BnF8XhVE.mjs";
1
+ import { h as docxExtensions } from "../core-wNNPJiKr.mjs";
2
2
  import { Markdown, MarkdownManager } from "@tiptap/markdown";
3
3
  //#region src/converters/markdown.ts
4
4
  const markdownManager = new MarkdownManager({ extensions: [...docxExtensions, Markdown] });
@@ -1,4 +1,4 @@
1
- import { a as JSONContent } from "../core-DC0_-WcE.mjs";
1
+ import { a as JSONContent } from "../core-BqyLL84S.mjs";
2
2
  import { PrepareStep } from "./prepare.mjs";
3
3
  import { OutputByType, OutputType, patchDocument } from "@office-open/docx";
4
4
 
@@ -1,4 +1,4 @@
1
- import { a as JSONContent } from "../core-DC0_-WcE.mjs";
1
+ import { a as JSONContent } from "../core-BqyLL84S.mjs";
2
2
 
3
3
  //#region src/converters/prepare.d.ts
4
4
  /**
@@ -1,5 +1,6 @@
1
+ import { ResolveContext } from "../extensions/types.mjs";
1
2
  import { JSONContent } from "@tiptap/core";
2
- import { StylesOptions } from "@office-open/docx";
3
+ import { ParagraphOptions, StylesOptions } from "@office-open/docx";
3
4
 
4
5
  //#region src/converters/styles.d.ts
5
6
  /** A named style entry as office-open models it: BaseParagraphStyleOptions or
@@ -35,6 +36,17 @@ declare function defaultParagraphStyleId(styles: StylesOptions | null | undefine
35
36
  */
36
37
  declare function stylesToCss(styles: StylesOptions | null | undefined, scope: string): string;
37
38
  declare function indexParagraphStyles(styles: StylesOptions): Map<string, StyleEntry>;
39
+ /** Resolve a table style's effective table-level properties (tblBorders,
40
+ * tblCellMar) by walking its basedOn chain (root first, child overrides) —
41
+ * the table-style counterpart of mergeStyleChain. office-open's parseDocument
42
+ * does NOT merge the referenced <w:tblStyle> into table.borders/cellMargin
43
+ * (they reflect only the table's own <w:tblPr>), so a "Table Grid" table whose
44
+ * borders live in the style needs this to render its grid. Returns empty when
45
+ * the style is absent or unknown. */
46
+ declare function mergeTableStyleProps(tableStyles: unknown, styleId: string | null | undefined): {
47
+ borders?: Record<string, unknown>;
48
+ cellMargin?: Record<string, unknown>;
49
+ };
38
50
  /** A gallery-ready paragraph-style entry for the Styles combobox. */
39
51
  interface QuickStyleEntry {
40
52
  id: string;
@@ -71,21 +83,53 @@ declare function effectiveRunProps(styles: StylesOptions | null | undefined, sty
71
83
  size: number | null;
72
84
  };
73
85
  /**
74
- * Inline a document's styles into each node's attrs a self-contained
75
- * JSONContent that round-trips and renders without the styles context. A
76
- * paragraph/heading absorbs its styleId's `basedOn` chain (paragraph properties
77
- * + the paragraph's default `run`); a textStyle mark absorbs its character
78
- * style's run. Explicit attrs/marks always override the inherited values;
79
- * styleId is preserved (the semantic reference is kept). The style definitions
80
- * themselves are untouched — only properties are copied onto nodes.
86
+ * Bake a document's named styles into each node's attrs so a snippet of
87
+ * JSONContent can be lifted into ANOTHER document (DB storage → extract →
88
+ * recombine) without its source styles.xml. The use case is fragment
89
+ * recombination, not editor rendering the editor never calls this (it
90
+ * renders via stylesToCss global CSS); this is an offline util for
91
+ * self-contained JSON.
92
+ *
93
+ * Baking is intentionally PARTIAL:
94
+ * - A paragraph/heading or textStyle mark WITH a styleId absorbs its basedOn
95
+ * chain, so a "Heading 1" stays styled across documents even when the
96
+ * target lacks that style. styleId is kept as the semantic reference; the
97
+ * baked props are the rendering fallback.
98
+ * - A node WITHOUT a styleId (body text, a default table) is LEFT AS-IS so it
99
+ * follows the TARGET document's body style after recombination. Baking
100
+ * docDefaults here would freeze font/size onto every body paragraph and
101
+ * defeat "change one body style to restyle them all".
102
+ * - Tables are NOT baked here: resolveTable already merged the table style
103
+ * (borders/cellMargin) and pushed insideH/V onto cells at parse time, so a
104
+ * table's JSON is already self-contained. stylesToCss cannot render the
105
+ * interior grid (CSS border-collapse puts it on cells), so that bake MUST
106
+ * stay in resolveDocument — moving it here would regress the editor.
81
107
  *
108
+ * Explicit attrs/marks always override the baked values; the style definitions
109
+ * themselves are untouched. Pure JSON — no DOM, no marks pushed onto text.
82
110
  * Styles default to the document's own `attrs.styles` (the round-tripped
83
- * styles.xml model carried on the doc node), so `inlineStyles(doc)` needs no
84
- * second argument; pass `styles` explicitly to override. Use cases:
85
- * cross-document paste (the snippet carries its styling) and self-contained
86
- * export. The editor still renders via global styles — this only merges JSON
87
- * properties.
111
+ * styles.xml model on the doc node), so `inlineStyles(doc)` needs no second
112
+ * argument; pass `styles` to override.
88
113
  */
89
114
  declare function inlineStyles(json: JSONContent, styles?: StylesOptions | null): JSONContent;
115
+ /** Remove keys with null/undefined values. */
116
+ declare function cleanAttrs(attrs: Record<string, unknown>): Record<string, unknown>;
117
+ /** Build a text-block node (paragraph/heading) from a resolved ParagraphOptions:
118
+ * reflective attrs parse, optional heading-level stamp, inline content, and
119
+ * null-stripped attrs. Shared by resolveParagraph's heading rule + plain
120
+ * fallback (and the list-item paragraph path) so the build stays DRY.
121
+ * `contentPara` overrides the content source — a list item strips its task
122
+ * checkbox before resolving content, but attrs still come from the original. */
123
+ declare function buildTextBlock(type: string, resolved: ParagraphOptions, ctx: ResolveContext, level?: number, contentPara?: ParagraphOptions): JSONContent;
124
+ /** True when a tblBorders object carries no REAL edge — every side is absent,
125
+ * none, or nil. office-open fills table.borders with all-`none` when the
126
+ * table's own <w:tblPr> defines no <w:tblBorders>, so this detects "the table
127
+ * has no borders of its own" to decide whether a referenced table style's
128
+ * borders should fill the gap. */
129
+ declare function allBordersNone(borders: unknown): boolean;
130
+ /** Merge consecutive text nodes with the same marks. Used by inline container
131
+ * resolution (hyperlink, track-change) so a link/revision range spanning
132
+ * multiple runs becomes a single text node carrying the container mark. */
133
+ declare function mergeTextNodes(nodes: JSONContent[]): JSONContent[];
90
134
  //#endregion
91
- export { QuickStyleEntry, StyleEntry, type StylesOptions, defaultParagraphStyleId, effectiveRunProps, indexParagraphStyles, inlineStyles, quickStyles, stylesToCss };
135
+ export { QuickStyleEntry, StyleEntry, type StylesOptions, allBordersNone, buildTextBlock, cleanAttrs, defaultParagraphStyleId, effectiveRunProps, indexParagraphStyles, inlineStyles, mergeTableStyleProps, mergeTextNodes, quickStyles, stylesToCss };
@@ -147,11 +147,44 @@ function mergeStyleChain(byId, styleId) {
147
147
  paragraph
148
148
  };
149
149
  }
150
+ /** Resolve a table style's effective table-level properties (tblBorders,
151
+ * tblCellMar) by walking its basedOn chain (root first, child overrides) —
152
+ * the table-style counterpart of mergeStyleChain. office-open's parseDocument
153
+ * does NOT merge the referenced <w:tblStyle> into table.borders/cellMargin
154
+ * (they reflect only the table's own <w:tblPr>), so a "Table Grid" table whose
155
+ * borders live in the style needs this to render its grid. Returns empty when
156
+ * the style is absent or unknown. */
157
+ function mergeTableStyleProps(tableStyles, styleId) {
158
+ if (!styleId || !tableStyles) return {};
159
+ const byId = new Map(tableStyles.map((t) => [t.id ?? "", t]));
160
+ const chain = [];
161
+ const visited = /* @__PURE__ */ new Set();
162
+ let cur = styleId ?? void 0;
163
+ while (cur && !visited.has(cur)) {
164
+ visited.add(cur);
165
+ const s = byId.get(cur);
166
+ if (!s) break;
167
+ chain.unshift(s);
168
+ cur = s.basedOn;
169
+ }
170
+ let borders;
171
+ let cellMargin;
172
+ for (const s of chain) {
173
+ const t = s.table;
174
+ if (!t) continue;
175
+ if (t.borders) borders = t.borders;
176
+ if (t.cellMargin) cellMargin = t.cellMargin;
177
+ }
178
+ const out = {};
179
+ if (borders) out.borders = borders;
180
+ if (cellMargin) out.cellMargin = cellMargin;
181
+ return out;
182
+ }
150
183
  /** The `DefaultStylesOptions` keys whose values are character styles, not
151
184
  * paragraph styles. The Quick Styles gallery is paragraph-only, so these are
152
185
  * excluded even when flagged `quickFormat` (the authoritative source is
153
186
  * office-open's DefaultStylesOptions interface). */
154
- const CHARACTER_DEFAULT_KEYS = new Set([
187
+ const CHARACTER_DEFAULT_KEYS = /* @__PURE__ */ new Set([
155
188
  "hyperlink",
156
189
  "footnoteReference",
157
190
  "footnoteTextChar",
@@ -247,9 +280,12 @@ function indexCharacterRunStyles(styles) {
247
280
  }
248
281
  return byId;
249
282
  }
250
- /** Resolve one node's style inheritance: a paragraph/heading absorbs its
283
+ /** Resolve one node's style inheritance. A paragraph/heading absorbs its
251
284
  * styleId's basedOn chain (paragraph properties + the default `run`); a
252
- * textStyle mark absorbs its character style's run. Explicit attrs/marks
285
+ * textStyle mark absorbs its character style's run. Other nodes (table,
286
+ * tableRow, tableCell, image, …) are NOT baked here — they only recurse into
287
+ * `content`, so a cell's paragraphs still get baked (see inlineStyles for why
288
+ * tables and docDefaults are intentionally out of scope). Explicit attrs/marks
253
289
  * override the inherited values; styleId is preserved. Pure JSON — no DOM, no
254
290
  * marks pushed onto text. */
255
291
  function resolveNode(node, paraById, charRunById) {
@@ -284,25 +320,97 @@ function resolveNode(node, paraById, charRunById) {
284
320
  return out;
285
321
  }
286
322
  /**
287
- * Inline a document's styles into each node's attrs a self-contained
288
- * JSONContent that round-trips and renders without the styles context. A
289
- * paragraph/heading absorbs its styleId's `basedOn` chain (paragraph properties
290
- * + the paragraph's default `run`); a textStyle mark absorbs its character
291
- * style's run. Explicit attrs/marks always override the inherited values;
292
- * styleId is preserved (the semantic reference is kept). The style definitions
293
- * themselves are untouched — only properties are copied onto nodes.
323
+ * Bake a document's named styles into each node's attrs so a snippet of
324
+ * JSONContent can be lifted into ANOTHER document (DB storage → extract →
325
+ * recombine) without its source styles.xml. The use case is fragment
326
+ * recombination, not editor rendering the editor never calls this (it
327
+ * renders via stylesToCss global CSS); this is an offline util for
328
+ * self-contained JSON.
294
329
  *
330
+ * Baking is intentionally PARTIAL:
331
+ * - A paragraph/heading or textStyle mark WITH a styleId absorbs its basedOn
332
+ * chain, so a "Heading 1" stays styled across documents even when the
333
+ * target lacks that style. styleId is kept as the semantic reference; the
334
+ * baked props are the rendering fallback.
335
+ * - A node WITHOUT a styleId (body text, a default table) is LEFT AS-IS so it
336
+ * follows the TARGET document's body style after recombination. Baking
337
+ * docDefaults here would freeze font/size onto every body paragraph and
338
+ * defeat "change one body style to restyle them all".
339
+ * - Tables are NOT baked here: resolveTable already merged the table style
340
+ * (borders/cellMargin) and pushed insideH/V onto cells at parse time, so a
341
+ * table's JSON is already self-contained. stylesToCss cannot render the
342
+ * interior grid (CSS border-collapse puts it on cells), so that bake MUST
343
+ * stay in resolveDocument — moving it here would regress the editor.
344
+ *
345
+ * Explicit attrs/marks always override the baked values; the style definitions
346
+ * themselves are untouched. Pure JSON — no DOM, no marks pushed onto text.
295
347
  * Styles default to the document's own `attrs.styles` (the round-tripped
296
- * styles.xml model carried on the doc node), so `inlineStyles(doc)` needs no
297
- * second argument; pass `styles` explicitly to override. Use cases:
298
- * cross-document paste (the snippet carries its styling) and self-contained
299
- * export. The editor still renders via global styles — this only merges JSON
300
- * properties.
348
+ * styles.xml model on the doc node), so `inlineStyles(doc)` needs no second
349
+ * argument; pass `styles` to override.
301
350
  */
302
351
  function inlineStyles(json, styles) {
303
352
  const docStyles = styles ?? json.attrs?.styles;
304
353
  if (!docStyles) return json;
305
354
  return resolveNode(json, indexParagraphStyles(docStyles), indexCharacterRunStyles(docStyles));
306
355
  }
356
+ /** Remove keys with null/undefined values. */
357
+ function cleanAttrs(attrs) {
358
+ const result = {};
359
+ for (const [key, value] of Object.entries(attrs)) if (value !== null && value !== void 0) result[key] = value;
360
+ return result;
361
+ }
362
+ /** Build a text-block node (paragraph/heading) from a resolved ParagraphOptions:
363
+ * reflective attrs parse, optional heading-level stamp, inline content, and
364
+ * null-stripped attrs. Shared by resolveParagraph's heading rule + plain
365
+ * fallback (and the list-item paragraph path) so the build stays DRY.
366
+ * `contentPara` overrides the content source — a list item strips its task
367
+ * checkbox before resolving content, but attrs still come from the original. */
368
+ function buildTextBlock(type, resolved, ctx, level, contentPara) {
369
+ const attrs = ctx.parseNodeAttrs(type, resolved);
370
+ if (level != null && attrs.level == null) attrs.level = level;
371
+ const content = ctx.resolveInlineContent(contentPara ?? resolved);
372
+ const cleaned = cleanAttrs(attrs);
373
+ const node = { type };
374
+ if (Object.keys(cleaned).length > 0) node.attrs = cleaned;
375
+ if (content.length > 0) node.content = content;
376
+ return node;
377
+ }
378
+ /** True when a tblBorders object carries no REAL edge — every side is absent,
379
+ * none, or nil. office-open fills table.borders with all-`none` when the
380
+ * table's own <w:tblPr> defines no <w:tblBorders>, so this detects "the table
381
+ * has no borders of its own" to decide whether a referenced table style's
382
+ * borders should fill the gap. */
383
+ function allBordersNone(borders) {
384
+ if (!borders || typeof borders !== "object") return true;
385
+ const b = borders;
386
+ return [
387
+ "top",
388
+ "bottom",
389
+ "left",
390
+ "right",
391
+ "insideHorizontal",
392
+ "insideVertical"
393
+ ].every((k) => {
394
+ const v = b[k];
395
+ return !v || v.style === "none" || v.style === "nil";
396
+ });
397
+ }
398
+ /** Merge consecutive text nodes with the same marks. Used by inline container
399
+ * resolution (hyperlink, track-change) so a link/revision range spanning
400
+ * multiple runs becomes a single text node carrying the container mark. */
401
+ function mergeTextNodes(nodes) {
402
+ const result = [];
403
+ for (const node of nodes) {
404
+ if (node.type === "text" && result.length > 0 && result[result.length - 1].type === "text") {
405
+ const prev = result[result.length - 1];
406
+ if (JSON.stringify(prev.marks) === JSON.stringify(node.marks)) {
407
+ prev.text = (prev.text ?? "") + (node.text ?? "");
408
+ continue;
409
+ }
410
+ }
411
+ result.push({ ...node });
412
+ }
413
+ return result;
414
+ }
307
415
  //#endregion
308
- export { defaultParagraphStyleId, effectiveRunProps, indexParagraphStyles, inlineStyles, quickStyles, stylesToCss };
416
+ export { allBordersNone, buildTextBlock, cleanAttrs, defaultParagraphStyleId, effectiveRunProps, indexParagraphStyles, inlineStyles, mergeTableStyleProps, mergeTextNodes, quickStyles, stylesToCss };
@@ -1,19 +1,31 @@
1
+ import { ParseBlockRule, ParseInlineRule, ParseParagraphRule } from "./extensions/types.mjs";
1
2
  import { AnyExtension, Editor, Extension, Extensions, JSONContent as JSONContent$1, Mark, Node } from "@tiptap/core";
3
+ import { CodeBlockLowlight as CodeBlockLowlight$1 } from "@tiptap/extension-code-block-lowlight";
4
+ import { Emoji as Emoji$1 } from "@tiptap/extension-emoji";
5
+ import { HardBreak as HardBreak$1 } from "@tiptap/extension-hard-break";
6
+ import { HorizontalRule as HorizontalRule$1 } from "@tiptap/extension-horizontal-rule";
7
+ import { ListItem as ListItem$1 } from "@tiptap/extension-list-item";
8
+ import { Mathematics as Mathematics$1 } from "@tiptap/extension-mathematics";
9
+ import { TaskList as TaskList$1 } from "@tiptap/extension-task-list";
10
+ import { Text as Text$1 } from "@tiptap/extension-text";
11
+ import { TextAlign as TextAlign$1 } from "@tiptap/extension-text-align";
2
12
 
3
13
  //#region src/extensions/code-block.d.ts
4
14
  /**
5
- * CodeBlock extension — CodeBlockLowlight with a DOCX renderDocx.
15
+ * CodeBlock extension — CodeBlockLowlight with a DOCX renderDocx + parse rule.
6
16
  *
7
17
  * DOCX has no dedicated code-block element. A code block maps to a single
8
18
  * paragraph styled "Code" with a monospace run font. Inline marks (syntax-
9
19
  * highlight tokens) and line breaks (`\n` → `<w:br/>`) are handled by
10
20
  * DocxManager's shared inline-content compilation; resolveCodeBlock reassembles
11
- * the text. This module owns only the paragraph-level style.
21
+ * the text. This module owns the paragraph-level style + the parse rule that
22
+ * recognizes a "Code"-styled paragraph.
12
23
  *
13
24
  * `language` has no OOXML carrier and is intentionally dropped (known lossy).
14
25
  */
15
26
  /** codeBlock node → paragraph properties (style "Code" + monospace font). */
16
27
  declare function renderDocx$1(_node: JSONContent$1): Record<string, unknown>;
28
+ declare const parseDocxParagraph: ParseParagraphRule;
17
29
  declare const CodeBlock: import("@tiptap/core").Node<import("@tiptap/extension-code-block-lowlight").CodeBlockLowlightOptions, any>;
18
30
  //#endregion
19
31
  //#region src/extensions/column-break.d.ts
@@ -26,13 +38,11 @@ declare const CodeBlock: import("@tiptap/core").Node<import("@tiptap/extension-c
26
38
  * layout (paged.js multi-column) is a future concern; the node preserves the
27
39
  * break losslessly regardless.
28
40
  *
29
- * The DOCX payload (`{ columnBreak: true }`) is inlined in DocxManager — a
30
- * one-liner with no per-node variance, so no extension helper for it.
31
- *
32
41
  * `setColumnBreak` only inserts the atom (no paragraph split): a column break
33
42
  * does not start a new page, and there is no column layout to reflow yet, so
34
43
  * the node is purely for round-trip fidelity until multi-column lands.
35
44
  */
45
+ declare const parseDocxInline$5: ParseInlineRule;
36
46
  declare const ColumnBreak: Node<any, any>;
37
47
  declare module "@tiptap/core" {
38
48
  interface Commands<ReturnType> {
@@ -108,6 +118,7 @@ declare function renderDocx(node: JSONContent$1): Record<string, unknown> | null
108
118
  * DocxManager from the image data bytes (kept out of parseDocx).
109
119
  */
110
120
  declare function parseDocx(imageOpts: Record<string, unknown>): Record<string, unknown>;
121
+ declare const parseDocxInline$4: ParseInlineRule;
111
122
  /** Extent-box dimensions needed to size the inner <img> for a cropped image. */
112
123
  interface CropRenderContext {
113
124
  width?: number;
@@ -129,6 +140,10 @@ declare function renderCropAttrs(crop: Record<string, unknown> | CropRect, ctx?:
129
140
  };
130
141
  declare const Image: import("@tiptap/core").Node<import("@tiptap/extension-image").ImageOptions, any>;
131
142
  //#endregion
143
+ //#region src/extensions/track-change.d.ts
144
+ declare const Insertion: Mark<any, any>;
145
+ declare const Deletion: Mark<any, any>;
146
+ //#endregion
132
147
  //#region src/extensions/formatting-marks.d.ts
133
148
  /**
134
149
  * FormattingMarks — paints the non-printing paragraph mark via ProseMirror
@@ -184,6 +199,7 @@ declare module "@tiptap/core" {
184
199
  * the paginator's `forcesPageBreakAfter` moves it to the next page (matching
185
200
  * Word's Ctrl+Enter behavior).
186
201
  */
202
+ declare const parseDocxInline$3: ParseInlineRule;
187
203
  declare const PageBreak: Node<any, any>;
188
204
  declare module "@tiptap/core" {
189
205
  interface Commands<ReturnType> {
@@ -284,9 +300,11 @@ interface WpsShapeStyles {
284
300
  * editor's NodeView and generateHTML render identically without re-deriving
285
301
  * the engine's EMU/floating math. */
286
302
  declare function wpsShapeStyles(ws: WpsShapeStandalone): WpsShapeStyles;
303
+ declare const parseDocxInline$2: ParseInlineRule;
287
304
  declare const WpgGroup: Node<any, any>;
288
305
  //#endregion
289
306
  //#region src/extensions/wps-shape.d.ts
307
+ declare const parseDocxInline$1: ParseInlineRule;
290
308
  declare const WpsShape: Node<any, any>;
291
309
  //#endregion
292
310
  //#region src/extensions/passthrough.d.ts
@@ -334,14 +352,16 @@ declare const InlinePassthrough: Node<any, any>;
334
352
  * whose content-less runs (fldChar begin/separate/end) office-open parses as
335
353
  * `null`. As opaque passthrough those nulls survived verbatim to
336
354
  * `generateDocument`, where office-open's `stringifyRunInline(null).break`
337
- * crashed. Resolving the entries through `resolveParagraphChildren` drops the
338
- * nulls (the existing `child !== null` guard), so compile rebuilds clean entries
339
- * and the generate path never sees a null — no office-open change required.
340
- *
341
- * DOCX serialization is inlined in DocxManager (resolve/compile read/write
342
- * `attrs.options` + the entry content directly), so no renderDocx/parseDocx is
343
- * needed here — the same pattern as the details extension.
355
+ * crashed. The `parseDocxBlock` rule resolves the entries through the shared
356
+ * block-stream path, which drops the nulls (the `child !== null` guard), so
357
+ * compile rebuilds clean entries and the generate path never sees a null — no
358
+ * office-open change required.
344
359
  */
360
+ /**
361
+ * Declarative block parse rule: recognize a table of contents SectionChild and
362
+ * rebuild it as an editable `tocField` container. DocxManager dispatches every
363
+ * SectionChild through this rule before the paragraph/passthrough fallbacks. */
364
+ declare const parseDocxBlock: ParseBlockRule;
345
365
  declare const TocField: Node<any, any>;
346
366
  //#endregion
347
367
  //#region src/extensions/tab.d.ts
@@ -357,6 +377,7 @@ declare const TocField: Node<any, any>;
357
377
  * marks where a tab leader (e.g. a TOC's dotted leader) renders. compile turns it
358
378
  * back into `{ tab: true }`.
359
379
  */
380
+ declare const parseDocxInline: ParseInlineRule;
360
381
  declare const Tab: Node<any, any>;
361
382
  //#endregion
362
383
  //#region src/extensions/extensions.d.ts
@@ -384,4 +405,4 @@ interface DocxKitOptions {
384
405
  }
385
406
  declare const DocxKit: Extension<DocxKitOptions, any>;
386
407
  //#endregion
387
- export { Image as A, renderWpsText as C, PageBreak as D, wpsShapeStyles as E, ColumnBreak as F, CodeBlock as I, renderDocx$1 as L, renderCropAttrs as M, renderDocx as N, FormattingMarks as O, SectionBreak as P, renderWpsInterior as S, wpsRotationVert as T, WpsShape as _, JSONContent$1 as a, WpsShapeStandalone as b, DocxKit as c, tiptapMarkExtensions as d, tiptapNodeExtensions as f, Passthrough as g, InlinePassthrough as h, Extensions as i, parseDocx as j, CropRenderContext as k, DocxKitOptions as l, TocField as m, Editor as n, Mark as o, Tab as p, Extension as r, Node as s, AnyExtension as t, docxExtensions as u, WpgGroup as v, wpsInnerStyle as w, WpsShapeStyles as x, WpsData as y };
408
+ export { parseDocxInline$5 as $, WpgGroup as A, PageBreak as B, parseDocxInline as C, Passthrough as D, InlinePassthrough as E, renderWpsInterior as F, CropRenderContext as G, FormattingMarks as H, renderWpsText as I, parseDocxInline$4 as J, Image as K, wpsInnerStyle as L, WpsShapeStandalone as M, WpsShapeStyles as N, WpsShape as O, parseDocxInline$2 as P, ColumnBreak as Q, wpsRotationVert as R, Tab as S, parseDocxBlock as T, Deletion as U, parseDocxInline$3 as V, Insertion as W, renderDocx as X, renderCropAttrs as Y, SectionBreak as Z, Text$1 as _, JSONContent$1 as a, tiptapMarkExtensions as b, CodeBlockLowlight$1 as c, Emoji$1 as d, CodeBlock as et, HardBreak$1 as f, TaskList$1 as g, Mathematics$1 as h, Extensions as i, WpsData as j, parseDocxInline$1 as k, DocxKit as l, ListItem$1 as m, Editor as n, renderDocx$1 as nt, Mark as o, HorizontalRule$1 as p, parseDocx as q, Extension as r, Node as s, AnyExtension as t, parseDocxParagraph as tt, DocxKitOptions as u, TextAlign$1 as v, TocField as w, tiptapNodeExtensions as x, docxExtensions as y, wpsShapeStyles as z };