[cad161]: / docs / scripts / plugin.py

Download this file

168 lines (145 with data), 5.3 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import os
from pathlib import Path
import jedi
import mkdocs.config
import mkdocs.plugins
import mkdocs.structure
import mkdocs.structure.files
import mkdocs.structure.nav
import mkdocs.structure.pages
from bs4 import BeautifulSoup
def exclude_file(name):
return name.startswith("assets/fragments/")
# Add the files from the project root
VIRTUAL_FILES = {}
REFERENCE_TEMPLATE = """
# `{ident}`
::: {ident}
options:
show_source: false
"""
def on_files(files: mkdocs.structure.files.Files, config: mkdocs.config.Config):
"""
Recursively the navigation of the mkdocs config
and recursively content of directories of page that point
to directories.
Parameters
----------
config: mkdocs.config.Config
The configuration object
kwargs: dict
Additional arguments
"""
root = Path("edsnlp")
reference_nav = []
for path in sorted(root.rglob("*.py")):
module_path = path.relative_to(root.parent).with_suffix("")
doc_path = Path("reference") / path.relative_to(root.parent).with_suffix(".md")
# full_doc_path = Path("docs/reference/") / doc_path
parts = list(module_path.parts)
current = reference_nav
for part in parts[:-1]:
sub = next((item[part] for item in current if part in item), None)
if sub is None:
current.append({part: []})
sub = current[-1][part]
current = sub
if parts[-1] == "__init__":
parts = parts[:-1]
doc_path = doc_path.with_name("index.md")
current.append({"index.md": str(doc_path)})
elif parts[-1] == "__main__":
continue
else:
current.append({parts[-1]: str(doc_path)})
ident = ".".join(parts)
os.makedirs(doc_path.parent, exist_ok=True)
VIRTUAL_FILES[str(doc_path)] = REFERENCE_TEMPLATE.format(ident=ident)
for item in config["nav"]:
if not isinstance(item, dict):
continue
key = next(iter(item.keys()))
if not isinstance(item[key], str):
continue
if item[key].strip("/") == "reference":
item[key] = reference_nav
VIRTUAL_FILES["contributing.md"] = Path("contributing.md").read_text()
VIRTUAL_FILES["changelog.md"] = Path("changelog.md").read_text()
return mkdocs.structure.files.Files(
[file for file in files if not exclude_file(file.src_path)]
+ [
mkdocs.structure.files.File(
file,
config["docs_dir"],
config["site_dir"],
config["use_directory_urls"],
)
for file in VIRTUAL_FILES
]
)
def on_nav(nav, config, files):
def rec(node):
if isinstance(node, list):
return [rec(item) for item in node]
if node.is_section and node.title == "Code Reference":
return
if isinstance(node, mkdocs.structure.nav.Navigation):
return rec(node.items)
if isinstance(node, mkdocs.structure.nav.Section):
if (
len(node.children)
and node.children[0].is_page
and node.children[0].is_index
):
first = node.children[0]
link = mkdocs.structure.nav.Link(
title=first.title,
url=first.url,
)
link.is_index = True
first.title = "Overview"
node.children.insert(0, link)
return rec(node.children)
rec(nav.items)
def on_page_read_source(page, config):
if page.file.src_path in VIRTUAL_FILES:
return VIRTUAL_FILES[page.file.src_path]
return None
# Get current git commit
GIT_COMMIT = os.popen("git rev-parse --short HEAD").read().strip()
@mkdocs.plugins.event_priority(-2000)
def on_post_page(
output: str,
page: mkdocs.structure.pages.Page,
config: mkdocs.config.Config,
):
"""
Add github links to the html output
"""
# Find all the headings (h1, h2, ...) whose id starts with "edsnlp"
soup = BeautifulSoup(output, "html.parser")
for heading in soup.find_all(["h1", "h2", "h3", "h4", "h5", "h6"]):
ref = heading.get("id", "")
if ref.startswith("edsnlp.") and "--" not in ref:
code = "import edsnlp; " + ref
interpreter = jedi.Interpreter(code, namespaces=[{}])
goto = interpreter.infer(1, len(code))
try:
file = goto[0].module_path.relative_to(Path.cwd())
except Exception:
goto = []
if not goto:
continue
line = goto[0].line
# Add a "[source]" span with a link to the source code in a new tab
url = f"https://github.com/aphp/edsnlp/blob/{GIT_COMMIT}/{file}#L{line}"
heading.append(
BeautifulSoup(
f'<span class="sourced-heading-spacer"></span>'
f'<a href="{url}" target="_blank">[source]</a>',
features="html.parser",
)
)
# add "sourced-heading" to heading class
heading["class"] = heading.get("class", []) + ["sourced-heading"]
return str(soup)