From 6fdee5a4b57832682e1c43156b2e075a5552f595 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Mon, 1 Apr 2013 15:24:41 +0100 Subject: Move document conversion into document-to-html module --- lib/document-to-html.js | 80 ++++++++++++++++++++++ lib/documents.js | 78 --------------------- lib/index.js | 8 +-- tests/document-to-html.tests.js | 146 ++++++++++++++++++++++++++++++++++++++++ tests/documents.tests.js | 146 ---------------------------------------- 5 files changed, 228 insertions(+), 230 deletions(-) create mode 100644 lib/document-to-html.js create mode 100644 tests/document-to-html.tests.js delete mode 100644 tests/documents.tests.js diff --git a/lib/document-to-html.js b/lib/document-to-html.js new file mode 100644 index 0000000..caccb6f --- /dev/null +++ b/lib/document-to-html.js @@ -0,0 +1,80 @@ +var q = require("q"); + +var styles = require("./styles"); +var HtmlGenerator = require("./html-generator").HtmlGenerator; + +exports.DocumentConverter = DocumentConverter; + + +function DocumentConverter(options) { + options = options || {}; + var defaultParagraphStyle = options.defaultParagraphStyle || styles.topLevelElement("p"); + + var paragraphStyleMap = options.paragraphStyleMap || {}; + var runStyleMap = options.runStyleMap || {}; + + function convertToHtml(document) { + var html = new HtmlGenerator(); + elementToHtml(document, html); + html.closeAll(); + + return q.when({ + html: html.asString() + }); + } + + function convertElements(elements, html) { + elements.forEach(function(element) { + elementToHtml(element, html); + }); + } + + function elementToHtml(element, html) { + var handler = elementConverters[element.type]; + if (handler) { + handler(element, html); + } + } + + function convertParagraph(element, html) { + html.style(styleForParagraph(element)); + convertElements(element.children, html); + } + + function styleForParagraph(element) { + return paragraphStyleMap[element.properties.styleName] || defaultParagraphStyle; + } + + function convertRun(run, html) { + var runHtml = new HtmlGenerator(); + if (run.properties.styleName) { + var style = runStyleMap[run.properties.styleName]; + if (style) { + runHtml.style(style); + } + } + if (run.properties.isBold) { + runHtml.push(styles.element("strong")); + } + if (run.properties.isItalic) { + runHtml.push(styles.element("em")); + } + convertElements(run.children, runHtml); + runHtml.closeAll(); + html.append(runHtml); + } + + var elementConverters = { + "document": function(document, html) { + convertElements(document.children, html); + }, + "paragraph": convertParagraph, + "run": convertRun, + "text": function(element, html) { + html.text(element.value); + } + }; + return { + convertToHtml: convertToHtml + } +} diff --git a/lib/documents.js b/lib/documents.js index 88f95ba..27190aa 100644 --- a/lib/documents.js +++ b/lib/documents.js @@ -1,86 +1,8 @@ -var q = require("q"); - -var styles = require("./styles"); -var HtmlGenerator = require("./html-generator").HtmlGenerator; - -exports.DocumentConverter = DocumentConverter; exports.Document = Document; exports.Paragraph = Paragraph; exports.Run = Run; exports.Text = Text; -function DocumentConverter(options) { - options = options || {}; - var defaultParagraphStyle = options.defaultParagraphStyle || styles.topLevelElement("p"); - - var paragraphStyleMap = options.paragraphStyleMap || {}; - var runStyleMap = options.runStyleMap || {}; - - function convertToHtml(document) { - var html = new HtmlGenerator(); - elementToHtml(document, html); - html.closeAll(); - - return q.when({ - html: html.asString() - }); - } - - function convertElements(elements, html) { - elements.forEach(function(element) { - elementToHtml(element, html); - }); - } - - function elementToHtml(element, html) { - var handler = elementConverters[element.type]; - if (handler) { - handler(element, html); - } - } - - function convertParagraph(element, html) { - html.style(styleForParagraph(element)); - convertElements(element.children, html); - } - - function styleForParagraph(element) { - return paragraphStyleMap[element.properties.styleName] || defaultParagraphStyle; - } - - function convertRun(run, html) { - var runHtml = new HtmlGenerator(); - if (run.properties.styleName) { - var style = runStyleMap[run.properties.styleName]; - if (style) { - runHtml.style(style); - } - } - if (run.properties.isBold) { - runHtml.push(styles.element("strong")); - } - if (run.properties.isItalic) { - runHtml.push(styles.element("em")); - } - convertElements(run.children, runHtml); - runHtml.closeAll(); - html.append(runHtml); - } - - var elementConverters = { - "document": function(document, html) { - convertElements(document.children, html); - }, - "paragraph": convertParagraph, - "run": convertRun, - "text": function(element, html) { - html.text(element.value); - } - }; - return { - convertToHtml: convertToHtml - } -} function Document(children) { return { diff --git a/lib/index.js b/lib/index.js index b124b81..146b507 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,9 +1,5 @@ -var q = require("q"); -var _ = require("underscore"); -var ZipFile = require("zipfile").ZipFile; - var docxReader = require("./docx-reader"); -var documents = require("./documents"); +var DocumentConverter = require("./document-to-html").DocumentConverter; var styles = require("./styles"); exports.Converter = Converter; @@ -17,7 +13,7 @@ exports.standardOptions = { }; function Converter(options) { - this._documentConverter = new documents.DocumentConverter(options); + this._documentConverter = new DocumentConverter(options); } Converter.prototype.convertToHtml = function(docxFile) { diff --git a/tests/document-to-html.tests.js b/tests/document-to-html.tests.js new file mode 100644 index 0000000..a53039b --- /dev/null +++ b/tests/document-to-html.tests.js @@ -0,0 +1,146 @@ +var assert = require("assert"); + +var documents = require("../lib/documents"); +var DocumentConverter = require("../lib/document-to-html").DocumentConverter; +var test = require("./testing").test; +var styles = require("../lib/styles"); + + +describe('DocumentConverter', function() { + 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.html, "

Hello.

"); + }); + }); + + 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.html, ""); + }); + }); + + test('can use non-default HTML element for unstyled paragraphs', function() { + var document = new documents.Document([ + paragraphOfText("Hello.") + ]); + var converter = new DocumentConverter({defaultParagraphStyle: styles.topLevelElement("h1")}); + return converter.convertToHtml(document).then(function(result) { + assert.equal(result.html, "

Hello.

"); + }); + }); + + 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.html, "

1 < 2

"); + }); + }); + + 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.html, "

Hello.

Goodbye.

"); + }); + }); + + test('uses style mappings to pick HTML element for docx paragraph', function() { + var document = new documents.Document([ + paragraphOfText("Hello.", "Heading1"), + ]); + var converter = new DocumentConverter({ + paragraphStyleMap: { + "Heading1": styles.topLevelElement("h1") + } + }); + return converter.convertToHtml(document).then(function(result) { + assert.equal(result.html, "

Hello.

"); + }); + }); + + test('can use stacked styles to generate nested HTML elements', function() { + var document = new documents.Document([ + paragraphOfText("Hello.", "Heading1") + ]); + var converter = new DocumentConverter({ + paragraphStyleMap: { + "Heading1": styles.elements(["h1", "span"]) + } + }); + return converter.convertToHtml(document).then(function(result) { + assert.equal(result.html, "

Hello.

"); + }); + }); + + test('bold runs are wrapped in tags', function() { + var run = runOfText("Hello.", {isBold: true}); + var converter = new DocumentConverter(); + return converter.convertToHtml(run).then(function(result) { + assert.equal(result.html, "Hello."); + }); + }); + + 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.html, "

Hello.

"); + }); + }); + + test('italic runs are wrapped in tags', function() { + var run = runOfText("Hello.", {isItalic: true}); + var converter = new DocumentConverter(); + return converter.convertToHtml(run).then(function(result) { + assert.equal(result.html, "Hello."); + }); + }); + + 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.html, "Hello."); + }); + }); + + test('run styles are converted to HTML if mapping exists', function() { + var run = runOfText("Hello.", {styleName: "Emphasis"}); + var converter = new DocumentConverter({ + runStyleMap: { + "Emphasis": styles.elements(["strong"]) + } + }); + return converter.convertToHtml(run).then(function(result) { + assert.equal(result.html, "Hello."); + }); + }); +}); + +function paragraphOfText(text, styleName) { + var run = runOfText(text); + return new documents.Paragraph([run], { + styleName: styleName + }); +} + +function runOfText(text, properties) { + var textElement = new documents.Text(text); + return new documents.Run([textElement], properties); +} diff --git a/tests/documents.tests.js b/tests/documents.tests.js deleted file mode 100644 index d08500d..0000000 --- a/tests/documents.tests.js +++ /dev/null @@ -1,146 +0,0 @@ -var assert = require("assert"); - -var documents = require("../lib/documents"); -var DocumentConverter = documents.DocumentConverter; -var test = require("./testing").test; -var styles = require("../lib/styles"); - - -describe('DocumentConverter', function() { - 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.html, "

Hello.

"); - }); - }); - - 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.html, ""); - }); - }); - - test('can use non-default HTML element for unstyled paragraphs', function() { - var document = new documents.Document([ - paragraphOfText("Hello.") - ]); - var converter = new DocumentConverter({defaultParagraphStyle: styles.topLevelElement("h1")}); - return converter.convertToHtml(document).then(function(result) { - assert.equal(result.html, "

Hello.

"); - }); - }); - - 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.html, "

1 < 2

"); - }); - }); - - 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.html, "

Hello.

Goodbye.

"); - }); - }); - - test('uses style mappings to pick HTML element for docx paragraph', function() { - var document = new documents.Document([ - paragraphOfText("Hello.", "Heading1"), - ]); - var converter = new DocumentConverter({ - paragraphStyleMap: { - "Heading1": styles.topLevelElement("h1") - } - }); - return converter.convertToHtml(document).then(function(result) { - assert.equal(result.html, "

Hello.

"); - }); - }); - - test('can use stacked styles to generate nested HTML elements', function() { - var document = new documents.Document([ - paragraphOfText("Hello.", "Heading1") - ]); - var converter = new DocumentConverter({ - paragraphStyleMap: { - "Heading1": styles.elements(["h1", "span"]) - } - }); - return converter.convertToHtml(document).then(function(result) { - assert.equal(result.html, "

Hello.

"); - }); - }); - - test('bold runs are wrapped in tags', function() { - var run = runOfText("Hello.", {isBold: true}); - var converter = new DocumentConverter(); - return converter.convertToHtml(run).then(function(result) { - assert.equal(result.html, "Hello."); - }); - }); - - 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.html, "

Hello.

"); - }); - }); - - test('italic runs are wrapped in tags', function() { - var run = runOfText("Hello.", {isItalic: true}); - var converter = new DocumentConverter(); - return converter.convertToHtml(run).then(function(result) { - assert.equal(result.html, "Hello."); - }); - }); - - 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.html, "Hello."); - }); - }); - - test('run styles are converted to HTML if mapping exists', function() { - var run = runOfText("Hello.", {styleName: "Emphasis"}); - var converter = new DocumentConverter({ - runStyleMap: { - "Emphasis": styles.elements(["strong"]) - } - }); - return converter.convertToHtml(run).then(function(result) { - assert.equal(result.html, "Hello."); - }); - }); -}); - -function paragraphOfText(text, styleName) { - var run = runOfText(text); - return new documents.Paragraph([run], { - styleName: styleName - }); -} - -function runOfText(text, properties) { - var textElement = new documents.Text(text); - return new documents.Run([textElement], properties); -} -- cgit v1.2.3