@hyperlex/mammoth 1.4.9-beta
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/.eslintrc.json +77 -0
- package/.github/ISSUE_TEMPLATE.md +12 -0
- package/.idea/mammoth.js.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.travis.yml +10 -0
- package/LICENSE +22 -0
- package/NEWS +373 -0
- package/README.md +883 -0
- package/bin/mammoth +38 -0
- package/browser/docx/files.js +14 -0
- package/browser/unzip.js +12 -0
- package/lib/document-to-html.js +453 -0
- package/lib/documents.js +238 -0
- package/lib/docx/body-reader.js +636 -0
- package/lib/docx/comments-reader.js +31 -0
- package/lib/docx/content-types-reader.js +58 -0
- package/lib/docx/document-xml-reader.js +26 -0
- package/lib/docx/docx-reader.js +222 -0
- package/lib/docx/files.js +67 -0
- package/lib/docx/notes-reader.js +28 -0
- package/lib/docx/numbering-xml.js +69 -0
- package/lib/docx/office-xml-reader.js +58 -0
- package/lib/docx/relationships-reader.js +43 -0
- package/lib/docx/style-map.js +75 -0
- package/lib/docx/styles-reader.js +70 -0
- package/lib/docx/uris.js +21 -0
- package/lib/html/ast.js +50 -0
- package/lib/html/index.js +41 -0
- package/lib/html/simplify.js +88 -0
- package/lib/images.js +29 -0
- package/lib/index.js +115 -0
- package/lib/main.js +63 -0
- package/lib/options-reader.js +98 -0
- package/lib/promises.js +42 -0
- package/lib/results.js +72 -0
- package/lib/style-reader.js +321 -0
- package/lib/styles/document-matchers.js +74 -0
- package/lib/styles/html-paths.js +81 -0
- package/lib/styles/parser/tokeniser.js +30 -0
- package/lib/transforms.js +61 -0
- package/lib/underline.js +11 -0
- package/lib/unzip.js +22 -0
- package/lib/writers/html-writer.js +160 -0
- package/lib/writers/index.js +14 -0
- package/lib/writers/markdown-writer.js +163 -0
- package/lib/xml/index.js +7 -0
- package/lib/xml/nodes.js +69 -0
- package/lib/xml/reader.js +83 -0
- package/lib/xml/writer.js +61 -0
- package/lib/zipfile.js +77 -0
- package/mammoth.browser.js +32950 -0
- package/mammoth.browser.min.js +18 -0
- package/package.json +65 -0
- package/test/.eslintrc.json +7 -0
- package/test/document-to-html.tests.js +834 -0
- package/test/docx/body-reader.tests.js +1342 -0
- package/test/docx/comments-reader.tests.js +52 -0
- package/test/docx/content-types-reader.tests.js +45 -0
- package/test/docx/document-matchers.js +37 -0
- package/test/docx/docx-reader.tests.js +179 -0
- package/test/docx/files.tests.js +94 -0
- package/test/docx/notes-reader.tests.js +35 -0
- package/test/docx/numbering-xml.tests.js +65 -0
- package/test/docx/office-xml-reader.tests.js +24 -0
- package/test/docx/relationships-reader.tests.js +65 -0
- package/test/docx/style-map.tests.js +112 -0
- package/test/docx/styles-reader.tests.js +133 -0
- package/test/docx/uris.tests.js +22 -0
- package/test/html/simplify.tests.js +134 -0
- package/test/html/write.tests.js +42 -0
- package/test/images.tests.js +34 -0
- package/test/main.tests.js +89 -0
- package/test/mammoth.tests.js +429 -0
- package/test/mocha.opts +1 -0
- package/test/options-reader.tests.js +63 -0
- package/test/results.tests.js +15 -0
- package/test/style-reader.tests.js +256 -0
- package/test/styles/document-matchers.tests.js +71 -0
- package/test/styles/html-paths.tests.js +20 -0
- package/test/styles/parser/tokeniser.tests.js +104 -0
- package/test/test-data/comments.docx +0 -0
- package/test/test-data/embedded-style-map.docx +0 -0
- package/test/test-data/empty.docx +0 -0
- package/test/test-data/empty.zip +0 -0
- package/test/test-data/endnotes.docx +0 -0
- package/test/test-data/external-picture.docx +0 -0
- package/test/test-data/footnote-hyperlink.docx +0 -0
- package/test/test-data/footnotes.docx +0 -0
- package/test/test-data/hello.zip +0 -0
- package/test/test-data/hyperlinks/word/_rels/document.xml.rels +10 -0
- package/test/test-data/hyperlinks/word/document.xml +18 -0
- package/test/test-data/simple/word/document.xml +18 -0
- package/test/test-data/simple-list.docx +0 -0
- package/test/test-data/single-paragraph.docx +0 -0
- package/test/test-data/strikethrough.docx +0 -0
- package/test/test-data/tables.docx +0 -0
- package/test/test-data/text-box.docx +0 -0
- package/test/test-data/tiny-picture-target-base-relative.docx +0 -0
- package/test/test-data/tiny-picture.docx +0 -0
- package/test/test-data/tiny-picture.png +0 -0
- package/test/test-data/underline.docx +0 -0
- package/test/test-data/utf8-bom.docx +0 -0
- package/test/test.js +11 -0
- package/test/testing.js +55 -0
- package/test/transforms.tests.js +125 -0
- package/test/unzip.tests.js +38 -0
- package/test/writers/html-writer.tests.js +133 -0
- package/test/writers/markdown-writer.tests.js +304 -0
- package/test/xml/reader.tests.js +85 -0
- package/test/xml/writer.tests.js +81 -0
- package/test/zipfile.tests.js +59 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
var util = require("util");
|
|
2
|
+
var _ = require("underscore");
|
|
3
|
+
|
|
4
|
+
exports.writer = writer;
|
|
5
|
+
|
|
6
|
+
function writer(options) {
|
|
7
|
+
options = options || {};
|
|
8
|
+
if (options.prettyPrint) {
|
|
9
|
+
return prettyWriter();
|
|
10
|
+
} else {
|
|
11
|
+
return simpleWriter();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var indentedElements = {
|
|
17
|
+
div: true,
|
|
18
|
+
p: true,
|
|
19
|
+
ul: true,
|
|
20
|
+
li: true
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
function prettyWriter() {
|
|
25
|
+
var indentationLevel = 0;
|
|
26
|
+
var indentation = " ";
|
|
27
|
+
var stack = [];
|
|
28
|
+
var start = true;
|
|
29
|
+
var inText = false;
|
|
30
|
+
|
|
31
|
+
var writer = simpleWriter();
|
|
32
|
+
|
|
33
|
+
function open(tagName, attributes) {
|
|
34
|
+
if (indentedElements[tagName]) {
|
|
35
|
+
indent();
|
|
36
|
+
}
|
|
37
|
+
stack.push(tagName);
|
|
38
|
+
writer.open(tagName, attributes);
|
|
39
|
+
if (indentedElements[tagName]) {
|
|
40
|
+
indentationLevel++;
|
|
41
|
+
}
|
|
42
|
+
start = false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function close(tagName) {
|
|
46
|
+
if (indentedElements[tagName]) {
|
|
47
|
+
indentationLevel--;
|
|
48
|
+
indent();
|
|
49
|
+
}
|
|
50
|
+
stack.pop();
|
|
51
|
+
writer.close(tagName);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function text(value) {
|
|
55
|
+
startText();
|
|
56
|
+
var text = isInPre() ? value : value.replace("\n", "\n" + indentation);
|
|
57
|
+
writer.text(text);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function selfClosing(tagName, attributes) {
|
|
61
|
+
indent();
|
|
62
|
+
writer.selfClosing(tagName, attributes);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function insideIndentedElement() {
|
|
66
|
+
return stack.length === 0 || indentedElements[stack[stack.length - 1]];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function startText() {
|
|
70
|
+
if (!inText) {
|
|
71
|
+
indent();
|
|
72
|
+
inText = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function indent() {
|
|
77
|
+
inText = false;
|
|
78
|
+
if (!start && insideIndentedElement() && !isInPre()) {
|
|
79
|
+
writer._append("\n");
|
|
80
|
+
for (var i = 0; i < indentationLevel; i++) {
|
|
81
|
+
writer._append(indentation);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function isInPre() {
|
|
87
|
+
return _.some(stack, function(tagName) {
|
|
88
|
+
return tagName === "pre";
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
asString: writer.asString,
|
|
94
|
+
open: open,
|
|
95
|
+
close: close,
|
|
96
|
+
text: text,
|
|
97
|
+
selfClosing: selfClosing
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
function simpleWriter() {
|
|
103
|
+
var fragments = [];
|
|
104
|
+
|
|
105
|
+
function open(tagName, attributes) {
|
|
106
|
+
var attributeString = generateAttributeString(attributes);
|
|
107
|
+
fragments.push(util.format("<%s%s>", tagName, attributeString));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function close(tagName) {
|
|
111
|
+
fragments.push(util.format("</%s>", tagName));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function selfClosing(tagName, attributes) {
|
|
115
|
+
var attributeString = generateAttributeString(attributes);
|
|
116
|
+
fragments.push(util.format("<%s%s />", tagName, attributeString));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function generateAttributeString(attributes) {
|
|
120
|
+
return _.map(attributes, function(value, key) {
|
|
121
|
+
return util.format(' %s="%s"', key, escapeHtmlAttribute(value));
|
|
122
|
+
}).join("");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function text(value) {
|
|
126
|
+
fragments.push(escapeHtmlText(value));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function append(html) {
|
|
130
|
+
fragments.push(html);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function asString() {
|
|
134
|
+
return fragments.join("");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
asString: asString,
|
|
139
|
+
open: open,
|
|
140
|
+
close: close,
|
|
141
|
+
text: text,
|
|
142
|
+
selfClosing: selfClosing,
|
|
143
|
+
_append: append
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function escapeHtmlText(value) {
|
|
148
|
+
return value
|
|
149
|
+
.replace(/&/g, '&')
|
|
150
|
+
.replace(/</g, '<')
|
|
151
|
+
.replace(/>/g, '>');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function escapeHtmlAttribute(value) {
|
|
155
|
+
return value
|
|
156
|
+
.replace(/&/g, '&')
|
|
157
|
+
.replace(/"/g, '"')
|
|
158
|
+
.replace(/</g, '<')
|
|
159
|
+
.replace(/>/g, '>');
|
|
160
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
var htmlWriter = require("./html-writer");
|
|
2
|
+
var markdownWriter = require("./markdown-writer");
|
|
3
|
+
|
|
4
|
+
exports.writer = writer;
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function writer(options) {
|
|
8
|
+
options = options || {};
|
|
9
|
+
if (options.outputFormat === "markdown") {
|
|
10
|
+
return markdownWriter.writer();
|
|
11
|
+
} else {
|
|
12
|
+
return htmlWriter.writer(options);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
var _ = require("underscore");
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function symmetricMarkdownElement(end) {
|
|
5
|
+
return markdownElement(end, end);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function markdownElement(start, end) {
|
|
9
|
+
return function() {
|
|
10
|
+
return {start: start, end: end};
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function markdownLink(attributes) {
|
|
15
|
+
var href = attributes.href || "";
|
|
16
|
+
if (href) {
|
|
17
|
+
return {
|
|
18
|
+
start: "[",
|
|
19
|
+
end: "](" + href + ")",
|
|
20
|
+
anchorPosition: "before"
|
|
21
|
+
};
|
|
22
|
+
} else {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function markdownImage(attributes) {
|
|
28
|
+
var src = attributes.src || "";
|
|
29
|
+
var altText = attributes.alt || "";
|
|
30
|
+
if (src || altText) {
|
|
31
|
+
return {start: ""};
|
|
32
|
+
} else {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function markdownList(options) {
|
|
38
|
+
return function(attributes, list) {
|
|
39
|
+
return {
|
|
40
|
+
start: list ? "\n" : "",
|
|
41
|
+
end: list ? "" : "\n",
|
|
42
|
+
list: {
|
|
43
|
+
isOrdered: options.isOrdered,
|
|
44
|
+
indent: list ? list.indent + 1 : 0,
|
|
45
|
+
count: 0
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function markdownListItem(attributes, list, listItem) {
|
|
52
|
+
list = list || {indent: 0, isOrdered: false, count: 0};
|
|
53
|
+
list.count++;
|
|
54
|
+
listItem.hasClosed = false;
|
|
55
|
+
|
|
56
|
+
var bullet = list.isOrdered ? list.count + "." : "-";
|
|
57
|
+
var start = repeatString("\t", list.indent) + bullet + " ";
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
start: start,
|
|
61
|
+
end: function() {
|
|
62
|
+
if (!listItem.hasClosed) {
|
|
63
|
+
listItem.hasClosed = true;
|
|
64
|
+
return "\n";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
var htmlToMarkdown = {
|
|
71
|
+
"p": markdownElement("", "\n\n"),
|
|
72
|
+
"br": markdownElement("", " \n"),
|
|
73
|
+
"ul": markdownList({isOrdered: false}),
|
|
74
|
+
"ol": markdownList({isOrdered: true}),
|
|
75
|
+
"li": markdownListItem,
|
|
76
|
+
"strong": symmetricMarkdownElement("__"),
|
|
77
|
+
"em": symmetricMarkdownElement("*"),
|
|
78
|
+
"a": markdownLink,
|
|
79
|
+
"img": markdownImage
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
(function() {
|
|
83
|
+
for (var i = 1; i <= 6; i++) {
|
|
84
|
+
htmlToMarkdown["h" + i] = markdownElement(repeatString("#", i) + " ", "\n\n");
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
87
|
+
|
|
88
|
+
function repeatString(value, count) {
|
|
89
|
+
return new Array(count + 1).join(value);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function markdownWriter() {
|
|
93
|
+
var fragments = [];
|
|
94
|
+
var elementStack = [];
|
|
95
|
+
var list = null;
|
|
96
|
+
var listItem = {};
|
|
97
|
+
|
|
98
|
+
function open(tagName, attributes) {
|
|
99
|
+
attributes = attributes || {};
|
|
100
|
+
|
|
101
|
+
var createElement = htmlToMarkdown[tagName] || function() {
|
|
102
|
+
return {};
|
|
103
|
+
};
|
|
104
|
+
var element = createElement(attributes, list, listItem);
|
|
105
|
+
elementStack.push({end: element.end, list: list});
|
|
106
|
+
|
|
107
|
+
if (element.list) {
|
|
108
|
+
list = element.list;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
var anchorBeforeStart = element.anchorPosition === "before";
|
|
112
|
+
if (anchorBeforeStart) {
|
|
113
|
+
writeAnchor(attributes);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
fragments.push(element.start || "");
|
|
117
|
+
if (!anchorBeforeStart) {
|
|
118
|
+
writeAnchor(attributes);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function writeAnchor(attributes) {
|
|
123
|
+
if (attributes.id) {
|
|
124
|
+
fragments.push('<a id="' + attributes.id + '"></a>');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function close(tagName) {
|
|
129
|
+
var element = elementStack.pop();
|
|
130
|
+
list = element.list;
|
|
131
|
+
var end = _.isFunction(element.end) ? element.end() : element.end;
|
|
132
|
+
fragments.push(end || "");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function selfClosing(tagName, attributes) {
|
|
136
|
+
open(tagName, attributes);
|
|
137
|
+
close(tagName);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function text(value) {
|
|
141
|
+
fragments.push(escapeMarkdown(value));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function asString() {
|
|
145
|
+
return fragments.join("");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
asString: asString,
|
|
150
|
+
open: open,
|
|
151
|
+
close: close,
|
|
152
|
+
text: text,
|
|
153
|
+
selfClosing: selfClosing
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
exports.writer = markdownWriter;
|
|
158
|
+
|
|
159
|
+
function escapeMarkdown(value) {
|
|
160
|
+
return value
|
|
161
|
+
.replace(/\\/g, '\\\\')
|
|
162
|
+
.replace(/([\`\*_\{\}\[\]\(\)\#\+\-\.\!])/g, '\\$1');
|
|
163
|
+
}
|
package/lib/xml/index.js
ADDED
package/lib/xml/nodes.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
var _ = require("underscore");
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
exports.Element = Element;
|
|
5
|
+
exports.element = function(name, attributes, children) {
|
|
6
|
+
return new Element(name, attributes, children);
|
|
7
|
+
};
|
|
8
|
+
exports.text = function(value) {
|
|
9
|
+
return {
|
|
10
|
+
type: "text",
|
|
11
|
+
value: value
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var emptyElement = {
|
|
17
|
+
first: function() {
|
|
18
|
+
return null;
|
|
19
|
+
},
|
|
20
|
+
firstOrEmpty: function() {
|
|
21
|
+
return emptyElement;
|
|
22
|
+
},
|
|
23
|
+
attributes: {}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function Element(name, attributes, children) {
|
|
27
|
+
this.type = "element";
|
|
28
|
+
this.name = name;
|
|
29
|
+
this.attributes = attributes || {};
|
|
30
|
+
this.children = children || [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Element.prototype.first = function(name) {
|
|
34
|
+
return _.find(this.children, function(child) {
|
|
35
|
+
return child.name === name;
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
Element.prototype.firstOrEmpty = function(name) {
|
|
40
|
+
return this.first(name) || emptyElement;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
Element.prototype.getElementsByTagName = function(name) {
|
|
44
|
+
var elements = _.filter(this.children, function(child) {
|
|
45
|
+
return child.name === name;
|
|
46
|
+
});
|
|
47
|
+
return toElementList(elements);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
Element.prototype.text = function() {
|
|
51
|
+
if (this.children.length === 0) {
|
|
52
|
+
return "";
|
|
53
|
+
} else if (this.children.length !== 1 || this.children[0].type !== "text") {
|
|
54
|
+
throw new Error("Not implemented");
|
|
55
|
+
}
|
|
56
|
+
return this.children[0].value;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
var elementListPrototype = {
|
|
60
|
+
getElementsByTagName: function(name) {
|
|
61
|
+
return toElementList(_.flatten(this.map(function(element) {
|
|
62
|
+
return element.getElementsByTagName(name);
|
|
63
|
+
}, true)));
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function toElementList(array) {
|
|
68
|
+
return _.extend(array, elementListPrototype);
|
|
69
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
var promises = require("../promises");
|
|
2
|
+
var sax = require("sax");
|
|
3
|
+
var _ = require("underscore");
|
|
4
|
+
|
|
5
|
+
var nodes = require("./nodes");
|
|
6
|
+
var Element = nodes.Element;
|
|
7
|
+
|
|
8
|
+
exports.readString = readString;
|
|
9
|
+
|
|
10
|
+
function readString(xmlString, namespaceMap) {
|
|
11
|
+
namespaceMap = namespaceMap || {};
|
|
12
|
+
|
|
13
|
+
var finished = false;
|
|
14
|
+
var parser = sax.parser(true, {xmlns: true, position: false});
|
|
15
|
+
|
|
16
|
+
var rootElement = {children: []};
|
|
17
|
+
var currentElement = rootElement;
|
|
18
|
+
var stack = [];
|
|
19
|
+
|
|
20
|
+
var deferred = promises.defer();
|
|
21
|
+
|
|
22
|
+
parser.onopentag = function(node) {
|
|
23
|
+
var attributes = mapObject(node.attributes, function(attribute) {
|
|
24
|
+
return attribute.value;
|
|
25
|
+
}, mapName);
|
|
26
|
+
|
|
27
|
+
var element = new Element(mapName(node), attributes);
|
|
28
|
+
currentElement.children.push(element);
|
|
29
|
+
stack.push(currentElement);
|
|
30
|
+
currentElement = element;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function mapName(node) {
|
|
34
|
+
if (node.uri) {
|
|
35
|
+
var mappedPrefix = namespaceMap[node.uri];
|
|
36
|
+
var prefix;
|
|
37
|
+
if (mappedPrefix) {
|
|
38
|
+
prefix = mappedPrefix + ":";
|
|
39
|
+
} else {
|
|
40
|
+
prefix = "{" + node.uri + "}";
|
|
41
|
+
}
|
|
42
|
+
return prefix + node.local;
|
|
43
|
+
} else {
|
|
44
|
+
return node.local;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
parser.onclosetag = function(node) {
|
|
49
|
+
currentElement = stack.pop();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
parser.ontext = function(text) {
|
|
53
|
+
if (currentElement !== rootElement) {
|
|
54
|
+
currentElement.children.push(nodes.text(text));
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
parser.onend = function() {
|
|
59
|
+
if (!finished) {
|
|
60
|
+
finished = true;
|
|
61
|
+
deferred.resolve(rootElement.children[0]);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
parser.onerror = function(error) {
|
|
66
|
+
if (!finished) {
|
|
67
|
+
finished = true;
|
|
68
|
+
deferred.reject(error);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
parser.write(xmlString).close();
|
|
73
|
+
|
|
74
|
+
return deferred.promise;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function mapObject(input, valueFunc, keyFunc) {
|
|
78
|
+
return _.reduce(input, function(result, value, key) {
|
|
79
|
+
var mappedKey = keyFunc(value, key, input);
|
|
80
|
+
result[mappedKey] = valueFunc(value, key, input);
|
|
81
|
+
return result;
|
|
82
|
+
}, {});
|
|
83
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
var _ = require("underscore");
|
|
2
|
+
var xmlbuilder = require("xmlbuilder");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
exports.writeString = writeString;
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
function writeString(root, namespaces) {
|
|
9
|
+
var uriToPrefix = _.invert(namespaces);
|
|
10
|
+
|
|
11
|
+
var nodeWriters = {
|
|
12
|
+
element: writeElement,
|
|
13
|
+
text: writeTextNode
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function writeNode(builder, node) {
|
|
17
|
+
return nodeWriters[node.type](builder, node);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function writeElement(builder, element) {
|
|
21
|
+
var elementBuilder = builder.element(mapElementName(element.name), element.attributes);
|
|
22
|
+
element.children.forEach(function(child) {
|
|
23
|
+
writeNode(elementBuilder, child);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function mapElementName(name) {
|
|
28
|
+
var longFormMatch = /^\{(.*)\}(.*)$/.exec(name);
|
|
29
|
+
if (longFormMatch) {
|
|
30
|
+
var prefix = uriToPrefix[longFormMatch[1]];
|
|
31
|
+
return prefix + (prefix === "" ? "" : ":") + longFormMatch[2];
|
|
32
|
+
} else {
|
|
33
|
+
return name;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function writeDocument(root) {
|
|
38
|
+
var builder = xmlbuilder
|
|
39
|
+
.create(mapElementName(root.name), {
|
|
40
|
+
version: '1.0',
|
|
41
|
+
encoding: 'UTF-8',
|
|
42
|
+
standalone: true
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
_.forEach(namespaces, function(uri, prefix) {
|
|
46
|
+
var key = "xmlns" + (prefix === "" ? "" : ":" + prefix);
|
|
47
|
+
builder.attribute(key, uri);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
root.children.forEach(function(child) {
|
|
51
|
+
writeNode(builder, child);
|
|
52
|
+
});
|
|
53
|
+
return builder.end();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return writeDocument(root);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function writeTextNode(builder, node) {
|
|
60
|
+
builder.text(node.value);
|
|
61
|
+
}
|
package/lib/zipfile.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var JSZip = require("jszip");
|
|
2
|
+
|
|
3
|
+
var promises = require("./promises");
|
|
4
|
+
|
|
5
|
+
exports.openArrayBuffer = openArrayBuffer;
|
|
6
|
+
exports.splitPath = splitPath;
|
|
7
|
+
exports.joinPath = joinPath;
|
|
8
|
+
|
|
9
|
+
function openArrayBuffer(arrayBuffer) {
|
|
10
|
+
var zipFile = new JSZip(arrayBuffer);
|
|
11
|
+
function exists(name) {
|
|
12
|
+
return zipFile.file(name) !== null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function read(name, encoding) {
|
|
16
|
+
var array = zipFile.file(name).asUint8Array();
|
|
17
|
+
var buffer = uint8ArrayToBuffer(array);
|
|
18
|
+
if (encoding) {
|
|
19
|
+
return promises.when(buffer.toString(encoding));
|
|
20
|
+
} else {
|
|
21
|
+
return promises.when(buffer);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function write(name, contents) {
|
|
26
|
+
zipFile.file(name, contents);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function toBuffer() {
|
|
30
|
+
return zipFile.generate({type: "nodebuffer"});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
exists: exists,
|
|
35
|
+
read: read,
|
|
36
|
+
write: write,
|
|
37
|
+
toBuffer: toBuffer
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function uint8ArrayToBuffer(array) {
|
|
42
|
+
if (Buffer.from && Buffer.from !== Uint8Array.from) {
|
|
43
|
+
return Buffer.from(array);
|
|
44
|
+
} else {
|
|
45
|
+
return new Buffer(array);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function splitPath(path) {
|
|
50
|
+
var lastIndex = path.lastIndexOf("/");
|
|
51
|
+
if (lastIndex === -1) {
|
|
52
|
+
return {dirname: "", basename: path};
|
|
53
|
+
} else {
|
|
54
|
+
return {
|
|
55
|
+
dirname: path.substring(0, lastIndex),
|
|
56
|
+
basename: path.substring(lastIndex + 1)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function joinPath() {
|
|
62
|
+
var nonEmptyPaths = Array.prototype.filter.call(arguments, function(path) {
|
|
63
|
+
return path;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
var relevantPaths = [];
|
|
67
|
+
|
|
68
|
+
nonEmptyPaths.forEach(function(path) {
|
|
69
|
+
if (/^\//.test(path)) {
|
|
70
|
+
relevantPaths = [path];
|
|
71
|
+
} else {
|
|
72
|
+
relevantPaths.push(path);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return relevantPaths.join("/");
|
|
77
|
+
}
|