@@ -343,6 +343,8 @@ def parse_doc_body(body_lines: Iterable[str]) -> dict[str, object]:
343343 - free text before any subsection -> summary
344344 - `#### Usage` -> usage string or fenced usage block
345345 - `Where:` -> list of documented parameters
346+ - general notes that appear inside `Where:` after the parameter bullets
347+ -> `notes`
346348 - `#### Test` -> example snippet
347349 - `#### Reference` / `#### References` -> references list
348350
@@ -353,13 +355,20 @@ def parse_doc_body(body_lines: Iterable[str]) -> dict[str, object]:
353355 summary_lines : list [str ] = []
354356 usage_buffer : list [str ] = []
355357 params : list [dict [str , str ]] = []
358+ notes : list [str ] = []
356359 references : list [str ] = []
357360 test_code : str | None = None
358361
359362 section = "summary"
360363 in_fence = False
361364 fence_buffer : list [str ] = []
362365 current_param : dict [str , str ] | None = None
366+ current_note_index : int | None = None
367+
368+ def is_general_note_line (text : str ) -> bool :
369+ """Heuristically detect note-like prose inside a `Where:` section."""
370+
371+ return bool (re .match (r"^(note|notes|output|outputs|return|returns|result|results)\b" , text , flags = re .IGNORECASE ))
363372
364373 def flush_fence () -> None :
365374 """Commit the current fenced code block into the active logical section."""
@@ -397,6 +406,7 @@ def flush_fence() -> None:
397406 if re .match (r"^where\s*:?\s*$" , trimmed , flags = re .IGNORECASE ):
398407 section = "where"
399408 current_param = None
409+ current_note_index = None
400410 continue
401411
402412 if trimmed .startswith ("```" ):
@@ -426,8 +436,15 @@ def flush_fence() -> None:
426436 if match :
427437 current_param = {"name" : match .group (1 ).strip (), "description" : match .group (2 ).strip ()}
428438 params .append (current_param )
429- elif current_param and trimmed and not trimmed .startswith ("* " ):
439+ current_note_index = None
440+ elif current_note_index is not None and trimmed and not trimmed .startswith ("* " ):
441+ notes [current_note_index ] = f"{ notes [current_note_index ]} { trimmed } " .strip ()
442+ elif current_param and trimmed and not trimmed .startswith ("* " ) and not is_general_note_line (trimmed ):
430443 current_param ["description" ] = f"{ current_param ['description' ]} { trimmed } " .strip ()
444+ elif trimmed and not trimmed .startswith ("* " ):
445+ notes .append (trimmed )
446+ current_note_index = len (notes ) - 1
447+ current_param = None
431448 continue
432449
433450 if section == "reference" :
@@ -440,12 +457,16 @@ def flush_fence() -> None:
440457
441458 usage = None
442459 if usage_buffer :
443- usage = next ((line for line in usage_buffer if ":" in line ), usage_buffer [0 ])
460+ if len (usage_buffer ) == 1 :
461+ usage = usage_buffer [0 ]
462+ else :
463+ usage = re .sub (r"\s+" , " " , " " .join (usage_buffer )).strip ()
444464
445465 return {
446466 "summary" : " " .join (summary_lines ).strip (),
447467 "usage" : usage ,
448468 "params" : params ,
469+ "notes" : notes ,
449470 "testCode" : test_code ,
450471 "references" : references ,
451472 }
@@ -569,6 +590,7 @@ def build_index(repo_root: Path, stdlib: Path) -> dict[str, object]:
569590 "summary" : body ["summary" ],
570591 "usage" : usage ,
571592 "params" : body ["params" ],
593+ "notes" : body ["notes" ],
572594 "io" : io ,
573595 "testCode" : body ["testCode" ],
574596 "references" : body ["references" ],
@@ -616,6 +638,7 @@ def make_symbol_summary(symbol: dict[str, object]) -> dict[str, object]:
616638 "tags" : symbol ["tags" ],
617639 "source" : symbol ["source" ],
618640 "hasTestCode" : bool (symbol .get ("testCode" )),
641+ "notesCount" : len (symbol .get ("notes" , [])),
619642 "referencesCount" : len (symbol .get ("references" , [])),
620643 }
621644
0 commit comments