UNPKG

@anohanafes/offline-document-viewer

Version:

🔒 完全离线的多格式文档预览器 - 支持PDF、DOCX、PPTX、XLSX、CSV,按需加载,支持URL预览

1,308 lines (1,165 loc) 1 MB
// Module: @xmldom/xmldom@0.8.6 // License: MIT // // Module: base64-js@1.5.1 // License: MIT // // Module: bluebird@3.4.7 // License: MIT // // Module: buffer@4.9.1 // License: MIT // // Module: dingbat-to-unicode@1.0.1 // License: BSD-2-Clause // // Module: ieee754@1.1.8 // License: BSD-3-Clause // // Module: isarray@1.0.0 // License: MIT // // Module: jszip@3.7.1 // License: (MIT OR GPL-3.0-or-later) // // Module: lop@0.4.2 // License: BSD-2-Clause // // Module: mammoth@1.9.1 // License: BSD-2-Clause // // Module: option@0.2.4 // License: BSD-2-Clause // // Module: process@0.11.9 // License: MIT // // Module: underscore@1.13.1 // License: MIT // // Module: xmlbuilder@10.0.0 // License: MIT // (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.mammoth = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var promises = require("../../lib/promises"); exports.Files = Files; function Files() { function read(uri) { return promises.reject(new Error("could not open external image: '" + uri + "'\ncannot open linked files from a web browser")); } return { read: read }; } },{"../../lib/promises":23}],2:[function(require,module,exports){ var promises = require("../lib/promises"); var zipfile = require("../lib/zipfile"); exports.openZip = openZip; function openZip(options) { if (options.arrayBuffer) { return promises.resolve(zipfile.openArrayBuffer(options.arrayBuffer)); } else { return promises.reject(new Error("Could not find file in options")); } } },{"../lib/promises":23,"../lib/zipfile":40}],3:[function(require,module,exports){ var _ = require("underscore"); var promises = require("./promises"); var documents = require("./documents"); var htmlPaths = require("./styles/html-paths"); var results = require("./results"); var images = require("./images"); var Html = require("./html"); var writers = require("./writers"); exports.DocumentConverter = DocumentConverter; function DocumentConverter(options) { return { 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, comments) { var noteNumber = 1; var noteReferences = []; var referencedComments = []; options = _.extend({ignoreEmptyParagraphs: true}, options); var idPrefix = options.idPrefix === undefined ? "" : options.idPrefix; var ignoreEmptyParagraphs = options.ignoreEmptyParagraphs; var defaultParagraphStyle = htmlPaths.topLevelElement("p"); var styleMap = options.styleMap || []; function convertToHtml(document) { var messages = []; var html = elementToHtml(document, messages, {}); var deferredNodes = []; walkHtml(html, function(node) { if (node.type === "deferred") { deferredNodes.push(node); } }); var deferredValues = {}; return promises.mapSeries(deferredNodes, function(deferred) { return deferred.value().then(function(value) { deferredValues[deferred.id] = value; }); }).then(function() { function replaceDeferred(nodes) { return flatMap(nodes, function(node) { if (node.type === "deferred") { return deferredValues[node.id]; } else if (node.children) { return [ _.extend({}, node, { children: replaceDeferred(node.children) }) ]; } else { return [node]; } }); } var writer = writers.writer({ prettyPrint: options.prettyPrint, outputFormat: options.outputFormat }); Html.write(writer, Html.simplify(replaceDeferred(html))); return new results.Result(writer.asString(), messages); }); } function convertElements(elements, messages, options) { return flatMap(elements, function(element) { return elementToHtml(element, messages, options); }); } function elementToHtml(element, messages, options) { if (!options) { throw new Error("options not set"); } var handler = elementConverters[element.type]; if (handler) { return handler(element, messages, options); } else { return []; } } function convertParagraph(element, messages, options) { return htmlPathForParagraph(element, messages).wrap(function() { var content = convertElements(element.children, messages, options); if (ignoreEmptyParagraphs) { return content; } else { return [Html.forceWrite].concat(content); } }); } function htmlPathForParagraph(element, messages) { var style = findStyle(element); if (style) { return style.to; } else { if (element.styleId) { messages.push(unrecognisedStyleWarning("paragraph", element)); } return defaultParagraphStyle; } } function convertRun(run, messages, options) { var nodes = function() { return convertElements(run.children, messages, options); }; var paths = []; if (run.highlight !== null) { var path = findHtmlPath({type: "highlight", color: run.highlight}); if (path) { paths.push(path); } } if (run.isSmallCaps) { paths.push(findHtmlPathForRunProperty("smallCaps")); } if (run.isAllCaps) { paths.push(findHtmlPathForRunProperty("allCaps")); } if (run.isStrikethrough) { paths.push(findHtmlPathForRunProperty("strikethrough", "s")); } if (run.isUnderline) { paths.push(findHtmlPathForRunProperty("underline")); } if (run.verticalAlignment === documents.verticalAlignment.subscript) { paths.push(htmlPaths.element("sub", {}, {fresh: false})); } if (run.verticalAlignment === documents.verticalAlignment.superscript) { paths.push(htmlPaths.element("sup", {}, {fresh: false})); } if (run.isItalic) { paths.push(findHtmlPathForRunProperty("italic", "em")); } if (run.isBold) { paths.push(findHtmlPathForRunProperty("bold", "strong")); } var stylePath = htmlPaths.empty; var style = findStyle(run); if (style) { stylePath = style.to; } else if (run.styleId) { messages.push(unrecognisedStyleWarning("run", run)); } paths.push(stylePath); paths.forEach(function(path) { nodes = path.wrap.bind(path, nodes); }); return nodes(); } function findHtmlPathForRunProperty(elementType, defaultTagName) { var path = findHtmlPath({type: elementType}); if (path) { return path; } else if (defaultTagName) { return htmlPaths.element(defaultTagName, {}, {fresh: false}); } else { return htmlPaths.empty; } } function findHtmlPath(element, defaultPath) { var style = findStyle(element); return style ? style.to : defaultPath; } function findStyle(element) { for (var i = 0; i < styleMap.length; i++) { if (styleMap[i].from.matches(element)) { return styleMap[i]; } } } function recoveringConvertImage(convertImage) { return function(image, messages) { return promises.attempt(function() { return convertImage(image, messages); }).caught(function(error) { messages.push(results.error(error)); return []; }); }; } function noteHtmlId(note) { return referentHtmlId(note.noteType, note.noteId); } function noteRefHtmlId(note) { 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) { return idPrefix + suffix; } var defaultTablePath = htmlPaths.elements([ htmlPaths.element("table", {}, {fresh: true}) ]); function convertTable(element, messages, options) { return findHtmlPath(element, defaultTablePath).wrap(function() { return convertTableChildren(element, messages, options); }); } function convertTableChildren(element, messages, options) { var bodyIndex = _.findIndex(element.children, function(child) { return !child.type === documents.types.tableRow || !child.isHeader; }); if (bodyIndex === -1) { bodyIndex = element.children.length; } var children; if (bodyIndex === 0) { children = convertElements( element.children, messages, _.extend({}, options, {isTableHeader: false}) ); } else { var headRows = convertElements( element.children.slice(0, bodyIndex), messages, _.extend({}, options, {isTableHeader: true}) ); var bodyRows = convertElements( element.children.slice(bodyIndex), messages, _.extend({}, options, {isTableHeader: false}) ); children = [ Html.freshElement("thead", {}, headRows), Html.freshElement("tbody", {}, bodyRows) ]; } return [Html.forceWrite].concat(children); } function convertTableRow(element, messages, options) { var children = convertElements(element.children, messages, options); return [ Html.freshElement("tr", {}, [Html.forceWrite].concat(children)) ]; } function convertTableCell(element, messages, options) { var tagName = options.isTableHeader ? "th" : "td"; var children = convertElements(element.children, messages, options); var attributes = {}; if (element.colSpan !== 1) { attributes.colspan = element.colSpan.toString(); } if (element.rowSpan !== 1) { attributes.rowspan = element.rowSpan.toString(); } return [ Html.freshElement(tagName, attributes, [Html.forceWrite].concat(children)) ]; } function convertCommentReference(reference, messages, options) { 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, options) { // TODO: remove duplication with note references var label = referencedComment.label; var comment = referencedComment.comment; var body = convertElements(comment.body, messages, options).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 convertBreak(element, messages, options) { return htmlPathForBreak(element).wrap(function() { return []; }); } function htmlPathForBreak(element) { var style = findStyle(element); if (style) { return style.to; } else if (element.breakType === "line") { return htmlPaths.topLevelElement("br"); } else { return htmlPaths.empty; } } var elementConverters = { "document": function(document, messages, options) { var children = convertElements(document.children, messages, options); var notes = noteReferences.map(function(noteReference) { return document.notes.resolve(noteReference); }); var notesNodes = convertElements(notes, messages, options); return children.concat([ Html.freshElement("ol", {}, notesNodes), Html.freshElement("dl", {}, flatMap(referencedComments, function(referencedComment) { return convertComment(referencedComment, messages, options); })) ]); }, "paragraph": convertParagraph, "run": convertRun, "text": function(element, messages, options) { return [Html.text(element.value)]; }, "tab": function(element, messages, options) { return [Html.text("\t")]; }, "hyperlink": function(element, messages, options) { var href = element.anchor ? "#" + htmlId(element.anchor) : element.href; var attributes = {href: href}; if (element.targetFrame != null) { attributes.target = element.targetFrame; } var children = convertElements(element.children, messages, options); return [Html.nonFreshElement("a", attributes, children)]; }, "checkbox": function(element) { var attributes = {type: "checkbox"}; if (element.checked) { attributes["checked"] = "checked"; } return [Html.freshElement("input", attributes)]; }, "bookmarkStart": function(element, messages, options) { var anchor = Html.freshElement("a", { id: htmlId(element.name) }, [Html.forceWrite]); return [anchor]; }, "noteReference": function(element, messages, options) { noteReferences.push(element); var anchor = Html.freshElement("a", { href: "#" + noteHtmlId(element), id: noteRefHtmlId(element) }, [Html.text("[" + (noteNumber++) + "]")]); return [Html.freshElement("sup", {}, [anchor])]; }, "note": function(element, messages, options) { var children = convertElements(element.body, messages, options); var backLink = Html.elementWithTag(htmlPaths.element("p", {}, {fresh: false}), [ Html.text(" "), Html.freshElement("a", {href: "#" + noteRefHtmlId(element)}, [Html.text("↑")]) ]); var body = children.concat([backLink]); return Html.freshElement("li", {id: noteHtmlId(element)}, body); }, "commentReference": convertCommentReference, "comment": convertComment, "image": deferredConversion(recoveringConvertImage(options.convertImage || images.dataUri)), "table": convertTable, "tableRow": convertTableRow, "tableCell": convertTableCell, "break": convertBreak }; return { convertToHtml: convertToHtml }; } var deferredId = 1; function deferredConversion(func) { return function(element, messages, options) { return [ { type: "deferred", id: deferredId++, value: function() { return func(element, messages, options); } } ]; }; } function unrecognisedStyleWarning(type, element) { return results.warning( "Unrecognised " + type + " style: '" + element.styleName + "'" + " (Style ID: " + element.styleId + ")" ); } function flatMap(values, func) { return _.flatten(values.map(func), true); } function walkHtml(nodes, callback) { nodes.forEach(function(node) { callback(node); if (node.children) { walkHtml(node.children, callback); } }); } var commentAuthorLabel = exports.commentAuthorLabel = function commentAuthorLabel(comment) { return comment.authorInitials || ""; }; },{"./documents":4,"./html":18,"./images":20,"./promises":23,"./results":25,"./styles/html-paths":28,"./writers":33,"underscore":102}],4:[function(require,module,exports){ (function (Buffer){ var _ = require("underscore"); var types = exports.types = { document: "document", paragraph: "paragraph", run: "run", text: "text", tab: "tab", checkbox: "checkbox", hyperlink: "hyperlink", noteReference: "noteReference", image: "image", note: "note", commentReference: "commentReference", comment: "comment", table: "table", tableRow: "tableRow", tableCell: "tableCell", "break": "break", bookmarkStart: "bookmarkStart" }; function Document(children, options) { options = options || {}; return { type: types.document, children: children, notes: options.notes || new Notes({}), comments: options.comments || [] }; } function Paragraph(children, properties) { properties = properties || {}; var indent = properties.indent || {}; return { type: types.paragraph, children: children, styleId: properties.styleId || null, styleName: properties.styleName || null, numbering: properties.numbering || null, alignment: properties.alignment || null, indent: { start: indent.start || null, end: indent.end || null, firstLine: indent.firstLine || null, hanging: indent.hanging || null } }; } function Run(children, properties) { properties = properties || {}; return { type: types.run, children: children, styleId: properties.styleId || null, styleName: properties.styleName || null, isBold: !!properties.isBold, isUnderline: !!properties.isUnderline, isItalic: !!properties.isItalic, isStrikethrough: !!properties.isStrikethrough, isAllCaps: !!properties.isAllCaps, isSmallCaps: !!properties.isSmallCaps, verticalAlignment: properties.verticalAlignment || verticalAlignment.baseline, font: properties.font || null, fontSize: properties.fontSize || null, highlight: properties.highlight || null }; } var verticalAlignment = { baseline: "baseline", superscript: "superscript", subscript: "subscript" }; function Text(value) { return { type: types.text, value: value }; } function Tab() { return { type: types.tab }; } function Checkbox(options) { return { type: types.checkbox, checked: options.checked }; } function Hyperlink(children, options) { return { type: types.hyperlink, children: children, href: options.href, anchor: options.anchor, targetFrame: options.targetFrame }; } function NoteReference(options) { return { type: types.noteReference, noteType: options.noteType, noteId: options.noteId }; } function Notes(notes) { this._notes = _.indexBy(notes, function(note) { return noteKey(note.noteType, note.noteId); }); } Notes.prototype.resolve = function(reference) { return this.findNoteByKey(noteKey(reference.noteType, reference.noteId)); }; Notes.prototype.findNoteByKey = function(key) { return this._notes[key] || null; }; function Note(options) { return { type: types.note, noteType: options.noteType, noteId: options.noteId, body: options.body }; } function commentReference(options) { return { type: types.commentReference, commentId: options.commentId }; } function comment(options) { return { type: types.comment, commentId: options.commentId, body: options.body, authorName: options.authorName, authorInitials: options.authorInitials }; } function noteKey(noteType, id) { return noteType + "-" + id; } function Image(options) { return { type: types.image, // `read` is retained for backwards compatibility, but other read // methods should be preferred. read: function(encoding) { if (encoding) { return options.readImage(encoding); } else { return options.readImage().then(function(arrayBuffer) { return Buffer.from(arrayBuffer); }); } }, readAsArrayBuffer: function() { return options.readImage(); }, readAsBase64String: function() { return options.readImage("base64"); }, readAsBuffer: function() { return options.readImage().then(function(arrayBuffer) { return Buffer.from(arrayBuffer); }); }, altText: options.altText, contentType: options.contentType }; } function Table(children, properties) { properties = properties || {}; return { type: types.table, children: children, styleId: properties.styleId || null, styleName: properties.styleName || null }; } function TableRow(children, options) { options = options || {}; return { type: types.tableRow, children: children, isHeader: options.isHeader || false }; } function TableCell(children, options) { options = options || {}; return { type: types.tableCell, children: children, colSpan: options.colSpan == null ? 1 : options.colSpan, rowSpan: options.rowSpan == null ? 1 : options.rowSpan }; } function Break(breakType) { return { type: types["break"], breakType: breakType }; } function BookmarkStart(options) { return { type: types.bookmarkStart, name: options.name }; } exports.document = exports.Document = Document; exports.paragraph = exports.Paragraph = Paragraph; exports.run = exports.Run = Run; exports.text = exports.Text = Text; exports.tab = exports.Tab = Tab; exports.checkbox = exports.Checkbox = Checkbox; exports.Hyperlink = Hyperlink; exports.noteReference = exports.NoteReference = NoteReference; exports.Notes = Notes; exports.Note = Note; exports.commentReference = commentReference; exports.comment = comment; exports.Image = Image; exports.Table = Table; exports.TableRow = TableRow; exports.TableCell = TableCell; exports.lineBreak = Break("line"); exports.pageBreak = Break("page"); exports.columnBreak = Break("column"); exports.BookmarkStart = BookmarkStart; exports.verticalAlignment = verticalAlignment; }).call(this,require("buffer").Buffer) },{"buffer":83,"underscore":102}],5:[function(require,module,exports){ exports.createBodyReader = createBodyReader; exports._readNumberingProperties = readNumberingProperties; var dingbatToUnicode = require("dingbat-to-unicode"); var _ = require("underscore"); var documents = require("../documents"); var Result = require("../results").Result; var warning = require("../results").warning; var xml = require("../xml"); var uris = require("./uris"); function createBodyReader(options) { return { readXmlElement: function(element) { return new BodyReader(options).readXmlElement(element); }, readXmlElements: function(elements) { return new BodyReader(options).readXmlElements(elements); } }; } function BodyReader(options) { var complexFieldStack = []; var currentInstrText = []; // When a paragraph is marked as deleted, its contents should be combined // with the following paragraph. See 17.13.5.15 del (Deleted Paragraph) of // ECMA-376 4th edition Part 1. var deletedParagraphContents = []; var relationships = options.relationships; var contentTypes = options.contentTypes; var docxFile = options.docxFile; var files = options.files; var numbering = options.numbering; var styles = options.styles; function readXmlElements(elements) { var results = elements.map(readXmlElement); return combineResults(results); } function readXmlElement(element) { if (element.type === "element") { var handler = xmlElementReaders[element.name]; if (handler) { return handler(element); } else if (!Object.prototype.hasOwnProperty.call(ignoreElements, element.name)) { var message = warning("An unrecognised element was ignored: " + element.name); return emptyResultWithMessages([message]); } } return emptyResult(); } function readParagraphProperties(element) { return readParagraphStyle(element).map(function(style) { return { type: "paragraphProperties", styleId: style.styleId, styleName: style.name, alignment: element.firstOrEmpty("w:jc").attributes["w:val"], numbering: readNumberingProperties(style.styleId, element.firstOrEmpty("w:numPr"), numbering), indent: readParagraphIndent(element.firstOrEmpty("w:ind")) }; }); } function readParagraphIndent(element) { return { start: element.attributes["w:start"] || element.attributes["w:left"], end: element.attributes["w:end"] || element.attributes["w:right"], firstLine: element.attributes["w:firstLine"], hanging: element.attributes["w:hanging"] }; } function readRunProperties(element) { return readRunStyle(element).map(function(style) { var fontSizeString = element.firstOrEmpty("w:sz").attributes["w:val"]; // w:sz gives the font size in half points, so halve the value to get the size in points var fontSize = /^[0-9]+$/.test(fontSizeString) ? parseInt(fontSizeString, 10) / 2 : null; return { type: "runProperties", styleId: style.styleId, styleName: style.name, verticalAlignment: element.firstOrEmpty("w:vertAlign").attributes["w:val"], font: element.firstOrEmpty("w:rFonts").attributes["w:ascii"], fontSize: fontSize, isBold: readBooleanElement(element.first("w:b")), isUnderline: readUnderline(element.first("w:u")), isItalic: readBooleanElement(element.first("w:i")), isStrikethrough: readBooleanElement(element.first("w:strike")), isAllCaps: readBooleanElement(element.first("w:caps")), isSmallCaps: readBooleanElement(element.first("w:smallCaps")), highlight: readHighlightValue(element.firstOrEmpty("w:highlight").attributes["w:val"]) }; }); } function readUnderline(element) { if (element) { var value = element.attributes["w:val"]; return value !== undefined && value !== "false" && value !== "0" && value !== "none"; } else { return false; } } function readBooleanElement(element) { if (element) { var value = element.attributes["w:val"]; return value !== "false" && value !== "0"; } else { return false; } } function readBooleanAttributeValue(value) { return value !== "false" && value !== "0"; } function readHighlightValue(value) { if (!value || value === "none") { return null; } else { return value; } } function readParagraphStyle(element) { return readStyle(element, "w:pStyle", "Paragraph", styles.findParagraphStyleById); } function readRunStyle(element) { return readStyle(element, "w:rStyle", "Run", styles.findCharacterStyleById); } function readTableStyle(element) { return readStyle(element, "w:tblStyle", "Table", styles.findTableStyleById); } function readStyle(element, styleTagName, styleType, findStyleById) { var messages = []; var styleElement = element.first(styleTagName); var styleId = null; var name = null; if (styleElement) { styleId = styleElement.attributes["w:val"]; if (styleId) { var style = findStyleById(styleId); if (style) { name = style.name; } else { messages.push(undefinedStyleWarning(styleType, styleId)); } } } return elementResultWithMessages({styleId: styleId, name: name}, messages); } function readFldChar(element) { var type = element.attributes["w:fldCharType"]; if (type === "begin") { complexFieldStack.push({type: "begin", fldChar: element}); currentInstrText = []; } else if (type === "end") { var complexFieldEnd = complexFieldStack.pop(); if (complexFieldEnd.type === "begin") { complexFieldEnd = parseCurrentInstrText(complexFieldEnd); } if (complexFieldEnd.type === "checkbox") { return elementResult(documents.checkbox({ checked: complexFieldEnd.checked })); } } else if (type === "separate") { var complexFieldSeparate = complexFieldStack.pop(); var complexField = parseCurrentInstrText(complexFieldSeparate); complexFieldStack.push(complexField); } return emptyResult(); } function currentHyperlinkOptions() { var topHyperlink = _.last(complexFieldStack.filter(function(complexField) { return complexField.type === "hyperlink"; })); return topHyperlink ? topHyperlink.options : null; } function parseCurrentInstrText(complexField) { return parseInstrText( currentInstrText.join(''), complexField.type === "begin" ? complexField.fldChar : xml.emptyElement ); } function parseInstrText(instrText, fldChar) { var externalLinkResult = /\s*HYPERLINK "(.*)"/.exec(instrText); if (externalLinkResult) { return {type: "hyperlink", options: {href: externalLinkResult[1]}}; } var internalLinkResult = /\s*HYPERLINK\s+\\l\s+"(.*)"/.exec(instrText); if (internalLinkResult) { return {type: "hyperlink", options: {anchor: internalLinkResult[1]}}; } var checkboxResult = /\s*FORMCHECKBOX\s*/.exec(instrText); if (checkboxResult) { var checkboxElement = fldChar .firstOrEmpty("w:ffData") .firstOrEmpty("w:checkBox"); var checkedElement = checkboxElement.first("w:checked"); var checked = checkedElement == null ? readBooleanElement(checkboxElement.first("w:default")) : readBooleanElement(checkedElement); return {type: "checkbox", checked: checked}; } return {type: "unknown"}; } function readInstrText(element) { currentInstrText.push(element.text()); return emptyResult(); } function readSymbol(element) { // See 17.3.3.30 sym (Symbol Character) of ECMA-376 4th edition Part 1 var font = element.attributes["w:font"]; var char = element.attributes["w:char"]; var unicodeCharacter = dingbatToUnicode.hex(font, char); if (unicodeCharacter == null && /^F0..$/.test(char)) { unicodeCharacter = dingbatToUnicode.hex(font, char.substring(2)); } if (unicodeCharacter == null) { return emptyResultWithMessages([warning( "A w:sym element with an unsupported character was ignored: char " + char + " in font " + font )]); } else { return elementResult(new documents.Text(unicodeCharacter.string)); } } function noteReferenceReader(noteType) { return function(element) { var noteId = element.attributes["w:id"]; return elementResult(new documents.NoteReference({ noteType: noteType, noteId: noteId })); }; } function readCommentReference(element) { return elementResult(documents.commentReference({ commentId: element.attributes["w:id"] })); } function readChildElements(element) { return readXmlElements(element.children); } var xmlElementReaders = { "w:p": function(element) { var paragraphPropertiesElement = element.firstOrEmpty("w:pPr"); var isDeleted = !!paragraphPropertiesElement .firstOrEmpty("w:rPr") .first("w:del"); if (isDeleted) { element.children.forEach(function(child) { deletedParagraphContents.push(child); }); return emptyResult(); } else { var childrenXml = element.children; if (deletedParagraphContents.length > 0) { childrenXml = deletedParagraphContents.concat(childrenXml); deletedParagraphContents = []; } return ReadResult.map( readParagraphProperties(paragraphPropertiesElement), readXmlElements(childrenXml), function(properties, children) { return new documents.Paragraph(children, properties); } ).insertExtra(); } }, "w:r": function(element) { return ReadResult.map( readRunProperties(element.firstOrEmpty("w:rPr")), readXmlElements(element.children), function(properties, children) { var hyperlinkOptions = currentHyperlinkOptions(); if (hyperlinkOptions !== null) { children = [new documents.Hyperlink(children, hyperlinkOptions)]; } return new documents.Run(children, properties); } ); }, "w:fldChar": readFldChar, "w:instrText": readInstrText, "w:t": function(element) { return elementResult(new documents.Text(element.text())); }, "w:tab": function(element) { return elementResult(new documents.Tab()); }, "w:noBreakHyphen": function() { return elementResult(new documents.Text("\u2011")); }, "w:softHyphen": function(element) { return elementResult(new documents.Text("\u00AD")); }, "w:sym": readSymbol, "w:hyperlink": function(element) { var relationshipId = element.attributes["r:id"]; var anchor = element.attributes["w:anchor"]; return readXmlElements(element.children).map(function(children) { function create(options) { var targetFrame = element.attributes["w:tgtFrame"] || null; return new documents.Hyperlink( children, _.extend({targetFrame: targetFrame}, options) ); } if (relationshipId) { var href = relationships.findTargetByRelationshipId(relationshipId); if (anchor) { href = uris.replaceFragment(href, anchor); } return create({href: href}); } else if (anchor) { return create({anchor: anchor}); } else { return children; } }); }, "w:tbl": readTable, "w:tr": readTableRow, "w:tc": readTableCell, "w:footnoteReference": noteReferenceReader("footnote"), "w:endnoteReference": noteReferenceReader("endnote"), "w:commentReference": readCommentReference, "w:br": function(element) { var breakType = element.attributes["w:type"]; if (breakType == null || breakType === "textWrapping") { return elementResult(documents.lineBreak); } else if (breakType === "page") { return elementResult(documents.pageBreak); } else if (breakType === "column") { return elementResult(documents.columnBreak); } else { return emptyResultWithMessages([warning("Unsupported break type: " + breakType)]); } }, "w:bookmarkStart": function(element){ var name = element.attributes["w:name"]; if (name === "_GoBack") { return emptyResult(); } else { return elementResult(new documents.BookmarkStart({name: name})); } }, "mc:AlternateContent": function(element) { return readChildElements(element.firstOrEmpty("mc:Fallback")); }, "w:sdt": function(element) { var checkbox = element .firstOrEmpty("w:sdtPr") .first("wordml:checkbox"); if (checkbox) { var checkedElement = checkbox.first("wordml:checked"); var isChecked = !!checkedElement && readBooleanAttributeValue( checkedElement.attributes["wordml:val"] ); return elementResult(documents.checkbox({ checked: isChecked })); } else { return readXmlElements(element.firstOrEmpty("w:sdtContent").children); } }, "w:ins": readChildElements, "w:object": readChildElements, "w:smartTag": readChildElements, "w:drawing": readChildElements, "w:pict": function(element) { return readChildElements(element).toExtra(); }, "v:roundrect": readChildElements, "v:shape": readChildElements, "v:textbox": readChildElements, "w:txbxContent": readChildElements, "wp:inline": readDrawingElement, "wp:anchor": readDrawingElement, "v:imagedata": readImageData, "v:group": readChildElements, "v:rect": readChildElements }; return { readXmlElement: readXmlElement, readXmlElements: readXmlElements }; function readTable(element) { var propertiesResult = readTableProperties(element.firstOrEmpty("w:tblPr")); return readXmlElements(element.children) .flatMap(calculateRowSpans) .flatMap(function(children) { return propertiesResult.map(function(properties) { return documents.Table(children, properties); }); }); } function readTableProperties(element) { return readTableStyle(element).map(function(style) { return { styleId: style.styleId, styleName: style.name }; }); } function readTableRow(element) { var properties = element.firstOrEmpty("w:trPr"); var isHeader = !!properties.first("w:tblHeader"); return readXmlElements(element.children).map(function(children) { return documents.TableRow(children, {isHeader: isHeader}); }); } function readTableCell(element) { return readXmlElements(element.children).map(function(children) { var properties = element.firstOrEmpty("w:tcPr"); var gridSpan = properties.firstOrEmpty("w:gridSpan").attributes["w:val"]; var colSpan = gridSpan ? parseInt(gridSpan, 10) : 1; var cell = documents.TableCell(children, {colSpan: colSpan}); cell._vMerge = readVMerge(properties); return cell; }); } function readVMerge(properties) { var element = properties.first("w:vMerge"); if (element) { var val = element.attributes["w:val"]; return val === "continue" || !val; } else { return null; } } function calculateRowSpans(rows) { var unexpectedNonRows = _.any(rows, function(row) { return row.type !== documents.types.tableRow; }); if (unexpectedNonRows) { return elementResultWithMessages(rows, [warning( "unexpected non-row element in table, cell merging may be incorrect" )]); } var unexpectedNonCells = _.any(rows, function(row) { return _.any(row.children, function(cell) { return cell.type !== documents.types.tableCell; }); }); if (unexpectedNonCells) { return elementResultWithMessages(rows, [warning( "unexpected non-cell element in table row, cell merging may be incorrect" )]); } var columns = {}; rows.forEach(function(row) { var cellIndex = 0; row.children.forEach(function(cell) { if (cell._vMerge && columns[cellIndex]) {