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.
Files changed (28) hide show
  1. {fr_docs-3.4.1 → fr_docs-3.5.0}/PKG-INFO +1 -1
  2. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/build.py +1 -1
  3. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/git.py +3 -4
  4. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/html_pipeline.py +1 -1
  5. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/markdown.py +7 -11
  6. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/search.py +6 -6
  7. fr_docs-3.5.0/fr_docs/update.py +93 -0
  8. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/PKG-INFO +1 -1
  9. {fr_docs-3.4.1 → fr_docs-3.5.0}/pyproject.toml +1 -1
  10. fr_docs-3.4.1/fr_docs/update.py +0 -135
  11. {fr_docs-3.4.1 → fr_docs-3.5.0}/LICENSE.md +0 -0
  12. {fr_docs-3.4.1 → fr_docs-3.5.0}/README.md +0 -0
  13. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/__init__.py +0 -0
  14. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/__main__.py +0 -0
  15. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/config.py +0 -0
  16. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/config_accessors.py +0 -0
  17. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/frontmatter.py +0 -0
  18. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/init.py +0 -0
  19. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/slug.py +0 -0
  20. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/syntax.py +0 -0
  21. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/template.py +0 -0
  22. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs/utils.py +0 -0
  23. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/SOURCES.txt +0 -0
  24. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/dependency_links.txt +0 -0
  25. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/entry_points.txt +0 -0
  26. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/requires.txt +0 -0
  27. {fr_docs-3.4.1 → fr_docs-3.5.0}/fr_docs.egg-info/top_level.txt +0 -0
  28. {fr_docs-3.4.1 → fr_docs-3.5.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fr-docs
3
- Version: 3.4.1
3
+ Version: 3.5.0
4
4
  Summary: Fast static documentation generator with search, versioning, and zero-config setup
5
5
  Author-email: Omena0 <omena0mc@gmail.com>
6
6
  License: # PolyForm Noncommercial License 1.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, remote_hash = _script_version_hash(
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
- if slug.endswith(".md"):
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 + ".md"
66
- if line.endswith(src_path) or line.endswith(f"/{src_path}") or line == 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, output_href, output_asset_href
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
- range_match = re.fullmatch(r"(\d+)-(\d+)(?::\d+)?", location)
44
- if range_match:
45
- return {
46
- "line": int(range_match.group(1)),
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
- "line": int(column_match.group(1)),
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, relative_slug_path, slug_output_name
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.group(0)) if indent_match else 0
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.group(0)) if indent_match else 0
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
- end_line = i + 1
242
- else:
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()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fr-docs
3
- Version: 3.4.1
3
+ Version: 3.5.0
4
4
  Summary: Fast static documentation generator with search, versioning, and zero-config setup
5
5
  Author-email: Omena0 <omena0mc@gmail.com>
6
6
  License: # PolyForm Noncommercial License 1.0.0
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "fr-docs"
9
- version = "3.4.1"
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"
@@ -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