@file-viewer/renderer-word 2.1.25 → 2.1.27

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.
@@ -0,0 +1,4 @@
1
+ type DOMParserConstructor = new () => DOMParser;
2
+ export declare const collectDocxChartSeriesNames: (buffer: ArrayBuffer, DOMParserCtor: DOMParserConstructor) => Promise<string[][]>;
3
+ export declare const applyDocxChartSeriesNames: (buffer: ArrayBuffer, target: HTMLDivElement) => Promise<void>;
4
+ export {};
@@ -0,0 +1,149 @@
1
+ import JSZip from 'jszip';
2
+ const localName = (node) => {
3
+ const name = node.localName || node.nodeName;
4
+ return name.split(':').pop() || name;
5
+ };
6
+ const elementsByLocal = (node, name) => {
7
+ const result = [];
8
+ const visit = (current) => {
9
+ childElements(current).forEach((child) => {
10
+ if (localName(child) === name) {
11
+ result.push(child);
12
+ }
13
+ visit(child);
14
+ });
15
+ };
16
+ if (node) {
17
+ visit(node);
18
+ }
19
+ return result;
20
+ };
21
+ const childElements = (node) => {
22
+ return node
23
+ ? Array.from(node.childNodes).filter((child) => child.nodeType === 1)
24
+ : [];
25
+ };
26
+ const firstChildByLocal = (node, name) => {
27
+ return childElements(node).find((child) => localName(child) === name);
28
+ };
29
+ const relationshipId = (element) => {
30
+ return (element.getAttribute('r:id') ||
31
+ element.getAttributeNS('http://schemas.openxmlformats.org/officeDocument/2006/relationships', 'id') ||
32
+ '');
33
+ };
34
+ const resolvePartPath = (sourcePart, target) => {
35
+ const sourceDirectory = sourcePart.slice(0, Math.max(0, sourcePart.lastIndexOf('/')));
36
+ const parts = (target.startsWith('/') ? target.slice(1) : `${sourceDirectory}/${target}`).split('/');
37
+ const normalized = [];
38
+ for (const part of parts) {
39
+ if (!part || part === '.') {
40
+ continue;
41
+ }
42
+ if (part === '..') {
43
+ normalized.pop();
44
+ }
45
+ else {
46
+ normalized.push(part);
47
+ }
48
+ }
49
+ return normalized.join('/');
50
+ };
51
+ const readXml = async (zip, path, DOMParserCtor) => {
52
+ const file = zip.file(path);
53
+ if (!file) {
54
+ return null;
55
+ }
56
+ return new DOMParserCtor().parseFromString(await file.async('text'), 'application/xml');
57
+ };
58
+ const extractSeriesName = (series) => {
59
+ var _a, _b;
60
+ const tx = firstChildByLocal(series, 'tx');
61
+ if (!tx) {
62
+ return '';
63
+ }
64
+ const points = elementsByLocal(tx, 'pt')
65
+ .map((point) => {
66
+ var _a, _b;
67
+ return ({
68
+ index: Number(point.getAttribute('idx')) || 0,
69
+ value: ((_b = (_a = firstChildByLocal(point, 'v')) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || ''
70
+ });
71
+ })
72
+ .sort((left, right) => left.index - right.index)
73
+ .map((point) => point.value)
74
+ .filter(Boolean);
75
+ if (points.length) {
76
+ return points.join(' ');
77
+ }
78
+ const richText = elementsByLocal(tx, 't')
79
+ .map((text) => { var _a; return ((_a = text.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || ''; })
80
+ .filter(Boolean)
81
+ .join(' ');
82
+ if (richText) {
83
+ return richText;
84
+ }
85
+ return ((_b = (_a = elementsByLocal(tx, 'v')[0]) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || '';
86
+ };
87
+ export const collectDocxChartSeriesNames = async (buffer, DOMParserCtor) => {
88
+ const zip = await JSZip.loadAsync(buffer);
89
+ const documentPart = 'word/document.xml';
90
+ const [documentXml, relationshipsXml] = await Promise.all([
91
+ readXml(zip, documentPart, DOMParserCtor),
92
+ readXml(zip, 'word/_rels/document.xml.rels', DOMParserCtor)
93
+ ]);
94
+ if (!documentXml || !relationshipsXml) {
95
+ return [];
96
+ }
97
+ const relationships = new Map(elementsByLocal(relationshipsXml.documentElement, 'Relationship').map((relationship) => [
98
+ relationship.getAttribute('Id') || '',
99
+ {
100
+ target: relationship.getAttribute('Target') || '',
101
+ type: relationship.getAttribute('Type') || ''
102
+ }
103
+ ]));
104
+ const chartParts = elementsByLocal(documentXml.documentElement, 'chart').flatMap((chart) => {
105
+ const relationship = relationships.get(relationshipId(chart));
106
+ if (!(relationship === null || relationship === void 0 ? void 0 : relationship.target) || !relationship.type.endsWith('/chart')) {
107
+ return [];
108
+ }
109
+ return [resolvePartPath(documentPart, relationship.target)];
110
+ });
111
+ return Promise.all(chartParts.map(async (chartPart) => {
112
+ const chartXml = await readXml(zip, chartPart, DOMParserCtor);
113
+ return chartXml ? elementsByLocal(chartXml.documentElement, 'ser').map(extractSeriesName) : [];
114
+ }));
115
+ };
116
+ export const applyDocxChartSeriesNames = async (buffer, target) => {
117
+ var _a;
118
+ const charts = Array.from(target.querySelectorAll('.docx-chart'));
119
+ const hasFallbackLegend = charts.some((chart) => /Series\s+\d+/.test(chart.textContent || ''));
120
+ if (!hasFallbackLegend) {
121
+ return;
122
+ }
123
+ const DOMParserCtor = ((_a = target.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.DOMParser) || globalThis.DOMParser;
124
+ if (!DOMParserCtor) {
125
+ return;
126
+ }
127
+ try {
128
+ const namesByChart = await collectDocxChartSeriesNames(buffer, DOMParserCtor);
129
+ charts.forEach((chart, chartIndex) => {
130
+ var _a;
131
+ const names = ((_a = namesByChart[chartIndex]) === null || _a === void 0 ? void 0 : _a.filter(Boolean)) || [];
132
+ if (!names.length) {
133
+ return;
134
+ }
135
+ chart.dataset.chartSeriesNames = JSON.stringify(names);
136
+ const textElements = Array.from(chart.querySelectorAll('text'));
137
+ names.forEach((name, seriesIndex) => {
138
+ const fallback = `Series ${seriesIndex + 1}`;
139
+ const legend = textElements.find((text) => { var _a; return ((_a = text.textContent) === null || _a === void 0 ? void 0 : _a.trim()) === fallback; });
140
+ if (legend) {
141
+ legend.textContent = name;
142
+ }
143
+ });
144
+ });
145
+ }
146
+ catch (error) {
147
+ console.warn('[file-viewer] DOCX 图表系列名修复失败,保留基础图表结果。', error);
148
+ }
149
+ };
@@ -84,8 +84,8 @@ const resolveRtfJs = async () => {
84
84
  const rtfModule = await import('rtf.js/dist/RTFJS.bundle.js');
85
85
  return rtfModule.RTFJS || rtfModule.default || rtfModule;
86
86
  };
87
- const renderRtf = async (buffer, target, t) => {
88
- var _a, _b;
87
+ const renderRtf = async (buffer, target, t, context) => {
88
+ var _a, _b, _c;
89
89
  const RTFJS = await resolveRtfJs();
90
90
  (_a = RTFJS.loggingEnabled) === null || _a === void 0 ? void 0 : _a.call(RTFJS, false);
91
91
  const doc = new RTFJS.Document(buffer, {});
@@ -102,27 +102,36 @@ const renderRtf = async (buffer, target, t) => {
102
102
  elements.forEach((element) => paper.appendChild(element));
103
103
  stage.append(header, paper);
104
104
  target.replaceChildren(createStyle(), stage);
105
+ (_c = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _c === void 0 ? void 0 : _c.call(context, { getTarget: () => paper });
105
106
  return {
106
107
  $el: target,
107
108
  unmount() {
109
+ var _a;
110
+ (_a = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _a === void 0 ? void 0 : _a.call(context, null);
108
111
  target.replaceChildren();
109
112
  },
110
113
  };
111
114
  };
112
115
  export default async function renderOpenDocument(buffer, target, type, context) {
116
+ var _a;
113
117
  const t = createFileViewerTranslator(context === null || context === void 0 ? void 0 : context.options);
114
118
  const normalizedType = (type || 'odt').toLowerCase();
115
119
  if (normalizedType === 'rtf') {
116
- return renderRtf(buffer, target, t);
120
+ return renderRtf(buffer, target, t, context);
117
121
  }
118
122
  const pages = await parseOdf(buffer, normalizedType, t);
119
123
  const title = normalizedType === 'odp'
120
124
  ? t('word.title.openDocumentPresentation')
121
125
  : t('word.title.openDocumentText');
122
126
  target.replaceChildren(createStyle(), renderOdfPages(normalizedType, title, pages));
127
+ (_a = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _a === void 0 ? void 0 : _a.call(context, {
128
+ getTarget: () => target.querySelector('.odf-page') || target
129
+ });
123
130
  return {
124
131
  $el: target,
125
132
  unmount() {
133
+ var _a;
134
+ (_a = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _a === void 0 ? void 0 : _a.call(context, null);
126
135
  target.replaceChildren();
127
136
  },
128
137
  };
package/dist/wordDoc.js CHANGED
@@ -343,7 +343,7 @@ function makeMsDocResponsive(target) {
343
343
  * 渲染 doc 文件
344
344
  */
345
345
  export default async function render(buffer, target, context) {
346
- var _a;
346
+ var _a, _b;
347
347
  const rendered = await parseMsDocToHtml(buffer, {
348
348
  renderOptions: {
349
349
  css: `${defaultMsDocCss()}\n${WORD_PAGE_CSS}`
@@ -356,11 +356,15 @@ export default async function render(buffer, target, context) {
356
356
  printStyle: buildMsDocPrintStyle,
357
357
  toHtml: () => prepareMsDocCloneForExport(target)
358
358
  });
359
+ (_b = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _b === void 0 ? void 0 : _b.call(context, {
360
+ getTarget: () => target.querySelector('.msdoc-page') || target
361
+ });
359
362
  return {
360
363
  $el: target,
361
364
  unmount() {
362
- var _a;
365
+ var _a, _b;
363
366
  (_a = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _a === void 0 ? void 0 : _a.call(context, null);
367
+ (_b = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _b === void 0 ? void 0 : _b.call(context, null);
364
368
  disposeResponsive();
365
369
  target.innerHTML = '';
366
370
  }
package/dist/wordDocx.js CHANGED
@@ -8,7 +8,7 @@ const DOCX_WORKER_UNSAFE_PROTOCOLS = new Set(['file:', 'about:', 'data:']);
8
8
  const DOCX_MIN_SCALE = 0.24;
9
9
  const DOCX_MAX_SCALE = 3;
10
10
  const DOCX_ZOOM_STEP = 0.15;
11
- const DOCX_VENDOR_ASSET_VERSION = '0.3.18';
11
+ const DOCX_VENDOR_ASSET_VERSION = '0.3.19';
12
12
  const ZIP_SIGNATURE_PK = 0x504b;
13
13
  const loadLibrary = (() => {
14
14
  const loader = {
@@ -495,7 +495,7 @@ function prepareDocxCloneForExport(target) {
495
495
  * 渲染docx文件
496
496
  */
497
497
  export default async function (buffer, target, context) {
498
- var _a;
498
+ var _a, _b;
499
499
  assertValidDocxPackage(buffer, context);
500
500
  target.innerHTML = '';
501
501
  let hasNotifiedProgressiveRender = false;
@@ -528,11 +528,15 @@ export default async function (buffer, target, context) {
528
528
  printStyle: () => buildDocxPrintStyle(target),
529
529
  toHtml: () => prepareDocxCloneForExport(target)
530
530
  });
531
+ (_b = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _b === void 0 ? void 0 : _b.call(context, {
532
+ getTarget: () => target.querySelector('.docx-page-frame, .docx-flow-frame') || target
533
+ });
531
534
  return {
532
535
  $el: target,
533
536
  unmount() {
534
- var _a;
537
+ var _a, _b;
535
538
  (_a = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _a === void 0 ? void 0 : _a.call(context, null);
539
+ (_b = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _b === void 0 ? void 0 : _b.call(context, null);
536
540
  disposeResponsive();
537
541
  delete target.dataset.docxWorker;
538
542
  delete target.dataset.docxDarkMode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/renderer-word",
3
- "version": "2.1.25",
3
+ "version": "2.1.27",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone Word and compatible document renderer plugin for Flyfish File Viewer powered by @file-viewer/docx, @file-viewer/doc, and RTF/ODF parsing.",
@@ -57,9 +57,9 @@
57
57
  "LICENSE"
58
58
  ],
59
59
  "dependencies": {
60
- "@file-viewer/core": "2.1.25",
61
- "@file-viewer/doc": "2.1.25",
62
- "@file-viewer/docx": "^0.3.18",
60
+ "@file-viewer/core": "2.1.27",
61
+ "@file-viewer/doc": "2.1.27",
62
+ "@file-viewer/docx": "^0.3.19",
63
63
  "jszip": "^3.10.1",
64
64
  "rtf.js": "^3.0.9"
65
65
  },