Skip to content

Commit 5a645ab

Browse files
authored
Support for mdx (ml-tooling#64)
1 parent 264da1a commit 5a645ab

File tree

4 files changed

+77
-30
lines changed

4 files changed

+77
-30
lines changed

setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[metadata]
2-
description-file = README.md
2+
description_file = README.md
33
license_files = LICENSE
44

55
[bdist_wheel]

src/lazydocs/_about.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Information about this library. This file will automatically changed."""
22

3-
__version__ = "0.5.0-dev.bugfix"
3+
__version__ = "0.5.1"
44
# __author__
55
# __email__

src/lazydocs/_cli.py

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ def generate(
4242
False,
4343
help="If `True`, validate the docstrings via pydocstyle. Requires pydocstyle to be installed.",
4444
),
45+
output_format: Optional[str] = typer.Option(
46+
None,
47+
help="The output format for the creation of the markdown files. This may be 'md' or 'mdx'. Defaults to md.",
48+
)
49+
4550
) -> None:
4651
"""Generates markdown documentation for your Python project based on Google-style docstrings."""
4752

@@ -52,6 +57,7 @@ def generate(
5257
src_base_url=src_base_url,
5358
remove_package_prefix=remove_package_prefix,
5459
ignored_modules=ignored_modules,
60+
output_format=output_format,
5561
overview_file=overview_file,
5662
watermark=watermark,
5763
validate=validate,

src/lazydocs/generation.py

+69-28
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
<a href="{path}"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square" /></a>
3333
"""
3434

35+
_MDX_SOURCE_BADGE_TEMPLATE = """
36+
<a href="{path}"><img align="right" style={{{{"float":"right"}}}} src="https://img.shields.io/badge/-source-cccccc?style=flat-square" /></a>
37+
"""
38+
3539
_SEPARATOR = """
3640
---
3741
"""
@@ -200,6 +204,7 @@ def to_md_file(
200204
out_path: str = ".",
201205
watermark: bool = True,
202206
disable_markdownlint: bool = True,
207+
is_mdx: bool = False
203208
) -> None:
204209
"""Creates an API docs file from a provided text.
205210
@@ -215,8 +220,13 @@ def to_md_file(
215220
return
216221

217222
md_file = filename
218-
if not filename.endswith(".md"):
219-
md_file = filename + ".md"
223+
224+
if is_mdx:
225+
if not filename.endswith(".mdx"):
226+
md_file = filename + ".mdx"
227+
else:
228+
if not filename.endswith(".md"):
229+
md_file = filename + ".md"
220230

221231
if disable_markdownlint:
222232
markdown_str = "<!-- markdownlint-disable -->\n" + markdown_str
@@ -521,7 +531,7 @@ def _get_src_path(self, obj: Any, append_base: bool = True) -> str:
521531

522532
return relative_path
523533

524-
def func2md(self, func: Callable, clsname: str = "", depth: int = 3) -> str:
534+
def func2md(self, func: Callable, clsname: str = "", depth: int = 3, is_mdx: bool = False) -> str:
525535
"""Takes a function (or method) and generates markdown docs.
526536
527537
Args:
@@ -602,11 +612,14 @@ def func2md(self, func: Callable, clsname: str = "", depth: int = 3) -> str:
602612
)
603613

604614
if path:
605-
markdown = _SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
615+
if is_mdx:
616+
markdown = _MDX_SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
617+
else:
618+
markdown = _SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
606619

607620
return markdown
608621

609-
def class2md(self, cls: Any, depth: int = 2) -> str:
622+
def class2md(self, cls: Any, depth: int = 2, is_mdx: bool = False) -> str:
610623
"""Takes a class and creates markdown text to document its methods and variables.
611624
612625
Args:
@@ -646,7 +659,7 @@ def class2md(self, cls: Any, depth: int = 2) -> str:
646659
hasattr(cls.__init__, "__module__")
647660
and cls.__init__.__module__ == modname
648661
):
649-
init = self.func2md(cls.__init__, clsname=clsname)
662+
init = self.func2md(cls.__init__, clsname=clsname, is_mdx=is_mdx)
650663
else:
651664
init = ""
652665
except (ValueError, TypeError):
@@ -698,7 +711,7 @@ def class2md(self, cls: Any, depth: int = 2) -> str:
698711
# object module should be the same as the calling module
699712
and obj.__module__ == modname
700713
):
701-
function_md = self.func2md(obj, clsname=clsname, depth=depth + 1)
714+
function_md = self.func2md(obj, clsname=clsname, depth=depth + 1, is_mdx=is_mdx)
702715
if function_md:
703716
methods.append(_SEPARATOR + function_md)
704717

@@ -713,11 +726,14 @@ def class2md(self, cls: Any, depth: int = 2) -> str:
713726
)
714727

715728
if path:
716-
markdown = _SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
729+
if is_mdx:
730+
markdown = _MDX_SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
731+
else:
732+
markdown = _SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
717733

718734
return markdown
719735

720-
def module2md(self, module: types.ModuleType, depth: int = 1) -> str:
736+
def module2md(self, module: types.ModuleType, depth: int = 1, is_mdx: bool = False) -> str:
721737
"""Takes an imported module object and create a Markdown string containing functions and classes.
722738
723739
Args:
@@ -758,7 +774,7 @@ def module2md(self, module: types.ModuleType, depth: int = 1) -> str:
758774
and hasattr(obj, "__module__")
759775
and obj.__module__ == modname
760776
):
761-
class_markdown = self.class2md(obj, depth=depth + 1)
777+
class_markdown = self.class2md(obj, depth=depth + 1, is_mdx=is_mdx)
762778
if class_markdown:
763779
classes.append(_SEPARATOR + class_markdown)
764780
line_nos.append(_get_line_no(obj) or 0)
@@ -774,7 +790,7 @@ def module2md(self, module: types.ModuleType, depth: int = 1) -> str:
774790
and hasattr(obj, "__module__")
775791
and obj.__module__ == modname
776792
):
777-
function_md = self.func2md(obj, depth=depth + 1)
793+
function_md = self.func2md(obj, depth=depth + 1, is_mdx=is_mdx)
778794
if function_md:
779795
functions.append(_SEPARATOR + function_md)
780796
line_nos.append(_get_line_no(obj) or 0)
@@ -808,11 +824,14 @@ def module2md(self, module: types.ModuleType, depth: int = 1) -> str:
808824
)
809825

810826
if path:
811-
markdown = _SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
827+
if (is_mdx):
828+
markdown = _MDX_SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
829+
else:
830+
markdown = _SOURCE_BADGE_TEMPLATE.format(path=path) + markdown
812831

813832
return markdown
814833

815-
def import2md(self, obj: Any, depth: int = 1) -> str:
834+
def import2md(self, obj: Any, depth: int = 1, is_mdx: bool = False) -> str:
816835
"""Generates markdown documentation for a selected object/import.
817836
818837
Args:
@@ -823,16 +842,16 @@ def import2md(self, obj: Any, depth: int = 1) -> str:
823842
str: Markdown documentation of selected object.
824843
"""
825844
if inspect.isclass(obj):
826-
return self.class2md(obj, depth=depth)
845+
return self.class2md(obj, depth=depth, is_mdx=is_mdx)
827846
elif isinstance(obj, types.ModuleType):
828-
return self.module2md(obj, depth=depth)
847+
return self.module2md(obj, depth=depth, is_mdx=is_mdx)
829848
elif callable(obj):
830-
return self.func2md(obj, depth=depth)
849+
return self.func2md(obj, depth=depth, is_mdx=is_mdx)
831850
else:
832851
print(f"Could not generate markdown for object type {str(type(obj))}")
833852
return ""
834853

835-
def overview2md(self) -> str:
854+
def overview2md(self, is_mdx: bool = False) -> str:
836855
"""Generates a documentation overview file based on the generated docs."""
837856

838857
entries_md = ""
@@ -841,7 +860,10 @@ def overview2md(self) -> str:
841860
):
842861
full_name = obj["full_name"]
843862
if "module" in obj:
844-
link = "./" + obj["module"] + ".md#" + obj["anchor_tag"]
863+
if is_mdx:
864+
link = "./" + obj["module"] + ".mdx#" + obj["anchor_tag"]
865+
else:
866+
link = "./" + obj["module"] + ".md#" + obj["anchor_tag"]
845867
else:
846868
link = "#unknown"
847869

@@ -857,7 +879,10 @@ def overview2md(self) -> str:
857879
for obj in list(filter(lambda d: d["type"] == "class", self.generated_objects)):
858880
module_name = obj["module"].split(".")[-1]
859881
name = module_name + "." + obj["full_name"]
860-
link = "./" + obj["module"] + ".md#" + obj["anchor_tag"]
882+
if is_mdx:
883+
link = "./" + obj["module"] + ".mdx#" + obj["anchor_tag"]
884+
else:
885+
link = "./" + obj["module"] + ".md#" + obj["anchor_tag"]
861886
description = obj["description"]
862887
entries_md += f"\n- [`{name}`]({link})"
863888
if description:
@@ -872,7 +897,10 @@ def overview2md(self) -> str:
872897
):
873898
module_name = obj["module"].split(".")[-1]
874899
name = module_name + "." + obj["full_name"]
875-
link = "./" + obj["module"] + ".md#" + obj["anchor_tag"]
900+
if is_mdx:
901+
link = "./" + obj["module"] + ".mdx#" + obj["anchor_tag"]
902+
else:
903+
link = "./" + obj["module"] + ".md#" + obj["anchor_tag"]
876904
description = obj["description"]
877905
entries_md += f"\n- [`{name}`]({link})"
878906
if description:
@@ -893,6 +921,7 @@ def generate_docs(
893921
src_base_url: Optional[str] = None,
894922
remove_package_prefix: bool = False,
895923
ignored_modules: Optional[List[str]] = None,
924+
output_format: Optional[str] = None,
896925
overview_file: Optional[str] = None,
897926
watermark: bool = True,
898927
validate: bool = False,
@@ -919,6 +948,10 @@ def generate_docs(
919948
if not ignored_modules:
920949
ignored_modules = list()
921950

951+
if output_format and output_format != 'md' and output_format != 'mdx':
952+
raise Exception(f"Unsupported output format: {output_format}. Choose either 'md' or 'mdx'.")
953+
is_mdx = output_format == 'mdx'
954+
922955
if not src_root_path:
923956
try:
924957
# Set src root path to git root
@@ -967,7 +1000,7 @@ def generate_docs(
9671000
try:
9681001
mod_spec = loader.find_spec(module_name)
9691002
mod = importlib.util.module_from_spec(mod_spec)
970-
module_md = generator.module2md(mod)
1003+
module_md = generator.module2md(mod, is_mdx=is_mdx)
9711004
if not module_md:
9721005
# Module md is empty -> ignore module and all submodules
9731006
# Add module to ignore list, so submodule will also be ignored
@@ -982,6 +1015,7 @@ def generate_docs(
9821015
mod.__name__,
9831016
out_path=output_path,
9841017
watermark=watermark,
1018+
is_mdx=is_mdx,
9851019
)
9861020
except Exception as ex:
9871021
print(
@@ -1005,7 +1039,7 @@ def generate_docs(
10051039
spec.loader.exec_module(mod) # type: ignore
10061040

10071041
if mod:
1008-
module_md = generator.module2md(mod)
1042+
module_md = generator.module2md(mod, is_mdx=is_mdx)
10091043
if stdout_mode:
10101044
print(module_md)
10111045
else:
@@ -1014,6 +1048,7 @@ def generate_docs(
10141048
module_name,
10151049
out_path=output_path,
10161050
watermark=watermark,
1051+
is_mdx=is_mdx,
10171052
)
10181053
else:
10191054
raise Exception(f"Failed to generate markdown for {path}")
@@ -1044,7 +1079,7 @@ def generate_docs(
10441079
try:
10451080
mod_spec = loader.find_spec(module_name)
10461081
mod = importlib.util.module_from_spec(mod_spec)
1047-
module_md = generator.module2md(mod)
1082+
module_md = generator.module2md(mod, is_mdx=is_mdx)
10481083

10491084
if not module_md:
10501085
# Module MD is empty -> ignore module and all submodules
@@ -1060,32 +1095,38 @@ def generate_docs(
10601095
mod.__name__,
10611096
out_path=output_path,
10621097
watermark=watermark,
1098+
is_mdx=is_mdx
10631099
)
10641100
except Exception as ex:
10651101
print(
10661102
f"Failed to generate docs for module {module_name}: "
10671103
+ repr(ex)
10681104
)
10691105
else:
1070-
import_md = generator.import2md(obj)
1106+
import_md = generator.import2md(obj, is_mdx=is_mdx)
10711107
if stdout_mode:
10721108
print(import_md)
10731109
else:
10741110
to_md_file(
1075-
import_md, path, out_path=output_path, watermark=watermark
1111+
import_md, path, out_path=output_path, watermark=watermark, is_mdx=is_mdx
10761112
)
10771113
else:
10781114
raise Exception(f"Failed to generate markdown for {path}.")
10791115

10801116
if overview_file and not stdout_mode:
1081-
if not overview_file.endswith(".md"):
1082-
overview_file = overview_file + ".md"
1117+
if is_mdx:
1118+
if not overview_file.endswith(".mdx"):
1119+
overview_file = overview_file + ".mdx"
1120+
else:
1121+
if not overview_file.endswith(".md"):
1122+
overview_file = overview_file + ".md"
10831123

10841124
to_md_file(
1085-
generator.overview2md(),
1125+
generator.overview2md(is_mdx=is_mdx),
10861126
overview_file,
10871127
out_path=output_path,
10881128
watermark=watermark,
1129+
is_mdx=is_mdx
10891130
)
10901131

10911132
# Write mkdocs pages file

0 commit comments

Comments
 (0)