@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,334 @@
|
|
|
1
|
+
import { _ as Image$1 } from "./tiptap-D7pl4I5U.mjs";
|
|
2
|
+
//#region src/extensions/image.ts
|
|
3
|
+
/**
|
|
4
|
+
* Custom Image extension with node-level renderHTML + renderDocx/parseDocx.
|
|
5
|
+
*
|
|
6
|
+
* Attrs:
|
|
7
|
+
* - src/alt/title/width/height: Tiptap structural names (kept verbatim so base
|
|
8
|
+
* image commands work).
|
|
9
|
+
* - rotation: editor display only (CSS transform) but also carried through DOCX
|
|
10
|
+
* via transformation.rotation (MediaTransformation.rotation).
|
|
11
|
+
* - floating/outline: nested office-open objects (Floating / OutlineOptions).
|
|
12
|
+
* - crop: nested office-open SourceRectangleOptions (srcRect).
|
|
13
|
+
* - display: editor-only display hint, no OOXML equivalent.
|
|
14
|
+
*
|
|
15
|
+
* DOCX round-trip is near-identity: renderDocx packs attrs into CoreImageOptions;
|
|
16
|
+
* parseDocx unpacks them back. src is a data URL ↔ { type, data } base64.
|
|
17
|
+
* Node-level renderHTML solves the style merge problem (rotation + floating).
|
|
18
|
+
*/
|
|
19
|
+
/** Attribute spec for a nested office-open value stored as JSON in a data-* attr. */
|
|
20
|
+
const attrDataJson = (name) => ({
|
|
21
|
+
default: null,
|
|
22
|
+
rendered: false,
|
|
23
|
+
parseHTML: (element) => {
|
|
24
|
+
const raw = element.getAttribute(name);
|
|
25
|
+
if (!raw) return null;
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(raw);
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Tiptap JSON image node → CoreImageOptions-shaped object.
|
|
35
|
+
*
|
|
36
|
+
* Returns `{ image: ImageOptions }` (structural wrapper) or null when no
|
|
37
|
+
* embedded image data is available (external URLs need pre-fetching).
|
|
38
|
+
* rotation is carried via transformation.rotation (not dropped).
|
|
39
|
+
*/
|
|
40
|
+
function renderDocx(node) {
|
|
41
|
+
const attrs = node.attrs ?? {};
|
|
42
|
+
const imageOpts = {};
|
|
43
|
+
const src = attrs.src;
|
|
44
|
+
if (src?.startsWith("data:image/")) {
|
|
45
|
+
const match = src.match(/^data:image\/([\w.+-]+);base64,(.+)$/);
|
|
46
|
+
if (match) {
|
|
47
|
+
imageOpts.type = match[1] === "jpeg" ? "jpg" : match[1];
|
|
48
|
+
const binary = atob(match[2]);
|
|
49
|
+
const bytes = new Uint8Array(binary.length);
|
|
50
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
51
|
+
imageOpts.data = bytes;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (!imageOpts.data) return null;
|
|
55
|
+
const transformation = {
|
|
56
|
+
width: attrs.width ?? 600,
|
|
57
|
+
height: attrs.height ?? 400
|
|
58
|
+
};
|
|
59
|
+
const rotation = attrs.rotation;
|
|
60
|
+
if (rotation != null) transformation.rotation = rotation;
|
|
61
|
+
imageOpts.transformation = transformation;
|
|
62
|
+
const altText = {};
|
|
63
|
+
if (attrs.alt) altText.name = attrs.alt;
|
|
64
|
+
if (attrs.title) altText.description = attrs.title;
|
|
65
|
+
if (Object.keys(altText).length > 0) imageOpts.altText = altText;
|
|
66
|
+
if (attrs.floating) imageOpts.floating = attrs.floating;
|
|
67
|
+
if (attrs.crop) imageOpts.sourceRectangle = attrs.crop;
|
|
68
|
+
if (attrs.outline) imageOpts.outline = attrs.outline;
|
|
69
|
+
if (attrs.nonVisualProperties) imageOpts.nonVisualProperties = attrs.nonVisualProperties;
|
|
70
|
+
if (attrs.effectExtent) transformation.effectExtent = attrs.effectExtent;
|
|
71
|
+
if (attrs.graphicFrameLocks) imageOpts.graphicFrameLocks = attrs.graphicFrameLocks;
|
|
72
|
+
if (attrs.blipEffects) imageOpts.blipEffects = attrs.blipEffects;
|
|
73
|
+
if (attrs.useLocalDpi !== null && attrs.useLocalDpi !== void 0) imageOpts.useLocalDpi = attrs.useLocalDpi;
|
|
74
|
+
if (attrs.fill) imageOpts.fill = attrs.fill;
|
|
75
|
+
if (attrs.effects) imageOpts.effects = attrs.effects;
|
|
76
|
+
if (attrs.tile) imageOpts.tile = attrs.tile;
|
|
77
|
+
if (attrs.runPropertiesRawXml) imageOpts.runPropertiesRawXml = attrs.runPropertiesRawXml;
|
|
78
|
+
return { image: imageOpts };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* ImageOptions-shaped object → Tiptap attrs.
|
|
82
|
+
*
|
|
83
|
+
* Near-identity unpack: transformation → width/height/rotation, altText → alt/title,
|
|
84
|
+
* floating/srcRect(→crop)/outline passed through verbatim. src is reconstructed by
|
|
85
|
+
* DocxManager from the image data bytes (kept out of parseDocx).
|
|
86
|
+
*/
|
|
87
|
+
function parseDocx(imageOpts) {
|
|
88
|
+
const opts = imageOpts ?? {};
|
|
89
|
+
const attrs = {};
|
|
90
|
+
const transformation = opts.transformation;
|
|
91
|
+
if (transformation) {
|
|
92
|
+
if (typeof transformation.width === "number") attrs.width = transformation.width;
|
|
93
|
+
if (typeof transformation.height === "number") attrs.height = transformation.height;
|
|
94
|
+
if (typeof transformation.rotation === "number") attrs.rotation = transformation.rotation;
|
|
95
|
+
}
|
|
96
|
+
const altText = opts.altText;
|
|
97
|
+
if (altText) {
|
|
98
|
+
if (altText.name) attrs.alt = altText.name;
|
|
99
|
+
if (altText.description) attrs.title = altText.description;
|
|
100
|
+
}
|
|
101
|
+
if (opts.floating) attrs.floating = opts.floating;
|
|
102
|
+
if (opts.sourceRectangle) attrs.crop = opts.sourceRectangle;
|
|
103
|
+
if (opts.outline) attrs.outline = opts.outline;
|
|
104
|
+
if (opts.nonVisualProperties) attrs.nonVisualProperties = opts.nonVisualProperties;
|
|
105
|
+
const effectExtent = opts.transformation?.effectExtent;
|
|
106
|
+
if (effectExtent) attrs.effectExtent = effectExtent;
|
|
107
|
+
if (opts.graphicFrameLocks) attrs.graphicFrameLocks = opts.graphicFrameLocks;
|
|
108
|
+
if (opts.blipEffects) attrs.blipEffects = opts.blipEffects;
|
|
109
|
+
if (opts.useLocalDpi !== void 0) attrs.useLocalDpi = opts.useLocalDpi;
|
|
110
|
+
if (opts.fill) attrs.fill = opts.fill;
|
|
111
|
+
if (opts.effects) attrs.effects = opts.effects;
|
|
112
|
+
if (opts.tile) attrs.tile = opts.tile;
|
|
113
|
+
if (opts.runPropertiesRawXml) attrs.runPropertiesRawXml = opts.runPropertiesRawXml;
|
|
114
|
+
return attrs;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Render crop as background-image styles for byte-accurate four-sided srcRect.
|
|
118
|
+
*
|
|
119
|
+
* object-fit:cover scales uniformly, so it only matches single-axis crops; for
|
|
120
|
+
* two-sided crops it shrinks the whole image and shows too much. background-size
|
|
121
|
+
* scales each axis independently (W/visibleW × H/visibleH), so the visible
|
|
122
|
+
* srcRect region always maps exactly onto the extent box. background-position
|
|
123
|
+
* then shifts the original so the cropped-left/top region falls outside the box.
|
|
124
|
+
*
|
|
125
|
+
* Requires a div[role=img] host (see Image.renderHTML) — an <img> cannot
|
|
126
|
+
* background-crop itself, since its src is always painted in the foreground.
|
|
127
|
+
*/
|
|
128
|
+
function renderCropAttrs(crop, ctx = {}) {
|
|
129
|
+
const c = crop;
|
|
130
|
+
const leftPct = (c.left || 0) / 1e5;
|
|
131
|
+
const topPct = (c.top || 0) / 1e5;
|
|
132
|
+
const rightPct = (c.right || 0) / 1e5;
|
|
133
|
+
const bottomPct = (c.bottom || 0) / 1e5;
|
|
134
|
+
const visibleW = 1 - leftPct - rightPct;
|
|
135
|
+
const visibleH = 1 - topPct - bottomPct;
|
|
136
|
+
const w = ctx.width ?? 0;
|
|
137
|
+
const h = ctx.height ?? 0;
|
|
138
|
+
const bgW = visibleW > 0 ? w / visibleW : w;
|
|
139
|
+
const bgH = visibleH > 0 ? h / visibleH : h;
|
|
140
|
+
const posX = leftPct + rightPct > 0 ? leftPct / (leftPct + rightPct) * 100 : 50;
|
|
141
|
+
const posY = topPct + bottomPct > 0 ? topPct / (topPct + bottomPct) * 100 : 50;
|
|
142
|
+
return { style: [
|
|
143
|
+
`background-image:url(${ctx.src ?? ""})`,
|
|
144
|
+
`background-size:${bgW.toFixed(2)}px ${bgH.toFixed(2)}px`,
|
|
145
|
+
`background-position:${posX.toFixed(2)}% ${posY.toFixed(2)}%`,
|
|
146
|
+
"background-repeat:no-repeat"
|
|
147
|
+
].join(";") };
|
|
148
|
+
}
|
|
149
|
+
function renderImageStyles(attrs) {
|
|
150
|
+
const styles = [];
|
|
151
|
+
if (attrs.display) styles.push(`display:${attrs.display}`);
|
|
152
|
+
if (attrs.rotation) styles.push(`transform:rotate(${attrs.rotation}deg)`);
|
|
153
|
+
const f = attrs.floating;
|
|
154
|
+
if (f) {
|
|
155
|
+
styles.push(f.behindDocument ? "z-index:-1" : "z-index:1");
|
|
156
|
+
const wrapType = f.wrap?.type ?? 0;
|
|
157
|
+
if (wrapType === 0) styles.push("position:absolute");
|
|
158
|
+
else if (wrapType === 1) {
|
|
159
|
+
const align = f.horizontalPosition?.align;
|
|
160
|
+
if (align === "left" || align === "inside") styles.push("float:left");
|
|
161
|
+
else if (align === "right" || align === "outside") styles.push("float:right");
|
|
162
|
+
else styles.push("float:left");
|
|
163
|
+
} else if (wrapType === 2) {
|
|
164
|
+
styles.push("float:left");
|
|
165
|
+
styles.push("shape-outside:margin-box");
|
|
166
|
+
} else if (wrapType === 3) {
|
|
167
|
+
styles.push("display:block");
|
|
168
|
+
styles.push("clear:both");
|
|
169
|
+
} else styles.push("display:inline-block");
|
|
170
|
+
const m = f.margins;
|
|
171
|
+
if (m) {
|
|
172
|
+
if (m.top) styles.push(`margin-top:${(m.top * 96 / 1440).toFixed(1)}pt`);
|
|
173
|
+
if (m.bottom) styles.push(`margin-bottom:${(m.bottom * 96 / 1440).toFixed(1)}pt`);
|
|
174
|
+
if (m.left) styles.push(`margin-left:${(m.left * 96 / 1440).toFixed(1)}pt`);
|
|
175
|
+
if (m.right) styles.push(`margin-right:${(m.right * 96 / 1440).toFixed(1)}pt`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return styles;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Stamp the nested office-open attrs onto an HTML attribute map as JSON
|
|
182
|
+
* data-* pairs. Shared by the cropped-div and plain-img render branches so the
|
|
183
|
+
* fidelity fields (floating/outline/nonVisualProperties/…) round-trip through
|
|
184
|
+
* HTML identically. `crop` is handled separately (crop branch only).
|
|
185
|
+
*/
|
|
186
|
+
const RAW_ATTR_DATA = [
|
|
187
|
+
["floating", "data-floating"],
|
|
188
|
+
["outline", "data-outline"],
|
|
189
|
+
["nonVisualProperties", "data-non-visual"],
|
|
190
|
+
["effectExtent", "data-effect-extent"],
|
|
191
|
+
["graphicFrameLocks", "data-graphic-frame-locks"],
|
|
192
|
+
["blipEffects", "data-blip-effects"],
|
|
193
|
+
["useLocalDpi", "data-use-local-dpi"],
|
|
194
|
+
["fill", "data-fill"],
|
|
195
|
+
["effects", "data-effects"],
|
|
196
|
+
["tile", "data-tile"],
|
|
197
|
+
["runPropertiesRawXml", "data-run-properties-raw-xml"]
|
|
198
|
+
];
|
|
199
|
+
function attachRawAttrs(target, attrs) {
|
|
200
|
+
for (const [attr, data] of RAW_ATTR_DATA) {
|
|
201
|
+
const value = attrs[attr];
|
|
202
|
+
if (value !== null && value !== void 0) target[data] = JSON.stringify(value);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const Image = Image$1.extend({
|
|
206
|
+
addAttributes() {
|
|
207
|
+
return {
|
|
208
|
+
...this.parent?.(),
|
|
209
|
+
display: {
|
|
210
|
+
default: null,
|
|
211
|
+
rendered: false,
|
|
212
|
+
parseHTML: () => this.options.inline ? "inline-block" : null
|
|
213
|
+
},
|
|
214
|
+
rotation: {
|
|
215
|
+
default: null,
|
|
216
|
+
rendered: false,
|
|
217
|
+
parseHTML: (element) => {
|
|
218
|
+
const match = (element.getAttribute("style") || "").match(/transform:\s*rotate\(([\d.]+)deg\)/);
|
|
219
|
+
return match ? parseFloat(match[1]) : null;
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
floating: {
|
|
223
|
+
default: null,
|
|
224
|
+
rendered: false,
|
|
225
|
+
parseHTML: (element) => {
|
|
226
|
+
const raw = element.getAttribute("data-floating");
|
|
227
|
+
if (!raw) return null;
|
|
228
|
+
try {
|
|
229
|
+
return JSON.parse(raw);
|
|
230
|
+
} catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
outline: {
|
|
236
|
+
default: null,
|
|
237
|
+
rendered: false,
|
|
238
|
+
parseHTML: (element) => {
|
|
239
|
+
const raw = element.getAttribute("data-outline");
|
|
240
|
+
if (!raw) return null;
|
|
241
|
+
try {
|
|
242
|
+
return JSON.parse(raw);
|
|
243
|
+
} catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
crop: {
|
|
249
|
+
default: null,
|
|
250
|
+
rendered: false,
|
|
251
|
+
parseHTML: (element) => {
|
|
252
|
+
const raw = element.getAttribute("data-crop");
|
|
253
|
+
if (!raw) return null;
|
|
254
|
+
try {
|
|
255
|
+
return JSON.parse(raw);
|
|
256
|
+
} catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
nonVisualProperties: attrDataJson("data-non-visual"),
|
|
262
|
+
effectExtent: attrDataJson("data-effect-extent"),
|
|
263
|
+
graphicFrameLocks: attrDataJson("data-graphic-frame-locks"),
|
|
264
|
+
blipEffects: attrDataJson("data-blip-effects"),
|
|
265
|
+
useLocalDpi: attrDataJson("data-use-local-dpi"),
|
|
266
|
+
fill: attrDataJson("data-fill"),
|
|
267
|
+
effects: attrDataJson("data-effects"),
|
|
268
|
+
tile: attrDataJson("data-tile"),
|
|
269
|
+
runPropertiesRawXml: attrDataJson("data-run-properties-raw-xml")
|
|
270
|
+
};
|
|
271
|
+
},
|
|
272
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
273
|
+
const attrs = node.attrs;
|
|
274
|
+
if (attrs.crop) {
|
|
275
|
+
const width = attrs.width;
|
|
276
|
+
const height = attrs.height;
|
|
277
|
+
const styles = renderImageStyles(attrs);
|
|
278
|
+
const crop = renderCropAttrs(attrs.crop, {
|
|
279
|
+
width,
|
|
280
|
+
height,
|
|
281
|
+
src: attrs.src
|
|
282
|
+
});
|
|
283
|
+
styles.push(crop.style, `width:${width}px`, `height:${height}px`);
|
|
284
|
+
const divAttrs = {
|
|
285
|
+
"data-image": "crop",
|
|
286
|
+
role: "img",
|
|
287
|
+
style: styles.join(";")
|
|
288
|
+
};
|
|
289
|
+
if (attrs.alt) divAttrs["aria-label"] = attrs.alt;
|
|
290
|
+
if (attrs.title) divAttrs["title"] = attrs.title;
|
|
291
|
+
attachRawAttrs(divAttrs, attrs);
|
|
292
|
+
divAttrs["data-crop"] = JSON.stringify(attrs.crop);
|
|
293
|
+
return ["div", divAttrs];
|
|
294
|
+
}
|
|
295
|
+
const htmlAttrs = { ...HTMLAttributes };
|
|
296
|
+
const styles = renderImageStyles(attrs);
|
|
297
|
+
if (styles.length > 0) htmlAttrs.style = styles.join(";");
|
|
298
|
+
attachRawAttrs(htmlAttrs, attrs);
|
|
299
|
+
return ["img", htmlAttrs];
|
|
300
|
+
},
|
|
301
|
+
parseHTML() {
|
|
302
|
+
return [{
|
|
303
|
+
tag: "div[data-image=crop]",
|
|
304
|
+
getAttrs: (el) => parseCropDiv(el)
|
|
305
|
+
}, { tag: "img[src]" }];
|
|
306
|
+
},
|
|
307
|
+
renderDocx,
|
|
308
|
+
parseDocx
|
|
309
|
+
});
|
|
310
|
+
/**
|
|
311
|
+
* Reverse-parse a cropped div[role=img] back into image attrs.
|
|
312
|
+
*
|
|
313
|
+
* Covers only what the attribute-level parseHTML rules cannot recover from a
|
|
314
|
+
* div: src (background-image), width/height (inline style extent box), and
|
|
315
|
+
* alt/title (aria-label/title). rotation/crop/floating/outline are left to
|
|
316
|
+
* their attribute parseHTML rules, which read the style/data-* the div carries.
|
|
317
|
+
*/
|
|
318
|
+
function parseCropDiv(el) {
|
|
319
|
+
const style = el.getAttribute("style") || "";
|
|
320
|
+
const attrs = {};
|
|
321
|
+
const bgMatch = style.match(/background-image:\s*url\(\s*([^)]+?)\s*\)/);
|
|
322
|
+
if (bgMatch) attrs.src = bgMatch[1].replace(/^['"]|['"]$/g, "");
|
|
323
|
+
const wMatch = style.match(/(?:^|;)\s*width:\s*([\d.]+)px/);
|
|
324
|
+
const hMatch = style.match(/(?:^|;)\s*height:\s*([\d.]+)px/);
|
|
325
|
+
if (wMatch) attrs.width = parseFloat(wMatch[1]);
|
|
326
|
+
if (hMatch) attrs.height = parseFloat(hMatch[1]);
|
|
327
|
+
const ariaLabel = el.getAttribute("aria-label");
|
|
328
|
+
if (ariaLabel) attrs.alt = ariaLabel;
|
|
329
|
+
const title = el.getAttribute("title");
|
|
330
|
+
if (title) attrs.title = title;
|
|
331
|
+
return attrs;
|
|
332
|
+
}
|
|
333
|
+
//#endregion
|
|
334
|
+
export { renderDocx as i, parseDocx as n, renderCropAttrs as r, Image as t };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { n as createDocument, t as Document } from "./document-BH1y4qHM.mjs";
|
|
2
|
+
import { a as JSONContent, c as DocxKit, d as docxExtensions, f as tiptapMarkExtensions, l as DocxKitOptions, p as tiptapNodeExtensions, t as AnyExtension } from "./core-fBMCCj4D.mjs";
|
|
3
|
+
import { i as prepareDocument, n as PrepareStep, o as prepareImages, r as fetchImageHandler, t as ImageFetchHandler } from "./prepare-CPAvcv6q.mjs";
|
|
4
|
+
import { a as generateDOCX, c as parseDOCX, i as compileDocument, l as resolveDocument, n as DocxGenerateOptions, o as generateDOCXStream, r as DocxManager, s as generateDOCXSync } from "./docx-C5wyjI-0.mjs";
|
|
5
|
+
import { n as parseHTML, t as generateHTML } from "./html-DCC_DSHv.mjs";
|
|
6
|
+
import { n as parseMarkdown, t as generateMarkdown } from "./markdown-D0k0sRYS.mjs";
|
|
7
|
+
import { n as DocxPatchOptions, r as patchDOCX, t as DocxPatchContent } from "./patch-Cdp5WKJz.mjs";
|
|
8
|
+
import { a as inlineStyles, i as effectiveRunProps, n as StylesOptions, o as quickStyles, s as stylesToCss, t as QuickStyleEntry } from "./styles-ugspkrxz.mjs";
|
|
9
|
+
import { n as createDocxEditor, t as DocxEditorOptions } from "./editor-DReY3Rb9.mjs";
|
|
8
10
|
import { JSONContent as TiptapJSONContent } from "@tiptap/core";
|
|
9
|
-
import { AlignmentType, BookmarkOptions, BorderOptions, BordersOptions, DocumentOptions, EmphasisMarkType, ExternalHyperlinkOptions, Floating, FontAttributesProperties, FrameOptions, HeadingLevel, HeightRule, HighlightColor, ImageChild, ImageOptions, IndentAttributesProperties, InternalHyperlinkOptions, LeaderType, LevelParagraphStylePropertiesOptions, LineRuleType, Margins, MathChild, MathInput, MediaTransformation, ParagraphChild, ParagraphOptions, ParagraphPropertiesOptions, ParagraphPropertiesOptionsBase,
|
|
11
|
+
import { AlignmentType, BookmarkOptions, BorderOptions, BordersOptions, DocumentOptions, EmphasisMarkType, ExternalHyperlinkOptions, Floating, Floating as Floating$1, FontAttributesProperties, FrameOptions, HeadingLevel, HeightRule, HighlightColor, ImageChild, ImageOptions, ImageOptions as ImageOptions$1, IndentAttributesProperties, InternalHyperlinkOptions, LeaderType, LevelParagraphStylePropertiesOptions, LineRuleType, Margins, MathChild, MathInput, MediaTransformation, ParagraphChild, ParagraphOptions, ParagraphPropertiesOptions, ParagraphPropertiesOptionsBase, ParagraphRunPropertiesOptions, ParagraphStylePropertiesOptions, RubyOptions, RunOptions, RunPropertiesOptions, RunStylePropertiesOptions, SectionChild, SectionOptions, SectionPropertiesOptions, ShadingAttributesProperties, SpacingProperties, TabStopDefinition, TabStopPosition, TabStopType, TableBordersOptions, TableCellBordersOptions, TableCellOptions, TableFloatOptions, TableLayoutType, TableLookOptions, TableOptions, TableRowOptions, TableRowPropertiesOptionsBase, TableVerticalAlign, TableWidthProperties, TextAlignmentType, UnderlineType, WidthType } from "@office-open/docx";
|
|
10
12
|
|
|
11
13
|
//#region src/types.d.ts
|
|
12
14
|
/**
|
|
@@ -20,14 +22,14 @@ type AttrNullable<T> = { [K in keyof T]-?: T[K] | null };
|
|
|
20
22
|
* indent/spacing/border/run/frame are nested objects (matching office-open),
|
|
21
23
|
* so one `indent` attr replaces 13 flattened indent attrs.
|
|
22
24
|
*/
|
|
23
|
-
type ParagraphAttrs = AttrNullable<ParagraphPropertiesOptionsBase
|
|
25
|
+
type ParagraphAttrs = AttrNullable<ParagraphPropertiesOptionsBase>;
|
|
24
26
|
/**
|
|
25
27
|
* Text style mark attrs — mirrors RunStylePropertiesOptions.
|
|
26
28
|
*
|
|
27
29
|
* Omits properties handled by dedicated marks (bold, italic, strike,
|
|
28
30
|
* doubleStrike, subScript, superScript). `size` is in POINTS.
|
|
29
31
|
*/
|
|
30
|
-
type TextStyleAttrs = AttrNullable<Omit<RunStylePropertiesOptions
|
|
32
|
+
type TextStyleAttrs = AttrNullable<Omit<RunStylePropertiesOptions, "bold" | "boldComplexScript" | "italic" | "italicComplexScript" | "strike" | "doubleStrike" | "subScript" | "superScript">>;
|
|
31
33
|
/**
|
|
32
34
|
* Link mark attrs.
|
|
33
35
|
*/
|
|
@@ -41,19 +43,19 @@ interface LinkAttrs {
|
|
|
41
43
|
/**
|
|
42
44
|
* Table attrs — mirrors TableOptions (minus `rows`, which is structural).
|
|
43
45
|
*/
|
|
44
|
-
type TableAttrs = AttrNullable<Omit<TableOptions
|
|
46
|
+
type TableAttrs = AttrNullable<Omit<TableOptions, "rows">>;
|
|
45
47
|
/**
|
|
46
48
|
* Table row attrs — mirrors TableRowPropertiesOptionsBase.
|
|
47
49
|
* height is nested { value, rule } matching office-open.
|
|
48
50
|
*/
|
|
49
|
-
type TableRowAttrs = AttrNullable<TableRowPropertiesOptionsBase
|
|
51
|
+
type TableRowAttrs = AttrNullable<TableRowPropertiesOptionsBase>;
|
|
50
52
|
/**
|
|
51
53
|
* Table cell / header attrs — mirrors TableCellOptions.
|
|
52
54
|
*
|
|
53
55
|
* colspan/rowspan/colwidth kept as Tiptap structural names (base extension
|
|
54
56
|
* dependent); office-open columnSpan/rowSpan are mapped in renderDocx.
|
|
55
57
|
*/
|
|
56
|
-
type TableCellAttrs = AttrNullable<Omit<TableCellOptions
|
|
58
|
+
type TableCellAttrs = AttrNullable<Omit<TableCellOptions, "children" | "columnSpan" | "rowSpan">> & {
|
|
57
59
|
/** Horizontal span (Tiptap base name; maps to office-open columnSpan). */colspan: number; /** Vertical span (Tiptap base name; maps to office-open rowSpan). */
|
|
58
60
|
rowspan: number; /** Column width in pixels per cell (Tiptap base name). */
|
|
59
61
|
colwidth: number[] | null;
|
|
@@ -70,10 +72,33 @@ interface ImageAttrs {
|
|
|
70
72
|
width: number | null;
|
|
71
73
|
height: number | null;
|
|
72
74
|
rotation: number | null;
|
|
73
|
-
floating:
|
|
74
|
-
outline:
|
|
75
|
-
crop:
|
|
75
|
+
floating: Floating$1 | null;
|
|
76
|
+
outline: NonNullable<ImageOptions$1["outline"]> | null;
|
|
77
|
+
crop: NonNullable<ImageOptions$1["sourceRectangle"]> | null;
|
|
76
78
|
display: string | null;
|
|
79
|
+
nonVisualProperties: NonNullable<ImageOptions$1["nonVisualProperties"]> | null;
|
|
80
|
+
effectExtent: {
|
|
81
|
+
l: number;
|
|
82
|
+
t: number;
|
|
83
|
+
r: number;
|
|
84
|
+
b: number;
|
|
85
|
+
} | null;
|
|
86
|
+
graphicFrameLocks: NonNullable<ImageOptions$1["graphicFrameLocks"]> | null;
|
|
87
|
+
blipEffects: NonNullable<ImageOptions$1["blipEffects"]> | null;
|
|
88
|
+
useLocalDpi: boolean | null;
|
|
89
|
+
fill: NonNullable<ImageOptions$1["fill"]> | null;
|
|
90
|
+
effects: NonNullable<ImageOptions$1["effects"]> | null;
|
|
91
|
+
tile: NonNullable<ImageOptions$1["tile"]> | null;
|
|
92
|
+
runPropertiesRawXml: string | null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Emoji node attrs.
|
|
96
|
+
* `name` is the shortcode (base @tiptap/extension-emoji); `emoji` is the
|
|
97
|
+
* resolved glyph cached for DOCX export (null when only the shortcode is known).
|
|
98
|
+
*/
|
|
99
|
+
interface EmojiAttrs {
|
|
100
|
+
name: string | null;
|
|
101
|
+
emoji: string | null;
|
|
77
102
|
}
|
|
78
103
|
/**
|
|
79
104
|
* Strike mark attrs.
|
|
@@ -120,7 +145,7 @@ type Mark = {
|
|
|
120
145
|
interface ParagraphNode extends TiptapJSONContent {
|
|
121
146
|
type: "paragraph";
|
|
122
147
|
attrs?: ParagraphAttrs;
|
|
123
|
-
content?: Array<TextNode | HardBreakNode | ImageNode>;
|
|
148
|
+
content?: Array<TextNode | HardBreakNode | ImageNode | EmojiNode>;
|
|
124
149
|
}
|
|
125
150
|
interface HeadingNode extends TiptapJSONContent {
|
|
126
151
|
type: "heading";
|
|
@@ -143,6 +168,16 @@ interface CodeBlockNode extends TiptapJSONContent {
|
|
|
143
168
|
interface HorizontalRuleNode extends TiptapJSONContent {
|
|
144
169
|
type: "horizontalRule";
|
|
145
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Header/footer slots in Tiptap JSON — each slot is the JSONContent[] produced
|
|
173
|
+
* by resolving that slot's SectionChild[] (paragraphs/tables/…). Mirrors
|
|
174
|
+
* SectionOptions.headers/footers in the runtime model.
|
|
175
|
+
*/
|
|
176
|
+
interface HeaderFooterSlots {
|
|
177
|
+
default?: TiptapJSONContent[];
|
|
178
|
+
first?: TiptapJSONContent[];
|
|
179
|
+
even?: TiptapJSONContent[];
|
|
180
|
+
}
|
|
146
181
|
interface BulletListNode extends TiptapJSONContent {
|
|
147
182
|
type: "bulletList";
|
|
148
183
|
content?: Array<ListItemNode>;
|
|
@@ -195,6 +230,21 @@ interface ImageNode extends TiptapJSONContent {
|
|
|
195
230
|
type: "image";
|
|
196
231
|
attrs?: ImageAttrs;
|
|
197
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Drawing group (wpg) carried as an opaque blob — the full WpgGroupRunOptions
|
|
235
|
+
* (pictures/shapes/nested groups + transform) round-trips verbatim. The editor
|
|
236
|
+
* doesn't model the group interior; renderHTML paints the first picture only.
|
|
237
|
+
*/
|
|
238
|
+
interface ImageGroupNode extends TiptapJSONContent {
|
|
239
|
+
type: "imageGroup";
|
|
240
|
+
attrs?: {
|
|
241
|
+
wpgGroup: Record<string, unknown> | null;
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
interface EmojiNode extends TiptapJSONContent {
|
|
245
|
+
type: "emoji";
|
|
246
|
+
attrs?: EmojiAttrs;
|
|
247
|
+
}
|
|
198
248
|
interface DetailsNode extends TiptapJSONContent {
|
|
199
249
|
type: "details";
|
|
200
250
|
content?: Array<DetailsSummaryNode | DetailsContentNode>;
|
|
@@ -210,4 +260,4 @@ interface DetailsContentNode extends TiptapJSONContent {
|
|
|
210
260
|
type InlineContent = TextNode | HardBreakNode;
|
|
211
261
|
type BlockNode = ParagraphNode | HeadingNode | BlockquoteNode | CodeBlockNode | HorizontalRuleNode | BulletListNode | OrderedListNode | TaskListNode | TableNode | ImageNode | DetailsNode;
|
|
212
262
|
//#endregion
|
|
213
|
-
export { type AlignmentType, type AnyExtension, type AttrNullable, type BlockNode, type BlockquoteNode, type BookmarkOptions, type BorderOptions, type BordersOptions, type BulletListNode, type CodeBlockNode, type DetailsContentNode, type DetailsNode, type DetailsSummaryNode, type DocumentOptions, type DocxEditorOptions, type DocxGenerateOptions, DocxManager, type DocxPatchContent, type DocxPatchOptions, type EmphasisMarkType, type ExternalHyperlinkOptions, type Floating, type FontAttributesProperties, type FrameOptions, type HardBreakNode, type HeadingLevel, type HeadingNode, type HeightRule, type HighlightColor, type HorizontalRuleNode, type ImageAttrs, type ImageChild, type ImageFetchHandler, type ImageNode, type ImageOptions, type IndentAttributesProperties, type InlineContent, type InternalHyperlinkOptions, type JSONContent, type LeaderType, type LevelParagraphStylePropertiesOptions, type LineRuleType, type LinkAttrs, type ListItemNode, type Margins, type Mark, type MathChild, type MathInput, type MediaTransformation, type OrderedListNode, type ParagraphAttrs, type ParagraphChild, type ParagraphNode, type ParagraphOptions, type ParagraphPropertiesOptions, type ParagraphPropertiesOptionsBase, type ParagraphRunPropertiesOptions, type ParagraphStylePropertiesOptions, type PrepareStep, type RubyOptions, type RunOptions, type RunPropertiesOptions, type RunStylePropertiesOptions, type SectionChild, type SectionOptions, type ShadingAttributesProperties, type SpacingProperties,
|
|
263
|
+
export { type AlignmentType, type AnyExtension, type AttrNullable, type BlockNode, type BlockquoteNode, type BookmarkOptions, type BorderOptions, type BordersOptions, type BulletListNode, type CodeBlockNode, type DetailsContentNode, type DetailsNode, type DetailsSummaryNode, Document, type DocumentOptions, type DocxEditorOptions, type DocxGenerateOptions, DocxKit, type DocxKitOptions, DocxManager, type DocxPatchContent, type DocxPatchOptions, type EmojiAttrs, type EmojiNode, type EmphasisMarkType, type ExternalHyperlinkOptions, type Floating, type FontAttributesProperties, type FrameOptions, type HardBreakNode, type HeaderFooterSlots, type HeadingLevel, type HeadingNode, type HeightRule, type HighlightColor, type HorizontalRuleNode, type ImageAttrs, type ImageChild, type ImageFetchHandler, type ImageGroupNode, type ImageNode, type ImageOptions, type IndentAttributesProperties, type InlineContent, type InternalHyperlinkOptions, type JSONContent, type LeaderType, type LevelParagraphStylePropertiesOptions, type LineRuleType, type LinkAttrs, type ListItemNode, type Margins, type Mark, type MathChild, type MathInput, type MediaTransformation, type OrderedListNode, type ParagraphAttrs, type ParagraphChild, type ParagraphNode, type ParagraphOptions, type ParagraphPropertiesOptions, type ParagraphPropertiesOptionsBase, type ParagraphRunPropertiesOptions, type ParagraphStylePropertiesOptions, type PrepareStep, type QuickStyleEntry, type RubyOptions, type RunOptions, type RunPropertiesOptions, type RunStylePropertiesOptions, type SectionChild, type SectionOptions, type SectionPropertiesOptions, type ShadingAttributesProperties, type SpacingProperties, type StrikeAttrs, type StylesOptions, type TabStopDefinition, type TabStopPosition, type TabStopType, type TableAttrs, type TableBordersOptions, type TableCellAttrs, type TableCellBordersOptions, type TableCellNode, type TableCellOptions, type TableFloatOptions, type TableHeaderNode, type TableLayoutType, type TableLookOptions, type TableNode, type TableOptions, type TableRowAttrs, type TableRowNode, type TableRowOptions, type TableRowPropertiesOptionsBase, type TableVerticalAlign, type TableWidthProperties, type TaskItemNode, type TaskListNode, type TextAlignmentType, type TextNode, type TextStyleAttrs, type UnderlineType, type WidthType, compileDocument, createDocument, createDocxEditor, docxExtensions, effectiveRunProps, fetchImageHandler, generateDOCX, generateDOCXStream, generateDOCXSync, generateHTML, generateMarkdown, inlineStyles, parseDOCX, parseHTML, parseMarkdown, patchDOCX, prepareDocument, prepareImages, quickStyles, resolveDocument, stylesToCss, tiptapMarkExtensions, tiptapNodeExtensions };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
1
|
+
import { a as DocxKit, c as tiptapMarkExtensions, l as tiptapNodeExtensions, s as docxExtensions } from "./core-DEqBHRzE.mjs";
|
|
2
|
+
import { n as createDocument, t as Document } from "./document-CvTym-FM.mjs";
|
|
3
|
+
import { t as createDocxEditor } from "./editor-Bf3CxQnY.mjs";
|
|
4
|
+
import { i as prepareImages, n as prepareDocument, t as fetchImageHandler } from "./prepare-Bdk8Cjkf.mjs";
|
|
5
|
+
import { a as generateDOCXSync, i as generateDOCXStream, n as compileDocument, o as parseDOCX, r as generateDOCX, s as resolveDocument, t as DocxManager } from "./docx-CONyAedl.mjs";
|
|
6
|
+
import { t as patchDOCX } from "./patch-IZ13tXTu.mjs";
|
|
7
|
+
import { n as parseHTML, t as generateHTML } from "./html-DedDWPoO.mjs";
|
|
8
|
+
import { n as parseMarkdown, t as generateMarkdown } from "./markdown-BzJmRsBs.mjs";
|
|
9
|
+
import { a as stylesToCss, i as quickStyles, n as effectiveRunProps, r as inlineStyles } from "./styles-QSX3RhxK.mjs";
|
|
10
|
+
export { Document, DocxKit, DocxManager, compileDocument, createDocument, createDocxEditor, docxExtensions, effectiveRunProps, fetchImageHandler, generateDOCX, generateDOCXStream, generateDOCXSync, generateHTML, generateMarkdown, inlineStyles, parseDOCX, parseHTML, parseMarkdown, patchDOCX, prepareDocument, prepareImages, quickStyles, resolveDocument, stylesToCss, tiptapMarkExtensions, tiptapNodeExtensions };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { s as docxExtensions } from "./core-DEqBHRzE.mjs";
|
|
2
|
+
import { Markdown, MarkdownManager } from "@tiptap/markdown";
|
|
3
|
+
//#region src/converters/markdown.ts
|
|
4
|
+
const markdownManager = new MarkdownManager({ extensions: [...docxExtensions, Markdown] });
|
|
5
|
+
/**
|
|
6
|
+
* Parse Markdown string to Tiptap JSON.
|
|
7
|
+
*/
|
|
8
|
+
function parseMarkdown(markdown) {
|
|
9
|
+
return markdownManager.parse(markdown);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generate Markdown string from Tiptap JSON.
|
|
13
|
+
*/
|
|
14
|
+
function generateMarkdown(doc) {
|
|
15
|
+
return markdownManager.serialize(doc);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { parseMarkdown as n, generateMarkdown as t };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { a as JSONContent } from "./core-fBMCCj4D.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/converters/markdown.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Parse Markdown string to Tiptap JSON.
|
|
6
|
+
*/
|
|
7
|
+
declare function parseMarkdown(markdown: string): JSONContent;
|
|
8
|
+
/**
|
|
9
|
+
* Generate Markdown string from Tiptap JSON.
|
|
10
|
+
*/
|
|
11
|
+
declare function generateMarkdown(doc: JSONContent): string;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { parseMarkdown as n, generateMarkdown as t };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import "./tiptap-D7pl4I5U.mjs";
|
|
2
|
+
//#region src/extensions/mention.ts
|
|
3
|
+
/**
|
|
4
|
+
* Mention extension — owns the DOCX expression of an inline mention.
|
|
5
|
+
*
|
|
6
|
+
* A mention is an atom node carrying `{ id, label }`. DOCX has no mention
|
|
7
|
+
* element, but an inline text-SDT (CT_SdtRun) is a reversible carrier: the
|
|
8
|
+
* `id` rides in the SDT alias, the `label` as the SDT's run text, and a fixed
|
|
9
|
+
* tag marks the type so resolve can recover the mention. (customXml would also
|
|
10
|
+
* carry the id but triggers Word's i4i patent warning; SDT does not.)
|
|
11
|
+
*/
|
|
12
|
+
/** SDT tag marking a mention content control. */
|
|
13
|
+
const MENTION_TAG = "docen-mention";
|
|
14
|
+
/** Inline text-SDT carrying a mention (id in alias, label as run text). */
|
|
15
|
+
function createMention(id, label) {
|
|
16
|
+
return { sdt: {
|
|
17
|
+
properties: {
|
|
18
|
+
tag: MENTION_TAG,
|
|
19
|
+
alias: id,
|
|
20
|
+
text: {}
|
|
21
|
+
},
|
|
22
|
+
children: [{ text: label }]
|
|
23
|
+
} };
|
|
24
|
+
}
|
|
25
|
+
/** True if an inline SDT child carries a mention. */
|
|
26
|
+
function isMention(child) {
|
|
27
|
+
if (typeof child !== "object" || child === null || !("sdt" in child)) return false;
|
|
28
|
+
return child.sdt?.properties?.tag === MENTION_TAG;
|
|
29
|
+
}
|
|
30
|
+
/** Read a mention SDT → `{ id, label }`. */
|
|
31
|
+
function readMention(child) {
|
|
32
|
+
const sdt = child.sdt;
|
|
33
|
+
const id = sdt?.properties?.alias ?? "";
|
|
34
|
+
let label = "";
|
|
35
|
+
const first = sdt?.children?.[0];
|
|
36
|
+
if (typeof first === "string") label = first;
|
|
37
|
+
else if (first && typeof first === "object" && "text" in first) label = String(first.text ?? "");
|
|
38
|
+
return {
|
|
39
|
+
id,
|
|
40
|
+
label
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { readMention as i, createMention as n, isMention as r, MENTION_TAG as t };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import "./tiptap-D7pl4I5U.mjs";
|
|
2
|
+
import { LevelFormat } from "@office-open/docx";
|
|
3
|
+
//#region src/extensions/ordered-list.ts
|
|
4
|
+
/**
|
|
5
|
+
* OrderedList extension — owns the DOCX expression of an ordered list.
|
|
6
|
+
*
|
|
7
|
+
* A Tiptap orderedList maps to a sequence of paragraphs referencing one
|
|
8
|
+
* abstractNum (decimal). The reference is keyed by `start` so lists with the
|
|
9
|
+
* same start share a definition; DocxManager gives each list its own instance
|
|
10
|
+
* for independent counting. This module owns that abstractNum shape; DocxManager
|
|
11
|
+
* owns the cross-paragraph tree walk, start recovery, and numbering-instance
|
|
12
|
+
* bookkeeping.
|
|
13
|
+
*/
|
|
14
|
+
/** Reference prefix for generated ordered-list abstractNum definitions. */
|
|
15
|
+
const ORDERED_REFERENCE_PREFIX = "docen-ordered";
|
|
16
|
+
/** lvlText per nesting depth (level 0 → "%1.", … level 8 → "%9."). */
|
|
17
|
+
const ORDERED_LEVEL_TEXT = [
|
|
18
|
+
"%1.",
|
|
19
|
+
"%2.",
|
|
20
|
+
"%3.",
|
|
21
|
+
"%4.",
|
|
22
|
+
"%5.",
|
|
23
|
+
"%6.",
|
|
24
|
+
"%7.",
|
|
25
|
+
"%8.",
|
|
26
|
+
"%9."
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Build nine decimal numbering levels for an ordered list. Level 0 carries
|
|
30
|
+
* `start`; deeper levels restart at 1 (Word convention).
|
|
31
|
+
*/
|
|
32
|
+
function buildOrderedLevels(start) {
|
|
33
|
+
return Array.from({ length: 9 }, (_, level) => ({
|
|
34
|
+
level,
|
|
35
|
+
format: LevelFormat.DECIMAL,
|
|
36
|
+
start: level === 0 ? start : 1,
|
|
37
|
+
text: ORDERED_LEVEL_TEXT[level]
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { ORDERED_REFERENCE_PREFIX as n, buildOrderedLevels as r, ORDERED_LEVEL_TEXT as t };
|