Skip to content

fix: update docgen templates and automate API reference generation#140

Merged
ernestognw merged 22 commits into
mainfrom
fix/docgen-template-fixes
May 7, 2026
Merged

fix: update docgen templates and automate API reference generation#140
ernestognw merged 22 commits into
mainfrom
fix/docgen-template-fixes

Conversation

@stevep0z

@stevep0z stevep0z commented Apr 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fix docgen template helpers to resolve cross-standard contamination in API reference pages
  • Add template injection to generate-api-docs.js so the docs monorepo controls template quality
  • Add receiver workflows for openzeppelin-contracts and confidential-contracts
  • Add link validation step to all receiver workflows
  • Regenerate API reference for contracts 5.x, community-contracts, and confidential-contracts

Details

Template fixes (docgen/templates-md/helpers.js)

The previous helpers.js used fuzzy matching for natspec references, which caused cross-standard contamination. For example, the ERC20 constructor description referenced Governor.name and IERC6909Metadata.symbol instead of ERC20.name and ERC20.symbol.

Fixes include:

  • Strict reference matching with same-page preference
  • Absolute paths for cross-page links using API_DOCS_PATH
  • Multi-line callout handling (NOTE/WARNING blocks spanning multiple lines)
  • Bare < escaping in natspec to prevent MDX parse errors
  • Antora xref pattern conversion to markdown links
  • AsciiDoc heading conversion and orphaned delimiter cleanup

Collapsible inherited functions (docgen/templates-md/contract.hbs)

Inherited function/event/error listings in TOC sections are now wrapped in collapsible toggles. The contract's own items are visible by default; inherited items are accessible but not overwhelming. Empty toggles are filtered out.

Template injection (scripts/generate-api-docs.js)

The script now injects canonical MDX templates from docgen/templates-md/ into the cloned source repo before running docgen. This makes the docs monorepo the single source of truth for templates. Source repos do not need MDX templates committed.

The script also supports a --pre-generated flag for non-Solidity repos that generate MDX through their own tooling.

Receiver workflows

New workflows for openzeppelin-contracts (versioned, tag-based) and confidential-contracts (non-versioned, tag-based). Link validation step added to all receiver workflows including the existing community-contracts workflow.

Test plan

  • Run pnpm run check (0 errors)
  • Run pnpm run build (clean)
  • Visual inspection of API reference pages
  • After merge: manually trigger each receiver workflow to verify PR creation
  • Verify ERC20 page references only ERC20 contracts (no cross-contamination)
  • Verify collapsible toggles render and expand/collapse correctly
  • Verify GitHub source links point to correct repos and versions

stevep0z added 9 commits April 2, 2026 10:22
…t fixes

- Remove fuzzy reference matching that caused cross-standard contamination
  (e.g., ERC20 constructor referencing Governor.name, IERC6909Metadata.symbol)
- Add same-page preference so {name} on an ERC20 page resolves to ERC20.name
- Use absolute paths for cross-page links via API_DOCS_PATH
- Fix multi-line callout handling (NOTE: blocks spanning multiple lines)
- Escape bare < in natspec (e.g., < 0x80) to prevent MDX parse errors
- Convert Antora xref patterns to markdown links
- Convert AsciiDoc headings (====) to markdown (####)
- Clean up orphaned block delimiters
- Strip /index from links for Fumadocs compatibility
Regenerated from openzeppelin-contracts (master) and
openzeppelin-community-contracts (master) using updated docgen templates.

- All cross-page links use absolute paths
- No cross-standard contamination in reference resolution
- No legacy AsciiDoc patterns in output
- 0 link validation errors
Wrap inherited function/event/error listings in <details>/<summary>
toggles so the contract's own items are prominent and inherited items
are accessible but not overwhelming.

Only renders toggles for inherited contracts that have items for that
section (no empty toggles).

Also regenerates API reference output with updated template.
The script now injects canonical MDX templates from docgen/templates-md/
into the cloned source repo before running docgen. This means source
repos don't need to have MDX templates committed — the docs monorepo
is the single source of truth.

- Copies templates-md/ and config-md.js into cloned repo
- Customizes API_DOCS_PATH, GitHub link, and import path per source repo
- Patches hardhat config to use config-md
- Overwrites config.js so prepare-docs.sh scripts still work
- Handles local paths, broken symlinks, both .js and .ts hardhat configs
- Adds --skip-template-inject flag for repos that already have MDX templates
Regenerated via generate-api-docs.js with template injection for:
- openzeppelin-contracts (master) -> content/contracts/5.x/api/
- openzeppelin-community-contracts (master) -> content/community-contracts/api/
- openzeppelin-confidential-contracts (master) -> content/confidential-contracts/api/

All repos: 0 link errors, clean build.
New GitHub Actions receiver workflows for API doc generation:
- generate-api-docs-contracts.yml: versioned paths (5.x/api), tag-based
- generate-api-docs-confidential-contracts.yml: non-versioned (api/), tag-based

Both include link validation step before PR creation.
Adds postinstall + lint:links step before PR creation to catch
broken links in generated docs before they're merged.
Prevents temp directories from showing in source control if a
generate-api-docs.js run is interrupted before cleanup.
For repos using Move, Rust, Cairo, or other languages that generate
MDX through their own tooling, the script can now skip template
injection and docgen entirely and just copy pre-generated MDX files.

Usage: node generate-api-docs.js --repo <url> --api-output <dir> --pre-generated <path>

This keeps the workflow generator-agnostic: Solidity repos use the
default injection mode, other repos use --pre-generated.
@stevep0z stevep0z self-assigned this Apr 5, 2026
@netlify

netlify Bot commented Apr 5, 2026

Copy link
Copy Markdown

Deploy Preview for openzeppelin-docs-v2 ready!

Name Link
🔨 Latest commit 80a979a
🔍 Latest deploy log https://app.netlify.com/projects/openzeppelin-docs-v2/deploys/69d1c1339df29f0009309642
😎 Deploy Preview https://deploy-preview-140--openzeppelin-docs-v2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Comment thread .github/workflows/generate-api-docs-confidential-contracts.yml Fixed
Comment thread .github/workflows/generate-api-docs-contracts.yml Fixed
stevep0z added 2 commits April 4, 2026 20:41
Replace the old manual template-copy instructions with documentation
for the template injection approach and automated GitHub workflow.
Covers Solidity repos, non-Solidity repos (--pre-generated flag),
canonical template locations, and versioning strategy.
- Use execFileSync for git clone to prevent command injection from
  CLI arguments (array args instead of shell string interpolation)
- Add explicit permissions block to all receiver workflows to limit
  GITHUB_TOKEN scope to contents:write and pull-requests:write
Comment thread docgen/templates-md/helpers.js Outdated
Comment thread docgen/templates-md/helpers.js Outdated
Comment thread scripts/generate-api-docs.js
Comment thread scripts/generate-api-docs.js Outdated
Comment thread .github/workflows/generate-api-docs-contracts.yml
Comment thread .github/workflows/generate-api-docs-confidential-contracts.yml Outdated
Comment thread .github/workflows/generate-api-docs-contracts.yml Outdated
Comment thread .github/workflows/generate-api-docs-contracts.yml Outdated
Comment thread content/contracts/5.x/api/token/ERC20.mdx Outdated
@netlify

netlify Bot commented May 6, 2026

Copy link
Copy Markdown

Deploy Preview for openzeppelin-docs-v2 ready!

Name Link
🔨 Latest commit f7e6b4f
🔍 Latest deploy log https://app.netlify.com/projects/openzeppelin-docs-v2/deploys/69fd09daaa1363000811b320
😎 Deploy Preview https://deploy-preview-140--openzeppelin-docs-v2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ernestognw ernestognw force-pushed the fix/docgen-template-fixes branch from 14021c9 to a2a4132 Compare May 6, 2026 21:16
@ernestognw

ernestognw commented May 6, 2026

Copy link
Copy Markdown
Member

Update — review comments addressed + scope additions

I went through all the review threads and resolved them with file/function references for each fix (helpers.js strict ref-matching + same-page preference, multi-line callout regex, heading regex \s+[ \t]+, injectTemplates simplification, workflow git add narrowing, ::error + exit 1 on PR-create failure). The workflow-parameterization comment is deferred to a follow-up.

While at it, the pipeline grew a couple of capabilities beyond the original review scope:

convert-adoc.js: hard fixes + ESM port

The script was effectively dead — require() in a "type": "module" package, so it errored at the first import. Ported to ESM (import { promises as fs } from "node:fs"; etc.). Two correctness fixes uncovered while wiring it in:

  • Frontmatter quoting: titles like ERC-7540: Asynchronous Tokenized Vaults were emitted unquoted (title: ERC-7540: ...), breaking YAML parsing. Now wraps via JSON.stringify(title).
  • Bare <digit escaping: AsciiDoc content like if you deposit <1 share blew up MDX prerendering. Added a code-block-aware pass that converts bare < followed by digit/space-word to &lt;, mirroring what helpers.js already does for natspec — but only outside \...`and ``` ```...``` ``` blocks so inline code like ``<4.6 to >=4.6` `` stays intact.

generate-api-docs.js: new --guides-output <dir> flag

After the API ref is copied, if --guides-output is set the script runs convert-adoc.js against the cloned repo's docs/modules/ROOT/pages/ and copies the resulting MDX into the section directory. Skipped silently if the source repo has no ROOT/pages/. Recursive .mdx-only copy preserves nested layout if the source uses subdirectories.

Receiver workflows: changelog + section dir

All three receivers (contracts, confidential-contracts, community-contracts) now:

  1. Expose a section-dir output in the "Determine output directory" step (the parent of api/ — versioned for contracts, non-versioned for the other two).
  2. Pass --guides-output ${{ steps.config.outputs.section-dir }} to generate-api-docs.js so guide MDX lands alongside api/.
  3. Run a new "Setup changelog-from-release" + "Update changelog" pair after API generation, invoking scripts/generate-changelog.js against ${{ env.SOURCE_REPO }} and the section dir. The auto-PR therefore picks up changelog.mdx updates in the same diff.

Defaults stay at the latest stable refs (v5.6.1, v0.4.0, main) so manual workflow_dispatch runs pick the right snapshot.

Regenerated content

All three sources were regenerated end-to-end against the proper refs (was previously master across the board):

  • openzeppelin-contractsv5.6.1
  • openzeppelin-confidential-contractsv0.4.0
  • openzeppelin-community-contractsmaster (no release tags by design)

Both API references and converted guide MDX are included. changelog.mdx files will refresh on the next workflow run (CI installs changelog-from-release; local runs need it pre-installed).

Known follow-ups

  • Workflow parameterization: the three receivers are now structurally identical apart from env vars — easier to factor out once this lands.
  • Source-side AsciiDoc curation drift: the auto-conversion produces faithful output but some previously hand-curated MDX has small divergences (cross-repo API ref paths, anchor underscore-vs-dash, relative-vs-absolute xrefs). Per offline discussion these are best fixed in the source .adoc so the next regen produces clean output — not patched in the docs repo.

- convert-adoc.js: same-module xrefs use absolute /<route>/<page> instead of
  ./<page>; cross-module index.adoc collapses to section root (no /index
  suffix). Both fix link-validator failures from index.mdx pages.
- Re-run generate-api-docs.js for contracts (v5.6.1), community-contracts
  (master), confidential-contracts (v0.4.0).
- accounts.mdx: bridge two xrefs that v5.6.1's source has malformed
  (api:account#X / api:interfaces#X). The fix is in solidity master so this
  override drops away naturally with v5.7.
- upgradeable.mdx: drop the openzeppelin::upgrades TIP that v5.6.1 carries;
  removed in solidity master.
- wizard.mdx, accounts.mdx: <oz-wizard> -> <OZWizard /> JSX component.
@ernestognw ernestognw marked this pull request as ready for review May 7, 2026 21:58

@ernestognw ernestognw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's merge this, so that we can update the docs by manually running the CI

@ernestognw ernestognw merged commit 196507b into main May 7, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants