aboutsummaryrefslogtreecommitdiff
path: root/lib/document-to-html.js
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-08-28 19:55:24 +0100
committerMichael Williamson <mike@zwobble.org>2016-08-28 19:55:38 +0100
commitb1ae23f544c479d2b71347bbf67df7baac40d78f (patch)
tree383e694dae42ba544f690c3b0ab388a7931c0793 /lib/document-to-html.js
parent7dba15069f9a606b9e248d7e4cd024ddaa6ac3e3 (diff)
parentc42714e5f4b643de27b106a084601e39b7e5d04c (diff)
Merge branch 'master' into image-errors
Conflicts: test/mammoth.tests.js
Diffstat (limited to 'lib/document-to-html.js')
-rw-r--r--lib/document-to-html.js162
1 files changed, 114 insertions, 48 deletions
diff --git a/lib/document-to-html.js b/lib/document-to-html.js
index 6aa7a9c..e022946 100644
--- a/lib/document-to-html.js
+++ b/lib/document-to-html.js
@@ -13,18 +13,24 @@ exports.DocumentConverter = DocumentConverter;
function DocumentConverter(options) {
return {
- convertToHtml: function() {
- var conversion = new DocumentConversion(options);
- return conversion.convertToHtml.apply(this, arguments);
+ convertToHtml: function(element) {
+ var comments = _.indexBy(
+ element.type === documents.types.document ? element.comments : [],
+ "commentId"
+ );
+ var conversion = new DocumentConversion(options, comments);
+ return conversion.convertToHtml(element);
}
};
}
-function DocumentConversion(options) {
+function DocumentConversion(options, comments) {
var noteNumber = 1;
var noteReferences = [];
+ var referencedComments = [];
+
options = _.extend({ignoreEmptyParagraphs: true}, options);
var idPrefix = options.idPrefix === undefined ? "" : options.idPrefix;
@@ -89,16 +95,17 @@ function DocumentConversion(options) {
}
function convertParagraph(element, messages) {
- var style = styleForParagraph(element, messages);
-
- var children = convertElements(element.children, messages);
- if (!options.ignoreEmptyParagraphs) {
- children = [Html.forceWrite].concat(children);
- }
- return Html.pathToNodes(style, children);
+ return htmlPathForParagraph(element, messages).wrap(function() {
+ var content = convertElements(element.children, messages);
+ if (options.ignoreEmptyParagraphs) {
+ return content;
+ } else {
+ return [Html.forceWrite].concat(content);
+ }
+ });
}
- function styleForParagraph(element, messages) {
+ function htmlPathForParagraph(element, messages) {
var style = findStyle(element);
if (style) {
@@ -112,58 +119,60 @@ function DocumentConversion(options) {
}
function convertRun(run, messages) {
- var style;
- if (run.styleId) {
- style = findStyle(run);
- if (!style) {
- messages.push(unrecognisedStyleWarning("run", run));
- }
- }
- var result = convertElements(run.children, messages);
+ var nodes = function() {
+ return convertElements(run.children, messages);
+ };
+ var paths = [];
if (run.isStrikethrough) {
- result = convertRunProperty(result, "strikethrough", "s");
+ paths.push(findHtmlPathForRunProperty("strikethrough", "s"));
}
if (run.isUnderline) {
- result = convertUnderline(result);
+ paths.push(findHtmlPathForRunProperty("underline"));
}
if (run.verticalAlignment === documents.verticalAlignment.subscript) {
- result = wrapInNonFreshElement(result, "sub");
+ paths.push(htmlPaths.element("sub", {}, {fresh: false}));
}
if (run.verticalAlignment === documents.verticalAlignment.superscript) {
- result = wrapInNonFreshElement(result, "sup");
+ paths.push(htmlPaths.element("sup", {}, {fresh: false}));
}
if (run.isItalic) {
- result = convertRunProperty(result, "italic", "em");
+ paths.push(findHtmlPathForRunProperty("italic", "em"));
}
if (run.isBold) {
- result = convertRunProperty(result, "bold", "strong");
+ paths.push(findHtmlPathForRunProperty("bold", "strong"));
}
- if (style) {
- result = Html.pathToNodes(style.to, result);
+ var stylePath = htmlPaths.empty;
+ if (run.styleId) {
+ var style = findStyle(run);
+ if (style) {
+ stylePath = style.to;
+ } else {
+ messages.push(unrecognisedStyleWarning("run", run));
+ }
}
- return result;
- }
-
- function wrapInNonFreshElement(nodes, tagName) {
- return [Html.nonFreshElement(tagName, {}, nodes)];
+ paths.push(stylePath);
+
+ paths.forEach(function(path) {
+ nodes = path.wrap.bind(path, nodes);
+ });
+
+ return nodes();
}
- function convertUnderline(runHtml) {
- var style = findStyle({type: "underline"});
- if (style) {
- return Html.pathToNodes(style.to, runHtml);
+ function findHtmlPathForRunProperty(elementType, defaultTagName) {
+ var path = findHtmlPath({type: elementType});
+ if (path) {
+ return path;
+ } else if (defaultTagName) {
+ return htmlPaths.element(defaultTagName, {}, {fresh: false});
} else {
- return runHtml;
+ return htmlPaths.empty;
}
}
- function convertRunProperty(result, elementType, defaultTagName) {
- var style = findStyle({type: elementType});
- if (style) {
- return Html.pathToNodes(style.to, result);
- } else {
- return wrapInNonFreshElement(result, defaultTagName);
- }
+ function findHtmlPath(element, defaultPath) {
+ var style = findStyle(element);
+ return style ? style.to : defaultPath;
}
function findStyle(element) {
@@ -192,11 +201,19 @@ function DocumentConversion(options) {
}
function noteHtmlId(note) {
- return htmlId(note.noteType + "-" + note.noteId);
+ return referentHtmlId(note.noteType, note.noteId);
}
function noteRefHtmlId(note) {
- return htmlId(note.noteType + "-ref-" + note.noteId);
+ return referenceHtmlId(note.noteType, note.noteId);
+ }
+
+ function referentHtmlId(referenceType, referenceId) {
+ return htmlId(referenceType + "-" + referenceId);
+ }
+
+ function referenceHtmlId(referenceType, referenceId) {
+ return htmlId(referenceType + "-ref-" + referenceId);
}
function htmlId(suffix) {
@@ -226,6 +243,46 @@ function DocumentConversion(options) {
];
}
+ function convertCommentReference(reference, messages) {
+ return findHtmlPath(reference, htmlPaths.ignore).wrap(function() {
+ var comment = comments[reference.commentId];
+ var count = referencedComments.length + 1;
+ var label = "[" + commentAuthorLabel(comment) + count + "]";
+ referencedComments.push({label: label, comment: comment});
+ // TODO: remove duplication with note references
+ return [
+ Html.freshElement("a", {
+ href: "#" + referentHtmlId("comment", reference.commentId),
+ id: referenceHtmlId("comment", reference.commentId)
+ }, [Html.text(label)])
+ ];
+ });
+ }
+
+ function convertComment(referencedComment, messages) {
+ // TODO: remove duplication with note references
+
+ var label = referencedComment.label;
+ var comment = referencedComment.comment;
+ var body = convertElements(comment.body).concat([
+ Html.nonFreshElement("p", {}, [
+ Html.text(" "),
+ Html.freshElement("a", {"href": "#" + referenceHtmlId("comment", comment.commentId)}, [
+ Html.text("↑")
+ ])
+ ])
+ ]);
+
+ return [
+ Html.freshElement(
+ "dt",
+ {"id": referentHtmlId("comment", comment.commentId)},
+ [Html.text("Comment " + label)]
+ ),
+ Html.freshElement("dd", {}, body)
+ ];
+ }
+
function wrapChildrenInFreshElement(element, wrapElementName, messages) {
var children = convertElements(element.children, messages);
return [
@@ -241,7 +298,10 @@ function DocumentConversion(options) {
});
var notesNodes = convertElements(notes, messages);
return children.concat([
- Html.freshElement("ol", {}, notesNodes)
+ Html.freshElement("ol", {}, notesNodes),
+ Html.freshElement("dl", {}, flatMap(referencedComments, function(referencedComment) {
+ return convertComment(referencedComment, messages);
+ }))
]);
},
"paragraph": convertParagraph,
@@ -283,6 +343,8 @@ function DocumentConversion(options) {
return Html.freshElement("li", {id: noteHtmlId(element)}, body);
},
+ "commentReference": convertCommentReference,
+ "comment": convertComment,
"image": deferredConversion(recoveringConvertImage(options.convertImage || defaultConvertImage)),
"table": convertTable,
"tableRow": convertTableRow,
@@ -331,3 +393,7 @@ function walkHtml(nodes, callback) {
}
});
}
+
+var commentAuthorLabel = exports.commentAuthorLabel = function commentAuthorLabel(comment) {
+ return comment.authorInitials || "";
+};