-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #230 from napse-invest/feature/mkdocstring
Feature/mkdocstring
- Loading branch information
Showing
5 changed files
with
194 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ on: | |
push: | ||
branches: | ||
- main | ||
- dev | ||
|
||
permissions: | ||
contents: write | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import ast | ||
import re | ||
from functools import partial | ||
from pathlib import Path | ||
from typing import Tuple | ||
|
||
from griffe.dataclasses import Object as GriffeObject | ||
from griffe.extensions import VisitorExtension | ||
from pymdownx.slugs import slugify | ||
|
||
DOCS_PATH = Path(__file__).parent.parent | ||
slugifier = slugify(case="lower") | ||
|
||
|
||
def find_heading(content: str, slug: str, file_path: Path) -> Tuple[str, int]: | ||
for m in re.finditer("^#+ (.+)", content, flags=re.M): | ||
heading = m.group(1) | ||
h_slug = slugifier(heading, "-") | ||
if h_slug == slug: | ||
return heading, m.end() | ||
msg = f"heading with slug {slug!r} not found in {file_path}" | ||
raise ValueError(msg) | ||
|
||
|
||
def insert_at_top(path: str, api_link: str) -> str: | ||
rel_file = path.rstrip("/") + ".md" | ||
file_path = DOCS_PATH / rel_file | ||
content = file_path.read_text() | ||
second_heading = re.search("^#+ ", content, flags=re.M) | ||
assert second_heading, "unable to find second heading in file" # noqa: S101 | ||
first_section = content[: second_heading.start()] | ||
|
||
if f"[{api_link}]" not in first_section: | ||
print(f'inserting API link "{api_link}" at the top of {file_path.relative_to(DOCS_PATH)}') | ||
file_path.write_text('??? api "API Documentation"\n' f" [`{api_link}`][{api_link}]<br>\n\n{content}") # noqa: ISC001 | ||
|
||
heading = file_path.stem.replace("_", " ").title() | ||
return f'!!! abstract "Usage Documentation"\n [{heading}](../{rel_file})\n' | ||
|
||
|
||
def replace_links(m: re.Match, *, api_link: str) -> str: | ||
path_group = m.group(1) | ||
if "#" not in path_group: | ||
# no heading id, put the content at the top of the page | ||
return insert_at_top(path_group, api_link) | ||
|
||
usage_path, slug = path_group.split("#", 1) | ||
rel_file = usage_path.rstrip("/") + ".md" | ||
file_path = DOCS_PATH / rel_file | ||
content = file_path.read_text() | ||
heading, heading_end = find_heading(content, slug, file_path) | ||
|
||
next_heading = re.search("^#+ ", content[heading_end:], flags=re.M) | ||
next_section = content[heading_end : heading_end + next_heading.start()] if next_heading else content[heading_end:] | ||
|
||
if f"[{api_link}]" not in next_section: | ||
print(f'inserting API link "{api_link}" into {file_path.relative_to(DOCS_PATH)}') | ||
file_path.write_text( | ||
f"{content[:heading_end]}\n\n" '??? api "API Documentation"\n' f" [`{api_link}`][{api_link}]<br>" f"{content[heading_end:]}", # noqa: ISC001 | ||
) | ||
|
||
return f'!!! abstract "Usage Documentation"\n [{heading}](../{rel_file}#{slug})\n' | ||
|
||
|
||
def update_docstring(obj: GriffeObject) -> str: | ||
return re.sub( | ||
r"usage[\- ]docs: ?https://docs\.pydantic\.dev/.+?/(\S+)", | ||
partial(replace_links, api_link=obj.path), | ||
obj.docstring.value, | ||
flags=re.I, | ||
) | ||
|
||
|
||
def update_docstrings_recursively(obj: GriffeObject) -> None: | ||
if obj.docstring: | ||
obj.docstring.value = update_docstring(obj) | ||
for member in obj.members.values(): | ||
if not member.is_alias: | ||
update_docstrings_recursively(member) | ||
|
||
|
||
class Extension(VisitorExtension): | ||
def visit_module(self, node: ast.AST) -> None: | ||
module = self.visitor.current.module | ||
update_docstrings_recursively(module) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
.tile { | ||
display: flex; | ||
text-align: center; | ||
width: 120px; | ||
height: 120px; | ||
display: inline-block; | ||
margin: 10px; | ||
padding: 5px; | ||
border-radius: .5rem; | ||
} | ||
|
||
.tile img { | ||
width: 100px; | ||
} | ||
|
||
.md-typeset__table > table { | ||
max-height: 60vh; | ||
} | ||
|
||
.md-typeset__table > table thead { | ||
position: sticky; | ||
top: 0; | ||
background-color: var(--md-default-bg-color); | ||
} | ||
|
||
.md-typeset__table > table th { | ||
border-bottom: .05rem solid var(--md-typeset-table-color); | ||
} | ||
|
||
.md-typeset__table > table tr:first-child td { | ||
border-top: none; | ||
} | ||
|
||
/* API documentation link admonition */ | ||
:root { | ||
--md-admonition-icon--api: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 7H5a2 2 0 0 0-2 2v8h2v-4h2v4h2V9a2 2 0 0 0-2-2m0 4H5V9h2m7-2h-4v10h2v-4h2a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2m0 4h-2V9h2m6 0v6h1v2h-4v-2h1V9h-1V7h4v2Z"/></svg>') | ||
} | ||
.md-typeset .admonition.api, .md-typeset details.api { | ||
border-color: #448aff; | ||
} | ||
.md-typeset .api > .admonition-title, .md-typeset .api > summary { | ||
background-color: #448aff1a; | ||
} | ||
.md-typeset .api > .admonition-title::before, .md-typeset .api > summary::before { | ||
background-color: #448aff; | ||
-webkit-mask-image: var(--md-admonition-icon--api); | ||
mask-image: var(--md-admonition-icon--api); | ||
} | ||
|
||
/* Revert hue value to that of pre mkdocs-material v9.4.0 */ | ||
[data-md-color-scheme="slate"] { | ||
--md-hue: 230; | ||
--md-default-bg-color: hsla(230, 15%, 21%, 1); | ||
} | ||
|
||
|
||
/* Indentation. */ | ||
div.doc-contents:not(.first) { | ||
padding-left: 25px; | ||
border-left: .05rem solid var(--md-typeset-table-color); | ||
} | ||
|
||
/* Mark external links as such. */ | ||
a.external::after, | ||
a.autorefs-external::after { | ||
/* https://primer.style/octicons/arrow-up-right-24 */ | ||
mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.25 15.5a.75.75 0 00.75-.75v-9a.75.75 0 00-.75-.75h-9a.75.75 0 000 1.5h7.19L6.22 16.72a.75.75 0 101.06 1.06L17.5 7.56v7.19c0 .414.336.75.75.75z"></path></svg>'); | ||
-webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.25 15.5a.75.75 0 00.75-.75v-9a.75.75 0 00-.75-.75h-9a.75.75 0 000 1.5h7.19L6.22 16.72a.75.75 0 101.06 1.06L17.5 7.56v7.19c0 .414.336.75.75.75z"></path></svg>'); | ||
content: ' '; | ||
|
||
display: inline-block; | ||
vertical-align: middle; | ||
position: relative; | ||
|
||
height: 1em; | ||
width: 1em; | ||
background-color: var(--md-typeset-a-color); | ||
} | ||
|
||
a.external:hover::after, | ||
a.autorefs-external:hover::after { | ||
background-color: var(--md-accent-fg-color); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters