fix(export_docs): sidebar folder tree follows parent/child paths
Render _Sidebar entries in DFS order instead of sorting by depth globally. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,6 +2,12 @@
|
||||
|
||||
All notable changes to **export_1c_help** are documented in this file.
|
||||
|
||||
## [0.3.12] - 2026-07-29
|
||||
|
||||
### Fixed
|
||||
|
||||
- `_Sidebar` folder tree: list subfolders under their real parent (DFS), not as a flat sort by depth (which made e.g. `transfer/mapping` appear under `ws`).
|
||||
|
||||
## [0.3.11] - 2026-07-29
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -344,32 +344,28 @@ def _docs_index_rel(folder: str, managed_files: set[str]) -> str | None:
|
||||
|
||||
def _sidebar_folder_links(folder: str, managed_files: set[str]) -> list[tuple[int, str, str]]:
|
||||
"""
|
||||
Return (depth, label, target) for folder index pages in wiki.
|
||||
Return (depth, label, target) for folder index pages in wiki, in tree order.
|
||||
|
||||
Supports both:
|
||||
- nested mode: docs/sub/INDEX.md
|
||||
- flat mode: docs__sub__INDEX.md
|
||||
"""
|
||||
folder_clean = folder.strip().strip("/").strip("\\")
|
||||
rows: list[tuple[int, str, str]] = []
|
||||
|
||||
if not folder_clean:
|
||||
return rows
|
||||
return []
|
||||
|
||||
target_by_folder: dict[str, str] = {}
|
||||
|
||||
# nested mode
|
||||
for rel in managed_files:
|
||||
if not rel.endswith("/INDEX.md"):
|
||||
continue
|
||||
if not rel.startswith(folder_clean + "/"):
|
||||
continue
|
||||
folder_rel = rel[: -len("/INDEX.md")]
|
||||
depth = max(folder_rel.count("/") - folder_clean.count("/"), 0)
|
||||
rows.append((depth, folder_rel, rel))
|
||||
if rel.startswith(folder_clean + "/"):
|
||||
folder_rel = rel[: -len("/INDEX.md")]
|
||||
target_by_folder[folder_rel] = rel
|
||||
|
||||
# flat mode
|
||||
root_flat = f"{folder_clean}__INDEX.md"
|
||||
if root_flat in managed_files:
|
||||
rows.append((0, folder_clean, root_flat))
|
||||
target_by_folder[folder_clean] = root_flat
|
||||
prefix = f"{folder_clean}__"
|
||||
suffix = "__INDEX.md"
|
||||
for rel in managed_files:
|
||||
@@ -379,14 +375,34 @@ def _sidebar_folder_links(folder: str, managed_files: set[str]) -> list[tuple[in
|
||||
if not mid:
|
||||
continue
|
||||
folder_rel = folder_clean + "/" + mid.replace("__", "/")
|
||||
depth = max(folder_rel.count("/") - folder_clean.count("/"), 0)
|
||||
rows.append((depth, folder_rel, rel))
|
||||
target_by_folder[folder_rel] = rel
|
||||
|
||||
# dedupe by target
|
||||
uniq: dict[str, tuple[int, str, str]] = {}
|
||||
for row in rows:
|
||||
uniq[row[2]] = row
|
||||
return sorted(uniq.values(), key=lambda x: (x[0], x[1].casefold()))
|
||||
if not target_by_folder:
|
||||
return []
|
||||
|
||||
children: dict[str, list[str]] = {}
|
||||
for folder_rel in target_by_folder:
|
||||
if folder_rel == folder_clean:
|
||||
continue
|
||||
parent = Path(folder_rel).parent.as_posix()
|
||||
if parent != folder_clean and not parent.startswith(folder_clean + "/"):
|
||||
parent = folder_clean
|
||||
children.setdefault(parent, []).append(folder_rel)
|
||||
|
||||
ordered: list[tuple[int, str, str]] = []
|
||||
|
||||
def walk(parent: str, depth: int) -> None:
|
||||
for child in sorted(children.get(parent, []), key=lambda x: x.casefold()):
|
||||
ordered.append((depth, child, target_by_folder[child]))
|
||||
walk(child, depth + 1)
|
||||
|
||||
if folder_clean in target_by_folder:
|
||||
ordered.append((0, folder_clean, target_by_folder[folder_clean]))
|
||||
walk(folder_clean, 1)
|
||||
else:
|
||||
walk(folder_clean, 0)
|
||||
|
||||
return ordered
|
||||
|
||||
|
||||
def ensure_root_navigation(
|
||||
|
||||
Reference in New Issue
Block a user