@cj-tech-master/excelts 4.2.2 → 4.2.3-canary.20260122073152.a9bb6b0
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/csv/csv-core.d.ts +0 -9
- package/dist/browser/modules/csv/csv.browser.js +3 -3
- 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/utils/passthrough-manager.d.ts +77 -0
- package/dist/browser/modules/excel/utils/passthrough-manager.js +129 -0
- package/dist/browser/modules/excel/workbook.d.ts +8 -0
- package/dist/browser/modules/excel/workbook.js +9 -1
- package/dist/browser/modules/excel/worksheet.d.ts +4 -0
- package/dist/browser/modules/excel/worksheet.js +4 -1
- package/dist/browser/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +16 -10
- 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/pivot-table/pivot-table-xform.d.ts +34 -11
- package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +256 -86
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +38 -11
- 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.d.ts +36 -1
- package/dist/browser/modules/excel/xlsx/xlsx.browser.js +213 -127
- package/dist/browser/modules/stream/streams.browser.js +0 -3
- package/dist/cjs/modules/csv/csv.browser.js +3 -3
- package/dist/cjs/modules/excel/utils/parse-sax.js +32 -13
- package/dist/cjs/modules/excel/utils/passthrough-manager.js +133 -0
- package/dist/cjs/modules/excel/workbook.js +9 -1
- package/dist/cjs/modules/excel/worksheet.js +4 -1
- package/dist/cjs/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +16 -10
- 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/pivot-table/pivot-table-xform.js +256 -86
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +38 -11
- 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 +213 -127
- package/dist/cjs/modules/stream/streams.browser.js +0 -3
- package/dist/esm/modules/csv/csv.browser.js +3 -3
- package/dist/esm/modules/excel/utils/parse-sax.js +32 -13
- package/dist/esm/modules/excel/utils/passthrough-manager.js +129 -0
- package/dist/esm/modules/excel/workbook.js +9 -1
- package/dist/esm/modules/excel/worksheet.js +4 -1
- package/dist/esm/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +16 -10
- 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/pivot-table/pivot-table-xform.js +256 -86
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +38 -11
- 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 +213 -127
- package/dist/esm/modules/stream/streams.browser.js +0 -3
- package/dist/iife/excelts.iife.js +603 -333
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +25 -52
- package/dist/types/modules/csv/csv-core.d.ts +0 -9
- package/dist/types/modules/excel/utils/parse-sax.d.ts +3 -0
- package/dist/types/modules/excel/utils/passthrough-manager.d.ts +77 -0
- package/dist/types/modules/excel/workbook.d.ts +8 -0
- package/dist/types/modules/excel/worksheet.d.ts +4 -0
- package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +34 -11
- package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +36 -1
- package/package.json +2 -2
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PassthroughManager - Manages passthrough files for round-trip preservation
|
|
4
|
+
*
|
|
5
|
+
* This module handles files that are not fully parsed by the library but need to be
|
|
6
|
+
* preserved during read/write cycles (e.g., charts, sparklines, slicers).
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PassthroughManager = void 0;
|
|
10
|
+
// Pre-compiled regex patterns for content type detection (performance optimization)
|
|
11
|
+
const chartXmlRegex = /^xl\/charts\/chart\d+\.xml$/;
|
|
12
|
+
const chartStyleXmlRegex = /^xl\/charts\/style\d+\.xml$/;
|
|
13
|
+
const chartColorsXmlRegex = /^xl\/charts\/colors\d+\.xml$/;
|
|
14
|
+
/**
|
|
15
|
+
* Content type definitions for passthrough files
|
|
16
|
+
*/
|
|
17
|
+
const PASSTHROUGH_CONTENT_TYPES = new Map([
|
|
18
|
+
[chartXmlRegex, "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"],
|
|
19
|
+
[chartStyleXmlRegex, "application/vnd.ms-office.chartstyle+xml"],
|
|
20
|
+
[chartColorsXmlRegex, "application/vnd.ms-office.chartcolorstyle+xml"]
|
|
21
|
+
]);
|
|
22
|
+
/**
|
|
23
|
+
* Passthrough path prefixes that should be preserved
|
|
24
|
+
*/
|
|
25
|
+
const PASSTHROUGH_PREFIXES = ["xl/charts/"];
|
|
26
|
+
/**
|
|
27
|
+
* PassthroughManager handles storage and retrieval of passthrough files
|
|
28
|
+
* that need to be preserved during Excel read/write cycles.
|
|
29
|
+
*/
|
|
30
|
+
class PassthroughManager {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.files = new Map();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if a path should be treated as passthrough
|
|
36
|
+
*/
|
|
37
|
+
static isPassthroughPath(path) {
|
|
38
|
+
return PASSTHROUGH_PREFIXES.some(prefix => path.startsWith(prefix));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get the content type for a passthrough file path
|
|
42
|
+
* @returns Content type string or undefined if unknown
|
|
43
|
+
*/
|
|
44
|
+
static getContentType(path) {
|
|
45
|
+
// Chart relationships are handled by Default extension="rels"
|
|
46
|
+
if (path.startsWith("xl/charts/_rels/")) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
for (const [regex, contentType] of PASSTHROUGH_CONTENT_TYPES) {
|
|
50
|
+
if (regex.test(path)) {
|
|
51
|
+
return contentType;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Add a file to passthrough storage
|
|
58
|
+
*/
|
|
59
|
+
add(path, data) {
|
|
60
|
+
this.files.set(path, data);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get a file from passthrough storage
|
|
64
|
+
*/
|
|
65
|
+
get(path) {
|
|
66
|
+
return this.files.get(path);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if a file exists in passthrough storage
|
|
70
|
+
*/
|
|
71
|
+
has(path) {
|
|
72
|
+
return this.files.has(path);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get all stored paths
|
|
76
|
+
*/
|
|
77
|
+
getPaths() {
|
|
78
|
+
return [...this.files.keys()];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get all files as a record (for serialization)
|
|
82
|
+
*/
|
|
83
|
+
toRecord() {
|
|
84
|
+
const record = {};
|
|
85
|
+
for (const [path, data] of this.files) {
|
|
86
|
+
record[path] = data;
|
|
87
|
+
}
|
|
88
|
+
return record;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Load files from a record (for deserialization)
|
|
92
|
+
*/
|
|
93
|
+
fromRecord(record) {
|
|
94
|
+
this.files.clear();
|
|
95
|
+
for (const [path, data] of Object.entries(record)) {
|
|
96
|
+
this.files.set(path, data);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get content types for all stored files that have known types
|
|
101
|
+
*/
|
|
102
|
+
getContentTypes() {
|
|
103
|
+
const contentTypes = [];
|
|
104
|
+
for (const path of this.files.keys()) {
|
|
105
|
+
const contentType = PassthroughManager.getContentType(path);
|
|
106
|
+
if (contentType) {
|
|
107
|
+
contentTypes.push({ partName: path, contentType });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return contentTypes;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Write all passthrough files to a ZIP writer
|
|
114
|
+
*/
|
|
115
|
+
writeToZip(zip) {
|
|
116
|
+
for (const [path, data] of this.files) {
|
|
117
|
+
zip.append(data, { name: path });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Clear all stored files
|
|
122
|
+
*/
|
|
123
|
+
clear() {
|
|
124
|
+
this.files.clear();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get the number of stored files
|
|
128
|
+
*/
|
|
129
|
+
get size() {
|
|
130
|
+
return this.files.size;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
exports.PassthroughManager = PassthroughManager;
|
|
@@ -41,6 +41,8 @@ class Workbook {
|
|
|
41
41
|
this.views = [];
|
|
42
42
|
this.media = [];
|
|
43
43
|
this.pivotTables = [];
|
|
44
|
+
this._passthrough = {};
|
|
45
|
+
this._rawDrawings = {};
|
|
44
46
|
this._definedNames = new defined_names_1.DefinedNames();
|
|
45
47
|
}
|
|
46
48
|
// ===========================================================================
|
|
@@ -254,7 +256,9 @@ class Workbook {
|
|
|
254
256
|
themes: this._themes,
|
|
255
257
|
media: this.media,
|
|
256
258
|
pivotTables: this.pivotTables,
|
|
257
|
-
calcProperties: this.calcProperties
|
|
259
|
+
calcProperties: this.calcProperties,
|
|
260
|
+
passthrough: this._passthrough,
|
|
261
|
+
rawDrawings: this._rawDrawings
|
|
258
262
|
};
|
|
259
263
|
}
|
|
260
264
|
set model(value) {
|
|
@@ -295,6 +299,10 @@ class Workbook {
|
|
|
295
299
|
// Handle pivot tables - either newly created or loaded from file
|
|
296
300
|
// Loaded pivot tables come from loadedPivotTables after reconciliation
|
|
297
301
|
this.pivotTables = value.pivotTables || value.loadedPivotTables || [];
|
|
302
|
+
// Preserve passthrough files (charts, etc.) for round-trip preservation
|
|
303
|
+
this._passthrough = value.passthrough || {};
|
|
304
|
+
// Preserve raw drawing data for drawings with chart references
|
|
305
|
+
this._rawDrawings = value.rawDrawings || {};
|
|
298
306
|
}
|
|
299
307
|
}
|
|
300
308
|
exports.Workbook = Workbook;
|
|
@@ -900,7 +900,8 @@ class Worksheet {
|
|
|
900
900
|
tables: Object.values(this.tables).map(table => table.model),
|
|
901
901
|
pivotTables: this.pivotTables,
|
|
902
902
|
conditionalFormattings: this.conditionalFormattings,
|
|
903
|
-
formControls: this.formControls.map(fc => fc.model)
|
|
903
|
+
formControls: this.formControls.map(fc => fc.model),
|
|
904
|
+
drawing: this._drawing
|
|
904
905
|
};
|
|
905
906
|
// =================================================
|
|
906
907
|
// columns
|
|
@@ -968,6 +969,8 @@ class Worksheet {
|
|
|
968
969
|
this.conditionalFormattings = value.conditionalFormattings;
|
|
969
970
|
// Form controls are currently write-only (not parsed from XLSX)
|
|
970
971
|
this.formControls = [];
|
|
972
|
+
// Preserve loaded drawing data (charts, etc.)
|
|
973
|
+
this._drawing = value.drawing;
|
|
971
974
|
}
|
|
972
975
|
}
|
|
973
976
|
exports.Worksheet = Worksheet;
|
|
@@ -13,7 +13,7 @@ class AppXform extends base_xform_1.BaseXform {
|
|
|
13
13
|
Company: new string_xform_1.StringXform({ tag: "Company" }),
|
|
14
14
|
Manager: new string_xform_1.StringXform({ tag: "Manager" }),
|
|
15
15
|
HeadingPairs: new app_heading_pairs_xform_1.AppHeadingPairsXform(),
|
|
16
|
-
|
|
16
|
+
TitlesOfParts: new app_titles_of_parts_xform_1.AppTitlesOfPartsXform()
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
render(xmlStream, model) {
|
|
@@ -23,7 +23,7 @@ class AppXform extends base_xform_1.BaseXform {
|
|
|
23
23
|
xmlStream.leafNode("DocSecurity", undefined, "0");
|
|
24
24
|
xmlStream.leafNode("ScaleCrop", undefined, "false");
|
|
25
25
|
this.map.HeadingPairs.render(xmlStream, model.worksheets);
|
|
26
|
-
this.map.
|
|
26
|
+
this.map.TitlesOfParts.render(xmlStream, model.worksheets);
|
|
27
27
|
this.map.Company.render(xmlStream, model.company || "");
|
|
28
28
|
this.map.Manager.render(xmlStream, model.manager);
|
|
29
29
|
xmlStream.leafNode("LinksUpToDate", undefined, "false");
|
|
@@ -65,7 +65,7 @@ class AppXform extends base_xform_1.BaseXform {
|
|
|
65
65
|
switch (name) {
|
|
66
66
|
case "Properties":
|
|
67
67
|
this.model = {
|
|
68
|
-
worksheets: this.map.
|
|
68
|
+
worksheets: this.map.TitlesOfParts.model,
|
|
69
69
|
company: this.map.Company.model,
|
|
70
70
|
manager: this.map.Manager.model
|
|
71
71
|
};
|
|
@@ -96,11 +96,16 @@ class ContentTypesXform extends base_xform_1.BaseXform {
|
|
|
96
96
|
});
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
|
-
|
|
99
|
+
// VML extension is needed for comments or form controls
|
|
100
|
+
const hasComments = model.commentRefs && model.commentRefs.length > 0;
|
|
101
|
+
const hasFormControls = model.formControlRefs && model.formControlRefs.length > 0;
|
|
102
|
+
if (hasComments || hasFormControls) {
|
|
100
103
|
xmlStream.leafNode("Default", {
|
|
101
104
|
Extension: "vml",
|
|
102
105
|
ContentType: "application/vnd.openxmlformats-officedocument.vmlDrawing"
|
|
103
106
|
});
|
|
107
|
+
}
|
|
108
|
+
if (hasComments) {
|
|
104
109
|
model.commentRefs.forEach(({ commentName }) => {
|
|
105
110
|
xmlStream.leafNode("Override", {
|
|
106
111
|
PartName: (0, ooxml_paths_1.toContentTypesPartName)((0, ooxml_paths_1.commentsPathFromName)(commentName)),
|
|
@@ -108,15 +113,7 @@ class ContentTypesXform extends base_xform_1.BaseXform {
|
|
|
108
113
|
});
|
|
109
114
|
});
|
|
110
115
|
}
|
|
111
|
-
|
|
112
|
-
if (model.formControlRefs) {
|
|
113
|
-
// Ensure vml extension is declared (may already be declared for comments)
|
|
114
|
-
if (!model.commentRefs) {
|
|
115
|
-
xmlStream.leafNode("Default", {
|
|
116
|
-
Extension: "vml",
|
|
117
|
-
ContentType: "application/vnd.openxmlformats-officedocument.vmlDrawing"
|
|
118
|
-
});
|
|
119
|
-
}
|
|
116
|
+
if (hasFormControls) {
|
|
120
117
|
for (const ctrlPropId of model.formControlRefs) {
|
|
121
118
|
xmlStream.leafNode("Override", {
|
|
122
119
|
PartName: (0, ooxml_paths_1.toContentTypesPartName)((0, ooxml_paths_1.ctrlPropPath)(ctrlPropId)),
|
|
@@ -124,6 +121,15 @@ class ContentTypesXform extends base_xform_1.BaseXform {
|
|
|
124
121
|
});
|
|
125
122
|
}
|
|
126
123
|
}
|
|
124
|
+
// Add passthrough content types (charts, etc.)
|
|
125
|
+
if (model.passthroughContentTypes) {
|
|
126
|
+
for (const { partName, contentType } of model.passthroughContentTypes) {
|
|
127
|
+
xmlStream.leafNode("Override", {
|
|
128
|
+
PartName: (0, ooxml_paths_1.toContentTypesPartName)(partName),
|
|
129
|
+
ContentType: contentType
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
127
133
|
xmlStream.leafNode("Override", {
|
|
128
134
|
PartName: (0, ooxml_paths_1.toContentTypesPartName)(ooxml_paths_1.OOXML_PATHS.docPropsCore),
|
|
129
135
|
ContentType: "application/vnd.openxmlformats-package.core-properties+xml"
|
|
@@ -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) {
|