fix(nav): de-duplicate package landing pages in splice#61
Conversation
After the multi-package TS refactor (#58), each package showed up twice in the TypeScript sub-group: - once as a standalone PAGE entry (e.g. \`analytics\`) - once as a collapsible GROUP entry (\`{group: \"analytics\", pages: [\"analytics/index/...\"]}\`) Root cause: the splice's \`/index\` strip turned \`analytics/index\` into the bare path \`analytics\`, which got registered as a leaf file at the parent level. Then \`analytics/index/classes/Analytics\` (and siblings) created a sibling \`analytics/\` directory tree. Both ended up in the parent group's pages list. Fix: introduce \`insert_landing()\` which stores the landing page id on the dir node itself (\`_landing\`) rather than as a sibling \`_files\` leaf. \`to_mintlify\` emits \`_landing\` first inside the dir's group, before any \`_files\` or sub-\`_dirs\`. Result: each package gets exactly one collapsible group, with its landing page as the first child. Applied to both: - automation/source-repo-templates/api-docs.typescript.yml (used at doc-generation time) - scripts/splice-sdk-nav.py (used for local re-splicing across all languages: TS, .NET, Python, Rust, C++) docs.json re-spliced locally to clear the duplicates already on main from PR #60.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR prevents duplicate directory landing pages in the TypeScript SDK navigation by introducing landing page tracking in the nav-tree builder. The core script now distinguishes between regular file pages and directory-rooted pages (ending in ChangesNavigation Landing Page Deduplication
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request addresses a duplicate-entries bug in the multi-package navigation by introducing a dedicated landing page mechanism for directory groups. The navigation tree construction logic in api-docs.typescript.yml and splice-sdk-nav.py has been refactored to store landing pages (such as index.md or README.md) directly on directory nodes using a new _landing key, ensuring they are not rendered as separate standalone entries. These changes are reflected in the updated structure of docs.json. Feedback was provided to refactor the insert_file function from a recursive to an iterative approach to improve consistency with the new insert_landing function and mitigate potential recursion depth issues in deep directory structures.
| def insert_file(node, parts, full_id): | ||
| if len(parts) == 1: | ||
| node.setdefault("_files", []).append((parts[0], full_id)) | ||
| return | ||
| head, *rest = parts | ||
| insert(node.setdefault("_dirs", {}).setdefault(head, {}), rest, full_id) | ||
| insert_file( | ||
| node.setdefault("_dirs", {}).setdefault(head, {}), | ||
| rest, | ||
| full_id, | ||
| ) |
There was a problem hiding this comment.
The insert_file function (renamed from insert) uses recursion, whereas the new insert_landing function is iterative. Switching to an iterative approach here would improve consistency and is generally safer for deep directory structures, avoiding potential recursion depth limits.
def insert_file(node, parts, full_id):
cur = node
for i in range(len(parts) - 1):
cur = cur.setdefault("_dirs", {}).setdefault(parts[i], {})
cur.setdefault("_files", []).append((parts[-1], full_id))The current Rust template emits one stub page per crate with name +
version + embedded README + a link out to docs.rs. Functional but
not what users expect from an SDK reference — they see prose, not
the type/function surface (modules, structs, traits, methods with
doc comments and examples) that the canonical rustdoc HTML at
github.io/crates already serves.
Use cargo-doc-md (the maintained rustdoc-JSON-to-markdown
converter) to render real API docs into Mintlify. JSON output
requires nightly so the workflow installs both stable + nightly
toolchains.
Hybrid pipeline: cargo-doc-md handles library crates (lib.rs);
README stubs remain the fallback for binary-only crates (TUIs:
resq-clean, resq-deploy, resq-flame, resq-health, resq-logs,
resq-perf — none of which have a public lib API to document).
Output layout:
- lib crates → OUTPUT_DIR/<crate>/index.md (landing) + per-module
siblings (resq_dsa/bloom.md, resq_dsa/graph.md, etc.)
- bin crates → OUTPUT_DIR/<crate>.md (single README stub)
The version banner injects after the H1 of each landing page so
both shapes carry the same metadata strip. Splice already handles
the dir-with-landing form (PR #61) and flat-file form (PR #49)
naturally.
Co-authored-by: Mike Odnis <engineer@resq.software>
…ly (#66) The Rust template's splice was the original flat version: every entry from _pages.json mapped to a standalone PAGE registration under the language group. This worked when every crate was a single stub page (PR #49 era), but PR #62 introduced multi-file output for library crates (resq-dsa with bloom.md, count_min.md, graph.md, ...). The flat splice rendered all those module pages as direct siblings of the language group rather than collapsing them into a `resq-dsa` group. Visible symptom: clicking `Resq dsa` in the sidebar showed only the index page; the per-module pages were registered but not discoverable from the nav (the user had to type each URL by hand or hope for autocomplete). The right-side TOC showed module structure but the left sidebar was flat. Replace with the hierarchical-with-landing splice from PR #61 (used by TS / .NET / Python / C++): each top-level dir under sdks/rust/api/ becomes a collapsible group with its index.md as the landing, and per-module pages as children. Single-file stub crates (binary-only TUIs) stay as leaf PAGEs. Local docs.json re-spliced with `scripts/splice-sdk-nav.py` so main reflects the corrected structure immediately. Verified Rust nav structure: 1 README + 6 leaf PAGEs (binary-only) + 5 GROUPs (library crates with rustdoc API) Co-authored-by: Mike Odnis <engineer@resq.software>
Symptom
After the multi-package TS refactor (#58 + #60), each package showed up twice in the TypeScript sub-group:
Root cause
The splice's `/index` strip turned the entry `analytics/index` into the bare path `analytics`, which got registered as a leaf file in the parent's `_files` list. Then sibling entries like `analytics/index/classes/Analytics` created a sibling `analytics/` directory tree. Both surfaced into the parent group's `pages` list.
Fix
New `insert_landing()` stores the landing page id on the dir node itself (`_landing`) rather than as a sibling `_files` leaf. `to_mintlify` emits `_landing` first inside the dir's group, before any `_files` or sub-`_dirs`. Each package now gets exactly one collapsible group, with its landing page as the first child.
Applied to both:
`docs.json` re-spliced locally to clear the duplicates already on main from PR #60.
Verified structure
Summary by CodeRabbit