123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876 |
- var assert = require("assert");
- var promises = require("../lib/promises");
- var documents = require("../lib/documents");
- var documentToHtml = require("../lib/document-to-html");
- var DocumentConverter = documentToHtml.DocumentConverter;
- var commentAuthorLabel = documentToHtml.commentAuthorLabel;
- var test = require("./test")(module);
- var htmlPaths = require("../lib/styles/html-paths");
- var xml = require("../lib/xml");
- var results = require("../lib/results");
- var documentMatchers = require("../lib/styles/document-matchers");
- var Html = require("../lib/html");
- test('should empty document to empty string', function() {
- var document = new documents.Document([]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "");
- });
- });
- test('should convert document containing one paragraph to single p element', function() {
- var document = new documents.Document([
- paragraphOfText("Hello.")
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "<p>Hello.</p>");
- });
- });
- test('ignores empty paragraphs', function() {
- var document = new documents.Document([
- paragraphOfText("")
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "");
- });
- });
- test('text is HTML-escaped', function() {
- var document = new documents.Document([
- paragraphOfText("1 < 2")
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "<p>1 < 2</p>");
- });
- });
- test('should convert document containing multiple paragraphs to multiple p elements', function() {
- var document = new documents.Document([
- paragraphOfText("Hello."),
- paragraphOfText("Goodbye.")
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "<p>Hello.</p><p>Goodbye.</p>");
- });
- });
- test('uses style mappings to pick HTML element for docx paragraph', function() {
- var document = new documents.Document([
- paragraphOfText("Hello.", "Heading1", "Heading 1")
- ]);
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.paragraph({styleName: documentMatchers.equalTo("Heading 1")}),
- to: htmlPaths.topLevelElement("h1")
- }
- ]
- });
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "<h1>Hello.</h1>");
- });
- });
- test('mappings for style names are case insensitive', function() {
- var document = new documents.Document([
- paragraphOfText("Hello.", "Heading1", "heading 1")
- ]);
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.paragraph({styleName: documentMatchers.equalTo("Heading 1")}),
- to: htmlPaths.topLevelElement("h1")
- }
- ]
- });
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "<h1>Hello.</h1>");
- });
- });
- test('can use non-default HTML element for unstyled paragraphs', function() {
- var document = new documents.Document([
- paragraphOfText("Hello.")
- ]);
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.paragraph(),
- to: htmlPaths.topLevelElement("h1")
- }
- ]
- });
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "<h1>Hello.</h1>");
- });
- });
- test('warning is emitted if paragraph style is unrecognised', function() {
- var document = new documents.Document([
- paragraphOfText("Hello.", "Heading1", "Heading 1")
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(document).then(function(result) {
- assert.deepEqual(result.messages, [results.warning("Unrecognised paragraph style: 'Heading 1' (Style ID: Heading1)")]);
- });
- });
- test('can use stacked styles to generate nested HTML elements', function() {
- var document = new documents.Document([
- paragraphOfText("Hello.")
- ]);
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.paragraph(),
- to: htmlPaths.elements(["h1", "span"])
- }
- ]
- });
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, "<h1><span>Hello.</span></h1>");
- });
- });
- test('bold runs are wrapped in <strong> tags by default', function() {
- var run = runOfText("Hello.", {isBold: true});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<strong>Hello.</strong>");
- });
- });
- test('bold runs can be configured with style mapping', function() {
- var run = runOfText("Hello.", {isBold: true});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.bold,
- to: htmlPaths.elements([htmlPaths.element("em")])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<em>Hello.</em>");
- });
- });
- test('bold runs can exist inside other tags', function() {
- var run = new documents.Paragraph([
- runOfText("Hello.", {isBold: true})
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<p><strong>Hello.</strong></p>");
- });
- });
- test('consecutive bold runs are wrapped in a single <strong> element', function() {
- var paragraph = new documents.Paragraph([
- runOfText("Hello", {isBold: true}),
- runOfText(".", {isBold: true})
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(paragraph).then(function(result) {
- assert.equal(result.value, "<p><strong>Hello.</strong></p>");
- });
- });
- test('underline runs are ignored by default', function() {
- var run = runOfText("Hello.", {isUnderline: true});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "Hello.");
- });
- });
- test('underline runs can be mapped using style mapping', function() {
- var run = runOfText("Hello.", {isUnderline: true});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.underline,
- to: htmlPaths.elements([htmlPaths.element("u")])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<u>Hello.</u>");
- });
- });
- test('style mapping for underline runs does not close parent elements', function() {
- var run = runOfText("Hello.", {isUnderline: true, isBold: true});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.underline,
- to: htmlPaths.elements([htmlPaths.element("u")])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<strong><u>Hello.</u></strong>");
- });
- });
- test('strikethrough runs are wrapped in <s> tags by default', function() {
- var run = runOfText("Hello.", {isStrikethrough: true});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<s>Hello.</s>");
- });
- });
- test('strikethrough runs can be configured with style mapping', function() {
- var run = runOfText("Hello.", {isStrikethrough: true});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.strikethrough,
- to: htmlPaths.elements([htmlPaths.element("del")])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<del>Hello.</del>");
- });
- });
- test('italic runs are wrapped in <em> tags', function() {
- var run = runOfText("Hello.", {isItalic: true});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<em>Hello.</em>");
- });
- });
- test('italic runs can be configured with style mapping', function() {
- var run = runOfText("Hello.", {isItalic: true});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.italic,
- to: htmlPaths.elements([htmlPaths.element("strong")])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<strong>Hello.</strong>");
- });
- });
- test('run can be both bold and italic', function() {
- var run = runOfText("Hello.", {isBold: true, isItalic: true});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<strong><em>Hello.</em></strong>");
- });
- });
- test('superscript runs are wrapped in <sup> tags', function() {
- var run = runOfText("Hello.", {
- verticalAlignment: documents.verticalAlignment.superscript
- });
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<sup>Hello.</sup>");
- });
- });
- test('subscript runs are wrapped in <sub> tags', function() {
- var run = runOfText("Hello.", {
- verticalAlignment: documents.verticalAlignment.subscript
- });
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<sub>Hello.</sub>");
- });
- });
- test('all caps runs are ignored by default', function() {
- var run = runOfText("Hello.", {isAllCaps: true});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "Hello.");
- });
- });
- test('all caps runs can be configured with style mapping', function() {
- var run = runOfText("Hello.", {isAllCaps: true});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.allCaps,
- to: htmlPaths.elements([htmlPaths.element("span")])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<span>Hello.</span>");
- });
- });
- test('small caps runs are ignored by default', function() {
- var run = runOfText("Hello.", {isSmallCaps: true});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "Hello.");
- });
- });
- test('small caps runs can be configured with style mapping', function() {
- var run = runOfText("Hello.", {isSmallCaps: true});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.smallCaps,
- to: htmlPaths.elements([htmlPaths.element("span")])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<span>Hello.</span>");
- });
- });
- test('highlighted runs are ignored by default', function() {
- var run = runOfText("Hello.", {highlight: "yellow"});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "Hello.");
- });
- });
- test('highlighted runs can be configured with style mapping for all highlights', function() {
- var run = runOfText("Hello.", {highlight: "yellow"});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.highlight(null),
- to: htmlPaths.elements([htmlPaths.element("mark")])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<mark>Hello.</mark>");
- });
- });
- test('highlighted runs can be configured with style mapping for specific highlight color', function() {
- var paragraph = new documents.Paragraph([
- runOfText("Yellow", {highlight: "yellow"}),
- runOfText("Red", {highlight: "red"})
- ]);
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.highlight({color: "yellow"}),
- to: htmlPaths.elements([htmlPaths.element("mark", {"class": "yellow"})])
- },
- {
- from: documentMatchers.highlight({color: undefined}),
- to: htmlPaths.elements([htmlPaths.element("mark")])
- }
- ]
- });
- return converter.convertToHtml(paragraph).then(function(result) {
- assert.equal(result.value, '<p><mark class="yellow">Yellow</mark><mark>Red</mark></p>');
- });
- });
- test('run styles are converted to HTML if mapping exists', function() {
- var run = runOfText("Hello.", {styleId: "Heading1Char", styleName: "Heading 1 Char"});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.run({styleName: documentMatchers.equalTo("Heading 1 Char")}),
- to: htmlPaths.elements(["strong"])
- }
- ]
- });
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, "<strong>Hello.</strong>");
- });
- });
- test('warning is emitted if run style is unrecognised', function() {
- var run = runOfText("Hello.", {styleId: "Heading1Char", styleName: "Heading 1 Char"});
- var converter = new DocumentConverter();
- return converter.convertToHtml(run).then(function(result) {
- assert.deepEqual(result.messages, [results.warning("Unrecognised run style: 'Heading 1 Char' (Style ID: Heading1Char)")]);
- });
- });
- test('docx hyperlink is converted to <a>', function() {
- var hyperlink = new documents.Hyperlink(
- [runOfText("Hello.")],
- {href: "http://www.example.com"}
- );
- var converter = new DocumentConverter();
- return converter.convertToHtml(hyperlink).then(function(result) {
- assert.equal(result.value, '<a href="http://www.example.com">Hello.</a>');
- });
- });
- test('docx hyperlink can be collapsed', function() {
- var hyperlink = new documents.Document([
- new documents.Hyperlink(
- [runOfText("Hello ")],
- {href: "http://www.example.com"}
- ),
- new documents.Hyperlink(
- [runOfText("world")],
- {href: "http://www.example.com"}
- )
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(hyperlink).then(function(result) {
- assert.equal(result.value, '<a href="http://www.example.com">Hello world</a>');
- });
- });
- test('docx hyperlink with anchor is converted to <a>', function() {
- var hyperlink = new documents.Hyperlink(
- [runOfText("Hello.")],
- {anchor: "_Peter"}
- );
- var converter = new DocumentConverter({
- idPrefix: "doc-42-"
- });
- return converter.convertToHtml(hyperlink).then(function(result) {
- assert.equal(result.value, '<a href="#doc-42-_Peter">Hello.</a>');
- });
- });
- test('hyperlink target frame is used as anchor target', function() {
- var hyperlink = new documents.Hyperlink(
- [runOfText("Hello.")],
- {anchor: "start", targetFrame: "_blank"}
- );
- var converter = new DocumentConverter();
- return converter.convertToHtml(hyperlink).then(function(result) {
- assert.equal(result.value, '<a href="#start" target="_blank">Hello.</a>');
- });
- });
- test('bookmarks are converted to anchors', function() {
- var bookmarkStart = new documents.BookmarkStart({name: "_Peter"});
- var converter = new DocumentConverter({
- idPrefix: "doc-42-"
- });
- var document = new documents.Document([bookmarkStart]);
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, '<a id="doc-42-_Peter"></a>');
- });
- });
- test('docx tab is converted to tab in HTML', function() {
- var tab = new documents.Tab();
- var converter = new DocumentConverter();
- return converter.convertToHtml(tab).then(function(result) {
- assert.equal(result.value, "\t");
- });
- });
- test('docx table is converted to table in HTML', function() {
- var table = new documents.Table([
- new documents.TableRow([
- new documents.TableCell([paragraphOfText("Top left")]),
- new documents.TableCell([paragraphOfText("Top right")])
- ]),
- new documents.TableRow([
- new documents.TableCell([paragraphOfText("Bottom left")]),
- new documents.TableCell([paragraphOfText("Bottom right")])
- ])
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = "<table>" +
- "<tr><td><p>Top left</p></td><td><p>Top right</p></td></tr>" +
- "<tr><td><p>Bottom left</p></td><td><p>Bottom right</p></td></tr>" +
- "</table>";
- assert.equal(result.value, expectedHtml);
- });
- });
- test('table style mappings can be used to map tables', function() {
- var table = new documents.Table([], {styleName: "Normal Table"});
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.table({styleName: documentMatchers.equalTo("Normal Table")}),
- to: htmlPaths.topLevelElement("table", {"class": "normal-table"})
- }
- ]
- });
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = '<table class="normal-table"></table>';
- assert.equal(result.value, expectedHtml);
- });
- });
- test('header rows are wrapped in thead', function() {
- var table = new documents.Table([
- new documents.TableRow([new documents.TableCell([])], {isHeader: true}),
- new documents.TableRow([new documents.TableCell([])], {isHeader: true}),
- new documents.TableRow([new documents.TableCell([])], {isHeader: false})
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = "<table>" +
- "<thead><tr><th></th></tr><tr><th></th></tr></thead>" +
- "<tbody><tr><td></td></tr></tbody>" +
- "</table>";
- assert.equal(result.value, expectedHtml);
- });
- });
- test('tbody is omitted if all rows are headers', function() {
- var table = new documents.Table([
- new documents.TableRow([new documents.TableCell([])], {isHeader: true})
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = "<table>" +
- "<thead><tr><th></th></tr></thead>" +
- "</table>";
- assert.equal(result.value, expectedHtml);
- });
- });
- test('unexpected table children do not cause error', function() {
- var table = new documents.Table([
- new documents.tab()
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = "<table>\t</table>";
- assert.equal(result.value, expectedHtml);
- });
- });
- test('empty cells are preserved in table', function() {
- var table = new documents.Table([
- new documents.TableRow([
- new documents.TableCell([paragraphOfText("")]),
- new documents.TableCell([paragraphOfText("Top right")])
- ])
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = "<table>" +
- "<tr><td></td><td><p>Top right</p></td></tr>" +
- "</table>";
- assert.equal(result.value, expectedHtml);
- });
- });
- test('empty rows are preserved in table', function() {
- var table = new documents.Table([
- new documents.TableRow([
- new documents.TableCell([paragraphOfText("Row 1")])
- ]),
- new documents.TableRow([])
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = "<table>" +
- "<tr><td><p>Row 1</p></td></tr><tr></tr>" +
- "</table>";
- assert.equal(result.value, expectedHtml);
- });
- });
- test('table cells are written with colSpan if not equal to one', function() {
- var table = new documents.Table([
- new documents.TableRow([
- new documents.TableCell([paragraphOfText("Top left")], {colSpan: 2}),
- new documents.TableCell([paragraphOfText("Top right")])
- ])
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = "<table>" +
- "<tr><td colspan=\"2\"><p>Top left</p></td><td><p>Top right</p></td></tr>" +
- "</table>";
- assert.equal(result.value, expectedHtml);
- });
- });
- test('table cells are written with rowSpan if not equal to one', function() {
- var table = new documents.Table([
- new documents.TableRow([
- new documents.TableCell([], {rowSpan: 2})
- ])
- ]);
- var converter = new DocumentConverter();
- return converter.convertToHtml(table).then(function(result) {
- var expectedHtml = "<table>" +
- "<tr><td rowspan=\"2\"></td></tr>" +
- "</table>";
- assert.equal(result.value, expectedHtml);
- });
- });
- test('line break is converted to <br>', function() {
- var converter = new DocumentConverter();
- return converter.convertToHtml(documents.lineBreak).then(function(result) {
- assert.equal(result.value, "<br />");
- });
- });
- test('breaks that are not line breaks are ignored', function() {
- var converter = new DocumentConverter();
- return converter.convertToHtml(documents.pageBreak).then(function(result) {
- assert.equal(result.value, "");
- });
- });
- test('breaks can be mapped using style mappings', function() {
- var converter = new DocumentConverter({
- styleMap: [
- {
- from: documentMatchers.pageBreak,
- to: htmlPaths.topLevelElement("hr")
- },
- {
- from: documentMatchers.lineBreak,
- to: htmlPaths.topLevelElement("br", {class: "line-break"})
- }
- ]
- });
- var run = documents.run([documents.pageBreak, documents.lineBreak]);
- return converter.convertToHtml(run).then(function(result) {
- assert.equal(result.value, '<hr /><br class="line-break" />');
- });
- });
- test('footnote reference is converted to superscript intra-page link', function() {
- var footnoteReference = new documents.NoteReference({
- noteType: "footnote",
- noteId: "4"
- });
- var converter = new DocumentConverter({
- idPrefix: "doc-42-"
- });
- return converter.convertToHtml(footnoteReference).then(function(result) {
- assert.equal(result.value, '<sup><a href="#doc-42-footnote-4" id="doc-42-footnote-ref-4">[1]</a></sup>');
- });
- });
- test('footnotes are included after the main body', function() {
- var footnoteReference = new documents.NoteReference({
- noteType: "footnote",
- noteId: "4"
- });
- var document = new documents.Document(
- [new documents.Paragraph([
- runOfText("Knock knock"),
- new documents.Run([footnoteReference])
- ])],
- {
- notes: new documents.Notes({
- 4: new documents.Note({
- noteType: "footnote",
- noteId: "4",
- body: [paragraphOfText("Who's there?")]
- })
- })
- }
- );
- var converter = new DocumentConverter({
- idPrefix: "doc-42-"
- });
- return converter.convertToHtml(document).then(function(result) {
- var expectedOutput = '<p>Knock knock<sup><a href="#doc-42-footnote-4" id="doc-42-footnote-ref-4">[1]</a></sup></p>' +
- '<ol><li id="doc-42-footnote-4"><p>Who\'s there? <a href="#doc-42-footnote-ref-4">↑</a></p></li></ol>';
- assert.equal(result.value, expectedOutput);
- });
- });
- test('comments are ignored by default', function() {
- var reference = documents.commentReference({commentId: "4"});
- var comment = documents.comment({
- commentId: "4",
- body: [paragraphOfText("Who's there?")]
- });
- var document = documents.document([
- documents.paragraph([
- runOfText("Knock knock"),
- documents.run([reference])
- ])
- ], {comments: [comment]});
- var converter = new DocumentConverter({});
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value, '<p>Knock knock</p>');
- assert.deepEqual(result.messages, []);
- });
- });
- test('comment references are linked to comment after main body', function() {
- var reference = documents.commentReference({commentId: "4"});
- var comment = documents.comment({
- commentId: "4",
- body: [paragraphOfText("Who's there?")],
- authorName: "The Piemaker",
- authorInitials: "TP"
- });
- var document = documents.document([
- documents.paragraph([
- runOfText("Knock knock"),
- documents.run([reference])
- ])
- ], {comments: [comment]});
- var converter = new DocumentConverter({
- idPrefix: "doc-42-",
- styleMap: [
- {from: documentMatchers.commentReference, to: htmlPaths.element("sup")}
- ]
- });
- return converter.convertToHtml(document).then(function(result) {
- var expectedHtml = (
- '<p>Knock knock<sup><a href="#doc-42-comment-4" id="doc-42-comment-ref-4">[TP1]</a></sup></p>' +
- '<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>'
- );
- assert.equal(result.value, expectedHtml);
- assert.deepEqual(result.messages, []);
- });
- });
- test('images are written with data URIs', function() {
- var imageBuffer = new Buffer("Not an image at all!");
- var image = new documents.Image({
- readImage: function(encoding) {
- return promises.when(imageBuffer.toString(encoding));
- },
- contentType: "image/png"
- });
- var converter = new DocumentConverter();
- return converter.convertToHtml(image).then(function(result) {
- assert.equal(result.value, '<img src="data:image/png;base64,' + imageBuffer.toString("base64") + '" />');
- });
- });
- test('images have alt attribute if available', function() {
- var imageBuffer = new Buffer("Not an image at all!");
- var image = new documents.Image({
- readImage: function() {
- return promises.when(imageBuffer);
- },
- altText: "It's a hat"
- });
- var converter = new DocumentConverter();
- return converter.convertToHtml(image)
- .then(function(result) {
- return xml.readString(result.value);
- })
- .then(function(htmlImageElement) {
- assert.equal(htmlImageElement.attributes.alt, "It's a hat");
- });
- });
- test('can add custom handler for images', function() {
- var imageBuffer = new Buffer("Not an image at all!");
- var image = new documents.Image({
- readImage: function(encoding) {
- return promises.when(imageBuffer.toString(encoding));
- },
- contentType: "image/png"
- });
- var converter = new DocumentConverter({
- convertImage: function(element, messages) {
- return element.read("utf8").then(function(altText) {
- return [Html.freshElement("img", {alt: altText})];
- });
- }
- });
- return converter.convertToHtml(image).then(function(result) {
- assert.equal(result.value, '<img alt="Not an image at all!" />');
- });
- });
- test('when custom image handler throws error then error is stored in error message', function() {
- var error = new Error("Failed to convert image");
- var image = new documents.Image({
- readImage: function(encoding) {
- return promises.when(new Buffer().toString(encoding));
- },
- contentType: "image/png"
- });
- var converter = new DocumentConverter({
- convertImage: function(element, messages) {
- throw error;
- }
- });
- return converter.convertToHtml(image).then(function(result) {
- assert.equal(result.value, '');
- assert.equal(result.messages.length, 1);
- var message = result.messages[0];
- assert.equal("error", message.type);
- assert.equal("Failed to convert image", message.message);
- assert.equal(error, message.error);
- });
- });
- test('long documents do not cause stack overflow', function() {
- var paragraphs = [];
- for (var i = 0; i < 1000; i++) {
- paragraphs.push(paragraphOfText("Hello."));
- }
- var document = new documents.Document(paragraphs);
- var converter = new DocumentConverter();
- return converter.convertToHtml(document).then(function(result) {
- assert.equal(result.value.indexOf("<p>Hello.</p>"), 0);
- });
- });
- function paragraphOfText(text, styleId, styleName) {
- var run = runOfText(text);
- return new documents.Paragraph([run], {
- styleId: styleId,
- styleName: styleName
- });
- }
- function runOfText(text, properties) {
- var textElement = new documents.Text(text);
- return new documents.Run([textElement], properties);
- }
- test('when initials are not blank then comment author label is initials', function() {
- assert.equal(commentAuthorLabel({authorInitials: "TP"}), "TP");
- });
- test('when initials are blank then comment author label is blank', function() {
- assert.equal(commentAuthorLabel({authorInitials: ""}), "");
- assert.equal(commentAuthorLabel({authorInitials: undefined}), "");
- assert.equal(commentAuthorLabel({authorInitials: null}), "");
- });
|