@cj-tech-master/excelts 4.2.2 → 4.2.3
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/browser/modules/excel/utils/parse-sax.d.ts +3 -0
- package/dist/browser/modules/excel/utils/parse-sax.js +32 -13
- package/dist/browser/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/browser/modules/excel/xlsx/xform/core/core-xform.js +56 -68
- package/dist/browser/modules/excel/xlsx/xform/list-xform.js +8 -10
- package/dist/browser/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
- package/dist/browser/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
- package/dist/browser/modules/excel/xlsx/xlsx.browser.js +8 -4
- package/dist/cjs/modules/excel/utils/parse-sax.js +32 -13
- package/dist/cjs/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/cjs/modules/excel/xlsx/xform/core/core-xform.js +56 -68
- package/dist/cjs/modules/excel/xlsx/xform/list-xform.js +8 -10
- package/dist/cjs/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
- package/dist/cjs/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
- package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +8 -4
- package/dist/esm/modules/excel/utils/parse-sax.js +32 -13
- package/dist/esm/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/esm/modules/excel/xlsx/xform/core/core-xform.js +56 -68
- package/dist/esm/modules/excel/xlsx/xform/list-xform.js +8 -10
- package/dist/esm/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
- package/dist/esm/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
- package/dist/esm/modules/excel/xlsx/xlsx.browser.js +8 -4
- package/dist/iife/excelts.iife.js +100 -100
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +24 -24
- package/dist/types/modules/excel/utils/parse-sax.d.ts +3 -0
- package/package.json +1 -1
|
@@ -6,31 +6,50 @@ const base_xform_1 = require("../base-xform.js");
|
|
|
6
6
|
const date_xform_1 = require("../simple/date-xform.js");
|
|
7
7
|
const string_xform_1 = require("../simple/string-xform.js");
|
|
8
8
|
const integer_xform_1 = require("../simple/integer-xform.js");
|
|
9
|
+
// Rendering uses namespace prefixes, parsing uses unqualified names (SAX strips prefixes)
|
|
10
|
+
const PROPS = {
|
|
11
|
+
creator: "dc:creator",
|
|
12
|
+
title: "dc:title",
|
|
13
|
+
subject: "dc:subject",
|
|
14
|
+
description: "dc:description",
|
|
15
|
+
identifier: "dc:identifier",
|
|
16
|
+
language: "dc:language",
|
|
17
|
+
keywords: "cp:keywords",
|
|
18
|
+
category: "cp:category",
|
|
19
|
+
lastModifiedBy: "cp:lastModifiedBy",
|
|
20
|
+
lastPrinted: "cp:lastPrinted",
|
|
21
|
+
revision: "cp:revision",
|
|
22
|
+
version: "cp:version",
|
|
23
|
+
contentStatus: "cp:contentStatus",
|
|
24
|
+
contentType: "cp:contentType",
|
|
25
|
+
created: "dcterms:created",
|
|
26
|
+
modified: "dcterms:modified"
|
|
27
|
+
};
|
|
9
28
|
class CoreXform extends base_xform_1.BaseXform {
|
|
10
29
|
constructor() {
|
|
11
30
|
super();
|
|
12
31
|
this.map = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
tag:
|
|
32
|
+
creator: new string_xform_1.StringXform({ tag: PROPS.creator }),
|
|
33
|
+
title: new string_xform_1.StringXform({ tag: PROPS.title }),
|
|
34
|
+
subject: new string_xform_1.StringXform({ tag: PROPS.subject }),
|
|
35
|
+
description: new string_xform_1.StringXform({ tag: PROPS.description }),
|
|
36
|
+
identifier: new string_xform_1.StringXform({ tag: PROPS.identifier }),
|
|
37
|
+
language: new string_xform_1.StringXform({ tag: PROPS.language }),
|
|
38
|
+
keywords: new string_xform_1.StringXform({ tag: PROPS.keywords }),
|
|
39
|
+
category: new string_xform_1.StringXform({ tag: PROPS.category }),
|
|
40
|
+
lastModifiedBy: new string_xform_1.StringXform({ tag: PROPS.lastModifiedBy }),
|
|
41
|
+
lastPrinted: new date_xform_1.DateXform({ tag: PROPS.lastPrinted, format: CoreXform.DateFormat }),
|
|
42
|
+
revision: new integer_xform_1.IntegerXform({ tag: PROPS.revision }),
|
|
43
|
+
version: new string_xform_1.StringXform({ tag: PROPS.version }),
|
|
44
|
+
contentStatus: new string_xform_1.StringXform({ tag: PROPS.contentStatus }),
|
|
45
|
+
contentType: new string_xform_1.StringXform({ tag: PROPS.contentType }),
|
|
46
|
+
created: new date_xform_1.DateXform({
|
|
47
|
+
tag: PROPS.created,
|
|
29
48
|
attrs: CoreXform.DateAttrs,
|
|
30
49
|
format: CoreXform.DateFormat
|
|
31
50
|
}),
|
|
32
|
-
|
|
33
|
-
tag:
|
|
51
|
+
modified: new date_xform_1.DateXform({
|
|
52
|
+
tag: PROPS.modified,
|
|
34
53
|
attrs: CoreXform.DateAttrs,
|
|
35
54
|
format: CoreXform.DateFormat
|
|
36
55
|
})
|
|
@@ -39,22 +58,9 @@ class CoreXform extends base_xform_1.BaseXform {
|
|
|
39
58
|
render(xmlStream, model) {
|
|
40
59
|
xmlStream.openXml(xml_stream_1.XmlStream.StdDocAttributes);
|
|
41
60
|
xmlStream.openNode("cp:coreProperties", CoreXform.CORE_PROPERTY_ATTRIBUTES);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.map["dc:description"].render(xmlStream, model.description);
|
|
46
|
-
this.map["dc:identifier"].render(xmlStream, model.identifier);
|
|
47
|
-
this.map["dc:language"].render(xmlStream, model.language);
|
|
48
|
-
this.map["cp:keywords"].render(xmlStream, model.keywords);
|
|
49
|
-
this.map["cp:category"].render(xmlStream, model.category);
|
|
50
|
-
this.map["cp:lastModifiedBy"].render(xmlStream, model.lastModifiedBy);
|
|
51
|
-
this.map["cp:lastPrinted"].render(xmlStream, model.lastPrinted);
|
|
52
|
-
this.map["cp:revision"].render(xmlStream, model.revision);
|
|
53
|
-
this.map["cp:version"].render(xmlStream, model.version);
|
|
54
|
-
this.map["cp:contentStatus"].render(xmlStream, model.contentStatus);
|
|
55
|
-
this.map["cp:contentType"].render(xmlStream, model.contentType);
|
|
56
|
-
this.map["dcterms:created"].render(xmlStream, model.created);
|
|
57
|
-
this.map["dcterms:modified"].render(xmlStream, model.modified);
|
|
61
|
+
for (const key of Object.keys(PROPS)) {
|
|
62
|
+
this.map[key].render(xmlStream, model[key]);
|
|
63
|
+
}
|
|
58
64
|
xmlStream.closeNode();
|
|
59
65
|
}
|
|
60
66
|
parseOpen(node) {
|
|
@@ -62,18 +68,13 @@ class CoreXform extends base_xform_1.BaseXform {
|
|
|
62
68
|
this.parser.parseOpen(node);
|
|
63
69
|
return true;
|
|
64
70
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.parser = this.map[node.name];
|
|
71
|
-
if (this.parser) {
|
|
72
|
-
this.parser.parseOpen(node);
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(node)}`);
|
|
71
|
+
if (node.name !== "coreProperties") {
|
|
72
|
+
this.parser = this.map[node.name];
|
|
73
|
+
if (this.parser) {
|
|
74
|
+
this.parser.parseOpen(node);
|
|
75
|
+
}
|
|
76
76
|
}
|
|
77
|
+
return true;
|
|
77
78
|
}
|
|
78
79
|
parseText(text) {
|
|
79
80
|
if (this.parser) {
|
|
@@ -87,30 +88,17 @@ class CoreXform extends base_xform_1.BaseXform {
|
|
|
87
88
|
}
|
|
88
89
|
return true;
|
|
89
90
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
this.model
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
language: this.map["dc:language"].model,
|
|
100
|
-
keywords: this.map["cp:keywords"].model,
|
|
101
|
-
category: this.map["cp:category"].model,
|
|
102
|
-
lastModifiedBy: this.map["cp:lastModifiedBy"].model,
|
|
103
|
-
lastPrinted: this.map["cp:lastPrinted"].model,
|
|
104
|
-
revision: this.map["cp:revision"].model,
|
|
105
|
-
contentStatus: this.map["cp:contentStatus"].model,
|
|
106
|
-
contentType: this.map["cp:contentType"].model,
|
|
107
|
-
created: this.map["dcterms:created"].model,
|
|
108
|
-
modified: this.map["dcterms:modified"].model
|
|
109
|
-
};
|
|
110
|
-
return false;
|
|
111
|
-
default:
|
|
112
|
-
throw new Error(`Unexpected xml node in parseClose: ${name}`);
|
|
91
|
+
if (name === "coreProperties") {
|
|
92
|
+
this.model = {};
|
|
93
|
+
for (const key of Object.keys(PROPS)) {
|
|
94
|
+
const val = this.map[key].model;
|
|
95
|
+
if (val !== undefined && val !== "") {
|
|
96
|
+
this.model[key] = val;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
113
100
|
}
|
|
101
|
+
return true;
|
|
114
102
|
}
|
|
115
103
|
}
|
|
116
104
|
exports.CoreXform = CoreXform;
|
|
@@ -44,17 +44,15 @@ class ListXform extends base_xform_1.BaseXform {
|
|
|
44
44
|
this.parser.parseOpen(node);
|
|
45
45
|
return true;
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return true;
|
|
51
|
-
default:
|
|
52
|
-
if (this.childXform.parseOpen(node)) {
|
|
53
|
-
this.parser = this.childXform;
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
return false;
|
|
47
|
+
if (node.name === this.tag) {
|
|
48
|
+
this.model = [];
|
|
49
|
+
return true;
|
|
57
50
|
}
|
|
51
|
+
if (this.childXform.parseOpen(node)) {
|
|
52
|
+
this.parser = this.childXform;
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
58
56
|
}
|
|
59
57
|
parseText(text) {
|
|
60
58
|
if (this.parser) {
|
|
@@ -39,16 +39,15 @@ class SharedStringXform extends base_xform_1.BaseXform {
|
|
|
39
39
|
xmlStream.closeNode();
|
|
40
40
|
}
|
|
41
41
|
parseOpen(node) {
|
|
42
|
-
const { name } = node;
|
|
43
42
|
if (this.parser) {
|
|
44
43
|
this.parser.parseOpen(node);
|
|
45
44
|
return true;
|
|
46
45
|
}
|
|
47
|
-
if (name === this.tag) {
|
|
46
|
+
if (node.name === this.tag) {
|
|
48
47
|
this.model = {};
|
|
49
48
|
return true;
|
|
50
49
|
}
|
|
51
|
-
this.parser = this.map[name];
|
|
50
|
+
this.parser = this.map[node.name];
|
|
52
51
|
if (this.parser) {
|
|
53
52
|
this.parser.parseOpen(node);
|
|
54
53
|
return true;
|
|
@@ -16,14 +16,12 @@ class TextXform extends base_xform_1.BaseXform {
|
|
|
16
16
|
xmlStream.closeNode();
|
|
17
17
|
}
|
|
18
18
|
parseOpen(node) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return true;
|
|
24
|
-
default:
|
|
25
|
-
return false;
|
|
19
|
+
if (node.name === "t") {
|
|
20
|
+
this._text = [];
|
|
21
|
+
this.model = "";
|
|
22
|
+
return true;
|
|
26
23
|
}
|
|
24
|
+
return false;
|
|
27
25
|
}
|
|
28
26
|
parseText(text) {
|
|
29
27
|
this._text.push(text);
|
|
@@ -367,8 +367,10 @@ class XLSX {
|
|
|
367
367
|
case ooxml_paths_1.OOXML_PATHS.docPropsApp: {
|
|
368
368
|
const appXform = new app_xform_1.AppXform();
|
|
369
369
|
const appProperties = await appXform.parseStream(stream);
|
|
370
|
-
|
|
371
|
-
|
|
370
|
+
if (appProperties) {
|
|
371
|
+
model.company = appProperties.company;
|
|
372
|
+
model.manager = appProperties.manager;
|
|
373
|
+
}
|
|
372
374
|
break;
|
|
373
375
|
}
|
|
374
376
|
case ooxml_paths_1.OOXML_PATHS.docPropsCore: {
|
|
@@ -830,8 +832,10 @@ class XLSX {
|
|
|
830
832
|
case ooxml_paths_1.OOXML_PATHS.docPropsApp: {
|
|
831
833
|
const appXform = new app_xform_1.AppXform();
|
|
832
834
|
const appProperties = await appXform.parseStream(stream);
|
|
833
|
-
|
|
834
|
-
|
|
835
|
+
if (appProperties) {
|
|
836
|
+
model.company = appProperties.company;
|
|
837
|
+
model.manager = appProperties.manager;
|
|
838
|
+
}
|
|
835
839
|
break;
|
|
836
840
|
}
|
|
837
841
|
case ooxml_paths_1.OOXML_PATHS.docPropsCore: {
|
|
@@ -142,6 +142,12 @@ const XML_ENTITIES = {
|
|
|
142
142
|
quot: '"',
|
|
143
143
|
apos: "'"
|
|
144
144
|
};
|
|
145
|
+
// HAN CELL namespace prefix normalization
|
|
146
|
+
// HAN CELL uses non-standard namespace prefixes (ep:, cp:, dc:, etc.)
|
|
147
|
+
// The x: prefix for spreadsheetml is detected dynamically from xmlns declarations
|
|
148
|
+
// See: https://github.com/exceljs/exceljs/issues/3014
|
|
149
|
+
const HAN_CELL_PREFIXES = /^(ep|cp|dc|dcterms|dcmitype|vt):/;
|
|
150
|
+
const SPREADSHEETML_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
|
|
145
151
|
// ============================================================================
|
|
146
152
|
// Parser States
|
|
147
153
|
// ============================================================================
|
|
@@ -202,6 +208,8 @@ export class SaxesParser {
|
|
|
202
208
|
this.chunkPosition = 0;
|
|
203
209
|
// Entity storage
|
|
204
210
|
this.ENTITIES = { ...XML_ENTITIES };
|
|
211
|
+
// HAN CELL compatibility: spreadsheetml namespace prefix (e.g., "x")
|
|
212
|
+
this.nsPrefix = null;
|
|
205
213
|
this.trackPosition = opt?.position !== false;
|
|
206
214
|
this.fileName = opt?.fileName;
|
|
207
215
|
this.fragment = opt?.fragment ?? false;
|
|
@@ -236,6 +244,14 @@ export class SaxesParser {
|
|
|
236
244
|
this.chunk = "";
|
|
237
245
|
this.i = 0;
|
|
238
246
|
this.prevI = 0;
|
|
247
|
+
this.nsPrefix = null;
|
|
248
|
+
}
|
|
249
|
+
// Strip HAN CELL namespace prefixes from element names
|
|
250
|
+
stripNsPrefix(name) {
|
|
251
|
+
const n = name.replace(HAN_CELL_PREFIXES, "");
|
|
252
|
+
return this.nsPrefix && n.startsWith(this.nsPrefix + ":")
|
|
253
|
+
? n.slice(this.nsPrefix.length + 1)
|
|
254
|
+
: n;
|
|
239
255
|
}
|
|
240
256
|
on(name, handler) {
|
|
241
257
|
switch (name) {
|
|
@@ -651,9 +667,8 @@ export class SaxesParser {
|
|
|
651
667
|
this.name += charFromCode(c);
|
|
652
668
|
return;
|
|
653
669
|
}
|
|
654
|
-
// Tag name complete
|
|
655
670
|
this.tag = {
|
|
656
|
-
name: this.name,
|
|
671
|
+
name: this.stripNsPrefix(this.name),
|
|
657
672
|
attributes: Object.create(null),
|
|
658
673
|
isSelfClosing: false
|
|
659
674
|
};
|
|
@@ -1092,11 +1107,7 @@ export class SaxesParser {
|
|
|
1092
1107
|
openTag() {
|
|
1093
1108
|
const tag = this.tag;
|
|
1094
1109
|
tag.isSelfClosing = false;
|
|
1095
|
-
|
|
1096
|
-
for (const { name, value } of this.attribList) {
|
|
1097
|
-
tag.attributes[name] = value;
|
|
1098
|
-
}
|
|
1099
|
-
this.attribList = [];
|
|
1110
|
+
this.processAttributes(tag);
|
|
1100
1111
|
this.openTagHandler?.(tag);
|
|
1101
1112
|
this.tags.push(tag);
|
|
1102
1113
|
this.name = "";
|
|
@@ -1105,11 +1116,7 @@ export class SaxesParser {
|
|
|
1105
1116
|
openSelfClosingTag() {
|
|
1106
1117
|
const tag = this.tag;
|
|
1107
1118
|
tag.isSelfClosing = true;
|
|
1108
|
-
|
|
1109
|
-
for (const { name, value } of this.attribList) {
|
|
1110
|
-
tag.attributes[name] = value;
|
|
1111
|
-
}
|
|
1112
|
-
this.attribList = [];
|
|
1119
|
+
this.processAttributes(tag);
|
|
1113
1120
|
this.openTagHandler?.(tag);
|
|
1114
1121
|
this.closeTagHandler?.(tag);
|
|
1115
1122
|
if (this.tags.length === 0) {
|
|
@@ -1118,8 +1125,20 @@ export class SaxesParser {
|
|
|
1118
1125
|
this.name = "";
|
|
1119
1126
|
this.state = S_TEXT;
|
|
1120
1127
|
}
|
|
1128
|
+
// Process attributes and detect spreadsheetml namespace prefix
|
|
1129
|
+
processAttributes(tag) {
|
|
1130
|
+
for (const { name, value } of this.attribList) {
|
|
1131
|
+
tag.attributes[name] = value;
|
|
1132
|
+
if (name.startsWith("xmlns:") && value === SPREADSHEETML_NS) {
|
|
1133
|
+
this.nsPrefix = name.slice(6);
|
|
1134
|
+
tag.name = this.stripNsPrefix(tag.name);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
this.attribList = [];
|
|
1138
|
+
}
|
|
1121
1139
|
closeTag() {
|
|
1122
|
-
const { tags
|
|
1140
|
+
const { tags } = this;
|
|
1141
|
+
const name = this.stripNsPrefix(this.name);
|
|
1123
1142
|
this.state = S_TEXT;
|
|
1124
1143
|
this.name = "";
|
|
1125
1144
|
if (name === "") {
|
|
@@ -10,7 +10,7 @@ class AppXform extends BaseXform {
|
|
|
10
10
|
Company: new StringXform({ tag: "Company" }),
|
|
11
11
|
Manager: new StringXform({ tag: "Manager" }),
|
|
12
12
|
HeadingPairs: new AppHeadingPairsXform(),
|
|
13
|
-
|
|
13
|
+
TitlesOfParts: new AppTitlesOfPartsXform()
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
render(xmlStream, model) {
|
|
@@ -20,7 +20,7 @@ class AppXform extends BaseXform {
|
|
|
20
20
|
xmlStream.leafNode("DocSecurity", undefined, "0");
|
|
21
21
|
xmlStream.leafNode("ScaleCrop", undefined, "false");
|
|
22
22
|
this.map.HeadingPairs.render(xmlStream, model.worksheets);
|
|
23
|
-
this.map.
|
|
23
|
+
this.map.TitlesOfParts.render(xmlStream, model.worksheets);
|
|
24
24
|
this.map.Company.render(xmlStream, model.company || "");
|
|
25
25
|
this.map.Manager.render(xmlStream, model.manager);
|
|
26
26
|
xmlStream.leafNode("LinksUpToDate", undefined, "false");
|
|
@@ -62,7 +62,7 @@ class AppXform extends BaseXform {
|
|
|
62
62
|
switch (name) {
|
|
63
63
|
case "Properties":
|
|
64
64
|
this.model = {
|
|
65
|
-
worksheets: this.map.
|
|
65
|
+
worksheets: this.map.TitlesOfParts.model,
|
|
66
66
|
company: this.map.Company.model,
|
|
67
67
|
manager: this.map.Manager.model
|
|
68
68
|
};
|
|
@@ -3,31 +3,50 @@ import { BaseXform } from "../base-xform.js";
|
|
|
3
3
|
import { DateXform } from "../simple/date-xform.js";
|
|
4
4
|
import { StringXform } from "../simple/string-xform.js";
|
|
5
5
|
import { IntegerXform } from "../simple/integer-xform.js";
|
|
6
|
+
// Rendering uses namespace prefixes, parsing uses unqualified names (SAX strips prefixes)
|
|
7
|
+
const PROPS = {
|
|
8
|
+
creator: "dc:creator",
|
|
9
|
+
title: "dc:title",
|
|
10
|
+
subject: "dc:subject",
|
|
11
|
+
description: "dc:description",
|
|
12
|
+
identifier: "dc:identifier",
|
|
13
|
+
language: "dc:language",
|
|
14
|
+
keywords: "cp:keywords",
|
|
15
|
+
category: "cp:category",
|
|
16
|
+
lastModifiedBy: "cp:lastModifiedBy",
|
|
17
|
+
lastPrinted: "cp:lastPrinted",
|
|
18
|
+
revision: "cp:revision",
|
|
19
|
+
version: "cp:version",
|
|
20
|
+
contentStatus: "cp:contentStatus",
|
|
21
|
+
contentType: "cp:contentType",
|
|
22
|
+
created: "dcterms:created",
|
|
23
|
+
modified: "dcterms:modified"
|
|
24
|
+
};
|
|
6
25
|
class CoreXform extends BaseXform {
|
|
7
26
|
constructor() {
|
|
8
27
|
super();
|
|
9
28
|
this.map = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
tag:
|
|
29
|
+
creator: new StringXform({ tag: PROPS.creator }),
|
|
30
|
+
title: new StringXform({ tag: PROPS.title }),
|
|
31
|
+
subject: new StringXform({ tag: PROPS.subject }),
|
|
32
|
+
description: new StringXform({ tag: PROPS.description }),
|
|
33
|
+
identifier: new StringXform({ tag: PROPS.identifier }),
|
|
34
|
+
language: new StringXform({ tag: PROPS.language }),
|
|
35
|
+
keywords: new StringXform({ tag: PROPS.keywords }),
|
|
36
|
+
category: new StringXform({ tag: PROPS.category }),
|
|
37
|
+
lastModifiedBy: new StringXform({ tag: PROPS.lastModifiedBy }),
|
|
38
|
+
lastPrinted: new DateXform({ tag: PROPS.lastPrinted, format: CoreXform.DateFormat }),
|
|
39
|
+
revision: new IntegerXform({ tag: PROPS.revision }),
|
|
40
|
+
version: new StringXform({ tag: PROPS.version }),
|
|
41
|
+
contentStatus: new StringXform({ tag: PROPS.contentStatus }),
|
|
42
|
+
contentType: new StringXform({ tag: PROPS.contentType }),
|
|
43
|
+
created: new DateXform({
|
|
44
|
+
tag: PROPS.created,
|
|
26
45
|
attrs: CoreXform.DateAttrs,
|
|
27
46
|
format: CoreXform.DateFormat
|
|
28
47
|
}),
|
|
29
|
-
|
|
30
|
-
tag:
|
|
48
|
+
modified: new DateXform({
|
|
49
|
+
tag: PROPS.modified,
|
|
31
50
|
attrs: CoreXform.DateAttrs,
|
|
32
51
|
format: CoreXform.DateFormat
|
|
33
52
|
})
|
|
@@ -36,22 +55,9 @@ class CoreXform extends BaseXform {
|
|
|
36
55
|
render(xmlStream, model) {
|
|
37
56
|
xmlStream.openXml(XmlStream.StdDocAttributes);
|
|
38
57
|
xmlStream.openNode("cp:coreProperties", CoreXform.CORE_PROPERTY_ATTRIBUTES);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.map["dc:description"].render(xmlStream, model.description);
|
|
43
|
-
this.map["dc:identifier"].render(xmlStream, model.identifier);
|
|
44
|
-
this.map["dc:language"].render(xmlStream, model.language);
|
|
45
|
-
this.map["cp:keywords"].render(xmlStream, model.keywords);
|
|
46
|
-
this.map["cp:category"].render(xmlStream, model.category);
|
|
47
|
-
this.map["cp:lastModifiedBy"].render(xmlStream, model.lastModifiedBy);
|
|
48
|
-
this.map["cp:lastPrinted"].render(xmlStream, model.lastPrinted);
|
|
49
|
-
this.map["cp:revision"].render(xmlStream, model.revision);
|
|
50
|
-
this.map["cp:version"].render(xmlStream, model.version);
|
|
51
|
-
this.map["cp:contentStatus"].render(xmlStream, model.contentStatus);
|
|
52
|
-
this.map["cp:contentType"].render(xmlStream, model.contentType);
|
|
53
|
-
this.map["dcterms:created"].render(xmlStream, model.created);
|
|
54
|
-
this.map["dcterms:modified"].render(xmlStream, model.modified);
|
|
58
|
+
for (const key of Object.keys(PROPS)) {
|
|
59
|
+
this.map[key].render(xmlStream, model[key]);
|
|
60
|
+
}
|
|
55
61
|
xmlStream.closeNode();
|
|
56
62
|
}
|
|
57
63
|
parseOpen(node) {
|
|
@@ -59,18 +65,13 @@ class CoreXform extends BaseXform {
|
|
|
59
65
|
this.parser.parseOpen(node);
|
|
60
66
|
return true;
|
|
61
67
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
this.parser = this.map[node.name];
|
|
68
|
-
if (this.parser) {
|
|
69
|
-
this.parser.parseOpen(node);
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(node)}`);
|
|
68
|
+
if (node.name !== "coreProperties") {
|
|
69
|
+
this.parser = this.map[node.name];
|
|
70
|
+
if (this.parser) {
|
|
71
|
+
this.parser.parseOpen(node);
|
|
72
|
+
}
|
|
73
73
|
}
|
|
74
|
+
return true;
|
|
74
75
|
}
|
|
75
76
|
parseText(text) {
|
|
76
77
|
if (this.parser) {
|
|
@@ -84,30 +85,17 @@ class CoreXform extends BaseXform {
|
|
|
84
85
|
}
|
|
85
86
|
return true;
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.model
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
language: this.map["dc:language"].model,
|
|
97
|
-
keywords: this.map["cp:keywords"].model,
|
|
98
|
-
category: this.map["cp:category"].model,
|
|
99
|
-
lastModifiedBy: this.map["cp:lastModifiedBy"].model,
|
|
100
|
-
lastPrinted: this.map["cp:lastPrinted"].model,
|
|
101
|
-
revision: this.map["cp:revision"].model,
|
|
102
|
-
contentStatus: this.map["cp:contentStatus"].model,
|
|
103
|
-
contentType: this.map["cp:contentType"].model,
|
|
104
|
-
created: this.map["dcterms:created"].model,
|
|
105
|
-
modified: this.map["dcterms:modified"].model
|
|
106
|
-
};
|
|
107
|
-
return false;
|
|
108
|
-
default:
|
|
109
|
-
throw new Error(`Unexpected xml node in parseClose: ${name}`);
|
|
88
|
+
if (name === "coreProperties") {
|
|
89
|
+
this.model = {};
|
|
90
|
+
for (const key of Object.keys(PROPS)) {
|
|
91
|
+
const val = this.map[key].model;
|
|
92
|
+
if (val !== undefined && val !== "") {
|
|
93
|
+
this.model[key] = val;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
110
97
|
}
|
|
98
|
+
return true;
|
|
111
99
|
}
|
|
112
100
|
}
|
|
113
101
|
CoreXform.DateFormat = function (dt) {
|
|
@@ -41,17 +41,15 @@ class ListXform extends BaseXform {
|
|
|
41
41
|
this.parser.parseOpen(node);
|
|
42
42
|
return true;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return true;
|
|
48
|
-
default:
|
|
49
|
-
if (this.childXform.parseOpen(node)) {
|
|
50
|
-
this.parser = this.childXform;
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
return false;
|
|
44
|
+
if (node.name === this.tag) {
|
|
45
|
+
this.model = [];
|
|
46
|
+
return true;
|
|
54
47
|
}
|
|
48
|
+
if (this.childXform.parseOpen(node)) {
|
|
49
|
+
this.parser = this.childXform;
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
55
53
|
}
|
|
56
54
|
parseText(text) {
|
|
57
55
|
if (this.parser) {
|
|
@@ -36,16 +36,15 @@ class SharedStringXform extends BaseXform {
|
|
|
36
36
|
xmlStream.closeNode();
|
|
37
37
|
}
|
|
38
38
|
parseOpen(node) {
|
|
39
|
-
const { name } = node;
|
|
40
39
|
if (this.parser) {
|
|
41
40
|
this.parser.parseOpen(node);
|
|
42
41
|
return true;
|
|
43
42
|
}
|
|
44
|
-
if (name === this.tag) {
|
|
43
|
+
if (node.name === this.tag) {
|
|
45
44
|
this.model = {};
|
|
46
45
|
return true;
|
|
47
46
|
}
|
|
48
|
-
this.parser = this.map[name];
|
|
47
|
+
this.parser = this.map[node.name];
|
|
49
48
|
if (this.parser) {
|
|
50
49
|
this.parser.parseOpen(node);
|
|
51
50
|
return true;
|
|
@@ -13,14 +13,12 @@ class TextXform extends BaseXform {
|
|
|
13
13
|
xmlStream.closeNode();
|
|
14
14
|
}
|
|
15
15
|
parseOpen(node) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return true;
|
|
21
|
-
default:
|
|
22
|
-
return false;
|
|
16
|
+
if (node.name === "t") {
|
|
17
|
+
this._text = [];
|
|
18
|
+
this.model = "";
|
|
19
|
+
return true;
|
|
23
20
|
}
|
|
21
|
+
return false;
|
|
24
22
|
}
|
|
25
23
|
parseText(text) {
|
|
26
24
|
this._text.push(text);
|
|
@@ -364,8 +364,10 @@ class XLSX {
|
|
|
364
364
|
case OOXML_PATHS.docPropsApp: {
|
|
365
365
|
const appXform = new AppXform();
|
|
366
366
|
const appProperties = await appXform.parseStream(stream);
|
|
367
|
-
|
|
368
|
-
|
|
367
|
+
if (appProperties) {
|
|
368
|
+
model.company = appProperties.company;
|
|
369
|
+
model.manager = appProperties.manager;
|
|
370
|
+
}
|
|
369
371
|
break;
|
|
370
372
|
}
|
|
371
373
|
case OOXML_PATHS.docPropsCore: {
|
|
@@ -827,8 +829,10 @@ class XLSX {
|
|
|
827
829
|
case OOXML_PATHS.docPropsApp: {
|
|
828
830
|
const appXform = new AppXform();
|
|
829
831
|
const appProperties = await appXform.parseStream(stream);
|
|
830
|
-
|
|
831
|
-
|
|
832
|
+
if (appProperties) {
|
|
833
|
+
model.company = appProperties.company;
|
|
834
|
+
model.manager = appProperties.manager;
|
|
835
|
+
}
|
|
832
836
|
break;
|
|
833
837
|
}
|
|
834
838
|
case OOXML_PATHS.docPropsCore: {
|