@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,125 @@
|
|
|
1
|
+
var assert = require("assert");
|
|
2
|
+
|
|
3
|
+
var _ = require("underscore");
|
|
4
|
+
|
|
5
|
+
var documents = require("../lib/documents");
|
|
6
|
+
var transforms = require("../lib/transforms");
|
|
7
|
+
var test = require("./test")(module);
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
test("paragraph()", {
|
|
11
|
+
"paragraph is transformed": function() {
|
|
12
|
+
var paragraph = documents.paragraph([]);
|
|
13
|
+
var result = transforms.paragraph(function() {
|
|
14
|
+
return documents.tab();
|
|
15
|
+
})(paragraph);
|
|
16
|
+
assert.deepEqual(result, documents.tab());
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
"non-paragraph elements are not transformed": function() {
|
|
20
|
+
var run = documents.run([]);
|
|
21
|
+
var result = transforms.paragraph(function() {
|
|
22
|
+
return documents.tab();
|
|
23
|
+
})(run);
|
|
24
|
+
assert.deepEqual(result, documents.run([]));
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
test("run()", {
|
|
30
|
+
"run is transformed": function() {
|
|
31
|
+
var run = documents.run([]);
|
|
32
|
+
var result = transforms.run(function() {
|
|
33
|
+
return documents.tab();
|
|
34
|
+
})(run);
|
|
35
|
+
assert.deepEqual(result, documents.tab());
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
"non-run elements are not transformed": function() {
|
|
39
|
+
var paragraph = documents.paragraph([]);
|
|
40
|
+
var result = transforms.run(function() {
|
|
41
|
+
return documents.tab();
|
|
42
|
+
})(paragraph);
|
|
43
|
+
assert.deepEqual(result, documents.paragraph([]));
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
test("elements()", {
|
|
49
|
+
"all descendants are transformed": function() {
|
|
50
|
+
var root = {
|
|
51
|
+
children: [
|
|
52
|
+
{
|
|
53
|
+
children: [
|
|
54
|
+
{}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
};
|
|
59
|
+
var currentCount = 0;
|
|
60
|
+
function setCount(node) {
|
|
61
|
+
currentCount++;
|
|
62
|
+
return _.extend(node, {count: currentCount});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var result = transforms._elements(setCount)(root);
|
|
66
|
+
|
|
67
|
+
assert.deepEqual(result, {
|
|
68
|
+
count: 3,
|
|
69
|
+
children: [
|
|
70
|
+
{
|
|
71
|
+
count: 2,
|
|
72
|
+
children: [
|
|
73
|
+
{count: 1}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
test("getDescendants()", {
|
|
83
|
+
"returns nothing if element has no children property": function() {
|
|
84
|
+
assert.deepEqual(transforms.getDescendants({}), []);
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
"returns nothing if element has empty children": function() {
|
|
88
|
+
assert.deepEqual(transforms.getDescendants({children: []}), []);
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
"includes children": function() {
|
|
92
|
+
var element = {
|
|
93
|
+
children: [{name: "child 1"}, {name: "child 2"}]
|
|
94
|
+
};
|
|
95
|
+
assert.deepEqual(
|
|
96
|
+
transforms.getDescendants(element),
|
|
97
|
+
[{name: "child 1"}, {name: "child 2"}]
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
"includes indirect descendants": function() {
|
|
102
|
+
var grandchild = {name: "grandchild"};
|
|
103
|
+
var child = {name: "child", children: [grandchild]};
|
|
104
|
+
var element = {children: [child]};
|
|
105
|
+
assert.deepEqual(
|
|
106
|
+
transforms.getDescendants(element),
|
|
107
|
+
[grandchild, child]
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
test("getDescendantsOfType()", {
|
|
114
|
+
"filters descendants to type": function() {
|
|
115
|
+
var paragraph = {type: "paragraph"};
|
|
116
|
+
var run = {type: "run"};
|
|
117
|
+
var element = {
|
|
118
|
+
children: [paragraph, run]
|
|
119
|
+
};
|
|
120
|
+
assert.deepEqual(
|
|
121
|
+
transforms.getDescendantsOfType(element, "run"),
|
|
122
|
+
[run]
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var fs = require("fs");
|
|
2
|
+
var assert = require("assert");
|
|
3
|
+
var path = require("path");
|
|
4
|
+
|
|
5
|
+
var test = require("./test")(module);
|
|
6
|
+
var unzip = require("../lib/unzip");
|
|
7
|
+
var promises = require("../lib/promises");
|
|
8
|
+
|
|
9
|
+
test("unzip fails if given empty object", function() {
|
|
10
|
+
return unzip.openZip({}).then(function() {
|
|
11
|
+
assert.ok(false, "Expected failure");
|
|
12
|
+
}, function(error) {
|
|
13
|
+
assert.equal("Could not find file in options", error.message);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("unzip can open local zip file", function() {
|
|
18
|
+
var zipPath = path.join(__dirname, "test-data/hello.zip");
|
|
19
|
+
return unzip.openZip({path: zipPath}).then(function(zipFile) {
|
|
20
|
+
return zipFile.read("hello", "utf8");
|
|
21
|
+
}).then(function(contents) {
|
|
22
|
+
assert.equal(contents, "Hello world\n");
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('unzip can open Buffer', function() {
|
|
27
|
+
var zipPath = path.join(__dirname, "test-data/hello.zip");
|
|
28
|
+
return promises.nfcall(fs.readFile, zipPath)
|
|
29
|
+
.then(function(buffer) {
|
|
30
|
+
return unzip.openZip({buffer: buffer});
|
|
31
|
+
})
|
|
32
|
+
.then(function(zipFile) {
|
|
33
|
+
return zipFile.read("hello", "utf8");
|
|
34
|
+
})
|
|
35
|
+
.then(function(contents) {
|
|
36
|
+
assert.equal(contents, "Hello world\n");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
var assert = require("assert");
|
|
2
|
+
var test = require("../test")(module);
|
|
3
|
+
|
|
4
|
+
var htmlWriter = require("../../lib/writers/html-writer");
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
test('can generate simple paragraph', function() {
|
|
8
|
+
var writer = htmlWriter.writer();
|
|
9
|
+
writer.open("p");
|
|
10
|
+
writer.text("Hello");
|
|
11
|
+
writer.close("p");
|
|
12
|
+
return assert.equal(writer.asString(), "<p>Hello</p>");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('can nest elements', function() {
|
|
16
|
+
var writer = htmlWriter.writer();
|
|
17
|
+
writer.open("ul");
|
|
18
|
+
writer.open("li");
|
|
19
|
+
writer.text("One");
|
|
20
|
+
writer.close("li");
|
|
21
|
+
writer.open("li");
|
|
22
|
+
writer.text("Two");
|
|
23
|
+
writer.close("li");
|
|
24
|
+
writer.close("ul");
|
|
25
|
+
return assert.equal(writer.asString(), "<ul><li>One</li><li>Two</li></ul>");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('indents text if prettyPrint is true', function() {
|
|
29
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
30
|
+
writer.open("p");
|
|
31
|
+
writer.text("One");
|
|
32
|
+
writer.close("p");
|
|
33
|
+
writer.open("p");
|
|
34
|
+
writer.text("Two");
|
|
35
|
+
writer.close("p");
|
|
36
|
+
return assert.equal(writer.asString(), "<p>\n One\n</p>\n<p>\n Two\n</p>");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('indents element if prettyPrint is true', function() {
|
|
40
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
41
|
+
writer.open("ul");
|
|
42
|
+
writer.open("li");
|
|
43
|
+
writer.text("One");
|
|
44
|
+
writer.close("li");
|
|
45
|
+
writer.open("li");
|
|
46
|
+
writer.text("Two");
|
|
47
|
+
writer.close("li");
|
|
48
|
+
writer.close("ul");
|
|
49
|
+
return assert.equal(writer.asString(), "<ul>\n <li>\n One\n </li>\n <li>\n Two\n </li>\n</ul>");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('when prettyPrint is true inner elements do not have new lines', function() {
|
|
53
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
54
|
+
writer.open("p");
|
|
55
|
+
writer.text("One");
|
|
56
|
+
writer.open("em");
|
|
57
|
+
writer.text("Two");
|
|
58
|
+
writer.close("em");
|
|
59
|
+
writer.close("p");
|
|
60
|
+
return assert.equal(writer.asString(), "<p>\n One<em>Two</em>\n</p>");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('indents closing element correctly when nested inside another indented element', function() {
|
|
64
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
65
|
+
writer.open("div");
|
|
66
|
+
writer.open("div");
|
|
67
|
+
writer.open("div");
|
|
68
|
+
writer.text("Hello");
|
|
69
|
+
writer.close("div");
|
|
70
|
+
writer.close("div");
|
|
71
|
+
writer.close("div");
|
|
72
|
+
return assert.equal(writer.asString(), "<div>\n <div>\n <div>\n Hello\n </div>\n </div>\n</div>");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('newlines in text are indented', function() {
|
|
76
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
77
|
+
writer.open("p");
|
|
78
|
+
writer.text("One\nTwo");
|
|
79
|
+
writer.close("p");
|
|
80
|
+
return assert.equal(writer.asString(), "<p>\n One\n Two\n</p>");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('run of text has only one new line', function() {
|
|
84
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
85
|
+
writer.open("p");
|
|
86
|
+
writer.text("One");
|
|
87
|
+
writer.text("Two");
|
|
88
|
+
writer.close("p");
|
|
89
|
+
return assert.equal(writer.asString(), "<p>\n OneTwo\n</p>");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('run of html has only one new line', function() {
|
|
93
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
94
|
+
writer.open("p");
|
|
95
|
+
writer.text("One");
|
|
96
|
+
writer.text("Two");
|
|
97
|
+
writer.close("p");
|
|
98
|
+
return assert.equal(writer.asString(), "<p>\n OneTwo\n</p>");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('self closing elements are indented', function() {
|
|
102
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
103
|
+
writer.open("p");
|
|
104
|
+
writer.selfClosing("br");
|
|
105
|
+
writer.close("p");
|
|
106
|
+
return assert.equal(writer.asString(), "<p>\n <br />\n</p>");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('newlines in appended HTML are indented', function() {
|
|
110
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
111
|
+
writer.open("p");
|
|
112
|
+
writer.text("One\nTwo");
|
|
113
|
+
writer.close("p");
|
|
114
|
+
return assert.equal(writer.asString(), "<p>\n One\n Two\n</p>");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('newlines in <pre> are not indented', function() {
|
|
118
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
119
|
+
writer.open("pre");
|
|
120
|
+
writer.text("One\nTwo");
|
|
121
|
+
writer.close("pre");
|
|
122
|
+
return assert.equal(writer.asString(), "<pre>One\nTwo</pre>");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('newlines in element in <pre> are not indented', function() {
|
|
126
|
+
var writer = htmlWriter.writer({prettyPrint: true});
|
|
127
|
+
writer.open("pre");
|
|
128
|
+
writer.open("p");
|
|
129
|
+
writer.text("One\nTwo");
|
|
130
|
+
writer.close("p");
|
|
131
|
+
writer.close("pre");
|
|
132
|
+
return assert.equal(writer.asString(), "<pre><p>One\nTwo</p></pre>");
|
|
133
|
+
});
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
var assert = require("assert");
|
|
2
|
+
var test = require("../test")(module);
|
|
3
|
+
|
|
4
|
+
var mdWriter = require("../../lib/writers/markdown-writer");
|
|
5
|
+
|
|
6
|
+
test('special markdown characters are escaped', function() {
|
|
7
|
+
var writer = mdWriter.writer();
|
|
8
|
+
writer.text("\\*");
|
|
9
|
+
return assert.equal(writer.asString(), "\\\\\\*");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('unrecognised elements are treated as normal text', function() {
|
|
13
|
+
var writer = mdWriter.writer();
|
|
14
|
+
writer.open("blah");
|
|
15
|
+
writer.text("Hello");
|
|
16
|
+
writer.close("blah");
|
|
17
|
+
return assert.equal(writer.asString(), "Hello");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('paragraphs are terminated with double new line', function() {
|
|
21
|
+
var writer = mdWriter.writer();
|
|
22
|
+
writer.open("p");
|
|
23
|
+
writer.text("Hello");
|
|
24
|
+
writer.close("p");
|
|
25
|
+
return assert.equal(writer.asString(), "Hello\n\n");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('h1 elements are converted to heading with leading hash', function() {
|
|
29
|
+
var writer = mdWriter.writer();
|
|
30
|
+
writer.open("h1");
|
|
31
|
+
writer.text("Hello");
|
|
32
|
+
writer.close("h1");
|
|
33
|
+
return assert.equal(writer.asString(), "# Hello\n\n");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('h6 elements are converted to heading with six leading hashes', function() {
|
|
37
|
+
var writer = mdWriter.writer();
|
|
38
|
+
writer.open("h6");
|
|
39
|
+
writer.text("Hello");
|
|
40
|
+
writer.close("h6");
|
|
41
|
+
return assert.equal(writer.asString(), "###### Hello\n\n");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('br is written as two spaces followed by new line', function() {
|
|
45
|
+
var writer = mdWriter.writer();
|
|
46
|
+
writer.text("Hello World");
|
|
47
|
+
writer.selfClosing("br");
|
|
48
|
+
return assert.equal(writer.asString(), "Hello World \n");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('strong text is surrounded by two underscores', function() {
|
|
52
|
+
var writer = mdWriter.writer();
|
|
53
|
+
writer.text("Hello ");
|
|
54
|
+
writer.open("strong");
|
|
55
|
+
writer.text("World");
|
|
56
|
+
writer.close("strong");
|
|
57
|
+
return assert.equal(writer.asString(), "Hello __World__");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('emphasised text is surrounded by one asterix', function() {
|
|
61
|
+
var writer = mdWriter.writer();
|
|
62
|
+
writer.text("Hello ");
|
|
63
|
+
writer.open("em");
|
|
64
|
+
writer.text("World");
|
|
65
|
+
writer.close("em");
|
|
66
|
+
return assert.equal(writer.asString(), "Hello *World*");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('anchor tags are written as hyperlinks', function() {
|
|
70
|
+
var writer = mdWriter.writer();
|
|
71
|
+
writer.open("a", {"href": "http://example.com"});
|
|
72
|
+
writer.text("Hello");
|
|
73
|
+
writer.close("a");
|
|
74
|
+
return assert.equal(writer.asString(), "[Hello](http://example.com)");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('anchor tags without href attribute are treated as ordinary text', function() {
|
|
78
|
+
var writer = mdWriter.writer();
|
|
79
|
+
writer.open("a");
|
|
80
|
+
writer.text("Hello");
|
|
81
|
+
writer.close("a");
|
|
82
|
+
return assert.equal(writer.asString(), "Hello");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('elements with IDs have anchor tags with IDs appended to start of markdown element', function() {
|
|
86
|
+
var writer = mdWriter.writer();
|
|
87
|
+
writer.open("h1", {id: "start"});
|
|
88
|
+
writer.text("Hello");
|
|
89
|
+
writer.close("h1");
|
|
90
|
+
return assert.equal(writer.asString(), '# <a id="start"></a>Hello\n\n');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('links have anchors before opening square bracket', function() {
|
|
94
|
+
var writer = mdWriter.writer();
|
|
95
|
+
writer.open("a", {href: "http://example.com", id: "start"});
|
|
96
|
+
writer.text("Hello");
|
|
97
|
+
writer.close("a");
|
|
98
|
+
return assert.equal(writer.asString(), '<a id="start"></a>[Hello](http://example.com)');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('can generate images', function() {
|
|
102
|
+
var writer = mdWriter.writer();
|
|
103
|
+
writer.selfClosing("img", {"src": "http://example.com/image.jpg", "alt": "Alt Text"});
|
|
104
|
+
return assert.equal(writer.asString(), "");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('can generate images with missing alt attribute', function() {
|
|
108
|
+
var writer = mdWriter.writer();
|
|
109
|
+
writer.selfClosing("img", {"src": "http://example.com/image.jpg"});
|
|
110
|
+
return assert.equal(writer.asString(), "");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('can generate images with missing src attribute', function() {
|
|
114
|
+
var writer = mdWriter.writer();
|
|
115
|
+
writer.selfClosing("img", {"alt": "Alt Text"});
|
|
116
|
+
return assert.equal(writer.asString(), "![Alt Text]()");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("doesn't display empty images", function() {
|
|
120
|
+
var writer = mdWriter.writer();
|
|
121
|
+
writer.selfClosing("img");
|
|
122
|
+
return assert.equal(writer.asString(), "");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('list item outside of list is treated as unordered list', function() {
|
|
126
|
+
var writer = mdWriter.writer();
|
|
127
|
+
writer.open("li");
|
|
128
|
+
writer.text("Hello");
|
|
129
|
+
writer.close("li");
|
|
130
|
+
return assert.equal(writer.asString(), "- Hello\n");
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('can generate an ordered list', function() {
|
|
134
|
+
var writer = mdWriter.writer();
|
|
135
|
+
writer.open("ol");
|
|
136
|
+
writer.open("li");
|
|
137
|
+
writer.text("Hello");
|
|
138
|
+
writer.close("li");
|
|
139
|
+
writer.open("li");
|
|
140
|
+
writer.text("World");
|
|
141
|
+
writer.close("li");
|
|
142
|
+
writer.close("ol");
|
|
143
|
+
return assert.equal(writer.asString(), "1. Hello\n2. World\n\n");
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('can generate an unordered list', function() {
|
|
147
|
+
var writer = mdWriter.writer();
|
|
148
|
+
writer.open("ul");
|
|
149
|
+
writer.open("li");
|
|
150
|
+
writer.text("Hello");
|
|
151
|
+
writer.close("li");
|
|
152
|
+
writer.open("li");
|
|
153
|
+
writer.text("World");
|
|
154
|
+
writer.close("li");
|
|
155
|
+
writer.close("ul");
|
|
156
|
+
return assert.equal(writer.asString(), "- Hello\n- World\n\n");
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('can generate a nested ordered list with correct numbering', function() {
|
|
160
|
+
var writer = mdWriter.writer();
|
|
161
|
+
writer.open("ol");
|
|
162
|
+
writer.open("li");
|
|
163
|
+
writer.text("Outer One");
|
|
164
|
+
|
|
165
|
+
writer.open("ol");
|
|
166
|
+
writer.open("li");
|
|
167
|
+
writer.text("Nested One");
|
|
168
|
+
writer.close("li");
|
|
169
|
+
writer.open("li");
|
|
170
|
+
writer.text("Nested Two");
|
|
171
|
+
writer.close("li");
|
|
172
|
+
writer.close("ol");
|
|
173
|
+
|
|
174
|
+
writer.close("li");
|
|
175
|
+
writer.open("li");
|
|
176
|
+
writer.text("Outer Two");
|
|
177
|
+
writer.close("li");
|
|
178
|
+
writer.close("ol");
|
|
179
|
+
return assert.equal(writer.asString(), "1. Outer One\n\t1. Nested One\n\t2. Nested Two\n2. Outer Two\n\n");
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('can generate a multi-level nested ordered list', function() {
|
|
183
|
+
var writer = mdWriter.writer();
|
|
184
|
+
writer.open("ol");
|
|
185
|
+
writer.open("li");
|
|
186
|
+
writer.text("Outer One");
|
|
187
|
+
|
|
188
|
+
writer.open("ol");
|
|
189
|
+
writer.open("li");
|
|
190
|
+
writer.text("Nested One");
|
|
191
|
+
|
|
192
|
+
writer.open("ol");
|
|
193
|
+
writer.open("li");
|
|
194
|
+
writer.text("Inner One");
|
|
195
|
+
writer.close("li");
|
|
196
|
+
writer.close("ol");
|
|
197
|
+
|
|
198
|
+
writer.close("li");
|
|
199
|
+
writer.close("ol");
|
|
200
|
+
|
|
201
|
+
writer.close("li");
|
|
202
|
+
writer.close("ol");
|
|
203
|
+
return assert.equal(writer.asString(), "1. Outer One\n\t1. Nested One\n\t\t1. Inner One\n\n");
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test('new ordered list resets numbering', function() {
|
|
207
|
+
var writer = mdWriter.writer();
|
|
208
|
+
writer.open("ol");
|
|
209
|
+
writer.open("li");
|
|
210
|
+
writer.text("First");
|
|
211
|
+
writer.close("li");
|
|
212
|
+
writer.close("ol");
|
|
213
|
+
|
|
214
|
+
writer.open("p");
|
|
215
|
+
writer.text("Hello");
|
|
216
|
+
writer.close("p");
|
|
217
|
+
|
|
218
|
+
writer.open("ol");
|
|
219
|
+
writer.open("li");
|
|
220
|
+
writer.text("Second");
|
|
221
|
+
writer.close("li");
|
|
222
|
+
writer.close("ol");
|
|
223
|
+
|
|
224
|
+
return assert.equal(writer.asString(), "1. First\n\nHello\n\n1. Second\n\n");
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test('can generate a nested unordered list', function() {
|
|
228
|
+
var writer = mdWriter.writer();
|
|
229
|
+
writer.open("ul");
|
|
230
|
+
writer.open("li");
|
|
231
|
+
writer.text("Outer One");
|
|
232
|
+
|
|
233
|
+
writer.open("ul");
|
|
234
|
+
writer.open("li");
|
|
235
|
+
writer.text("Nested One");
|
|
236
|
+
writer.close("li");
|
|
237
|
+
writer.open("li");
|
|
238
|
+
writer.text("Nested Two");
|
|
239
|
+
writer.close("li");
|
|
240
|
+
writer.close("ul");
|
|
241
|
+
|
|
242
|
+
writer.close("li");
|
|
243
|
+
writer.open("li");
|
|
244
|
+
writer.text("Outer Two");
|
|
245
|
+
writer.close("li");
|
|
246
|
+
writer.close("ul");
|
|
247
|
+
return assert.equal(writer.asString(), "- Outer One\n\t- Nested One\n\t- Nested Two\n- Outer Two\n\n");
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test('can nest inline elements', function() {
|
|
251
|
+
var writer = mdWriter.writer();
|
|
252
|
+
writer.open("p");
|
|
253
|
+
writer.text("Lorem ");
|
|
254
|
+
writer.open("strong");
|
|
255
|
+
writer.text("ipsum ");
|
|
256
|
+
writer.open("em");
|
|
257
|
+
writer.text("dolor");
|
|
258
|
+
writer.close("em");
|
|
259
|
+
writer.text(" sit");
|
|
260
|
+
writer.close("strong");
|
|
261
|
+
writer.text(" amet");
|
|
262
|
+
writer.close("p");
|
|
263
|
+
return assert.equal(writer.asString(), "Lorem __ipsum *dolor* sit__ amet\n\n");
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test('can emphasise list text', function() {
|
|
267
|
+
var writer = mdWriter.writer();
|
|
268
|
+
writer.open("ol");
|
|
269
|
+
writer.open("li");
|
|
270
|
+
writer.text("Hello ");
|
|
271
|
+
writer.open("strong");
|
|
272
|
+
writer.text("Strong");
|
|
273
|
+
writer.close("strong");
|
|
274
|
+
writer.text(" World");
|
|
275
|
+
writer.close("li");
|
|
276
|
+
writer.open("li");
|
|
277
|
+
writer.text("Hello ");
|
|
278
|
+
writer.open("em");
|
|
279
|
+
writer.text("Emphasis");
|
|
280
|
+
writer.close("em");
|
|
281
|
+
writer.text(" World");
|
|
282
|
+
writer.close("li");
|
|
283
|
+
writer.close("ol");
|
|
284
|
+
return assert.equal(writer.asString(), "1. Hello __Strong__ World\n2. Hello *Emphasis* World\n\n");
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test('generates correct spacing between paragraphs and lists', function() {
|
|
288
|
+
var writer = mdWriter.writer();
|
|
289
|
+
writer.open("p");
|
|
290
|
+
writer.text("Hello World");
|
|
291
|
+
writer.close("p");
|
|
292
|
+
writer.open("ul");
|
|
293
|
+
writer.open("li");
|
|
294
|
+
writer.text("First Item");
|
|
295
|
+
writer.close("li");
|
|
296
|
+
writer.open("li");
|
|
297
|
+
writer.text("Second Item");
|
|
298
|
+
writer.close("li");
|
|
299
|
+
writer.close("ul");
|
|
300
|
+
writer.open("p");
|
|
301
|
+
writer.text("Hello World");
|
|
302
|
+
writer.close("p");
|
|
303
|
+
return assert.equal(writer.asString(), "Hello World\n\n- First Item\n- Second Item\n\nHello World\n\n");
|
|
304
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
var assert = require("assert");
|
|
2
|
+
|
|
3
|
+
var xmlreader = require("../../lib/xml/reader");
|
|
4
|
+
var test = require("../test")(module);
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
test('should read self-closing element', function() {
|
|
8
|
+
return xmlreader.readString("<body/>").then(function(result) {
|
|
9
|
+
assert.deepEqual({type: "element", name: "body", attributes: {}, children: []}, result);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('should read empty element with separate closing tag', function() {
|
|
14
|
+
return xmlreader.readString("<body></body>").then(function(result) {
|
|
15
|
+
assert.deepEqual({type: "element", name: "body", attributes: {}, children: []}, result);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('should read attributes of tags', function() {
|
|
20
|
+
return xmlreader.readString('<body name="bob"/>').then(function(result) {
|
|
21
|
+
assert.deepEqual({name: "bob"}, result.attributes);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('can read text element', function() {
|
|
26
|
+
return xmlreader.readString('<body>Hello!</body>').then(function(result) {
|
|
27
|
+
assert.deepEqual({type: "text", value: "Hello!"}, result.children[0]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('should read element with children', function() {
|
|
32
|
+
return xmlreader.readString("<body><a/><b/></body>").then(function(root) {
|
|
33
|
+
assert.equal(2, root.children.length);
|
|
34
|
+
assert.equal("a", root.children[0].name);
|
|
35
|
+
assert.equal("b", root.children[1].name);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('unmapped namespaces URIs are included in braces as prefix', function() {
|
|
40
|
+
return xmlreader.readString('<w:body xmlns:w="word"/>').then(function(result) {
|
|
41
|
+
assert.deepEqual(result.name, "{word}body");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('mapped namespaces URIs are translated using map', function() {
|
|
46
|
+
var namespaceMap = {
|
|
47
|
+
"word": "x"
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return xmlreader.readString('<w:body xmlns:w="word"/>', namespaceMap).then(function(result) {
|
|
51
|
+
assert.deepEqual(result.name, "x:body");
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('namespace of attributes is mapped to prefix', function() {
|
|
56
|
+
var namespaceMap = {
|
|
57
|
+
"word": "x"
|
|
58
|
+
};
|
|
59
|
+
var xmlString = '<w:body xmlns:w="word" w:val="Hello!"/>';
|
|
60
|
+
return xmlreader.readString(xmlString, namespaceMap).then(function(result) {
|
|
61
|
+
assert.deepEqual(result.attributes["x:val"], "Hello!");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('can find first element with name', function() {
|
|
66
|
+
return xmlreader.readString('<body><a/><b index="1"/><b index="2"/></body>').then(function(result) {
|
|
67
|
+
var first = result.first("b");
|
|
68
|
+
assert.equal("1", first.attributes.index);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('whitespace between xml declaration and root tag is ignored', function() {
|
|
73
|
+
return xmlreader.readString('<?xml version="1.0" ?>\n<body/>').then(function(result) {
|
|
74
|
+
assert.deepEqual("body", result.name);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('error if XML is badly formed', function() {
|
|
79
|
+
return xmlreader.readString("<bo").then(function(result) {
|
|
80
|
+
throw new Error("Expected failure");
|
|
81
|
+
}, function(error) {
|
|
82
|
+
assert.ok(error);
|
|
83
|
+
return 1;
|
|
84
|
+
});
|
|
85
|
+
});
|