@@ -5,9 +5,10 @@ use serde::{Serialize, Deserialize};
55
66lazy_static ! {
77 static ref HEADING_REGEX : Regex = Regex :: new(
8- r#"<h([1-6])(?: [^>]*)(?:id=["']([^"']+)["'])?(?:[^>]*)>(.* ?)</h\1 >"#
8+ r#"<h([1-6])([^>]*)>([\s\S]* ?)</h[1-6] >"#
99 ) . unwrap( ) ;
1010
11+ static ref ID_REGEX : Regex = Regex :: new( r#"id=["']([^"']+)["']"# ) . unwrap( ) ;
1112 static ref TAG_REGEX : Regex = Regex :: new( r"<[^>]*>" ) . unwrap( ) ;
1213}
1314
@@ -139,7 +140,7 @@ impl TableOfContents {
139140 }
140141
141142 // Reverse to maintain order
142- self . headings . reverse ( ) ;
143+ // self.headings.reverse();
143144 }
144145
145146 /// Generate HTML for the table of contents
@@ -201,16 +202,18 @@ pub fn extract_headings(html: &str) -> BoxResult<Vec<(usize, String, String)>> {
201202
202203 for cap in HEADING_REGEX . captures_iter ( html) {
203204 let level: usize = cap[ 1 ] . parse ( ) ?;
205+ let attrs = & cap[ 2 ] ;
206+ let content = & cap[ 3 ] ;
204207
205- // Get ID from the heading or generate from text
206- let id = if let Some ( id_match) = cap . get ( 2 ) {
207- id_match. as_str ( ) . to_string ( )
208+ // Get ID from attributes
209+ let id = if let Some ( id_match) = ID_REGEX . captures ( attrs ) {
210+ id_match[ 1 ] . to_string ( )
208211 } else {
209212 // Generate ID from heading text
210- generate_id_from_text ( & cap [ 3 ] )
213+ generate_id_from_text ( content )
211214 } ;
212215
213- let text = strip_html_tags ( & cap [ 3 ] ) ;
216+ let text = strip_html_tags ( content ) ;
214217
215218 headings. push ( ( level, id, text) ) ;
216219 }
@@ -296,14 +299,8 @@ impl Default for TocOptions {
296299}
297300
298301/// Generate TOC with custom options
299- pub fn generate_toc_with_options ( _html : & str , _options : & TocOptions ) -> BoxResult < String > {
300- // Temporarily return empty string due to compilation issues
301- Ok ( String :: new ( ) )
302- }
303-
304- // Original implementation commented out temporarily
305- /*
306- pub fn generate_toc_with_options_original(html: &str, options: &TocOptions) -> BoxResult<String> {
302+ /// Generate TOC with custom options
303+ pub fn generate_toc_with_options ( html : & str , options : & TocOptions ) -> BoxResult < String > {
307304 let flat_headings = extract_headings ( html) ?;
308305
309306 // Filter headings by level and no_toc class
@@ -317,7 +314,7 @@ pub fn generate_toc_with_options_original(html: &str, options: &TocOptions) -> B
317314 }
318315
319316 let list_tag = if options. ordered_list { "ol" } else { "ul" } ;
320- let mut html = format!(
317+ let mut html_out = format ! (
321318 r#"<{} id="{}" class="{}">"# ,
322319 list_tag, options. list_id, options. list_class
323320 ) ;
@@ -328,19 +325,19 @@ pub fn generate_toc_with_options_original(html: &str, options: &TocOptions) -> B
328325 for ( level, id, text) in filtered {
329326 // Adjust nesting
330327 while current_level < level {
331- html .push_str(&format!(r#"<{} class="{}">"#, list_tag, options.sublist_class));
328+ html_out . push_str ( & format ! ( r#"<{} class="{}">"# , list_tag, options. sublist_class) ) ;
332329 current_level += 1 ;
333330 stack_depth += 1 ;
334331 }
335332
336333 while current_level > level {
337- html .push_str(&format!("</{}></li>", list_tag));
334+ html_out . push_str ( & format ! ( "</{}></li>" , list_tag) ) ;
338335 current_level -= 1 ;
339336 stack_depth -= 1 ;
340337 }
341338
342339 // Add item
343- html .push_str(&format!(
340+ html_out . push_str ( & format ! (
344341 "<li class=\" {}\" ><a href=\" #{}\" {}>{}</a>" ,
345342 options. item_class,
346343 id,
@@ -357,16 +354,15 @@ pub fn generate_toc_with_options_original(html: &str, options: &TocOptions) -> B
357354
358355 // Close any remaining open tags
359356 for _ in 0 ..=stack_depth {
360- html .push_str("</li>");
357+ html_out . push_str ( "</li>" ) ;
361358 if stack_depth > 0 {
362- html .push_str(&format!("</{}>", list_tag));
359+ html_out . push_str ( & format ! ( "</{}>" , list_tag) ) ;
363360 }
364361 }
365362
366- html .push_str(&format!("</{}>", list_tag));
367- Ok(html )
363+ html_out . push_str ( & format ! ( "</{}>" , list_tag) ) ;
364+ Ok ( html_out )
368365}
369- */
370366
371367#[ cfg( test) ]
372368mod tests {
@@ -413,6 +409,11 @@ mod tests {
413409 <h1 id="usage">Usage</h1>
414410 "# ;
415411
412+ let headings = extract_headings ( html) . unwrap ( ) ;
413+ if headings. is_empty ( ) {
414+ panic ! ( "No headings found! HTML: {}" , html) ;
415+ }
416+
416417 let toc = build_toc_from_html ( html) . unwrap ( ) ;
417418 assert_eq ! ( toc. headings. len( ) , 2 ) ; // Two h1 headings
418419 assert_eq ! ( toc. headings[ 0 ] . children. len( ) , 2 ) ; // Two h2 under first h1
0 commit comments