aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2025-06-02 18:50:31 +0100
committerMichael Williamson <mike@zwobble.org>2025-06-02 18:50:31 +0100
commitee76b524a54ff235416458abb8b17bedcb478eb8 (patch)
treec639fa0f66fdbe78b4c76eb562cb42d751caa03e /lib
parent3f5dd013a9259827aef9c63d8c33ed4aab88cdc6 (diff)
Handle SDTs representing checkboxes wrapped in other elements
Diffstat (limited to 'lib')
-rw-r--r--lib/docx/body-reader.js62
-rw-r--r--lib/transforms.js1
2 files changed, 48 insertions, 15 deletions
diff --git a/lib/docx/body-reader.js b/lib/docx/body-reader.js
index 93144c3..2ab5ba7 100644
--- a/lib/docx/body-reader.js
+++ b/lib/docx/body-reader.js
@@ -8,6 +8,7 @@ var documents = require("../documents");
var Result = require("../results").Result;
var warning = require("../results").warning;
var xml = require("../xml");
+var transforms = require("../transforms");
var uris = require("./uris");
function createBodyReader(options) {
@@ -385,21 +386,52 @@ function BodyReader(options) {
},
"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);
- }
+ var contentResult = readXmlElements(element.firstOrEmpty("w:sdtContent").children);
+ return contentResult.map(function(content) {
+ // From the WordML standard: https://learn.microsoft.com/en-us/openspecs/office_standards/ms-docx/3350cb64-931f-41f7-8824-f18b2568ce66
+ //
+ // > A CT_SdtCheckbox element that specifies that the parent
+ // > structured document tag is a checkbox when displayed in the
+ // > document. The parent structured document tag contents MUST
+ // > contain a single character and optionally an additional
+ // > character in a deleted run.
+
+ 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"]
+ );
+ var documentCheckbox = documents.checkbox({
+ checked: isChecked
+ });
+
+ var hasCheckbox = false;
+ var replacedContent = content.map(transforms._elementsOfType(
+ documents.types.text,
+ function(text) {
+ if (text.value.length > 0 && !hasCheckbox) {
+ hasCheckbox = true;
+ return documentCheckbox;
+ } else {
+ return text;
+ }
+ }
+ ));
+
+ if (hasCheckbox) {
+ return replacedContent;
+ } else {
+ return documentCheckbox;
+ }
+
+ } else {
+ return content;
+ }
+ });
},
"w:ins": readChildElements,
diff --git a/lib/transforms.js b/lib/transforms.js
index 01ba0d8..3c5cf73 100644
--- a/lib/transforms.js
+++ b/lib/transforms.js
@@ -3,6 +3,7 @@ var _ = require("underscore");
exports.paragraph = paragraph;
exports.run = run;
exports._elements = elements;
+exports._elementsOfType = elementsOfType;
exports.getDescendantsOfType = getDescendantsOfType;
exports.getDescendants = getDescendants;