@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
@@ -1,14 +1,29 @@
1
- import { a as JSONContent, i as Extensions } from "../core-omBKMRtl.mjs";
1
+ import { a as JSONContent, i as Extensions } from "../core-C9VunJ8o.mjs";
2
2
  import { ParseOptions } from "@tiptap/pm/model";
3
3
 
4
4
  //#region src/converters/html.d.ts
5
5
  /**
6
- * Parse HTML string to Tiptap JSON.
6
+ * Serialize Tiptap JSON to an HTML string. Renders per-section: each OOXML
7
+ * section (CT_SectPr) becomes a `<section>` carrying its own page margin
8
+ * (padding) and a document-grid line-height (the font's `normal` metric —
9
+ * Word does not add the grid pitch to rendered line height), so paragraph
10
+ * line-spacing multiples resolve against the section's font, not a fallback.
11
+ * The document background (CT_DocumentBase, single for the whole doc) wraps all
12
+ * sections.
13
+ *
14
+ * Same ProseMirror DOMSerializer pipeline as @tiptap/html, on a linkedom
15
+ * document: happy-dom drops calc(var(…)) when re-serializing the style
16
+ * attribute, so DOCX line-spacing survives only with linkedom.
7
17
  */
8
- declare function parseHTML(html: string, extensions?: Extensions, options?: ParseOptions): JSONContent;
18
+ declare function generateHTML(doc: JSONContent, extensions?: Extensions): string;
9
19
  /**
10
- * Generate HTML string from Tiptap JSON.
20
+ * Parse an HTML string into Tiptap JSON. Same ProseMirror DOMParser pipeline as
21
+ * @tiptap/html on a linkedom document. The background wrapper and section
22
+ * containers are unknown elements (no doc/div/section node in the schema), so
23
+ * the parser ignores their tags and extracts the content. Section geometry
24
+ * (linePitch/margins) and the page background are section/doc-level metadata,
25
+ * not content — they round-trip losslessly via DOCX, not HTML.
11
26
  */
12
- declare function generateHTML(doc: JSONContent, extensions?: Extensions): string;
27
+ declare function parseHTML(html: string, extensions?: Extensions, options?: ParseOptions): JSONContent;
13
28
  //#endregion
14
29
  export { generateHTML, parseHTML };
@@ -1,18 +1,104 @@
1
- import { s as docxExtensions } from "../core-CFIQVRfx.mjs";
2
- import { generateHTML as generateHTML$1, generateJSON } from "@tiptap/html";
1
+ import { s as docxExtensions } from "../core-DT9IrTzN.mjs";
2
+ import { sectionLinePitchCss, sectionMarginCss } from "../extensions/utils.mjs";
3
+ import { getSchema } from "@tiptap/core";
4
+ import { encodeBase64 } from "@office-open/core";
5
+ import { DOMParser, DOMSerializer, Node } from "@tiptap/pm/model";
6
+ import { parseHTML as parseHTML$1 } from "linkedom";
3
7
  //#region src/converters/html.ts
4
8
  const defaultExtensions = docxExtensions;
9
+ /** JSON round-trips byte arrays as plain objects ({0:byte,…}); rebuild here. */
10
+ function toBytes(data) {
11
+ if (!data) return null;
12
+ return data instanceof Uint8Array ? data : new Uint8Array(Object.values(data));
13
+ }
14
+ /** Page background → CSS for the root wrapper. Color renders directly; a VML
15
+ * pattern's first media item tiles as an image. OOXML patterns have no CSS
16
+ * equivalent, so DOCX (not HTML) is the fidelity source. */
17
+ function backgroundToCss(bg) {
18
+ const styles = [];
19
+ if (bg?.color) styles.push(`background-color:#${bg.color}`);
20
+ const media = bg?.rawMedia?.[0];
21
+ const bytes = toBytes(media?.data);
22
+ if (bytes) styles.push(`background-image:url(data:image/${media?.type ?? "png"};base64,${encodeBase64(bytes)})`, "background-repeat:repeat");
23
+ return styles.length ? styles.join(";") : void 0;
24
+ }
25
+ /** Split flat `doc > block+` into sections by section-carrying paragraphs.
26
+ * Mirrors DocxManager's compile-time split (converters/docx.ts): a paragraph
27
+ * with `sectionProperties` closes its section; trailing blocks form the final
28
+ * section under doc.attrs.sectionProperties. No section-carrying paragraph →
29
+ * a single section (backward compatible). */
30
+ function splitJsonSections(doc) {
31
+ const sections = [];
32
+ let current = [];
33
+ for (const node of doc.content ?? []) {
34
+ current.push(node);
35
+ const sp = node.attrs?.sectionProperties;
36
+ if (sp != null) {
37
+ sections.push({
38
+ properties: sp,
39
+ blocks: current
40
+ });
41
+ current = [];
42
+ }
43
+ }
44
+ const tailProps = doc.attrs?.sectionProperties;
45
+ sections.push({
46
+ properties: tailProps ?? null,
47
+ blocks: current
48
+ });
49
+ return sections;
50
+ }
5
51
  /**
6
- * Parse HTML string to Tiptap JSON.
52
+ * Serialize Tiptap JSON to an HTML string. Renders per-section: each OOXML
53
+ * section (CT_SectPr) becomes a `<section>` carrying its own page margin
54
+ * (padding) and a document-grid line-height (the font's `normal` metric —
55
+ * Word does not add the grid pitch to rendered line height), so paragraph
56
+ * line-spacing multiples resolve against the section's font, not a fallback.
57
+ * The document background (CT_DocumentBase, single for the whole doc) wraps all
58
+ * sections.
59
+ *
60
+ * Same ProseMirror DOMSerializer pipeline as @tiptap/html, on a linkedom
61
+ * document: happy-dom drops calc(var(…)) when re-serializing the style
62
+ * attribute, so DOCX line-spacing survives only with linkedom.
7
63
  */
8
- function parseHTML(html, extensions, options) {
9
- return generateJSON(html, extensions ?? defaultExtensions, options);
64
+ function generateHTML(doc, extensions = defaultExtensions) {
65
+ const schema = getSchema(extensions);
66
+ const { document } = parseHTML$1("<!DOCTYPE html><html><body></body></html>");
67
+ const serializer = DOMSerializer.fromSchema(schema);
68
+ const parts = [];
69
+ for (const section of splitJsonSections(doc)) {
70
+ const sp = section.properties;
71
+ const styles = [];
72
+ const padding = sectionMarginCss(sp?.page?.margin);
73
+ if (padding) styles.push(padding);
74
+ styles.push(...sectionLinePitchCss(sp?.grid));
75
+ const sec = document.createElement("section");
76
+ if (styles.length) sec.setAttribute("style", styles.join(";"));
77
+ if (section.blocks.length) {
78
+ const fragment = Node.fromJSON(schema, {
79
+ type: "doc",
80
+ content: section.blocks
81
+ }).content;
82
+ serializer.serializeFragment(fragment, { document }, sec);
83
+ }
84
+ parts.push(sec.outerHTML);
85
+ }
86
+ const body = parts.join("");
87
+ const bgCss = backgroundToCss(doc.attrs?.background);
88
+ return bgCss ? `<div style="${bgCss}">${body}</div>` : body;
10
89
  }
11
90
  /**
12
- * Generate HTML string from Tiptap JSON.
91
+ * Parse an HTML string into Tiptap JSON. Same ProseMirror DOMParser pipeline as
92
+ * @tiptap/html on a linkedom document. The background wrapper and section
93
+ * containers are unknown elements (no doc/div/section node in the schema), so
94
+ * the parser ignores their tags and extracts the content. Section geometry
95
+ * (linePitch/margins) and the page background are section/doc-level metadata,
96
+ * not content — they round-trip losslessly via DOCX, not HTML.
13
97
  */
14
- function generateHTML(doc, extensions) {
15
- return generateHTML$1(doc, extensions ?? defaultExtensions);
98
+ function parseHTML(html, extensions = defaultExtensions, options) {
99
+ const schema = getSchema(extensions);
100
+ const { document } = parseHTML$1(`<!DOCTYPE html><html><body>${html}</body></html>`);
101
+ return DOMParser.fromSchema(schema).parse(document.body, options).toJSON();
16
102
  }
17
103
  //#endregion
18
104
  export { generateHTML, parseHTML };
@@ -1,4 +1,4 @@
1
- import { a as JSONContent } from "../core-omBKMRtl.mjs";
1
+ import { a as JSONContent } from "../core-C9VunJ8o.mjs";
2
2
 
3
3
  //#region src/converters/markdown.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { s as docxExtensions } from "../core-CFIQVRfx.mjs";
1
+ import { s as docxExtensions } from "../core-DT9IrTzN.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-omBKMRtl.mjs";
1
+ import { a as JSONContent } from "../core-C9VunJ8o.mjs";
2
2
  import { PrepareStep } from "./prepare.mjs";
3
3
  import { OutputByType, OutputType, patchDocument } from "@office-open/docx";
4
4
 
@@ -1,6 +1,6 @@
1
1
  import { prepareDocument } from "./prepare.mjs";
2
2
  import { compileDocument } from "./docx.mjs";
3
- import { PatchType, patchDocument } from "@office-open/docx";
3
+ import { patchDocument } from "@office-open/docx";
4
4
  //#region src/converters/patch.ts
5
5
  /**
6
6
  * Patch a DOCX template by replacing placeholders with Tiptap-JSON content.
@@ -15,16 +15,15 @@ async function patchDOCX(options) {
15
15
  const patchesObject = {};
16
16
  for (const [key, patchContent] of Object.entries(patches)) {
17
17
  if (prepare !== false) await prepareDocument(patchContent.content, prepare === true ? void 0 : prepare);
18
- const children = compileDocument(patchContent.content).sections?.[0]?.children ?? [];
19
18
  patchesObject[key] = {
20
- type: PatchType.DOCUMENT,
21
- children
19
+ type: "document",
20
+ children: compileDocument(patchContent.content).sections?.[0]?.children ?? []
22
21
  };
23
22
  }
24
23
  return patchDocument({
25
24
  outputType,
26
25
  data: template,
27
- patches: patchesObject,
26
+ placeholders: patchesObject,
28
27
  ...keepOriginalStyles !== void 0 && { keepOriginalStyles },
29
28
  ...recursive !== void 0 && { recursive },
30
29
  ...placeholderDelimiters && { placeholderDelimiters: {
@@ -1,4 +1,4 @@
1
- import { a as JSONContent } from "../core-omBKMRtl.mjs";
1
+ import { a as JSONContent } from "../core-C9VunJ8o.mjs";
2
2
 
3
3
  //#region src/converters/prepare.d.ts
4
4
  /**
@@ -31,13 +31,25 @@ declare function fetchImageHandler(url: string): Promise<Uint8Array>;
31
31
  * ```
32
32
  */
33
33
  declare function prepareImages(handler?: ImageFetchHandler): PrepareStep;
34
+ /**
35
+ * Create a prepare step that fills in missing image dimensions by reading image
36
+ * metadata. Intended to run after {@link prepareImages} so HTTP sources are
37
+ * already embedded as data URLs.
38
+ *
39
+ * Only images lacking `width` or `height` are probed — the DOCX round-trip path
40
+ * already carries `transformation.width/height`, so this mainly serves images
41
+ * entering via HTML/Markdown (which carry no intrinsic size). Images whose
42
+ * metadata can't be read are left untouched; `renderDocx` falls back to 600×400
43
+ * (see extensions/image.ts).
44
+ */
45
+ declare function prepareImageSizes(): PrepareStep;
34
46
  /**
35
47
  * Run prepare steps on a Tiptap JSON document before compilation.
36
48
  *
37
49
  * Each step receives the JSON and may mutate it in place (e.g. replace external
38
50
  * URLs with embedded data). Steps run sequentially in order.
39
51
  *
40
- * Defaults to `[prepareImages()]` when no steps are provided.
52
+ * Defaults to `[prepareImages(), prepareImageSizes()]` when no steps are provided.
41
53
  *
42
54
  * @example
43
55
  * ```ts
@@ -48,4 +60,4 @@ declare function prepareImages(handler?: ImageFetchHandler): PrepareStep;
48
60
  */
49
61
  declare function prepareDocument(json: JSONContent, steps?: readonly PrepareStep[]): Promise<void>;
50
62
  //#endregion
51
- export { ImageFetchHandler, PrepareStep, fetchImageHandler, prepareDocument, prepareImages };
63
+ export { ImageFetchHandler, PrepareStep, fetchImageHandler, prepareDocument, prepareImageSizes, prepareImages };
@@ -1,3 +1,5 @@
1
+ import { encodeBase64 } from "@office-open/core";
2
+ import { imageMeta } from "image-meta";
1
3
  //#region src/converters/prepare.ts
2
4
  /**
3
5
  * Default fetch handler using the global `fetch` API (Node 18+ and browsers).
@@ -27,15 +29,31 @@ function prepareImages(handler = fetchImageHandler) {
27
29
  await walkImages(json, handler);
28
30
  };
29
31
  }
32
+ /**
33
+ * Create a prepare step that fills in missing image dimensions by reading image
34
+ * metadata. Intended to run after {@link prepareImages} so HTTP sources are
35
+ * already embedded as data URLs.
36
+ *
37
+ * Only images lacking `width` or `height` are probed — the DOCX round-trip path
38
+ * already carries `transformation.width/height`, so this mainly serves images
39
+ * entering via HTML/Markdown (which carry no intrinsic size). Images whose
40
+ * metadata can't be read are left untouched; `renderDocx` falls back to 600×400
41
+ * (see extensions/image.ts).
42
+ */
43
+ function prepareImageSizes() {
44
+ return async (json) => {
45
+ await walkImageSizes(json);
46
+ };
47
+ }
30
48
  /** Built-in prepare steps, run when no custom steps are provided. */
31
- const DEFAULT_STEPS = [prepareImages()];
49
+ const DEFAULT_STEPS = [prepareImages(), prepareImageSizes()];
32
50
  /**
33
51
  * Run prepare steps on a Tiptap JSON document before compilation.
34
52
  *
35
53
  * Each step receives the JSON and may mutate it in place (e.g. replace external
36
54
  * URLs with embedded data). Steps run sequentially in order.
37
55
  *
38
- * Defaults to `[prepareImages()]` when no steps are provided.
56
+ * Defaults to `[prepareImages(), prepareImageSizes()]` when no steps are provided.
39
57
  *
40
58
  * @example
41
59
  * ```ts
@@ -57,7 +75,7 @@ async function toDataUrl(src, handler) {
57
75
  bmp: "image/bmp",
58
76
  svg: "image/svg+xml",
59
77
  webp: "image/webp"
60
- }[src.split(".").pop()?.toLowerCase() ?? "png"] ?? "image/png"};base64,${typeof btoa !== "undefined" ? btoa(String.fromCharCode(...data)) : Buffer.from(data).toString("base64")}`;
78
+ }[src.split(".").pop()?.toLowerCase() ?? "png"] ?? "image/png"};base64,${encodeBase64(data)}`;
61
79
  }
62
80
  async function walkImages(node, handler) {
63
81
  if (node.type === "image" && node.attrs) {
@@ -72,5 +90,33 @@ async function walkImages(node, handler) {
72
90
  for (const child of node.content ?? []) tasks.push(walkImages(child, handler));
73
91
  await Promise.all(tasks);
74
92
  }
93
+ async function walkImageSizes(node) {
94
+ if (node.type === "image" && node.attrs) {
95
+ const attrs = node.attrs;
96
+ const needsWidth = attrs.width == null;
97
+ const needsHeight = attrs.height == null;
98
+ if (needsWidth || needsHeight) {
99
+ const bytes = decodeDataUrl(attrs.src);
100
+ if (bytes) try {
101
+ const meta = imageMeta(bytes);
102
+ if (needsWidth && typeof meta.width === "number") attrs.width = meta.width;
103
+ if (needsHeight && typeof meta.height === "number") attrs.height = meta.height;
104
+ } catch {}
105
+ }
106
+ }
107
+ const tasks = [];
108
+ for (const child of node.content ?? []) tasks.push(walkImageSizes(child));
109
+ await Promise.all(tasks);
110
+ }
111
+ /** Decode a `data:image/...;base64,...` URL to bytes; null if not a data URL. */
112
+ function decodeDataUrl(src) {
113
+ if (!src) return null;
114
+ const match = src.match(/^data:image\/[\w.+-]+;base64,(.+)$/);
115
+ if (!match) return null;
116
+ const binary = atob(match[1]);
117
+ const bytes = new Uint8Array(binary.length);
118
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
119
+ return bytes;
120
+ }
75
121
  //#endregion
76
- export { fetchImageHandler, prepareDocument, prepareImages };
122
+ export { fetchImageHandler, prepareDocument, prepareImageSizes, prepareImages };
@@ -0,0 +1,85 @@
1
+ import { JSONContent } from "@tiptap/core";
2
+ import { StylesOptions } from "@office-open/docx";
3
+
4
+ //#region src/converters/styles.d.ts
5
+ /** The styleId of the document's default paragraph style (`w:default="1"`
6
+ * type="paragraph") — the implicit style applied to every paragraph WITHOUT an
7
+ * explicit pStyle. OOXML renders a pStyle-less paragraph as this style (usually
8
+ * "Normal"), so the editor's `.docx-default` class — emitted by Paragraph/
9
+ * Heading renderHTML on a styleId-less node — targets it. Searched in
10
+ * `paragraphStyles` and the built-in named styles nested under `default`
11
+ * (key → pStyle id). null when the document declares none. */
12
+ declare function defaultParagraphStyleId(styles: StylesOptions | null | undefined): string | null;
13
+ /**
14
+ * Generate scoped CSS from a document's `styles.xml` model (`StylesOptions`) so
15
+ * named paragraph/character styles and the document defaults render correctly
16
+ * in the editor. All rules are scoped to `.docen-page` (the editor's page
17
+ * surface); the editor injects the result into a `<style>` after load.
18
+ *
19
+ * - `default.document` → `.docen-page` base run + paragraph defaults (the doc's
20
+ * default font/size, line spacing, …).
21
+ * - `paragraphStyles[]` → `.docen-page .docx-style-{id}` (run + paragraph CSS).
22
+ * Paragraph nodes carry `class="docx-style-{styleId}"` (see the Paragraph /
23
+ * Heading extensions' pStyle ↔ styleId round-trip).
24
+ * - `characterStyles[]` → `.docen-page .docx-char-{id}` (run CSS).
25
+ *
26
+ * `basedOn` inheritance is deep-merged per-property into each named style's
27
+ * rule (root first, child overrides) — see mergeStyleChain. CSS inheritance
28
+ * follows the DOM tree, not a style's basedOn, so each `.docx-style-{id}` rule
29
+ * carries its full ancestor chain rather than relying on source order.
30
+ */
31
+ declare function stylesToCss(styles: StylesOptions | null | undefined, scope: string): string;
32
+ /** A gallery-ready paragraph-style entry for the Styles combobox. */
33
+ interface QuickStyleEntry {
34
+ id: string;
35
+ name: string;
36
+ }
37
+ /**
38
+ * The paragraph styles to list in the Quick Styles gallery, matching Word's
39
+ * default behavior: the gallery is a *paragraph-style* selector (it applies a
40
+ * pStyle), so only paragraph styles appear — never character styles, even
41
+ * those flagged `quickFormat` (those live in the Styles task pane). Among
42
+ * paragraph styles, only those flagged `quickFormat` are listed, ordered by
43
+ * `uiPriority` (Word orders the gallery this way).
44
+ *
45
+ * Reads `quickFormat`/`uiPriority`/`name` straight from office-open's styles
46
+ * model (`StylesOptions`): `paragraphStyles` (Normal + custom) and the built-in
47
+ * named paragraph styles nested under `default` (title/heading1-9/quote/…). The
48
+ * `default` keys that hold character styles are excluded via
49
+ * `CHARACTER_DEFAULT_KEYS`. When a document carries no quickFormat flags at all
50
+ * (e.g. some LibreOffice-generated files), fall back to all paragraph styles so
51
+ * the gallery is never empty.
52
+ */
53
+ declare function quickStyles(styles: StylesOptions | null | undefined): QuickStyleEntry[];
54
+ /** Resolve the effective run-level properties (font name, size in points) at the
55
+ * caret, staying in the document's own units — no px conversion. Priority:
56
+ * direct run props (the textStyle mark) → the paragraph style (`styleId`) →
57
+ * its `basedOn` chain → the document defaults. `font` is resolved to a single
58
+ * display name (ascii/hAnsi/eastAsia). Returns null where nothing in the chain
59
+ * sets a property, so the caller can leave the box empty. */
60
+ declare function effectiveRunProps(styles: StylesOptions | null | undefined, styleId: string | null | undefined, direct?: {
61
+ font?: unknown;
62
+ size?: unknown;
63
+ }): {
64
+ font: string | null;
65
+ size: number | null;
66
+ };
67
+ /**
68
+ * Inline a document's styles into each node's attrs — a self-contained
69
+ * JSONContent that round-trips and renders without the styles context. A
70
+ * paragraph/heading absorbs its styleId's `basedOn` chain (paragraph properties
71
+ * + the paragraph's default `run`); a textStyle mark absorbs its character
72
+ * style's run. Explicit attrs/marks always override the inherited values;
73
+ * styleId is preserved (the semantic reference is kept). The style definitions
74
+ * themselves are untouched — only properties are copied onto nodes.
75
+ *
76
+ * Styles default to the document's own `attrs.styles` (the round-tripped
77
+ * styles.xml model carried on the doc node), so `inlineStyles(doc)` needs no
78
+ * second argument; pass `styles` explicitly to override. Use cases:
79
+ * cross-document paste (the snippet carries its styling) and self-contained
80
+ * export. The editor still renders via global styles — this only merges JSON
81
+ * properties.
82
+ */
83
+ declare function inlineStyles(json: JSONContent, styles?: StylesOptions | null): JSONContent;
84
+ //#endregion
85
+ export { QuickStyleEntry, type StylesOptions, defaultParagraphStyleId, effectiveRunProps, inlineStyles, quickStyles, stylesToCss };