diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-08-28 19:55:24 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-08-28 19:55:38 +0100 |
| commit | b1ae23f544c479d2b71347bbf67df7baac40d78f (patch) | |
| tree | 383e694dae42ba544f690c3b0ab388a7931c0793 /lib/document-to-html.js | |
| parent | 7dba15069f9a606b9e248d7e4cd024ddaa6ac3e3 (diff) | |
| parent | c42714e5f4b643de27b106a084601e39b7e5d04c (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.js | 162 |
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 || ""; +}; |
