Skip to content

feat(rust-docs): render real rustdoc API via cargo-doc-md#62

Merged
WomB0ComB0 merged 1 commit intomainfrom
feat/rust-real-api-docs
May 10, 2026
Merged

feat(rust-docs): render real rustdoc API via cargo-doc-md#62
WomB0ComB0 merged 1 commit intomainfrom
feat/rust-real-api-docs

Conversation

@WomB0ComB0
Copy link
Copy Markdown
Member

Symptom

Each Rust SDK page in the docs is just "name + version + embedded README + link to docs.rs". Users expected the actual API surface — modules, structs, traits, methods with doc comments and examples — like what `cargo doc` produces at `https://resq-software.github.io/crates/resq_dsa/index.html\`.

Fix

Use cargo-doc-md to convert rustdoc JSON output into Markdown that Mintlify can render. JSON output is nightly-only, so the workflow installs both stable + nightly toolchains.

Hybrid pipeline:

Crate type Source Output
Library (`lib.rs` exists) cargo-doc-md `/index.md` (landing) + per-module siblings (`resq_dsa/bloom.md`, etc.)
Binary-only (TUIs: `resq-clean`, `-deploy`, `-flame`, `-health`, `-logs`, `-perf`) README stub `.md` (single file)

The version banner injects after the H1 of each landing page so both shapes carry the same metadata strip. The splice already handles dir-with-landing (#61) and flat-file (#49) forms naturally.

Sample output

`resq_dsa/bloom.md`:

```md
resq_dsa > bloom

Module: bloom

Contents

Structs

  • `BloomFilter` - A space-efficient probabilistic set membership data structure.

resq_dsa::bloom::BloomFilter

Struct

A space-efficient probabilistic set membership data structure.

Methods:

  • `fn new(capacity: usize, error_rate: f64) -> Self` - Creates a new Bloom filter…
    ```

Test plan

  • Verified locally: cargo-doc-md emits structured per-module markdown for resq-ai, resq-bin, resq-cli, resq-dsa, resq-tui (the 5 lib crates)
  • Binary-only crates fall through to README stub
  • After merge: sync to crates via `automation/sync-templates.sh rust`, dispatch workflow, verify auto-PR contains real type/function refs

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.
@github-actions github-actions Bot added the area:content MDX/MD documentation content label May 10, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

Warning

Rate limit exceeded

@WomB0ComB0 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 27 minutes and 13 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c5dcf088-d2a6-4a96-a9ba-ec4d0c26a732

📥 Commits

Reviewing files that changed from the base of the PR and between 834aceb and 6f5e921.

📒 Files selected for processing (1)
  • automation/source-repo-templates/api-docs.rust.yml
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rust-real-api-docs

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request enhances the Rust API documentation workflow by integrating cargo-doc-md to generate rich API references for library crates while maintaining README stubs for binary-only crates. The changes include installing the necessary nightly toolchain, running the documentation generator, and updating the indexing logic to handle both directory-based rich docs and standalone markdown stubs. Feedback from the review suggests pinning the cargo-doc-md version for build determinism and improving the robustness of the regex used to identify Markdown headers.

# cargo registry.
run: |
rustup toolchain install nightly --profile minimal --no-self-update
cargo install cargo-doc-md --locked
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

Running cargo install without a pinned version can lead to non-deterministic builds. Consider pinning the version and using actions/cache to improve efficiency. Additionally, ensure the workflow's concurrency is configured with cancel-in-progress: true to prevent race conditions. When configuring the documentation generator, prefer explicit project lists over automated discovery and include the relative path to the package directory in source code links for correct monorepo resolution.

cargo install cargo-doc-md --locked --version 0.1.4
References
  1. When configuring source code links in documentation generators for monorepos, the base URL must include the relative path to the package directory to ensure 'View source' links resolve correctly to the file locations.
  2. Prefer explicit project lists over automated discovery (e.g., via grep) in CI workflows if the repository structure contains duplicate project configurations or if manual oversight of the public API surface is necessary.
  3. For documentation synchronization workflows that force-push to the same branch, set cancel-in-progress: true to prevent race conditions from concurrent runs.

landing = dest / "index.md"
if landing.is_file():
text = landing.read_text(encoding="utf-8")
h1 = re.match(r"(# [^\n]+\n+)", text)
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 use of re.match is fragile; re.search with re.MULTILINE is more robust for finding the H1 header. Furthermore, when processing Markdown/MDX files to escape curly braces for JSX compatibility, ensure the logic ignores content within inline code spans (backticks) to prevent breaking code snippets.

h1 = re.search(r"^#\s+[^\n]+\n+", text, re.M)
References
  1. When processing Markdown/MDX files to escape curly braces for JSX compatibility, ensure the logic ignores content within inline code spans (backticks) to prevent breaking code snippets.

@WomB0ComB0 WomB0ComB0 merged commit cc78942 into main May 10, 2026
13 checks passed
@WomB0ComB0 WomB0ComB0 deleted the feat/rust-real-api-docs branch May 10, 2026 08:34
WomB0ComB0 added a commit that referenced this pull request May 10, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:content MDX/MD documentation content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants