aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2013-04-01 22:21:56 +0100
committerMichael Williamson <mike@zwobble.org>2013-04-01 22:21:56 +0100
commit720f997476ab2d0ac3cef17b890b423133ae5e7d (patch)
treeb0af74d498a82a6161af1aa0ca3fd39f32c19a8a
parenta70e8e05948c593fdc253b6d0a256d7aa656d988 (diff)
Generate images using data URIs
-rw-r--r--lib/document-to-html.js50
-rw-r--r--lib/docx-reader.js4
-rw-r--r--lib/html-generator.js14
-rw-r--r--tests/document-to-html.tests.js22
4 files changed, 75 insertions, 15 deletions
diff --git a/lib/document-to-html.js b/lib/document-to-html.js
index 1224878..b9efe0d 100644
--- a/lib/document-to-html.js
+++ b/lib/document-to-html.js
@@ -15,24 +15,28 @@ function DocumentConverter(options) {
function convertToHtml(document) {
var html = new HtmlGenerator();
- elementToHtml(document, html);
- html.closeAll();
-
- return q.when({
- html: html.asString()
- });
+ return elementToHtml(document, html)
+ .then(function() {
+ html.closeAll();
+
+ return {
+ html: html.asString()
+ };
+ });
}
function convertElements(elements, html) {
- elements.forEach(function(element) {
- elementToHtml(element, html);
+ return forEachPromise(elements, function(element) {
+ return elementToHtml(element, html);
});
}
function elementToHtml(element, html) {
var handler = elementConverters[element.type];
if (handler) {
- handler(element, html);
+ return q.when(handler(element, html));
+ } else {
+ return q.when();
}
}
@@ -66,7 +70,7 @@ function DocumentConverter(options) {
var elementConverters = {
"document": function(document, html) {
- convertElements(document.children, html);
+ return convertElements(document.children, html);
},
"paragraph": convertParagraph,
"run": convertRun,
@@ -75,11 +79,33 @@ function DocumentConverter(options) {
},
"hyperlink": function(element, html) {
html.push(styles.element("a", {href: element.href}));
- convertElements(element.children, html);
- html.pop();
+ return convertElements(element.children, html).then(function() {
+ html.pop();
+ });
+ },
+ "image": function(element, html) {
+ return element.read().then(function(imageBuffer) {
+ var src = "data:image/png;base64," + imageBuffer.toString("base64");
+ html.selfClosing(styles.element("img", {"src": src}))
+ });
}
};
return {
convertToHtml: convertToHtml
}
}
+
+function forEachPromise(array, func) {
+ var index = -1;
+ return next();
+
+ function next() {
+ index++;
+ if (index < array.length) {
+ return q.when(func(array[index]))
+ .then(next);
+ } else {
+ return q.when();
+ }
+ }
+}
diff --git a/lib/docx-reader.js b/lib/docx-reader.js
index d15ec3e..eece7bb 100644
--- a/lib/docx-reader.js
+++ b/lib/docx-reader.js
@@ -167,7 +167,9 @@ function DocumentReader(relationships, docxFile) {
.first("a:blip")
.attributes["r:embed"];
var imagePath = relationships[relationshipId].target;
- var image = documents.Image(docxFile.read.bind(docxFile, imagePath));
+ var image = documents.Image(function() {
+ return docxFile.read(imagePath);
+ })
return new Result(image);
}
};
diff --git a/lib/html-generator.js b/lib/html-generator.js
index 179d6d0..6a8fb32 100644
--- a/lib/html-generator.js
+++ b/lib/html-generator.js
@@ -79,10 +79,19 @@ function HtmlGenerator() {
function writeElement(stackElement) {
stackElement.written = true;
var element = stackElement.element;
- var attributeString = _.map(element.attributes, function(value, key) {
+ var attributeString = generateAttributeString(element.attributes)
+ fragments.push(util.format("<%s%s>", element.tagName, attributeString));
+ }
+
+ function selfClosing(element) {
+ var attributeString = generateAttributeString(element.attributes)
+ fragments.push(util.format("<%s%s />", element.tagName, attributeString));
+ }
+
+ function generateAttributeString(attributes) {
+ return _.map(attributes, function(value, key) {
return util.format(' %s="%s"', key, value);
}).join("");
- fragments.push(util.format("<%s%s>", element.tagName, attributeString));
}
return {
@@ -93,6 +102,7 @@ function HtmlGenerator() {
append: append,
push: push,
pop: pop,
+ selfClosing: selfClosing,
_fragments: fragments
};
}
diff --git a/tests/document-to-html.tests.js b/tests/document-to-html.tests.js
index 7c84482..f8ea482 100644
--- a/tests/document-to-html.tests.js
+++ b/tests/document-to-html.tests.js
@@ -1,4 +1,5 @@
var assert = require("assert");
+var q = require("q");
var documents = require("../lib/documents");
var DocumentConverter = require("../lib/document-to-html").DocumentConverter;
@@ -7,6 +8,14 @@ var styles = require("../lib/styles");
describe('DocumentConverter', function() {
+ 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.html, "");
+ });
+ });
+
test('should convert document containing one paragraph to single p element', function() {
var document = new documents.Document([
paragraphOfText("Hello.")
@@ -142,6 +151,19 @@ describe('DocumentConverter', function() {
assert.equal(result.html, '<a href="http://www.example.com">Hello.</a>');
});
});
+
+ test('images are written with data URIs', function() {
+ var imageBuffer = new Buffer("Not an image at all!");
+ var image = new documents.Image(
+ function() {
+ return q.when(imageBuffer);
+ }
+ );
+ var converter = new DocumentConverter();
+ return converter.convertToHtml(image).then(function(result) {
+ assert.equal(result.html, '<img src="data:image/png;base64,' + imageBuffer.toString("base64") + '" />');
+ });
+ });
});
function paragraphOfText(text, styleName) {