@coding01/docsjs 0.1.3 → 0.1.6

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.
@@ -1,3 +1,6 @@
1
+ // src/lib/docxHtml.ts
2
+ import JSZip from "jszip";
3
+
1
4
  // src/lib/htmlSnapshot.ts
2
5
  var SNAPSHOT_SHELL_START = '<!DOCTYPE html><html><head><meta charset="utf-8"/>';
3
6
  var SNAPSHOT_SHELL_END = "</head><body></body></html>";
@@ -16,7 +19,21 @@ function buildHtmlSnapshot(rawHtml) {
16
19
  }
17
20
 
18
21
  // src/lib/docxHtml.ts
19
- import JSZip from "jszip";
22
+ function createEmptyFeatureCounts() {
23
+ return {
24
+ hyperlinkCount: 0,
25
+ anchorImageCount: 0,
26
+ chartCount: 0,
27
+ smartArtCount: 0,
28
+ ommlCount: 0,
29
+ tableCount: 0,
30
+ footnoteRefCount: 0,
31
+ endnoteRefCount: 0,
32
+ commentRefCount: 0,
33
+ revisionCount: 0,
34
+ pageBreakCount: 0
35
+ };
36
+ }
20
37
  function escapeHtml(text) {
21
38
  return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
22
39
  }
@@ -40,6 +57,9 @@ function getAttr(node, name) {
40
57
  function emuToPx(emu) {
41
58
  return emu * 96 / 914400;
42
59
  }
60
+ function twipToPx(twip) {
61
+ return twip * 96 / 1440;
62
+ }
43
63
  function parseDrawingSizePx(drawing) {
44
64
  const extentNode = queryAllByLocalName(drawing, "extent").find((node) => {
45
65
  const parent = node.parentElement;
@@ -68,9 +88,7 @@ function imageDimensionAttributes(sizePx) {
68
88
  }
69
89
  return attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
70
90
  }
71
- function parseAnchorPositionPx(drawing) {
72
- const anchor = directChildrenByLocalName(drawing, "anchor")[0] ?? null;
73
- if (!anchor) return { leftPx: null, topPx: null };
91
+ function parseAnchorPositionPx(anchor) {
74
92
  let leftPx = null;
75
93
  let topPx = null;
76
94
  const positionH = directChildrenByLocalName(anchor, "positionH")[0] ?? null;
@@ -85,34 +103,80 @@ function parseAnchorPositionPx(drawing) {
85
103
  if (Number.isFinite(top)) topPx = emuToPx(top);
86
104
  return { leftPx, topPx };
87
105
  }
88
- function parseAnchorWrapMode(drawing) {
89
- const anchor = directChildrenByLocalName(drawing, "anchor")[0] ?? null;
90
- if (!anchor) return null;
106
+ function parseAnchorWrapMode(anchor) {
91
107
  if (directChildrenByLocalName(anchor, "wrapSquare")[0]) return "square";
92
108
  if (directChildrenByLocalName(anchor, "wrapTight")[0]) return "tight";
93
109
  if (directChildrenByLocalName(anchor, "wrapTopAndBottom")[0]) return "topAndBottom";
94
110
  if (directChildrenByLocalName(anchor, "wrapNone")[0]) return "none";
95
111
  return null;
96
112
  }
97
- function mergeImageStyle(baseAttrs, anchorPos, wrapMode) {
98
- if (anchorPos.leftPx === null && anchorPos.topPx === null) return baseAttrs;
113
+ function parseAnchorMeta(drawing) {
114
+ const anchor = directChildrenByLocalName(drawing, "anchor")[0] ?? null;
115
+ if (!anchor) return null;
116
+ const positionH = directChildrenByLocalName(anchor, "positionH")[0] ?? null;
117
+ const positionV = directChildrenByLocalName(anchor, "positionV")[0] ?? null;
118
+ const relativeFromH = getAttr(positionH, "relativeFrom");
119
+ const relativeFromV = getAttr(positionV, "relativeFrom");
120
+ const parseDistPx = (name) => {
121
+ const raw = getAttr(anchor, name);
122
+ const emu = raw ? Number.parseInt(raw, 10) : Number.NaN;
123
+ return Number.isFinite(emu) && emu >= 0 ? emuToPx(emu) : null;
124
+ };
125
+ const rawHeight = getAttr(anchor, "relativeHeight");
126
+ const parsedHeight = rawHeight ? Number.parseInt(rawHeight, 10) : Number.NaN;
127
+ const boolAttr = (name, fallback) => {
128
+ const raw = (getAttr(anchor, name) ?? "").toLowerCase();
129
+ if (raw === "1" || raw === "true" || raw === "on") return true;
130
+ if (raw === "0" || raw === "false" || raw === "off") return false;
131
+ return fallback;
132
+ };
133
+ return {
134
+ position: parseAnchorPositionPx(anchor),
135
+ wrapMode: parseAnchorWrapMode(anchor),
136
+ distTPx: parseDistPx("distT"),
137
+ distBPx: parseDistPx("distB"),
138
+ distLPx: parseDistPx("distL"),
139
+ distRPx: parseDistPx("distR"),
140
+ relativeFromH,
141
+ relativeFromV,
142
+ behindDoc: boolAttr("behindDoc", false),
143
+ allowOverlap: boolAttr("allowOverlap", true),
144
+ layoutInCell: boolAttr("layoutInCell", true),
145
+ relativeHeight: Number.isFinite(parsedHeight) ? parsedHeight : null
146
+ };
147
+ }
148
+ function mergeImageStyle(baseAttrs, anchorMeta) {
149
+ if (!anchorMeta) return baseAttrs;
150
+ const { position, wrapMode } = anchorMeta;
151
+ if (position.leftPx === null && position.topPx === null) return baseAttrs;
99
152
  const styleParts = [
100
153
  "position:absolute",
101
- anchorPos.leftPx !== null ? `left:${anchorPos.leftPx.toFixed(2)}px` : "",
102
- anchorPos.topPx !== null ? `top:${anchorPos.topPx.toFixed(2)}px` : "",
103
- "z-index:3"
154
+ position.leftPx !== null ? `left:${position.leftPx.toFixed(2)}px` : "",
155
+ position.topPx !== null ? `top:${position.topPx.toFixed(2)}px` : "",
156
+ `z-index:${anchorMeta.behindDoc ? 0 : anchorMeta.relativeHeight ?? 3}`,
157
+ anchorMeta.distTPx !== null ? `margin-top:${anchorMeta.distTPx.toFixed(2)}px` : "",
158
+ anchorMeta.distBPx !== null ? `margin-bottom:${anchorMeta.distBPx.toFixed(2)}px` : "",
159
+ anchorMeta.distLPx !== null ? `margin-left:${anchorMeta.distLPx.toFixed(2)}px` : "",
160
+ anchorMeta.distRPx !== null ? `margin-right:${anchorMeta.distRPx.toFixed(2)}px` : ""
104
161
  ].filter((x) => x.length > 0);
105
162
  if (wrapMode === "topAndBottom") {
106
- styleParts.push("display:block");
107
- }
163
+ styleParts.push("display:block", "clear:both");
164
+ }
165
+ const anchorAttrs = [
166
+ `data-word-anchor="1"`,
167
+ wrapMode ? `data-word-wrap="${wrapMode}"` : "",
168
+ anchorMeta.relativeFromH ? `data-word-anchor-relh="${escapeHtml(anchorMeta.relativeFromH)}"` : "",
169
+ anchorMeta.relativeFromV ? `data-word-anchor-relv="${escapeHtml(anchorMeta.relativeFromV)}"` : "",
170
+ anchorMeta.behindDoc ? `data-word-anchor-behind="1"` : `data-word-anchor-behind="0"`,
171
+ anchorMeta.allowOverlap ? `data-word-anchor-overlap="1"` : `data-word-anchor-overlap="0"`,
172
+ anchorMeta.layoutInCell ? `data-word-anchor-layout-cell="1"` : `data-word-anchor-layout-cell="0"`
173
+ ].filter((x) => x.length > 0).join(" ");
108
174
  if (!baseAttrs.includes("style=")) {
109
- const wrapAttr = wrapMode ? ` data-word-wrap="${wrapMode}"` : "";
110
- return `${baseAttrs} style="${styleParts.join(";")}" data-word-anchor="1"${wrapAttr}`;
175
+ return `${baseAttrs} style="${styleParts.join(";")}" ${anchorAttrs}`;
111
176
  }
112
177
  return baseAttrs.replace(/style="([^"]*)"/, (_m, styleText) => {
113
178
  const merged = [styleText, ...styleParts].filter((x) => x.length > 0).join(";");
114
- const wrapAttr = wrapMode ? ` data-word-wrap="${wrapMode}"` : "";
115
- return `style="${merged}" data-word-anchor="1"${wrapAttr}`;
179
+ return `style="${merged}" ${anchorAttrs}`;
116
180
  });
117
181
  }
118
182
  function parseDocRelsMap(relsXmlText) {
@@ -138,11 +202,29 @@ function extToMime(ext) {
138
202
  if (lower === "svg") return "image/svg+xml";
139
203
  return "application/octet-stream";
140
204
  }
205
+ function normalizeWordPath(relTarget) {
206
+ const normalized = relTarget.replace(/\\/g, "/").replace(/^\/+/, "");
207
+ if (normalized.startsWith("word/")) return normalized;
208
+ if (normalized.startsWith("../")) return `word/${normalized.replace(/^(\.\.\/)+/, "")}`;
209
+ return `word/${normalized}`;
210
+ }
211
+ function resolveHyperlinkHref(relMap, rid, anchor) {
212
+ if (anchor && anchor.trim()) return `#${encodeURIComponent(anchor.trim())}`;
213
+ if (!rid) return null;
214
+ const relTarget = relMap[rid];
215
+ if (!relTarget) return null;
216
+ const trimmed = relTarget.trim();
217
+ if (!trimmed) return null;
218
+ const lower = trimmed.toLowerCase();
219
+ if (lower.startsWith("http://") || lower.startsWith("https://") || lower.startsWith("mailto:") || lower.startsWith("tel:")) {
220
+ return trimmed;
221
+ }
222
+ return trimmed.startsWith("#") ? trimmed : `#${encodeURIComponent(trimmed)}`;
223
+ }
141
224
  async function imageRidToDataUrl(zip, relMap, rid) {
142
225
  const relTarget = relMap[rid];
143
226
  if (!relTarget) return null;
144
- const normalized = relTarget.replace(/^\/+/, "");
145
- const path = normalized.startsWith("word/") ? normalized : `word/${normalized}`;
227
+ const path = normalizeWordPath(relTarget);
146
228
  const file = zip.file(path);
147
229
  if (!file) return null;
148
230
  const base64 = await file.async("base64");
@@ -150,6 +232,55 @@ async function imageRidToDataUrl(zip, relMap, rid) {
150
232
  const mime = extToMime(ext);
151
233
  return `data:${mime};base64,${base64}`;
152
234
  }
235
+ async function readXmlByRid(zip, relMap, rid) {
236
+ const relTarget = relMap[rid];
237
+ if (!relTarget) return null;
238
+ const path = normalizeWordPath(relTarget);
239
+ const file = zip.file(path);
240
+ return file ? file.async("string") : null;
241
+ }
242
+ function parseChartType(chartDoc) {
243
+ const known = ["barChart", "lineChart", "pieChart", "areaChart", "scatterChart", "radarChart", "doughnutChart"];
244
+ for (const type of known) {
245
+ if (queryByLocalName(chartDoc, type)) return type.replace(/Chart$/, "");
246
+ }
247
+ return "unknown";
248
+ }
249
+ function parseChartSummary(chartXmlText) {
250
+ const chartDoc = parseXml(chartXmlText);
251
+ const title = queryAllByLocalName(chartDoc, "t").map((n) => (n.textContent ?? "").trim()).find((v) => v.length > 0) ?? "Chart";
252
+ const seriesCount = queryAllByLocalName(chartDoc, "ser").length;
253
+ const pointCount = queryAllByLocalName(chartDoc, "pt").length;
254
+ const type = parseChartType(chartDoc);
255
+ return { title, type, seriesCount, pointCount };
256
+ }
257
+ function extractSmartArtText(diagramXmlText) {
258
+ const diagramDoc = parseXml(diagramXmlText);
259
+ return queryAllByLocalName(diagramDoc, "t").map((n) => (n.textContent ?? "").trim()).filter((v) => v.length > 0).slice(0, 12);
260
+ }
261
+ function ommlNodeToText(node) {
262
+ if (node.localName === "t") return node.textContent ?? "";
263
+ if (node.localName === "f") {
264
+ const num = queryByLocalName(node, "num");
265
+ const den = queryByLocalName(node, "den");
266
+ return `(${num ? ommlNodeToText(num) : "?"})/(${den ? ommlNodeToText(den) : "?"})`;
267
+ }
268
+ if (node.localName === "sSup") {
269
+ const e = queryByLocalName(node, "e");
270
+ const sup = queryByLocalName(node, "sup");
271
+ return `${e ? ommlNodeToText(e) : ""}^(${sup ? ommlNodeToText(sup) : ""})`;
272
+ }
273
+ if (node.localName === "sSub") {
274
+ const e = queryByLocalName(node, "e");
275
+ const sub = queryByLocalName(node, "sub");
276
+ return `${e ? ommlNodeToText(e) : ""}_(${sub ? ommlNodeToText(sub) : ""})`;
277
+ }
278
+ if (node.localName === "rad") {
279
+ const e = queryByLocalName(node, "e");
280
+ return `sqrt(${e ? ommlNodeToText(e) : ""})`;
281
+ }
282
+ return Array.from(node.children).map((child) => ommlNodeToText(child)).join("");
283
+ }
153
284
  function runStyleToCss(rPr) {
154
285
  if (!rPr) return "";
155
286
  const declarations = [];
@@ -264,48 +395,73 @@ function renderEndnotesSection(usedIds, endnotesMap) {
264
395
  const items = uniq.map((id) => `<li id="word-endnote-${id}" data-word-endnote-id="${id}">${endnotesMap[id]}</li>`).join("");
265
396
  return `<section data-word-endnotes="1"><hr/><ol>${items}</ol></section>`;
266
397
  }
267
- async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotesMap, usedFootnoteIds, endnotesMap, usedEndnoteIds, commentsMap, usedCommentIds) {
398
+ async function paragraphToHtml(zip, relMap, context, paragraph, paragraphIndex, footnotesMap, usedFootnoteIds, endnotesMap, usedEndnoteIds, commentsMap, usedCommentIds) {
268
399
  const tag = paragraphTag(paragraph);
269
400
  const alignStyle = paragraphAlignStyle(paragraph);
270
401
  const dataAttr = paragraphDataAttr(paragraphIndex);
271
- const runs = queryAllByLocalName(paragraph, "r");
272
- if (runs.length === 0) {
402
+ const hasRenderableNode = queryAllByLocalName(paragraph, "r").length > 0 || queryAllByLocalName(paragraph, "oMath").length > 0 || queryAllByLocalName(paragraph, "oMathPara").length > 0;
403
+ if (!hasRenderableNode) {
273
404
  return `<${tag}${dataAttr}${alignStyle ? ` style="${alignStyle}"` : ""}><br/></${tag}>`;
274
405
  }
275
- const parts = [];
276
- const renderedPageBreakCount = queryAllByLocalName(paragraph, "lastRenderedPageBreak").length;
277
- for (let i = 0; i < renderedPageBreakCount; i += 1) {
278
- parts.push(`<span data-word-page-break="1" style="display:block;break-before:page"></span>`);
406
+ function parseRevisionMeta(node, type) {
407
+ return {
408
+ type,
409
+ id: getAttr(node, "w:id") ?? getAttr(node, "id"),
410
+ author: getAttr(node, "w:author") ?? getAttr(node, "author"),
411
+ date: getAttr(node, "w:date") ?? getAttr(node, "date")
412
+ };
413
+ }
414
+ function inferRevisionMeta(run, fallback) {
415
+ if (fallback) return fallback;
416
+ let cursor = run;
417
+ while (cursor) {
418
+ if (cursor.localName === "ins") return parseRevisionMeta(cursor, "ins");
419
+ if (cursor.localName === "del") return parseRevisionMeta(cursor, "del");
420
+ if (cursor.localName === "p") break;
421
+ cursor = cursor.parentElement;
422
+ }
423
+ return null;
424
+ }
425
+ function revisionMetaAttrs(meta) {
426
+ const attrs = [`data-word-revision="${meta.type}"`];
427
+ if (meta.id) attrs.push(`data-word-revision-id="${escapeHtml(meta.id)}"`);
428
+ if (meta.author) attrs.push(`data-word-revision-author="${escapeHtml(meta.author)}"`);
429
+ if (meta.date) attrs.push(`data-word-revision-date="${escapeHtml(meta.date)}"`);
430
+ return attrs.join(" ");
279
431
  }
280
- for (const run of runs) {
432
+ async function runToHtml(run, revisionFallback) {
433
+ const result = [];
281
434
  const rPr = queryByLocalName(run, "rPr");
282
435
  const css = runStyleToCss(rPr);
283
436
  const footnoteRef = queryByLocalName(run, "footnoteReference");
284
437
  const footnoteId = getAttr(footnoteRef, "w:id") ?? getAttr(footnoteRef, "id");
285
438
  if (footnoteId && footnotesMap[footnoteId]) {
439
+ context.features.footnoteRefCount += 1;
286
440
  usedFootnoteIds.push(footnoteId);
287
- parts.push(
441
+ result.push(
288
442
  `<sup data-word-footnote-ref="${footnoteId}"><a href="#word-footnote-${footnoteId}">[${footnoteId}]</a></sup>`
289
443
  );
290
- continue;
444
+ return result;
291
445
  }
292
446
  const endnoteRef = queryByLocalName(run, "endnoteReference");
293
447
  const endnoteId = getAttr(endnoteRef, "w:id") ?? getAttr(endnoteRef, "id");
294
448
  if (endnoteId && endnotesMap[endnoteId]) {
449
+ context.features.endnoteRefCount += 1;
295
450
  usedEndnoteIds.push(endnoteId);
296
- parts.push(
451
+ result.push(
297
452
  `<sup data-word-endnote-ref="${endnoteId}"><a href="#word-endnote-${endnoteId}">[${endnoteId}]</a></sup>`
298
453
  );
299
- continue;
454
+ return result;
300
455
  }
301
456
  const commentRef = queryByLocalName(run, "commentReference");
302
457
  const commentId = getAttr(commentRef, "w:id") ?? getAttr(commentRef, "id");
303
458
  if (commentId && commentsMap[commentId]) {
459
+ context.features.commentRefCount += 1;
304
460
  usedCommentIds.push(commentId);
305
- parts.push(
461
+ result.push(
306
462
  `<sup data-word-comment-ref="${commentId}"><a href="#word-comment-${commentId}">[c${commentId}]</a></sup>`
307
463
  );
308
- continue;
464
+ return result;
309
465
  }
310
466
  const drawing = queryByLocalName(run, "drawing");
311
467
  if (drawing) {
@@ -316,13 +472,38 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
316
472
  if (src) {
317
473
  const imageSize = parseDrawingSizePx(drawing);
318
474
  const dimensionAttrs = imageDimensionAttributes(imageSize);
319
- const anchorPos = parseAnchorPositionPx(drawing);
320
- const wrapMode = parseAnchorWrapMode(drawing);
321
- const attrs = mergeImageStyle(dimensionAttrs, anchorPos, wrapMode);
322
- parts.push(`<img src="${src}" alt="word-image"${attrs}/>`);
323
- continue;
475
+ const anchorMeta = parseAnchorMeta(drawing);
476
+ const attrs = mergeImageStyle(dimensionAttrs, anchorMeta);
477
+ if (anchorMeta) context.features.anchorImageCount += 1;
478
+ result.push(`<img src="${src}" alt="word-image"${attrs}/>`);
479
+ return result;
324
480
  }
325
481
  }
482
+ const chartRef = queryByLocalName(drawing, "chart");
483
+ const chartRid = getAttr(chartRef, "r:id") ?? getAttr(chartRef, "id");
484
+ if (chartRid) {
485
+ const chartXmlText = await readXmlByRid(zip, relMap, chartRid);
486
+ if (chartXmlText) {
487
+ const summary = parseChartSummary(chartXmlText);
488
+ context.features.chartCount += 1;
489
+ result.push(
490
+ `<figure data-word-chart="1" data-word-chart-type="${summary.type}" data-word-chart-series="${summary.seriesCount}" data-word-chart-points="${summary.pointCount}"><figcaption>${escapeHtml(summary.title)}</figcaption><div>Chart(${escapeHtml(summary.type)}): series=${summary.seriesCount}, points=${summary.pointCount}</div></figure>`
491
+ );
492
+ return result;
493
+ }
494
+ }
495
+ const smartArtRef = queryByLocalName(drawing, "relIds");
496
+ const smartArtRid = getAttr(smartArtRef, "r:dm") ?? getAttr(smartArtRef, "dm");
497
+ if (smartArtRid) {
498
+ const diagramXmlText = await readXmlByRid(zip, relMap, smartArtRid);
499
+ const textItems = diagramXmlText ? extractSmartArtText(diagramXmlText) : [];
500
+ context.features.smartArtCount += 1;
501
+ const preview = textItems.length > 0 ? `: ${escapeHtml(textItems.join(" / "))}` : "";
502
+ result.push(
503
+ `<figure data-word-smartart="1" data-word-smartart-items="${textItems.length}"><figcaption>SmartArt fallback${preview}</figcaption></figure>`
504
+ );
505
+ return result;
506
+ }
326
507
  }
327
508
  const texts = queryAllByLocalName(run, "t").map((t) => t.textContent ?? "").join("");
328
509
  const delTexts = queryAllByLocalName(run, "delText").map((t) => t.textContent ?? "").join("");
@@ -333,40 +514,86 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
333
514
  }).length;
334
515
  const lineBreakCount = Math.max(0, brNodes.length - pageBreakCount);
335
516
  const runText2 = `${escapeHtml(texts || delTexts)}${"<br/>".repeat(lineBreakCount)}`;
336
- if (!runText2) continue;
337
- let revisionType = null;
338
- let cursor = run;
339
- while (cursor) {
340
- if (cursor.localName === "ins") {
341
- revisionType = "ins";
342
- break;
343
- }
344
- if (cursor.localName === "del") {
345
- revisionType = "del";
346
- break;
517
+ if (runText2) {
518
+ const revisionMeta = inferRevisionMeta(run, revisionFallback);
519
+ if (css) {
520
+ const span = `<span style="${css}">${runText2}</span>`;
521
+ if (revisionMeta) {
522
+ context.features.revisionCount += 1;
523
+ const tagName = revisionMeta.type === "ins" ? "ins" : "del";
524
+ result.push(`<${tagName} ${revisionMetaAttrs(revisionMeta)}>${span}</${tagName}>`);
525
+ } else {
526
+ result.push(span);
527
+ }
528
+ } else if (revisionMeta) {
529
+ context.features.revisionCount += 1;
530
+ const tagName = revisionMeta.type === "ins" ? "ins" : "del";
531
+ result.push(`<${tagName} ${revisionMetaAttrs(revisionMeta)}>${runText2}</${tagName}>`);
532
+ } else {
533
+ result.push(runText2);
347
534
  }
348
- if (cursor.localName === "p") break;
349
- cursor = cursor.parentElement;
350
535
  }
351
- if (css) {
352
- const span = `<span style="${css}">${runText2}</span>`;
353
- if (revisionType) {
354
- const tag2 = revisionType === "ins" ? "ins" : "del";
355
- parts.push(`<${tag2} data-word-revision="${revisionType}">${span}</${tag2}>`);
356
- } else {
357
- parts.push(span);
536
+ for (let i = 0; i < pageBreakCount; i += 1) {
537
+ context.features.pageBreakCount += 1;
538
+ result.push(`<span data-word-page-break="1" style="display:block;break-before:page"></span>`);
539
+ }
540
+ return result;
541
+ }
542
+ async function nodeToHtml(node, revisionFallback) {
543
+ if (node.localName === "commentRangeStart") {
544
+ const id = getAttr(node, "w:id") ?? getAttr(node, "id");
545
+ return id ? [`<span data-word-comment-range-start="${id}"></span>`] : [];
546
+ }
547
+ if (node.localName === "commentRangeEnd") {
548
+ const id = getAttr(node, "w:id") ?? getAttr(node, "id");
549
+ return id ? [`<span data-word-comment-range-end="${id}"></span>`] : [];
550
+ }
551
+ if (node.localName === "r") {
552
+ return runToHtml(node, revisionFallback);
553
+ }
554
+ if (node.localName === "hyperlink") {
555
+ const rid = getAttr(node, "r:id") ?? getAttr(node, "id");
556
+ const anchor = getAttr(node, "w:anchor") ?? getAttr(node, "anchor");
557
+ const href = resolveHyperlinkHref(relMap, rid, anchor);
558
+ const nested2 = [];
559
+ for (const child of Array.from(node.children)) {
560
+ nested2.push(...await nodeToHtml(child, revisionFallback));
358
561
  }
359
- } else {
360
- if (revisionType) {
361
- const tag2 = revisionType === "ins" ? "ins" : "del";
362
- parts.push(`<${tag2} data-word-revision="${revisionType}">${runText2}</${tag2}>`);
363
- } else {
364
- parts.push(runText2);
562
+ const content2 = nested2.join("") || escapeHtml(node.textContent ?? "");
563
+ if (!href) return content2 ? [content2] : [];
564
+ context.features.hyperlinkCount += 1;
565
+ return [
566
+ `<a data-word-hyperlink="1" href="${escapeHtml(href)}" rel="noreferrer noopener" target="_blank">${content2}</a>`
567
+ ];
568
+ }
569
+ if (node.localName === "oMath" || node.localName === "oMathPara") {
570
+ const linear = ommlNodeToText(node).trim();
571
+ if (!linear) return [];
572
+ context.features.ommlCount += 1;
573
+ return [`<span data-word-omml="1">${escapeHtml(linear)}</span>`];
574
+ }
575
+ if (node.localName === "ins" || node.localName === "del") {
576
+ const scopedMeta = parseRevisionMeta(node, node.localName === "ins" ? "ins" : "del");
577
+ const nested2 = [];
578
+ for (const child of Array.from(node.children)) {
579
+ nested2.push(...await nodeToHtml(child, scopedMeta));
365
580
  }
581
+ return nested2;
366
582
  }
367
- for (let i = 0; i < pageBreakCount; i += 1) {
368
- parts.push(`<span data-word-page-break="1" style="display:block;break-before:page"></span>`);
583
+ const nested = [];
584
+ for (const child of Array.from(node.children)) {
585
+ nested.push(...await nodeToHtml(child, revisionFallback));
369
586
  }
587
+ return nested;
588
+ }
589
+ const parts = [];
590
+ const renderedPageBreakCount = queryAllByLocalName(paragraph, "lastRenderedPageBreak").length;
591
+ for (let i = 0; i < renderedPageBreakCount; i += 1) {
592
+ context.features.pageBreakCount += 1;
593
+ parts.push(`<span data-word-page-break="1" style="display:block;break-before:page"></span>`);
594
+ }
595
+ for (const child of Array.from(paragraph.children)) {
596
+ parts.push(...await nodeToHtml(child, null));
370
597
  }
371
598
  const content = parts.join("") || "<br/>";
372
599
  return `<${tag}${dataAttr}${alignStyle ? ` style="${alignStyle}"` : ""}>${content}</${tag}>`;
@@ -396,7 +623,102 @@ function parseTcVMerge(tc) {
396
623
  const rawVal = (getAttr(vMerge, "w:val") ?? getAttr(vMerge, "val") ?? "continue").toLowerCase();
397
624
  return rawVal === "restart" ? "restart" : "continue";
398
625
  }
399
- function tableCellHtml(cell, paragraphIndexMap) {
626
+ function parseTblGridWidthsPx(table) {
627
+ const grid = directChildrenByLocalName(table, "tblGrid")[0] ?? null;
628
+ if (!grid) return [];
629
+ return directChildrenByLocalName(grid, "gridCol").map((col) => {
630
+ const raw = getAttr(col, "w:w") ?? getAttr(col, "w");
631
+ const twip = raw ? Number.parseInt(raw, 10) : Number.NaN;
632
+ return Number.isFinite(twip) && twip > 0 ? twipToPx(twip) : 0;
633
+ }).filter((px) => px > 0);
634
+ }
635
+ function borderSizeToPx(size) {
636
+ return size / 6;
637
+ }
638
+ function parseBorderCss(borderNode) {
639
+ if (!borderNode) return null;
640
+ const val = (getAttr(borderNode, "w:val") ?? getAttr(borderNode, "val") ?? "").toLowerCase();
641
+ if (!val || val === "nil" || val === "none") return "none";
642
+ const color = (getAttr(borderNode, "w:color") ?? getAttr(borderNode, "color") ?? "222222").replace(/^#/, "");
643
+ const rawSize = getAttr(borderNode, "w:sz") ?? getAttr(borderNode, "sz");
644
+ const size = rawSize ? Number.parseInt(rawSize, 10) : Number.NaN;
645
+ const px = Number.isFinite(size) && size > 0 ? borderSizeToPx(size) : 1;
646
+ const style = val === "single" ? "solid" : val;
647
+ return `${px.toFixed(2)}px ${style} #${color}`;
648
+ }
649
+ function parseTableStyleProfile(table) {
650
+ const tblPr = directChildrenByLocalName(table, "tblPr")[0] ?? null;
651
+ const tblBorders = tblPr ? directChildrenByLocalName(tblPr, "tblBorders")[0] ?? null : null;
652
+ const layout = tblPr ? directChildrenByLocalName(tblPr, "tblLayout")[0] ?? null : null;
653
+ const spacing = tblPr ? directChildrenByLocalName(tblPr, "tblCellSpacing")[0] ?? null : null;
654
+ const spacingType = (getAttr(spacing, "w:type") ?? getAttr(spacing, "type") ?? "dxa").toLowerCase();
655
+ const spacingRaw = getAttr(spacing, "w:w") ?? getAttr(spacing, "w");
656
+ const spacingVal = spacingRaw ? Number.parseFloat(spacingRaw) : Number.NaN;
657
+ const borderSpacingPx = spacingType === "dxa" && Number.isFinite(spacingVal) && spacingVal > 0 ? twipToPx(spacingVal) : 0;
658
+ const borderCollapse = borderSpacingPx > 0 ? "separate" : "collapse";
659
+ const tableLayout = (getAttr(layout, "w:type") ?? getAttr(layout, "type") ?? "").toLowerCase() === "autofit" ? "auto" : "fixed";
660
+ const top = parseBorderCss(tblBorders ? directChildrenByLocalName(tblBorders, "top")[0] ?? null : null);
661
+ const bottom = parseBorderCss(tblBorders ? directChildrenByLocalName(tblBorders, "bottom")[0] ?? null : null);
662
+ const left = parseBorderCss(tblBorders ? directChildrenByLocalName(tblBorders, "left")[0] ?? null : null);
663
+ const right = parseBorderCss(tblBorders ? directChildrenByLocalName(tblBorders, "right")[0] ?? null : null);
664
+ const insideH = parseBorderCss(tblBorders ? directChildrenByLocalName(tblBorders, "insideH")[0] ?? null : null);
665
+ const insideV = parseBorderCss(tblBorders ? directChildrenByLocalName(tblBorders, "insideV")[0] ?? null : null);
666
+ const borderCss = top ?? right ?? bottom ?? left ?? "1px solid #222";
667
+ return {
668
+ tableLayout,
669
+ borderCollapse,
670
+ borderSpacingPx,
671
+ borderCss,
672
+ insideHCss: insideH,
673
+ insideVCss: insideV
674
+ };
675
+ }
676
+ function parseTableWidthStyle(table, gridWidthsPx) {
677
+ const tblPr = directChildrenByLocalName(table, "tblPr")[0] ?? null;
678
+ const tblW = tblPr ? directChildrenByLocalName(tblPr, "tblW")[0] ?? null : null;
679
+ const type = (getAttr(tblW, "w:type") ?? getAttr(tblW, "type") ?? "").toLowerCase();
680
+ const rawVal = getAttr(tblW, "w:w") ?? getAttr(tblW, "w");
681
+ const numericVal = rawVal ? Number.parseFloat(rawVal) : Number.NaN;
682
+ if (type === "dxa" && Number.isFinite(numericVal) && numericVal > 0) {
683
+ return `width:${twipToPx(numericVal).toFixed(2)}px`;
684
+ }
685
+ if (type === "pct" && Number.isFinite(numericVal) && numericVal > 0) {
686
+ return `width:${(numericVal / 50).toFixed(2)}%`;
687
+ }
688
+ const gridTotal = gridWidthsPx.reduce((sum, item) => sum + item, 0);
689
+ if (gridTotal > 0) return `width:${gridTotal.toFixed(2)}px;max-width:100%`;
690
+ return "width:100%";
691
+ }
692
+ function parseCellWidthStyle(cell, colCursor, colSpan, gridWidthsPx) {
693
+ const tcPr = directChildrenByLocalName(cell, "tcPr")[0] ?? null;
694
+ const tcW = tcPr ? directChildrenByLocalName(tcPr, "tcW")[0] ?? null : null;
695
+ const type = (getAttr(tcW, "w:type") ?? getAttr(tcW, "type") ?? "").toLowerCase();
696
+ const rawVal = getAttr(tcW, "w:w") ?? getAttr(tcW, "w");
697
+ const numericVal = rawVal ? Number.parseFloat(rawVal) : Number.NaN;
698
+ if (type === "dxa" && Number.isFinite(numericVal) && numericVal > 0) {
699
+ return `width:${twipToPx(numericVal).toFixed(2)}px`;
700
+ }
701
+ if (type === "pct" && Number.isFinite(numericVal) && numericVal > 0) {
702
+ return `width:${(numericVal / 50).toFixed(2)}%`;
703
+ }
704
+ const width = gridWidthsPx.slice(colCursor, colCursor + colSpan).reduce((sum, item) => sum + item, 0);
705
+ if (width > 0) return `width:${width.toFixed(2)}px`;
706
+ return "";
707
+ }
708
+ function parseCellBorderStyle(cell, tableStyle) {
709
+ const tcPr = directChildrenByLocalName(cell, "tcPr")[0] ?? null;
710
+ const tcBorders = tcPr ? directChildrenByLocalName(tcPr, "tcBorders")[0] ?? null : null;
711
+ if (!tcBorders) {
712
+ const fallback = tableStyle.insideHCss ?? tableStyle.insideVCss ?? tableStyle.borderCss;
713
+ return `border:${fallback}`;
714
+ }
715
+ const top = parseBorderCss(directChildrenByLocalName(tcBorders, "top")[0] ?? null) ?? tableStyle.insideHCss ?? tableStyle.borderCss;
716
+ const right = parseBorderCss(directChildrenByLocalName(tcBorders, "right")[0] ?? null) ?? tableStyle.insideVCss ?? tableStyle.borderCss;
717
+ const bottom = parseBorderCss(directChildrenByLocalName(tcBorders, "bottom")[0] ?? null) ?? tableStyle.insideHCss ?? tableStyle.borderCss;
718
+ const left = parseBorderCss(directChildrenByLocalName(tcBorders, "left")[0] ?? null) ?? tableStyle.insideVCss ?? tableStyle.borderCss;
719
+ return `border-top:${top};border-right:${right};border-bottom:${bottom};border-left:${left}`;
720
+ }
721
+ function tableCellHtml(cell, paragraphIndexMap, context) {
400
722
  const blocks = [];
401
723
  for (const child of Array.from(cell.children)) {
402
724
  if (child.localName === "tcPr") continue;
@@ -406,7 +728,7 @@ function tableCellHtml(cell, paragraphIndexMap) {
406
728
  continue;
407
729
  }
408
730
  if (child.localName === "tbl") {
409
- blocks.push(tableToHtml(child, paragraphIndexMap));
731
+ blocks.push(tableToHtml(child, paragraphIndexMap, context));
410
732
  continue;
411
733
  }
412
734
  }
@@ -414,8 +736,11 @@ function tableCellHtml(cell, paragraphIndexMap) {
414
736
  const text = queryAllByLocalName(cell, "t").map((t) => t.textContent ?? "").join("").trim();
415
737
  return escapeHtml(text) || "<br/>";
416
738
  }
417
- function tableToHtml(table, paragraphIndexMap) {
739
+ function tableToHtml(table, paragraphIndexMap, context) {
740
+ context.features.tableCount += 1;
418
741
  const rows = directChildrenByLocalName(table, "tr");
742
+ const gridWidthsPx = parseTblGridWidthsPx(table);
743
+ const tableStyle = parseTableStyleProfile(table);
419
744
  const activeByCol = /* @__PURE__ */ new Map();
420
745
  const allOrigins = [];
421
746
  let nextOriginId = 1;
@@ -440,8 +765,10 @@ function tableToHtml(table, paragraphIndexMap) {
440
765
  while (activeByCol.has(colCursor)) {
441
766
  colCursor += 1;
442
767
  }
443
- const html = tableCellHtml(cell, paragraphIndexMap);
768
+ const html = tableCellHtml(cell, paragraphIndexMap, context);
444
769
  const attrs = [];
770
+ const widthStyle = parseCellWidthStyle(cell, colCursor, colSpan, gridWidthsPx);
771
+ const borderStyle = parseCellBorderStyle(cell, tableStyle);
445
772
  if (vMerge === "restart") {
446
773
  const origin = {
447
774
  id: `m${nextOriginId}`,
@@ -459,7 +786,7 @@ function tableToHtml(table, paragraphIndexMap) {
459
786
  }
460
787
  if (colSpan > 1) attrs.push(`colspan="${colSpan}"`);
461
788
  emittedCells.push(
462
- `<td${attrs.length > 0 ? ` ${attrs.join(" ")}` : ""} style="border:1px solid #222;vertical-align:top;">${html}</td>`
789
+ `<td${attrs.length > 0 ? ` ${attrs.join(" ")}` : ""} style="${borderStyle};vertical-align:top;${widthStyle}">${html}</td>`
463
790
  );
464
791
  colCursor += colSpan;
465
792
  }
@@ -478,9 +805,13 @@ function tableToHtml(table, paragraphIndexMap) {
478
805
  const replacement = origin.rowSpan > 1 ? `rowspan="${origin.rowSpan}"` : "";
479
806
  merged = merged.replace(marker, replacement).replace(/\s{2,}/g, " ");
480
807
  }
481
- return `<table style="border-collapse:collapse;table-layout:fixed;width:100%;border:1px solid #222;">${merged}</table>`;
808
+ const tableWidthStyle = parseTableWidthStyle(table, gridWidthsPx);
809
+ const spacing = tableStyle.borderSpacingPx > 0 ? `border-spacing:${tableStyle.borderSpacingPx.toFixed(2)}px;` : "";
810
+ return `<table style="border-collapse:${tableStyle.borderCollapse};${spacing}table-layout:${tableStyle.tableLayout};${tableWidthStyle};border:${tableStyle.borderCss};">${merged}</table>`;
482
811
  }
483
- async function parseDocxToHtmlSnapshot(file) {
812
+ async function parseDocxToHtmlSnapshotWithReport(file) {
813
+ const startedAt = Date.now();
814
+ const context = { features: createEmptyFeatureCounts() };
484
815
  const maybeArrayBuffer = file.arrayBuffer;
485
816
  const buffer = maybeArrayBuffer ? await maybeArrayBuffer.call(file) : await new Response(file).arrayBuffer();
486
817
  const zip = await JSZip.loadAsync(buffer);
@@ -517,6 +848,7 @@ async function parseDocxToHtmlSnapshot(file) {
517
848
  await paragraphToHtml(
518
849
  zip,
519
850
  relMap,
851
+ context,
520
852
  child,
521
853
  paragraphIndex,
522
854
  footnotesMap,
@@ -530,14 +862,24 @@ async function parseDocxToHtmlSnapshot(file) {
530
862
  continue;
531
863
  }
532
864
  if (child.localName === "tbl") {
533
- blockHtml.push(tableToHtml(child, paragraphIndexMap));
865
+ blockHtml.push(tableToHtml(child, paragraphIndexMap, context));
534
866
  continue;
535
867
  }
536
868
  }
537
869
  blockHtml.push(renderFootnotesSection(usedFootnoteIds, footnotesMap));
538
870
  blockHtml.push(renderEndnotesSection(usedEndnoteIds, endnotesMap));
539
871
  blockHtml.push(renderCommentsSection(usedCommentIds, commentsMap));
540
- return buildHtmlSnapshot(blockHtml.join("\n"));
872
+ return {
873
+ htmlSnapshot: buildHtmlSnapshot(blockHtml.join("\n")),
874
+ report: {
875
+ elapsedMs: Date.now() - startedAt,
876
+ features: context.features
877
+ }
878
+ };
879
+ }
880
+ async function parseDocxToHtmlSnapshot(file) {
881
+ const result = await parseDocxToHtmlSnapshotWithReport(file);
882
+ return result.htmlSnapshot;
541
883
  }
542
884
 
543
885
  // src/lib/pastePipeline.ts
@@ -768,7 +1110,7 @@ function createFallbackWordStyleProfile(sourceFileName = "snapshot") {
768
1110
  paragraphProfiles: []
769
1111
  };
770
1112
  }
771
- function twipToPx(twip) {
1113
+ function twipToPx2(twip) {
772
1114
  return twip / 15;
773
1115
  }
774
1116
  function getAttr2(node, attr) {
@@ -812,10 +1154,10 @@ function parsePageGeometry(documentXml) {
812
1154
  const top = getTwipAttr(pgMar, "w:top") ?? getTwipAttr(pgMar, "top") ?? null;
813
1155
  const bottom = getTwipAttr(pgMar, "w:bottom") ?? getTwipAttr(pgMar, "bottom") ?? null;
814
1156
  return {
815
- contentWidthPx: pageW === null ? null : twipToPx(pageW - left - right),
816
- pageHeightPx: pageH === null ? null : twipToPx(pageH),
817
- marginTopPx: top === null ? null : twipToPx(top),
818
- marginBottomPx: bottom === null ? null : twipToPx(bottom)
1157
+ contentWidthPx: pageW === null ? null : twipToPx2(pageW - left - right),
1158
+ pageHeightPx: pageH === null ? null : twipToPx2(pageH),
1159
+ marginTopPx: top === null ? null : twipToPx2(top),
1160
+ marginBottomPx: bottom === null ? null : twipToPx2(bottom)
819
1161
  };
820
1162
  }
821
1163
  function parseHeadingAlignFromDocument(documentXml) {
@@ -988,15 +1330,15 @@ function parseParagraphProfiles(documentXml, numberingMap) {
988
1330
  text,
989
1331
  isEmpty: text.length === 0,
990
1332
  align: parseParagraphAlign(paragraph),
991
- beforePx: before === null ? null : twipToPx(before),
992
- afterPx: after === null ? null : twipToPx(after),
1333
+ beforePx: before === null ? null : twipToPx2(before),
1334
+ afterPx: after === null ? null : twipToPx2(after),
993
1335
  lineHeightRatio: line === null || lineHeightRule !== "auto" ? null : line / 240,
994
- lineHeightPx: line === null || lineHeightRule === "auto" ? null : twipToPx(line),
1336
+ lineHeightPx: line === null || lineHeightRule === "auto" ? null : twipToPx2(line),
995
1337
  lineHeightRule,
996
- indentLeftPx: left === null ? null : twipToPx(left),
997
- indentRightPx: right === null ? null : twipToPx(right),
998
- firstLinePx: firstLine === null ? null : twipToPx(firstLine),
999
- hangingPx: hanging === null ? null : twipToPx(hanging),
1338
+ indentLeftPx: left === null ? null : twipToPx2(left),
1339
+ indentRightPx: right === null ? null : twipToPx2(right),
1340
+ firstLinePx: firstLine === null ? null : twipToPx2(firstLine),
1341
+ hangingPx: hanging === null ? null : twipToPx2(hanging),
1000
1342
  listNumId,
1001
1343
  listLevel,
1002
1344
  listFormat: listSpec?.numFmt ?? null,
@@ -1031,19 +1373,19 @@ function parseTableDefaults(stylesXml) {
1031
1373
  return {
1032
1374
  topPx: (() => {
1033
1375
  const v = getTwipAttr(top, "w:w") ?? getTwipAttr(top, "w") ?? null;
1034
- return v === null ? null : twipToPx(v);
1376
+ return v === null ? null : twipToPx2(v);
1035
1377
  })(),
1036
1378
  leftPx: (() => {
1037
1379
  const v = getTwipAttr(left, "w:w") ?? getTwipAttr(left, "w") ?? null;
1038
- return v === null ? null : twipToPx(v);
1380
+ return v === null ? null : twipToPx2(v);
1039
1381
  })(),
1040
1382
  bottomPx: (() => {
1041
1383
  const v = getTwipAttr(bottom, "w:w") ?? getTwipAttr(bottom, "w") ?? null;
1042
- return v === null ? null : twipToPx(v);
1384
+ return v === null ? null : twipToPx2(v);
1043
1385
  })(),
1044
1386
  rightPx: (() => {
1045
1387
  const v = getTwipAttr(right, "w:w") ?? getTwipAttr(right, "w") ?? null;
1046
- return v === null ? null : twipToPx(v);
1388
+ return v === null ? null : twipToPx2(v);
1047
1389
  })()
1048
1390
  };
1049
1391
  }
@@ -1141,9 +1483,9 @@ function parseDefaults(stylesXml) {
1141
1483
  const rawLineRule = (getAttr2(spacing, "w:lineRule") ?? getAttr2(spacing, "lineRule") ?? "auto").toLowerCase();
1142
1484
  const bodyLineHeightRule = rawLineRule === "exact" ? "exact" : rawLineRule === "atleast" ? "atLeast" : "auto";
1143
1485
  const bodyLineHeightRatio = line === null || bodyLineHeightRule !== "auto" ? null : line / 240;
1144
- const bodyLineHeightPx = line === null || bodyLineHeightRule === "auto" ? null : twipToPx(line);
1486
+ const bodyLineHeightPx = line === null || bodyLineHeightRule === "auto" ? null : twipToPx2(line);
1145
1487
  const after = getTwipAttr(spacing, "w:after") ?? getTwipAttr(spacing, "after") ?? null;
1146
- const paragraphAfterPx = after === null ? null : twipToPx(after);
1488
+ const paragraphAfterPx = after === null ? null : twipToPx2(after);
1147
1489
  return { bodyFontPx, bodyLineHeightRatio, bodyLineHeightPx, bodyLineHeightRule, paragraphAfterPx };
1148
1490
  }
1149
1491
  function parseHeading1Style(stylesXml) {
@@ -1668,7 +2010,7 @@ function applyWordRenderModel({ doc, styleProfile, showFormattingMarks }) {
1668
2010
  }
1669
2011
 
1670
2012
  // src/core/DocsWordElement.ts
1671
- var VERSION = "0.1.2";
2013
+ var VERSION = "0.1.5";
1672
2014
  var MESSAGES = {
1673
2015
  zh: {
1674
2016
  readClipboard: "\u4ECE\u7CFB\u7EDF\u526A\u8D34\u677F\u8BFB\u53D6",
@@ -1811,15 +2153,15 @@ var DocsWordElement = class extends HTMLElement {
1811
2153
  }
1812
2154
  async applyDocx(file) {
1813
2155
  try {
1814
- const [snapshot, profile] = await Promise.all([
1815
- parseDocxToHtmlSnapshot(file),
2156
+ const [parseResult, profile] = await Promise.all([
2157
+ parseDocxToHtmlSnapshotWithReport(file),
1816
2158
  parseDocxStyleProfile(file)
1817
2159
  ]);
1818
2160
  this.styleProfile = profile;
1819
- this.htmlSnapshot = snapshot;
2161
+ this.htmlSnapshot = parseResult.htmlSnapshot;
1820
2162
  this.renderSnapshot();
1821
2163
  this.setHint(MESSAGES[this.locale].loadedWord(profile.sourceFileName));
1822
- this.emitChange("upload", profile.sourceFileName);
2164
+ this.emitChange("upload", profile.sourceFileName, parseResult.report);
1823
2165
  } catch (error) {
1824
2166
  this.emitError(error instanceof Error ? error.message : MESSAGES[this.locale].parseFailed);
1825
2167
  }
@@ -1879,8 +2221,10 @@ var DocsWordElement = class extends HTMLElement {
1879
2221
  renderSnapshot() {
1880
2222
  this.frame.srcdoc = this.htmlSnapshot;
1881
2223
  }
1882
- emitChange(source, fileName) {
1883
- this.dispatchEvent(new CustomEvent("docsjs-change", { detail: { htmlSnapshot: this.htmlSnapshot, source, fileName } }));
2224
+ emitChange(source, fileName, parseReport) {
2225
+ this.dispatchEvent(
2226
+ new CustomEvent("docsjs-change", { detail: { htmlSnapshot: this.htmlSnapshot, source, fileName, parseReport } })
2227
+ );
1884
2228
  }
1885
2229
  emitError(message) {
1886
2230
  this.dispatchEvent(new CustomEvent("docsjs-error", { detail: { message } }));
@@ -1915,7 +2259,9 @@ function defineDocsWordElement() {
1915
2259
  }
1916
2260
 
1917
2261
  export {
2262
+ parseDocxToHtmlSnapshotWithReport,
2263
+ parseDocxToHtmlSnapshot,
1918
2264
  DocsWordElement,
1919
2265
  defineDocsWordElement
1920
2266
  };
1921
- //# sourceMappingURL=chunk-PRPDJOB7.js.map
2267
+ //# sourceMappingURL=chunk-632UOG2B.js.map