@@ -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