Skip to content

Commit 49231af

Browse files
jeremymanningclaude
andcommitted
Fix checklist extraction to include TEXT nodes in DOM traversal
tex4ht places checklist item text in TEXT nodes between MJX-CONTAINER elements, not inside element nodes. Changed from nextElementSibling (elements only) to childNodes iteration (all nodes including text). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 3509aeb commit 49231af

File tree

1 file changed

+54
-28
lines changed

1 file changed

+54
-28
lines changed

checklist.js

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,38 +38,53 @@ function convertChecklistToInteractive() {
3838
if (!checklistHeading) return;
3939

4040
// tex4ht generates a complex structure where checklist items are spread across
41-
// many elements: MJX-CONTAINER (for checkbox chars), SPAN, A, and text nodes
42-
// We need to gather all content from heading to the signature table
41+
// many nodes: MJX-CONTAINER (for checkbox chars), TEXT nodes, SPAN, A elements
42+
// The actual item text is in TEXT NODES between elements, not inside elements
43+
// We need to iterate over ALL child nodes, not just element siblings
4344

44-
// Collect all elements between heading and signature table
45-
var elementsToHide = [];
46-
var sibling = checklistHeading.nextElementSibling;
47-
var signatureTable = null;
45+
var parent = checklistHeading.parentElement;
46+
if (!parent) return;
4847

49-
while (sibling) {
50-
// Check if this is the signature table (contains "Signature" and "Date" labels)
51-
if (sibling.tagName === 'TABLE' ||
52-
(sibling.textContent &&
53-
sibling.textContent.includes('Signature') &&
54-
sibling.textContent.includes('Date') &&
55-
!sibling.textContent.includes('tasks'))) {
56-
signatureTable = sibling;
48+
// Find the index of the heading in parent's childNodes
49+
var startIndex = -1;
50+
var childNodes = parent.childNodes;
51+
for (var i = 0; i < childNodes.length; i++) {
52+
if (childNodes[i] === checklistHeading) {
53+
startIndex = i;
5754
break;
5855
}
59-
elementsToHide.push(sibling);
60-
sibling = sibling.nextElementSibling;
6156
}
57+
if (startIndex === -1) return;
6258

63-
// Get the parent element to extract text from
64-
var parent = checklistHeading.parentElement;
65-
if (!parent) return;
66-
67-
// Get all text content between heading and signature table
68-
// by walking through nodes and splitting on checkbox characters
59+
// Collect all nodes (elements AND text nodes) after the heading until signature table
60+
var nodesToHide = [];
61+
var signatureTable = null;
6962
var fullText = '';
70-
elementsToHide.forEach(function(el) {
71-
fullText += el.textContent || '';
72-
});
63+
64+
for (var i = startIndex + 1; i < childNodes.length; i++) {
65+
var node = childNodes[i];
66+
67+
// Check if this is the signature table (TABLE element or contains Signature/Date labels)
68+
if (node.nodeType === Node.ELEMENT_NODE) {
69+
if (node.tagName === 'TABLE' ||
70+
(node.textContent &&
71+
node.textContent.includes('Signature') &&
72+
node.textContent.includes('Date') &&
73+
!node.textContent.includes('tasks'))) {
74+
signatureTable = node;
75+
break;
76+
}
77+
}
78+
79+
nodesToHide.push(node);
80+
81+
// Extract text from both text nodes and elements
82+
if (node.nodeType === Node.TEXT_NODE) {
83+
fullText += node.textContent || '';
84+
} else if (node.nodeType === Node.ELEMENT_NODE) {
85+
fullText += node.textContent || '';
86+
}
87+
}
7388

7489
// Check if we have checkbox characters
7590
if (!fullText.includes('\u25A1') && !fullText.includes('\u2610')) {
@@ -184,9 +199,20 @@ function convertChecklistToInteractive() {
184199

185200
container.appendChild(signatureSection);
186201

187-
// Hide all the original checklist elements
188-
elementsToHide.forEach(function(el) {
189-
el.style.display = 'none';
202+
// Hide all the original checklist nodes (elements and text nodes)
203+
nodesToHide.forEach(function(node) {
204+
if (node.nodeType === Node.ELEMENT_NODE) {
205+
node.style.display = 'none';
206+
} else if (node.nodeType === Node.TEXT_NODE) {
207+
// For text nodes, we need to remove them or replace with empty
208+
// We'll wrap them in a span and hide it
209+
if (node.textContent.trim()) {
210+
var wrapper = document.createElement('span');
211+
wrapper.style.display = 'none';
212+
node.parentNode.insertBefore(wrapper, node);
213+
wrapper.appendChild(node);
214+
}
215+
}
190216
});
191217

192218
// Hide signature table if found

0 commit comments

Comments
 (0)