diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed3f1a..a135bb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/VERSION b/VERSION index 2080591..0b9c019 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.11 +0.3.12 diff --git a/export1c_help/docs_export.py b/export1c_help/docs_export.py index 2efbe72..c9ec973 100644 --- a/export1c_help/docs_export.py +++ b/export1c_help/docs_export.py @@ -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(