6262"""
6363
6464
65+ _TOC_TEMPLATE = """
66+ ## Table of Contents
67+ {toc}
68+ """
69+
6570_CLASS_TEMPLATE = """
6671{section} <kbd>class</kbd> `{header}`
6772{doc}
7479_MODULE_TEMPLATE = """
7580{section} <kbd>module</kbd> `{header}`
7681{doc}
82+ {toc}
7783{global_vars}
7884{functions}
7985{classes}
@@ -883,13 +889,14 @@ def class2md(self, cls: Any, depth: int = 2, is_mdx: bool = False) -> str:
883889
884890 return markdown
885891
886- def module2md (self , module : types .ModuleType , depth : int = 1 , is_mdx : bool = False ) -> str :
892+ def module2md (self , module : types .ModuleType , depth : int = 1 , is_mdx : bool = False , include_toc : bool = False ) -> str :
887893 """Takes an imported module object and create a Markdown string containing functions and classes.
888894
889895 Args:
890896 module (types.ModuleType): Selected module for markdown generation.
891897 depth (int, optional): Number of # to append before module heading. Defaults to 1.
892898 is_mdx (bool, optional): JSX support. Default to False.
899+ include_toc (bool, optional): Include table of contents in module file. Defaults to False.
893900
894901 Returns:
895902 str: Markdown documentation for selected module.
@@ -965,10 +972,13 @@ def module2md(self, module: types.ModuleType, depth: int = 1, is_mdx: bool = Fal
965972 new_list = ["\n **Global Variables**" , "---------------" , * variables ]
966973 variables = new_list
967974
975+ toc = self .toc2md (module = module , is_mdx = is_mdx ) if include_toc else ""
976+
968977 markdown = _MODULE_TEMPLATE .format (
969978 header = modname ,
970979 section = "#" * depth ,
971980 doc = doc ,
981+ toc = toc ,
972982 global_vars = "\n " .join (variables ) if variables else "" ,
973983 functions = "\n " .join (functions ) if functions else "" ,
974984 classes = "" .join (classes ) if classes else "" ,
@@ -982,21 +992,22 @@ def module2md(self, module: types.ModuleType, depth: int = 1, is_mdx: bool = Fal
982992
983993 return markdown
984994
985- def import2md (self , obj : Any , depth : int = 1 , is_mdx : bool = False ) -> str :
995+ def import2md (self , obj : Any , depth : int = 1 , is_mdx : bool = False , include_toc : bool = False ) -> str :
986996 """Generates markdown documentation for a selected object/import.
987997
988998 Args:
989999 obj (Any): Selcted object for markdown docs generation.
9901000 depth (int, optional): Number of # to append before heading. Defaults to 1.
9911001 is_mdx (bool, optional): JSX support. Default to False.
1002+ include_toc(bool, Optional): Include table of contents for module file. Defaults to False.
9921003
9931004 Returns:
9941005 str: Markdown documentation of selected object.
9951006 """
9961007 if inspect .isclass (obj ):
9971008 return self .class2md (obj , depth = depth , is_mdx = is_mdx )
9981009 elif isinstance (obj , types .ModuleType ):
999- return self .module2md (obj , depth = depth , is_mdx = is_mdx )
1010+ return self .module2md (obj , depth = depth , is_mdx = is_mdx , include_toc = include_toc )
10001011 elif callable (obj ):
10011012 return self .func2md (obj , depth = depth , is_mdx = is_mdx )
10021013 else :
@@ -1072,6 +1083,26 @@ def overview2md(self, is_mdx: bool = False) -> str:
10721083 modules = modules_md , classes = classes_md , functions = functions_md
10731084 )
10741085
1086+ def toc2md (self , module : types .ModuleType = None , is_mdx : bool = False ) -> str :
1087+ """Generates table of contents for imported object."""
1088+ toc = []
1089+ for obj in self .generated_objects :
1090+ if module and (module .__name__ != obj ["module" ] or obj ["type" ] == "module" ):
1091+ continue
1092+ # module_name = obj["module"].split(".")[-1]
1093+ full_name = obj ["full_name" ]
1094+ name = obj ["name" ]
1095+ if is_mdx :
1096+ link = "./" + obj ["module" ] + ".mdx#" + obj ["anchor_tag" ]
1097+ else :
1098+ link = "./" + obj ["module" ] + ".md#" + obj ["anchor_tag" ]
1099+ line = f"- [`{ name } `]({ link } )"
1100+ depth = max (len (full_name .split ("." )) - 1 , 0 )
1101+ if depth :
1102+ line = "\t " * depth + line
1103+ toc .append (line )
1104+ return _TOC_TEMPLATE .format (toc = "\n " .join (toc ))
1105+
10751106
10761107def generate_docs (
10771108 paths : List [str ],
@@ -1085,6 +1116,7 @@ def generate_docs(
10851116 watermark : bool = True ,
10861117 validate : bool = False ,
10871118 private_modules : bool = False ,
1119+ include_toc : bool = False ,
10881120) -> None :
10891121 """Generates markdown documentation for provided paths based on Google-style docstrings.
10901122
@@ -1166,7 +1198,7 @@ def generate_docs(
11661198 except AttributeError :
11671199 # For older python version compatibility
11681200 mod = loader .find_module (module_name ).load_module (module_name ) # type: ignore
1169- module_md = generator .module2md (mod , is_mdx = is_mdx )
1201+ module_md = generator .module2md (mod , is_mdx = is_mdx , include_toc = include_toc )
11701202 if not module_md :
11711203 # Module md is empty -> ignore module and all submodules
11721204 # Add module to ignore list, so submodule will also be ignored
@@ -1205,7 +1237,7 @@ def generate_docs(
12051237 spec .loader .exec_module (mod ) # type: ignore
12061238
12071239 if mod :
1208- module_md = generator .module2md (mod , is_mdx = is_mdx )
1240+ module_md = generator .module2md (mod , is_mdx = is_mdx , include_toc = include_toc )
12091241 if stdout_mode :
12101242 print (module_md )
12111243 else :
@@ -1250,7 +1282,7 @@ def generate_docs(
12501282 except AttributeError :
12511283 # For older python version compatibility
12521284 mod = loader .find_module (module_name ).load_module (module_name ) # type: ignore
1253- module_md = generator .module2md (mod , is_mdx = is_mdx )
1285+ module_md = generator .module2md (mod , is_mdx = is_mdx , include_toc = include_toc )
12541286
12551287 if not module_md :
12561288 # Module MD is empty -> ignore module and all submodules
0 commit comments