aboutsummaryrefslogtreecommitdiff
path: root/lib/docx/document-xml-reader.js
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-06-14 12:57:55 +0100
committerMichael Williamson <mike@zwobble.org>2015-06-14 12:57:55 +0100
commit7fd0b913c41926a745331e26e779d6ee33e70ae0 (patch)
treeffcf9ac9619bb509152f35a4163b7bfd0b579e99 /lib/docx/document-xml-reader.js
parentaaabb8c8d6d3f0f61064d906ea86342a87bb0c3f (diff)
Add basic support for text boxes
Diffstat (limited to 'lib/docx/document-xml-reader.js')
-rw-r--r--lib/docx/document-xml-reader.js116
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
+ );
+}