@@ -340,6 +340,8 @@ class KeywordDoc(SourceEntity):
340340 default = None , compare = False , repr = False , hash = False
341341 )
342342
343+ parent : Optional [LibraryDoc ] = None
344+
343345 def __str__ (self ) -> str :
344346 return f"{ self .name } ({ ', ' .join (str (arg ) for arg in self .args )} )"
345347
@@ -394,7 +396,7 @@ def range(self) -> Range:
394396 ),
395397 )
396398
397- def to_markdown (self , add_signature : bool = True , header_level : int = 0 , add_type : bool = True ) -> str :
399+ def to_markdown (self , add_signature : bool = True , header_level : int = 2 , add_type : bool = True ) -> str :
398400 result = ""
399401
400402 if add_signature :
@@ -417,10 +419,10 @@ def to_markdown(self, add_signature: bool = True, header_level: int = 0, add_typ
417419
418420 def _get_signature (self , header_level : int , add_type : bool = True ) -> str :
419421 if add_type :
420- result = f"#{ '#' * header_level } { 'Library' if self .is_initializer else 'Keyword' } *{ self .name } *"
422+ result = f"#{ '#' * header_level } { 'Library' if self .is_initializer else 'Keyword' } *{ self .name } *\n "
421423 else :
422424 if not self .is_initializer :
423- result = f"\n \n #{ '#' * header_level } { self .name } "
425+ result = f"\n \n #{ '#' * header_level } { self .name } \n "
424426 else :
425427 result = ""
426428
@@ -575,7 +577,7 @@ class ModuleSpec:
575577@dataclass
576578class LibraryDoc :
577579 name : str = ""
578- doc : str = ""
580+ doc : str = field ( default = "" , compare = False )
579581 version : str = ""
580582 type : str = "LIBRARY"
581583 scope : str = "TEST"
@@ -592,6 +594,21 @@ class LibraryDoc:
592594 stdout : Optional [str ] = field (default = None , compare = False )
593595 has_listener : Optional [bool ] = None
594596
597+ @single_call
598+ def __hash__ (self ) -> int :
599+ return hash (
600+ (
601+ self .name ,
602+ self .source ,
603+ self .line_no ,
604+ self .end_line_no ,
605+ self .version ,
606+ self .type ,
607+ self .scope ,
608+ self .doc_format ,
609+ )
610+ )
611+
595612 @property
596613 def is_deprecated (self ) -> bool :
597614 return DEPRECATED_PATTERN .match (self .doc ) is not None
@@ -612,17 +629,19 @@ def range(self) -> Range:
612629 ),
613630 )
614631
615- def to_markdown (self , add_signature : bool = True , only_doc : bool = True ) -> str :
632+ def to_markdown (self , add_signature : bool = True , only_doc : bool = True , header_level : int = 2 ) -> str :
616633 with io .StringIO (newline = "\n " ) as result :
617634
618635 def write_lines (* args : str ) -> None :
619636 result .writelines (i + "\n " for i in args )
620637
621638 if add_signature and any (v for v in self .inits .values () if v .args ):
622639 for i in self .inits .values ():
623- write_lines (i .to_markdown (), "" , "---" )
640+ write_lines (i .to_markdown (header_level = header_level ), "" , "---" )
624641
625- write_lines (f"# { (self .type .capitalize ()) if self .type else 'Unknown' } *{ self .name } *" , "" , "" )
642+ write_lines (
643+ f"#{ '#' * header_level } { (self .type .capitalize ()) if self .type else 'Unknown' } *{ self .name } *" , "" , ""
644+ )
626645
627646 if self .version or self .scope :
628647 write_lines (
@@ -639,7 +658,7 @@ def write_lines(*args: str) -> None:
639658
640659 if self .doc :
641660
642- write_lines ("## Introduction" , "" )
661+ write_lines (f "##{ '#' * header_level } Introduction" , "" )
643662
644663 if self .doc_format == ROBOT_DOC_FORMAT :
645664 doc = MarkDownFormatter ().format (self .doc )
@@ -655,7 +674,7 @@ def write_lines(*args: str) -> None:
655674 result .write (self .doc )
656675
657676 if not only_doc :
658- result .write (self ._get_doc_for_keywords ())
677+ result .write (self ._get_doc_for_keywords (header_level = header_level ))
659678
660679 return self ._link_inline_links (result .getvalue ())
661680
@@ -680,23 +699,23 @@ def source_or_origin(self) -> Optional[str]:
680699 re .VERBOSE ,
681700 )
682701
683- _headers : ClassVar [re .Pattern ] = re .compile (r"^(#{2,5 })\s+(\S.*)$" , re .MULTILINE ) # type: ignore
702+ _headers : ClassVar [re .Pattern ] = re .compile (r"^(#{2,9 })\s+(\S.*)$" , re .MULTILINE ) # type: ignore
684703
685704 def _link_inline_links (self , text : str ) -> str :
686705 headers = [v .group (2 ) for v in self ._headers .finditer (text )]
687706
688707 def repl (m : re .Match ) -> str : # type: ignore
689708 if m .group (2 ) in headers :
690- return f"[{ str (m .group (2 ))} ](#{ str (m .group (2 )).lower ().replace (' ' , '-' )} )"
709+ return f"[{ str (m .group (2 ))} ](\\ #{ str (m .group (2 )).lower ().replace (' ' , '-' )} )"
691710 return str (m .group (0 ))
692711
693712 return str (self ._inline_link .sub (repl , text ))
694713
695- def _get_doc_for_keywords (self ) -> str :
714+ def _get_doc_for_keywords (self , header_level : int = 2 ) -> str :
696715 result = ""
697716 if any (v for v in self .inits .values () if v .args ):
698717 result += "\n ---\n \n "
699- result += "\n ## Importing\n \n "
718+ result += f "\n ##{ '#' * header_level } Importing\n \n "
700719
701720 first = True
702721
@@ -709,7 +728,7 @@ def _get_doc_for_keywords(self) -> str:
709728
710729 if self .keywords :
711730 result += "\n ---\n \n "
712- result += "\n ## Keywords\n \n "
731+ result += f "\n ##{ '#' * header_level } Keywords\n \n "
713732
714733 first = True
715734
@@ -718,7 +737,7 @@ def _get_doc_for_keywords(self) -> str:
718737 result += "\n ---\n "
719738 first = False
720739
721- result += "\n " + kw .to_markdown (header_level = 2 , add_type = False )
740+ result += "\n " + kw .to_markdown (header_level = header_level , add_type = False )
722741 return result
723742
724743 def _add_toc (self , doc : str , only_doc : bool = True ) -> str :
@@ -1102,6 +1121,21 @@ def find_library(
11021121 )[0 ]
11031122
11041123
1124+ def get_robot_library_html_doc_str (name : str , working_dir : str = "." , base_dir : str = "." ) -> str :
1125+ from robot .libdocpkg import LibraryDocumentation
1126+ from robot .libdocpkg .htmlwriter import LibdocHtmlWriter
1127+
1128+ _update_env (working_dir )
1129+
1130+ robot_libdoc = LibraryDocumentation (name )
1131+ robot_libdoc .convert_docs_to_html ()
1132+ with io .StringIO () as output :
1133+ writer = LibdocHtmlWriter ()
1134+ writer .write (robot_libdoc , output )
1135+
1136+ return output .getvalue ()
1137+
1138+
11051139def get_library_doc (
11061140 name : str ,
11071141 args : Optional [Tuple [Any , ...]] = None ,
@@ -1278,6 +1312,7 @@ def get_test_library(
12781312 doc_format = str (lib .doc_format ) or ROBOT_DOC_FORMAT ,
12791313 is_initializer = True ,
12801314 arguments = ArgumentSpec .from_robot_argument_spec (kw [1 ].arguments ),
1315+ parent = libdoc ,
12811316 )
12821317 for kw in [
12831318 (KeywordDocBuilder ().build_keyword (k ), k ) for k in [KeywordWrapper (lib .init , source )]
@@ -1326,6 +1361,7 @@ def get_test_library(
13261361 arguments = ArgumentSpec .from_robot_argument_spec (kw [1 ].arguments )
13271362 if not kw [1 ].is_error_handler
13281363 else None ,
1364+ parent = libdoc ,
13291365 )
13301366 for kw in [
13311367 (KeywordDocBuilder ().build_keyword (k ), k )
0 commit comments