@@ -274,13 +274,31 @@ pub fn scan_dir(dir: &Path, entries: &mut Vec<Entry>, excludes: &mut Vec<PathBuf
274274pub fn scan_todo_file ( path : & Path , entries : & mut Vec < Entry > ) -> io:: Result < ( ) > {
275275 let str = fs:: read_to_string ( path) ?;
276276 let mut current_category: Option < & str > = None ;
277+ let mut in_code_block = false ;
277278
278279 // This can produce:
279280 // - generic todos (above any category)
280281 // - category todos (below a ## category heading)
281282 // - priority todos (priority keyword part of the line)
282283 ' line: for ( line_num, line) in str. lines ( ) . enumerate ( ) {
283- if line. starts_with ( '#' ) {
284+ if line. starts_with ( "```" ) {
285+ // If we are in an *unindented* code block, we ignore lines
286+ // starting with # - they cannot be headings. Indented
287+ // code blocks are irrelevant.
288+ in_code_block = ! in_code_block;
289+ continue ;
290+ }
291+
292+ // We need the line to start with # followed by spaces. So we cannot check just for '#'
293+ // There's also no real need for any complex logic iterating over the line's characters,
294+ // we can just check reasonable heading hierarchy like this. Anything else is unlikely.
295+ if ! in_code_block && ( false
296+ || line. starts_with ( "# " )
297+ || line. starts_with ( "## " )
298+ || line. starts_with ( "### " )
299+ || line. starts_with ( "#### " )
300+ || line. starts_with ( "##### " )
301+ ) {
284302 current_category = Some ( line. split_once ( "# " ) . unwrap ( ) . 1 ) ;
285303
286304 continue ;
@@ -338,13 +356,31 @@ pub fn scan_todo_file(path: &Path, entries: &mut Vec<Entry>) -> io::Result<()> {
338356pub fn scan_readme_file ( path : & Path , entries : & mut Vec < Entry > ) -> io:: Result < ( ) > {
339357 let str = fs:: read_to_string ( path) ?;
340358 let mut in_todo_section = false ;
359+ let mut in_code_block = false ;
341360
342361 // This can produce:
343362 // - generic todos (above any category)
344363 // - category todos (below a ## category heading) todo@real add this logic and update README.md
345364 // - priority todos (priority keyword part of the line)
346365 ' line: for ( line_num, line) in str. lines ( ) . enumerate ( ) {
347- if line. starts_with ( '#' ) {
366+ if line. starts_with ( "```" ) {
367+ // If we are in an *unindented* code block, we ignore lines
368+ // starting with # - they cannot be headings. Indented
369+ // code blocks are irrelevant.
370+ in_code_block = ! in_code_block;
371+ continue ;
372+ }
373+
374+ // We need the line to start with # followed by spaces. So we cannot check just for '#'
375+ // There's also no real need for any complex logic iterating over the line's characters,
376+ // we can just check reasonable heading hierarchy like this. Anything else is unlikely.
377+ if ! in_code_block && ( false
378+ || line. starts_with ( "# " )
379+ || line. starts_with ( "## " )
380+ || line. starts_with ( "### " )
381+ || line. starts_with ( "#### " )
382+ || line. starts_with ( "##### " )
383+ ) {
348384 let section = line. split_once ( "# " ) . unwrap ( ) . 1 ;
349385 let cleaned_section = section. to_lowercase ( ) . trim_end_matches ( ':' ) . trim ( ) . to_string ( ) ;
350386
0 commit comments