fr-docs 3.4.1__tar.gz → 3.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fr_docs-3.4.1 → fr_docs-3.5.0}/PKG-INFO +1 -1
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/build.py +1 -1
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/git.py +3 -4
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/html_pipeline.py +1 -1
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/markdown.py +7 -11
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/search.py +6 -6
- fr_docs-3.5.0/fr_docs/update.py +93 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/PKG-INFO +1 -1
- {fr_docs-3.4.1 → fr_docs-3.5.0}/pyproject.toml +1 -1
- fr_docs-3.4.1/fr_docs/update.py +0 -135
- {fr_docs-3.4.1 → fr_docs-3.5.0}/LICENSE.md +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/README.md +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/__init__.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/__main__.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/config.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/config_accessors.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/frontmatter.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/init.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/slug.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/syntax.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/template.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/utils.py +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/SOURCES.txt +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/dependency_links.txt +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/entry_points.txt +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/requires.txt +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/top_level.txt +0 -0
- {fr_docs-3.4.1 → fr_docs-3.5.0}/setup.cfg +0 -0
|
@@ -148,7 +148,7 @@ def _resolve_script_version(repo_root, script_rel_path, local_path):
|
|
|
148
148
|
remote content is used instead.
|
|
149
149
|
"""
|
|
150
150
|
local_version, local_hash = _script_version_hash(local_path)
|
|
151
|
-
remote_version,
|
|
151
|
+
remote_version, _remote_hash = _script_version_hash(
|
|
152
152
|
Path(repo_root, script_rel_path)
|
|
153
153
|
)
|
|
154
154
|
|
|
@@ -57,13 +57,12 @@ def _build_pages_by_commit(out, slugs):
|
|
|
57
57
|
elif current_commit:
|
|
58
58
|
# Recover the slug from the file path: strip dir prefix and .md
|
|
59
59
|
slug = line
|
|
60
|
-
|
|
61
|
-
slug = slug[:-3]
|
|
60
|
+
slug = slug.removesuffix(".md")
|
|
62
61
|
# Try to match against known slugs (handles prefix variations)
|
|
63
62
|
matched = None
|
|
64
63
|
for s in slugs:
|
|
65
|
-
src_path = s
|
|
66
|
-
if line.endswith(src_path
|
|
64
|
+
src_path = f"{s}.md"
|
|
65
|
+
if line.endswith((src_path, f"/{src_path}")) or line == src_path:
|
|
67
66
|
matched = s
|
|
68
67
|
break
|
|
69
68
|
if matched is None:
|
|
@@ -43,7 +43,7 @@ from .syntax import (
|
|
|
43
43
|
process_blockquotes,
|
|
44
44
|
)
|
|
45
45
|
from .template import TEMPLATE, build_toc_sidebar
|
|
46
|
-
from .utils import normalized_site_prefix,
|
|
46
|
+
from .utils import normalized_site_prefix, output_asset_href, output_href
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _determine_tagged_sections(config):
|
|
@@ -13,7 +13,6 @@ from markdown.extensions.tables import TableExtension
|
|
|
13
13
|
from .slug import (
|
|
14
14
|
normalize_slug,
|
|
15
15
|
relative_slug_path,
|
|
16
|
-
slug_output_name,
|
|
17
16
|
)
|
|
18
17
|
from .syntax import URL_ATTR_RE
|
|
19
18
|
|
|
@@ -38,20 +37,17 @@ def _parse_code_location(location):
|
|
|
38
37
|
location = str(location or "").strip()
|
|
39
38
|
if not location:
|
|
40
39
|
return {}
|
|
40
|
+
|
|
41
41
|
if re.fullmatch(r"\d+", location):
|
|
42
42
|
return {"line": int(location)}
|
|
43
|
-
|
|
44
|
-
if range_match:
|
|
45
|
-
return {
|
|
46
|
-
|
|
47
|
-
"end_line": int(range_match.group(2)),
|
|
48
|
-
}
|
|
43
|
+
|
|
44
|
+
if range_match := re.fullmatch(r"(\d+)-(\d+)(?::\d+)?", location):
|
|
45
|
+
return {"line": int(range_match[1]), "end_line": int(range_match[2])}
|
|
46
|
+
|
|
49
47
|
column_match = re.fullmatch(r"(\d+):(\d+)", location)
|
|
50
48
|
if column_match:
|
|
51
|
-
return {
|
|
52
|
-
|
|
53
|
-
"column": int(column_match.group(2)),
|
|
54
|
-
}
|
|
49
|
+
return {"line": int(column_match[1]), "column": int(column_match[2])}
|
|
50
|
+
|
|
55
51
|
return {"function": location}
|
|
56
52
|
|
|
57
53
|
|
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
|
|
6
6
|
from .config_accessors import feature_enabled
|
|
7
7
|
from .frontmatter import parse_frontmatter
|
|
8
|
-
from .slug import normalize_slug,
|
|
8
|
+
from .slug import normalize_slug, slug_output_name
|
|
9
9
|
from .utils import output_href
|
|
10
10
|
|
|
11
11
|
# Symbol extraction patterns for various languages
|
|
@@ -229,18 +229,18 @@ def extract_symbols_from_content(content, language):
|
|
|
229
229
|
if symbol_type in ("function", "method", "decorator_function") and language == "python":
|
|
230
230
|
# Find function end by indentation
|
|
231
231
|
indent_match = re.match(r"^[^\S\n]*", lines[line_num - 1])
|
|
232
|
-
indent = len(indent_match
|
|
232
|
+
indent = len(indent_match[0]) if indent_match else 0
|
|
233
233
|
end_line = line_num
|
|
234
|
+
|
|
234
235
|
for i in range(line_num, len(lines)):
|
|
235
236
|
if lines[i].strip():
|
|
236
237
|
indent_match = re.match(r"^[^\S\n]*", lines[i])
|
|
237
|
-
line_indent = len(indent_match
|
|
238
|
+
line_indent = len(indent_match[0]) if indent_match else 0
|
|
238
239
|
if line_indent <= indent:
|
|
239
240
|
end_line = i
|
|
240
241
|
break
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
end_line = i + 1
|
|
242
|
+
|
|
243
|
+
end_line = i + 1
|
|
244
244
|
|
|
245
245
|
symbols.append(
|
|
246
246
|
{
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Update fr-docs resources (script.js, style.css, fonts) from upstream."""
|
|
2
|
+
|
|
3
|
+
import tempfile
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .build import (
|
|
7
|
+
_script_version_hash,
|
|
8
|
+
_write_script_js,
|
|
9
|
+
)
|
|
10
|
+
from .config import load_config
|
|
11
|
+
from .config_accessors import project_name
|
|
12
|
+
from .init import (
|
|
13
|
+
DEFAULT_CSS_URL,
|
|
14
|
+
FAVICON_SVG_URL,
|
|
15
|
+
SCRIPT_JS_URL,
|
|
16
|
+
STYLE_CSS_URL,
|
|
17
|
+
download_file,
|
|
18
|
+
run_fetch_fonts,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def update_resources(config):
|
|
23
|
+
"""Update script.js, style.css, favicon.svg, and fonts from the fr-docs upstream repo.
|
|
24
|
+
|
|
25
|
+
Downloads the latest resources from raw.githubusercontent.com and writes them
|
|
26
|
+
to the local docs/ directory. For script.js, preserves version numbering
|
|
27
|
+
by reading the version from the downloaded content.
|
|
28
|
+
"""
|
|
29
|
+
docs_path = Path(config["_docs_dir"]).resolve()
|
|
30
|
+
updated = []
|
|
31
|
+
|
|
32
|
+
# Update script.js
|
|
33
|
+
with tempfile.NamedTemporaryFile(mode="w+", suffix=".js", delete=False) as tmp:
|
|
34
|
+
tmp_path = Path(tmp.name)
|
|
35
|
+
try:
|
|
36
|
+
if download_file(SCRIPT_JS_URL, tmp_path):
|
|
37
|
+
version, _ = _script_version_hash(tmp_path)
|
|
38
|
+
content = tmp_path.read_text(encoding="utf-8")
|
|
39
|
+
local_path = docs_path / "script.js"
|
|
40
|
+
_write_script_js(local_path, version, content)
|
|
41
|
+
updated.append(f"script.js (v{version})")
|
|
42
|
+
finally:
|
|
43
|
+
tmp_path.unlink(missing_ok=True)
|
|
44
|
+
|
|
45
|
+
# Update style.css
|
|
46
|
+
local_style = docs_path / "style.css"
|
|
47
|
+
if download_file(STYLE_CSS_URL, local_style):
|
|
48
|
+
updated.append("style.css")
|
|
49
|
+
|
|
50
|
+
# Update favicon.svg
|
|
51
|
+
local_favicon = docs_path / "favicon.svg"
|
|
52
|
+
if download_file(FAVICON_SVG_URL, local_favicon):
|
|
53
|
+
updated.append("favicon.svg")
|
|
54
|
+
|
|
55
|
+
# Update fonts (download from Google Fonts, generate fonts.css)
|
|
56
|
+
fonts_dir = docs_path / "fonts"
|
|
57
|
+
if fonts_dir.is_dir():
|
|
58
|
+
old_count = len(list(fonts_dir.iterdir()))
|
|
59
|
+
result = run_fetch_fonts(docs_path, DEFAULT_CSS_URL)
|
|
60
|
+
if result == 0:
|
|
61
|
+
new_count = len(list(fonts_dir.iterdir()))
|
|
62
|
+
if new_count > old_count:
|
|
63
|
+
updated.append(f"fonts ({new_count - old_count} new)")
|
|
64
|
+
else:
|
|
65
|
+
updated.append("fonts (refreshed)")
|
|
66
|
+
|
|
67
|
+
if updated:
|
|
68
|
+
print(f" Updated: {', '.join(updated)}")
|
|
69
|
+
else:
|
|
70
|
+
print(" No resources updated.")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def main(argv=None) -> None:
|
|
74
|
+
import argparse
|
|
75
|
+
|
|
76
|
+
parser = argparse.ArgumentParser(
|
|
77
|
+
prog="fr-docs update",
|
|
78
|
+
description="Update fr-docs resources (script.js, style.css, fonts) from upstream.",
|
|
79
|
+
)
|
|
80
|
+
parser.add_argument(
|
|
81
|
+
"--config",
|
|
82
|
+
help="Path to the configuration JSON file.",
|
|
83
|
+
)
|
|
84
|
+
args = parser.parse_args(argv)
|
|
85
|
+
|
|
86
|
+
config = load_config(args.config)
|
|
87
|
+
print(f"🔄 Updating {project_name(config)} resources...")
|
|
88
|
+
update_resources(config)
|
|
89
|
+
print("✅ Update complete.")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
main()
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "fr-docs"
|
|
9
|
-
version = "3.
|
|
9
|
+
version = "3.5.0"
|
|
10
10
|
description = "Fast static documentation generator with search, versioning, and zero-config setup"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
requires-python = ">=3.14"
|
fr_docs-3.4.1/fr_docs/update.py
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
"""Update fr-docs resources (script.js, style.css, fonts) from the repo."""
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
import shutil
|
|
5
|
-
import subprocess
|
|
6
|
-
import sys
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
|
|
9
|
-
from .config import load_config
|
|
10
|
-
from .config_accessors import out_dir, project_name, src_dir as config_src_dir
|
|
11
|
-
from .build import (
|
|
12
|
-
_resolve_script_version,
|
|
13
|
-
_write_script_js,
|
|
14
|
-
_minify_static_asset,
|
|
15
|
-
_script_version_hash,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def _fetch_remote(repo_root, rel_path):
|
|
20
|
-
"""Fetch a file from the fr-docs repo via git show HEAD:path."""
|
|
21
|
-
try:
|
|
22
|
-
return subprocess.check_output(
|
|
23
|
-
["git", "show", f"HEAD:{rel_path}"],
|
|
24
|
-
cwd=repo_root,
|
|
25
|
-
stderr=subprocess.DEVNULL,
|
|
26
|
-
).decode("utf-8", errors="replace")
|
|
27
|
-
except (subprocess.CalledProcessError, OSError):
|
|
28
|
-
return None
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def _git_current_commit(repo_root):
|
|
32
|
-
try:
|
|
33
|
-
return subprocess.check_output(
|
|
34
|
-
["git", "rev-parse", "HEAD"],
|
|
35
|
-
cwd=repo_root,
|
|
36
|
-
stderr=subprocess.DEVNULL,
|
|
37
|
-
).decode("utf-8", errors="replace").strip()
|
|
38
|
-
except (subprocess.CalledProcessError, OSError):
|
|
39
|
-
return None
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _git_remote_url(repo_root):
|
|
43
|
-
try:
|
|
44
|
-
return subprocess.check_output(
|
|
45
|
-
["git", "remote", "get-url", "origin"],
|
|
46
|
-
cwd=repo_root,
|
|
47
|
-
stderr=subprocess.DEVNULL,
|
|
48
|
-
).decode("utf-8", errors="replace").strip()
|
|
49
|
-
except (subprocess.CalledProcessError, OSError):
|
|
50
|
-
return None
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def _is_fr_docs_repo(repo_root):
|
|
54
|
-
"""Return True if the repo is the fr-docs repo itself."""
|
|
55
|
-
url = _git_remote_url(repo_root) or ""
|
|
56
|
-
return "Omena0/fr-docs" in url or "omena0/fr-docs" in url.lower()
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def update_resources(config):
|
|
60
|
-
"""Update script.js, style.css, favicon.svg, and fonts from the fr-docs repo.
|
|
61
|
-
|
|
62
|
-
Only runs when the current repo IS the fr-docs repo (so we can read
|
|
63
|
-
the source files from git). For downstream repos, the resources are
|
|
64
|
-
pulled from PyPI via the `fr-docs` package or copied from the docs/
|
|
65
|
-
directory.
|
|
66
|
-
"""
|
|
67
|
-
docs_path = Path(config["_docs_dir"]).resolve()
|
|
68
|
-
repo_root = docs_path.parent
|
|
69
|
-
if not _is_fr_docs_repo(repo_root):
|
|
70
|
-
print(" Not the fr-docs repo; skipping remote resource update.")
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
resources = ["script.js", "style.css", "favicon.svg"]
|
|
74
|
-
updated = []
|
|
75
|
-
for name in resources:
|
|
76
|
-
rel = f"docs/{name}"
|
|
77
|
-
remote = _fetch_remote(repo_root, rel)
|
|
78
|
-
if remote is None:
|
|
79
|
-
continue
|
|
80
|
-
local_path = docs_path / name
|
|
81
|
-
if name == "script.js":
|
|
82
|
-
version, content = _resolve_script_version(repo_root, rel, local_path)
|
|
83
|
-
_write_script_js(local_path, version, content)
|
|
84
|
-
updated.append(f"{name} (v{version})")
|
|
85
|
-
else:
|
|
86
|
-
local_path.write_text(remote, encoding="utf-8")
|
|
87
|
-
updated.append(name)
|
|
88
|
-
|
|
89
|
-
# Update fonts
|
|
90
|
-
fonts_dir = docs_path / "fonts"
|
|
91
|
-
if fonts_dir.is_dir():
|
|
92
|
-
remote_fonts = _fetch_remote(repo_root, "docs/fonts")
|
|
93
|
-
# Can't fetch a directory; instead list remote files via git ls-tree
|
|
94
|
-
try:
|
|
95
|
-
out = subprocess.check_output(
|
|
96
|
-
["git", "ls-tree", "-r", "--name-only", "HEAD", "docs/fonts"],
|
|
97
|
-
cwd=repo_root,
|
|
98
|
-
stderr=subprocess.DEVNULL,
|
|
99
|
-
).decode("utf-8", errors="replace")
|
|
100
|
-
for line in out.splitlines():
|
|
101
|
-
fname = Path(line).name
|
|
102
|
-
content = _fetch_remote(repo_root, line)
|
|
103
|
-
if content is not None:
|
|
104
|
-
(fonts_dir / fname).write_text(content, encoding="utf-8")
|
|
105
|
-
updated.append(f"fonts/{fname}")
|
|
106
|
-
except (subprocess.CalledProcessError, OSError):
|
|
107
|
-
pass
|
|
108
|
-
|
|
109
|
-
if updated:
|
|
110
|
-
print(f" Updated: {', '.join(updated)}")
|
|
111
|
-
else:
|
|
112
|
-
print(" No resources updated.")
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def main(argv=None) -> None:
|
|
116
|
-
import argparse
|
|
117
|
-
|
|
118
|
-
parser = argparse.ArgumentParser(
|
|
119
|
-
prog="fr-docs update",
|
|
120
|
-
description="Update fr-docs resources (script.js, style.css, fonts) from the repo.",
|
|
121
|
-
)
|
|
122
|
-
parser.add_argument(
|
|
123
|
-
"--config",
|
|
124
|
-
help="Path to the configuration JSON file.",
|
|
125
|
-
)
|
|
126
|
-
args = parser.parse_args(argv)
|
|
127
|
-
|
|
128
|
-
config = load_config(args.config)
|
|
129
|
-
print(f"🔄 Updating {project_name(config)} resources...")
|
|
130
|
-
update_resources(config)
|
|
131
|
-
print("✅ Update complete.")
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if __name__ == "__main__":
|
|
135
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|