summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-11-30 11:32:45 +0000
committerMichael Williamson <mike@zwobble.org>2024-11-30 11:32:45 +0000
commit0a86099a0d60c8bfe404cf66b5e5f1fb1549bb1d (patch)
treee0e090e2a7bb1384e277b55e10294dc518dacfdf
parent3751195339954f49f525446de0795d2acad2c234 (diff)
Parse default value of complex field checkbox
-rw-r--r--lib/docx/body-reader.js31
-rw-r--r--lib/xml/index.js1
-rw-r--r--lib/xml/nodes.js2
-rw-r--r--test/docx/body-reader.tests.js78
4 files changed, 85 insertions, 27 deletions
diff --git a/lib/docx/body-reader.js b/lib/docx/body-reader.js
index a4a6c0c..2726b76 100644
--- a/lib/docx/body-reader.js
+++ b/lib/docx/body-reader.js
@@ -7,6 +7,7 @@ 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) {
@@ -157,21 +158,26 @@ function BodyReader(options) {
return elementResultWithMessages({styleId: styleId, name: name}, messages);
}
- var unknownComplexField = {type: "unknown"};
-
function readFldChar(element) {
var type = element.attributes["w:fldCharType"];
if (type === "begin") {
- complexFieldStack.push(unknownComplexField);
+ complexFieldStack.push({type: "begin", fldChar: element});
currentInstrText = [];
} else if (type === "end") {
var complexFieldEnd = complexFieldStack.pop();
if (complexFieldEnd.type === "checkbox") {
- return elementResult(documents.checkbox({checked: false}));
+ return elementResult(documents.checkbox({
+ checked: complexFieldEnd.checked
+ }));
}
} else if (type === "separate") {
- var complexField = parseInstrText(currentInstrText.join(''));
- complexFieldStack.pop();
+ var complexFieldSeparate = complexFieldStack.pop();
+ var complexField = parseInstrText(
+ currentInstrText.join(''),
+ complexFieldSeparate.type === "begin"
+ ? complexFieldSeparate.fldChar
+ : xml.emptyElement
+ );
complexFieldStack.push(complexField);
}
return emptyResult();
@@ -184,7 +190,7 @@ function BodyReader(options) {
return topHyperlink ? topHyperlink.options : null;
}
- function parseInstrText(instrText) {
+ function parseInstrText(instrText, fldChar) {
var externalLinkResult = /\s*HYPERLINK "(.*)"/.exec(instrText);
if (externalLinkResult) {
return {type: "hyperlink", options: {href: externalLinkResult[1]}};
@@ -197,10 +203,17 @@ function BodyReader(options) {
var checkboxResult = /\s*FORMCHECKBOX\s*/.exec(instrText);
if (checkboxResult) {
- return {type: "checkbox"};
+ var checkboxElement = fldChar
+ .firstOrEmpty("w:ffData")
+ .firstOrEmpty("w:checkBox");
+ var defaultValue = readBooleanElement(
+ checkboxElement.first("w:default")
+ );
+ var checked = defaultValue;
+ return {type: "checkbox", checked: checked};
}
- return unknownComplexField;
+ return {type: "unknown"};
}
function readInstrText(element) {
diff --git a/lib/xml/index.js b/lib/xml/index.js
index a2f572e..2532bd7 100644
--- a/lib/xml/index.js
+++ b/lib/xml/index.js
@@ -2,6 +2,7 @@ var nodes = require("./nodes");
exports.Element = nodes.Element;
exports.element = nodes.element;
+exports.emptyElement = nodes.emptyElement;
exports.text = nodes.text;
exports.readString = require("./reader").readString;
exports.writeString = require("./writer").writeString;
diff --git a/lib/xml/nodes.js b/lib/xml/nodes.js
index 76f5fd7..2c77d4d 100644
--- a/lib/xml/nodes.js
+++ b/lib/xml/nodes.js
@@ -13,7 +13,7 @@ exports.text = function(value) {
};
-var emptyElement = {
+var emptyElement = exports.emptyElement = {
first: function() {
return null;
},
diff --git a/test/docx/body-reader.tests.js b/test/docx/body-reader.tests.js
index a431866..49c81b9 100644
--- a/test/docx/body-reader.tests.js
+++ b/test/docx/body-reader.tests.js
@@ -532,23 +532,28 @@ test("complex fields", (function() {
})());
test("checkboxes", {
- "complex field checkbox without default or checked elements is unchecked": function() {
- var paragraphXml = xml.element("w:p", {}, [
- xml.element("w:r", {}, [
- xml.element("w:fldChar", {"w:fldCharType": "begin"}, [
- xml.element("w:ffData", {}, [
- xml.element("w:checkBox")
- ])
- ])
- ]),
- xml.element("w:instrText", {}, [
- xml.text(' FORMCHECKBOX ')
- ]),
- xml.element("w:r", {}, [
- xml.element("w:fldChar", {"w:fldCharType": "separate"})
- ]),
- xml.element("w:r", {}, [
- xml.element("w:fldChar", {"w:fldCharType": "end"})
+ "complex field checkbox without w:default nor w:checked is unchecked": function() {
+ var paragraphXml = complexFieldCheckboxParagraph([
+ xml.element("w:checkBox")
+ ]);
+
+ var paragraph = readXmlElementValue(paragraphXml);
+
+ assertThat(paragraph.children, contains(
+ isEmptyRun,
+ isEmptyRun,
+ isRun({
+ children: contains(
+ isCheckbox({checked: equalTo(false)})
+ )
+ })
+ ));
+ },
+
+ "complex field checkbox with w:default=0 and without w:checked is unchecked": function() {
+ var paragraphXml = complexFieldCheckboxParagraph([
+ xml.element("w:checkBox", {}, [
+ xml.element("w:default", {"w:val": "0"})
])
]);
@@ -563,9 +568,48 @@ test("checkboxes", {
)
})
));
+ },
+
+ "complex field checkbox with w:default=1 and without w:checked is checked": function() {
+ var paragraphXml = complexFieldCheckboxParagraph([
+ xml.element("w:checkBox", {}, [
+ xml.element("w:default", {"w:val": "1"})
+ ])
+ ]);
+
+ var paragraph = readXmlElementValue(paragraphXml);
+
+ assertThat(paragraph.children, contains(
+ isEmptyRun,
+ isEmptyRun,
+ isRun({
+ children: contains(
+ isCheckbox({checked: equalTo(true)})
+ )
+ })
+ ));
}
});
+function complexFieldCheckboxParagraph(ffDataChildren) {
+ return xml.element("w:p", {}, [
+ xml.element("w:r", {}, [
+ xml.element("w:fldChar", {"w:fldCharType": "begin"}, [
+ xml.element("w:ffData", {}, ffDataChildren)
+ ])
+ ]),
+ xml.element("w:instrText", {}, [
+ xml.text(' FORMCHECKBOX ')
+ ]),
+ xml.element("w:r", {}, [
+ xml.element("w:fldChar", {"w:fldCharType": "separate"})
+ ]),
+ xml.element("w:r", {}, [
+ xml.element("w:fldChar", {"w:fldCharType": "end"})
+ ])
+ ]);
+}
+
test("run has no style if it has no properties", function() {
var runXml = runWithProperties([]);
var run = readXmlElementValue(runXml);