Skip to content

Commit fb132fa

Browse files
committed
feat: enhance CustomContent block handling in createConditionalToc function
- Improved the logic for identifying CustomContent block ranges by implementing a two-pass approach to track opening and closing tags. - Updated heading matching to ensure accurate association with CustomContent attributes, enhancing the functionality of the table of contents generation.
1 parent be836fb commit fb132fa

File tree

1 file changed

+42
-32
lines changed

1 file changed

+42
-32
lines changed

gatsby/plugin/conditional-toc/conditional-toc.js

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -101,46 +101,56 @@ export const createConditionalToc = ({
101101
};
102102

103103
// Traverse the mdast tree to track CustomContent blocks
104-
let insideCustomContent = false;
105-
let currentConditionAttrs = null;
104+
// We need to identify start position and end position of CustomContent blocks
105+
const customContentRanges = [];
106+
let tempStack = [];
106107

108+
// First pass: identify all CustomContent block ranges
107109
visit(mdast, (node, index, parent) => {
108-
// Check for opening CustomContent tag
109-
if (
110-
node.type === "jsx" &&
111-
node.value &&
112-
node.value.includes("<CustomContent")
113-
) {
114-
const attributes = parseCustomContentAttributes(node.value);
115-
conditionStack.push(attributes);
116-
insideCustomContent = true;
117-
currentConditionAttrs = attributes;
118-
}
119-
// Check for closing CustomContent tag
120-
else if (
121-
node.type === "jsx" &&
122-
node.value &&
123-
node.value.includes("</CustomContent>")
124-
) {
125-
if (conditionStack.length > 0) {
126-
conditionStack.pop();
110+
if (node.type === "jsx" && node.value) {
111+
const trimmedValue = node.value.trim();
112+
113+
// Check for opening tag (not self-closing)
114+
if (
115+
trimmedValue.includes("<CustomContent") &&
116+
!trimmedValue.includes("/>")
117+
) {
118+
const attributes = parseCustomContentAttributes(node.value);
119+
tempStack.push({
120+
startPosition: node.position,
121+
attributes,
122+
});
127123
}
128-
if (conditionStack.length === 0) {
129-
insideCustomContent = false;
130-
currentConditionAttrs = null;
131-
} else {
132-
currentConditionAttrs =
133-
conditionStack[conditionStack.length - 1];
124+
// Check for closing tag
125+
else if (trimmedValue.includes("</CustomContent>")) {
126+
if (tempStack.length > 0) {
127+
const blockInfo = tempStack.pop();
128+
customContentRanges.push({
129+
start: blockInfo.startPosition,
130+
end: node.position,
131+
attributes: blockInfo.attributes,
132+
});
133+
}
134134
}
135135
}
136-
// Track headings inside CustomContent blocks
137-
else if (node.type === "heading" && conditionStack.length > 0) {
136+
});
137+
138+
// Second pass: match headings with CustomContent blocks
139+
visit(mdast, (node) => {
140+
if (node.type === "heading" && node.position) {
138141
const headingText = getHeadingText(node);
139142
const headingId = slugger.slug(headingText);
140143

141-
headingConditions[headingId] = {
142-
...conditionStack[conditionStack.length - 1],
143-
};
144+
// Check if this heading is inside any CustomContent block
145+
for (const range of customContentRanges) {
146+
if (
147+
node.position.start.line > range.start.end.line &&
148+
node.position.end.line < range.end.start.line
149+
) {
150+
headingConditions[headingId] = { ...range.attributes };
151+
break; // Only use the first matching range (innermost)
152+
}
153+
}
144154
}
145155
});
146156

0 commit comments

Comments
 (0)