office-viewer 0.1.5 → 0.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/README.md +0 -2
- package/esm/Word.d.ts +9 -1
- package/esm/Word.js +92 -43
- package/esm/package/PackageParser.d.ts +4 -0
- package/esm/package/XMLPackageParser.d.ts +1 -0
- package/esm/package/ZipPackageParser.d.ts +4 -0
- package/esm/package/ZipPackageParser.js +9 -0
- package/esm/util/fileType.d.ts +9 -0
- package/esm/util/fileType.js +66 -0
- package/esm/util/replaceVar.d.ts +7 -1
- package/esm/util/replaceVar.js +277 -114
- package/lib/Word.d.ts +9 -1
- package/lib/Word.js +91 -42
- package/lib/package/PackageParser.d.ts +4 -0
- package/lib/package/XMLPackageParser.d.ts +2 -1
- package/lib/package/ZipPackageParser.d.ts +5 -1
- package/lib/package/ZipPackageParser.js +9 -0
- package/lib/util/fileType.d.ts +9 -0
- package/lib/util/fileType.js +70 -0
- package/lib/util/replaceVar.d.ts +7 -1
- package/lib/util/replaceVar.js +276 -113
- package/package.json +4 -2
package/README.md
CHANGED
package/esm/Word.d.ts
CHANGED
|
@@ -209,6 +209,7 @@ export default class Word {
|
|
|
209
209
|
* 当前渲染的段,因为很多渲染需要,所以为了避免大量传参,这里直接挂在这里
|
|
210
210
|
*/
|
|
211
211
|
currentSection: Section;
|
|
212
|
+
DOCUMENT_RELS: string;
|
|
212
213
|
/**
|
|
213
214
|
* 初始化一些公共资源,比如
|
|
214
215
|
*/
|
|
@@ -263,6 +264,13 @@ export default class Word {
|
|
|
263
264
|
* 加载图片
|
|
264
265
|
*/
|
|
265
266
|
loadImage(relation: Relationship): string | null;
|
|
267
|
+
/**
|
|
268
|
+
* 保存新图片,这个方法主要用于图片变量,需要生成新的 relation
|
|
269
|
+
* @param newRelId 关系 id
|
|
270
|
+
* @param blob 文件数据
|
|
271
|
+
* @param ext 扩展名
|
|
272
|
+
*/
|
|
273
|
+
saveNewImage(newRelId: string, data: Uint8Array): void;
|
|
266
274
|
loadFont(rId: string, key: string): string | null;
|
|
267
275
|
/**
|
|
268
276
|
* 解析 html
|
|
@@ -310,7 +318,7 @@ export default class Word {
|
|
|
310
318
|
/**
|
|
311
319
|
* 下载生成的文档,会对 word/document.xml 进行处理,替换文本
|
|
312
320
|
*/
|
|
313
|
-
download(fileName?: string): void
|
|
321
|
+
download(fileName?: string): Promise<void>;
|
|
314
322
|
/**
|
|
315
323
|
* 打印功能
|
|
316
324
|
*/
|
package/esm/Word.js
CHANGED
|
@@ -16,13 +16,14 @@ import ZipPackageParser from './package/ZipPackageParser.js';
|
|
|
16
16
|
import { buildXML } from './util/xml.js';
|
|
17
17
|
import { deobfuscate } from './openxml/word/Font.js';
|
|
18
18
|
import { renderFont } from './render/renderFont.js';
|
|
19
|
-
import {
|
|
19
|
+
import { replaceT, replaceVar } from './util/replaceVar.js';
|
|
20
20
|
import { parseFootnotes } from './parse/Footnotes.js';
|
|
21
21
|
import { parseEndnotes } from './parse/parseEndnotes.js';
|
|
22
22
|
import { renderNotes } from './render/renderNotes.js';
|
|
23
23
|
import { printIframe } from './util/print.js';
|
|
24
24
|
import { Settings } from './openxml/Settings.js';
|
|
25
25
|
import { get } from './util/get.js';
|
|
26
|
+
import { fileTypeFromBuffer } from './util/fileType.js';
|
|
26
27
|
|
|
27
28
|
var defaultRenderOptions = {
|
|
28
29
|
classPrefix: 'docx-viewer',
|
|
@@ -78,6 +79,7 @@ var Word = /** @class */ (function () {
|
|
|
78
79
|
* 分页标记,如果为 true,那么在渲染的时候会强制分页
|
|
79
80
|
*/
|
|
80
81
|
this.breakPage = false;
|
|
82
|
+
this.DOCUMENT_RELS = '/word/_rels/document.xml.rels';
|
|
81
83
|
parser.load(docFile);
|
|
82
84
|
this.id = Word.globalId++;
|
|
83
85
|
this.parser = parser;
|
|
@@ -201,8 +203,8 @@ var Word = /** @class */ (function () {
|
|
|
201
203
|
}
|
|
202
204
|
this.relationships = rels;
|
|
203
205
|
var documentRels = {};
|
|
204
|
-
if (this.parser.fileExists(
|
|
205
|
-
documentRels = parseRelationships(this.parser.getXML(
|
|
206
|
+
if (this.parser.fileExists(this.DOCUMENT_RELS)) {
|
|
207
|
+
documentRels = parseRelationships(this.parser.getXML(this.DOCUMENT_RELS), 'word');
|
|
206
208
|
}
|
|
207
209
|
this.documentRels = documentRels;
|
|
208
210
|
var fontTableRels = {};
|
|
@@ -300,7 +302,7 @@ var Word = /** @class */ (function () {
|
|
|
300
302
|
}
|
|
301
303
|
var data = this.renderOptions.data;
|
|
302
304
|
if (text.indexOf('{{') !== -1) {
|
|
303
|
-
text = text.replace(/{{([^}]+)}}/g, function (all, group) {
|
|
305
|
+
text = text.replace(/{{([^{}]+)}}/g, function (all, group) {
|
|
304
306
|
var result = _this.renderOptions.evalVar(group, data);
|
|
305
307
|
if (typeof result === 'undefined') {
|
|
306
308
|
return '';
|
|
@@ -331,6 +333,37 @@ var Word = /** @class */ (function () {
|
|
|
331
333
|
}
|
|
332
334
|
return null;
|
|
333
335
|
};
|
|
336
|
+
/**
|
|
337
|
+
* 保存新图片,这个方法主要用于图片变量,需要生成新的 relation
|
|
338
|
+
* @param newRelId 关系 id
|
|
339
|
+
* @param blob 文件数据
|
|
340
|
+
* @param ext 扩展名
|
|
341
|
+
*/
|
|
342
|
+
Word.prototype.saveNewImage = function (newRelId, data) {
|
|
343
|
+
if (this.parser.fileExists(this.DOCUMENT_RELS)) {
|
|
344
|
+
var documentRels = this.parser.getXML(this.DOCUMENT_RELS);
|
|
345
|
+
// 基于一个克隆更稳妥
|
|
346
|
+
var newRelation = documentRels
|
|
347
|
+
.getElementsByTagName('Relationship')
|
|
348
|
+
.item(0)
|
|
349
|
+
.cloneNode(true);
|
|
350
|
+
newRelation.setAttributeNS(null, 'Id', newRelId);
|
|
351
|
+
newRelation.setAttributeNS(null, 'Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image');
|
|
352
|
+
var ext = '';
|
|
353
|
+
var fileType = fileTypeFromBuffer(data);
|
|
354
|
+
if (fileType) {
|
|
355
|
+
ext = '.' + fileType.ext;
|
|
356
|
+
}
|
|
357
|
+
var imagePath = 'media/image' + newRelId + ext;
|
|
358
|
+
newRelation.setAttributeNS(null, 'Target', imagePath);
|
|
359
|
+
documentRels
|
|
360
|
+
.getElementsByTagName('Relationships')[0]
|
|
361
|
+
.appendChild(newRelation);
|
|
362
|
+
// 需要使用相对路径
|
|
363
|
+
this.parser.saveFile(this.DOCUMENT_RELS.replace(/^\//, ''), buildXML(documentRels));
|
|
364
|
+
this.parser.saveFile('word/' + imagePath, data);
|
|
365
|
+
}
|
|
366
|
+
};
|
|
334
367
|
Word.prototype.loadFont = function (rId, key) {
|
|
335
368
|
var relation = this.getFontTableRels(rId);
|
|
336
369
|
if (!relation) {
|
|
@@ -458,18 +491,29 @@ var Word = /** @class */ (function () {
|
|
|
458
491
|
*/
|
|
459
492
|
Word.prototype.download = function (fileName) {
|
|
460
493
|
if (fileName === void 0) { fileName = 'document.docx'; }
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
494
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
495
|
+
var documentData, ts, i, blob;
|
|
496
|
+
return __generator(this, function (_a) {
|
|
497
|
+
switch (_a.label) {
|
|
498
|
+
case 0:
|
|
499
|
+
documentData = this.getXML('word/document.xml');
|
|
500
|
+
if (!this.renderOptions.enableVar) return [3 /*break*/, 2];
|
|
501
|
+
mergeRun(this, documentData);
|
|
502
|
+
return [4 /*yield*/, replaceVar(this, documentData, true)];
|
|
503
|
+
case 1:
|
|
504
|
+
_a.sent();
|
|
505
|
+
ts = documentData.getElementsByTagName('w:t');
|
|
506
|
+
for (i = 0; i < ts.length; i++) {
|
|
507
|
+
replaceT(this, ts[i], this.renderOptions.data);
|
|
508
|
+
}
|
|
509
|
+
_a.label = 2;
|
|
510
|
+
case 2:
|
|
511
|
+
blob = this.parser.generateZip(buildXML(documentData));
|
|
512
|
+
downloadBlob(blob, fileName);
|
|
513
|
+
return [2 /*return*/];
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
});
|
|
473
517
|
};
|
|
474
518
|
/**
|
|
475
519
|
* 打印功能
|
|
@@ -514,34 +558,39 @@ var Word = /** @class */ (function () {
|
|
|
514
558
|
return __awaiter(this, void 0, void 0, function () {
|
|
515
559
|
var renderOptions, isDebug, documentData, document, documentElement;
|
|
516
560
|
return __generator(this, function (_a) {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
561
|
+
switch (_a.label) {
|
|
562
|
+
case 0:
|
|
563
|
+
this.init();
|
|
564
|
+
this.currentPage = 0;
|
|
565
|
+
renderOptions = __assign(__assign({}, this.renderOptions), renderOptionsOverride);
|
|
566
|
+
isDebug = renderOptions.debug;
|
|
567
|
+
isDebug && console.log('init', this);
|
|
568
|
+
this.rootElement = root;
|
|
569
|
+
root.innerHTML = '';
|
|
570
|
+
documentData = this.getXML('word/document.xml');
|
|
571
|
+
isDebug && console.log('documentData', documentData);
|
|
572
|
+
if (!renderOptions.enableVar) return [3 /*break*/, 2];
|
|
573
|
+
mergeRun(this, documentData);
|
|
574
|
+
return [4 /*yield*/, replaceVar(this, documentData)];
|
|
575
|
+
case 1:
|
|
576
|
+
_a.sent();
|
|
577
|
+
_a.label = 2;
|
|
578
|
+
case 2:
|
|
579
|
+
document = WDocument.fromXML(this, documentData);
|
|
580
|
+
isDebug && console.log('document', document);
|
|
581
|
+
documentElement = renderDocument(root, this, document, renderOptions);
|
|
582
|
+
root.classList.add(this.getClassPrefix());
|
|
583
|
+
if (renderOptions.page && renderOptions.pageWrap) {
|
|
584
|
+
root.classList.add(this.wrapClassName);
|
|
585
|
+
root.style.padding = "".concat(renderOptions.pageWrapPadding || 0, "pt");
|
|
586
|
+
root.style.background = renderOptions.pageWrapBackground || '#ECECEC';
|
|
587
|
+
}
|
|
588
|
+
appendChild(root, renderStyle(this));
|
|
589
|
+
appendChild(root, renderFont(this.fontTable));
|
|
590
|
+
appendChild(root, documentElement);
|
|
591
|
+
appendChild(root, renderNotes(this));
|
|
592
|
+
return [2 /*return*/];
|
|
539
593
|
}
|
|
540
|
-
appendChild(root, renderStyle(this));
|
|
541
|
-
appendChild(root, renderFont(this.fontTable));
|
|
542
|
-
appendChild(root, documentElement);
|
|
543
|
-
appendChild(root, renderNotes(this));
|
|
544
|
-
return [2 /*return*/];
|
|
545
594
|
});
|
|
546
595
|
});
|
|
547
596
|
};
|
|
@@ -13,6 +13,10 @@ export interface PackageParser {
|
|
|
13
13
|
* 根据类型读取文件
|
|
14
14
|
*/
|
|
15
15
|
getFileByType(filePath: string, type: 'string' | 'blob' | 'uint8array'): string | Blob | Uint8Array | null;
|
|
16
|
+
/**
|
|
17
|
+
* 写入文件,主要用于图片
|
|
18
|
+
*/
|
|
19
|
+
saveFile(filePath: string, content: Uint8Array | string): void;
|
|
16
20
|
/**
|
|
17
21
|
* 文件是否存在
|
|
18
22
|
*/
|
|
@@ -20,6 +20,7 @@ export default class XMLPackageParser implements PackageParser {
|
|
|
20
20
|
* 在 xml 下基本不用这个
|
|
21
21
|
*/
|
|
22
22
|
getFileByType(filePath: string, type: 'string' | 'blob'): string | Uint8Array | Blob | null;
|
|
23
|
+
saveFile(filePath: string, content: Uint8Array | string): void;
|
|
23
24
|
/**
|
|
24
25
|
* 判断文件是否存在
|
|
25
26
|
*/
|
|
@@ -18,6 +18,10 @@ export default class ZipPackageParser implements PackageParser {
|
|
|
18
18
|
* 根据类型读取文件
|
|
19
19
|
*/
|
|
20
20
|
getFileByType(filePath: string, type: 'string' | 'blob' | 'uint8array'): string | Uint8Array | Blob | null;
|
|
21
|
+
/**
|
|
22
|
+
* xml 下没这功能
|
|
23
|
+
*/
|
|
24
|
+
saveFile(filePath: string, content: Uint8Array | string): void;
|
|
21
25
|
/**
|
|
22
26
|
* 判断文件是否存在
|
|
23
27
|
*/
|
|
@@ -48,6 +48,15 @@ var ZipPackageParser = /** @class */ (function () {
|
|
|
48
48
|
console.warn('getFileByType', filePath, 'not found');
|
|
49
49
|
return null;
|
|
50
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* xml 下没这功能
|
|
53
|
+
*/
|
|
54
|
+
ZipPackageParser.prototype.saveFile = function (filePath, content) {
|
|
55
|
+
if (typeof content === 'string') {
|
|
56
|
+
content = strToU8(content);
|
|
57
|
+
}
|
|
58
|
+
this.zip[filePath] = content;
|
|
59
|
+
};
|
|
51
60
|
/**
|
|
52
61
|
* 判断文件是否存在
|
|
53
62
|
*/
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { __values, __read, __spreadArray } from 'tslib';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 自动识别文件类型,只支持少数几种,参考了 file-type 项目里的实现
|
|
5
|
+
*/
|
|
6
|
+
function check(buffer, headers, options) {
|
|
7
|
+
var e_1, _a;
|
|
8
|
+
if (options === void 0) { options = {}; }
|
|
9
|
+
var offset = options.offset || 0;
|
|
10
|
+
try {
|
|
11
|
+
for (var _b = __values(headers.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
12
|
+
var _d = __read(_c.value, 2), index = _d[0], header = _d[1];
|
|
13
|
+
// If a bitmask is set
|
|
14
|
+
if (options.mask) {
|
|
15
|
+
// If header doesn't equal `buf` with bits masked off
|
|
16
|
+
if (header !== (options.mask[index] & buffer[index + offset])) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else if (header !== buffer[index + offset]) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
26
|
+
finally {
|
|
27
|
+
try {
|
|
28
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
29
|
+
}
|
|
30
|
+
finally { if (e_1) throw e_1.error; }
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
function stringToBytes(string) {
|
|
35
|
+
return __spreadArray([], __read(string), false).map(function (character) { return character.charCodeAt(0); });
|
|
36
|
+
}
|
|
37
|
+
function checkString(buffer, string, options) {
|
|
38
|
+
if (options === void 0) { options = {}; }
|
|
39
|
+
return check(buffer, stringToBytes(string), options);
|
|
40
|
+
}
|
|
41
|
+
function fileTypeFromBuffer(buffer) {
|
|
42
|
+
if (check(buffer, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) {
|
|
43
|
+
return { ext: 'png', mime: 'image/png' };
|
|
44
|
+
}
|
|
45
|
+
if (check(buffer, [0xff, 0xd8, 0xff])) {
|
|
46
|
+
return { ext: 'jpg', mime: 'image/jpeg' };
|
|
47
|
+
}
|
|
48
|
+
if (check(buffer, [0x47, 0x49, 0x46])) {
|
|
49
|
+
return { ext: 'gif', mime: 'image/gif' };
|
|
50
|
+
}
|
|
51
|
+
if (check(buffer, [0x42, 0x4d])) {
|
|
52
|
+
return { ext: 'bmp', mime: 'image/bmp' };
|
|
53
|
+
}
|
|
54
|
+
if (check(buffer, [0xc5, 0xd0, 0xd3, 0xc6])) {
|
|
55
|
+
return { ext: 'eps', mime: 'application/eps' };
|
|
56
|
+
}
|
|
57
|
+
if (checkString(buffer, '8BPS')) {
|
|
58
|
+
return { ext: 'psd', mime: 'image/vnd.adobe.photoshop' };
|
|
59
|
+
}
|
|
60
|
+
if (checkString(buffer, '%PDF')) {
|
|
61
|
+
return { ext: 'pdf', mime: 'application/pdf' };
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { fileTypeFromBuffer };
|
package/esm/util/replaceVar.d.ts
CHANGED
|
@@ -7,4 +7,10 @@ import Word from '../Word';
|
|
|
7
7
|
* 替换单个文本变量
|
|
8
8
|
*/
|
|
9
9
|
export declare function replaceT(word: Word, t: Element, data: any): void;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* 变量替换主入口
|
|
12
|
+
* @param word
|
|
13
|
+
* @param documentData
|
|
14
|
+
* @param replaceImage 是否替换掉图片,只有下载时才替换,避免性能问题
|
|
15
|
+
*/
|
|
16
|
+
export declare function replaceVar(word: Word, documentData: Document, replaceImage?: boolean): Promise<void>;
|