diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-06-14 12:57:55 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-06-14 12:57:55 +0100 |
| commit | 7fd0b913c41926a745331e26e779d6ee33e70ae0 (patch) | |
| tree | ffcf9ac9619bb509152f35a4163b7bfd0b579e99 /lib/docx/document-xml-reader.js | |
| parent | aaabb8c8d6d3f0f61064d906ea86342a87bb0c3f (diff) | |
Add basic support for text boxes
Diffstat (limited to 'lib/docx/document-xml-reader.js')
| -rw-r--r-- | lib/docx/document-xml-reader.js | 116 |
1 files changed, 96 insertions, 20 deletions
diff --git a/lib/docx/document-xml-reader.js b/lib/docx/document-xml-reader.js index ab48fe7..8e459cc 100644 --- a/lib/docx/document-xml-reader.js +++ b/lib/docx/document-xml-reader.js @@ -19,16 +19,17 @@ function DocumentXmlReader(options) { function convertXmlToDocument(documentXml) { var body = documentXml.root.first("w:body"); - return readXmlElements(body.children) + var result = readXmlElements(body.children) .flatMap(function(children) { return readNotes().map(function(notes) { return new documents.Document(children, {notes: notes}); }); }); + return new Result(result.value, result.messages); } function readNotes() { - return Result.combine(rawNotes.map(function(rawNote) { + return combineResults(rawNotes.map(function(rawNote) { return readXmlElements(rawNote.body).map(function(body) { return new documents.Note({ noteType: rawNote.noteType, @@ -43,7 +44,7 @@ function DocumentXmlReader(options) { function readXmlElements(elements) { var results = elements.map(readXmlElement); - return Result.combine(results); + return combineResults(results); } function readXmlElement(element) { @@ -52,13 +53,11 @@ function DocumentXmlReader(options) { if (handler) { return handler(element); } else if (!Object.prototype.hasOwnProperty.call(ignoreElements, element.name)) { - return new Result( - [], - [warning("An unrecognised element was ignored: " + element.name)] - ); + var message = warning("An unrecognised element was ignored: " + element.name); + return emptyResultWithMessages([message]); } } - return new Result([]); + return emptyResult(); } function readRunProperties(element) { @@ -77,7 +76,7 @@ function DocumentXmlReader(options) { properties.isUnderline = !!element.first("w:u"); properties.isItalic = !!element.first("w:i"); - return new Result(properties); + return elementResult(properties); } function readRunStyle(properties, element) { @@ -95,7 +94,7 @@ function DocumentXmlReader(options) { function noteReferenceReader(noteType) { return function(element) { var noteId = element.attributes["w:id"]; - return new Result(new documents.NoteReference({ + return elementResult(new documents.NoteReference({ noteType: noteType, noteId: noteId })); @@ -115,7 +114,8 @@ function DocumentXmlReader(options) { children.filter(negate(isParagraphProperties)), properties ); - }); + }) + .insertExtra(); }, "w:pPr": function(element) { var properties = { @@ -143,7 +143,7 @@ function DocumentXmlReader(options) { properties.numbering = numbering.findLevel(numId, level); } - return new Result(properties); + return elementResult(properties); }, "w:r": function(element) { return readXmlElements(element.children) @@ -158,10 +158,10 @@ function DocumentXmlReader(options) { }, "w:rPr": readRunProperties, "w:t": function(element) { - return new Result(new documents.Text(element.text())); + return elementResult(new documents.Text(element.text())); }, "w:tab": function(element) { - return new Result(new documents.Tab()); + return elementResult(new documents.Tab()); }, "w:hyperlink": function(element) { var relationshipId = element.attributes["r:id"]; @@ -191,23 +191,33 @@ function DocumentXmlReader(options) { "w:br": function(element) { var breakType = element.attributes["w:type"]; if (breakType) { - return new Result([], [warning("Unsupported break type: " + breakType)]); + return emptyResultWithMessages([warning("Unsupported break type: " + breakType)]); } else { - return new Result(new documents.LineBreak()); + return elementResult(new documents.LineBreak()); } }, "w:bookmarkStart": function(element){ var name = element.attributes["w:name"]; if (name === "_GoBack") { - return new Result([]); + return emptyResult(); } else { - return new Result(new documents.BookmarkStart({name: name})); + return elementResult(new documents.BookmarkStart({name: name})); } }, + + "mc:AlternateContent": function(element) { + return readChildElements(element.first("mc:Fallback")); + }, "w:ins": readChildElements, "w:smartTag": readChildElements, "w:drawing": readChildElements, + "w:pict": function(element) { + return readChildElements(element).toExtra(); + }, + "v:shape": readChildElements, + "v:textbox": readChildElements, + "w:txbxContent": readChildElements, "wp:inline": readDrawingElement, "wp:anchor": readDrawingElement }; @@ -224,7 +234,7 @@ function DocumentXmlReader(options) { .getElementsByTagName("pic:blipFill") .getElementsByTagName("a:blip"); - return Result.combine(blips.map(readBlip.bind(null, element))); + return combineResults(blips.map(readBlip.bind(null, element))); } function readBlip(element, blip) { @@ -241,7 +251,7 @@ function DocumentXmlReader(options) { }); var warnings = supportedImageTypes[contentType] ? [] : warning("Image of type " + contentType + " is unlikely to display in web browsers"); - return new Result(image, warnings); + return elementResultWithMessages(image, warnings); } } @@ -288,3 +298,69 @@ function joinZipPath(first, second) { // but in our specific case this seems to be sufficient return first + "/" + second; } + + + +function emptyResultWithMessages(messages) { + return new ReadResult(null, null, messages); +} + +function emptyResult() { + return new ReadResult(null); +} + +function elementResult(element) { + return new ReadResult(element); +} + +function elementResultWithMessages(element, messages) { + return new ReadResult(element, null, messages); +} + +function ReadResult(element, extra, messages) { + this.value = element || []; + this.extra = extra; + this._result = new Result({ + element: this.value, + extra: extra + }, messages); + this.messages = this._result.messages; +} + +ReadResult.prototype.toExtra = function() { + // TODO: handle non-empty this.extra + return new ReadResult(null, this.value, this.messages); +}; + +ReadResult.prototype.insertExtra = function() { + var extra = this.extra; + if (extra && extra.length) { + return new ReadResult(_.flatten([this.value, extra]), null, this.messages); + } else { + return this; + } +}; + +ReadResult.prototype.map = function(func) { + var result = this._result.map(function(value) { + return func(value.element); + }); + return new ReadResult(result.value, this.extra, result.messages); +}; + +ReadResult.prototype.flatMap = function(func) { + var result = this._result.flatMap(function(value) { + return func(value.element)._result; + }); + // TODO: handle non-empty this.extra + return new ReadResult(result.value.element, result.value.extra, result.messages); +}; + +function combineResults(results) { + var result = Result.combine(_.pluck(results, "_result")); + return new ReadResult( + _.flatten(_.pluck(result.value, "element")), + _.filter(_.flatten(_.pluck(result.value, "extra")), function(x) { return x; }), + result.messages + ); +} |
