Skip to content

Commit

Permalink
Parse default value of complex field checkbox
Browse files Browse the repository at this point in the history
  • Loading branch information
mwilliamson committed Nov 30, 2024
1 parent 3751195 commit 0a86099
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 27 deletions.
31 changes: 22 additions & 9 deletions lib/docx/body-reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand All @@ -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]}};
Expand All @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions lib/xml/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
2 changes: 1 addition & 1 deletion lib/xml/nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ exports.text = function(value) {
};


var emptyElement = {
var emptyElement = exports.emptyElement = {
first: function() {
return null;
},
Expand Down
78 changes: 61 additions & 17 deletions test/docx/body-reader.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"})
])
]);

Expand All @@ -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);
Expand Down

0 comments on commit 0a86099

Please sign in to comment.