@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,429 @@
|
|
|
1
|
+
var assert = require("assert");
|
|
2
|
+
var path = require("path");
|
|
3
|
+
var fs = require("fs");
|
|
4
|
+
var _ = require("underscore");
|
|
5
|
+
|
|
6
|
+
var mammoth = require("../");
|
|
7
|
+
var promises = require("../lib/promises");
|
|
8
|
+
var results = require("../lib/results");
|
|
9
|
+
|
|
10
|
+
var testing = require("./testing");
|
|
11
|
+
var test = require("./test")(module);
|
|
12
|
+
var testData = testing.testData;
|
|
13
|
+
var createFakeDocxFile = testing.createFakeDocxFile;
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
test('should convert docx containing one paragraph to single p element', function() {
|
|
17
|
+
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
|
|
18
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
19
|
+
assert.equal(result.value, "<p>Walking on imported air</p>");
|
|
20
|
+
assert.deepEqual(result.messages, []);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('should convert docx represented by a Buffer', function() {
|
|
25
|
+
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
|
|
26
|
+
return promises.nfcall(fs.readFile, docxPath)
|
|
27
|
+
.then(function(buffer) {
|
|
28
|
+
return mammoth.convertToHtml({buffer: buffer});
|
|
29
|
+
})
|
|
30
|
+
.then(function(result) {
|
|
31
|
+
assert.equal(result.value, "<p>Walking on imported air</p>");
|
|
32
|
+
assert.deepEqual(result.messages, []);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('should read docx xml files with unicode byte order mark', function() {
|
|
37
|
+
var docxPath = path.join(__dirname, "test-data/utf8-bom.docx");
|
|
38
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
39
|
+
assert.equal(result.value, "<p>This XML has a byte order mark.</p>");
|
|
40
|
+
assert.deepEqual(result.messages, []);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('empty paragraphs are ignored by default', function() {
|
|
45
|
+
var docxPath = path.join(__dirname, "test-data/empty.docx");
|
|
46
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
47
|
+
assert.equal(result.value, "");
|
|
48
|
+
assert.deepEqual(result.messages, []);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('empty paragraphs are preserved if ignoreEmptyParagraphs is false', function() {
|
|
53
|
+
var docxPath = path.join(__dirname, "test-data/empty.docx");
|
|
54
|
+
return mammoth.convertToHtml({path: docxPath}, {ignoreEmptyParagraphs: false}).then(function(result) {
|
|
55
|
+
assert.equal(result.value, "<p></p>");
|
|
56
|
+
assert.deepEqual(result.messages, []);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('style map can be expressed as string', function() {
|
|
61
|
+
var docxFile = createFakeDocxFile({
|
|
62
|
+
"word/document.xml": testData("simple/word/document.xml")
|
|
63
|
+
});
|
|
64
|
+
var options = {
|
|
65
|
+
styleMap: "p => h1"
|
|
66
|
+
};
|
|
67
|
+
return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
|
|
68
|
+
assert.equal("<h1>Hello.</h1>", result.value);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('style map can be expressed as array of style mappings', function() {
|
|
73
|
+
var docxFile = createFakeDocxFile({
|
|
74
|
+
"word/document.xml": testData("simple/word/document.xml")
|
|
75
|
+
});
|
|
76
|
+
var options = {
|
|
77
|
+
styleMap: ["p => h1"]
|
|
78
|
+
};
|
|
79
|
+
return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
|
|
80
|
+
assert.equal("<h1>Hello.</h1>", result.value);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('embedded style map is used if present', function() {
|
|
85
|
+
var docxPath = path.join(__dirname, "test-data/embedded-style-map.docx");
|
|
86
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
87
|
+
assert.equal(result.value, "<h1>Walking on imported air</h1>");
|
|
88
|
+
assert.deepEqual(result.messages, []);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('explicit style map takes precedence over embedded style map', function() {
|
|
93
|
+
var docxPath = path.join(__dirname, "test-data/embedded-style-map.docx");
|
|
94
|
+
var options = {
|
|
95
|
+
styleMap: ["p => p"]
|
|
96
|
+
};
|
|
97
|
+
return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
|
|
98
|
+
assert.equal(result.value, "<p>Walking on imported air</p>");
|
|
99
|
+
assert.deepEqual(result.messages, []);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('explicit style map is combined with embedded style map', function() {
|
|
104
|
+
var docxPath = path.join(__dirname, "test-data/embedded-style-map.docx");
|
|
105
|
+
var options = {
|
|
106
|
+
styleMap: ["r => strong"]
|
|
107
|
+
};
|
|
108
|
+
return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
|
|
109
|
+
assert.equal(result.value, "<h1><strong>Walking on imported air</strong></h1>");
|
|
110
|
+
assert.deepEqual(result.messages, []);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('embedded style maps can be disabled', function() {
|
|
115
|
+
var docxPath = path.join(__dirname, "test-data/embedded-style-map.docx");
|
|
116
|
+
var options = {
|
|
117
|
+
includeEmbeddedStyleMap: false
|
|
118
|
+
};
|
|
119
|
+
return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
|
|
120
|
+
assert.equal(result.value, "<p>Walking on imported air</p>");
|
|
121
|
+
assert.deepEqual(result.messages, []);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('embedded style map can be written and then read', function() {
|
|
126
|
+
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
|
|
127
|
+
return promises.nfcall(fs.readFile, docxPath)
|
|
128
|
+
.then(function(buffer) {
|
|
129
|
+
return mammoth.embedStyleMap({buffer: buffer}, "p => h1");
|
|
130
|
+
})
|
|
131
|
+
.then(function(docx) {
|
|
132
|
+
return mammoth.convertToHtml({buffer: docx.toBuffer()});
|
|
133
|
+
})
|
|
134
|
+
.then(function(result) {
|
|
135
|
+
assert.equal(result.value, "<h1>Walking on imported air</h1>");
|
|
136
|
+
assert.deepEqual(result.messages, []);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('embedded style map can be retrieved', function() {
|
|
141
|
+
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
|
|
142
|
+
return promises.nfcall(fs.readFile, docxPath)
|
|
143
|
+
.then(function(buffer) {
|
|
144
|
+
return mammoth.embedStyleMap({buffer: buffer}, "p => h1");
|
|
145
|
+
})
|
|
146
|
+
.then(function(docx) {
|
|
147
|
+
return mammoth.readEmbeddedStyleMap({buffer: docx.toBuffer()});
|
|
148
|
+
})
|
|
149
|
+
.then(function(styleMap) {
|
|
150
|
+
assert.equal(styleMap, "p => h1");
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test('warning if style mapping is not understood', function() {
|
|
155
|
+
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
|
|
156
|
+
var options = {
|
|
157
|
+
styleMap: "????\np => h1"
|
|
158
|
+
};
|
|
159
|
+
return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
|
|
160
|
+
assert.equal("<h1>Walking on imported air</h1>", result.value);
|
|
161
|
+
var warning = "Did not understand this style mapping, so ignored it: ????\n" +
|
|
162
|
+
'Error was at character number 1: Expected element type but got unrecognisedCharacter "?"';
|
|
163
|
+
assert.deepEqual(result.messages, [results.warning(warning)]);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('options are passed to document converter when calling mammoth.convertToHtml', function() {
|
|
168
|
+
var docxFile = createFakeDocxFile({
|
|
169
|
+
"word/document.xml": testData("simple/word/document.xml")
|
|
170
|
+
});
|
|
171
|
+
var options = {
|
|
172
|
+
styleMap: "p => h1"
|
|
173
|
+
};
|
|
174
|
+
return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
|
|
175
|
+
assert.equal("<h1>Hello.</h1>", result.value);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test('options.transformDocument is used to transform document if set', function() {
|
|
180
|
+
var docxFile = createFakeDocxFile({
|
|
181
|
+
"word/document.xml": testData("simple/word/document.xml")
|
|
182
|
+
});
|
|
183
|
+
var options = {
|
|
184
|
+
transformDocument: function(document) {
|
|
185
|
+
document.children[0].styleId = "Heading1";
|
|
186
|
+
return document;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
|
|
190
|
+
assert.equal("<h1>Hello.</h1>", result.value);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test('mammoth.transforms.paragraph only transforms paragraphs', function() {
|
|
195
|
+
var docxFile = createFakeDocxFile({
|
|
196
|
+
"word/document.xml": testData("simple/word/document.xml")
|
|
197
|
+
});
|
|
198
|
+
var options = {
|
|
199
|
+
transformDocument: mammoth.transforms.paragraph(function(paragraph) {
|
|
200
|
+
return _.extend(paragraph, {styleId: "Heading1"});
|
|
201
|
+
})
|
|
202
|
+
};
|
|
203
|
+
return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
|
|
204
|
+
assert.equal("<h1>Hello.</h1>", result.value);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test('inline images referenced by path relative to part are included in output', function() {
|
|
209
|
+
var docxPath = path.join(__dirname, "test-data/tiny-picture.docx");
|
|
210
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
211
|
+
assert.equal(result.value, '<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAOvgAADr4B6kKxwAAAABNJREFUKFNj/M+ADzDhlWUYqdIAQSwBE8U+X40AAAAASUVORK5CYII=" /></p>');
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('inline images referenced by path relative to base are included in output', function() {
|
|
216
|
+
var docxPath = path.join(__dirname, "test-data/tiny-picture-target-base-relative.docx");
|
|
217
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
218
|
+
assert.equal(result.value, '<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAOvgAADr4B6kKxwAAAABNJREFUKFNj/M+ADzDhlWUYqdIAQSwBE8U+X40AAAAASUVORK5CYII=" /></p>');
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('src of inline images can be changed', function() {
|
|
223
|
+
var docxPath = path.join(__dirname, "test-data/tiny-picture.docx");
|
|
224
|
+
var convertImage = mammoth.images.imgElement(function(element) {
|
|
225
|
+
return element.read("base64").then(function(encodedImage) {
|
|
226
|
+
return {src: encodedImage.substring(0, 2) + "," + element.contentType};
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
return mammoth.convertToHtml({path: docxPath}, {convertImage: convertImage}).then(function(result) {
|
|
230
|
+
assert.equal(result.value, '<p><img src="iV,image/png" /></p>');
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('images stored outside of document are included in output', function() {
|
|
235
|
+
var docxPath = path.join(__dirname, "test-data/external-picture.docx");
|
|
236
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
237
|
+
assert.equal(result.value, '<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAOvgAADr4B6kKxwAAAABNJREFUKFNj/M+ADzDhlWUYqdIAQSwBE8U+X40AAAAASUVORK5CYII=" /></p>');
|
|
238
|
+
assert.deepEqual(result.messages, []);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('error if images stored outside of document are specified when passing file without path', function() {
|
|
243
|
+
var docxPath = path.join(__dirname, "test-data/external-picture.docx");
|
|
244
|
+
var buffer = fs.readFileSync(docxPath);
|
|
245
|
+
return mammoth.convertToHtml({buffer: buffer}).then(function(result) {
|
|
246
|
+
assert.equal(result.value, '');
|
|
247
|
+
assert.equal(result.messages[0].message, "could not find external image 'tiny-picture.png', path of input document is unknown");
|
|
248
|
+
assert.equal(result.messages[0].type, "error");
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test('simple list is converted to list elements', function() {
|
|
253
|
+
var docxPath = path.join(__dirname, "test-data/simple-list.docx");
|
|
254
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
255
|
+
assert.equal(result.value, '<ul><li>Apple</li><li>Banana</li></ul>');
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('word tables are converted to html tables', function() {
|
|
260
|
+
var docxPath = path.join(__dirname, "test-data/tables.docx");
|
|
261
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
262
|
+
var expectedHtml = "<p>Above</p>" +
|
|
263
|
+
"<table>" +
|
|
264
|
+
"<tr><td><p>Top left</p></td><td><p>Top right</p></td></tr>" +
|
|
265
|
+
"<tr><td><p>Bottom left</p></td><td><p>Bottom right</p></td></tr>" +
|
|
266
|
+
"</table>" +
|
|
267
|
+
"<p>Below</p>";
|
|
268
|
+
assert.equal(result.value, expectedHtml);
|
|
269
|
+
assert.deepEqual(result.messages, []);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('footnotes are appended to text', function() {
|
|
274
|
+
// TODO: don't duplicate footnotes with multiple references
|
|
275
|
+
var docxPath = path.join(__dirname, "test-data/footnotes.docx");
|
|
276
|
+
var options = {
|
|
277
|
+
idPrefix: "doc-42-"
|
|
278
|
+
};
|
|
279
|
+
return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
|
|
280
|
+
var expectedOutput = '<p>Ouch' +
|
|
281
|
+
'<sup><a href="#doc-42-footnote-1" id="doc-42-footnote-ref-1">[1]</a></sup>.' +
|
|
282
|
+
'<sup><a href="#doc-42-footnote-2" id="doc-42-footnote-ref-2">[2]</a></sup></p>' +
|
|
283
|
+
'<ol><li id="doc-42-footnote-1"><p> A tachyon walks into a bar. <a href="#doc-42-footnote-ref-1">↑</a></p></li>' +
|
|
284
|
+
'<li id="doc-42-footnote-2"><p> Fin. <a href="#doc-42-footnote-ref-2">↑</a></p></li></ol>';
|
|
285
|
+
assert.equal(result.value, expectedOutput);
|
|
286
|
+
assert.deepEqual(result.messages, []);
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test('endnotes are appended to text', function() {
|
|
291
|
+
var docxPath = path.join(__dirname, "test-data/endnotes.docx");
|
|
292
|
+
var options = {
|
|
293
|
+
idPrefix: "doc-42-"
|
|
294
|
+
};
|
|
295
|
+
return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
|
|
296
|
+
var expectedOutput = '<p>Ouch' +
|
|
297
|
+
'<sup><a href="#doc-42-endnote-2" id="doc-42-endnote-ref-2">[1]</a></sup>.' +
|
|
298
|
+
'<sup><a href="#doc-42-endnote-3" id="doc-42-endnote-ref-3">[2]</a></sup></p>' +
|
|
299
|
+
'<ol><li id="doc-42-endnote-2"><p> A tachyon walks into a bar. <a href="#doc-42-endnote-ref-2">↑</a></p></li>' +
|
|
300
|
+
'<li id="doc-42-endnote-3"><p> Fin. <a href="#doc-42-endnote-ref-3">↑</a></p></li></ol>';
|
|
301
|
+
assert.equal(result.value, expectedOutput);
|
|
302
|
+
assert.deepEqual(result.messages, []);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test('relationships are handled properly in footnotes', function() {
|
|
307
|
+
var docxPath = path.join(__dirname, "test-data/footnote-hyperlink.docx");
|
|
308
|
+
var options = {
|
|
309
|
+
idPrefix: "doc-42-"
|
|
310
|
+
};
|
|
311
|
+
return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
|
|
312
|
+
var expectedOutput =
|
|
313
|
+
'<p><sup><a href="#doc-42-footnote-1" id="doc-42-footnote-ref-1">[1]</a></sup></p>' +
|
|
314
|
+
'<ol><li id="doc-42-footnote-1"><p> <a href="http://www.example.com">Example</a> <a href="#doc-42-footnote-ref-1">↑</a></p></li></ol>';
|
|
315
|
+
assert.equal(result.value, expectedOutput);
|
|
316
|
+
assert.deepEqual(result.messages, []);
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
test('when style mapping is defined for comment references then comments are included', function() {
|
|
321
|
+
var docxPath = path.join(__dirname, "test-data/comments.docx");
|
|
322
|
+
var options = {
|
|
323
|
+
idPrefix: "doc-42-",
|
|
324
|
+
styleMap: "comment-reference => sup"
|
|
325
|
+
};
|
|
326
|
+
return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
|
|
327
|
+
var expectedOutput = (
|
|
328
|
+
'<p>Ouch' +
|
|
329
|
+
'<sup><a href="#doc-42-comment-0" id="doc-42-comment-ref-0">[MW1]</a></sup>.' +
|
|
330
|
+
'<sup><a href="#doc-42-comment-2" id="doc-42-comment-ref-2">[MW2]</a></sup></p>' +
|
|
331
|
+
'<dl><dt id="doc-42-comment-0">Comment [MW1]</dt><dd><p>A tachyon walks into a bar. <a href="#doc-42-comment-ref-0">↑</a></p></dd>' +
|
|
332
|
+
'<dt id="doc-42-comment-2">Comment [MW2]</dt><dd><p>Fin. <a href="#doc-42-comment-ref-2">↑</a></p></dd></dl>'
|
|
333
|
+
);
|
|
334
|
+
assert.equal(result.value, expectedOutput);
|
|
335
|
+
assert.deepEqual(result.messages, []);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
test('textboxes are read', function() {
|
|
340
|
+
var docxPath = path.join(__dirname, "test-data/text-box.docx");
|
|
341
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
342
|
+
var expectedOutput = '<p>Datum plane</p>';
|
|
343
|
+
assert.equal(result.value, expectedOutput);
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
test('underline is ignored by default', function() {
|
|
348
|
+
var docxPath = path.join(__dirname, "test-data/underline.docx");
|
|
349
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
350
|
+
assert.equal(result.value, '<p><strong>The Sunset Tree</strong></p>');
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test('underline can be configured with style mapping', function() {
|
|
355
|
+
var docxPath = path.join(__dirname, "test-data/underline.docx");
|
|
356
|
+
return mammoth.convertToHtml({path: docxPath}, {styleMap: "u => em"}).then(function(result) {
|
|
357
|
+
assert.equal(result.value, '<p><strong>The <em>Sunset</em> Tree</strong></p>');
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
test('strikethrough is converted to <s> by default', function() {
|
|
362
|
+
var docxPath = path.join(__dirname, "test-data/strikethrough.docx");
|
|
363
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
364
|
+
assert.equal(result.value, "<p><s>Today's Special: Salmon</s> Sold out</p>");
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
test('strikethrough conversion can be configured with style mappings', function() {
|
|
369
|
+
var docxPath = path.join(__dirname, "test-data/strikethrough.docx");
|
|
370
|
+
return mammoth.convertToHtml({path: docxPath}, {styleMap: "strike => del"}).then(function(result) {
|
|
371
|
+
assert.equal(result.value, "<p><del>Today's Special: Salmon</del> Sold out</p>");
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test('indentation is used if prettyPrint is true', function() {
|
|
376
|
+
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
|
|
377
|
+
return mammoth.convertToHtml({path: docxPath}, {prettyPrint: true}).then(function(result) {
|
|
378
|
+
assert.equal(result.value, "<p>\n Walking on imported air\n</p>");
|
|
379
|
+
assert.deepEqual(result.messages, []);
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
test('using styleMapping throws error', function() {
|
|
384
|
+
try {
|
|
385
|
+
mammoth.styleMapping();
|
|
386
|
+
} catch (error) {
|
|
387
|
+
assert.equal(
|
|
388
|
+
error.message,
|
|
389
|
+
'Use a raw string instead of mammoth.styleMapping e.g. "p[style-name=\'Title\'] => h1" instead of mammoth.styleMapping("p[style-name=\'Title\'] => h1")'
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
test('can convert single paragraph to markdown', function() {
|
|
395
|
+
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
|
|
396
|
+
return mammoth.convertToMarkdown({path: docxPath}).then(function(result) {
|
|
397
|
+
assert.equal(result.value, "Walking on imported air\n\n");
|
|
398
|
+
assert.deepEqual(result.messages, []);
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
test('extractRawText only retains raw text', function() {
|
|
403
|
+
var docxPath = path.join(__dirname, "test-data/simple-list.docx");
|
|
404
|
+
return mammoth.extractRawText({path: docxPath}).then(function(result) {
|
|
405
|
+
assert.equal(result.value, 'Apple\n\nBanana\n\n');
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
test('extractRawText can use .docx files represented by a Buffer', function() {
|
|
410
|
+
var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
|
|
411
|
+
return promises.nfcall(fs.readFile, docxPath)
|
|
412
|
+
.then(function(buffer) {
|
|
413
|
+
return mammoth.extractRawText({buffer: buffer});
|
|
414
|
+
})
|
|
415
|
+
.then(function(result) {
|
|
416
|
+
assert.equal(result.value, "Walking on imported air\n\n");
|
|
417
|
+
assert.deepEqual(result.messages, []);
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
test('should throw error if file is not a valid docx document', function() {
|
|
423
|
+
var docxPath = path.join(__dirname, "test-data/empty.zip");
|
|
424
|
+
return mammoth.convertToHtml({path: docxPath}).then(function(result) {
|
|
425
|
+
assert.ok(false, "Expected error");
|
|
426
|
+
}, function(error) {
|
|
427
|
+
assert.equal(error.message, "Could not find main document part. Are you sure this is a valid .docx file?");
|
|
428
|
+
});
|
|
429
|
+
});
|
package/test/mocha.opts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--ui exports
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
var assert = require("assert");
|
|
2
|
+
|
|
3
|
+
var _ = require("underscore");
|
|
4
|
+
|
|
5
|
+
var optionsReader = require("../lib/options-reader");
|
|
6
|
+
var standardOptions = optionsReader._standardOptions;
|
|
7
|
+
var readOptions = optionsReader.readOptions;
|
|
8
|
+
var test = require("./test")(module);
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
test('standard options are used if options is undefined', function() {
|
|
12
|
+
var options = readOptions(undefined);
|
|
13
|
+
assert.deepEqual(standardOptions, _.omit(options, "customStyleMap", "readStyleMap"));
|
|
14
|
+
assert.deepEqual(options.customStyleMap, []);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('standard options are used if options is empty', function() {
|
|
18
|
+
var options = readOptions({});
|
|
19
|
+
assert.deepEqual(standardOptions, _.omit(options, "customStyleMap", "readStyleMap"));
|
|
20
|
+
assert.deepEqual(options.customStyleMap, []);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('custom style map as string is prepended to standard style map', function() {
|
|
24
|
+
var options = readOptions({
|
|
25
|
+
styleMap: "p.SectionTitle => h2"
|
|
26
|
+
});
|
|
27
|
+
var styleMap = options.readStyleMap();
|
|
28
|
+
assert.deepEqual("p.SectionTitle => h2", styleMap[0]);
|
|
29
|
+
assert.deepEqual(optionsReader._defaultStyleMap, styleMap.slice(1));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('custom style map as array is prepended to standard style map', function() {
|
|
33
|
+
var options = readOptions({
|
|
34
|
+
styleMap: ["p.SectionTitle => h2"]
|
|
35
|
+
});
|
|
36
|
+
var styleMap = options.readStyleMap();
|
|
37
|
+
assert.deepEqual("p.SectionTitle => h2", styleMap[0]);
|
|
38
|
+
assert.deepEqual(optionsReader._defaultStyleMap, styleMap.slice(1));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('lines starting with # in custom style map are ignored', function() {
|
|
42
|
+
var options = readOptions({
|
|
43
|
+
styleMap: "# p.SectionTitle => h3\np.SectionTitle => h2"
|
|
44
|
+
});
|
|
45
|
+
var styleMap = options.readStyleMap();
|
|
46
|
+
assert.deepEqual("p.SectionTitle => h2", styleMap[0]);
|
|
47
|
+
assert.deepEqual(optionsReader._defaultStyleMap, styleMap.slice(1));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('blank lines in custom style map are ignored', function() {
|
|
51
|
+
var options = readOptions({
|
|
52
|
+
styleMap: "\n\n"
|
|
53
|
+
});
|
|
54
|
+
assert.deepEqual(optionsReader._defaultStyleMap, options.readStyleMap());
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('default style mappings are ignored if includeDefaultStyleMap is false', function() {
|
|
58
|
+
var options = readOptions({
|
|
59
|
+
styleMap: "p.SectionTitle => h2",
|
|
60
|
+
includeDefaultStyleMap: false
|
|
61
|
+
});
|
|
62
|
+
assert.deepEqual(["p.SectionTitle => h2"], options.readStyleMap());
|
|
63
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
var assert = require("assert");
|
|
2
|
+
|
|
3
|
+
var results = require("../lib/results");
|
|
4
|
+
var Result = results.Result;
|
|
5
|
+
var test = require("./test")(module);
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
test("Result.combine removes any duplicate messages", function() {
|
|
9
|
+
var first = new Result(null, [results.warning("Warning...")]);
|
|
10
|
+
var second = new Result(null, [results.warning("Warning...")]);
|
|
11
|
+
|
|
12
|
+
var combined = Result.combine([first, second]);
|
|
13
|
+
|
|
14
|
+
assert.deepEqual(combined.messages, [results.warning("Warning...")]);
|
|
15
|
+
});
|