@coding01/docsjs 0.1.5 → 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.
- package/README.md +57 -28
- package/README.zh-CN.md +56 -27
- package/dist/{chunk-IBVWD4UO.js → chunk-632UOG2B.js} +91 -17
- package/dist/chunk-632UOG2B.js.map +1 -0
- package/dist/index.cjs +91 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +92 -17
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +12 -3
- package/dist/react.js.map +1 -1
- package/dist/types-VvdwVF0_.d.cts +44 -0
- package/dist/types-VvdwVF0_.d.ts +44 -0
- package/dist/vue.cjs +81 -15
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +1 -1
- package/package.json +2 -1
- package/dist/chunk-IBVWD4UO.js.map +0 -1
- package/dist/types-DF14w1ol.d.cts +0 -20
- package/dist/types-DF14w1ol.d.ts +0 -20
package/dist/react.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { Ref } from 'react';
|
|
2
|
-
import { D as DocsWordEditorChangeDetail, b as DocsWordEditorErrorDetail, c as DocsWordEditorReadyDetail, a as DocsWordEditorElementApi } from './types-
|
|
2
|
+
import { D as DocsWordEditorChangeDetail, b as DocsWordEditorErrorDetail, c as DocsWordEditorReadyDetail, a as DocsWordEditorElementApi } from './types-VvdwVF0_.cjs';
|
|
3
3
|
|
|
4
4
|
interface WordFidelityEditorReactProps {
|
|
5
5
|
lang?: "zh" | "en";
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { Ref } from 'react';
|
|
2
|
-
import { D as DocsWordEditorChangeDetail, b as DocsWordEditorErrorDetail, c as DocsWordEditorReadyDetail, a as DocsWordEditorElementApi } from './types-
|
|
2
|
+
import { D as DocsWordEditorChangeDetail, b as DocsWordEditorErrorDetail, c as DocsWordEditorReadyDetail, a as DocsWordEditorElementApi } from './types-VvdwVF0_.js';
|
|
3
3
|
|
|
4
4
|
interface WordFidelityEditorReactProps {
|
|
5
5
|
lang?: "zh" | "en";
|
package/dist/react.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineDocsWordElement
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-632UOG2B.js";
|
|
4
4
|
|
|
5
5
|
// src/react/WordFidelityEditorReact.tsx
|
|
6
6
|
import React, { useEffect, useRef } from "react";
|
|
7
7
|
defineDocsWordElement();
|
|
8
|
-
function WordFidelityEditorReact({
|
|
8
|
+
function WordFidelityEditorReact({
|
|
9
|
+
lang,
|
|
10
|
+
onChange,
|
|
11
|
+
onError,
|
|
12
|
+
onReady,
|
|
13
|
+
editorRef
|
|
14
|
+
}) {
|
|
9
15
|
const ref = useRef(null);
|
|
10
16
|
useEffect(() => {
|
|
11
17
|
const node = ref.current;
|
|
@@ -33,7 +39,10 @@ function WordFidelityEditorReact({ lang, onChange, onError, onReady, editorRef }
|
|
|
33
39
|
editorRef?.(null);
|
|
34
40
|
};
|
|
35
41
|
}, [editorRef, onChange, onError, onReady]);
|
|
36
|
-
return React.createElement("docs-word-editor", {
|
|
42
|
+
return React.createElement("docs-word-editor", {
|
|
43
|
+
ref,
|
|
44
|
+
lang
|
|
45
|
+
});
|
|
37
46
|
}
|
|
38
47
|
export {
|
|
39
48
|
WordFidelityEditorReact
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/WordFidelityEditorReact.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport type { Ref } from \"react\";\nimport { defineDocsWordElement } from \"../core/DocsWordElement\";\nimport type {\n DocsWordEditorChangeDetail,\n DocsWordEditorElementApi,\n DocsWordEditorErrorDetail,\n DocsWordEditorReadyDetail\n} from \"../core/types\";\n\ndefineDocsWordElement();\n\nexport interface WordFidelityEditorReactProps {\n lang?: \"zh\" | \"en\";\n onChange?: (payload: DocsWordEditorChangeDetail) => void;\n onError?: (payload: DocsWordEditorErrorDetail) => void;\n onReady?: (payload: DocsWordEditorReadyDetail) => void;\n editorRef?: (el: DocsWordEditorElementApi | null) => void;\n}\n\nexport function WordFidelityEditorReact({
|
|
1
|
+
{"version":3,"sources":["../src/react/WordFidelityEditorReact.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport type { Ref } from \"react\";\nimport { defineDocsWordElement } from \"../core/DocsWordElement\";\nimport type {\n DocsWordEditorChangeDetail,\n DocsWordEditorElementApi,\n DocsWordEditorErrorDetail,\n DocsWordEditorReadyDetail\n} from \"../core/types\";\n\ndefineDocsWordElement();\n\nexport interface WordFidelityEditorReactProps {\n lang?: \"zh\" | \"en\";\n onChange?: (payload: DocsWordEditorChangeDetail) => void;\n onError?: (payload: DocsWordEditorErrorDetail) => void;\n onReady?: (payload: DocsWordEditorReadyDetail) => void;\n editorRef?: (el: DocsWordEditorElementApi | null) => void;\n}\n\nexport function WordFidelityEditorReact({\n lang,\n onChange,\n onError,\n onReady,\n editorRef\n}: WordFidelityEditorReactProps) {\n const ref = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n const node = ref.current;\n if (!node) return;\n\n const onChangeEvent = (event: Event) => {\n const detail = (event as CustomEvent<DocsWordEditorChangeDetail>).detail;\n onChange?.(detail);\n };\n const onErrorEvent = (event: Event) => {\n const detail = (event as CustomEvent<DocsWordEditorErrorDetail>).detail;\n onError?.(detail);\n };\n const onReadyEvent = (event: Event) => {\n const detail = (event as CustomEvent<DocsWordEditorReadyDetail>).detail;\n onReady?.(detail);\n };\n\n node.addEventListener(\"docsjs-change\", onChangeEvent);\n node.addEventListener(\"docsjs-error\", onErrorEvent);\n node.addEventListener(\"docsjs-ready\", onReadyEvent);\n editorRef?.(node as DocsWordEditorElementApi);\n return () => {\n node.removeEventListener(\"docsjs-change\", onChangeEvent);\n node.removeEventListener(\"docsjs-error\", onErrorEvent);\n node.removeEventListener(\"docsjs-ready\", onReadyEvent);\n editorRef?.(null);\n };\n }, [editorRef, onChange, onError, onReady]);\n\n return React.createElement(\"docs-word-editor\", {\n ref: ref as unknown as Ref<HTMLElement>,\n lang\n });\n}\n"],"mappings":";;;;;AAAA,OAAO,SAAS,WAAW,cAAc;AAUzC,sBAAsB;AAUf,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAiC;AAC/B,QAAM,MAAM,OAA2B,IAAI;AAE3C,YAAU,MAAM;AACd,UAAM,OAAO,IAAI;AACjB,QAAI,CAAC,KAAM;AAEX,UAAM,gBAAgB,CAAC,UAAiB;AACtC,YAAM,SAAU,MAAkD;AAClE,iBAAW,MAAM;AAAA,IACnB;AACA,UAAM,eAAe,CAAC,UAAiB;AACrC,YAAM,SAAU,MAAiD;AACjE,gBAAU,MAAM;AAAA,IAClB;AACA,UAAM,eAAe,CAAC,UAAiB;AACrC,YAAM,SAAU,MAAiD;AACjE,gBAAU,MAAM;AAAA,IAClB;AAEA,SAAK,iBAAiB,iBAAiB,aAAa;AACpD,SAAK,iBAAiB,gBAAgB,YAAY;AAClD,SAAK,iBAAiB,gBAAgB,YAAY;AAClD,gBAAY,IAAgC;AAC5C,WAAO,MAAM;AACX,WAAK,oBAAoB,iBAAiB,aAAa;AACvD,WAAK,oBAAoB,gBAAgB,YAAY;AACrD,WAAK,oBAAoB,gBAAgB,YAAY;AACrD,kBAAY,IAAI;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,WAAW,UAAU,SAAS,OAAO,CAAC;AAE1C,SAAO,MAAM,cAAc,oBAAoB;AAAA,IAC7C;AAAA,IACA;AAAA,EACF,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
interface DocxParseFeatureCounts {
|
|
2
|
+
hyperlinkCount: number;
|
|
3
|
+
anchorImageCount: number;
|
|
4
|
+
chartCount: number;
|
|
5
|
+
smartArtCount: number;
|
|
6
|
+
ommlCount: number;
|
|
7
|
+
tableCount: number;
|
|
8
|
+
footnoteRefCount: number;
|
|
9
|
+
endnoteRefCount: number;
|
|
10
|
+
commentRefCount: number;
|
|
11
|
+
revisionCount: number;
|
|
12
|
+
pageBreakCount: number;
|
|
13
|
+
}
|
|
14
|
+
interface DocxParseReport {
|
|
15
|
+
elapsedMs: number;
|
|
16
|
+
features: DocxParseFeatureCounts;
|
|
17
|
+
}
|
|
18
|
+
declare function parseDocxToHtmlSnapshotWithReport(file: File): Promise<{
|
|
19
|
+
htmlSnapshot: string;
|
|
20
|
+
report: DocxParseReport;
|
|
21
|
+
}>;
|
|
22
|
+
declare function parseDocxToHtmlSnapshot(file: File): Promise<string>;
|
|
23
|
+
|
|
24
|
+
interface DocsWordEditorChangeDetail {
|
|
25
|
+
htmlSnapshot: string;
|
|
26
|
+
source: "paste" | "upload" | "api" | "clear";
|
|
27
|
+
fileName?: string;
|
|
28
|
+
parseReport?: DocxParseReport;
|
|
29
|
+
}
|
|
30
|
+
interface DocsWordEditorErrorDetail {
|
|
31
|
+
message: string;
|
|
32
|
+
}
|
|
33
|
+
interface DocsWordEditorReadyDetail {
|
|
34
|
+
version: string;
|
|
35
|
+
}
|
|
36
|
+
interface DocsWordEditorElementApi extends HTMLElement {
|
|
37
|
+
loadDocx(file: File): Promise<void>;
|
|
38
|
+
loadHtml(rawHtml: string): void;
|
|
39
|
+
loadClipboard(): Promise<void>;
|
|
40
|
+
clear(): void;
|
|
41
|
+
getSnapshot(): string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { type DocsWordEditorChangeDetail as D, type DocsWordEditorElementApi as a, type DocsWordEditorErrorDetail as b, type DocsWordEditorReadyDetail as c, type DocxParseFeatureCounts as d, type DocxParseReport as e, parseDocxToHtmlSnapshotWithReport as f, parseDocxToHtmlSnapshot as p };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
interface DocxParseFeatureCounts {
|
|
2
|
+
hyperlinkCount: number;
|
|
3
|
+
anchorImageCount: number;
|
|
4
|
+
chartCount: number;
|
|
5
|
+
smartArtCount: number;
|
|
6
|
+
ommlCount: number;
|
|
7
|
+
tableCount: number;
|
|
8
|
+
footnoteRefCount: number;
|
|
9
|
+
endnoteRefCount: number;
|
|
10
|
+
commentRefCount: number;
|
|
11
|
+
revisionCount: number;
|
|
12
|
+
pageBreakCount: number;
|
|
13
|
+
}
|
|
14
|
+
interface DocxParseReport {
|
|
15
|
+
elapsedMs: number;
|
|
16
|
+
features: DocxParseFeatureCounts;
|
|
17
|
+
}
|
|
18
|
+
declare function parseDocxToHtmlSnapshotWithReport(file: File): Promise<{
|
|
19
|
+
htmlSnapshot: string;
|
|
20
|
+
report: DocxParseReport;
|
|
21
|
+
}>;
|
|
22
|
+
declare function parseDocxToHtmlSnapshot(file: File): Promise<string>;
|
|
23
|
+
|
|
24
|
+
interface DocsWordEditorChangeDetail {
|
|
25
|
+
htmlSnapshot: string;
|
|
26
|
+
source: "paste" | "upload" | "api" | "clear";
|
|
27
|
+
fileName?: string;
|
|
28
|
+
parseReport?: DocxParseReport;
|
|
29
|
+
}
|
|
30
|
+
interface DocsWordEditorErrorDetail {
|
|
31
|
+
message: string;
|
|
32
|
+
}
|
|
33
|
+
interface DocsWordEditorReadyDetail {
|
|
34
|
+
version: string;
|
|
35
|
+
}
|
|
36
|
+
interface DocsWordEditorElementApi extends HTMLElement {
|
|
37
|
+
loadDocx(file: File): Promise<void>;
|
|
38
|
+
loadHtml(rawHtml: string): void;
|
|
39
|
+
loadClipboard(): Promise<void>;
|
|
40
|
+
clear(): void;
|
|
41
|
+
getSnapshot(): string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { type DocsWordEditorChangeDetail as D, type DocsWordEditorElementApi as a, type DocsWordEditorErrorDetail as b, type DocsWordEditorReadyDetail as c, type DocxParseFeatureCounts as d, type DocxParseReport as e, parseDocxToHtmlSnapshotWithReport as f, parseDocxToHtmlSnapshot as p };
|
package/dist/vue.cjs
CHANGED
|
@@ -56,6 +56,21 @@ function buildHtmlSnapshot(rawHtml) {
|
|
|
56
56
|
|
|
57
57
|
// src/lib/docxHtml.ts
|
|
58
58
|
var import_jszip = __toESM(require("jszip"), 1);
|
|
59
|
+
function createEmptyFeatureCounts() {
|
|
60
|
+
return {
|
|
61
|
+
hyperlinkCount: 0,
|
|
62
|
+
anchorImageCount: 0,
|
|
63
|
+
chartCount: 0,
|
|
64
|
+
smartArtCount: 0,
|
|
65
|
+
ommlCount: 0,
|
|
66
|
+
tableCount: 0,
|
|
67
|
+
footnoteRefCount: 0,
|
|
68
|
+
endnoteRefCount: 0,
|
|
69
|
+
commentRefCount: 0,
|
|
70
|
+
revisionCount: 0,
|
|
71
|
+
pageBreakCount: 0
|
|
72
|
+
};
|
|
73
|
+
}
|
|
59
74
|
function escapeHtml(text) {
|
|
60
75
|
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
61
76
|
}
|
|
@@ -230,6 +245,19 @@ function normalizeWordPath(relTarget) {
|
|
|
230
245
|
if (normalized.startsWith("../")) return `word/${normalized.replace(/^(\.\.\/)+/, "")}`;
|
|
231
246
|
return `word/${normalized}`;
|
|
232
247
|
}
|
|
248
|
+
function resolveHyperlinkHref(relMap, rid, anchor) {
|
|
249
|
+
if (anchor && anchor.trim()) return `#${encodeURIComponent(anchor.trim())}`;
|
|
250
|
+
if (!rid) return null;
|
|
251
|
+
const relTarget = relMap[rid];
|
|
252
|
+
if (!relTarget) return null;
|
|
253
|
+
const trimmed = relTarget.trim();
|
|
254
|
+
if (!trimmed) return null;
|
|
255
|
+
const lower = trimmed.toLowerCase();
|
|
256
|
+
if (lower.startsWith("http://") || lower.startsWith("https://") || lower.startsWith("mailto:") || lower.startsWith("tel:")) {
|
|
257
|
+
return trimmed;
|
|
258
|
+
}
|
|
259
|
+
return trimmed.startsWith("#") ? trimmed : `#${encodeURIComponent(trimmed)}`;
|
|
260
|
+
}
|
|
233
261
|
async function imageRidToDataUrl(zip, relMap, rid) {
|
|
234
262
|
const relTarget = relMap[rid];
|
|
235
263
|
if (!relTarget) return null;
|
|
@@ -404,7 +432,7 @@ function renderEndnotesSection(usedIds, endnotesMap) {
|
|
|
404
432
|
const items = uniq.map((id) => `<li id="word-endnote-${id}" data-word-endnote-id="${id}">${endnotesMap[id]}</li>`).join("");
|
|
405
433
|
return `<section data-word-endnotes="1"><hr/><ol>${items}</ol></section>`;
|
|
406
434
|
}
|
|
407
|
-
async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotesMap, usedFootnoteIds, endnotesMap, usedEndnoteIds, commentsMap, usedCommentIds) {
|
|
435
|
+
async function paragraphToHtml(zip, relMap, context, paragraph, paragraphIndex, footnotesMap, usedFootnoteIds, endnotesMap, usedEndnoteIds, commentsMap, usedCommentIds) {
|
|
408
436
|
const tag = paragraphTag(paragraph);
|
|
409
437
|
const alignStyle = paragraphAlignStyle(paragraph);
|
|
410
438
|
const dataAttr = paragraphDataAttr(paragraphIndex);
|
|
@@ -445,6 +473,7 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
445
473
|
const footnoteRef = queryByLocalName(run, "footnoteReference");
|
|
446
474
|
const footnoteId = getAttr(footnoteRef, "w:id") ?? getAttr(footnoteRef, "id");
|
|
447
475
|
if (footnoteId && footnotesMap[footnoteId]) {
|
|
476
|
+
context.features.footnoteRefCount += 1;
|
|
448
477
|
usedFootnoteIds.push(footnoteId);
|
|
449
478
|
result.push(
|
|
450
479
|
`<sup data-word-footnote-ref="${footnoteId}"><a href="#word-footnote-${footnoteId}">[${footnoteId}]</a></sup>`
|
|
@@ -454,6 +483,7 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
454
483
|
const endnoteRef = queryByLocalName(run, "endnoteReference");
|
|
455
484
|
const endnoteId = getAttr(endnoteRef, "w:id") ?? getAttr(endnoteRef, "id");
|
|
456
485
|
if (endnoteId && endnotesMap[endnoteId]) {
|
|
486
|
+
context.features.endnoteRefCount += 1;
|
|
457
487
|
usedEndnoteIds.push(endnoteId);
|
|
458
488
|
result.push(
|
|
459
489
|
`<sup data-word-endnote-ref="${endnoteId}"><a href="#word-endnote-${endnoteId}">[${endnoteId}]</a></sup>`
|
|
@@ -463,6 +493,7 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
463
493
|
const commentRef = queryByLocalName(run, "commentReference");
|
|
464
494
|
const commentId = getAttr(commentRef, "w:id") ?? getAttr(commentRef, "id");
|
|
465
495
|
if (commentId && commentsMap[commentId]) {
|
|
496
|
+
context.features.commentRefCount += 1;
|
|
466
497
|
usedCommentIds.push(commentId);
|
|
467
498
|
result.push(
|
|
468
499
|
`<sup data-word-comment-ref="${commentId}"><a href="#word-comment-${commentId}">[c${commentId}]</a></sup>`
|
|
@@ -480,6 +511,7 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
480
511
|
const dimensionAttrs = imageDimensionAttributes(imageSize);
|
|
481
512
|
const anchorMeta = parseAnchorMeta(drawing);
|
|
482
513
|
const attrs = mergeImageStyle(dimensionAttrs, anchorMeta);
|
|
514
|
+
if (anchorMeta) context.features.anchorImageCount += 1;
|
|
483
515
|
result.push(`<img src="${src}" alt="word-image"${attrs}/>`);
|
|
484
516
|
return result;
|
|
485
517
|
}
|
|
@@ -490,6 +522,7 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
490
522
|
const chartXmlText = await readXmlByRid(zip, relMap, chartRid);
|
|
491
523
|
if (chartXmlText) {
|
|
492
524
|
const summary = parseChartSummary(chartXmlText);
|
|
525
|
+
context.features.chartCount += 1;
|
|
493
526
|
result.push(
|
|
494
527
|
`<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>`
|
|
495
528
|
);
|
|
@@ -501,6 +534,7 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
501
534
|
if (smartArtRid) {
|
|
502
535
|
const diagramXmlText = await readXmlByRid(zip, relMap, smartArtRid);
|
|
503
536
|
const textItems = diagramXmlText ? extractSmartArtText(diagramXmlText) : [];
|
|
537
|
+
context.features.smartArtCount += 1;
|
|
504
538
|
const preview = textItems.length > 0 ? `: ${escapeHtml(textItems.join(" / "))}` : "";
|
|
505
539
|
result.push(
|
|
506
540
|
`<figure data-word-smartart="1" data-word-smartart-items="${textItems.length}"><figcaption>SmartArt fallback${preview}</figcaption></figure>`
|
|
@@ -522,12 +556,14 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
522
556
|
if (css) {
|
|
523
557
|
const span = `<span style="${css}">${runText2}</span>`;
|
|
524
558
|
if (revisionMeta) {
|
|
559
|
+
context.features.revisionCount += 1;
|
|
525
560
|
const tagName = revisionMeta.type === "ins" ? "ins" : "del";
|
|
526
561
|
result.push(`<${tagName} ${revisionMetaAttrs(revisionMeta)}>${span}</${tagName}>`);
|
|
527
562
|
} else {
|
|
528
563
|
result.push(span);
|
|
529
564
|
}
|
|
530
565
|
} else if (revisionMeta) {
|
|
566
|
+
context.features.revisionCount += 1;
|
|
531
567
|
const tagName = revisionMeta.type === "ins" ? "ins" : "del";
|
|
532
568
|
result.push(`<${tagName} ${revisionMetaAttrs(revisionMeta)}>${runText2}</${tagName}>`);
|
|
533
569
|
} else {
|
|
@@ -535,6 +571,7 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
535
571
|
}
|
|
536
572
|
}
|
|
537
573
|
for (let i = 0; i < pageBreakCount; i += 1) {
|
|
574
|
+
context.features.pageBreakCount += 1;
|
|
538
575
|
result.push(`<span data-word-page-break="1" style="display:block;break-before:page"></span>`);
|
|
539
576
|
}
|
|
540
577
|
return result;
|
|
@@ -551,9 +588,25 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
551
588
|
if (node.localName === "r") {
|
|
552
589
|
return runToHtml(node, revisionFallback);
|
|
553
590
|
}
|
|
591
|
+
if (node.localName === "hyperlink") {
|
|
592
|
+
const rid = getAttr(node, "r:id") ?? getAttr(node, "id");
|
|
593
|
+
const anchor = getAttr(node, "w:anchor") ?? getAttr(node, "anchor");
|
|
594
|
+
const href = resolveHyperlinkHref(relMap, rid, anchor);
|
|
595
|
+
const nested2 = [];
|
|
596
|
+
for (const child of Array.from(node.children)) {
|
|
597
|
+
nested2.push(...await nodeToHtml(child, revisionFallback));
|
|
598
|
+
}
|
|
599
|
+
const content2 = nested2.join("") || escapeHtml(node.textContent ?? "");
|
|
600
|
+
if (!href) return content2 ? [content2] : [];
|
|
601
|
+
context.features.hyperlinkCount += 1;
|
|
602
|
+
return [
|
|
603
|
+
`<a data-word-hyperlink="1" href="${escapeHtml(href)}" rel="noreferrer noopener" target="_blank">${content2}</a>`
|
|
604
|
+
];
|
|
605
|
+
}
|
|
554
606
|
if (node.localName === "oMath" || node.localName === "oMathPara") {
|
|
555
607
|
const linear = ommlNodeToText(node).trim();
|
|
556
608
|
if (!linear) return [];
|
|
609
|
+
context.features.ommlCount += 1;
|
|
557
610
|
return [`<span data-word-omml="1">${escapeHtml(linear)}</span>`];
|
|
558
611
|
}
|
|
559
612
|
if (node.localName === "ins" || node.localName === "del") {
|
|
@@ -573,6 +626,7 @@ async function paragraphToHtml(zip, relMap, paragraph, paragraphIndex, footnotes
|
|
|
573
626
|
const parts = [];
|
|
574
627
|
const renderedPageBreakCount = queryAllByLocalName(paragraph, "lastRenderedPageBreak").length;
|
|
575
628
|
for (let i = 0; i < renderedPageBreakCount; i += 1) {
|
|
629
|
+
context.features.pageBreakCount += 1;
|
|
576
630
|
parts.push(`<span data-word-page-break="1" style="display:block;break-before:page"></span>`);
|
|
577
631
|
}
|
|
578
632
|
for (const child of Array.from(paragraph.children)) {
|
|
@@ -701,7 +755,7 @@ function parseCellBorderStyle(cell, tableStyle) {
|
|
|
701
755
|
const left = parseBorderCss(directChildrenByLocalName(tcBorders, "left")[0] ?? null) ?? tableStyle.insideVCss ?? tableStyle.borderCss;
|
|
702
756
|
return `border-top:${top};border-right:${right};border-bottom:${bottom};border-left:${left}`;
|
|
703
757
|
}
|
|
704
|
-
function tableCellHtml(cell, paragraphIndexMap) {
|
|
758
|
+
function tableCellHtml(cell, paragraphIndexMap, context) {
|
|
705
759
|
const blocks = [];
|
|
706
760
|
for (const child of Array.from(cell.children)) {
|
|
707
761
|
if (child.localName === "tcPr") continue;
|
|
@@ -711,7 +765,7 @@ function tableCellHtml(cell, paragraphIndexMap) {
|
|
|
711
765
|
continue;
|
|
712
766
|
}
|
|
713
767
|
if (child.localName === "tbl") {
|
|
714
|
-
blocks.push(tableToHtml(child, paragraphIndexMap));
|
|
768
|
+
blocks.push(tableToHtml(child, paragraphIndexMap, context));
|
|
715
769
|
continue;
|
|
716
770
|
}
|
|
717
771
|
}
|
|
@@ -719,7 +773,8 @@ function tableCellHtml(cell, paragraphIndexMap) {
|
|
|
719
773
|
const text = queryAllByLocalName(cell, "t").map((t) => t.textContent ?? "").join("").trim();
|
|
720
774
|
return escapeHtml(text) || "<br/>";
|
|
721
775
|
}
|
|
722
|
-
function tableToHtml(table, paragraphIndexMap) {
|
|
776
|
+
function tableToHtml(table, paragraphIndexMap, context) {
|
|
777
|
+
context.features.tableCount += 1;
|
|
723
778
|
const rows = directChildrenByLocalName(table, "tr");
|
|
724
779
|
const gridWidthsPx = parseTblGridWidthsPx(table);
|
|
725
780
|
const tableStyle = parseTableStyleProfile(table);
|
|
@@ -747,7 +802,7 @@ function tableToHtml(table, paragraphIndexMap) {
|
|
|
747
802
|
while (activeByCol.has(colCursor)) {
|
|
748
803
|
colCursor += 1;
|
|
749
804
|
}
|
|
750
|
-
const html = tableCellHtml(cell, paragraphIndexMap);
|
|
805
|
+
const html = tableCellHtml(cell, paragraphIndexMap, context);
|
|
751
806
|
const attrs = [];
|
|
752
807
|
const widthStyle = parseCellWidthStyle(cell, colCursor, colSpan, gridWidthsPx);
|
|
753
808
|
const borderStyle = parseCellBorderStyle(cell, tableStyle);
|
|
@@ -791,7 +846,9 @@ function tableToHtml(table, paragraphIndexMap) {
|
|
|
791
846
|
const spacing = tableStyle.borderSpacingPx > 0 ? `border-spacing:${tableStyle.borderSpacingPx.toFixed(2)}px;` : "";
|
|
792
847
|
return `<table style="border-collapse:${tableStyle.borderCollapse};${spacing}table-layout:${tableStyle.tableLayout};${tableWidthStyle};border:${tableStyle.borderCss};">${merged}</table>`;
|
|
793
848
|
}
|
|
794
|
-
async function
|
|
849
|
+
async function parseDocxToHtmlSnapshotWithReport(file) {
|
|
850
|
+
const startedAt = Date.now();
|
|
851
|
+
const context = { features: createEmptyFeatureCounts() };
|
|
795
852
|
const maybeArrayBuffer = file.arrayBuffer;
|
|
796
853
|
const buffer = maybeArrayBuffer ? await maybeArrayBuffer.call(file) : await new Response(file).arrayBuffer();
|
|
797
854
|
const zip = await import_jszip.default.loadAsync(buffer);
|
|
@@ -828,6 +885,7 @@ async function parseDocxToHtmlSnapshot(file) {
|
|
|
828
885
|
await paragraphToHtml(
|
|
829
886
|
zip,
|
|
830
887
|
relMap,
|
|
888
|
+
context,
|
|
831
889
|
child,
|
|
832
890
|
paragraphIndex,
|
|
833
891
|
footnotesMap,
|
|
@@ -841,14 +899,20 @@ async function parseDocxToHtmlSnapshot(file) {
|
|
|
841
899
|
continue;
|
|
842
900
|
}
|
|
843
901
|
if (child.localName === "tbl") {
|
|
844
|
-
blockHtml.push(tableToHtml(child, paragraphIndexMap));
|
|
902
|
+
blockHtml.push(tableToHtml(child, paragraphIndexMap, context));
|
|
845
903
|
continue;
|
|
846
904
|
}
|
|
847
905
|
}
|
|
848
906
|
blockHtml.push(renderFootnotesSection(usedFootnoteIds, footnotesMap));
|
|
849
907
|
blockHtml.push(renderEndnotesSection(usedEndnoteIds, endnotesMap));
|
|
850
908
|
blockHtml.push(renderCommentsSection(usedCommentIds, commentsMap));
|
|
851
|
-
return
|
|
909
|
+
return {
|
|
910
|
+
htmlSnapshot: buildHtmlSnapshot(blockHtml.join("\n")),
|
|
911
|
+
report: {
|
|
912
|
+
elapsedMs: Date.now() - startedAt,
|
|
913
|
+
features: context.features
|
|
914
|
+
}
|
|
915
|
+
};
|
|
852
916
|
}
|
|
853
917
|
|
|
854
918
|
// src/lib/pastePipeline.ts
|
|
@@ -1979,7 +2043,7 @@ function applyWordRenderModel({ doc, styleProfile, showFormattingMarks }) {
|
|
|
1979
2043
|
}
|
|
1980
2044
|
|
|
1981
2045
|
// src/core/DocsWordElement.ts
|
|
1982
|
-
var VERSION = "0.1.
|
|
2046
|
+
var VERSION = "0.1.5";
|
|
1983
2047
|
var MESSAGES = {
|
|
1984
2048
|
zh: {
|
|
1985
2049
|
readClipboard: "\u4ECE\u7CFB\u7EDF\u526A\u8D34\u677F\u8BFB\u53D6",
|
|
@@ -2122,15 +2186,15 @@ var DocsWordElement = class extends HTMLElement {
|
|
|
2122
2186
|
}
|
|
2123
2187
|
async applyDocx(file) {
|
|
2124
2188
|
try {
|
|
2125
|
-
const [
|
|
2126
|
-
|
|
2189
|
+
const [parseResult, profile] = await Promise.all([
|
|
2190
|
+
parseDocxToHtmlSnapshotWithReport(file),
|
|
2127
2191
|
parseDocxStyleProfile(file)
|
|
2128
2192
|
]);
|
|
2129
2193
|
this.styleProfile = profile;
|
|
2130
|
-
this.htmlSnapshot =
|
|
2194
|
+
this.htmlSnapshot = parseResult.htmlSnapshot;
|
|
2131
2195
|
this.renderSnapshot();
|
|
2132
2196
|
this.setHint(MESSAGES[this.locale].loadedWord(profile.sourceFileName));
|
|
2133
|
-
this.emitChange("upload", profile.sourceFileName);
|
|
2197
|
+
this.emitChange("upload", profile.sourceFileName, parseResult.report);
|
|
2134
2198
|
} catch (error) {
|
|
2135
2199
|
this.emitError(error instanceof Error ? error.message : MESSAGES[this.locale].parseFailed);
|
|
2136
2200
|
}
|
|
@@ -2190,8 +2254,10 @@ var DocsWordElement = class extends HTMLElement {
|
|
|
2190
2254
|
renderSnapshot() {
|
|
2191
2255
|
this.frame.srcdoc = this.htmlSnapshot;
|
|
2192
2256
|
}
|
|
2193
|
-
emitChange(source, fileName) {
|
|
2194
|
-
this.dispatchEvent(
|
|
2257
|
+
emitChange(source, fileName, parseReport) {
|
|
2258
|
+
this.dispatchEvent(
|
|
2259
|
+
new CustomEvent("docsjs-change", { detail: { htmlSnapshot: this.htmlSnapshot, source, fileName, parseReport } })
|
|
2260
|
+
);
|
|
2195
2261
|
}
|
|
2196
2262
|
emitError(message) {
|
|
2197
2263
|
this.dispatchEvent(new CustomEvent("docsjs-error", { detail: { message } }));
|