Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 54 additions & 9 deletions automation/source-repo-templates/api-docs.rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -490,12 +490,12 @@ jobs:
cp -R "${OUTPUT_DIR}/." "$target/"

- name: Splice _pages.json into docs.json nav
# Mintlify only routes pages registered in docs.json. The
# _pages.json artifact lists every generated Markdown path;
# rewrite the matching language sub-group under the
# 'Generated Package References' group so all pages are
# discoverable, in-content cross-links resolve, and direct
# URLs work.
# Mintlify only routes pages registered in docs.json. Build
# hierarchical groups so each library crate becomes its own
# collapsible sidebar entry (`resq-dsa` → bloom, count_min,
# graph, ...) instead of flat siblings under the language
# group. Single-file stub crates (binary-only TUIs) stay as
# leaf pages directly under Rust.
working-directory: docs-checkout
run: |
python3 - <<'PYINNER'
Expand All @@ -512,9 +512,54 @@ jobs:
raise SystemExit(f"missing {pages_path}")
raw = json.loads(pages_path.read_text())

new_pages = [f"{PREFIX}/README"] + [
f"{PREFIX}/{p}" for p in raw if p != "README"
]
tree: dict = {}

def insert_file(node, parts, full_id):
if len(parts) == 1:
node.setdefault("_files", []).append((parts[0], full_id))
return
head, *rest = parts
insert_file(
node.setdefault("_dirs", {}).setdefault(head, {}),
rest,
full_id,
)

def insert_landing(node, parts, full_id):
# Drill down to the dir node for `parts` and store the
# landing page id there. Stored on the dir itself
# rather than as a sibling _files leaf so the dir and
# its landing aren't both rendered in the parent group
# (the duplicate-entries bug fixed in #61).
cur = node
for part in parts:
cur = cur.setdefault("_dirs", {}).setdefault(part, {})
cur["_landing"] = full_id

for p in raw:
if p in ("README", "index"):
continue
if p.endswith("/index") or p.endswith("/README"):
bare = p.rsplit("/", 1)[0]
full_id = f"{PREFIX}/{bare}"
parts = bare.split("/")
insert_landing(tree, parts, full_id)
else:
full_id = f"{PREFIX}/{p}"
parts = p.split("/")
insert_file(tree, parts, full_id)

def to_mintlify(node, group_name):
pages = []
if "_landing" in node:
pages.append(node["_landing"])
for fname, full_id in sorted(node.get("_files", [])):
pages.append(full_id)
for dname, sub in sorted(node.get("_dirs", {}).items()):
pages.append(to_mintlify(sub, dname))
return pages if group_name is None else {"group": group_name, "pages": pages}
Comment on lines +552 to +560
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current logic results in duplicate entries in the sidebar when a module (e.g., commands) has both a documentation file and a subdirectory for submodules. This happens because the file is added to the parent's _files list while the subdirectory becomes a separate group.

We should detect when a file name matches a subdirectory name and use that file as the landing page for the group to provide a cleaner navigation experience and ensure the output adheres to the Mintlify nested group structure.

          def to_mintlify(node, group_name):
              pages = []
              if "_landing" in node:
                  pages.append(node["_landing"])

              files = {fname: full_id for fname, full_id in node.get("_files", [])}
              dirs = node.get("_dirs", {})

              # Merge files that act as landing pages for subdirectories
              for dname, sub in dirs.items():
                  if dname in files:
                      sub["_landing"] = files.pop(dname)

              for fname in sorted(files):
                  pages.append(files[fname])
              for dname, sub in sorted(dirs.items()):
                  pages.append(to_mintlify(sub, dname))

              return pages if group_name is None else {"group": group_name, "pages": pages}
References
  1. In Mintlify docs.json navigation configuration, use a nested group object to define custom sidebar labels for pages, as the schema does not support a label property within the pages array.


new_pages = [f"{PREFIX}/README"] + to_mintlify(tree, None)

en = next(l for l in docs["navigation"]["languages"] if l["language"] == "en")
sdks_tab = next(t for t in en["tabs"] if t["tab"] == "SDKs")
Expand Down
102 changes: 66 additions & 36 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -2145,47 +2145,77 @@
"group": "Rust",
"pages": [
"sdks/rust/api/README",
"sdks/rust/api/resq-ai/config",
"sdks/rust/api/resq-ai/index",
"sdks/rust/api/resq-ai/provider",
"sdks/rust/api/resq-ai/token",
"sdks/rust/api/resq-bin/analysis",
"sdks/rust/api/resq-bin/bin_explorer",
"sdks/rust/api/resq-bin/index",
"sdks/rust/api/resq-clean",
"sdks/rust/api/resq-cli/commands",
"sdks/rust/api/resq-cli/commands/audit",
"sdks/rust/api/resq-cli/commands/commit",
"sdks/rust/api/resq-cli/commands/completions",
"sdks/rust/api/resq-cli/commands/copyright",
"sdks/rust/api/resq-cli/commands/dev",
"sdks/rust/api/resq-cli/commands/docs",
"sdks/rust/api/resq-cli/commands/explore",
"sdks/rust/api/resq-cli/commands/format",
"sdks/rust/api/resq-cli/commands/hook_templates",
"sdks/rust/api/resq-cli/commands/hooks",
"sdks/rust/api/resq-cli/commands/pre_commit",
"sdks/rust/api/resq-cli/commands/secrets",
"sdks/rust/api/resq-cli/commands/version",
"sdks/rust/api/resq-cli/gitignore",
"sdks/rust/api/resq-cli/index",
"sdks/rust/api/resq-cli/resq_cli",
"sdks/rust/api/resq-cli/utils",
"sdks/rust/api/resq-deploy",
"sdks/rust/api/resq-dsa/bloom",
"sdks/rust/api/resq-dsa/count_min",
"sdks/rust/api/resq-dsa/graph",
"sdks/rust/api/resq-dsa/heap",
"sdks/rust/api/resq-dsa/index",
"sdks/rust/api/resq-dsa/resq_dsa",
"sdks/rust/api/resq-dsa/trie",
"sdks/rust/api/resq-flame",
"sdks/rust/api/resq-health",
"sdks/rust/api/resq-logs",
"sdks/rust/api/resq-perf",
"sdks/rust/api/resq-tui/index",
"sdks/rust/api/resq-tui/resq_tui",
"sdks/rust/api/resq-tui/terminal"
{
"group": "resq-ai",
"pages": [
"sdks/rust/api/resq-ai",
"sdks/rust/api/resq-ai/config",
"sdks/rust/api/resq-ai/provider",
"sdks/rust/api/resq-ai/token"
]
},
{
"group": "resq-bin",
"pages": [
"sdks/rust/api/resq-bin",
"sdks/rust/api/resq-bin/analysis",
"sdks/rust/api/resq-bin/bin_explorer"
]
},
{
"group": "resq-cli",
"pages": [
"sdks/rust/api/resq-cli",
"sdks/rust/api/resq-cli/commands",
"sdks/rust/api/resq-cli/gitignore",
"sdks/rust/api/resq-cli/resq_cli",
"sdks/rust/api/resq-cli/utils",
{
"group": "commands",
"pages": [
"sdks/rust/api/resq-cli/commands/audit",
"sdks/rust/api/resq-cli/commands/commit",
"sdks/rust/api/resq-cli/commands/completions",
"sdks/rust/api/resq-cli/commands/copyright",
"sdks/rust/api/resq-cli/commands/dev",
"sdks/rust/api/resq-cli/commands/docs",
"sdks/rust/api/resq-cli/commands/explore",
"sdks/rust/api/resq-cli/commands/format",
"sdks/rust/api/resq-cli/commands/hook_templates",
"sdks/rust/api/resq-cli/commands/hooks",
"sdks/rust/api/resq-cli/commands/pre_commit",
"sdks/rust/api/resq-cli/commands/secrets",
"sdks/rust/api/resq-cli/commands/version"
]
}
]
},
{
"group": "resq-dsa",
"pages": [
"sdks/rust/api/resq-dsa",
"sdks/rust/api/resq-dsa/bloom",
"sdks/rust/api/resq-dsa/count_min",
"sdks/rust/api/resq-dsa/graph",
"sdks/rust/api/resq-dsa/heap",
"sdks/rust/api/resq-dsa/resq_dsa",
"sdks/rust/api/resq-dsa/trie"
]
},
{
"group": "resq-tui",
"pages": [
"sdks/rust/api/resq-tui",
"sdks/rust/api/resq-tui/resq_tui",
"sdks/rust/api/resq-tui/terminal"
]
}
]
},
{
Expand Down Expand Up @@ -2524,4 +2554,4 @@
"website": "https://resq.software"
}
}
}
}
Loading