@file-viewer/renderer-word 2.2.4 → 2.2.5
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/wordDocx.d.ts +7 -0
- package/dist/wordDocx.js +137 -1
- package/package.json +3 -3
package/dist/wordDocx.d.ts
CHANGED
|
@@ -9,6 +9,13 @@ export declare const isMissingDocxHeaderFooterRootError: (error: unknown) => boo
|
|
|
9
9
|
* rolls through lockfiles and private registries.
|
|
10
10
|
*/
|
|
11
11
|
export declare const renderDocxWithHeaderFooterFallback: (render: DocxRenderAsync, buffer: ArrayBuffer, target: HTMLDivElement, options: Options) => Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* WPS and Word can store a page background as a document-level VML fill. The
|
|
14
|
+
* DOCX engine intentionally ignores that legacy drawing node, so resolve only
|
|
15
|
+
* its package-local image relationship here and leave all body layout to it.
|
|
16
|
+
*/
|
|
17
|
+
export declare const resolveDocxPageBackgroundImage: (buffer: ArrayBuffer, createXmlParser?: () => Pick<DOMParser, "parseFromString">) => Promise<string | undefined>;
|
|
18
|
+
export declare const applyDocxPageBackgroundImage: (target: HTMLDivElement, imageUrl: string | undefined) => number;
|
|
12
19
|
/**
|
|
13
20
|
* 渲染docx文件
|
|
14
21
|
*/
|
package/dist/wordDocx.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import JSZip from 'jszip';
|
|
1
2
|
import { resolveFileViewerDocxWorkerJsZipUrl, resolveFileViewerDocxWorkerUrl, resolveFileViewerRuntimeAssetBaseUrl, } from '@file-viewer/core/assets';
|
|
2
3
|
import { applyPrintPageSize, buildPrintPageStyle, createFileViewerTranslator, createFileViewerZoomChangeEmitter as createZoomChangeEmitter, formatCssPixels, getElementPrintPageSize, normalizeFileViewerTheme, registerFileViewerZoomProvider, resolveFileViewerFitScale, unregisterFileViewerZoomProvider, } from '@file-viewer/core';
|
|
3
4
|
const DOCX_DEFAULT_PAGE_SIZE = {
|
|
@@ -10,6 +11,24 @@ const DOCX_MAX_SCALE = 3;
|
|
|
10
11
|
const DOCX_ZOOM_STEP = 0.15;
|
|
11
12
|
const DOCX_VENDOR_ASSET_VERSION = '0.3.26';
|
|
12
13
|
const ZIP_SIGNATURE_PK = 0x504b;
|
|
14
|
+
const WORDPROCESSINGML_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
15
|
+
const OFFICE_RELATIONSHIP_NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
|
|
16
|
+
const PACKAGE_RELATIONSHIP_NAMESPACE = 'http://schemas.openxmlformats.org/package/2006/relationships';
|
|
17
|
+
const VML_NAMESPACE = 'urn:schemas-microsoft-com:vml';
|
|
18
|
+
const DOCX_DOCUMENT_PART = 'word/document.xml';
|
|
19
|
+
const DOCX_DOCUMENT_RELATIONSHIPS_PART = 'word/_rels/document.xml.rels';
|
|
20
|
+
const DOCX_PAGE_BACKGROUND_CLASS = 'docx-page-background';
|
|
21
|
+
const DOCX_BACKGROUND_MIME_TYPES = {
|
|
22
|
+
bmp: 'image/bmp',
|
|
23
|
+
gif: 'image/gif',
|
|
24
|
+
jpeg: 'image/jpeg',
|
|
25
|
+
jpg: 'image/jpeg',
|
|
26
|
+
png: 'image/png',
|
|
27
|
+
svg: 'image/svg+xml',
|
|
28
|
+
tif: 'image/tiff',
|
|
29
|
+
tiff: 'image/tiff',
|
|
30
|
+
webp: 'image/webp'
|
|
31
|
+
};
|
|
13
32
|
// Modern bundlers expose the ESM named exports, while some legacy webpack
|
|
14
33
|
// configurations wrap the CommonJS browser API in `default`.
|
|
15
34
|
const resolveDocxLibrary = (module) => {
|
|
@@ -79,6 +98,11 @@ const assertValidDocxPackage = (buffer, context) => {
|
|
|
79
98
|
const getTargetWindow = (target) => {
|
|
80
99
|
return target.ownerDocument.defaultView;
|
|
81
100
|
};
|
|
101
|
+
const createTargetXmlParser = (target) => {
|
|
102
|
+
var _a, _b;
|
|
103
|
+
const DOMParserCtor = (_b = (_a = getTargetWindow(target)) === null || _a === void 0 ? void 0 : _a.DOMParser) !== null && _b !== void 0 ? _b : globalThis.DOMParser;
|
|
104
|
+
return new DOMParserCtor();
|
|
105
|
+
};
|
|
82
106
|
const getTargetProtocol = (target) => {
|
|
83
107
|
var _a, _b, _c;
|
|
84
108
|
const candidates = [
|
|
@@ -96,6 +120,103 @@ const getTargetProtocol = (target) => {
|
|
|
96
120
|
}
|
|
97
121
|
return '';
|
|
98
122
|
};
|
|
123
|
+
const getElementsByLocalName = (root, namespace, localName) => {
|
|
124
|
+
const namespaced = Array.from(root.getElementsByTagNameNS(namespace, localName));
|
|
125
|
+
if (namespaced.length) {
|
|
126
|
+
return namespaced;
|
|
127
|
+
}
|
|
128
|
+
return Array.from(root.getElementsByTagName('*')).filter(element => element.localName === localName);
|
|
129
|
+
};
|
|
130
|
+
const parseDocxXml = (source, parser) => {
|
|
131
|
+
const xml = parser.parseFromString(source, 'application/xml');
|
|
132
|
+
return getElementsByLocalName(xml, 'http://www.mozilla.org/newlayout/xml/parsererror.xml', 'parsererror').length
|
|
133
|
+
? null
|
|
134
|
+
: xml;
|
|
135
|
+
};
|
|
136
|
+
const resolvePackagePartPath = (basePart, relationshipTarget) => {
|
|
137
|
+
const segments = relationshipTarget.startsWith('/') ? [] : basePart.split('/').slice(0, -1);
|
|
138
|
+
relationshipTarget
|
|
139
|
+
.replace(/^\/+/, '')
|
|
140
|
+
.split('/')
|
|
141
|
+
.forEach(segment => {
|
|
142
|
+
if (!segment || segment === '.') {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (segment === '..') {
|
|
146
|
+
segments.pop();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
segments.push(segment);
|
|
150
|
+
});
|
|
151
|
+
return segments.join('/');
|
|
152
|
+
};
|
|
153
|
+
const resolveDocxImageMimeType = (partName) => {
|
|
154
|
+
var _a;
|
|
155
|
+
const extension = ((_a = partName.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
|
|
156
|
+
return DOCX_BACKGROUND_MIME_TYPES[extension];
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* WPS and Word can store a page background as a document-level VML fill. The
|
|
160
|
+
* DOCX engine intentionally ignores that legacy drawing node, so resolve only
|
|
161
|
+
* its package-local image relationship here and leave all body layout to it.
|
|
162
|
+
*/
|
|
163
|
+
export const resolveDocxPageBackgroundImage = async (buffer, createXmlParser = () => new DOMParser()) => {
|
|
164
|
+
try {
|
|
165
|
+
const archive = await JSZip.loadAsync(buffer);
|
|
166
|
+
const documentEntry = archive.file(DOCX_DOCUMENT_PART);
|
|
167
|
+
const relationshipsEntry = archive.file(DOCX_DOCUMENT_RELATIONSHIPS_PART);
|
|
168
|
+
if (!documentEntry || !relationshipsEntry) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
const parser = createXmlParser();
|
|
172
|
+
const documentXml = parseDocxXml(await documentEntry.async('string'), parser);
|
|
173
|
+
const relationshipsXml = parseDocxXml(await relationshipsEntry.async('string'), parser);
|
|
174
|
+
if (!documentXml || !relationshipsXml) {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
const background = getElementsByLocalName(documentXml, WORDPROCESSINGML_NAMESPACE, 'background')[0];
|
|
178
|
+
const fill = background && getElementsByLocalName(background, VML_NAMESPACE, 'fill')[0];
|
|
179
|
+
const relationshipId = (fill === null || fill === void 0 ? void 0 : fill.getAttributeNS(OFFICE_RELATIONSHIP_NAMESPACE, 'id')) || (fill === null || fill === void 0 ? void 0 : fill.getAttribute('r:id'));
|
|
180
|
+
if (!relationshipId) {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
const relationship = getElementsByLocalName(relationshipsXml, PACKAGE_RELATIONSHIP_NAMESPACE, 'Relationship').find(candidate => candidate.getAttribute('Id') === relationshipId);
|
|
184
|
+
const target = relationship === null || relationship === void 0 ? void 0 : relationship.getAttribute('Target');
|
|
185
|
+
if (!target || (relationship === null || relationship === void 0 ? void 0 : relationship.getAttribute('TargetMode')) === 'External') {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
const partName = resolvePackagePartPath(DOCX_DOCUMENT_PART, target);
|
|
189
|
+
const mimeType = resolveDocxImageMimeType(partName);
|
|
190
|
+
const imageEntry = archive.file(partName) || archive.file(decodeURIComponent(partName));
|
|
191
|
+
if (!mimeType || !imageEntry) {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
return `data:${mimeType};base64,${await imageEntry.async('base64')}`;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// A page background is optional and must never make an otherwise readable
|
|
198
|
+
// document fail. The DOCX engine remains responsible for package errors.
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
export const applyDocxPageBackgroundImage = (target, imageUrl) => {
|
|
203
|
+
if (!imageUrl) {
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
let applied = 0;
|
|
207
|
+
target.querySelectorAll('section.docx').forEach(page => {
|
|
208
|
+
const existing = Array.from(page.children).find(child => child.classList.contains(DOCX_PAGE_BACKGROUND_CLASS));
|
|
209
|
+
const background = existing || target.ownerDocument.createElement('div');
|
|
210
|
+
background.className = DOCX_PAGE_BACKGROUND_CLASS;
|
|
211
|
+
background.setAttribute('aria-hidden', 'true');
|
|
212
|
+
background.style.backgroundImage = `url("${imageUrl}")`;
|
|
213
|
+
if (!existing) {
|
|
214
|
+
page.prepend(background);
|
|
215
|
+
}
|
|
216
|
+
applied += 1;
|
|
217
|
+
});
|
|
218
|
+
return applied;
|
|
219
|
+
};
|
|
99
220
|
const shouldUseDocxWorker = (target, docxOptions) => {
|
|
100
221
|
var _a, _b;
|
|
101
222
|
if ((docxOptions === null || docxOptions === void 0 ? void 0 : docxOptions.worker) === false) {
|
|
@@ -250,6 +371,15 @@ const DOCX_RESPONSIVE_CSS = `
|
|
|
250
371
|
overflow: hidden;
|
|
251
372
|
transform-origin: top center;
|
|
252
373
|
}
|
|
374
|
+
.docx-fit-viewer .docx-page-background {
|
|
375
|
+
position: absolute;
|
|
376
|
+
inset: 0;
|
|
377
|
+
z-index: 0;
|
|
378
|
+
pointer-events: none;
|
|
379
|
+
background-position: center;
|
|
380
|
+
background-repeat: no-repeat;
|
|
381
|
+
background-size: 100% 100%;
|
|
382
|
+
}
|
|
253
383
|
.docx-fit-viewer[data-docx-dark-mode='true'] .docx-page-frame > section.docx,
|
|
254
384
|
.docx-fit-viewer[data-docx-dark-mode='true'] .docx-flow-frame > section.docx {
|
|
255
385
|
background: rgb(51, 51, 51) !important;
|
|
@@ -552,7 +682,10 @@ export default async function (buffer, target, context) {
|
|
|
552
682
|
(_a = context === null || context === void 0 ? void 0 : context.onProgressiveRender) === null || _a === void 0 ? void 0 : _a.call(context);
|
|
553
683
|
};
|
|
554
684
|
const docxOptions = createDocxOptions(target, context, notifyProgressiveRender);
|
|
555
|
-
const { defaultOptions, renderAsync } = await
|
|
685
|
+
const [{ defaultOptions, renderAsync }, pageBackgroundImage] = await Promise.all([
|
|
686
|
+
loadLibrary(),
|
|
687
|
+
resolveDocxPageBackgroundImage(buffer, () => createTargetXmlParser(target))
|
|
688
|
+
]);
|
|
556
689
|
target.dataset.docxWorker = docxOptions.useWorker ? 'self' : 'false';
|
|
557
690
|
target.dataset.docxDarkMode = docxOptions.darkMode ? 'true' : 'false';
|
|
558
691
|
const usedHeaderFooterFallback = await renderDocxWithHeaderFooterFallback(renderAsync, buffer, target, {
|
|
@@ -560,6 +693,8 @@ export default async function (buffer, target, context) {
|
|
|
560
693
|
...docxOptions
|
|
561
694
|
});
|
|
562
695
|
target.dataset.docxHeaderFooterFallback = usedHeaderFooterFallback ? 'true' : 'false';
|
|
696
|
+
target.dataset.docxPageBackground =
|
|
697
|
+
applyDocxPageBackgroundImage(target, pageBackgroundImage) > 0 ? 'true' : 'false';
|
|
563
698
|
notifyProgressiveRender();
|
|
564
699
|
const disposeResponsive = makeDocxResponsive(target, context);
|
|
565
700
|
(_a = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _a === void 0 ? void 0 : _a.call(context, {
|
|
@@ -587,6 +722,7 @@ export default async function (buffer, target, context) {
|
|
|
587
722
|
delete target.dataset.docxWorker;
|
|
588
723
|
delete target.dataset.docxDarkMode;
|
|
589
724
|
delete target.dataset.docxHeaderFooterFallback;
|
|
725
|
+
delete target.dataset.docxPageBackground;
|
|
590
726
|
target.innerHTML = '';
|
|
591
727
|
}
|
|
592
728
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@file-viewer/renderer-word",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.5",
|
|
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.",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"LICENSE"
|
|
58
58
|
],
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@file-viewer/core": "2.2.
|
|
61
|
-
"@file-viewer/doc": "2.2.
|
|
60
|
+
"@file-viewer/core": "2.2.5",
|
|
61
|
+
"@file-viewer/doc": "2.2.5",
|
|
62
62
|
"@file-viewer/docx": "^0.3.26",
|
|
63
63
|
"jszip": "^3.10.1",
|
|
64
64
|
"rtf.js": "^3.0.9"
|