@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,834 @@
|
|
|
1
|
+
var assert = require("assert");
|
|
2
|
+
var promises = require("../lib/promises");
|
|
3
|
+
|
|
4
|
+
var documents = require("../lib/documents");
|
|
5
|
+
var documentToHtml = require("../lib/document-to-html");
|
|
6
|
+
var DocumentConverter = documentToHtml.DocumentConverter;
|
|
7
|
+
var commentAuthorLabel = documentToHtml.commentAuthorLabel;
|
|
8
|
+
var test = require("./test")(module);
|
|
9
|
+
var htmlPaths = require("../lib/styles/html-paths");
|
|
10
|
+
var xml = require("../lib/xml");
|
|
11
|
+
var results = require("../lib/results");
|
|
12
|
+
var documentMatchers = require("../lib/styles/document-matchers");
|
|
13
|
+
var Html = require("../lib/html");
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
test('should empty document to empty string', function() {
|
|
17
|
+
var document = new documents.Document([]);
|
|
18
|
+
var converter = new DocumentConverter();
|
|
19
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
20
|
+
assert.equal(result.value, "");
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('should convert document containing one paragraph to single p element', function() {
|
|
25
|
+
var document = new documents.Document([
|
|
26
|
+
paragraphOfText("Hello.")
|
|
27
|
+
]);
|
|
28
|
+
var converter = new DocumentConverter();
|
|
29
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
30
|
+
assert.equal(result.value, "<p>Hello.</p>");
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('ignores empty paragraphs', function() {
|
|
35
|
+
var document = new documents.Document([
|
|
36
|
+
paragraphOfText("")
|
|
37
|
+
]);
|
|
38
|
+
var converter = new DocumentConverter();
|
|
39
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
40
|
+
assert.equal(result.value, "");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('text is HTML-escaped', function() {
|
|
45
|
+
var document = new documents.Document([
|
|
46
|
+
paragraphOfText("1 < 2")
|
|
47
|
+
]);
|
|
48
|
+
var converter = new DocumentConverter();
|
|
49
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
50
|
+
assert.equal(result.value, "<p>1 < 2</p>");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('should convert document containing multiple paragraphs to multiple p elements', function() {
|
|
55
|
+
var document = new documents.Document([
|
|
56
|
+
paragraphOfText("Hello."),
|
|
57
|
+
paragraphOfText("Goodbye.")
|
|
58
|
+
]);
|
|
59
|
+
var converter = new DocumentConverter();
|
|
60
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
61
|
+
assert.equal(result.value, "<p>Hello.</p><p>Goodbye.</p>");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('uses style mappings to pick HTML element for docx paragraph', function() {
|
|
66
|
+
var document = new documents.Document([
|
|
67
|
+
paragraphOfText("Hello.", "Heading1", "Heading 1")
|
|
68
|
+
]);
|
|
69
|
+
var converter = new DocumentConverter({
|
|
70
|
+
styleMap: [
|
|
71
|
+
{
|
|
72
|
+
from: documentMatchers.paragraph({styleName: documentMatchers.equalTo("Heading 1")}),
|
|
73
|
+
to: htmlPaths.topLevelElement("h1")
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
78
|
+
assert.equal(result.value, "<h1>Hello.</h1>");
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('uses dynamic style mappings to pick HTML element for docx paragraph', function() {
|
|
83
|
+
var document = new documents.Document([
|
|
84
|
+
new documents.Paragraph([runOfText("Lorem ipsum.")], {
|
|
85
|
+
styleName: 'Normal',
|
|
86
|
+
alignment: "center",
|
|
87
|
+
spacing: {line: "480"}
|
|
88
|
+
}),
|
|
89
|
+
new documents.Paragraph([runOfText("Dolor amet.")], {
|
|
90
|
+
styleName: 'Normal',
|
|
91
|
+
alignment: "left"
|
|
92
|
+
})
|
|
93
|
+
]);
|
|
94
|
+
var converter = new DocumentConverter({
|
|
95
|
+
styleMap: [
|
|
96
|
+
{
|
|
97
|
+
from: documentMatchers.paragraph(),
|
|
98
|
+
to: htmlPaths.topLevelElement('p', {}, function(element) {
|
|
99
|
+
var classNames = [];
|
|
100
|
+
if (element.alignment) {
|
|
101
|
+
classNames.push('align-' + element.alignment);
|
|
102
|
+
}
|
|
103
|
+
if (element.spacing && element.spacing.line) {
|
|
104
|
+
classNames.push('spacing-' + element.spacing.line);
|
|
105
|
+
}
|
|
106
|
+
return {class: classNames.join(' ')};
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
});
|
|
111
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
112
|
+
assert.equal(result.value, "<p class=\"align-center spacing-480\">Lorem ipsum.</p><p class=\"align-left\">Dolor amet.</p>");
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('mappings for style names are case insensitive', function() {
|
|
117
|
+
var document = new documents.Document([
|
|
118
|
+
paragraphOfText("Hello.", "Heading1", "heading 1")
|
|
119
|
+
]);
|
|
120
|
+
var converter = new DocumentConverter({
|
|
121
|
+
styleMap: [
|
|
122
|
+
{
|
|
123
|
+
from: documentMatchers.paragraph({styleName: documentMatchers.equalTo("Heading 1")}),
|
|
124
|
+
to: htmlPaths.topLevelElement("h1")
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
});
|
|
128
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
129
|
+
assert.equal(result.value, "<h1>Hello.</h1>");
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('can use non-default HTML element for unstyled paragraphs', function() {
|
|
134
|
+
var document = new documents.Document([
|
|
135
|
+
paragraphOfText("Hello.")
|
|
136
|
+
]);
|
|
137
|
+
var converter = new DocumentConverter({
|
|
138
|
+
styleMap: [
|
|
139
|
+
{
|
|
140
|
+
from: documentMatchers.paragraph(),
|
|
141
|
+
to: htmlPaths.topLevelElement("h1")
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
});
|
|
145
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
146
|
+
assert.equal(result.value, "<h1>Hello.</h1>");
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('warning is emitted if paragraph style is unrecognised', function() {
|
|
151
|
+
var document = new documents.Document([
|
|
152
|
+
paragraphOfText("Hello.", "Heading1", "Heading 1")
|
|
153
|
+
]);
|
|
154
|
+
var converter = new DocumentConverter();
|
|
155
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
156
|
+
assert.deepEqual(result.messages, [results.warning("Unrecognised paragraph style: 'Heading 1' (Style ID: Heading1)")]);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('can use stacked styles to generate nested HTML elements', function() {
|
|
161
|
+
var document = new documents.Document([
|
|
162
|
+
paragraphOfText("Hello.")
|
|
163
|
+
]);
|
|
164
|
+
var converter = new DocumentConverter({
|
|
165
|
+
styleMap: [
|
|
166
|
+
{
|
|
167
|
+
from: documentMatchers.paragraph(),
|
|
168
|
+
to: htmlPaths.elements(["h1", "span"])
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
});
|
|
172
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
173
|
+
assert.equal(result.value, "<h1><span>Hello.</span></h1>");
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test('bold runs are wrapped in <strong> tags by default', function() {
|
|
178
|
+
var run = runOfText("Hello.", {isBold: true});
|
|
179
|
+
var converter = new DocumentConverter();
|
|
180
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
181
|
+
assert.equal(result.value, "<strong>Hello.</strong>");
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('bold runs can be configured with style mapping', function() {
|
|
186
|
+
var run = runOfText("Hello.", {isBold: true});
|
|
187
|
+
var converter = new DocumentConverter({
|
|
188
|
+
styleMap: [
|
|
189
|
+
{
|
|
190
|
+
from: documentMatchers.bold,
|
|
191
|
+
to: htmlPaths.elements([htmlPaths.element("em")])
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
});
|
|
195
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
196
|
+
assert.equal(result.value, "<em>Hello.</em>");
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('bold runs can exist inside other tags', function() {
|
|
201
|
+
var run = new documents.Paragraph([
|
|
202
|
+
runOfText("Hello.", {isBold: true})
|
|
203
|
+
]);
|
|
204
|
+
var converter = new DocumentConverter();
|
|
205
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
206
|
+
assert.equal(result.value, "<p><strong>Hello.</strong></p>");
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test('consecutive bold runs are wrapped in a single <strong> element', function() {
|
|
211
|
+
var paragraph = new documents.Paragraph([
|
|
212
|
+
runOfText("Hello", {isBold: true}),
|
|
213
|
+
runOfText(".", {isBold: true})
|
|
214
|
+
]);
|
|
215
|
+
var converter = new DocumentConverter();
|
|
216
|
+
return converter.convertToHtml(paragraph).then(function(result) {
|
|
217
|
+
assert.equal(result.value, "<p><strong>Hello.</strong></p>");
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test('underline runs are ignored by default', function() {
|
|
222
|
+
var run = runOfText("Hello.", {isUnderline: true});
|
|
223
|
+
var converter = new DocumentConverter();
|
|
224
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
225
|
+
assert.equal(result.value, "Hello.");
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test('underline runs can be mapped using style mapping', function() {
|
|
230
|
+
var run = runOfText("Hello.", {isUnderline: true});
|
|
231
|
+
var converter = new DocumentConverter({
|
|
232
|
+
styleMap: [
|
|
233
|
+
{
|
|
234
|
+
from: documentMatchers.underline,
|
|
235
|
+
to: htmlPaths.elements([htmlPaths.element("u")])
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
});
|
|
239
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
240
|
+
assert.equal(result.value, "<u>Hello.</u>");
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test('style mapping for underline runs does not close parent elements', function() {
|
|
245
|
+
var run = runOfText("Hello.", {isUnderline: true, isBold: true});
|
|
246
|
+
var converter = new DocumentConverter({
|
|
247
|
+
styleMap: [
|
|
248
|
+
{
|
|
249
|
+
from: documentMatchers.underline,
|
|
250
|
+
to: htmlPaths.elements([htmlPaths.element("u")])
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
});
|
|
254
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
255
|
+
assert.equal(result.value, "<strong><u>Hello.</u></strong>");
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('strikethrough runs are wrapped in <s> tags by default', function() {
|
|
260
|
+
var run = runOfText("Hello.", {isStrikethrough: true});
|
|
261
|
+
var converter = new DocumentConverter();
|
|
262
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
263
|
+
assert.equal(result.value, "<s>Hello.</s>");
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test('strikethrough runs can be configured with style mapping', function() {
|
|
268
|
+
var run = runOfText("Hello.", {isStrikethrough: true});
|
|
269
|
+
var converter = new DocumentConverter({
|
|
270
|
+
styleMap: [
|
|
271
|
+
{
|
|
272
|
+
from: documentMatchers.strikethrough,
|
|
273
|
+
to: htmlPaths.elements([htmlPaths.element("del")])
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
});
|
|
277
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
278
|
+
assert.equal(result.value, "<del>Hello.</del>");
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
test('italic runs are wrapped in <em> tags', function() {
|
|
283
|
+
var run = runOfText("Hello.", {isItalic: true});
|
|
284
|
+
var converter = new DocumentConverter();
|
|
285
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
286
|
+
assert.equal(result.value, "<em>Hello.</em>");
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test('italic runs can be configured with style mapping', function() {
|
|
291
|
+
var run = runOfText("Hello.", {isItalic: true});
|
|
292
|
+
var converter = new DocumentConverter({
|
|
293
|
+
styleMap: [
|
|
294
|
+
{
|
|
295
|
+
from: documentMatchers.italic,
|
|
296
|
+
to: htmlPaths.elements([htmlPaths.element("strong")])
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
});
|
|
300
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
301
|
+
assert.equal(result.value, "<strong>Hello.</strong>");
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
test('run can be both bold and italic', function() {
|
|
306
|
+
var run = runOfText("Hello.", {isBold: true, isItalic: true});
|
|
307
|
+
var converter = new DocumentConverter();
|
|
308
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
309
|
+
assert.equal(result.value, "<strong><em>Hello.</em></strong>");
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test('superscript runs are wrapped in <sup> tags', function() {
|
|
314
|
+
var run = runOfText("Hello.", {
|
|
315
|
+
verticalAlignment: documents.verticalAlignment.superscript
|
|
316
|
+
});
|
|
317
|
+
var converter = new DocumentConverter();
|
|
318
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
319
|
+
assert.equal(result.value, "<sup>Hello.</sup>");
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test('subscript runs are wrapped in <sub> tags', function() {
|
|
324
|
+
var run = runOfText("Hello.", {
|
|
325
|
+
verticalAlignment: documents.verticalAlignment.subscript
|
|
326
|
+
});
|
|
327
|
+
var converter = new DocumentConverter();
|
|
328
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
329
|
+
assert.equal(result.value, "<sub>Hello.</sub>");
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
test('small caps runs are ignored by default', function() {
|
|
334
|
+
var run = runOfText("Hello.", {isSmallCaps: true});
|
|
335
|
+
var converter = new DocumentConverter();
|
|
336
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
337
|
+
assert.equal(result.value, "Hello.");
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test('small caps runs can be configured with style mapping', function() {
|
|
342
|
+
var run = runOfText("Hello.", {isSmallCaps: true});
|
|
343
|
+
var converter = new DocumentConverter({
|
|
344
|
+
styleMap: [
|
|
345
|
+
{
|
|
346
|
+
from: documentMatchers.smallCaps,
|
|
347
|
+
to: htmlPaths.elements([htmlPaths.element("span")])
|
|
348
|
+
}
|
|
349
|
+
]
|
|
350
|
+
});
|
|
351
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
352
|
+
assert.equal(result.value, "<span>Hello.</span>");
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
test('run styles are converted to HTML if mapping exists', function() {
|
|
358
|
+
var run = runOfText("Hello.", {styleId: "Heading1Char", styleName: "Heading 1 Char"});
|
|
359
|
+
var converter = new DocumentConverter({
|
|
360
|
+
styleMap: [
|
|
361
|
+
{
|
|
362
|
+
from: documentMatchers.run({styleName: documentMatchers.equalTo("Heading 1 Char")}),
|
|
363
|
+
to: htmlPaths.elements(["strong"])
|
|
364
|
+
}
|
|
365
|
+
]
|
|
366
|
+
});
|
|
367
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
368
|
+
assert.equal(result.value, "<strong>Hello.</strong>");
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
test('warning is emitted if run style is unrecognised', function() {
|
|
373
|
+
var run = runOfText("Hello.", {styleId: "Heading1Char", styleName: "Heading 1 Char"});
|
|
374
|
+
var converter = new DocumentConverter();
|
|
375
|
+
return converter.convertToHtml(run).then(function(result) {
|
|
376
|
+
assert.deepEqual(result.messages, [results.warning("Unrecognised run style: 'Heading 1 Char' (Style ID: Heading1Char)")]);
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
test('docx hyperlink is converted to <a>', function() {
|
|
381
|
+
var hyperlink = new documents.Hyperlink(
|
|
382
|
+
[runOfText("Hello.")],
|
|
383
|
+
{href: "http://www.example.com"}
|
|
384
|
+
);
|
|
385
|
+
var converter = new DocumentConverter();
|
|
386
|
+
return converter.convertToHtml(hyperlink).then(function(result) {
|
|
387
|
+
assert.equal(result.value, '<a href="http://www.example.com">Hello.</a>');
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test('docx hyperlink can be collapsed', function() {
|
|
392
|
+
var hyperlink = new documents.Document([
|
|
393
|
+
new documents.Hyperlink(
|
|
394
|
+
[runOfText("Hello ")],
|
|
395
|
+
{href: "http://www.example.com"}
|
|
396
|
+
),
|
|
397
|
+
new documents.Hyperlink(
|
|
398
|
+
[runOfText("world")],
|
|
399
|
+
{href: "http://www.example.com"}
|
|
400
|
+
)
|
|
401
|
+
]);
|
|
402
|
+
var converter = new DocumentConverter();
|
|
403
|
+
return converter.convertToHtml(hyperlink).then(function(result) {
|
|
404
|
+
assert.equal(result.value, '<a href="http://www.example.com">Hello world</a>');
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
test('docx hyperlink with anchor is converted to <a>', function() {
|
|
409
|
+
var hyperlink = new documents.Hyperlink(
|
|
410
|
+
[runOfText("Hello.")],
|
|
411
|
+
{anchor: "_Peter"}
|
|
412
|
+
);
|
|
413
|
+
var converter = new DocumentConverter({
|
|
414
|
+
idPrefix: "doc-42-"
|
|
415
|
+
});
|
|
416
|
+
return converter.convertToHtml(hyperlink).then(function(result) {
|
|
417
|
+
assert.equal(result.value, '<a href="#doc-42-_Peter">Hello.</a>');
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
test('hyperlink target frame is used as anchor target', function() {
|
|
422
|
+
var hyperlink = new documents.Hyperlink(
|
|
423
|
+
[runOfText("Hello.")],
|
|
424
|
+
{anchor: "start", targetFrame: "_blank"}
|
|
425
|
+
);
|
|
426
|
+
var converter = new DocumentConverter();
|
|
427
|
+
return converter.convertToHtml(hyperlink).then(function(result) {
|
|
428
|
+
assert.equal(result.value, '<a href="#start" target="_blank">Hello.</a>');
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
test('bookmarks are converted to anchors', function() {
|
|
433
|
+
var bookmarkStart = new documents.BookmarkStart({name: "_Peter"});
|
|
434
|
+
var converter = new DocumentConverter({
|
|
435
|
+
idPrefix: "doc-42-"
|
|
436
|
+
});
|
|
437
|
+
var document = new documents.Document([bookmarkStart]);
|
|
438
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
439
|
+
assert.equal(result.value, '<a id="doc-42-_Peter"></a>');
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
test('docx tab is converted to tab in HTML', function() {
|
|
444
|
+
var tab = new documents.Tab();
|
|
445
|
+
var converter = new DocumentConverter();
|
|
446
|
+
return converter.convertToHtml(tab).then(function(result) {
|
|
447
|
+
assert.equal(result.value, "\t");
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
test('docx table is converted to table in HTML', function() {
|
|
452
|
+
var table = new documents.Table([
|
|
453
|
+
new documents.TableRow([
|
|
454
|
+
new documents.TableCell([paragraphOfText("Top left")]),
|
|
455
|
+
new documents.TableCell([paragraphOfText("Top right")])
|
|
456
|
+
]),
|
|
457
|
+
new documents.TableRow([
|
|
458
|
+
new documents.TableCell([paragraphOfText("Bottom left")]),
|
|
459
|
+
new documents.TableCell([paragraphOfText("Bottom right")])
|
|
460
|
+
])
|
|
461
|
+
]);
|
|
462
|
+
var converter = new DocumentConverter();
|
|
463
|
+
|
|
464
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
465
|
+
var expectedHtml = "<table>" +
|
|
466
|
+
"<tr><td><p>Top left</p></td><td><p>Top right</p></td></tr>" +
|
|
467
|
+
"<tr><td><p>Bottom left</p></td><td><p>Bottom right</p></td></tr>" +
|
|
468
|
+
"</table>";
|
|
469
|
+
assert.equal(result.value, expectedHtml);
|
|
470
|
+
});
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
test('table style mappings can be used to map tables', function() {
|
|
474
|
+
var table = new documents.Table([], {styleName: "Normal Table"});
|
|
475
|
+
var converter = new DocumentConverter({
|
|
476
|
+
styleMap: [
|
|
477
|
+
{
|
|
478
|
+
from: documentMatchers.table({styleName: documentMatchers.equalTo("Normal Table")}),
|
|
479
|
+
to: htmlPaths.topLevelElement("table", {"class": "normal-table"})
|
|
480
|
+
}
|
|
481
|
+
]
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
485
|
+
var expectedHtml = '<table class="normal-table"></table>';
|
|
486
|
+
assert.equal(result.value, expectedHtml);
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
test('header rows are wrapped in thead', function() {
|
|
491
|
+
var table = new documents.Table([
|
|
492
|
+
new documents.TableRow([new documents.TableCell([])], {isHeader: true}),
|
|
493
|
+
new documents.TableRow([new documents.TableCell([])], {isHeader: true}),
|
|
494
|
+
new documents.TableRow([new documents.TableCell([])], {isHeader: false})
|
|
495
|
+
]);
|
|
496
|
+
var converter = new DocumentConverter();
|
|
497
|
+
|
|
498
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
499
|
+
var expectedHtml = "<table>" +
|
|
500
|
+
"<thead><tr><th></th></tr><tr><th></th></tr></thead>" +
|
|
501
|
+
"<tbody><tr><td></td></tr></tbody>" +
|
|
502
|
+
"</table>";
|
|
503
|
+
assert.equal(result.value, expectedHtml);
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
test('tbody is omitted if all rows are headers', function() {
|
|
508
|
+
var table = new documents.Table([
|
|
509
|
+
new documents.TableRow([new documents.TableCell([])], {isHeader: true})
|
|
510
|
+
]);
|
|
511
|
+
var converter = new DocumentConverter();
|
|
512
|
+
|
|
513
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
514
|
+
var expectedHtml = "<table>" +
|
|
515
|
+
"<thead><tr><th></th></tr></thead>" +
|
|
516
|
+
"</table>";
|
|
517
|
+
assert.equal(result.value, expectedHtml);
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
test('unexpected table children do not cause error', function() {
|
|
522
|
+
var table = new documents.Table([
|
|
523
|
+
new documents.tab()
|
|
524
|
+
]);
|
|
525
|
+
var converter = new DocumentConverter();
|
|
526
|
+
|
|
527
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
528
|
+
var expectedHtml = "<table>\t</table>";
|
|
529
|
+
assert.equal(result.value, expectedHtml);
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
test('empty cells are preserved in table', function() {
|
|
534
|
+
var table = new documents.Table([
|
|
535
|
+
new documents.TableRow([
|
|
536
|
+
new documents.TableCell([paragraphOfText("")]),
|
|
537
|
+
new documents.TableCell([paragraphOfText("Top right")])
|
|
538
|
+
])
|
|
539
|
+
]);
|
|
540
|
+
var converter = new DocumentConverter();
|
|
541
|
+
|
|
542
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
543
|
+
var expectedHtml = "<table>" +
|
|
544
|
+
"<tr><td></td><td><p>Top right</p></td></tr>" +
|
|
545
|
+
"</table>";
|
|
546
|
+
assert.equal(result.value, expectedHtml);
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
test('empty rows are preserved in table', function() {
|
|
551
|
+
var table = new documents.Table([
|
|
552
|
+
new documents.TableRow([
|
|
553
|
+
new documents.TableCell([paragraphOfText("Row 1")])
|
|
554
|
+
]),
|
|
555
|
+
new documents.TableRow([])
|
|
556
|
+
]);
|
|
557
|
+
var converter = new DocumentConverter();
|
|
558
|
+
|
|
559
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
560
|
+
var expectedHtml = "<table>" +
|
|
561
|
+
"<tr><td><p>Row 1</p></td></tr><tr></tr>" +
|
|
562
|
+
"</table>";
|
|
563
|
+
assert.equal(result.value, expectedHtml);
|
|
564
|
+
});
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
test('table cells are written with colSpan if not equal to one', function() {
|
|
568
|
+
var table = new documents.Table([
|
|
569
|
+
new documents.TableRow([
|
|
570
|
+
new documents.TableCell([paragraphOfText("Top left")], {colSpan: 2}),
|
|
571
|
+
new documents.TableCell([paragraphOfText("Top right")])
|
|
572
|
+
])
|
|
573
|
+
]);
|
|
574
|
+
var converter = new DocumentConverter();
|
|
575
|
+
|
|
576
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
577
|
+
var expectedHtml = "<table>" +
|
|
578
|
+
"<tr><td colspan=\"2\"><p>Top left</p></td><td><p>Top right</p></td></tr>" +
|
|
579
|
+
"</table>";
|
|
580
|
+
assert.equal(result.value, expectedHtml);
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
test('table cells are written with rowSpan if not equal to one', function() {
|
|
585
|
+
var table = new documents.Table([
|
|
586
|
+
new documents.TableRow([
|
|
587
|
+
new documents.TableCell([], {rowSpan: 2})
|
|
588
|
+
])
|
|
589
|
+
]);
|
|
590
|
+
var converter = new DocumentConverter();
|
|
591
|
+
|
|
592
|
+
return converter.convertToHtml(table).then(function(result) {
|
|
593
|
+
var expectedHtml = "<table>" +
|
|
594
|
+
"<tr><td rowspan=\"2\"></td></tr>" +
|
|
595
|
+
"</table>";
|
|
596
|
+
assert.equal(result.value, expectedHtml);
|
|
597
|
+
});
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
test('line break is converted to <br>', function() {
|
|
601
|
+
var converter = new DocumentConverter();
|
|
602
|
+
|
|
603
|
+
return converter.convertToHtml(documents.lineBreak).then(function(result) {
|
|
604
|
+
assert.equal(result.value, "<br />");
|
|
605
|
+
});
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
test('breaks that are not line breaks are ignored', function() {
|
|
609
|
+
var converter = new DocumentConverter();
|
|
610
|
+
|
|
611
|
+
return converter.convertToHtml(documents.pageBreak).then(function(result) {
|
|
612
|
+
assert.equal(result.value, "");
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
test('breaks can be mapped using style mappings', function() {
|
|
617
|
+
var converter = new DocumentConverter({
|
|
618
|
+
styleMap: [
|
|
619
|
+
{
|
|
620
|
+
from: documentMatchers.pageBreak,
|
|
621
|
+
to: htmlPaths.topLevelElement("hr")
|
|
622
|
+
}
|
|
623
|
+
]
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
return converter.convertToHtml(documents.pageBreak).then(function(result) {
|
|
627
|
+
assert.equal(result.value, "<hr />");
|
|
628
|
+
});
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
test('footnote reference is converted to superscript intra-page link', function() {
|
|
632
|
+
var footnoteReference = new documents.NoteReference({
|
|
633
|
+
noteType: "footnote",
|
|
634
|
+
noteId: "4"
|
|
635
|
+
});
|
|
636
|
+
var converter = new DocumentConverter({
|
|
637
|
+
idPrefix: "doc-42-"
|
|
638
|
+
});
|
|
639
|
+
return converter.convertToHtml(footnoteReference).then(function(result) {
|
|
640
|
+
assert.equal(result.value, '<sup><a href="#doc-42-footnote-4" id="doc-42-footnote-ref-4">[1]</a></sup>');
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
test('footnotes are included after the main body', function() {
|
|
645
|
+
var footnoteReference = new documents.NoteReference({
|
|
646
|
+
noteType: "footnote",
|
|
647
|
+
noteId: "4"
|
|
648
|
+
});
|
|
649
|
+
var document = new documents.Document(
|
|
650
|
+
[new documents.Paragraph([
|
|
651
|
+
runOfText("Knock knock"),
|
|
652
|
+
new documents.Run([footnoteReference])
|
|
653
|
+
])],
|
|
654
|
+
{
|
|
655
|
+
notes: new documents.Notes({
|
|
656
|
+
4: new documents.Note({
|
|
657
|
+
noteType: "footnote",
|
|
658
|
+
noteId: "4",
|
|
659
|
+
body: [paragraphOfText("Who's there?")]
|
|
660
|
+
})
|
|
661
|
+
})
|
|
662
|
+
}
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
var converter = new DocumentConverter({
|
|
666
|
+
idPrefix: "doc-42-"
|
|
667
|
+
});
|
|
668
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
669
|
+
var expectedOutput = '<p>Knock knock<sup><a href="#doc-42-footnote-4" id="doc-42-footnote-ref-4">[1]</a></sup></p>' +
|
|
670
|
+
'<ol><li id="doc-42-footnote-4"><p>Who\'s there? <a href="#doc-42-footnote-ref-4">↑</a></p></li></ol>';
|
|
671
|
+
assert.equal(result.value, expectedOutput);
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
test('comments are ignored by default', function() {
|
|
676
|
+
var reference = documents.commentReference({commentId: "4"});
|
|
677
|
+
var comment = documents.comment({
|
|
678
|
+
commentId: "4",
|
|
679
|
+
body: [paragraphOfText("Who's there?")]
|
|
680
|
+
});
|
|
681
|
+
var document = documents.document([
|
|
682
|
+
documents.paragraph([
|
|
683
|
+
runOfText("Knock knock"),
|
|
684
|
+
documents.run([reference])
|
|
685
|
+
])
|
|
686
|
+
], {comments: [comment]});
|
|
687
|
+
|
|
688
|
+
var converter = new DocumentConverter({});
|
|
689
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
690
|
+
assert.equal(result.value, '<p>Knock knock</p>');
|
|
691
|
+
assert.deepEqual(result.messages, []);
|
|
692
|
+
});
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
test('comment references are linked to comment after main body', function() {
|
|
696
|
+
var reference = documents.commentReference({commentId: "4"});
|
|
697
|
+
var comment = documents.comment({
|
|
698
|
+
commentId: "4",
|
|
699
|
+
body: [paragraphOfText("Who's there?")],
|
|
700
|
+
authorName: "The Piemaker",
|
|
701
|
+
authorInitials: "TP"
|
|
702
|
+
});
|
|
703
|
+
var document = documents.document([
|
|
704
|
+
documents.paragraph([
|
|
705
|
+
runOfText("Knock knock"),
|
|
706
|
+
documents.run([reference])
|
|
707
|
+
])
|
|
708
|
+
], {comments: [comment]});
|
|
709
|
+
|
|
710
|
+
var converter = new DocumentConverter({
|
|
711
|
+
idPrefix: "doc-42-",
|
|
712
|
+
styleMap: [
|
|
713
|
+
{from: documentMatchers.commentReference, to: htmlPaths.element("sup")}
|
|
714
|
+
]
|
|
715
|
+
});
|
|
716
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
717
|
+
var expectedHtml = (
|
|
718
|
+
'<p>Knock knock<sup><a href="#doc-42-comment-4" id="doc-42-comment-ref-4">[TP1]</a></sup></p>' +
|
|
719
|
+
'<dl><dt id="doc-42-comment-4">Comment [TP1]</dt><dd><p>Who\'s there? <a href="#doc-42-comment-ref-4">↑</a></p></dd></dl>'
|
|
720
|
+
);
|
|
721
|
+
assert.equal(result.value, expectedHtml);
|
|
722
|
+
assert.deepEqual(result.messages, []);
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
test('images are written with data URIs', function() {
|
|
727
|
+
var imageBuffer = new Buffer("Not an image at all!");
|
|
728
|
+
var image = new documents.Image({
|
|
729
|
+
readImage: function(encoding) {
|
|
730
|
+
return promises.when(imageBuffer.toString(encoding));
|
|
731
|
+
},
|
|
732
|
+
contentType: "image/png"
|
|
733
|
+
});
|
|
734
|
+
var converter = new DocumentConverter();
|
|
735
|
+
return converter.convertToHtml(image).then(function(result) {
|
|
736
|
+
assert.equal(result.value, '<img src="data:image/png;base64,' + imageBuffer.toString("base64") + '" />');
|
|
737
|
+
});
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
test('images have alt attribute if available', function() {
|
|
741
|
+
var imageBuffer = new Buffer("Not an image at all!");
|
|
742
|
+
var image = new documents.Image({
|
|
743
|
+
readImage: function() {
|
|
744
|
+
return promises.when(imageBuffer);
|
|
745
|
+
},
|
|
746
|
+
altText: "It's a hat"
|
|
747
|
+
});
|
|
748
|
+
var converter = new DocumentConverter();
|
|
749
|
+
return converter.convertToHtml(image)
|
|
750
|
+
.then(function(result) {
|
|
751
|
+
return xml.readString(result.value);
|
|
752
|
+
})
|
|
753
|
+
.then(function(htmlImageElement) {
|
|
754
|
+
assert.equal(htmlImageElement.attributes.alt, "It's a hat");
|
|
755
|
+
});
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
test('can add custom handler for images', function() {
|
|
759
|
+
var imageBuffer = new Buffer("Not an image at all!");
|
|
760
|
+
var image = new documents.Image({
|
|
761
|
+
readImage: function(encoding) {
|
|
762
|
+
return promises.when(imageBuffer.toString(encoding));
|
|
763
|
+
},
|
|
764
|
+
contentType: "image/png"
|
|
765
|
+
});
|
|
766
|
+
var converter = new DocumentConverter({
|
|
767
|
+
convertImage: function(element, messages) {
|
|
768
|
+
return element.read("utf8").then(function(altText) {
|
|
769
|
+
return [Html.freshElement("img", {alt: altText})];
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
return converter.convertToHtml(image).then(function(result) {
|
|
774
|
+
assert.equal(result.value, '<img alt="Not an image at all!" />');
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
test('when custom image handler throws error then error is stored in error message', function() {
|
|
779
|
+
var error = new Error("Failed to convert image");
|
|
780
|
+
var image = new documents.Image({
|
|
781
|
+
readImage: function(encoding) {
|
|
782
|
+
return promises.when(new Buffer().toString(encoding));
|
|
783
|
+
},
|
|
784
|
+
contentType: "image/png"
|
|
785
|
+
});
|
|
786
|
+
var converter = new DocumentConverter({
|
|
787
|
+
convertImage: function(element, messages) {
|
|
788
|
+
throw error;
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
return converter.convertToHtml(image).then(function(result) {
|
|
792
|
+
assert.equal(result.value, '');
|
|
793
|
+
assert.equal(result.messages.length, 1);
|
|
794
|
+
var message = result.messages[0];
|
|
795
|
+
assert.equal("error", message.type);
|
|
796
|
+
assert.equal("Failed to convert image", message.message);
|
|
797
|
+
assert.equal(error, message.error);
|
|
798
|
+
});
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
test('long documents do not cause stack overflow', function() {
|
|
802
|
+
var paragraphs = [];
|
|
803
|
+
for (var i = 0; i < 1000; i++) {
|
|
804
|
+
paragraphs.push(paragraphOfText("Hello."));
|
|
805
|
+
}
|
|
806
|
+
var document = new documents.Document(paragraphs);
|
|
807
|
+
var converter = new DocumentConverter();
|
|
808
|
+
return converter.convertToHtml(document).then(function(result) {
|
|
809
|
+
assert.equal(result.value.indexOf("<p>Hello.</p>"), 0);
|
|
810
|
+
});
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
function paragraphOfText(text, styleId, styleName) {
|
|
814
|
+
var run = runOfText(text);
|
|
815
|
+
return new documents.Paragraph([run], {
|
|
816
|
+
styleId: styleId,
|
|
817
|
+
styleName: styleName
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
function runOfText(text, properties) {
|
|
822
|
+
var textElement = new documents.Text(text);
|
|
823
|
+
return new documents.Run([textElement], properties);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
test('when initials are not blank then comment author label is initials', function() {
|
|
827
|
+
assert.equal(commentAuthorLabel({authorInitials: "TP"}), "TP");
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
test('when initials are blank then comment author label is blank', function() {
|
|
831
|
+
assert.equal(commentAuthorLabel({authorInitials: ""}), "");
|
|
832
|
+
assert.equal(commentAuthorLabel({authorInitials: undefined}), "");
|
|
833
|
+
assert.equal(commentAuthorLabel({authorInitials: null}), "");
|
|
834
|
+
});
|