Skip to content

Conversation

@ernestognw
Copy link
Member

@ernestognw ernestognw commented Dec 22, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Documentation now includes direct GitHub repository links for source code reference.
    • Improved documentation layout with structured card-based design for contracts and components.
  • Documentation

    • Migrated documentation format to support enhanced rendering and better visual presentation.
    • Updated link formatting throughout documentation for consistency and improved readability.
    • Reorganized directory-level documentation with streamlined navigation structure.
  • Chores

    • Simplified documentation build workflow and configuration.
    • Updated build system configuration for documentation generation.

✏️ Tip: You can customize this high-level summary in your review settings.

stevedylandev and others added 30 commits October 31, 2025 00:28
- Updated all README.adoc to README.mdx
- Moved `templates-md` and the contents to just `templates`
- Updated `hardhat.config.js` to use `docs/config`
- Updated `helpers.js` to account for adoc change
- Updated `docs/config.js` to use mdx
Updated the following legacy patterns:
- `https://url[Link Text]` -> `[Link Text](https://url)`
- `WARNING: | IMPORTANT: | CAUTION: | IMPORTANT:` -> `<Callout
type=warn"></Callout>`
- `NOTE: | TIP:` -> <Callout></Callout>
- Delimitters such as `====` -> `####` or removed if no header text
present
Co-authored-by: James Toussaint <33313130+james-toussaint@users.noreply.github.com>
james-toussaint and others added 11 commits December 16, 2025 10:21
Co-authored-by: James Toussaint <33313130+james-toussaint@users.noreply.github.com>
Co-authored-by: James Toussaint <33313130+james-toussaint@users.noreply.github.com>
Co-authored-by: James Toussaint <33313130+james-toussaint@users.noreply.github.com>
Co-authored-by: Ernesto García <ernestognw@gmail.com>
@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

Walkthrough

This change migrates documentation infrastructure from AsciiDoc to MDX format, refactors documentation templates to support structured HTML card layouts with processed NatSpec content, updates Solidity contract doc comments with Markdown-style links, and introduces a new shell script-based build orchestration that synchronizes with an external OpenZeppelin docs repository.

Changes

Cohort / File(s) Summary
Documentation Format Migration
contracts/access/README.*, contracts/account/README.*, contracts/crosschain/README.mdx, contracts/governance/README.*, contracts/interfaces/README.mdx, contracts/proxy/README.*, contracts/token/README.*, contracts/utils/README.*, contracts/utils/cryptography/README.*
Removed legacy .adoc documentation files and added corresponding .mdx files with front matter, callouts, and structured sections for contract directories.
Contract Doc Comment Link Formatting
contracts/token/ERC20/extensions/ERC20Restricted.sol, contracts/token/ERC20/extensions/ERC20uRWA.sol, contracts/token/ERC20/extensions/ERC4626Fees.sol, contracts/account/paymaster/PaymasterCore.sol, contracts/account/paymaster/PaymasterERC20.sol, contracts/account/modules/ERC7579DelayedExecutor.sol, contracts/utils/cryptography/DKIMRegistry.sol, contracts/utils/cryptography/ZKEmailUtils.sol, contracts/utils/cryptography/signers/SignerZKEmail.sol, contracts/utils/structs/EnumerableMapExtended.sol, contracts/utils/structs/EnumerableSetExtended.sol
Updated documentation comments to convert inline URLs to Markdown-style links and adjusted section header formatting (e.g., ==== to ####). No functional code changes.
Documentation Template Infrastructure
docs/templates/contract.hbs, docs/templates/page.hbs, docs/templates/helpers.js, docs/templates/properties.js
Refactored Handlebars templates and helpers: converted simple doc rendering to structured HTML card layouts with processed NatSpec, added link resolution and callout processing, updated README target lookup from .adoc to .mdx, and added helper functions for ID generation and content processing.
Documentation Page Removals
docs/index.md, docs/modules/ROOT/nav.adoc, docs/modules/ROOT/pages/index.adoc, docs/modules/ROOT/pages/account-modules.adoc, docs/modules/ROOT/pages/crosschain.adoc, docs/modules/ROOT/pages/utilities.adoc
Removed legacy AsciiDoc pages and Solidity API documentation that are now generated dynamically via the new template system.
Build and CI Orchestration
.github/workflows/docs.yml, scripts/oz-docs.sh, scripts/prepare-docs.sh
Refactored GitHub Actions workflow to trigger external workflow via gh workflow run, replaced multi-step docs building with unified shell script that manages OpenZeppelin docs repo sync, watches for changes, and handles build/dev modes.
Build Configuration and Scripts
package.json, netlify.toml, docs/config.js, scripts/generate/templates/EnumerableMapExtended.js, scripts/generate/templates/EnumerableSetExtended.js, scripts/gen-nav.js
Updated npm scripts (docs, docs:watch use new oz-docs), added chokidar-cli dependency, changed Netlify build command and publish directory, updated docs config to use .mdx extension, removed legacy nav generation script.
Project Configuration
.gitignore, docs/antora.yml
Added docs/oz-docs to gitignore, removed Antora configuration block.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • docs/templates/helpers.js: High-density logic with new link resolution caching, MDX content processing, callout normalization, and reference handling. Requires careful validation of link path generation and content transformation.
  • docs/templates/contract.hbs: Significant structural refactoring from simple doc rendering to complex nested HTML card layouts with conditional blocks and per-item processing. Verify template correctness and NatSpec rendering pipeline.
  • scripts/oz-docs.sh: New shell script with watch mode, sync logic, and repository management. Validate error handling and control flow across init, prepare, sync, and watch modes.
  • docs/templates/properties.js: Changes to nullable property access and new fullname function logic; ensure guard clauses prevent runtime errors.

Possibly related PRs

  • PR #215: Modifies the same cryptography documentation files (contracts/utils/cryptography/*) and DKIMRegistry.sol docblock with similar link formatting updates.

Suggested reviewers

  • james-toussaint
  • frangio

Poem

🐰 From .adoc to .mdx, docs take flight,
With Markdown links shining so bright!
Cards and callouts in templates align,
Build scripts sync up—the pipeline's divine!
A rabbit hops through, all docs redesigned. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: converting documentation templates from AsciiDoc (.adoc) to Markdown (.mdx) format throughout the project.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch stevedylandev/master

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (6)
contracts/utils/cryptography/README.mdx (1)

12-12: Consider standardizing "onchain" vs "on-chain".

The term "onchain" is flagged by the linter. While both "onchain" and "on-chain" are acceptable in blockchain contexts, consider standardizing on one form across the documentation for consistency.

scripts/prepare-docs.sh (1)

5-6: Remove unused ROOT variable.

The ROOT variable is set but never used in the script. Since the script uses relative paths and doesn't reference $ROOT, this variable can be safely removed.

🔎 Proposed fix
 cd "$(dirname "$0")/.."
-ROOT="$(pwd)"
-
docs/templates/properties.js (1)

20-34: Consider handling multiple trailing dashes.

The current logic only removes a single trailing -. If slug() produces consecutive dashes (e.g., from type[][]type----), multiple trailing dashes could remain. However, looking at the slug implementation which replaces \W with -, this seems unlikely in practice for type strings.

🔎 Optional fix using regex to handle all trailing dashes
-  if (res.charAt(res.length - 1) === '-') {
-    return res.slice(0, -1);
-  }
-  return res;
+  return res.replace(/-+$/, '');
scripts/oz-docs.sh (2)

14-30: Consider adding error handling for network failures during clone/fetch.

The git clone and git fetch operations could fail due to network issues. While set -e will cause the script to exit, a more informative error message might help users troubleshoot.

🔎 Optional: Add explicit error handling
 init() {
   if [ -d "$OZ_DOCS/.git" ]; then
     echo "[oz-docs] updating cached docs repo..."
     cd "$OZ_DOCS"
-    git fetch origin main
-    git reset --hard origin/main
+    git fetch origin main || { echo "error: failed to fetch docs repo" >&2; exit 1; }
+    git reset --hard origin/main || { echo "error: failed to reset docs repo" >&2; exit 1; }
     git clean -fd
   else

65-78: Background watcher process is not cleaned up on script exit.

The chokidar process is started in the background (&) but there's no trap to kill it when the script exits (e.g., via Ctrl+C). This could leave orphaned processes.

🔎 Add cleanup trap for background processes
+# Cleanup function for background processes
+cleanup() {
+  jobs -p | xargs -r kill 2>/dev/null || true
+}
+trap cleanup EXIT INT TERM
+
 if [ "${WATCH:-false}" = "true" ]; then
   if [ ! -x "$CHOKIDAR_BIN" ]; then
     echo "error: chokidar-cli not found (run: npm i -D chokidar-cli)" >&2
     exit 1
   fi
docs/templates/helpers.js (1)

240-298: Complex regex chain is fragile and hard to maintain.

The processCallouts function has ~15 regex replacements handling various admonition formats. This is prone to breaking when new formats are encountered and difficult to debug.

Consider extracting patterns into a configuration array for easier maintenance:

const CALLOUT_PATTERNS = [
  { pattern: /^\[(NOTE|TIP)\]\s*\n====\s*\n([\s\S]*?)\n====$/gm, type: '' },
  { pattern: /^\[(IMPORTANT|WARNING|CAUTION)\]\s*\n====\s*\n([\s\S]*?)\n====$/gm, type: 'warn' },
  // ... etc
];
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ebbee9 and a2e09ac.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (48)
  • .github/workflows/docs.yml
  • .gitignore
  • contracts/access/README.adoc
  • contracts/access/README.mdx
  • contracts/account/README.adoc
  • contracts/account/README.mdx
  • contracts/account/modules/ERC7579DelayedExecutor.sol
  • contracts/account/paymaster/PaymasterCore.sol
  • contracts/account/paymaster/PaymasterERC20.sol
  • contracts/crosschain/README.mdx
  • contracts/governance/README.adoc
  • contracts/governance/README.mdx
  • contracts/interfaces/README.mdx
  • contracts/proxy/README.adoc
  • contracts/proxy/README.mdx
  • contracts/token/ERC20/extensions/ERC20Restricted.sol
  • contracts/token/ERC20/extensions/ERC20uRWA.sol
  • contracts/token/ERC20/extensions/ERC4626Fees.sol
  • contracts/token/README.adoc
  • contracts/token/README.mdx
  • contracts/utils/README.adoc
  • contracts/utils/README.mdx
  • contracts/utils/cryptography/DKIMRegistry.sol
  • contracts/utils/cryptography/README.adoc
  • contracts/utils/cryptography/README.mdx
  • contracts/utils/cryptography/ZKEmailUtils.sol
  • contracts/utils/cryptography/signers/SignerZKEmail.sol
  • contracts/utils/structs/EnumerableMapExtended.sol
  • contracts/utils/structs/EnumerableSetExtended.sol
  • docs/antora.yml
  • docs/config.js
  • docs/index.md
  • docs/modules/ROOT/nav.adoc
  • docs/modules/ROOT/pages/account-modules.adoc
  • docs/modules/ROOT/pages/crosschain.adoc
  • docs/modules/ROOT/pages/index.adoc
  • docs/modules/ROOT/pages/utilities.adoc
  • docs/templates/contract.hbs
  • docs/templates/helpers.js
  • docs/templates/page.hbs
  • docs/templates/properties.js
  • netlify.toml
  • package.json
  • scripts/gen-nav.js
  • scripts/generate/templates/EnumerableMapExtended.js
  • scripts/generate/templates/EnumerableSetExtended.js
  • scripts/oz-docs.sh
  • scripts/prepare-docs.sh
💤 Files with no reviewable changes (15)
  • contracts/utils/README.adoc
  • docs/modules/ROOT/pages/utilities.adoc
  • docs/modules/ROOT/pages/index.adoc
  • scripts/gen-nav.js
  • docs/modules/ROOT/pages/crosschain.adoc
  • contracts/proxy/README.adoc
  • contracts/utils/cryptography/README.adoc
  • docs/antora.yml
  • docs/index.md
  • contracts/access/README.adoc
  • docs/modules/ROOT/nav.adoc
  • contracts/governance/README.adoc
  • contracts/token/README.adoc
  • contracts/account/README.adoc
  • docs/modules/ROOT/pages/account-modules.adoc
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-04T15:44:43.674Z
Learnt from: aviggiano
Repo: OpenZeppelin/openzeppelin-community-contracts PR: 214
File: contracts/governance/TimelockControllerEnumerable.sol:103-115
Timestamp: 2025-09-04T15:44:43.674Z
Learning: The base TimelockController contract intentionally preserves executed operations in the `_timestamps` mapping with `_DONE_TIMESTAMP` value to allow confirmation of executed status. This is by design, not a storage leak, and extensions like TimelockControllerEnumerable should follow the same pattern.

Applied to files:

  • contracts/governance/README.mdx
🧬 Code graph analysis (2)
docs/templates/properties.js (1)
docs/templates/helpers.js (1)
  • slug (64-69)
docs/templates/helpers.js (1)
docs/config.js (1)
  • fs (2-2)
🪛 LanguageTool
contracts/token/README.mdx

[grammar] ~9-~9: Ensure spelling is correct
Context: ...ens (e.g ERC-20, ERC-721, ERC-1155) and derivated ERCs (e.g. ERC-4626, ERC-1363). * {OnT...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

contracts/interfaces/README.mdx

[grammar] ~11-~11: Use a hyphen to join words.
Context: ... These are useful to interact with third party contracts that implement them. * ...

(QB_NEW_EN_HYPHEN)

contracts/utils/cryptography/README.mdx

[grammar] ~12-~12: Ensure spelling is correct
Context: ...s.ethereum.org/EIPS/eip-7969) to enable onchain verification of DomainKeys Identified M...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 Shellcheck (0.11.0)
scripts/prepare-docs.sh

[warning] 6-6: ROOT appears unused. Verify use (or export if used externally).

(SC2034)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Redirect rules - community-contracts
  • GitHub Check: Header rules - community-contracts
  • GitHub Check: Pages changed - community-contracts
  • GitHub Check: tests-foundry
  • GitHub Check: coverage
  • GitHub Check: slither
  • GitHub Check: tests
🔇 Additional comments (36)
contracts/token/ERC20/extensions/ERC20Restricted.sol (1)

9-9: Documentation link format aligns with Markdown migration objectives.

The EIP-7943 reference is properly formatted as a Markdown link and maintains accuracy. This change fits the PR's documentation infrastructure migration without affecting contract functionality or behavior.

contracts/account/paymaster/PaymasterERC20.sol (1)

175-175: Verify the Markdown heading level is intentional.

The change converts AsciiDoc syntax ==== (h2 heading) to Markdown syntax #### (h4 heading), which is a two-level drop in the semantic heading hierarchy. Confirm this heading level aligns with your documentation structure, especially if other headings in the codebase follow a different pattern.

contracts/token/ERC20/extensions/ERC20uRWA.sol (1)

12-12: Documentation link formatting aligned with PR objectives.

The NatSpec comment was correctly updated to use Markdown-style inline link syntax, improving consistency with the documentation migration effort. The link syntax and target URL are both valid.

contracts/account/paymaster/PaymasterCore.sol (1)

129-129: Verify markdown syntax in NatSpec comments is supported by the docs pipeline.

The markdown link syntax [access control](url) in the NatSpec comment (line 129) departs from standard Solidity documentation conventions. While this aligns with the PR's migration to MDX, confirm that your documentation processing pipeline correctly handles and renders markdown syntax within NatSpec comments. Standard Solidity documentation viewers may not interpret markdown correctly without special preprocessing.

To verify this is handled correctly, you can:

  • Check the documentation build pipeline configuration for markdown/MDX processing
  • Verify the URL is accessible: https://docs.openzeppelin.com/contracts/5.x/access-control
  • Ensure similar changes across the PR follow the same pattern for consistency
contracts/access/README.mdx (1)

11-11: Clarify the {AccessManagerLight} reference syntax.

The syntax {AccessManagerLight} is non-standard for Markdown/MDX. Confirm whether this is intentional custom processor syntax or if it should use standard MDX component or markdown link syntax (e.g., <AccessManagerLight /> or [AccessManagerLight](path)).

contracts/token/ERC20/extensions/ERC4626Fees.sol (1)

10-10: LGTM! Improved documentation formatting.

The conversion from inline URL to Markdown link format improves readability and follows documentation best practices.

.gitignore (1)

40-40: LGTM! Appropriate addition of generated docs to .gitignore.

Adding docs/oz-docs to the ignore list is correct since this directory contains generated documentation artifacts that should not be committed to version control.

scripts/generate/templates/EnumerableSetExtended.js (1)

13-13: LGTM! Consistent Markdown link formatting.

The documentation comments have been properly updated to use Markdown-style links, which will render correctly in the new MDX-based documentation system.

Also applies to: 40-40

contracts/utils/cryptography/DKIMRegistry.sol (1)

7-7: LGTM! Improved documentation formatting.

The ERC-7969 reference has been properly formatted as a Markdown link, consistent with the documentation migration across the repository.

contracts/utils/cryptography/ZKEmailUtils.sol (1)

13-13: LGTM! Consistent Markdown link formatting for external documentation.

All ZKEmail documentation references have been properly converted to Markdown link format, improving readability and consistency with the new documentation system.

Also applies to: 21-21, 23-23, 25-25

scripts/generate/templates/EnumerableMapExtended.js (1)

12-12: LGTM! Consistent Markdown link formatting.

The documentation comments have been updated with proper Markdown-style links, consistent with the changes in EnumerableSetExtended.js and the broader documentation migration.

Also applies to: 41-41

contracts/utils/structs/EnumerableSetExtended.sol (1)

12-12: LGTM! Documentation link formatting improved.

The conversion from inline URL references to proper Markdown link syntax improves readability and follows documentation best practices.

Also applies to: 39-39

contracts/crosschain/README.mdx (1)

1-25: Documentation structure looks good.

The MDX file follows a clear structure with proper front matter, callout, and content sections. The crosschain concepts are well-documented.

contracts/utils/cryptography/signers/SignerZKEmail.sol (1)

12-12: LGTM! Documentation link formatting improved.

The conversion to proper Markdown link syntax enhances documentation readability and consistency across the codebase.

Also applies to: 61-61, 79-79, 87-87

contracts/proxy/README.mdx (1)

1-15: LGTM! Clear proxy documentation.

The MDX file provides clear documentation about proxy patterns and the HybridProxy implementation. The structure is consistent with other documentation files in this PR.

contracts/governance/README.mdx (1)

1-15: LGTM! Governance documentation is clear.

The MDX file properly documents the governance extensions, particularly the TimelockControllerEnumerable. The structure is consistent with other documentation files in this PR.

contracts/account/modules/ERC7579DelayedExecutor.sol (1)

12-12: LGTM! Section headers migrated to Markdown format.

The conversion from AsciiDoc-style section markers to Markdown headers aligns with the broader documentation migration to MDX format.

Also applies to: 27-27, 35-35

contracts/utils/structs/EnumerableMapExtended.sol (1)

11-11: LGTM! Documentation link formatting improved.

The conversion to proper Markdown link syntax for both the Solidity documentation reference and the GitHub issue improves consistency and readability.

Also applies to: 40-40

docs/templates/contract.hbs (1)

1-158: LGTM: Well-structured card-based layout.

The template successfully introduces a modern card-based documentation layout with proper anchoring, GitHub links, and processed NatSpec content. The use of React/JSX syntax (className, style attributes) aligns well with MDX output format.

contracts/utils/README.mdx (1)

1-22: LGTM: Clean and consistent MDX documentation.

The utilities README follows the same structure and conventions as the other MDX documentation files in this PR.

docs/templates/page.hbs (1)

1-13: LGTM: Clean template structure with proper front matter.

The page template correctly introduces YAML front matter for MDX compatibility and delegates item rendering to the contract partial. The structure is simple and maintainable.

.github/workflows/docs.yml (2)

12-18: Verify the DOCS_REPO_TOKEN secret exists.

The workflow now relies on the DOCS_REPO_TOKEN secret to trigger the external workflow. Ensure this secret is configured in the repository settings with appropriate permissions to trigger workflows in the OpenZeppelin/docs repository.


1-18: LGTM: Workflow simplification improves maintainability.

The change from a multi-step in-repo docs generation to delegating to an external workflow in the OpenZeppelin/docs repository is a good architectural decision. This centralizes docs generation logic and reduces duplication. The addition of workflow_dispatch for manual triggers is also helpful for testing.

scripts/prepare-docs.sh (1)

17-33: LGTM: Clean refactoring into prepare() function.

Wrapping the preparation logic in a prepare() function improves code organization and makes the script easier to understand and maintain. The function encapsulates all the doc preparation steps logically.

package.json (2)

14-18: LGTM!

The script reorganization cleanly delegates to oz-docs.sh for both regular builds and watch mode. The WATCH=true environment variable pattern is a clean approach for mode switching.


51-51: The version specification "chokidar-cli": "^3.0.0" is appropriate. The latest available version is 3.0.0 on the npm registry, and no critical issues have been reported. The semver range correctly pins to the latest major.minor version while allowing patch updates.

docs/templates/properties.js (3)

36-45: LGTM!

Returning an empty array for non-contracts (interfaces, libraries) is appropriate defensive behavior that prevents downstream errors when consumers iterate over inheritance.


47-57: LGTM!

The inheritance && guards properly handle cases where inheritance is undefined or empty, preventing runtime errors when these helpers are called on non-contract items.


74-82: LGTM!

Early return for missing inheritance prevents errors and aligns with the defensive pattern used in the has-* functions.

scripts/oz-docs.sh (2)

1-11: LGTM!

Good use of set -euo pipefail for strict error handling. The path setup and variable definitions are clear and well-organized.


39-45: LGTM!

The sync function properly creates directories before rsync and uses --delete to ensure the destination mirrors the source exactly.

docs/templates/helpers.js (5)

153-158: Regex may match unintended standalone words.

The pattern ^([A-Z][a-zA-Z0-9]+)$ matches any PascalCase word on its own line, not just contract names. This could unintentionally convert words like "Overview" or "Introduction" to links if they happen to match a contract name.

Consider whether this is the intended behavior. If contract names should be explicit, this pattern might be too broad.


71-108: LGTM!

The WeakMap caching with per-page Map keys is a good pattern for memoizing link generation without memory leaks. The cache properly invalidates when items reference changes.


198-213: LGTM!

The HTML entity decoding and URL format normalization are correctly implemented. The regex for converting AsciiDoc-style links (url[text]) to Markdown ([text](url)) is appropriate.


300-317: LGTM!

The title and description helpers properly derive display text from page IDs with appropriate formatting.


28-44: simple-id helper is not used anywhere in the codebase.

The functionNameCounts global state and reset-function-counts exist but are unused. The anchor property is generated dynamically in properties.js, not via the simple-id helper. While reset-function-counts is called at line 1 of contract.hbs, it has no practical effect. Consider removing these unused helpers to reduce code complexity.

Likely an incorrect or invalid review comment.

Comment on lines +13 to +15
## AccessManager

AccessManagerLight
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix incomplete section structure.

The "## AccessManager" section header is followed immediately by "AccessManagerLight" with no content. Either:

  1. Add content under the AccessManager section, or
  2. Rename to "## AccessManagerLight" with appropriate content, or
  3. Restructure with proper subsections

The file appears to be incomplete or malformed.

🤖 Prompt for AI Agents
In contracts/access/README.mdx around lines 13 to 15, the "## AccessManager"
header is followed directly by the bare text "AccessManagerLight", leaving the
section incomplete or malformed; either add explanatory content and examples
under "## AccessManager" about its purpose and relationship to
AccessManagerLight, or rename the header to "## AccessManagerLight" and provide
appropriate content (description, usage, API/props or links), or split into
proper subsections (e.g., "## AccessManager" with "### AccessManagerLight") so
the README is well structured and each header has matching content.


This directory includes contracts to build accounts for ERC-4337. These include:

* {ERC7579Executor}: An executor module that enables executing calls from accounts where the it’s installed.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix grammatical error: remove extra "the".

The phrase "where the it's installed" contains an extra "the" before "it's".

🔎 Proposed fix
-* {ERC7579Executor}: An executor module that enables executing calls from accounts where the it's installed.
+* {ERC7579Executor}: An executor module that enables executing calls from accounts where it's installed.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* {ERC7579Executor}: An executor module that enables executing calls from accounts where the it’s installed.
* {ERC7579Executor}: An executor module that enables executing calls from accounts where it's installed.
🤖 Prompt for AI Agents
In contracts/account/README.mdx around line 11, the phrase "where the it’s
installed" contains an extra "the"; remove the extra word so the sentence reads
"where it's installed" (i.e., replace "where the it’s installed" with "where
it’s installed").


## List of standardized interfaces

These interfaces are available as `.sol` files. These are useful to interact with third party contracts that implement them.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider hyphenating "third-party" when used as an adjective.

The phrase "third party contracts" should be "third-party contracts" for grammatically correct usage when the term modifies a noun.

🔎 Suggested fix
-These are useful to interact with third party contracts that implement them.
+These are useful to interact with third-party contracts that implement them.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
These interfaces are available as `.sol` files. These are useful to interact with third party contracts that implement them.
These interfaces are available as `.sol` files. These are useful to interact with third-party contracts that implement them.
🧰 Tools
🪛 LanguageTool

[grammar] ~11-~11: Use a hyphen to join words.
Context: ... These are useful to interact with third party contracts that implement them. * ...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
In contracts/interfaces/README.mdx at line 11, change the phrase "third party
contracts" to the hyphenated form "third-party contracts" so the compound
adjective correctly modifies "contracts"; update the line accordingly.

This document is better viewed at https://docs.openzeppelin.com/community-contracts/token
</Callout>

Set of extensions and utilities for tokens (e.g ERC-20, ERC-721, ERC-1155) and derivated ERCs (e.g. ERC-4626, ERC-1363).
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix spelling error: "derivated" should be "derived".

The word "derivated" is not standard English. Use "derived" instead.

🔎 Proposed fix
-Set of extensions and utilities for tokens (e.g ERC-20, ERC-721, ERC-1155) and derivated ERCs (e.g. ERC-4626, ERC-1363).
+Set of extensions and utilities for tokens (e.g ERC-20, ERC-721, ERC-1155) and derived ERCs (e.g. ERC-4626, ERC-1363).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Set of extensions and utilities for tokens (e.g ERC-20, ERC-721, ERC-1155) and derivated ERCs (e.g. ERC-4626, ERC-1363).
Set of extensions and utilities for tokens (e.g ERC-20, ERC-721, ERC-1155) and derived ERCs (e.g. ERC-4626, ERC-1363).
🧰 Tools
🪛 LanguageTool

[grammar] ~9-~9: Ensure spelling is correct
Context: ...ens (e.g ERC-20, ERC-721, ERC-1155) and derivated ERCs (e.g. ERC-4626, ERC-1363). * {OnT...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
In contracts/token/README.mdx around line 9, change the misspelled word
"derivated" to the correct word "derived" so the sentence reads "...and derived
ERCs (e.g. ERC-4626, ERC-1363)." Update the file accordingly and run a quick
spell-check to ensure no other instances of the same typo remain.

templates: 'docs/templates',
exclude: ['mocks'],
pageExtension: '.adoc',
pageExtension: '.mdx',
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Examine the docs/config.js file and repository structure

echo "=== Checking docs/config.js file ==="
if [ -f "docs/config.js" ]; then
  cat -n docs/config.js
else
  echo "docs/config.js not found - searching for config files in docs/"
  fd -e js . docs/ | head -20
fi

echo -e "\n=== Repository structure overview ==="
ls -la | head -20

echo -e "\n=== Checking for .adoc files in entire repository ==="
fd -e adoc . | head -30

echo -e "\n=== Checking for .mdx files in entire repository ==="
fd -e mdx . | head -30

echo -e "\n=== Checking for .adoc references in JS files ==="
rg "\.adoc" --type=js -g '!node_modules' -g '!package-lock.json' | head -20

Repository: OpenZeppelin/openzeppelin-community-contracts

Length of output: 2751


Configuration is correct but remove stale AsciiDoc files to complete the migration. The pageExtension: '.mdx' setting is properly configured for solidity-docgen. However, three .adoc files remain and should be deleted:

  • contracts/crosschain/README.adoc
  • contracts/interfaces/README.adoc
  • docs/modules/ROOT/pages/paymasters.adoc

These are duplicates of successfully migrated .mdx files (except paymasters.adoc which has no .mdx equivalent). Clean up these remnants to complete the MDX migration across the repository.

🤖 Prompt for AI Agents
In docs/config.js at line 9, the pageExtension is correctly set to '.mdx' but
there are stale AsciiDoc files left; delete the three files
contracts/crosschain/README.adoc, contracts/interfaces/README.adoc, and
docs/modules/ROOT/pages/paymasters.adoc from the repository, and update or
remove any references/links to them (or replace with the corresponding .mdx
where applicable) so the MDX migration is complete.

[.hljs-theme-light.nopadding]
```solidity
import "@openzeppelin/community-{{__item_context.file.absolutePath}}";
import "@openzeppelin/{{__item_context.file.absolutePath}}";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the contract.hbs template file
if [ -f "docs/templates/contract.hbs" ]; then
  echo "=== Contract template content ==="
  cat -n docs/templates/contract.hbs | head -30
fi

# Search for other template files
echo -e "\n=== Looking for other templates ==="
find docs/templates -name "*.hbs" -type f 2>/dev/null | head -10

# Check package.json name
echo -e "\n=== Package name ==="
if [ -f "package.json" ]; then
  cat package.json | grep -A 1 '"name"'
fi

Repository: OpenZeppelin/openzeppelin-community-contracts

Length of output: 1748


Add missing package name to import statement.

The import path is missing the "community-contracts" package name. It should be @openzeppelin/community-contracts/{{__item_context.file.absolutePath}} to match the actual package name and reflect the correct import users should use.

🤖 Prompt for AI Agents
In docs/templates/contract.hbs around line 14, the import path is missing the
package name; update the import to include the "community-contracts" package
segment so it reads the full package path
(@openzeppelin/community-contracts/{{__item_context.file.absolutePath}})
ensuring generated imports reference the correct package.

Comment on lines +110 to +142
function generateLinkPath(pagePath, currentPagePath, anchor) {
if (
currentPagePath &&
(pagePath === currentPagePath || pagePath.split('/').pop() === currentPagePath.split('/').pop())
) {
return `#${anchor}`;
}

if (currentPagePath) {
const currentParts = currentPagePath.split('/');
const targetParts = pagePath.split('/');

// Find common base
let i = 0;
while (i < currentParts.length && i < targetParts.length && currentParts[i] === targetParts[i]) {
i++;
}

const upLevels = Math.max(0, currentParts.length - 1 - i);
const downPath = targetParts.slice(i);

if (upLevels === 0 && downPath.length === 1) {
return `${PATH_PREFIX}${downPath[0]}#${anchor}`;
} else if (upLevels === 0) {
return `${PATH_PREFIX}${downPath.join('/')}#${anchor}`;
} else {
const relativePath = downPath.join('/');
return `${PATH_PREFIX}${relativePath}#${anchor}`;
}
}

return `${PATH_PREFIX}${pagePath}#${anchor}`;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Path comparison may produce incorrect results for similar path endings.

Line 113 compares only the last path segment (split('/').pop()), which could incorrectly match utils/token and extensions/token as the same page, generating anchor-only links when full paths are needed.

🔎 Suggested fix: require exact path match
   if (
     currentPagePath &&
-    (pagePath === currentPagePath || pagePath.split('/').pop() === currentPagePath.split('/').pop())
+    pagePath === currentPagePath
   ) {
     return `#${anchor}`;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function generateLinkPath(pagePath, currentPagePath, anchor) {
if (
currentPagePath &&
(pagePath === currentPagePath || pagePath.split('/').pop() === currentPagePath.split('/').pop())
) {
return `#${anchor}`;
}
if (currentPagePath) {
const currentParts = currentPagePath.split('/');
const targetParts = pagePath.split('/');
// Find common base
let i = 0;
while (i < currentParts.length && i < targetParts.length && currentParts[i] === targetParts[i]) {
i++;
}
const upLevels = Math.max(0, currentParts.length - 1 - i);
const downPath = targetParts.slice(i);
if (upLevels === 0 && downPath.length === 1) {
return `${PATH_PREFIX}${downPath[0]}#${anchor}`;
} else if (upLevels === 0) {
return `${PATH_PREFIX}${downPath.join('/')}#${anchor}`;
} else {
const relativePath = downPath.join('/');
return `${PATH_PREFIX}${relativePath}#${anchor}`;
}
}
return `${PATH_PREFIX}${pagePath}#${anchor}`;
}
function generateLinkPath(pagePath, currentPagePath, anchor) {
if (
currentPagePath &&
pagePath === currentPagePath
) {
return `#${anchor}`;
}
if (currentPagePath) {
const currentParts = currentPagePath.split('/');
const targetParts = pagePath.split('/');
// Find common base
let i = 0;
while (i < currentParts.length && i < targetParts.length && currentParts[i] === targetParts[i]) {
i++;
}
const upLevels = Math.max(0, currentParts.length - 1 - i);
const downPath = targetParts.slice(i);
if (upLevels === 0 && downPath.length === 1) {
return `${PATH_PREFIX}${downPath[0]}#${anchor}`;
} else if (upLevels === 0) {
return `${PATH_PREFIX}${downPath.join('/')}#${anchor}`;
} else {
const relativePath = downPath.join('/');
return `${PATH_PREFIX}${relativePath}#${anchor}`;
}
}
return `${PATH_PREFIX}${pagePath}#${anchor}`;
}
🤖 Prompt for AI Agents
In docs/templates/helpers.js around lines 110 to 142, the current comparison
treats pages with the same final segment as identical
(pagePath.split('/').pop()), which incorrectly collapses distinct paths like
utils/token and extensions/token into anchor-only links; update the logic to
require an exact path match (normalize and compare full paths, e.g., strip
trailing slashes or index filenames if your routing uses them) and remove the
last-segment equality check so only true identical page paths return `#anchor`,
otherwise build a full path as before.

Comment on lines +226 to +229
// Ensure relative image paths start with /
.replace(/!\[([^\]]*)\]\(([^/)][^)]*\.(png|jpg|jpeg|gif|svg|webp))\)/g, '![$1](/$2)')
// Remove any title headers (they're in frontmatter now)
.replace(/^#+\s+.+$/m, '')
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Regex removes all top-level headers, not just title headers.

Line 229 (/^#+\s+.+$/m) removes the first header it finds, but the comment says "title headers." If a README has a title header already removed by frontmatter, this could remove meaningful content headers.

🔎 Suggested fix: only remove h1 headers
-      // Remove any title headers (they're in frontmatter now)
-      .replace(/^#+\s+.+$/m, '')
+      // Remove any h1 title headers (they're in frontmatter now)
+      .replace(/^#\s+.+$/m, '')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Ensure relative image paths start with /
.replace(/!\[([^\]]*)\]\(([^/)][^)]*\.(png|jpg|jpeg|gif|svg|webp))\)/g, '![$1](/$2)')
// Remove any title headers (they're in frontmatter now)
.replace(/^#+\s+.+$/m, '')
// Ensure relative image paths start with /
.replace(/!\[([^\]]*)\]\(([^/)][^)]*\.(png|jpg|jpeg|gif|svg|webp))\)/g, '![$1](/$2)')
// Remove any h1 title headers (they're in frontmatter now)
.replace(/^#\s+.+$/m, '')
🤖 Prompt for AI Agents
In docs/templates/helpers.js around lines 226 to 229, the current regex
.replace(/^#+\s+.+$/m, '') removes any header level (h1-h6) whereas we only want
to strip title headers; change the pattern to target only h1 headers (e.g. use a
regex matching lines that start with exactly one '#' followed by space) so only
top-level title headers are removed, keeping other meaningful section headers
intact.

[build]
command = "npm run docs"
publish = "build/site"
command = "pnpm run docs"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for the docs script in package.json and pnpm configuration

# Check if docs script exists
echo "=== Checking for 'docs' script in package.json ==="
jq -r '.scripts.docs // "NOT FOUND"' package.json 2>/dev/null || echo "package.json not found or not valid JSON"

# Check for pnpm-specific configuration
echo -e "\n=== Checking for pnpm configuration ==="
if [ -f "pnpm-lock.yaml" ]; then
  echo "pnpm-lock.yaml exists"
else
  echo "pnpm-lock.yaml NOT FOUND"
fi

if [ -f ".npmrc" ]; then
  echo ".npmrc exists with contents:"
  cat .npmrc
else
  echo ".npmrc NOT FOUND"
fi

# Check if netlify.toml specifies Node version or build image
echo -e "\n=== Checking netlify.toml for build settings ==="
cat netlify.toml

Repository: OpenZeppelin/openzeppelin-community-contracts

Length of output: 351


Add pnpm-lock.yaml or configure pnpm in package.json to enable Netlify pnpm support.

Netlify supports pnpm for Node.js 16.9.0 and later and automatically runs pnpm install when a pnpm-lock.yaml file is present. Your repository uses pnpm run docs in netlify.toml but lacks a pnpm-lock.yaml file. Without it, Netlify will default to npm for dependency installation, causing the build command to fail with "pnpm: command not found."

To fix this, either:

  • Commit the pnpm-lock.yaml file to the repository, or
  • Add "packageManager": "pnpm@VERSION" to package.json to signal pnpm usage via Corepack
🤖 Prompt for AI Agents
In netlify.toml around line 2, the build command uses "pnpm run docs" but the
repo lacks pnpm configuration so Netlify will default to npm and fail; fix by
either committing your generated pnpm-lock.yaml into the repository so Netlify
detects and uses pnpm, or add a "packageManager": "pnpm@<version>" entry to
package.json (use the pnpm version you develop with) to enable pnpm via
Corepack; choose one of these fixes and ensure the lockfile or package.json
change is committed before redeploy.

command = "npm run docs"
publish = "build/site"
command = "pnpm run docs"
publish = "docs/oz-docs/out"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify that the build process creates the expected output directory

# Check if there's a script that generates docs/oz-docs/out
echo "=== Checking package.json scripts for oz-docs ==="
jq -r '.scripts | to_entries[] | select(.key | contains("oz") or contains("docs")) | "\(.key): \(.value)"' package.json 2>/dev/null || echo "No package.json or jq unavailable"

# Check if there are any scripts in the scripts directory related to oz-docs
echo -e "\n=== Checking for oz-docs related scripts ==="
fd -t f "oz-docs" scripts/ 2>/dev/null || echo "No oz-docs scripts found"

# Check if docs/oz-docs directory exists
echo -e "\n=== Checking for docs/oz-docs directory ==="
if [ -d "docs/oz-docs" ]; then
    echo "docs/oz-docs directory exists"
    ls -la docs/oz-docs/ 2>/dev/null | head -20
else
    echo "docs/oz-docs directory does not exist"
fi

# Look for antora.yml or antora-playbook files
echo -e "\n=== Looking for Antora configuration files ==="
find . -maxdepth 3 -name "*antora*.yml" -o -name "*antora*.yaml" 2>/dev/null | head -20

# Check package.json for docs-related dependencies
echo -e "\n=== Checking for docs dependencies in package.json ==="
jq -r '.devDependencies | keys[] | select(contains("antora") or contains("docs"))' package.json 2>/dev/null || echo "No relevant dependencies found"

Repository: OpenZeppelin/openzeppelin-community-contracts

Length of output: 514


🏁 Script executed:

#!/bin/bash
cat scripts/oz-docs.sh

Repository: OpenZeppelin/openzeppelin-community-contracts

Length of output: 1965


🏁 Script executed:

#!/bin/bash
# Check the OpenZeppelin docs repository configuration for output directory
# Since oz-docs clones the docs repo, check what build output it would generate

echo "=== Checking if docs/oz-docs exists and what's inside ==="
if [ -d "docs/oz-docs" ]; then
  echo "docs/oz-docs directory exists"
  ls -la docs/oz-docs/ 2>/dev/null | grep -E "^\." | head -5
  # Check for antora config
  find docs/oz-docs -maxdepth 2 -name "*antora*" -o -name "package.json" 2>/dev/null | head
else
  echo "docs/oz-docs does not exist (expected - it's cloned during build)"
fi

echo -e "\n=== Checking netlify.toml for current configuration ==="
cat netlify.toml 2>/dev/null || echo "netlify.toml not found"

Repository: OpenZeppelin/openzeppelin-community-contracts

Length of output: 332


Correct the publish directory path to match the actual build output.

The build process generates output at docs/oz-docs/build/site (following Antora's default output directory), not docs/oz-docs/out. Update netlify.toml to use publish = "docs/oz-docs/build/site" or verify that the OpenZeppelin/docs repository has a custom antora configuration that outputs to an out directory. Without this correction, Netlify will fail to find the publish directory during deployment.

🤖 Prompt for AI Agents
In netlify.toml around line 3, the publish path is incorrect—Netlify is pointed
to docs/oz-docs/out but the site is actually built to docs/oz-docs/build/site;
update the publish setting to publish = "docs/oz-docs/build/site" (or, if the
repo intentionally outputs to out, adjust the Antora/build config to emit into
docs/oz-docs/out) so Netlify can find the build output during deployment.

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.

5 participants