Skip to content

Conversation

panteliselef
Copy link
Member

@panteliselef panteliselef commented Aug 27, 2025

Description

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Documentation

    • API docs now hide experimental content (and related examples) by default for clearer output.
    • Accessors (getters/setters) are rendered as a dedicated Properties table for improved clarity.
    • TypeDoc config updated to hide the "overrides" column in generated markdown tables.
    • Added snapshot testing guidance documenting patterns, best practices, and how to run/update snapshots.
  • Tests

    • Added a script to regenerate TypeDoc data and update snapshots.
  • Chores

    • Narrowed billing integration test targeting for more precise execution.

This reverts commit 659a1bb60c3a4cf18e3bad1b04c544e144b49a75.
This reverts commit a36bdf7df3c42a47829139af3da330d7369c5890.
This reverts commit 54c8c22b1e3841122392014b08b4fa16af6ecf6f.
Copy link

changeset-bot bot commented Aug 27, 2025

⚠️ No Changeset found

Latest commit: dea5e8e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented Aug 27, 2025

Walkthrough

Updates TypeDoc tooling: a non-functional ts-check comment tweak in the custom plugin, experimental-content filtering and accessor-aware group rendering in the custom theme, adds a typedoc test script and narrows an integration test app ID in package.json, hides overrides column in typedoc config, and adds snapshot-testing documentation.

Changes

Cohort / File(s) Summary of changes
TypeDoc plugin (non-functional)
./.typedoc/custom-plugin.mjs
Top-of-file // @ts-check comment expanded to clarify intent. No runtime or logic changes.
TypeDoc theme (rendering changes)
./.typedoc/custom-theme.mjs
Adds experimental-aware comment partial that hides @experimental content by default on Class/Interface pages (removes @experimental, strips @example/@see, trims leading newline before rendering). Modifies memberWithGroups to filter out non-user-facing groups (removes Methods, extracts and removes Accessors), calls superclass renderer with filtered groups, then restores originals. Renders an Accessors section as a Properties-style table when accessors exist, with per-accessor partial support. Internal rendering changes only; no public API changes.
TypeDoc config
typedoc.config.mjs
Adds hideOverrides: true to typedocPluginMarkdownOptions.tableColumnSettings to hide the overrides column in generated markdown tables.
Package scripts
package.json
Adds test:typedoc:update (pnpm typedoc:generate && cd ./.typedoc && vitest --u) and narrows test:integration:billing to E2E_APP_ID=withBilling.next.appRouter.
Testing docs
packages/clerk-js/src/core/resources/__tests__/README-snapshots.md
New README describing snapshot testing patterns for resource classes with Vitest: examples, best practices, snapshot updating and running instructions. Documentation only.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant NPM as package.json scripts
  participant TD as TypeDoc
  participant Theme as Custom Theme
  participant Part as Comment Partial
  participant MWG as memberWithGroups
  participant Plugin as Post-process Plugin
  participant Out as Docs

  Dev->>NPM: run test:typedoc:update
  NPM->>TD: typedoc:generate
  TD->>Theme: render reflections
  Theme->>Part: render comment partial
  Note right of Part #DDEBF7: If comment has @experimental\nand page kind is Class/Interface\nremove @experimental/@example/@see
  Part-->>Theme: comment HTML (experimental content removed)
  Theme->>MWG: render member groups
  alt owningReflection marked @experimental
    MWG-->>Theme: filter Methods, extract Accessors, render filtered groups
    Note right of Theme #FFF2CC: If Accessors exist\nrender Accessors as Properties table
  else
    MWG-->>Theme: render all groups normally
  end
  Theme-->>TD: rendered pages
  TD-->>Plugin: post-process MDX
  Note over Plugin #F3E8FF: plugin file ts-check comment changed\n(no logic changes)
  Plugin-->>Out: final docs
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Poem

I thump my paws on fresh release,
Experimental bits tucked out of sight,
Accessors lined up in tidy rows,
Snapshots kept snug through test-night,
Scripts hop ready — docs delight. 🥕🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch elef/remove-experimental-from-typedoc

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

vercel bot commented Aug 27, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
clerk-js-sandbox Ready Ready Preview Comment Aug 29, 2025 5:59pm

Copy link

pkg-pr-new bot commented Aug 27, 2025

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@6651

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@6651

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@6651

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@6651

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@6651

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@6651

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@6651

@clerk/clerk-expo

npm i https://pkg.pr.new/@clerk/clerk-expo@6651

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@6651

@clerk/express

npm i https://pkg.pr.new/@clerk/express@6651

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@6651

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@6651

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@6651

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@6651

@clerk/clerk-react

npm i https://pkg.pr.new/@clerk/clerk-react@6651

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@6651

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@6651

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@6651

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@6651

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@6651

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@6651

@clerk/types

npm i https://pkg.pr.new/@clerk/types@6651

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@6651

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@6651

commit: dea5e8e

Copy link
Contributor

@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: 3

🧹 Nitpick comments (7)
package.json (1)

55-55: Use Vitest’s canonical update flag.

Prefer -u (or --update) over --u for clarity and future-proofing.

Apply:

-    "test:typedoc:update": "pnpm typedoc:generate && cd ./.typedoc && vitest --u",
+    "test:typedoc:update": "pnpm typedoc:generate && cd ./.typedoc && vitest -u",
packages/clerk-js/src/core/resources/__tests__/README-snapshots.md (4)

72-73: Align snapshot update command with repo tooling (pnpm + Vitest).

Docs currently suggest npm test -- --update-snapshots. In this repo we use pnpm and Vitest; recommend pnpm test -- -u.

-5. **Update When Intentional**: When you intentionally change a resource's structure, update the snapshots using `npm test -- --update-snapshots`.
+5. **Update When Intentional**: When you intentionally change a resource's structure, update the snapshots using `pnpm test -- -u`.

77-85: Use pnpm in examples and the short update flag.

Keep CLI examples consistent with package manager and Vitest flags.

-# Run all resource tests
-npm test -- src/core/resources/__tests__/*.spec.ts
+# Run all resource tests
+pnpm test -- src/core/resources/__tests__/*.spec.ts

-# Run specific test file
-npm test -- src/core/resources/__tests__/Client.spec.ts
+# Run specific test file
+pnpm test -- src/core/resources/__tests__/Client.spec.ts

-# Update snapshots when structure changes intentionally
-npm test -- --update-snapshots
+# Update snapshots when structure changes intentionally
+pnpm test -- -u

37-43: Avoid as any in examples; prefer minimal types or Partial.

Using as any in docs encourages bypassing type safety. Suggest Partial<ResourceName> or explicit optional props.

-} as any); // Use 'as any' if TypeScript complains about null values
+} as Partial<ResourceName>); // Allow null/empty for snapshot variants without bypassing types

64-66: Add reminder to restore timers to prevent test bleed.

When using fake timers, always revert.

 1. **Use Fixed Dates**: Use `vi.useFakeTimers()` and `vi.setSystemTime()` to ensure consistent timestamps in snapshots.
+   Remember to call `vi.useRealTimers()` in `afterEach` to avoid leaking fake timers across tests.
.typedoc/custom-theme.mjs (2)

239-251: Simplify experimental group handling and clarify naming.

Early-return logic is fine; rename for clarity.

-        const experimentalGroups = originalGroups?.find(g =>
+        const experimentalGroups = originalGroups?.find(g =>
           g?.owningReflection?.comment?.modifierTags.has('@experimental'),
         );
 
-        if (experimentalGroups) {
-          const groupsWithoutMethods = originalGroups?.filter(g => g.title === 'Properties');
-
-          customizedModel.groups = groupsWithoutMethods;
+        if (experimentalGroups) {
+          const propertiesOnlyGroups = originalGroups?.filter(g => g.title === 'Properties');
+          customizedModel.groups = propertiesOnlyGroups;
           const nonAccessorOutput = superPartials.memberWithGroups(customizedModel, options);
           customizedModel.groups = originalGroups;
 
           return nonAccessorOutput;
         }

259-262: Remove unreachable duplicate check.

This if (experimentalGroups) path cannot be hit due to the earlier early return.

-        if (experimentalGroups) {
-          return nonAccessorOutput;
-        }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ee3c4a5 and 8c1cd5e.

📒 Files selected for processing (4)
  • .typedoc/custom-plugin.mjs (2 hunks)
  • .typedoc/custom-theme.mjs (2 hunks)
  • package.json (2 hunks)
  • packages/clerk-js/src/core/resources/__tests__/README-snapshots.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/clerk-js/src/core/resources/__tests__/README-snapshots.md
  • package.json
🪛 LanguageTool
packages/clerk-js/src/core/resources/__tests__/README-snapshots.md

[grammar] ~100-~100: There might be a mistake here.
Context: ...etermine if the change is intentional**: - If yes: Update the snapshot with `--upda...

(QB_NEW_EN)


[grammar] ~101-~101: There might be a mistake here.
Context: ...: - If yes: Update the snapshot with --update-snapshots - If no: Fix the code to maintain backward...

(QB_NEW_EN)

⏰ 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). (6)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (2)
package.json (1)

36-36: Confirm billing E2E app ID scope

Please verify whether it’s intentional to run your billing integration tests against only the withBilling.next.appRouter variant, since there are additional Billing presets defined. Narrowing from a wildcard to a single app ID will skip:

  • integration/presets/longRunningApps.ts (lines 45, 47, 72):
    • withBilling.next.appRouter
    • withBilling.vue.vite
    • withBilling.astro.node

  • All other @billing tests (e.g. pricing-table.test.ts using testAgainstRunningApps({ withEnv: [envs.withBilling] })) expect to exercise every “withBilling.*” scenario, not just the Next App Router variant.

If you intend to cover every Billing stack, consider updating the test script to use a wildcard (e.g. E2E_APP_ID=withBilling.*) or adding separate commands per variant. Otherwise, confirm that limiting to withBilling.next.appRouter matches your intended test surface.

.typedoc/custom-plugin.mjs (1)

1-1: Enabling // @ts-check is a good safety net.

Comment on lines 86 to 92
// Robustly remove the full Experimental section (including optional Example/code block)
// from the first "**`Experimental`**" until the next heading (## ...) or end of file.
// This covers variations in wording/whitespace and ensures the block is stripped.
{
pattern: /(?:^|\r?\n)\*\*`Experimental`\*\*[\s\S]*?(?=(?:\r?\n##\s)|$)/g,
replace: '',
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Experimental-section regex is too strict; may miss real output.

It requires backticks around Experimental and only looks for ## ; some outputs use no backticks or different heading levels. Make backticks optional and allow any level-2+ heading.

-    {
-      pattern: /(?:^|\r?\n)\*\*`Experimental`\*\*[\s\S]*?(?=(?:\r?\n##\s)|$)/g,
-      replace: '',
-    },
+    {
+      // Match **Experimental** or **`Experimental`**, until the next heading (##, ###, …) or EOF
+      pattern: /(?:^|\r?\n)\*\*`?Experimental`?\*\*[\s\S]*?(?=(?:\r?\n#{2,}\s)|$)/g,
+      replace: '',
+    },
📝 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
// Robustly remove the full Experimental section (including optional Example/code block)
// from the first "**`Experimental`**" until the next heading (## ...) or end of file.
// This covers variations in wording/whitespace and ensures the block is stripped.
{
pattern: /(?:^|\r?\n)\*\*`Experimental`\*\*[\s\S]*?(?=(?:\r?\n##\s)|$)/g,
replace: '',
},
// Robustly remove the full Experimental section (including optional Example/code block)
// from the first "**`Experimental`**" until the next heading (## ...) or end of file.
// This covers variations in wording/whitespace and ensures the block is stripped.
{
// Match **Experimental** or **`Experimental`**, until the next heading (##, ###, …) or EOF
pattern: /(?:^|\r?\n)\*\*`?Experimental`?\*\*[\s\S]*?(?=(?:\r?\n#{2,}\s)|$)/g,
replace: '',
},
🤖 Prompt for AI Agents
In .typedoc/custom-plugin.mjs around lines 86 to 92, the regex that strips the
Experimental section is too strict (it expects backticks and only "## "
headings); update the pattern to make backticks optional (and tolerate optional
bold markers) and change the lookahead to match any heading level 2 or higher
(e.g., #{2,}\s) or end-of-file; ensure the regex still uses global/multiline
semantics so it robustly removes the entire Experimental block across variants.

Comment on lines 93 to 98
// As a safeguard, remove any leftover Example section that specifically shows ClerkProvider clerkJsVersion snippet
{
pattern:
/(?:^|\r?\n)## Example\r?\n(?:\r?\n)?```tsx[\s\S]*?ClerkProvider\s+clerkJsVersion="[^"]*"[\s\S]*?```(?:\r?\n)?/g,
replace: '',
},
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Broaden Example-stripper to handle any code fence/lang and quote style.

Current pattern only matches ```tsx and double quotes. Generalize to avoid misses.

-    {
-      pattern:
-        /(?:^|\r?\n)## Example\r?\n(?:\r?\n)?```tsx[\s\S]*?ClerkProvider\s+clerkJsVersion="[^"]*"[\s\S]*?```(?:\r?\n)?/g,
-      replace: '',
-    },
+    {
+      pattern:
+        /(?:^|\r?\n)##\s+Example\r?\n(?:\r?\n)?```[a-zA-Z]*[\s\S]*?ClerkProvider\s+clerkJsVersion=(?:"[^"]*"|'[^']*')[\s\S]*?```(?:\r?\n)?/g,
+      replace: '',
+    },

Please add/update .typedoc Vitest fixtures to assert both patterns against realistic samples (backtick/no-backtick Experimental; Example blocks with ts/tsx/js and single/double quotes).


🏁 Script executed:

#!/bin/bash
set -e

echo "== Locating custom-plugin.mjs =="
PLUGIN_PATH=$(fd custom-plugin.mjs -t f)
echo "Found at: $PLUGIN_PATH"

echo "== Showing lines 80-120 from the plugin =="
sed -n '80,120p' "$PLUGIN_PATH"

echo
echo "== Searching for test/spec files referencing '## Example' =="
rg -n '##\s+Example' -g '*.{test,spec}.{js,ts,mjs}' || echo "No matches for '## Example' in test files"

echo
echo "== Searching for fixtures directories under .typedoc =="
fd fixtures .typedoc -t d || echo "No fixtures directory under .typedoc"

echo
echo "== Searching for clerkJsVersion usage in tests =="
rg -n 'clerkJsVersion' -g '*.{test,spec}.{js,ts,mjs}' || echo "No references to clerkJsVersion in test files"

Length of output: 317


🏁 Script executed:

#!/bin/bash
set -eu

echo "== Finding custom-plugin.mjs =="
PLUGIN=$(find . -type f -name custom-plugin.mjs | head -n 1 || true)
if [[ -z "$PLUGIN" ]]; then
  echo "custom-plugin.mjs not found"
  exit 1
fi
echo "Found plugin at: $PLUGIN"

echo
echo "== Displaying lines 80-120 from the plugin =="
sed -n '80,120p' "$PLUGIN" || echo "Unable to display plugin snippet"

echo
echo "== Listing files under .typedoc directory =="
if [[ -d .typedoc ]]; then
  find .typedoc -maxdepth 2 -type f
else
  echo ".typedoc directory not found"
fi

echo
echo "== Searching for test/spec files under .typedoc =="
find .typedoc -type f \( -name '*.test.*' -o -name '*.spec.*' \) || echo "No test/spec files under .typedoc"

echo
echo "== Searching for fixtures directory under .typedoc =="
find .typedoc -type d -name 'fixtures' || echo "No fixtures directory under .typedoc"

echo
echo "== Searching for 'clerkJsVersion' in .typedoc =="
grep -R "clerkJsVersion" .typedoc || echo "No clerkJsVersion references in .typedoc"

echo
echo "== Searching for '## Example' in .typedoc =="
grep -R "## Example" .typedoc || echo "No '## Example' headings in .typedoc"

Length of output: 3489


Broaden Example-Stripper Regex & Add Vitest Fixtures

To fully cover all code-fence languages and both quote styles, update the regex in .typedoc/custom-plugin.mjs and introduce Vitest fixtures/tests under .typedoc/fixtures and .typedoc/__tests__.

• In .typedoc/custom-plugin.mjs (around lines 93–98), replace the existing pattern with:

-    {
-      pattern:
-        /(?:^|\r?\n)## Example\r?\n(?:\r?\n)?```tsx[\s\S]*?ClerkProvider\s+clerkJsVersion="[^"]*"[\s\S]*?```(?:\r?\n)?/g,
-      replace: '',
-    },
+    {
+      pattern:
+        /(?:^|\r?\n)##\s+Example\r?\n(?:\r?\n)?```[a-zA-Z]*[\s\S]*?ClerkProvider\s+clerkJsVersion=(?:"[^"]*"|'[^']*')[\s\S]*?```(?:\r?\n)?/g,
+      replace: '',
+    },

• Create a fixtures directory under .typedoc and add realistic sample files, for example:

  • fixtures/example-tsx-double-quotes.md (tsx + `clerkJsVersion="v1.2.3"```)
  • fixtures/example-js-single-quotes.md (js + `clerkJsVersion='v4.5.6'```)
  • (Optionally) more variants with no-lang fences or other languages.

• In .typedoc/__tests__/custom-plugin.test.ts, write Vitest cases that:

  • Load each fixture, run getCatchAllReplacements(), and assert the transformed output no longer contains the ClerkProvider snippet.
  • Cover both the original double-quoted/tsx case and the new single-quoted/js case.

This ensures the plugin reliably strips all “Example” blocks showing ClerkProvider clerkJsVersion across languages and quote styles.

🤖 Prompt for AI Agents
In .typedoc/custom-plugin.mjs around lines 93–98, the current regex only matches
tsx code-fences with double quotes; update the pattern to
/(?:^|\r?\n)##\s+Example\r?\n(?:\r?\n)?```[a-zA-Z]*[\s\S]*?ClerkProvider\s+clerkJsVersion=(?:"[^"]*"|'[^']*')[\s\S]*?```(?:\r?\n)?/g
and keep replace:'' so it strips Example blocks for any fence language and both
quote styles; additionally add a .typedoc/fixtures directory with at least
fixtures/example-tsx-double-quotes.md (```tsx + clerkJsVersion="v1.2.3"```) and
fixtures/example-js-single-quotes.md (```js + clerkJsVersion='v4.5.6'```) and
create .typedoc/__tests__/custom-plugin.test.ts Vitest tests that load each
fixture, call getCatchAllReplacements(), and assert the output no longer
contains the ClerkProvider snippet (cover double-quoted tsx and single-quoted js
cases).

Comment on lines 49 to 69
/**
* This hides the "Experimental" section from the output (by default).
* @param {import('typedoc').Comment} model
* @param {{ headingLevel?: number; showSummary?: boolean; showTags?: boolean; showReturns?: boolean; isTableColumn?: boolean }} [options]
*/
comment: (model, options) => {
if (model?.modifierTags.has('@experimental')) {
const originalBlockTags = model.blockTags;
model.blockTags = model.blockTags.filter(tag => tag.name !== '@example');
const res = superPartials.comment(model, options);
model.blockTags = originalBlockTags;
return res;
}
return superPartials.comment(model, options);
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Guard against undefined blockTags when filtering @example.

model.blockTags can be undefined; filter defensively to avoid runtime errors.

       comment: (model, options) => {
         if (model?.modifierTags.has('@experimental')) {
-          const originalBlockTags = model.blockTags;
-          model.blockTags = model.blockTags.filter(tag => tag.name !== '@example');
+          const originalBlockTags = model.blockTags;
+          const safeBlockTags = model.blockTags ?? [];
+          model.blockTags = safeBlockTags.filter(tag => tag.name !== '@example');
           const res = superPartials.comment(model, options);
           model.blockTags = originalBlockTags;
           return res;
         }
         return superPartials.comment(model, options);
       },
📝 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
/**
* This hides the "Experimental" section from the output (by default).
* @param {import('typedoc').Comment} model
* @param {{ headingLevel?: number; showSummary?: boolean; showTags?: boolean; showReturns?: boolean; isTableColumn?: boolean }} [options]
*/
comment: (model, options) => {
if (model?.modifierTags.has('@experimental')) {
const originalBlockTags = model.blockTags;
model.blockTags = model.blockTags.filter(tag => tag.name !== '@example');
const res = superPartials.comment(model, options);
model.blockTags = originalBlockTags;
return res;
}
return superPartials.comment(model, options);
},
comment: (model, options) => {
if (model?.modifierTags.has('@experimental')) {
const originalBlockTags = model.blockTags;
const safeBlockTags = model.blockTags ?? [];
model.blockTags = safeBlockTags.filter(tag => tag.name !== '@example');
const res = superPartials.comment(model, options);
model.blockTags = originalBlockTags;
return res;
}
return superPartials.comment(model, options);
},
🤖 Prompt for AI Agents
In .typedoc/custom-theme.mjs around lines 49 to 63, model.blockTags may be
undefined causing a runtime error when calling .filter; capture
originalBlockTags as-is, then when filtering use a defensive check (e.g.,
replace model.blockTags with (Array.isArray(model.blockTags) ?
model.blockTags.filter(...) : [] ) or use nullish-coalescing with .filter only
when defined) and finally restore originalBlockTags (which may be undefined)
after calling superPartials.comment so behavior is preserved.

Copy link
Contributor

@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: 1

🧹 Nitpick comments (2)
.typedoc/custom-theme.mjs (2)

65-66: Fix ESLint: remove unused variable.

line is never used. The refactor above eliminates it by avoiding the destructure. If you keep the current structure, at minimum rename to _line or remove the destructure.


245-257: Handle missing “Properties” group; avoid rendering nothing.

If the class/interface is experimental but has no “Properties” group, this returns an empty section. Guard and fall back to default rendering (or decide on another group).

-        if (experimentalGroups) {
-          const groupsWithoutMethods = originalGroups?.filter(g => g.title === 'Properties');
-
-          customizedModel.groups = groupsWithoutMethods;
-          const nonAccessorOutput = superPartials.memberWithGroups(customizedModel, options);
-          customizedModel.groups = originalGroups;
-
-          return nonAccessorOutput;
-        }
+        if (experimentalGroups) {
+          const propertiesGroups = originalGroups?.filter(g => g.title === 'Properties') ?? [];
+          if (propertiesGroups.length === 0) {
+            // Nothing to filter to; render default groups instead.
+            return superPartials.memberWithGroups(customizedModel, options);
+          }
+          customizedModel.groups = propertiesGroups;
+          const nonAccessorOutput = superPartials.memberWithGroups(customizedModel, options);
+          customizedModel.groups = originalGroups;
+          return nonAccessorOutput;
+        }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8c1cd5e and def7a20.

📒 Files selected for processing (2)
  • .typedoc/custom-plugin.mjs (1 hunks)
  • .typedoc/custom-theme.mjs (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .typedoc/custom-plugin.mjs
🧰 Additional context used
🪛 ESLint
.typedoc/custom-theme.mjs

[error] 65-65: 'line' is assigned a value but never used. Allowed unused vars must match /^_/u.

(no-unused-vars)


[error] 65-65: 'line' is assigned a value but never used. Allowed unused vars must match /^_/u.

(@typescript-eslint/no-unused-vars)

⏰ 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). (26)
  • GitHub Check: Integration Tests (billing, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 14)
  • GitHub Check: Integration Tests (machine, chrome)
  • GitHub Check: Integration Tests (react-router, chrome)
  • GitHub Check: Integration Tests (nuxt, chrome)
  • GitHub Check: Integration Tests (expo-web, chrome)
  • GitHub Check: Integration Tests (nextjs, chrome, 15)
  • GitHub Check: Integration Tests (tanstack-react-router, chrome)
  • GitHub Check: Integration Tests (tanstack-react-start, chrome)
  • GitHub Check: Integration Tests (vue, chrome)
  • GitHub Check: Integration Tests (astro, chrome)
  • GitHub Check: Integration Tests (localhost, chrome)
  • GitHub Check: Integration Tests (elements, chrome)
  • GitHub Check: Integration Tests (sessions, chrome)
  • GitHub Check: Integration Tests (ap-flows, chrome)
  • GitHub Check: Integration Tests (generic, chrome)
  • GitHub Check: Integration Tests (quickstart, chrome)
  • GitHub Check: Integration Tests (express, chrome)
  • GitHub Check: Unit Tests (18, --filter=@clerk/astro --filter=@clerk/backend --filter=@clerk/express --filter=@c...
  • GitHub Check: Publish with pkg-pr-new
  • GitHub Check: Unit Tests (22, **)
  • GitHub Check: Static analysis
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan

Copy link
Contributor

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.typedoc/custom-theme.mjs (1)

426-434: Harden parsing of @unionReturnHeadings; avoid crashes on invalid JSON.

JSON.parse on user-authored tag content is brittle. Wrap in try/catch and default gracefully.

-                const content = this.helpers.getCommentParts(unionReturnHeadings.content);
-                const unionHeadings = JSON.parse(content);
+                let unionHeadings = [];
+                try {
+                  const content = this.helpers.getCommentParts(unionReturnHeadings.content);
+                  const parsed = JSON.parse(content);
+                  unionHeadings = Array.isArray(parsed) ? parsed : [];
+                } catch {
+                  unionHeadings = [];
+                }
@@
-                headings.push(unionHeadings[i]);
+                headings.push(unionHeadings[i] ?? `Variant ${i + 1}`);
♻️ Duplicate comments (1)
.typedoc/custom-theme.mjs (1)

49-68: Do not mutate Comment; clone (or locally shadow) and guard API calls.

Mutating model with removeModifier/removeTags can leak side effects into other partials. Also, hasModifier/removeTags/removeModifier may be undefined across TypeDoc versions; guard them and fall back to safe blockTags filtering.

Apply:

-      comment: (model, options) => {
-        if (
-          model.hasModifier('@experimental') &&
-          [ReflectionKind.Class, ReflectionKind.Interface].includes(this.page?.model?.kind)
-        ) {
-          model.removeModifier('@experimental');
-          model.removeTags('@example');
-          model.removeTags('@see');
-
-          const res = superPartials.comment(model, options);
-
-          return res.replace(/^\n+/, '');
-        }
-        return superPartials.comment(model, options);
-      },
+      comment: (model, options) => {
+        if (
+          model?.hasModifier?.('@experimental') &&
+          [ReflectionKind.Class, ReflectionKind.Interface].includes(this.page?.model?.kind)
+        ) {
+          // Avoid side effects: operate on a cloned/shadowed comment.
+          const temp =
+            typeof model.clone === 'function'
+              ? model.clone()
+              : (() => {
+                  const shallow = Object.assign(Object.create(Object.getPrototypeOf(model)), model);
+                  if (Array.isArray(shallow.blockTags)) shallow.blockTags = [...shallow.blockTags];
+                  if (shallow.modifierTags instanceof Set) shallow.modifierTags = new Set(shallow.modifierTags);
+                  return shallow;
+                })();
+          // Strip experimental + noisy sections with guards for older/newer TypeDoc APIs.
+          temp.removeModifier?.('@experimental');
+          if (typeof temp.removeTags === 'function') {
+            temp.removeTags('@example');
+            temp.removeTags('@see');
+          } else if (Array.isArray(temp.blockTags)) {
+            temp.blockTags = temp.blockTags.filter(t => !['@example', '@see'].includes(t.tag || t.name));
+          }
+          const res = superPartials.comment(temp, options);
+          return res.replace(/^\n+/, '');
+        }
+        return superPartials.comment(model, options);
+      },

To verify, run the TypeDoc snapshot tests for pages that render comments both before and after comment to ensure no tag leakage or missing content.

🧹 Nitpick comments (1)
.typedoc/custom-theme.mjs (1)

447-453: Union comment memoization key can collide across pages; include reflection IDs.

${model.name}-${decl.name} is not globally unique. Use stable reflection IDs to avoid cross-contamination.

-                    const id = `${model.name}-${decl.name}`;
+                    const pageId = this.page?.model?.id ?? 'p';
+                    const modelId = typeof model?.id === 'number' ? model.id : model?.name;
+                    const declId = typeof decl?.id === 'number' ? decl.id : decl?.name;
+                    const id = `${pageId}-${modelId}-${declId}`;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0c3d485 and dea5e8e.

📒 Files selected for processing (1)
  • .typedoc/custom-theme.mjs (2 hunks)
⏰ 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). (6)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan

Comment on lines 238 to 240
const customizedModel = model;
customizedModel.typeParameters = undefined;

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid mutating typeParameters; restore after rendering.

You unset typeParameters and never restore it, which may affect downstream partials that read the same model instance.

-        const customizedModel = model;
-        customizedModel.typeParameters = undefined;
+        const customizedModel = model;
+        const originalTypeParameters = customizedModel.typeParameters;
+        customizedModel.typeParameters = undefined;
@@
-        customizedModel.groups = originalGroups;
+        customizedModel.groups = originalGroups;
+        customizedModel.typeParameters = originalTypeParameters;

Also applies to: 254-255

🤖 Prompt for AI Agents
In .typedoc/custom-theme.mjs around lines 238-240 (and likewise lines 254-255),
the code mutates model.typeParameters and never restores it; instead create a
shallow copy of the model (or save the original typeParameters to a temp
variable) before clearing typeParameters, use the copy/temp for rendering, and
then restore the original model.typeParameters after rendering so downstream
partials see the original data.

Comment on lines +243 to +249
// When an interface extends another interface, typedoc will generate a "Methods" group
// We want to hide this group from being rendered
const groupsWithoutMethods = originalGroups?.filter(g => g.title !== 'Methods');

// Extract the Accessors group (if any) and prevent default rendering for it
const accessorsGroup = groupsWithoutMethods?.find(g => g.title === 'Accessors');
const groupsWithoutAccessors = groupsWithoutMethods?.filter(g => g.title !== 'Accessors');
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Hiding every “Methods” group is too broad; restrict to interfaces (extends case).

As written, you’ll also remove legitimate methods from classes. Limit the filter to interface pages only.

-        const groupsWithoutMethods = originalGroups?.filter(g => g.title !== 'Methods');
+        const isInterface = customizedModel?.kind === ReflectionKind.Interface;
+        const groupsWithoutMethods = isInterface
+          ? originalGroups?.filter(g => g.title !== 'Methods')
+          : originalGroups;

Build a sample class with methods in the docs to confirm the Methods section remains visible.


🏁 Script executed:

#!/bin/bash
# Locate ReflectionKind usage and import in custom-theme.mjs
grep -R "ReflectionKind" -n .typedoc/custom-theme.mjs || true
# Locate where customizedModel is defined or passed in
grep -R "customizedModel" -n .typedoc/custom-theme.mjs || true

Length of output: 1133


Restrict “Methods” filtering to interfaces only
Only omit the “Methods” group when customizedModel.kind === ReflectionKind.Interface; leave it intact for classes.

-        const groupsWithoutMethods = originalGroups?.filter(g => g.title !== 'Methods');
+        const isInterface = customizedModel.kind === ReflectionKind.Interface;
+        const groupsWithoutMethods = isInterface
+          ? originalGroups.filter(g => g.title !== 'Methods')
+          : originalGroups;

[matches .typedoc/custom-theme.mjs:243]

📝 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
// When an interface extends another interface, typedoc will generate a "Methods" group
// We want to hide this group from being rendered
const groupsWithoutMethods = originalGroups?.filter(g => g.title !== 'Methods');
// Extract the Accessors group (if any) and prevent default rendering for it
const accessorsGroup = groupsWithoutMethods?.find(g => g.title === 'Accessors');
const groupsWithoutAccessors = groupsWithoutMethods?.filter(g => g.title !== 'Accessors');
// When an interface extends another interface, typedoc will generate a "Methods" group
// We want to hide this group from being rendered
const isInterface = customizedModel.kind === ReflectionKind.Interface;
const groupsWithoutMethods = isInterface
? originalGroups.filter(g => g.title !== 'Methods')
: originalGroups;
// Extract the Accessors group (if any) and prevent default rendering for it
const accessorsGroup = groupsWithoutMethods?.find(g => g.title === 'Accessors');
const groupsWithoutAccessors = groupsWithoutMethods?.filter(g => g.title !== 'Accessors');
🤖 Prompt for AI Agents
In .typedoc/custom-theme.mjs around lines 243 to 249, the current code always
filters out the "Methods" group; change this to only filter when the model is an
interface by wrapping the "Methods" removal in a conditional that checks if
customizedModel.kind === ReflectionKind.Interface (ensure ReflectionKind is
imported/available in this module). Leave the "Accessors" extraction and
subsequent filtering unchanged so accessors are still handled the same way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants