@docen/docx 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +2 -3
  2. package/dist/converters/docx.d.mts +95 -5
  3. package/dist/converters/docx.mjs +732 -82
  4. package/dist/converters/html.d.mts +20 -5
  5. package/dist/converters/html.mjs +94 -8
  6. package/dist/converters/markdown.d.mts +1 -1
  7. package/dist/converters/markdown.mjs +1 -1
  8. package/dist/converters/patch.d.mts +1 -1
  9. package/dist/converters/patch.mjs +4 -5
  10. package/dist/converters/prepare.d.mts +15 -3
  11. package/dist/converters/prepare.mjs +50 -4
  12. package/dist/converters/styles.d.mts +85 -0
  13. package/dist/converters/styles.mjs +285 -0
  14. package/dist/core-C9VunJ8o.d.mts +174 -0
  15. package/dist/core-DT9IrTzN.mjs +670 -0
  16. package/dist/core.d.mts +1 -1
  17. package/dist/core.mjs +1 -1
  18. package/dist/document-BH1y4qHM.d.mts +6 -0
  19. package/dist/editor.d.mts +1 -1
  20. package/dist/editor.mjs +3 -2
  21. package/dist/extensions/blockquote.d.mts +23 -0
  22. package/dist/extensions/blockquote.mjs +31 -0
  23. package/dist/extensions/code-block.d.mts +19 -0
  24. package/dist/extensions/code-block.mjs +23 -0
  25. package/dist/extensions/column-break.d.mts +31 -0
  26. package/dist/extensions/column-break.mjs +2 -0
  27. package/dist/extensions/details.d.mts +19 -0
  28. package/dist/extensions/details.mjs +18 -0
  29. package/dist/extensions/document.d.mts +2 -0
  30. package/dist/extensions/document.mjs +50 -0
  31. package/dist/extensions/extensions.d.mts +5 -5
  32. package/dist/extensions/extensions.mjs +4 -3
  33. package/dist/extensions/formatting-marks.d.mts +38 -0
  34. package/dist/extensions/formatting-marks.mjs +2 -0
  35. package/dist/extensions/heading.mjs +24 -3
  36. package/dist/extensions/image.d.mts +2 -2
  37. package/dist/extensions/image.mjs +244 -49
  38. package/dist/extensions/index.d.mts +4 -2
  39. package/dist/extensions/index.mjs +4 -2
  40. package/dist/extensions/mention.d.mts +25 -0
  41. package/dist/extensions/mention.mjs +44 -0
  42. package/dist/extensions/ordered-list.d.mts +25 -0
  43. package/dist/extensions/ordered-list.mjs +41 -0
  44. package/dist/extensions/page-break.d.mts +2 -0
  45. package/dist/extensions/page-break.mjs +2 -0
  46. package/dist/extensions/paragraph.d.mts +1 -1
  47. package/dist/extensions/paragraph.mjs +39 -4
  48. package/dist/extensions/passthrough.d.mts +2 -0
  49. package/dist/extensions/passthrough.mjs +2 -0
  50. package/dist/extensions/section-break.d.mts +44 -0
  51. package/dist/extensions/section-break.mjs +2 -0
  52. package/dist/extensions/table.mjs +29 -3
  53. package/dist/extensions/task-item.d.mts +27 -0
  54. package/dist/extensions/task-item.mjs +37 -0
  55. package/dist/extensions/text-style.mjs +20 -3
  56. package/dist/extensions/tiptap.d.mts +2 -2
  57. package/dist/extensions/tiptap.mjs +1 -3
  58. package/dist/extensions/types.d.mts +7 -5
  59. package/dist/extensions/utils.d.mts +2 -49
  60. package/dist/extensions/utils.mjs +222 -12
  61. package/dist/extensions/wpg-group.d.mts +2 -0
  62. package/dist/extensions/wpg-group.mjs +2 -0
  63. package/dist/extensions/wps-shape.d.mts +2 -0
  64. package/dist/extensions/wps-shape.mjs +2 -0
  65. package/dist/index.d.mts +127 -18
  66. package/dist/index.mjs +7 -2
  67. package/dist/paragraph-D8mpHo_o.d.mts +8 -0
  68. package/dist/{tiptap-TErPjuNJ.d.mts → tiptap-pZsNPsvV.d.mts} +1 -3
  69. package/dist/utils-D87vukzp.d.mts +128 -0
  70. package/package.json +40 -40
  71. package/dist/core-CFIQVRfx.mjs +0 -88
  72. package/dist/core-omBKMRtl.d.mts +0 -34
  73. package/dist/image-Ge1y6uam.d.mts +0 -47
  74. package/dist/paragraph-fhEXtAN2.d.mts +0 -16
package/dist/editor.mjs CHANGED
@@ -1,13 +1,14 @@
1
- import { s as docxExtensions, t as Editor } from "./core-CFIQVRfx.mjs";
1
+ import { s as docxExtensions, t as Editor } from "./core-DT9IrTzN.mjs";
2
2
  //#region src/editor.ts
3
3
  /**
4
4
  * Create a Tiptap editor configured for DOCX editing.
5
5
  */
6
6
  function createDocxEditor(options) {
7
7
  const { element, extensions: extraExtensions = [], content, spellcheck = true, editable = true } = options;
8
+ const extraNames = new Set(extraExtensions.map((e) => e.name).filter(Boolean));
8
9
  return new Editor({
9
10
  element,
10
- extensions: [...docxExtensions, ...extraExtensions],
11
+ extensions: [...docxExtensions.filter((e) => !extraNames.has(e.name)), ...extraExtensions],
11
12
  content: content ?? {
12
13
  type: "doc",
13
14
  content: [{ type: "paragraph" }]
@@ -0,0 +1,23 @@
1
+ import { t as Blockquote } from "../tiptap-pZsNPsvV.mjs";
2
+
3
+ //#region src/extensions/blockquote.d.ts
4
+ /**
5
+ * Blockquote extension — owns the DOCX expression of a blockquote.
6
+ *
7
+ * DOCX has no blockquote element; the convention is a left indent plus a left
8
+ * border on each contained paragraph. This module owns that signature; the
9
+ * DocxManager walks the blockquote's child paragraphs and applies it to each.
10
+ */
11
+ /** Left indent (twips, ~0.5 inch) marking a blockquote. */
12
+ declare const BLOCKQUOTE_INDENT_LEFT = 720;
13
+ /** Left border marking a blockquote. */
14
+ declare const BLOCKQUOTE_BORDER: {
15
+ readonly style: "single";
16
+ readonly size: 18;
17
+ readonly space: 12;
18
+ readonly color: "CCCCCC";
19
+ };
20
+ /** Apply the blockquote signature (left indent + left border) to paragraph opts. */
21
+ declare function applyBlockquoteStyle(paraObj: Record<string, unknown>): void;
22
+ //#endregion
23
+ export { BLOCKQUOTE_BORDER, BLOCKQUOTE_INDENT_LEFT, Blockquote, applyBlockquoteStyle };
@@ -0,0 +1,31 @@
1
+ import { Blockquote } from "./tiptap.mjs";
2
+ //#region src/extensions/blockquote.ts
3
+ /**
4
+ * Blockquote extension — owns the DOCX expression of a blockquote.
5
+ *
6
+ * DOCX has no blockquote element; the convention is a left indent plus a left
7
+ * border on each contained paragraph. This module owns that signature; the
8
+ * DocxManager walks the blockquote's child paragraphs and applies it to each.
9
+ */
10
+ /** Left indent (twips, ~0.5 inch) marking a blockquote. */
11
+ const BLOCKQUOTE_INDENT_LEFT = 720;
12
+ /** Left border marking a blockquote. */
13
+ const BLOCKQUOTE_BORDER = {
14
+ style: "single",
15
+ size: 18,
16
+ space: 12,
17
+ color: "CCCCCC"
18
+ };
19
+ /** Apply the blockquote signature (left indent + left border) to paragraph opts. */
20
+ function applyBlockquoteStyle(paraObj) {
21
+ paraObj.indent = {
22
+ ...paraObj.indent ?? {},
23
+ left: 720
24
+ };
25
+ paraObj.border = {
26
+ ...paraObj.border ?? {},
27
+ left: BLOCKQUOTE_BORDER
28
+ };
29
+ }
30
+ //#endregion
31
+ export { BLOCKQUOTE_BORDER, BLOCKQUOTE_INDENT_LEFT, Blockquote, applyBlockquoteStyle };
@@ -0,0 +1,19 @@
1
+ import { a as JSONContent } from "../core-C9VunJ8o.mjs";
2
+
3
+ //#region src/extensions/code-block.d.ts
4
+ /**
5
+ * CodeBlock extension — CodeBlockLowlight with a DOCX renderDocx.
6
+ *
7
+ * DOCX has no dedicated code-block element. A code block maps to a single
8
+ * paragraph styled "Code" with a monospace run font. Inline marks (syntax-
9
+ * highlight tokens) and line breaks (`\n` → `<w:br/>`) are handled by
10
+ * DocxManager's shared inline-content compilation; resolveCodeBlock reassembles
11
+ * the text. This module owns only the paragraph-level style.
12
+ *
13
+ * `language` has no OOXML carrier and is intentionally dropped (known lossy).
14
+ */
15
+ /** codeBlock node → paragraph properties (style "Code" + monospace font). */
16
+ declare function renderDocx(_node: JSONContent): Record<string, unknown>;
17
+ declare const CodeBlock: import("@tiptap/core").Node<import("@tiptap/extension-code-block-lowlight").CodeBlockLowlightOptions, any>;
18
+ //#endregion
19
+ export { CodeBlock, renderDocx };
@@ -0,0 +1,23 @@
1
+ import { CodeBlockLowlight } from "./tiptap.mjs";
2
+ //#region src/extensions/code-block.ts
3
+ /**
4
+ * CodeBlock extension — CodeBlockLowlight with a DOCX renderDocx.
5
+ *
6
+ * DOCX has no dedicated code-block element. A code block maps to a single
7
+ * paragraph styled "Code" with a monospace run font. Inline marks (syntax-
8
+ * highlight tokens) and line breaks (`\n` → `<w:br/>`) are handled by
9
+ * DocxManager's shared inline-content compilation; resolveCodeBlock reassembles
10
+ * the text. This module owns only the paragraph-level style.
11
+ *
12
+ * `language` has no OOXML carrier and is intentionally dropped (known lossy).
13
+ */
14
+ /** codeBlock node → paragraph properties (style "Code" + monospace font). */
15
+ function renderDocx(_node) {
16
+ return {
17
+ style: "Code",
18
+ run: { font: "Consolas" }
19
+ };
20
+ }
21
+ const CodeBlock = CodeBlockLowlight.extend({ renderDocx });
22
+ //#endregion
23
+ export { CodeBlock, renderDocx };
@@ -0,0 +1,31 @@
1
+ import { s as Node } from "../core-C9VunJ8o.mjs";
2
+
3
+ //#region src/extensions/column-break.d.ts
4
+ /**
5
+ * ColumnBreak — inline atom node for DOCX column breaks (`<w:br w:type="column"/>`).
6
+ *
7
+ * Sibling to PageBreak and HardBreak: all three render `<w:br>`, differing only
8
+ * by type. Inline (group "inline") to match the run-internal OOXML position,
9
+ * keeping a column break inside its paragraph on round-trip. Visual column
10
+ * layout (paged.js multi-column) is a future concern; the node preserves the
11
+ * break losslessly regardless.
12
+ *
13
+ * The DOCX payload (`{ columnBreak: true }`) is inlined in DocxManager — a
14
+ * one-liner with no per-node variance, so no extension helper for it.
15
+ *
16
+ * `setColumnBreak` only inserts the atom (no paragraph split): a column break
17
+ * does not start a new page, and there is no column layout to reflow yet, so
18
+ * the node is purely for round-trip fidelity until multi-column lands.
19
+ */
20
+ declare const ColumnBreak: Node<any, any>;
21
+ declare module "@tiptap/core" {
22
+ interface Commands<ReturnType> {
23
+ columnBreak: {
24
+ /** Insert a column break atom at the cursor (round-trip only until
25
+ * multi-column layout lands). */
26
+ setColumnBreak: () => ReturnType;
27
+ };
28
+ }
29
+ }
30
+ //#endregion
31
+ export { ColumnBreak };
@@ -0,0 +1,2 @@
1
+ import { v as ColumnBreak } from "../core-DT9IrTzN.mjs";
2
+ export { ColumnBreak };
@@ -0,0 +1,19 @@
1
+ import { c as DetailsSummary, o as Details, s as DetailsContent } from "../tiptap-pZsNPsvV.mjs";
2
+
3
+ //#region src/extensions/details.d.ts
4
+ /**
5
+ * Details extension — owns the DOCX expression of a collapsible details block.
6
+ *
7
+ * DOCX has no native collapsible region, but a block-level group-SDT is a
8
+ * reversible container. The details maps to one group-SDT tagged "docen-
9
+ * details"; the summary paragraph is marked with a fixed style so resolve can
10
+ * split it back out from the content paragraphs. Structure round-trips fully
11
+ * (summary + content); Word shows it expanded (no collapse) — an inherent
12
+ * DOCX limitation, not data loss.
13
+ */
14
+ /** SDT tag marking a details group content control. */
15
+ declare const DETAILS_TAG = "docen-details";
16
+ /** Paragraph style marking the summary line within a details group-SDT. */
17
+ declare const DETAILS_SUMMARY_STYLE = "DocenDetailsSummary";
18
+ //#endregion
19
+ export { DETAILS_SUMMARY_STYLE, DETAILS_TAG, Details, DetailsContent, DetailsSummary };
@@ -0,0 +1,18 @@
1
+ import { Details, DetailsContent, DetailsSummary } from "./tiptap.mjs";
2
+ //#region src/extensions/details.ts
3
+ /**
4
+ * Details extension — owns the DOCX expression of a collapsible details block.
5
+ *
6
+ * DOCX has no native collapsible region, but a block-level group-SDT is a
7
+ * reversible container. The details maps to one group-SDT tagged "docen-
8
+ * details"; the summary paragraph is marked with a fixed style so resolve can
9
+ * split it back out from the content paragraphs. Structure round-trips fully
10
+ * (summary + content); Word shows it expanded (no collapse) — an inherent
11
+ * DOCX limitation, not data loss.
12
+ */
13
+ /** SDT tag marking a details group content control. */
14
+ const DETAILS_TAG = "docen-details";
15
+ /** Paragraph style marking the summary line within a details group-SDT. */
16
+ const DETAILS_SUMMARY_STYLE = "DocenDetailsSummary";
17
+ //#endregion
18
+ export { DETAILS_SUMMARY_STYLE, DETAILS_TAG, Details, DetailsContent, DetailsSummary };
@@ -0,0 +1,2 @@
1
+ import { n as createDocument, t as Document } from "../document-BH1y4qHM.mjs";
2
+ export { Document, createDocument };
@@ -0,0 +1,50 @@
1
+ import { Document as Document$1 } from "./tiptap.mjs";
2
+ //#region src/extensions/document.ts
3
+ /**
4
+ * Document extension carrying DOCX document-level data through the Tiptap JSON
5
+ * for lossless round-trip (declared as attrs so editor setContent → getJSON
6
+ * preserves them, not just the standalone converters):
7
+ *
8
+ * - `attrs.styles` — office-open `StylesOptions` (styles.xml: importedStyles /
9
+ * docDefaultsXml / latentStylesXml as raw XML).
10
+ * - `attrs.core` — docProps/core.xml properties (title/creator/description/…,
11
+ * see DocxCoreProperties in converters/docx.ts).
12
+ * - `attrs.sectionProperties` — the last section's page layout (page size/margin/
13
+ * orientation, columns, type, grid; intermediate sections carry theirs on
14
+ * sectionBreak nodes).
15
+ *
16
+ * None rendered to HTML — phase 2 applies styles via injected CSS.
17
+ *
18
+ * Factory form (`createDocument`): the editor layer needs a different top-level
19
+ * content expression (`doc > page+` for the C-route editing schema) but the SAME
20
+ * DOCX attrs. Building it via this factory keeps the Document definition in ONE
21
+ * place (here) — the editor parameterizes only `content`, instead of `.extend`-
22
+ * overriding this Document and re-stating the attrs. `Document` is the default
23
+ * flat `doc > block+` shape used by the docx package itself.
24
+ */
25
+ const attrNative = () => ({
26
+ default: null,
27
+ parseHTML: () => null,
28
+ rendered: false
29
+ });
30
+ function createDocument(content = "block+") {
31
+ return Document$1.extend({
32
+ content,
33
+ addAttributes() {
34
+ return {
35
+ ...this.parent?.(),
36
+ styles: attrNative(),
37
+ core: attrNative(),
38
+ sectionProperties: attrNative(),
39
+ sectionHeaders: attrNative(),
40
+ sectionFooters: attrNative(),
41
+ background: attrNative(),
42
+ documentExtras: attrNative()
43
+ };
44
+ }
45
+ });
46
+ }
47
+ /** Default flat Document (`doc > block+`) — the DOCX round-trip shape. */
48
+ const Document = createDocument();
49
+ //#endregion
50
+ export { Document, createDocument };
@@ -1,12 +1,12 @@
1
- import { B as UndoRedo, C as Mention, D as Subscript, F as Text, N as TaskItem, O as Superscript, P as TaskList, R as TrailingNode, S as Mathematics, a as CodeBlockLowlight, b as ListItem, c as DetailsSummary, d as Emoji, f as Gapcursor, g as HorizontalRule, h as Highlight, i as Code, l as Document, n as Bold, o as Details, p as HardBreak, r as BulletList, s as DetailsContent, t as Blockquote, u as Dropcursor, v as Italic, w as OrderedList, x as ListKeymap, y as Link, z as Underline } from "../tiptap-TErPjuNJ.mjs";
1
+ import { A as TaskItem, F as Underline, M as Text, T as Superscript, _ as Link, a as CodeBlockLowlight, b as Mention, c as DetailsSummary, d as HardBreak, g as Italic, i as Code, j as TaskList, m as HorizontalRule, n as Bold, o as Details, p as Highlight, r as BulletList, s as DetailsContent, t as Blockquote, u as Emoji, v as ListItem, w as Subscript, x as OrderedList, y as Mathematics } from "../tiptap-pZsNPsvV.mjs";
2
+ import { t as Document } from "../document-BH1y4qHM.mjs";
2
3
  import { t as Heading } from "../heading-BvqBD2zX.mjs";
3
- import { t as Image } from "../image-Ge1y6uam.mjs";
4
- import { t as Paragraph } from "../paragraph-fhEXtAN2.mjs";
4
+ import { S as Image, _ as WpgGroup, d as TextAlign, f as docxExtensions, g as WpsShape, h as Passthrough, l as DocxKit, m as tiptapNodeExtensions, p as tiptapMarkExtensions, u as DocxKitOptions } from "../core-C9VunJ8o.mjs";
5
+ import { t as Paragraph } from "../paragraph-D8mpHo_o.mjs";
5
6
  import { t as TableRow } from "../table-row-kgzYkZlW.mjs";
6
7
  import { t as Table } from "../table-BFkfeRp9.mjs";
7
8
  import { t as TableCell } from "../table-cell-D_FV4D2h.mjs";
8
9
  import { t as TableHeader } from "../table-header-KGQ2aEkP.mjs";
9
10
  import { t as Strike } from "../strike-BgWGvjKr.mjs";
10
11
  import { t as TextStyle } from "../text-style-BHdtXkMb.mjs";
11
- import { c as StarterKit, d as docxExtensions, f as tiptapMarkExtensions, l as StarterKitOptions, p as tiptapNodeExtensions, u as TextAlign } from "../core-omBKMRtl.mjs";
12
- export { Blockquote, Bold, BulletList, Code, CodeBlockLowlight, Details, DetailsContent, DetailsSummary, Document, Dropcursor, Emoji, Gapcursor, HardBreak, Heading, Highlight, HorizontalRule, Image, Italic, Link, ListItem, ListKeymap, Mathematics, Mention, OrderedList, Paragraph, StarterKit, StarterKitOptions, Strike, Subscript, Superscript, Table, TableCell, TableHeader, TableRow, TaskItem, TaskList, Text, TextAlign, TextStyle, TrailingNode, Underline, UndoRedo, docxExtensions, tiptapMarkExtensions, tiptapNodeExtensions };
12
+ export { Blockquote, Bold, BulletList, Code, CodeBlockLowlight, Details, DetailsContent, DetailsSummary, Document, DocxKit, DocxKitOptions, Emoji, HardBreak, Heading, Highlight, HorizontalRule, Image, Italic, Link, ListItem, Mathematics, Mention, OrderedList, Paragraph, Passthrough, Strike, Subscript, Superscript, Table, TableCell, TableHeader, TableRow, TaskItem, TaskList, Text, TextAlign, TextStyle, Underline, WpgGroup, WpsShape, docxExtensions, tiptapMarkExtensions, tiptapNodeExtensions };
@@ -1,4 +1,6 @@
1
- import { Blockquote, Bold, BulletList, Code, CodeBlockLowlight, Details, DetailsContent, DetailsSummary, Document, Dropcursor, Emoji, Gapcursor, HardBreak, Highlight, HorizontalRule, Italic, Link, ListItem, ListKeymap, Mathematics, Mention, OrderedList, Subscript, Superscript, TaskItem, TaskList, Text, TrailingNode, Underline, UndoRedo } from "./tiptap.mjs";
1
+ import { Blockquote, Bold, BulletList, Code, CodeBlockLowlight, Details, DetailsContent, DetailsSummary, Emoji, HardBreak, Highlight, HorizontalRule, Italic, Link, ListItem, Mathematics, Mention, OrderedList, Subscript, Superscript, TaskItem, TaskList, Text, Underline } from "./tiptap.mjs";
2
+ import { a as DocxKit, c as tiptapMarkExtensions, d as WpgGroup, h as Passthrough, l as tiptapNodeExtensions, o as TextAlign, s as docxExtensions, u as WpsShape } from "../core-DT9IrTzN.mjs";
3
+ import { Document } from "./document.mjs";
2
4
  import { Heading } from "./heading.mjs";
3
5
  import { Image } from "./image.mjs";
4
6
  import { Paragraph } from "./paragraph.mjs";
@@ -8,5 +10,4 @@ import { TableCell } from "./table-cell.mjs";
8
10
  import { TableHeader } from "./table-header.mjs";
9
11
  import { TableRow } from "./table-row.mjs";
10
12
  import { TextStyle } from "./text-style.mjs";
11
- import { a as StarterKit, c as tiptapMarkExtensions, l as tiptapNodeExtensions, o as TextAlign, s as docxExtensions } from "../core-CFIQVRfx.mjs";
12
- export { Blockquote, Bold, BulletList, Code, CodeBlockLowlight, Details, DetailsContent, DetailsSummary, Document, Dropcursor, Emoji, Gapcursor, HardBreak, Heading, Highlight, HorizontalRule, Image, Italic, Link, ListItem, ListKeymap, Mathematics, Mention, OrderedList, Paragraph, StarterKit, Strike, Subscript, Superscript, Table, TableCell, TableHeader, TableRow, TaskItem, TaskList, Text, TextAlign, TextStyle, TrailingNode, Underline, UndoRedo, docxExtensions, tiptapMarkExtensions, tiptapNodeExtensions };
13
+ export { Blockquote, Bold, BulletList, Code, CodeBlockLowlight, Details, DetailsContent, DetailsSummary, Document, DocxKit, Emoji, HardBreak, Heading, Highlight, HorizontalRule, Image, Italic, Link, ListItem, Mathematics, Mention, OrderedList, Paragraph, Passthrough, Strike, Subscript, Superscript, Table, TableCell, TableHeader, TableRow, TaskItem, TaskList, Text, TextAlign, TextStyle, Underline, WpgGroup, WpsShape, docxExtensions, tiptapMarkExtensions, tiptapNodeExtensions };
@@ -0,0 +1,38 @@
1
+ import { r as Extension } from "../core-C9VunJ8o.mjs";
2
+
3
+ //#region src/extensions/formatting-marks.d.ts
4
+ /**
5
+ * FormattingMarks — paints the non-printing paragraph mark via ProseMirror
6
+ * widget decorations.
7
+ *
8
+ * CSS `p::after { content: "…" }` does NOT work on a ProseMirror-managed
9
+ * paragraph: the view owns the DOM and the trailing-break kludge pushes the
10
+ * pseudo-element off the visible line, so the mark never appears (verified).
11
+ * Marijn Haverbeke endorses widget decorations for exactly this use case
12
+ * (https://discuss.prosemirror.net/t/1442). Each textblock gets a widget at its
13
+ * closing position (inside the textblock, so it stays on the content's line)
14
+ * holding a non-editable `<span class="docen-para-mark">`. `side: 1` keeps the
15
+ * mark to the right of a cursor resting at the paragraph end (the cursor always
16
+ * precedes its own paragraph mark).
17
+ *
18
+ * Glyph: a down-then-left return arrow (↲, U+21B2 "downwards arrow with tip
19
+ * leftwards" — the Enter-key glyph). Word/WPS use the pilcrow ¶ for paragraph
20
+ * marks; that down-then-left arrow is Word's line-break glyph — adopted here as
21
+ * the paragraph mark per the project's visual preference.
22
+ *
23
+ * Performance: the widget set is cached in plugin state and rebuilt only on a
24
+ * doc change or a marks toggle — NOT on every selectionUpdate. Without the
25
+ * cache, each caret move / selection re-traverses the whole document (one
26
+ * widget per textblock) and rebuilds the set, which costs 200ms+ on 1000-page
27
+ * documents. Pure selection transactions now reuse the cached set in O(1).
28
+ */
29
+ declare const FormattingMarks: Extension<any, any>;
30
+ declare module "@tiptap/core" {
31
+ interface Commands<ReturnType> {
32
+ formattingMarks: {
33
+ /** Toggle the non-printing paragraph marks on or off. */toggleFormattingMarks: () => ReturnType;
34
+ };
35
+ }
36
+ }
37
+ //#endregion
38
+ export { FormattingMarks };
@@ -0,0 +1,2 @@
1
+ import { _ as FormattingMarks } from "../core-DT9IrTzN.mjs";
2
+ export { FormattingMarks };
@@ -28,13 +28,19 @@ const HEADING_PARSE_MAP = {
28
28
  Heading6: 6,
29
29
  Title: 1
30
30
  };
31
+ /** Runtime-only attrs the TableOfContents extension injects on each heading
32
+ * (`id` / `data-toc-id`). They are regenerated on every load, so never persist
33
+ * them to DOCX — skip them in renderDocx. */
34
+ const TOC_RUNTIME_KEYS = new Set(["id", "data-toc-id"]);
31
35
  function renderDocx(node) {
32
36
  const attrs = node.attrs ?? {};
33
37
  const opts = {};
34
38
  const level = attrs.level;
35
- if (level) opts.heading = HEADING_COMPILE_MAP[level] ?? "Heading1";
39
+ const styleId = attrs.styleId;
40
+ if (styleId) opts.heading = styleId;
41
+ else if (level) opts.heading = HEADING_COMPILE_MAP[level] ?? "Heading1";
36
42
  for (const [key, value] of Object.entries(attrs)) {
37
- if (key === "level") continue;
43
+ if (key === "level" || key === "styleId" || TOC_RUNTIME_KEYS.has(key)) continue;
38
44
  if (value !== null && value !== void 0) opts[key] = value;
39
45
  }
40
46
  return opts;
@@ -56,7 +62,9 @@ function parseDocx(opts) {
56
62
  if (resolved.heading) {
57
63
  const level = HEADING_PARSE_MAP[resolved.heading];
58
64
  if (level) attrs.level = level;
65
+ attrs.styleId = resolved.heading;
59
66
  }
67
+ if (resolved.style) attrs.styleId = resolved.style;
60
68
  for (const [key, value] of Object.entries(resolved)) {
61
69
  if (SKIP_KEYS.has(key)) continue;
62
70
  attrs[key] = value ?? null;
@@ -72,6 +80,13 @@ const Heading = Heading$1.extend({
72
80
  addAttributes() {
73
81
  return {
74
82
  ...this.parent?.(),
83
+ styleId: {
84
+ default: null,
85
+ parseHTML: (el) => {
86
+ const m = (el.getAttribute("class") || "").match(/(?:^|\s)docx-style-(\S+)/);
87
+ return m ? m[1] : null;
88
+ }
89
+ },
75
90
  alignment: {
76
91
  default: null,
77
92
  rendered: false,
@@ -128,9 +143,15 @@ const Heading = Heading$1.extend({
128
143
  };
129
144
  },
130
145
  renderHTML({ node, HTMLAttributes }) {
131
- const styles = renderParagraphStyles(node.attrs);
146
+ let hasContent = false;
147
+ node.forEach?.((child) => {
148
+ if (child.isText || child.type?.name === "hardBreak" || child.type?.name === "image") hasContent = true;
149
+ });
150
+ const styles = renderParagraphStyles(node.attrs, { empty: !hasContent });
132
151
  const level = node.attrs?.level ?? 1;
133
152
  const attrs = { ...HTMLAttributes };
153
+ const styleId = node.attrs.styleId;
154
+ if (styleId) attrs.class = `docx-style-${styleId}`;
134
155
  if (styles.length > 0) attrs.style = styles.join(";");
135
156
  return [
136
157
  `h${level}`,
@@ -1,2 +1,2 @@
1
- import { i as renderDocx, n as parseDocx, r as renderCropAttrs, t as Image } from "../image-Ge1y6uam.mjs";
2
- export { Image, parseDocx, renderCropAttrs, renderDocx };
1
+ import { C as parseDocx, S as Image, T as renderDocx, w as renderCropAttrs, x as CropRenderContext } from "../core-C9VunJ8o.mjs";
2
+ export { CropRenderContext, Image, parseDocx, renderCropAttrs, renderDocx };