@file-viewer/renderer-word 2.3.0 → 2.3.2

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/dist/wordDoc.js CHANGED
@@ -1,4 +1,4 @@
1
- import { defaultMsDocCss, parseMsDocToHtml } from '@file-viewer/doc';
1
+ import { defaultMsDocCss, parseMsDocToHtml, sanitizeMsDocHtml } from '@file-viewer/doc';
2
2
  import { applyPrintPageSize, buildPrintPageStyle, createFileViewerZoomChangeEmitter as createZoomChangeEmitter, formatCssPixels, registerFileViewerZoomProvider, resolveFileViewerFitScale, unregisterFileViewerZoomProvider, } from '@file-viewer/core';
3
3
  const PAGE_BREAK_MARKER = '<span class="msdoc-page-break"></span>';
4
4
  const EMPTY_PAGE_HTML = '<p class="msdoc-paragraph"><br></p>';
@@ -368,21 +368,31 @@ function makeMsDocResponsive(target) {
368
368
  * 渲染 doc 文件
369
369
  */
370
370
  export default async function render(buffer, target, context) {
371
- var _a, _b;
371
+ var _a, _b, _c, _d, _e;
372
372
  const rendered = await parseMsDocToHtml(buffer, {
373
373
  renderOptions: {
374
- css: `${defaultMsDocCss()}\n${WORD_PAGE_CSS}`
374
+ css: `${defaultMsDocCss()}\n${WORD_PAGE_CSS}`,
375
+ externalLinkPolicy: (_c = (_b = (_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a.docx) === null || _b === void 0 ? void 0 : _b.externalLinkPolicy) !== null && _c !== void 0 ? _c : 'block'
375
376
  }
376
377
  });
377
- target.innerHTML = `<style data-msdoc>${rendered.css}</style>${wrapAsWordPages(rendered.html)}`;
378
+ const targetWindow = target.ownerDocument.defaultView;
379
+ if (!targetWindow) {
380
+ throw new Error('The DOC target must belong to a browser document');
381
+ }
382
+ const style = target.ownerDocument.createElement('style');
383
+ style.dataset.msdoc = '';
384
+ style.textContent = rendered.css;
385
+ const content = target.ownerDocument.createElement('div');
386
+ content.append(sanitizeMsDocHtml(wrapAsWordPages(rendered.html), targetWindow));
387
+ target.replaceChildren(style, ...Array.from(content.childNodes));
378
388
  const disposeResponsive = makeMsDocResponsive(target);
379
- (_a = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _a === void 0 ? void 0 : _a.call(context, {
389
+ (_d = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _d === void 0 ? void 0 : _d.call(context, {
380
390
  includeDocumentStyles: false,
381
391
  getPrintMaskPages: () => Array.from(target.querySelectorAll('.msdoc-page')),
382
392
  printStyle: buildMsDocPrintStyle,
383
393
  toHtml: () => prepareMsDocCloneForExport(target)
384
394
  });
385
- (_b = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _b === void 0 ? void 0 : _b.call(context, {
395
+ (_e = context === null || context === void 0 ? void 0 : context.registerThumbnailAdapter) === null || _e === void 0 ? void 0 : _e.call(context, {
386
396
  getTarget: () => target.querySelector('.msdoc-page') || target
387
397
  });
388
398
  return {
package/dist/wordDocx.js CHANGED
@@ -9,7 +9,7 @@ const DOCX_WORKER_UNSAFE_PROTOCOLS = new Set(['file:', 'about:', 'data:']);
9
9
  const DOCX_MIN_SCALE = 0.24;
10
10
  const DOCX_MAX_SCALE = 3;
11
11
  const DOCX_ZOOM_STEP = 0.15;
12
- const DOCX_VENDOR_ASSET_VERSION = '0.3.26';
12
+ const DOCX_VENDOR_ASSET_VERSION = '0.3.27';
13
13
  const ZIP_SIGNATURE_PK = 0x504b;
14
14
  const WORDPROCESSINGML_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
15
15
  const OFFICE_RELATIONSHIP_NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
@@ -258,6 +258,9 @@ const appendDocxVendorAssetVersion = (url, explicitUrl) => {
258
258
  if (!url || explicitUrl) {
259
259
  return url;
260
260
  }
261
+ if (/[?&]file-viewer-docx=[^&#]*/.test(url)) {
262
+ return url.replace(/([?&])file-viewer-docx=[^&#]*/, `$1file-viewer-docx=${DOCX_VENDOR_ASSET_VERSION}`);
263
+ }
261
264
  return `${url}${url.includes('?') ? '&' : '?'}file-viewer-docx=${DOCX_VENDOR_ASSET_VERSION}`;
262
265
  };
263
266
  export const applyDocxExternalLinkPolicy = (target, policy) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/renderer-word",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Standalone Word and compatible document renderer plugin for File Viewer powered by @file-viewer/docx, @file-viewer/doc, and RTF/ODF parsing.",
@@ -58,7 +58,7 @@
58
58
  ],
59
59
  "dependencies": {
60
60
  "@file-viewer/core": "2.3.0",
61
- "@file-viewer/doc": "2.3.0",
61
+ "@file-viewer/doc": "2.3.1",
62
62
  "@file-viewer/docx": "^0.3.27",
63
63
  "jszip": "^3.10.1",
64
64
  "rtf.js": "^3.0.9"
@@ -1,4 +0,0 @@
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 {};
package/dist/docxChart.js DELETED
@@ -1,149 +0,0 @@
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
- };