@file-viewer/renderer-word 2.1.30 → 2.2.0

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/index.d.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  import { type FileRenderHandler, type FileViewerRenderedInstance, type FileViewerRendererPlugin, type RendererDefinition } from '@file-viewer/core';
2
2
  export declare const wordRendererDefinitions: RendererDefinition[];
3
3
  export declare const renderFileViewerWordDocx: FileRenderHandler<FileViewerRenderedInstance, HTMLDivElement>;
4
+ /**
5
+ * A surprising number of legacy systems keep the `.doc` suffix after saving
6
+ * an OOXML document. Route those ZIP-based files through the DOCX engine while
7
+ * leaving genuine OLE/CFB `.doc` files on the binary parser.
8
+ */
9
+ export declare const resolveFileViewerWordContainer: (buffer: ArrayBuffer) => "openxml" | "binary";
4
10
  export declare const renderFileViewerWordDoc: FileRenderHandler<FileViewerRenderedInstance, HTMLDivElement>;
5
11
  export declare const renderFileViewerOpenDocument: FileRenderHandler<FileViewerRenderedInstance, HTMLDivElement>;
6
12
  export declare const wordRenderer: FileViewerRendererPlugin<FileRenderHandler<FileViewerRenderedInstance, HTMLDivElement>>;
package/dist/index.js CHANGED
@@ -10,7 +10,21 @@ if (wordDefinitions.length !== wordRendererIds.length) {
10
10
  }
11
11
  export const wordRendererDefinitions = wordDefinitions;
12
12
  export const renderFileViewerWordDocx = (buffer, target, _type, context) => import('./wordDocx.js').then(({ default: renderWordDocx }) => renderWordDocx(buffer, target, context));
13
- export const renderFileViewerWordDoc = (buffer, target, _type, context) => import('./wordDoc.js').then(({ default: renderWordDoc }) => renderWordDoc(buffer, target, context));
13
+ /**
14
+ * A surprising number of legacy systems keep the `.doc` suffix after saving
15
+ * an OOXML document. Route those ZIP-based files through the DOCX engine while
16
+ * leaving genuine OLE/CFB `.doc` files on the binary parser.
17
+ */
18
+ export const resolveFileViewerWordContainer = (buffer) => {
19
+ if (buffer.byteLength < 2) {
20
+ return 'binary';
21
+ }
22
+ const bytes = new Uint8Array(buffer, 0, 2);
23
+ return bytes[0] === 0x50 && bytes[1] === 0x4b ? 'openxml' : 'binary';
24
+ };
25
+ export const renderFileViewerWordDoc = (buffer, target, _type, context) => resolveFileViewerWordContainer(buffer) === 'openxml'
26
+ ? import('./wordDocx.js').then(({ default: renderWordDocx }) => renderWordDocx(buffer, target, context))
27
+ : import('./wordDoc.js').then(({ default: renderWordDoc }) => renderWordDoc(buffer, target, context));
14
28
  export const renderFileViewerOpenDocument = (buffer, target, type, context) => import('./openDocument.js').then(({ default: renderOpenDocument }) => renderOpenDocument(buffer, target, type, context));
15
29
  export const wordRenderer = {
16
30
  id: 'file-viewer-renderer-word',
@@ -1,17 +1,20 @@
1
1
  import JSZip from 'jszip';
2
2
  import { createFileViewerTranslator, } from '@file-viewer/core';
3
3
  const openDocumentStyle = `
4
- .odf-viewer{min-height:100%;padding:28px;overflow:auto;background:#dfe5eb;box-sizing:border-box}
4
+ .odf-viewer{min-height:100%;padding:28px;overflow:auto;background:var(--file-viewer-render-surface-background,#dfe5eb);box-sizing:border-box}
5
5
  .odf-shell{width:min(100%,980px);margin:0 auto}.odf-shell>header{margin-bottom:18px;padding:18px 22px;border-radius:8px;background:#fff;box-shadow:0 10px 26px rgba(15,23,42,.1);box-sizing:border-box}
6
6
  .odf-shell>header span{color:#0f766e;font-size:12px;font-weight:800}.odf-shell>header h2{margin:6px 0 0;color:#132235;font-size:24px}
7
7
  .odf-page{min-height:360px;margin:0 auto 18px;padding:42px 48px;border-radius:4px;background:#fff;box-shadow:0 16px 38px rgba(15,23,42,.12);color:#1f2937;box-sizing:border-box}
8
8
  .odf-page h3{margin:0 0 20px;color:#334155;font-size:18px}.odf-page p{margin:0 0 12px;font-size:15px;line-height:1.85;white-space:pre-wrap}
9
- .flyfish-rtf-viewer{min-height:100%;padding:28px;overflow:auto;background:#dfe5eb;color:#1f2937;box-sizing:border-box}
9
+ .flyfish-rtf-viewer{min-height:100%;padding:28px;overflow:auto;background:var(--file-viewer-render-surface-background,#dfe5eb);color:#1f2937;box-sizing:border-box}
10
10
  .flyfish-rtf-header{width:min(100%,900px);margin:0 auto 18px;padding:18px 22px;border-radius:8px;background:#fff;box-shadow:0 10px 26px rgba(15,23,42,.1);box-sizing:border-box}
11
11
  .flyfish-rtf-header span{display:block;color:#0f766e;font-size:12px;font-weight:800}.flyfish-rtf-header strong{display:block;margin-top:6px;color:#132235;font-size:24px}
12
12
  .flyfish-rtf-paper{width:min(100%,900px);min-height:980px;margin:0 auto;padding:54px 62px;background:#fff;box-shadow:0 16px 38px rgba(15,23,42,.12);line-height:1.75;box-sizing:border-box}.flyfish-rtf-paper p{margin:0 0 12px}
13
- [data-viewer-theme='dark'] .odf-viewer,[data-viewer-theme='dark'] .flyfish-rtf-viewer{background:#111827}[data-viewer-theme='dark'] .odf-shell>header,[data-viewer-theme='dark'] .odf-page,[data-viewer-theme='dark'] .flyfish-rtf-header,[data-viewer-theme='dark'] .flyfish-rtf-paper{background:#f8fafc;color:#1f2937}
14
- @media (prefers-color-scheme:dark){[data-viewer-theme='system'] .odf-viewer,[data-viewer-theme='system'] .flyfish-rtf-viewer{background:#111827}[data-viewer-theme='system'] .odf-shell>header,[data-viewer-theme='system'] .odf-page,[data-viewer-theme='system'] .flyfish-rtf-header,[data-viewer-theme='system'] .flyfish-rtf-paper{background:#f8fafc;color:#1f2937}}
13
+ [data-viewer-theme='dark'] .odf-viewer,[data-viewer-theme='dark'] .flyfish-rtf-viewer{color-scheme:dark;background:var(--file-viewer-render-surface-background,#0d1117);color:#e6edf3}
14
+ [data-viewer-theme='dark'] .odf-shell>header,[data-viewer-theme='dark'] .odf-page,[data-viewer-theme='dark'] .flyfish-rtf-header,[data-viewer-theme='dark'] .flyfish-rtf-paper{border:1px solid rgba(139,148,158,.24);background:#161b22;color:#e6edf3;box-shadow:0 18px 44px rgba(0,0,0,.34)}
15
+ [data-viewer-theme='dark'] .odf-shell>header h2,[data-viewer-theme='dark'] .odf-page h3,[data-viewer-theme='dark'] .flyfish-rtf-header strong{color:#f0f6fc}
16
+ [data-viewer-theme='dark'] .odf-shell>header span,[data-viewer-theme='dark'] .flyfish-rtf-header span{color:#6ee7b7}
17
+ @media (prefers-color-scheme:dark){[data-viewer-theme='system'] .odf-viewer,[data-viewer-theme='system'] .flyfish-rtf-viewer{color-scheme:dark;background:var(--file-viewer-render-surface-background,#0d1117);color:#e6edf3}[data-viewer-theme='system'] .odf-shell>header,[data-viewer-theme='system'] .odf-page,[data-viewer-theme='system'] .flyfish-rtf-header,[data-viewer-theme='system'] .flyfish-rtf-paper{border:1px solid rgba(139,148,158,.24);background:#161b22;color:#e6edf3;box-shadow:0 18px 44px rgba(0,0,0,.34)}[data-viewer-theme='system'] .odf-shell>header h2,[data-viewer-theme='system'] .odf-page h3,[data-viewer-theme='system'] .flyfish-rtf-header strong{color:#f0f6fc}[data-viewer-theme='system'] .odf-shell>header span,[data-viewer-theme='system'] .flyfish-rtf-header span{color:#6ee7b7}}
15
18
  @media (max-width:720px){.odf-viewer,.flyfish-rtf-viewer{padding:14px}.odf-page{padding:28px 24px}.flyfish-rtf-paper{padding:36px 28px}}
16
19
  `;
17
20
  const createStyle = () => {
package/dist/wordDoc.js CHANGED
@@ -14,7 +14,7 @@ const WORD_PAGE_CSS = `
14
14
  box-sizing:border-box;
15
15
  min-height:100%;
16
16
  padding:32px 24px 48px;
17
- background:#ececec;
17
+ background:var(--file-viewer-render-surface-background,#ececec);
18
18
  display:flex;
19
19
  flex-direction:column;
20
20
  align-items:center;
@@ -71,23 +71,47 @@ const WORD_PAGE_CSS = `
71
71
  display:none;
72
72
  }
73
73
  [data-viewer-theme='dark'] .msdoc-stage{
74
- background:#111827;
74
+ background:var(--file-viewer-render-surface-background,#111827);
75
75
  }
76
76
  [data-viewer-theme='dark'] .msdoc-page > .msdoc-root{
77
- color-scheme:only light;
78
- forced-color-adjust:none;
79
- background:#fff;
80
- color:#111;
77
+ color-scheme:dark;
78
+ background:#161b22;
79
+ border-color:rgba(139,148,158,.24);
80
+ color:#e6edf3;
81
+ box-shadow:0 18px 44px rgba(0,0,0,.36);
82
+ }
83
+ [data-viewer-theme='dark'] .msdoc-page > .msdoc-root span[style*='color:#000000']{
84
+ color:#e6edf3!important;
85
+ }
86
+ [data-viewer-theme='dark'] .msdoc-page .msdoc-link{
87
+ color:#58a6ff;
88
+ }
89
+ [data-viewer-theme='dark'] .msdoc-page .msdoc-attachment{
90
+ border-color:rgba(139,148,158,.3);
91
+ background:#21262d;
92
+ color:#58a6ff;
81
93
  }
82
94
  @media (prefers-color-scheme:dark){
83
95
  [data-viewer-theme='system'] .msdoc-stage{
84
- background:#111827;
96
+ background:var(--file-viewer-render-surface-background,#111827);
85
97
  }
86
98
  [data-viewer-theme='system'] .msdoc-page > .msdoc-root{
87
- color-scheme:only light;
88
- forced-color-adjust:none;
89
- background:#fff;
90
- color:#111;
99
+ color-scheme:dark;
100
+ background:#161b22;
101
+ border-color:rgba(139,148,158,.24);
102
+ color:#e6edf3;
103
+ box-shadow:0 18px 44px rgba(0,0,0,.36);
104
+ }
105
+ [data-viewer-theme='system'] .msdoc-page > .msdoc-root span[style*='color:#000000']{
106
+ color:#e6edf3!important;
107
+ }
108
+ [data-viewer-theme='system'] .msdoc-page .msdoc-link{
109
+ color:#58a6ff;
110
+ }
111
+ [data-viewer-theme='system'] .msdoc-page .msdoc-attachment{
112
+ border-color:rgba(139,148,158,.3);
113
+ background:#21262d;
114
+ color:#58a6ff;
91
115
  }
92
116
  }
93
117
  @media (max-width: 860px){
@@ -110,14 +134,14 @@ const MSDOC_ZOOM_CSS = `
110
134
  box-sizing:border-box;
111
135
  height:100%;
112
136
  overflow:auto;
113
- background:#ececec;
137
+ background:var(--file-viewer-render-surface-background,#ececec);
114
138
  }
115
139
  [data-viewer-theme='dark'] .msdoc-zoom-viewer{
116
- background:#111827;
140
+ background:var(--file-viewer-render-surface-background,#111827);
117
141
  }
118
142
  @media (prefers-color-scheme:dark){
119
143
  [data-viewer-theme='system'] .msdoc-zoom-viewer{
120
- background:#111827;
144
+ background:var(--file-viewer-render-surface-background,#111827);
121
145
  }
122
146
  }
123
147
  .msdoc-zoom-viewer .msdoc-stage{
@@ -1,5 +1,16 @@
1
+ import type { Options, renderAsync } from '@file-viewer/docx';
1
2
  import { type FileRenderContext, type FileViewerRenderedInstance as AppWrapper } from '@file-viewer/core';
3
+ type DocxRenderAsync = typeof renderAsync;
4
+ export declare const isMissingDocxHeaderFooterRootError: (error: unknown) => boolean;
5
+ /**
6
+ * Some malformed or partially generated DOCX files reference a header/footer
7
+ * part whose parsed root is missing. @file-viewer/docx 0.3.21 skips that part;
8
+ * this retry keeps older installed engines usable while the dependency update
9
+ * rolls through lockfiles and private registries.
10
+ */
11
+ export declare const renderDocxWithHeaderFooterFallback: (render: DocxRenderAsync, buffer: ArrayBuffer, target: HTMLDivElement, options: Options) => Promise<boolean>;
2
12
  /**
3
13
  * 渲染docx文件
4
14
  */
5
15
  export default function (buffer: ArrayBuffer, target: HTMLDivElement, context?: FileRenderContext): Promise<AppWrapper>;
16
+ export {};
package/dist/wordDocx.js CHANGED
@@ -1,4 +1,4 @@
1
- import { resolveFileViewerDocxWorkerJsZipUrl, resolveFileViewerDocxWorkerUrl, } from '@file-viewer/core/assets';
1
+ import { resolveFileViewerDocxWorkerJsZipUrl, resolveFileViewerDocxWorkerUrl, resolveFileViewerRuntimeAssetBaseUrl, } from '@file-viewer/core/assets';
2
2
  import { applyPrintPageSize, buildPrintPageStyle, createFileViewerTranslator, createFileViewerZoomChangeEmitter as createZoomChangeEmitter, formatCssPixels, getElementPrintPageSize, normalizeFileViewerTheme, registerFileViewerZoomProvider, resolveFileViewerFitScale, unregisterFileViewerZoomProvider, } from '@file-viewer/core';
3
3
  const DOCX_DEFAULT_PAGE_SIZE = {
4
4
  width: 794,
@@ -33,6 +33,37 @@ const loadLibrary = (() => {
33
33
  return resolveDocxLibrary(await loader.load());
34
34
  };
35
35
  })();
36
+ export const isMissingDocxHeaderFooterRootError = (error) => {
37
+ if (!(error instanceof Error)) {
38
+ return false;
39
+ }
40
+ return /(?:undefined|null).*children|children.*(?:undefined|null)/i.test(error.message) &&
41
+ /renderHeaderFooter/i.test(error.stack || '');
42
+ };
43
+ /**
44
+ * Some malformed or partially generated DOCX files reference a header/footer
45
+ * part whose parsed root is missing. @file-viewer/docx 0.3.21 skips that part;
46
+ * this retry keeps older installed engines usable while the dependency update
47
+ * rolls through lockfiles and private registries.
48
+ */
49
+ export const renderDocxWithHeaderFooterFallback = async (render, buffer, target, options) => {
50
+ try {
51
+ await render(buffer, target, undefined, options);
52
+ return false;
53
+ }
54
+ catch (error) {
55
+ if (!isMissingDocxHeaderFooterRootError(error)) {
56
+ throw error;
57
+ }
58
+ target.innerHTML = '';
59
+ await render(buffer, target, undefined, {
60
+ ...options,
61
+ renderHeaders: false,
62
+ renderFooters: false
63
+ });
64
+ return true;
65
+ }
66
+ };
36
67
  /**
37
68
  * DOCX / DOCM / DOTX / DOTM are OOXML packages, so a valid file must start
38
69
  * with a ZIP signature. This catches common enterprise download failures where
@@ -73,11 +104,14 @@ const shouldUseDocxWorker = (target, docxOptions) => {
73
104
  if ((docxOptions === null || docxOptions === void 0 ? void 0 : docxOptions.worker) === true) {
74
105
  return true;
75
106
  }
107
+ // Auto mode is asset-aware. A browser can expose Worker even when a host has
108
+ // not copied the optional DOCX vendor files; probing that missing URL often
109
+ // returns an SPA HTML fallback and emits a SyntaxError before main-thread
110
+ // rendering recovers. Full packages inject workerUrl, so they still use it.
76
111
  const WorkerCtor = (_b = (_a = getTargetWindow(target)) === null || _a === void 0 ? void 0 : _a.Worker) !== null && _b !== void 0 ? _b : globalThis.Worker;
77
- if (!WorkerCtor) {
78
- return false;
79
- }
80
- return !DOCX_WORKER_UNSAFE_PROTOCOLS.has(getTargetProtocol(target));
112
+ return Boolean(WorkerCtor &&
113
+ (docxOptions === null || docxOptions === void 0 ? void 0 : docxOptions.workerUrl) &&
114
+ !DOCX_WORKER_UNSAFE_PROTOCOLS.has(getTargetProtocol(target)));
81
115
  };
82
116
  const prefersDarkColorScheme = (target) => {
83
117
  var _a;
@@ -108,7 +142,7 @@ const appendDocxVendorAssetVersion = (url, explicitUrl) => {
108
142
  const createDocxOptions = (target, context, notifyProgressiveRender) => {
109
143
  var _a, _b;
110
144
  const docxOptions = (_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a.docx;
111
- const documentBaseUrl = target.ownerDocument.URL || undefined;
145
+ const documentBaseUrl = resolveFileViewerRuntimeAssetBaseUrl(target.ownerDocument);
112
146
  const useWorker = shouldUseDocxWorker(target, docxOptions);
113
147
  const usePagedLayout = (docxOptions === null || docxOptions === void 0 ? void 0 : docxOptions.visualPagination) === true;
114
148
  const darkMode = resolveDocxDarkMode(target, context, docxOptions);
@@ -173,11 +207,11 @@ const DOCX_RESPONSIVE_CSS = `
173
207
  box-sizing: border-box;
174
208
  height: 100%;
175
209
  overflow: auto;
176
- background: #ececec;
210
+ background: var(--file-viewer-render-surface-background, #ececec);
177
211
  color-scheme: light;
178
212
  }
179
213
  .docx-fit-viewer[data-docx-dark-mode='true'] {
180
- background: #242424;
214
+ background: var(--file-viewer-render-surface-background, #242424);
181
215
  color-scheme: dark;
182
216
  }
183
217
  .docx-fit-viewer .docx-wrapper {
@@ -185,10 +219,10 @@ const DOCX_RESPONSIVE_CSS = `
185
219
  min-width: 0 !important;
186
220
  width: 100% !important;
187
221
  padding: 24px 14px 40px !important;
188
- background: #e7e9ec !important;
222
+ background: var(--file-viewer-render-surface-background, #e7e9ec) !important;
189
223
  }
190
224
  .docx-fit-viewer[data-docx-dark-mode='true'] .docx-wrapper {
191
- background: #242424 !important;
225
+ background: var(--file-viewer-render-surface-background, #242424) !important;
192
226
  }
193
227
  .docx-fit-viewer .docx-page-frame {
194
228
  position: relative;
@@ -521,10 +555,11 @@ export default async function (buffer, target, context) {
521
555
  const { defaultOptions, renderAsync } = await loadLibrary();
522
556
  target.dataset.docxWorker = docxOptions.useWorker ? 'self' : 'false';
523
557
  target.dataset.docxDarkMode = docxOptions.darkMode ? 'true' : 'false';
524
- await renderAsync(buffer, target, undefined, {
558
+ const usedHeaderFooterFallback = await renderDocxWithHeaderFooterFallback(renderAsync, buffer, target, {
525
559
  ...defaultOptions,
526
560
  ...docxOptions
527
561
  });
562
+ target.dataset.docxHeaderFooterFallback = usedHeaderFooterFallback ? 'true' : 'false';
528
563
  notifyProgressiveRender();
529
564
  const disposeResponsive = makeDocxResponsive(target, context);
530
565
  (_a = context === null || context === void 0 ? void 0 : context.registerExportAdapter) === null || _a === void 0 ? void 0 : _a.call(context, {
@@ -551,6 +586,7 @@ export default async function (buffer, target, context) {
551
586
  disposeResponsive();
552
587
  delete target.dataset.docxWorker;
553
588
  delete target.dataset.docxDarkMode;
589
+ delete target.dataset.docxHeaderFooterFallback;
554
590
  target.innerHTML = '';
555
591
  }
556
592
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/renderer-word",
3
- "version": "2.1.30",
3
+ "version": "2.2.0",
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,8 +57,8 @@
57
57
  "LICENSE"
58
58
  ],
59
59
  "dependencies": {
60
- "@file-viewer/core": "2.1.30",
61
- "@file-viewer/doc": "2.1.30",
60
+ "@file-viewer/core": "2.2.0",
61
+ "@file-viewer/doc": "2.2.0",
62
62
  "@file-viewer/docx": "^0.3.20",
63
63
  "jszip": "^3.10.1",
64
64
  "rtf.js": "^3.0.9"