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:
mihailkudravcev
2026-07-29 13:42:22 +03:00
parent cd79549c27
commit 31659d4287
3 changed files with 42 additions and 20 deletions
+6
View File
@@ -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
+1 -1
View File
@@ -1 +1 @@
0.3.11
0.3.12
+34 -18
View File
@@ -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
if rel.startswith(folder_clean + "/"):
folder_rel = rel[: -len("/INDEX.md")]
depth = max(folder_rel.count("/") - folder_clean.count("/"), 0)
rows.append((depth, folder_rel, rel))
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(