@docen/docx 0.3.0 → 0.3.1
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.
- package/README.md +2 -3
- package/dist/blockquote-Ky9xD_Q-.mjs +31 -0
- package/dist/code-block-BgNjhADy.mjs +23 -0
- package/dist/converters/docx.d.mts +1 -109
- package/dist/converters/docx.mjs +1 -623
- package/dist/converters/html.d.mts +1 -13
- package/dist/converters/html.mjs +1 -17
- package/dist/converters/markdown.d.mts +1 -12
- package/dist/converters/markdown.mjs +1 -17
- package/dist/converters/patch.d.mts +1 -52
- package/dist/converters/patch.mjs +1 -36
- package/dist/converters/prepare.d.mts +2 -51
- package/dist/converters/prepare.mjs +2 -76
- package/dist/converters/styles.d.mts +2 -0
- package/dist/converters/styles.mjs +2 -0
- package/dist/core-DEqBHRzE.mjs +406 -0
- package/dist/core-fBMCCj4D.d.mts +97 -0
- package/dist/core.d.mts +1 -1
- package/dist/core.mjs +1 -1
- package/dist/details-Dh8luWb2.mjs +18 -0
- package/dist/dist-B6B3HnVZ.mjs +1838 -0
- package/dist/document-BH1y4qHM.d.mts +6 -0
- package/dist/document-CvTym-FM.mjs +50 -0
- package/dist/docx-C5wyjI-0.d.mts +200 -0
- package/dist/docx-CONyAedl.mjs +1231 -0
- package/dist/editor-Bf3CxQnY.mjs +21 -0
- package/dist/editor-DReY3Rb9.d.mts +21 -0
- package/dist/editor.d.mts +1 -20
- package/dist/editor.mjs +1 -19
- package/dist/emoji-BZ1dJD7d.d.mts +17 -0
- package/dist/emoji-C2OsTWR7.mjs +27 -0
- package/dist/extensions/blockquote.d.mts +23 -0
- package/dist/extensions/blockquote.mjs +3 -0
- package/dist/extensions/code-block.d.mts +19 -0
- package/dist/extensions/code-block.mjs +2 -0
- package/dist/extensions/column-break.d.mts +31 -0
- package/dist/extensions/column-break.mjs +2 -0
- package/dist/extensions/details.d.mts +19 -0
- package/dist/extensions/details.mjs +3 -0
- package/dist/extensions/document.d.mts +2 -0
- package/dist/extensions/document.mjs +2 -0
- package/dist/extensions/emoji.d.mts +2 -0
- package/dist/extensions/emoji.mjs +2 -0
- package/dist/extensions/extensions.d.mts +6 -5
- package/dist/extensions/extensions.mjs +14 -12
- package/dist/extensions/formatting-marks.d.mts +32 -0
- package/dist/extensions/formatting-marks.mjs +2 -0
- package/dist/extensions/heading.mjs +1 -144
- package/dist/extensions/image-group.d.mts +6 -0
- package/dist/extensions/image-group.mjs +2 -0
- package/dist/extensions/image.d.mts +2 -2
- package/dist/extensions/image.mjs +1 -200
- package/dist/extensions/index.d.mts +3 -2
- package/dist/extensions/index.mjs +3 -2
- package/dist/extensions/mention.d.mts +25 -0
- package/dist/extensions/mention.mjs +3 -0
- package/dist/extensions/ordered-list.d.mts +25 -0
- package/dist/extensions/ordered-list.mjs +3 -0
- package/dist/extensions/page-break.d.mts +34 -0
- package/dist/extensions/page-break.mjs +2 -0
- package/dist/extensions/paragraph.d.mts +1 -1
- package/dist/extensions/paragraph.mjs +1 -115
- package/dist/extensions/passthrough.d.mts +2 -0
- package/dist/extensions/passthrough.mjs +2 -0
- package/dist/extensions/section-break.d.mts +27 -0
- package/dist/extensions/section-break.mjs +2 -0
- package/dist/extensions/strike.mjs +1 -49
- package/dist/extensions/table-cell.mjs +1 -111
- package/dist/extensions/table-header.mjs +1 -111
- package/dist/extensions/table-row.mjs +1 -83
- package/dist/extensions/table.mjs +1 -133
- package/dist/extensions/task-item.d.mts +27 -0
- package/dist/extensions/task-item.mjs +3 -0
- package/dist/extensions/text-style.mjs +1 -133
- package/dist/extensions/tiptap.mjs +1 -32
- package/dist/extensions/types.d.mts +7 -5
- package/dist/extensions/utils.d.mts +16 -3
- package/dist/extensions/utils.mjs +2 -289
- package/dist/heading-DAubgJJN.mjs +166 -0
- package/dist/html-DCC_DSHv.d.mts +18 -0
- package/dist/html-DedDWPoO.mjs +66 -0
- package/dist/image-CuEIXoZl.mjs +334 -0
- package/dist/index.d.mts +68 -18
- package/dist/index.mjs +10 -8
- package/dist/markdown-BzJmRsBs.mjs +18 -0
- package/dist/markdown-D0k0sRYS.d.mts +13 -0
- package/dist/mention-C-dTR6MK.mjs +44 -0
- package/dist/ordered-list-V-3xFQmV.mjs +41 -0
- package/dist/paragraph-BrWH-BOV.mjs +147 -0
- package/dist/paragraph-D8mpHo_o.d.mts +8 -0
- package/dist/patch-Cdp5WKJz.d.mts +53 -0
- package/dist/patch-IZ13tXTu.mjs +36 -0
- package/dist/prepare-Bdk8Cjkf.mjs +122 -0
- package/dist/prepare-CPAvcv6q.d.mts +63 -0
- package/dist/strike-hWxShOgb.mjs +50 -0
- package/dist/styles-QSX3RhxK.mjs +285 -0
- package/dist/styles-ugspkrxz.d.mts +85 -0
- package/dist/table-DrA12lxX.mjs +159 -0
- package/dist/table-cell-DmkfYwDc.mjs +112 -0
- package/dist/table-header-Bwr5GKWg.mjs +112 -0
- package/dist/table-row-vew1y7WH.mjs +84 -0
- package/dist/task-item-BnlXGrIG.mjs +37 -0
- package/dist/text-style-tMeBq5XQ.mjs +151 -0
- package/dist/tiptap-D7pl4I5U.mjs +33 -0
- package/dist/utils-BPT4tjcn.mjs +333 -0
- package/package.json +3 -2
- package/dist/core-CFIQVRfx.mjs +0 -88
- package/dist/core-omBKMRtl.d.mts +0 -34
- package/dist/image-Ge1y6uam.d.mts +0 -47
- package/dist/paragraph-fhEXtAN2.d.mts +0 -16
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { T as Paragraph$1 } from "./tiptap-D7pl4I5U.mjs";
|
|
2
|
+
import { _ as shadingFromElement, c as indentFromElement, f as renderParagraphStyles, i as bordersFromElement, n as alignmentFromElement, x as spacingFromElement } from "./utils-BPT4tjcn.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 attrNative = () => ({
|
|
57
|
+
default: null,
|
|
58
|
+
parseHTML: () => null,
|
|
59
|
+
rendered: false
|
|
60
|
+
});
|
|
61
|
+
const Paragraph = Paragraph$1.extend({
|
|
62
|
+
addAttributes() {
|
|
63
|
+
return {
|
|
64
|
+
...this.parent?.(),
|
|
65
|
+
styleId: {
|
|
66
|
+
default: null,
|
|
67
|
+
parseHTML: (el) => {
|
|
68
|
+
const m = (el.getAttribute("class") || "").match(/(?:^|\s)docx-style-(\S+)/);
|
|
69
|
+
return m ? m[1] : null;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
alignment: {
|
|
73
|
+
default: null,
|
|
74
|
+
rendered: false,
|
|
75
|
+
parseHTML: (el) => alignmentFromElement(el)
|
|
76
|
+
},
|
|
77
|
+
indent: {
|
|
78
|
+
default: null,
|
|
79
|
+
rendered: false,
|
|
80
|
+
parseHTML: (el) => indentFromElement(el)
|
|
81
|
+
},
|
|
82
|
+
spacing: {
|
|
83
|
+
default: null,
|
|
84
|
+
rendered: false,
|
|
85
|
+
parseHTML: (el) => spacingFromElement(el)
|
|
86
|
+
},
|
|
87
|
+
shading: {
|
|
88
|
+
default: null,
|
|
89
|
+
rendered: false,
|
|
90
|
+
parseHTML: (el) => shadingFromElement(el)
|
|
91
|
+
},
|
|
92
|
+
border: {
|
|
93
|
+
default: null,
|
|
94
|
+
rendered: false,
|
|
95
|
+
parseHTML: (el) => bordersFromElement(el)
|
|
96
|
+
},
|
|
97
|
+
frame: attrNative(),
|
|
98
|
+
run: attrNative(),
|
|
99
|
+
sectionProperties: attrNative(),
|
|
100
|
+
sectionHeaders: attrNative(),
|
|
101
|
+
sectionFooters: attrNative(),
|
|
102
|
+
keepNext: attrNative(),
|
|
103
|
+
keepLines: attrNative(),
|
|
104
|
+
pageBreakBefore: attrNative(),
|
|
105
|
+
widowControl: attrNative(),
|
|
106
|
+
contextualSpacing: attrNative(),
|
|
107
|
+
bidirectional: attrNative(),
|
|
108
|
+
outlineLevel: attrNative(),
|
|
109
|
+
textDirection: attrNative(),
|
|
110
|
+
textAlignment: attrNative(),
|
|
111
|
+
suppressLineNumbers: attrNative(),
|
|
112
|
+
wordWrap: attrNative(),
|
|
113
|
+
overflowPunctuation: attrNative(),
|
|
114
|
+
autoSpaceEastAsianText: attrNative(),
|
|
115
|
+
suppressOverlap: attrNative(),
|
|
116
|
+
suppressAutoHyphens: attrNative(),
|
|
117
|
+
adjustRightInd: attrNative(),
|
|
118
|
+
snapToGrid: attrNative(),
|
|
119
|
+
mirrorIndents: attrNative(),
|
|
120
|
+
kinsoku: attrNative(),
|
|
121
|
+
topLinePunct: attrNative(),
|
|
122
|
+
autoSpaceDE: attrNative(),
|
|
123
|
+
textboxTightWrap: attrNative(),
|
|
124
|
+
rightTabStop: attrNative(),
|
|
125
|
+
leftTabStop: attrNative(),
|
|
126
|
+
divId: attrNative(),
|
|
127
|
+
tabStops: attrNative(),
|
|
128
|
+
cnfStyle: attrNative()
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
132
|
+
const styles = renderParagraphStyles(node.attrs);
|
|
133
|
+
const attrs = { ...HTMLAttributes };
|
|
134
|
+
const styleId = node.attrs.styleId;
|
|
135
|
+
attrs.class = styleId ? `docx-style-${styleId}` : "docx-default";
|
|
136
|
+
if (styles.length > 0) attrs.style = styles.join(";");
|
|
137
|
+
return [
|
|
138
|
+
"p",
|
|
139
|
+
attrs,
|
|
140
|
+
0
|
|
141
|
+
];
|
|
142
|
+
},
|
|
143
|
+
renderDocx,
|
|
144
|
+
parseDocx
|
|
145
|
+
});
|
|
146
|
+
//#endregion
|
|
147
|
+
export { parseDocx as n, renderDocx as r, Paragraph as t };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { JSONContent } from "@tiptap/core";
|
|
2
|
+
|
|
3
|
+
//#region src/extensions/paragraph.d.ts
|
|
4
|
+
declare function renderDocx(node: JSONContent): Record<string, unknown>;
|
|
5
|
+
declare function parseDocx(opts: Record<string, unknown>): Record<string, unknown>;
|
|
6
|
+
declare const Paragraph: import("@tiptap/core").Node<import("@tiptap/extension-paragraph").ParagraphOptions, any>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { parseDocx as n, renderDocx as r, Paragraph as t };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { a as JSONContent } from "./core-fBMCCj4D.mjs";
|
|
2
|
+
import { n as PrepareStep } from "./prepare-CPAvcv6q.mjs";
|
|
3
|
+
import { OutputByType, OutputType, patchDocument } from "@office-open/docx";
|
|
4
|
+
|
|
5
|
+
//#region src/converters/patch.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* A patch's replacement content, expressed as Tiptap JSON. `compileDocument`
|
|
8
|
+
* converts it to office-open `SectionChild[]` before applying.
|
|
9
|
+
*/
|
|
10
|
+
interface DocxPatchContent {
|
|
11
|
+
content: JSONContent;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Options for patching a DOCX template.
|
|
15
|
+
*
|
|
16
|
+
* Mirrors the legacy `@docen/export-docx` DocxPatchOptions minus `exportOptions`
|
|
17
|
+
* — `compileDocument` already derives all styling from the Tiptap attrs, so no
|
|
18
|
+
* separate export configuration is needed.
|
|
19
|
+
*/
|
|
20
|
+
interface DocxPatchOptions<T extends OutputType = OutputType> {
|
|
21
|
+
/** Template DOCX to patch. */
|
|
22
|
+
template: Parameters<typeof patchDocument>[0]["data"];
|
|
23
|
+
/** Placeholder name → replacement content. */
|
|
24
|
+
patches: Record<string, DocxPatchContent>;
|
|
25
|
+
/**
|
|
26
|
+
* Pre-compilation steps run on each patch's content in place (default:
|
|
27
|
+
* `prepareImages()`). `false` skips; `PrepareStep[]` runs custom steps.
|
|
28
|
+
* Required when patch content references http image URLs.
|
|
29
|
+
*/
|
|
30
|
+
prepare?: boolean | PrepareStep[];
|
|
31
|
+
/** Custom placeholder delimiters (default `{{` / `}}`). */
|
|
32
|
+
placeholderDelimiters?: {
|
|
33
|
+
start?: string;
|
|
34
|
+
end?: string;
|
|
35
|
+
};
|
|
36
|
+
/** Keep the template's paragraph styles on patched content. */
|
|
37
|
+
keepOriginalStyles?: boolean;
|
|
38
|
+
/** Recurse into nested patches. */
|
|
39
|
+
recursive?: boolean;
|
|
40
|
+
/** Output container type. */
|
|
41
|
+
outputType: T;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Patch a DOCX template by replacing placeholders with Tiptap-JSON content.
|
|
45
|
+
*
|
|
46
|
+
* Each patch's `content` is prepared (default: `prepareImages`, in place) then
|
|
47
|
+
* compiled (`compileDocument` → `DocumentOptions`); its first section's
|
|
48
|
+
* `children` become the replacement. Patching is delegated to
|
|
49
|
+
* `@office-open/docx`'s `patchDocument`.
|
|
50
|
+
*/
|
|
51
|
+
declare function patchDOCX<T extends OutputType>(options: DocxPatchOptions<T>): Promise<OutputByType[T]>;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { DocxPatchOptions as n, patchDOCX as r, DocxPatchContent as t };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { n as prepareDocument } from "./prepare-Bdk8Cjkf.mjs";
|
|
2
|
+
import { n as compileDocument } from "./docx-CONyAedl.mjs";
|
|
3
|
+
import { patchDocument } from "@office-open/docx";
|
|
4
|
+
//#region src/converters/patch.ts
|
|
5
|
+
/**
|
|
6
|
+
* Patch a DOCX template by replacing placeholders with Tiptap-JSON content.
|
|
7
|
+
*
|
|
8
|
+
* Each patch's `content` is prepared (default: `prepareImages`, in place) then
|
|
9
|
+
* compiled (`compileDocument` → `DocumentOptions`); its first section's
|
|
10
|
+
* `children` become the replacement. Patching is delegated to
|
|
11
|
+
* `@office-open/docx`'s `patchDocument`.
|
|
12
|
+
*/
|
|
13
|
+
async function patchDOCX(options) {
|
|
14
|
+
const { template, patches, prepare = true, placeholderDelimiters, keepOriginalStyles, recursive, outputType } = options;
|
|
15
|
+
const patchesObject = {};
|
|
16
|
+
for (const [key, patchContent] of Object.entries(patches)) {
|
|
17
|
+
if (prepare !== false) await prepareDocument(patchContent.content, prepare === true ? void 0 : prepare);
|
|
18
|
+
patchesObject[key] = {
|
|
19
|
+
type: "document",
|
|
20
|
+
children: compileDocument(patchContent.content).sections?.[0]?.children ?? []
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return patchDocument({
|
|
24
|
+
outputType,
|
|
25
|
+
data: template,
|
|
26
|
+
placeholders: patchesObject,
|
|
27
|
+
...keepOriginalStyles !== void 0 && { keepOriginalStyles },
|
|
28
|
+
...recursive !== void 0 && { recursive },
|
|
29
|
+
...placeholderDelimiters && { placeholderDelimiters: {
|
|
30
|
+
start: placeholderDelimiters.start ?? "{{",
|
|
31
|
+
end: placeholderDelimiters.end ?? "}}"
|
|
32
|
+
} }
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { patchDOCX as t };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { t as encodeBase64 } from "./dist-B6B3HnVZ.mjs";
|
|
2
|
+
import { imageMeta } from "image-meta";
|
|
3
|
+
//#region src/converters/prepare.ts
|
|
4
|
+
/**
|
|
5
|
+
* Default fetch handler using the global `fetch` API (Node 18+ and browsers).
|
|
6
|
+
*/
|
|
7
|
+
async function fetchImageHandler(url) {
|
|
8
|
+
const response = await fetch(url);
|
|
9
|
+
if (!response.ok) throw new Error(`Failed to fetch image from ${url}: ${response.status} ${response.statusText}`);
|
|
10
|
+
const buffer = await response.arrayBuffer();
|
|
11
|
+
return new Uint8Array(buffer);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a prepare step that fetches external image URLs and converts them to data URLs.
|
|
15
|
+
*
|
|
16
|
+
* @param handler - Custom fetch handler (defaults to `fetchImageHandler`)
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // Use with defaults
|
|
21
|
+
* await prepareDocument(json);
|
|
22
|
+
*
|
|
23
|
+
* // Custom handler
|
|
24
|
+
* await prepareDocument(json, [prepareImages(myHandler)]);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function prepareImages(handler = fetchImageHandler) {
|
|
28
|
+
return async (json) => {
|
|
29
|
+
await walkImages(json, handler);
|
|
30
|
+
};
|
|
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
|
+
}
|
|
48
|
+
/** Built-in prepare steps, run when no custom steps are provided. */
|
|
49
|
+
const DEFAULT_STEPS = [prepareImages(), prepareImageSizes()];
|
|
50
|
+
/**
|
|
51
|
+
* Run prepare steps on a Tiptap JSON document before compilation.
|
|
52
|
+
*
|
|
53
|
+
* Each step receives the JSON and may mutate it in place (e.g. replace external
|
|
54
|
+
* URLs with embedded data). Steps run sequentially in order.
|
|
55
|
+
*
|
|
56
|
+
* Defaults to `[prepareImages(), prepareImageSizes()]` when no steps are provided.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const json = parseHTML(html);
|
|
61
|
+
* await prepareDocument(json); // default: fetch images
|
|
62
|
+
* const docOpts = compileDocument(json);
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
async function prepareDocument(json, steps = DEFAULT_STEPS) {
|
|
66
|
+
for (const step of steps) await step(json);
|
|
67
|
+
}
|
|
68
|
+
async function toDataUrl(src, handler) {
|
|
69
|
+
const data = await handler(src);
|
|
70
|
+
return `data:${{
|
|
71
|
+
jpg: "image/jpeg",
|
|
72
|
+
jpeg: "image/jpeg",
|
|
73
|
+
png: "image/png",
|
|
74
|
+
gif: "image/gif",
|
|
75
|
+
bmp: "image/bmp",
|
|
76
|
+
svg: "image/svg+xml",
|
|
77
|
+
webp: "image/webp"
|
|
78
|
+
}[src.split(".").pop()?.toLowerCase() ?? "png"] ?? "image/png"};base64,${encodeBase64(data)}`;
|
|
79
|
+
}
|
|
80
|
+
async function walkImages(node, handler) {
|
|
81
|
+
if (node.type === "image" && node.attrs) {
|
|
82
|
+
const src = node.attrs.src;
|
|
83
|
+
if (src && (src.startsWith("http://") || src.startsWith("https://"))) try {
|
|
84
|
+
node.attrs.src = await toDataUrl(src, handler);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.warn(`Failed to fetch image: ${src}`, error instanceof Error ? error.message : error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const tasks = [];
|
|
90
|
+
for (const child of node.content ?? []) tasks.push(walkImages(child, handler));
|
|
91
|
+
await Promise.all(tasks);
|
|
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
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { prepareImages as i, prepareDocument as n, prepareImageSizes as r, fetchImageHandler as t };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { a as JSONContent } from "./core-fBMCCj4D.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/converters/prepare.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A prepare step that transforms Tiptap JSON in place (e.g. fetch external resources).
|
|
6
|
+
*/
|
|
7
|
+
type PrepareStep = (json: JSONContent) => Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Fetch handler for external image URLs.
|
|
10
|
+
*
|
|
11
|
+
* Receives the URL, returns the image binary data.
|
|
12
|
+
* Override to customize fetching (proxy, auth, caching, etc.).
|
|
13
|
+
*/
|
|
14
|
+
type ImageFetchHandler = (url: string) => Promise<Uint8Array>;
|
|
15
|
+
/**
|
|
16
|
+
* Default fetch handler using the global `fetch` API (Node 18+ and browsers).
|
|
17
|
+
*/
|
|
18
|
+
declare function fetchImageHandler(url: string): Promise<Uint8Array>;
|
|
19
|
+
/**
|
|
20
|
+
* Create a prepare step that fetches external image URLs and converts them to data URLs.
|
|
21
|
+
*
|
|
22
|
+
* @param handler - Custom fetch handler (defaults to `fetchImageHandler`)
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* // Use with defaults
|
|
27
|
+
* await prepareDocument(json);
|
|
28
|
+
*
|
|
29
|
+
* // Custom handler
|
|
30
|
+
* await prepareDocument(json, [prepareImages(myHandler)]);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
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;
|
|
46
|
+
/**
|
|
47
|
+
* Run prepare steps on a Tiptap JSON document before compilation.
|
|
48
|
+
*
|
|
49
|
+
* Each step receives the JSON and may mutate it in place (e.g. replace external
|
|
50
|
+
* URLs with embedded data). Steps run sequentially in order.
|
|
51
|
+
*
|
|
52
|
+
* Defaults to `[prepareImages(), prepareImageSizes()]` when no steps are provided.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* const json = parseHTML(html);
|
|
57
|
+
* await prepareDocument(json); // default: fetch images
|
|
58
|
+
* const docOpts = compileDocument(json);
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare function prepareDocument(json: JSONContent, steps?: readonly PrepareStep[]): Promise<void>;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { prepareImageSizes as a, prepareDocument as i, PrepareStep as n, prepareImages as o, fetchImageHandler as r, ImageFetchHandler as t };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { E as Strike$1 } from "./tiptap-D7pl4I5U.mjs";
|
|
2
|
+
//#region src/extensions/strike.ts
|
|
3
|
+
/**
|
|
4
|
+
* Strike mark extension with nested office-open attrs.
|
|
5
|
+
*
|
|
6
|
+
* OOXML represents strikethrough on a run via two mutually exclusive booleans:
|
|
7
|
+
* `strike` (single) and `doubleStrike` (double). The mark itself is "single
|
|
8
|
+
* strikethrough"; the `doubleStrike` attr flips it to double. DOCX round-trip
|
|
9
|
+
* is near-identity for the doubleStrike flag; `strike` itself is implied by the
|
|
10
|
+
* mark's presence and handled in renderDocx/parseDocx.
|
|
11
|
+
*
|
|
12
|
+
* Mark attribute-level renderHTML is delegated to the base Strike extension
|
|
13
|
+
* (renders `<s>`); only the DOCX flag needs custom handling.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* attrs → run properties.
|
|
17
|
+
*
|
|
18
|
+
* The mark presence itself means single strikethrough. When `doubleStrike` is
|
|
19
|
+
* set, emit the OOXML double-strike flag instead (the two are mutually
|
|
20
|
+
* exclusive in OOXML). DocxManager calls this with `mark.attrs`.
|
|
21
|
+
*/
|
|
22
|
+
function renderDocx(attrs) {
|
|
23
|
+
return attrs.doubleStrike ? { doubleStrike: true } : { strike: true };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* run properties → attrs.
|
|
27
|
+
*
|
|
28
|
+
* Only the `doubleStrike` flag needs to round-trip; single strike is implied by
|
|
29
|
+
* the mark's existence. `strike` is structural/semantic (the mark) and skipped.
|
|
30
|
+
*/
|
|
31
|
+
function parseDocx(runOpts) {
|
|
32
|
+
return { doubleStrike: runOpts.doubleStrike ?? null };
|
|
33
|
+
}
|
|
34
|
+
const attrNative = () => ({
|
|
35
|
+
default: null,
|
|
36
|
+
parseHTML: () => null,
|
|
37
|
+
rendered: false
|
|
38
|
+
});
|
|
39
|
+
const Strike = Strike$1.extend({
|
|
40
|
+
addAttributes() {
|
|
41
|
+
return {
|
|
42
|
+
...this.parent?.(),
|
|
43
|
+
doubleStrike: attrNative()
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
renderDocx,
|
|
47
|
+
parseDocx
|
|
48
|
+
});
|
|
49
|
+
//#endregion
|
|
50
|
+
export { parseDocx as n, renderDocx as r, Strike as t };
|