Skip to content

Commit 3c15fdd

Browse files
committed
Robustness update.
Better concurrency and error handling, sanity checks, argument type validation. Better cross-platform support. Added num_failed to `with server.atomic() as num_failed:`. Added dependency version pinning.
1 parent 32e1c35 commit 3c15fdd

139 files changed

Lines changed: 1638 additions & 799 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/deploy-pages.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ jobs:
3838

3939
- name: Install Node tools
4040
run: |
41-
npm install --no-audit --no-fund --no-save html-minifier-next critical
41+
npm install --no-audit --no-fund --no-save html-minifier-next@6.1.2 critical@7.2.1
4242
4343
- name: Build docs
4444
run: |
45-
pip install markdown zstandard
45+
pip install markdown==3.10.2 zstandard==0.25.0
4646
python docs/build.py
4747
4848
- name: Setup Pages

changelog.md

Lines changed: 178 additions & 174 deletions
Large diffs are not rendered by default.

docs/build.py

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,57 @@
158158

159159
def slug_basename(slug):
160160
"""Extract the filename part from a possibly prefixed slug (e.g. 'core/entity' → 'entity')."""
161-
return slug.rsplit("/", 1)[-1]
161+
normalized = str(slug).replace("\\", "/").strip("/")
162+
if not normalized:
163+
return ""
164+
165+
return normalized.rsplit("/", 1)[-1]
166+
167+
def _normalize_slug(slug):
168+
"""Normalize slugs to forward-slash format for cross-platform consistency."""
169+
return str(slug).replace("\\", "/").strip("/")
170+
171+
def _build_slug_page_keys(slugs):
172+
"""Build unique output keys for slugs, disambiguating basename collisions."""
173+
groups = {}
174+
for slug in slugs:
175+
norm = _normalize_slug(slug)
176+
base = slug_basename(norm).lower()
177+
groups.setdefault(base, []).append(norm)
178+
179+
keys = {}
180+
used = set()
181+
for base, entries in sorted(groups.items()):
182+
entries = sorted(set(entries))
183+
has_collision = len(entries) > 1
184+
for norm in entries:
185+
if not has_collision:
186+
base_key = slug_basename(norm)
187+
elif base == "index" and norm == "index":
188+
base_key = "index"
189+
else:
190+
base_key = norm.replace("/", "__")
191+
192+
candidate = base_key
193+
suffix = 2
194+
while candidate in used:
195+
candidate = f"{base_key}-{suffix}"
196+
suffix += 1
197+
198+
used.add(candidate)
199+
keys[norm] = candidate
200+
201+
return keys
202+
203+
def slug_page_key(slug):
204+
"""Return the stable output key for a slug."""
205+
norm = _normalize_slug(slug)
206+
return SLUG_PAGE_KEYS.get(norm, slug_basename(norm))
207+
208+
def slug_output_name(slug):
209+
"""Return output HTML filename for a slug."""
210+
key = slug_page_key(slug)
211+
return "index.html" if key == "index" else f"{key}.html"
162212

163213

164214
# ── Frontmatter parser ──────────────────────────────────────────────────────
@@ -406,9 +456,8 @@ def build_sidebar_html(current_slug):
406456
)
407457
is_ext = section_name == "Extensions"
408458
for slug, label in pages:
409-
base = slug_basename(slug)
410459
active = ' class="active"' if slug == current_slug else ''
411-
href = "index.html" if base == "index" else f"{base}.html"
460+
href = slug_output_name(slug)
412461
display = f'{label} <span class="ext-tag">ext</span>' if is_ext else label
413462
parts.append(f' <li><a href="{href}"{active}>{display}</a></li>')
414463

@@ -617,7 +666,7 @@ def _safe(s):
617666
except Exception as e:
618667
print(f'Failed to minify HTML: {e}')
619668

620-
out_name = "index.html" if slug_basename(slug) == "index" else f"{slug_basename(slug)}.html"
669+
out_name = slug_output_name(slug)
621670
out_path = os.path.join(OUT_DIR, out_name)
622671
with open(out_path, "w", encoding="utf-8") as f:
623672
f.write(out_html)
@@ -727,12 +776,13 @@ def get_all_slugs():
727776
SEARCH_MAP = {}
728777
VERSION_OPTIONS = ""
729778
_git_meta_json = '{}'
779+
SLUG_PAGE_KEYS = {}
730780

731781
WORKERS = 18
732782

733783
def main():
734784
"""Build the static documentation site from markdown sources."""
735-
global _search_index_zstd_b64
785+
global _search_index_zstd_b64, SLUG_PAGE_KEYS
736786
print("📖 Building PyJavaBridge docs...")
737787
print(f" Source: {SRC_DIR}")
738788
print(f" Output: {OUT_DIR}")
@@ -761,6 +811,8 @@ def main():
761811
if s not in slugs:
762812
slugs.append(s)
763813

814+
SLUG_PAGE_KEYS = _build_slug_page_keys(slugs)
815+
764816
built = 0
765817
search_index = []
766818

@@ -832,8 +884,15 @@ def main():
832884
if table_first_cols:
833885
sections.append({"heading": current_heading, "text": ", ".join(table_first_cols)})
834886

835-
url = "index.html" if slug_basename(slug) == "index" else f"{slug_basename(slug)}.html"
836-
search_index.append({"slug": slug_basename(slug), "title": title, "url": url, "sections": sections})
887+
page_key = slug_page_key(slug)
888+
url = slug_output_name(slug)
889+
search_index.append({
890+
"slug": page_key,
891+
"source_slug": _normalize_slug(slug),
892+
"title": title,
893+
"url": url,
894+
"sections": sections,
895+
})
837896

838897
import json
839898

@@ -846,8 +905,8 @@ def main():
846905
SEARCH_MAP = {}
847906
for item in search_index:
848907
title = item.get('title') or ''
849-
slug = item.get('slug')
850-
if not title or not slug:
908+
source_slug = item.get('source_slug') or item.get('slug')
909+
if not title or not source_slug:
851910
continue
852911

853912
# Remove explicit [ext] markers and lightweight markdown chars
@@ -859,7 +918,7 @@ def main():
859918
if cleaned == 'PyJavaBridge' or title == 'PyJavaBridge':
860919
continue
861920

862-
dest = f"{slug}.md"
921+
dest = f"{source_slug}.md"
863922
# Map both cleaned and original titles (if different)
864923
SEARCH_MAP[cleaned] = dest
865924
if title != cleaned:
@@ -991,7 +1050,7 @@ def words(s):
9911050
# markdown path so the client can fetch raw markdown at a historical
9921051
# commit when the generated HTML isn't present in that commit.
9931052
try:
994-
src_map = {slug_basename(s): f"docs/src/{s}.md" for s in slugs}
1053+
src_map = {slug_page_key(s): f"docs/src/{_normalize_slug(s)}.md" for s in slugs}
9951054
except Exception:
9961055
src_map = {}
9971056

@@ -1013,13 +1072,14 @@ def words(s):
10131072
tree_files = set()
10141073
avail = []
10151074
for s in slugs:
1075+
normalized = _normalize_slug(s)
10161076
# Check both the full slug path (e.g. docs/src/getting_started/index.md)
10171077
# and the basename path (e.g. docs/src/index.md) because files
10181078
# were moved between commits and may appear under either location.
1019-
path_full = f"docs/src/{s}.md"
1020-
path_base = f"docs/src/{slug_basename(s)}.md"
1079+
path_full = f"docs/src/{normalized}.md"
1080+
path_base = f"docs/src/{slug_basename(normalized)}.md"
10211081
if path_full in tree_files or path_base in tree_files:
1022-
avail.append(slug_basename(s))
1082+
avail.append(slug_page_key(s))
10231083
pages_by_commit[c] = avail
10241084
except Exception:
10251085
pages_by_commit = {}
@@ -1096,10 +1156,10 @@ def words(s):
10961156
slug = future_to_slug[fut]
10971157
try:
10981158
fut.result()
1099-
print(f" ✓ {slug_basename(slug)}.html")
1159+
print(f" ✓ {slug_output_name(slug)}")
11001160
built += 1
11011161
except Exception as e:
1102-
print(f" ✗ {slug_basename(slug)}.html (error: {e})")
1162+
print(f" ✗ {slug_output_name(slug)} (error: {e})")
11031163
else:
11041164
print("No pages found to build.")
11051165

docs/site/ability.html

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

docs/site/actionbardisplay.html

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

docs/site/advancement.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/site/attribute.html

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

docs/site/bank.html

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

docs/site/block.html

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

docs/site/blockdisplay.html

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)