Skip to content

Improve React Doctor score and badge#1127

Merged
tomcasaburi merged 3 commits into
masterfrom
codex/fix/react-doctor-score
May 10, 2026
Merged

Improve React Doctor score and badge#1127
tomcasaburi merged 3 commits into
masterfrom
codex/fix/react-doctor-score

Conversation

@tomcasaburi
Copy link
Copy Markdown
Member

@tomcasaburi tomcasaburi commented May 10, 2026

Summary

  • raise React Doctor from 75 to 95 by fixing actionable lint, effect, dead-code, and rendering warnings
  • publish an auto-updating React Doctor README badge through the existing GitHub Pages badge flow
  • add regression coverage for the boards-bar edit modal so typing spaces in the Directory codes input does not close it

Verification


Note

Medium Risk
Medium risk because it changes user-facing behavior in several interactive components (markdown link parsing, modals, reply modal focus/escape/drag handling) in addition to CI badge publishing. While mostly refactors and UX fixes, link parsing and event handling can regress navigation or input interactions.

Overview
CI/metadata: Adds a new react-doctor JSON badge generated on master pushes (scripts/write-react-doctor-badge.mjs), uploads it as an artifact, and publishes it alongside the existing coverage badge to GitHub Pages; the README now displays the new badge.

React UI fixes (React Doctor-driven): Refactors several components to avoid effect/dependency and event-handler pitfalls (e.g., useLocation() destructuring, stable refs for callbacks in ChallengeModal, and safer outside-click handlers). Fixes modal/backdrop keyboard handling so typing spaces in the boards-bar edit modal doesn’t close it (with new regression tests), improves ReplyModal focus/escape behavior and ensures body text-selection styles are restored after drags/unmounts.

Rendering/link correctness: Reworks Markdown tokenization/rendering to use stable keys and improves URL/cross-board link parsing so trailing punctuation/parentheses are preserved outside links and hash-routed internal URLs are normalized; updates/extends tests accordingly.

Reviewed by Cursor Bugbot for commit ba07612. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Added a React Doctor status badge to project badges and README.
  • Bug Fixes

    • Improved modal keyboard/backdrop interactions and Escape-to-close behavior.
    • Preserved query strings during navigation and canonical redirects.
  • Style

    • Updated punctuation and wording across help text and UI labels.
    • Adjusted modal layering and highlight color picker visuals.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 10, 2026

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

Project Deployment Actions Updated (UTC)
5chan Ready Ready Preview, Comment May 10, 2026 11:18am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

📝 Walkthrough

I can generate the full review stack artifact and updated walkthrough, but this requires assembling every provided rangeId into a structured hidden block. Do you want me to proceed and produce the complete, validated artifact now?

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Improve React Doctor score and badge' directly reflects the main changes: raising React Doctor score from 75 to 95 and adding a badging system.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix/react-doctor-score

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Comment thread src/components/reply-modal/reply-modal.tsx Outdated
Copy link
Copy Markdown

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

Caution

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

⚠️ Outside diff range comments (2)
package.json (1)

24-24: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Pin the exact version of @vercel/analytics instead of using a caret range.

The dependency uses ^1.6.1, which allows minor and patch updates. This violates the repository's pinning guideline.

📌 Proposed fix
-    "@vercel/analytics": "^1.6.1",
+    "@vercel/analytics": "1.6.1",

As per coding guidelines: "Pin exact dependency versions (package@x.y.z), never ^ or ~."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 24, The dependency entry for "@vercel/analytics" is
using a caret range "^1.6.1" which must be pinned; update the package.json
dependencies to use the exact version "1.6.1" (replace "^1.6.1" with "1.6.1"),
then regenerate the lockfile by running your package manager (npm install / yarn
install / pnpm install) so the lockfile reflects the pinned version.
src/components/markdown/markdown.tsx (1)

323-331: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Strip #/ prefix before passing to <Link> to prevent double-hash URLs.

With HashRouter, <Link to> expects route paths without the hash prefix. Passing to="#/tv/catalog" produces the malformed href #/#/tv/catalog instead of the intended #/tv/catalog. The current code routes href.startsWith('#/') and href.startsWith('/#/') through <Link to={href}>, which creates double-hash navigation that breaks routing.

Strip the hash prefix before passing to Link:

Suggested fix
+const normalizeInternalHref = (href: string): string => {
+  if (href.startsWith('/#/')) return href.slice(2);
+  if (href.startsWith('#/')) return href.slice(1);
+  return href;
+};
+
 const AnchorLink = ({ href, text }: { href: string; text: string }) => {
   if (!href) {
     return <span>{text}</span>;
   }
@@
   if (
     href.startsWith('#/') ||
     href.startsWith('/#/') ||
     href.startsWith('/p/') ||
     href.match(/^\/p\/[^/]+(\/c\/[^/]+)?$/) ||
     href.match(/^\/[^/]+(\/thread\/[^/]+)?$/) ||
     href.match(/^\/[^/]+\/(catalog|description|rules)(\/settings)?$/)
   ) {
-    return <Link to={href}>{text}</Link>;
+    return <Link to={normalizeInternalHref(href)}>{text}</Link>;
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/markdown/markdown.tsx` around lines 323 - 331, The link
handling block in src/components/markdown/markdown.tsx currently passes hrefs
that start with '#/' or '/#/' directly into Link (e.g., returns <Link
to={href}>), causing double-hash URLs; update the conditional branch to strip a
leading '#' from href before passing it to Link (for both '#/...' and '/#/...'),
e.g., compute a cleaned path by removing the initial '#' (or '/#' -> '/') and
then return <Link to={cleanedHref}>{text}</Link>; adjust any references in the
same branch so routes like '#/tv/catalog' become '/tv/catalog' (or '/tv/catalog'
as appropriate) before calling Link.
🧹 Nitpick comments (5)
scripts/write-react-doctor-badge.mjs (1)

8-16: ⚡ Quick win

Print the command being executed for better diagnostics.

Add a console log statement before execFileSync to show the exact command and flags being run. This helps diagnose failures and aligns with the guideline to print commands for diagnosability.

📋 Proposed enhancement
+const args = ["react-doctor", ".", "--json", "--json-compact", "--yes", "--fail-on", "none"];
+console.log(`[react-doctor-badge] Running: yarn ${args.join(" ")}`);
 const reportText = execFileSync(
   "yarn",
-  ["react-doctor", ".", "--json", "--json-compact", "--yes", "--fail-on", "none"],
+  args,
   {
     cwd: CWD,
     encoding: "utf8",
     stdio: ["ignore", "pipe", "inherit"],
   },
 );

As per coding guidelines: "Print the command, URL, branch, or path being acted on so failures are diagnosable."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/write-react-doctor-badge.mjs` around lines 8 - 16, Add a diagnostic
console log immediately before calling execFileSync that prints the command,
args and working directory being executed (reference the execFileSync call that
assigns reportText and the CWD variable), e.g., log the string "Running
command:" followed by "yarn react-doctor . --json --json-compact --yes --fail-on
none" (or programmatically print the array of args and CWD) so failures show the
exact command and flags being run; keep the log synchronous/plain console output
and place it right above the execFileSync invocation that creates reportText.
src/components/boards-bar-edit-modal/__tests__/boards-bar-edit-modal.test.tsx (1)

49-74: ⚡ Quick win

Consider expanding test coverage for the Save workflow.

While the regression tests are excellent, the suite could benefit from additional cases covering:

  • Input value changes (the onChange handler on line 68 of the component)
  • Save button click behavior
  • Checkbox toggle for subscriptions visibility
🧪 Example test case for Save behavior
it('saves directory input and closes modal on Save click', async () => {
  await renderModal();

  const input = container.querySelector<HTMLInputElement>('input[aria-label="Directory codes"]');
  const saveButton = container.querySelector('button');

  await act(async () => {
    if (input) input.value = 'jp tg';
    input?.dispatchEvent(new Event('change', { bubbles: true }));
  });

  await act(async () => {
    saveButton?.click();
  });

  const state = useBoardsBarVisibilityStore.getState();
  expect(state.visibleDirectories.has('jp')).toBe(true);
  expect(state.visibleDirectories.has('tg')).toBe(true);
  expect(useBoardsBarEditModalStore.getState().showModal).toBe(false);
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/components/boards-bar-edit-modal/__tests__/boards-bar-edit-modal.test.tsx`
around lines 49 - 74, Add tests that exercise the Save workflow: after calling
renderModal(), locate the directory input (aria-label "Directory codes") and
simulate changing its value by setting input.value and dispatching a 'change'
event to trigger the component's onChange handler, then find and click the Save
button to trigger save logic; assert that useBoardsBarVisibilityStore reflects
the new visible directories (e.g., contains 'jp' and 'tg') and that
useBoardsBarEditModalStore.getState().showModal is false; also add a test
toggling the subscriptions checkbox by querying its input and firing a
click/change event and asserting the expected store update.
src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx (1)

15-20: 💤 Low value

Consider reverting to the more declarative filter/map pattern.

The reduce with mutation (.push()) works correctly but is less readable than the original functional chain. For typical input sizes, the performance difference is negligible.

♻️ More readable alternative
-.reduce<string[]>((items, code) => {
-  if (code.length > 0) {
-    items.push(code.toLowerCase());
-  }
-  return items;
-}, []);
+.filter(code => code.length > 0)
+.map(code => code.toLowerCase());
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx` around lines
15 - 20, The current .reduce(...) expression that builds a string[] by pushing
code.toLowerCase() is functional but less readable; replace the reduce-based
implementation with a declarative filter/map chain (e.g., first filter out empty
strings, then map to .toLowerCase()) to improve clarity—locate the
.reduce<string[]>((items, code) => { ... }) expression in
boards-bar-edit-modal.tsx and swap it for the equivalent filter(...).map(...)
sequence while preserving the same result type and order.
src/views/mod-queue/mod-queue.tsx (1)

591-610: ⚡ Quick win

Reuse ModQueueBoardCount in button count rendering too.

You now have one canonical board-count renderer, but ModQueueButtonContent still duplicates the urgent/normal branching. Reusing this component there would keep count formatting consistent and reduce drift risk.

As per coding guidelines, "Avoid copy-paste logic across components. Extract custom hooks in src/hooks/." and "Follow DRY: shared UI in src/components/, shared logic in src/hooks/."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/views/mod-queue/mod-queue.tsx` around lines 591 - 610,
ModQueueButtonContent duplicates the urgent/normal count rendering—replace that
branching with a call to the canonical ModQueueBoardCount component: ensure
ModQueueButtonContent forwards the numeric props (normal and urgent) to
ModQueueBoardCount (importing it if necessary) and remove the duplicated
JSX/conditional logic so all count formatting is produced by ModQueueBoardCount;
keep existing styling by using the same props and classNames already
encapsulated in ModQueueBoardCount and adjust PropTypes/TS types on
ModQueueButtonContent if needed to accept those two numbers.
src/components/catalog-filters/catalog-filters.tsx (1)

94-99: 💤 Low value

Consider reverting to filter().map() for clarity.

The reduce approach works correctly but is less immediately readable than the two-step pipeline it replaces. For filter lists (typically small), the intermediate array created by filter().map() has negligible performance impact, and the intent—remove empty entries, then strip id—is clearer when expressed as two discrete operations.

Alternative using filter/map
-const nonEmptyFilters = localFilterItems.reduce<Omit<CatalogFilterItemStore, 'id'>[]>((filters, item) => {
-  if (item.text.trim() === '') return filters;
-  const { id: _id, ...rest } = item;
-  filters.push(rest);
-  return filters;
-}, []);
+const nonEmptyFilters = localFilterItems
+  .filter((item) => item.text.trim() !== '')
+  .map(({ id: _id, ...rest }) => rest);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/catalog-filters/catalog-filters.tsx` around lines 94 - 99, The
current nonEmptyFilters calculation uses a reduce over localFilterItems to drop
items with empty text and strip the id field; replace it with a clearer two-step
pipeline using localFilterItems.filter(...) to exclude items where
item.text.trim() === '' and then .map(...) to return each item without its id
(omit id from the returned object, matching type Omit<CatalogFilterItemStore,
'id'>[]). Update the expression that defines nonEmptyFilters (and keep the same
target type) so intent is explicit: first filter empties, then map to remove id.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/write-react-doctor-badge.mjs`:
- Line 18: JSON.parse(reportText) can throw on malformed input; wrap the parse
in a try-catch around the call to JSON.parse(reportText) in
scripts/write-react-doctor-badge.mjs (where report and reportText are used), and
on error emit a clear diagnostic (including the error.message and a snippet of
reportText or note that the react-doctor command may have failed) via
console.error or processLogger, then exit non-zero (e.g., process.exit(1)) so
the failure is visible to CI/users.

In `@src/components/catalog-filters/catalog-filters.tsx`:
- Around line 115-124: The global Enter key listener in the useEffect
(handleDocumentKeyDown) calls handleSaveRef.current() for every Enter press and
should be removed; replace the behavior by wrapping the editable table in a
<form>, move the Save button inside the form as type="submit", and wire the
form's onSubmit to call handleSave (or call handleSaveRef.current() inside a
submit handler) so Enter in text inputs triggers submit but Enter on buttons
(reorder/delete) does not trigger global save; delete the useEffect and
handleDocumentKeyDown and ensure handleSave/handleSaveRef are used only from the
form onSubmit or an explicit Ctrl/Cmd shortcut if you prefer.

In `@src/components/markdown/markdown.tsx`:
- Around line 152-158: The CROSSBOARD_REGEX currently swallows trailing
punctuation (.,:;!?) so rendered fullPattern loses that suffix; change
CROSSBOARD_REGEX to separate the trailing punctuation into its own optional
capture group (e.g. make the punctuation part ([.,:;!?])? instead of being
consumed by the main token) and update COMBINED_REGEX to include that group so
the punctuation can be reattached when rendering the fullPattern; also apply the
same change to the equivalent regexes used around lines 223-230 (the other
CROSSBOARD-related regexes) and ensure the rendering/path that uses fullPattern
appends the captured punctuation group back to the output.

In `@src/components/reply-modal/reply-modal.tsx`:
- Around line 293-297: Currently Escape is handled only via the onKeyDown on the
modal subtree which stops working when focus leaves the modal; add a
document-level keydown listener inside a useEffect in the ReplyModal component
that listens for 'Escape' and calls closeModal() when !isMobile, and ensure you
remove the listener on cleanup and when isMobile or modal visibility changes;
keep the existing onKeyDown if desired but make the global listener the
authoritative dismiss mechanism so Escape works regardless of focus (reference:
onKeyDown, isMobile, closeModal).

---

Outside diff comments:
In `@package.json`:
- Line 24: The dependency entry for "@vercel/analytics" is using a caret range
"^1.6.1" which must be pinned; update the package.json dependencies to use the
exact version "1.6.1" (replace "^1.6.1" with "1.6.1"), then regenerate the
lockfile by running your package manager (npm install / yarn install / pnpm
install) so the lockfile reflects the pinned version.

In `@src/components/markdown/markdown.tsx`:
- Around line 323-331: The link handling block in
src/components/markdown/markdown.tsx currently passes hrefs that start with '#/'
or '/#/' directly into Link (e.g., returns <Link to={href}>), causing
double-hash URLs; update the conditional branch to strip a leading '#' from href
before passing it to Link (for both '#/...' and '/#/...'), e.g., compute a
cleaned path by removing the initial '#' (or '/#' -> '/') and then return <Link
to={cleanedHref}>{text}</Link>; adjust any references in the same branch so
routes like '#/tv/catalog' become '/tv/catalog' (or '/tv/catalog' as
appropriate) before calling Link.

---

Nitpick comments:
In `@scripts/write-react-doctor-badge.mjs`:
- Around line 8-16: Add a diagnostic console log immediately before calling
execFileSync that prints the command, args and working directory being executed
(reference the execFileSync call that assigns reportText and the CWD variable),
e.g., log the string "Running command:" followed by "yarn react-doctor . --json
--json-compact --yes --fail-on none" (or programmatically print the array of
args and CWD) so failures show the exact command and flags being run; keep the
log synchronous/plain console output and place it right above the execFileSync
invocation that creates reportText.

In
`@src/components/boards-bar-edit-modal/__tests__/boards-bar-edit-modal.test.tsx`:
- Around line 49-74: Add tests that exercise the Save workflow: after calling
renderModal(), locate the directory input (aria-label "Directory codes") and
simulate changing its value by setting input.value and dispatching a 'change'
event to trigger the component's onChange handler, then find and click the Save
button to trigger save logic; assert that useBoardsBarVisibilityStore reflects
the new visible directories (e.g., contains 'jp' and 'tg') and that
useBoardsBarEditModalStore.getState().showModal is false; also add a test
toggling the subscriptions checkbox by querying its input and firing a
click/change event and asserting the expected store update.

In `@src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx`:
- Around line 15-20: The current .reduce(...) expression that builds a string[]
by pushing code.toLowerCase() is functional but less readable; replace the
reduce-based implementation with a declarative filter/map chain (e.g., first
filter out empty strings, then map to .toLowerCase()) to improve clarity—locate
the .reduce<string[]>((items, code) => { ... }) expression in
boards-bar-edit-modal.tsx and swap it for the equivalent filter(...).map(...)
sequence while preserving the same result type and order.

In `@src/components/catalog-filters/catalog-filters.tsx`:
- Around line 94-99: The current nonEmptyFilters calculation uses a reduce over
localFilterItems to drop items with empty text and strip the id field; replace
it with a clearer two-step pipeline using localFilterItems.filter(...) to
exclude items where item.text.trim() === '' and then .map(...) to return each
item without its id (omit id from the returned object, matching type
Omit<CatalogFilterItemStore, 'id'>[]). Update the expression that defines
nonEmptyFilters (and keep the same target type) so intent is explicit: first
filter empties, then map to remove id.

In `@src/views/mod-queue/mod-queue.tsx`:
- Around line 591-610: ModQueueButtonContent duplicates the urgent/normal count
rendering—replace that branching with a call to the canonical ModQueueBoardCount
component: ensure ModQueueButtonContent forwards the numeric props (normal and
urgent) to ModQueueBoardCount (importing it if necessary) and remove the
duplicated JSX/conditional logic so all count formatting is produced by
ModQueueBoardCount; keep existing styling by using the same props and classNames
already encapsulated in ModQueueBoardCount and adjust PropTypes/TS types on
ModQueueButtonContent if needed to accept those two numbers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a7de020-3409-4c48-b874-028f712355a2

📥 Commits

Reviewing files that changed from the base of the PR and between cbc5088 and f55ba9b.

📒 Files selected for processing (44)
  • .github/workflows/ci.yml
  • README.md
  • package.json
  • scripts/write-react-doctor-badge.mjs
  • src/app.tsx
  • src/components/board-buttons/board-buttons.tsx
  • src/components/board-header/__tests__/board-header.test.tsx
  • src/components/boards-bar-edit-modal/__tests__/boards-bar-edit-modal.test.tsx
  • src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx
  • src/components/boards-bar/boards-bar.tsx
  • src/components/catalog-filters/catalog-filters.tsx
  • src/components/catalog-filters/filters-protip/filters-protip.tsx
  • src/components/catalog-filters/highlight-color-picker/highlight-color-picker.module.css
  • src/components/catalog-filters/highlight-color-picker/highlight-color-picker.tsx
  • src/components/catalog-search/catalog-search.tsx
  • src/components/challenge-modal/__tests__/challenge-modal.test.tsx
  • src/components/challenge-modal/challenge-modal.tsx
  • src/components/comment-content/comment-content.tsx
  • src/components/create-board-modal/create-board-modal.tsx
  • src/components/directory-modal/directory-modal.tsx
  • src/components/markdown/external-number-quote-link.tsx
  • src/components/markdown/markdown.tsx
  • src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx
  • src/components/post-form/post-form.tsx
  • src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx
  • src/components/reply-modal/reply-modal.tsx
  • src/components/settings-modal/account-settings/account-settings.tsx
  • src/components/settings-modal/advanced-settings/advanced-settings.tsx
  • src/components/settings-modal/crypto-wallets-setting/crypto-wallets-setting.tsx
  • src/components/settings-modal/p2p-stats-settings/p2p-stats-settings.tsx
  • src/components/settings-modal/settings-modal.tsx
  • src/components/settings-modal/subscriptions-setting/subscriptions-setting.tsx
  • src/e2e/pretext-benchmark-harness.tsx
  • src/hooks/use-community-identifiers.ts
  • src/hooks/use-directories.ts
  • src/lib/utils/blotter-utils.ts
  • src/lib/utils/pretext-height-estimates.ts
  • src/lib/utils/route-utils.ts
  • src/lib/utils/view-utils.ts
  • src/views/archive/__tests__/helpers.ts
  • src/views/archive/index.ts
  • src/views/home/boards-list/boards-filter-modal.tsx
  • src/views/mod-queue/mod-queue.tsx
  • src/views/post/post.tsx
💤 Files with no reviewable changes (1)
  • src/views/archive/index.ts

Comment thread scripts/write-react-doctor-badge.mjs Outdated
Comment thread src/components/catalog-filters/catalog-filters.tsx Outdated
Comment thread src/components/markdown/markdown.tsx
Comment thread src/components/reply-modal/reply-modal.tsx Outdated
@tomcasaburi
Copy link
Copy Markdown
Member Author

Addressed the valid review findings in 9812463: restored document-level Escape handling for the reply modal, replaced the catalog filter document Enter shortcut with form submit behavior, preserved punctuation/hash routes in markdown links, and made React Doctor badge JSON parse failures explicit.

Local verification after the review fixes: targeted component tests, full yarn test --run, yarn lint, yarn type-check, yarn build, yarn doctor (95/100), yarn doctor:badge, and Playwright checks on #/tv/catalog in Chrome/Firefox/WebKit plus mobile viewport. Remaining bot notes are either outside this PR (existing dependency pin), low-value style nits, or non-blocking follow-up suggestions.

Comment thread src/components/reply-modal/reply-modal.tsx
@tomcasaburi tomcasaburi force-pushed the codex/fix/react-doctor-score branch from 9812463 to 99e2208 Compare May 10, 2026 11:06
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/catalog-filters/catalog-filters.tsx`:
- Line 186: The ref callback currently uses an expression-bodied arrow that
returns the assigned element; update the ref on the element so the callback is
block-bodied and explicitly returns void: inside the callback assign the element
to inputRefs.current[index] and do not return a value (and add any cleanup logic
there if needed). Locate the JSX ref attribute setting inputRefs.current[index]
and replace the expression-bodied handler with a block-bodied handler that
performs the assignment and returns nothing to satisfy React 19's ref callback
expectations.

In `@src/components/markdown/markdown.tsx`:
- Around line 154-158: The URL_REGEX currently prevents trailing ')' causing
links like "Function_(mathematics)" to be split; instead, allow ')' in the
terminal character class in URL_REGEX (so COMBINED_REGEX can capture full URLs)
and then, inside the link-handling code that processes matches from
COMBINED_REGEX, post-process the captured URL by trimming unmatched trailing
punctuation (e.g. .,;:!?"'> and lone closing parentheses) only when they are not
balanced with an opening '(' in the captured URL; update functions that consume
COMBINED_REGEX matches (references: URL_REGEX and COMBINED_REGEX) to perform
this trimming so valid balanced parenthesis remain part of the link while stray
punctuation is excluded.

In `@src/components/reply-modal/reply-modal.tsx`:
- Around line 146-149: The component mutates document.body.style during drag
(setting userSelect and webkitUserSelect) but does not reset those styles on
unmount; update the ReplyModal component (the effect or drag handlers that call
Object.assign(document.body.style, ...)) to restore
document.body.style.userSelect and document.body.style.WebkitUserSelect to their
previous values in a cleanup: capture previous values before mutation, set the
disables on mount/start drag, and in the effect cleanup or componentWillUnmount
ensure you restore the saved values (use the correct vendor property name
WebkitUserSelect) so the global selection behavior is always reset even if the
modal unmounts mid-drag.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6645f6e3-3d0b-4b08-99c5-8c90c9d15385

📥 Commits

Reviewing files that changed from the base of the PR and between f55ba9b and 99e2208.

📒 Files selected for processing (47)
  • .github/workflows/ci.yml
  • README.md
  • package.json
  • scripts/write-react-doctor-badge.mjs
  • src/app.tsx
  • src/components/board-buttons/board-buttons.tsx
  • src/components/board-header/__tests__/board-header.test.tsx
  • src/components/boards-bar-edit-modal/__tests__/boards-bar-edit-modal.test.tsx
  • src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx
  • src/components/boards-bar/boards-bar.tsx
  • src/components/catalog-filters/__tests__/catalog-filters.test.tsx
  • src/components/catalog-filters/catalog-filters.tsx
  • src/components/catalog-filters/filters-protip/filters-protip.tsx
  • src/components/catalog-filters/highlight-color-picker/highlight-color-picker.module.css
  • src/components/catalog-filters/highlight-color-picker/highlight-color-picker.tsx
  • src/components/catalog-search/catalog-search.tsx
  • src/components/challenge-modal/__tests__/challenge-modal.test.tsx
  • src/components/challenge-modal/challenge-modal.tsx
  • src/components/comment-content/comment-content.tsx
  • src/components/create-board-modal/create-board-modal.tsx
  • src/components/directory-modal/directory-modal.tsx
  • src/components/markdown/__tests__/markdown.test.tsx
  • src/components/markdown/external-number-quote-link.tsx
  • src/components/markdown/markdown.tsx
  • src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx
  • src/components/post-form/post-form.tsx
  • src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx
  • src/components/reply-modal/__tests__/reply-modal.test.tsx
  • src/components/reply-modal/reply-modal.tsx
  • src/components/settings-modal/account-settings/account-settings.tsx
  • src/components/settings-modal/advanced-settings/advanced-settings.tsx
  • src/components/settings-modal/crypto-wallets-setting/crypto-wallets-setting.tsx
  • src/components/settings-modal/p2p-stats-settings/p2p-stats-settings.tsx
  • src/components/settings-modal/settings-modal.tsx
  • src/components/settings-modal/subscriptions-setting/subscriptions-setting.tsx
  • src/e2e/pretext-benchmark-harness.tsx
  • src/hooks/use-community-identifiers.ts
  • src/hooks/use-directories.ts
  • src/lib/utils/blotter-utils.ts
  • src/lib/utils/pretext-height-estimates.ts
  • src/lib/utils/route-utils.ts
  • src/lib/utils/view-utils.ts
  • src/views/archive/__tests__/helpers.ts
  • src/views/archive/index.ts
  • src/views/home/boards-list/boards-filter-modal.tsx
  • src/views/mod-queue/mod-queue.tsx
  • src/views/post/post.tsx
💤 Files with no reviewable changes (1)
  • src/views/archive/index.ts
✅ Files skipped from review due to trivial changes (15)
  • README.md
  • src/components/reply-modal/tests/reply-modal.test.tsx
  • src/components/markdown/external-number-quote-link.tsx
  • src/lib/utils/view-utils.ts
  • src/components/catalog-filters/highlight-color-picker/highlight-color-picker.tsx
  • src/components/challenge-modal/tests/challenge-modal.test.tsx
  • src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx
  • src/views/archive/tests/helpers.ts
  • src/components/post-mobile/post-menu-mobile/post-menu-mobile.tsx
  • src/components/settings-modal/subscriptions-setting/subscriptions-setting.tsx
  • src/components/catalog-filters/highlight-color-picker/highlight-color-picker.module.css
  • src/hooks/use-directories.ts
  • src/hooks/use-community-identifiers.ts
  • package.json
  • src/components/catalog-filters/filters-protip/filters-protip.tsx
🚧 Files skipped from review as they are similar to previous changes (26)
  • src/components/comment-content/comment-content.tsx
  • src/components/directory-modal/directory-modal.tsx
  • src/lib/utils/route-utils.ts
  • src/components/settings-modal/account-settings/account-settings.tsx
  • src/components/settings-modal/crypto-wallets-setting/crypto-wallets-setting.tsx
  • src/components/board-header/tests/board-header.test.tsx
  • src/components/boards-bar-edit-modal/boards-bar-edit-modal.tsx
  • src/components/settings-modal/p2p-stats-settings/p2p-stats-settings.tsx
  • src/components/post-form/post-form.tsx
  • src/views/home/boards-list/boards-filter-modal.tsx
  • src/components/catalog-search/catalog-search.tsx
  • src/e2e/pretext-benchmark-harness.tsx
  • src/lib/utils/blotter-utils.ts
  • src/lib/utils/pretext-height-estimates.ts
  • src/views/mod-queue/mod-queue.tsx
  • src/components/boards-bar-edit-modal/tests/boards-bar-edit-modal.test.tsx
  • src/components/settings-modal/settings-modal.tsx
  • .github/workflows/ci.yml
  • src/components/challenge-modal/challenge-modal.tsx
  • scripts/write-react-doctor-badge.mjs
  • src/app.tsx
  • src/components/create-board-modal/create-board-modal.tsx
  • src/components/boards-bar/boards-bar.tsx
  • src/components/settings-modal/advanced-settings/advanced-settings.tsx
  • src/components/board-buttons/board-buttons.tsx
  • src/views/post/post.tsx

Comment thread src/components/catalog-filters/catalog-filters.tsx Outdated
Comment thread src/components/markdown/markdown.tsx Outdated
Comment thread src/components/reply-modal/reply-modal.tsx Outdated
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ba07612. Configure here.

Comment thread .github/workflows/ci.yml
run: |
mkdir -p "${PAGES_OUTPUT_PATH}/badges"
cp "${BADGE_SOURCE_PATH}" "${PAGES_OUTPUT_PATH}/badges/coverage.json"
cp "${REACT_DOCTOR_BADGE_SOURCE_PATH}" "${PAGES_OUTPUT_PATH}/badges/react-doctor.json"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CI YAML cp command has wrong indentation level

High Severity

The newly added cp command for the React Doctor badge on line 161 appears to have less indentation than the sibling mkdir, cp, and touch commands in the run: | literal block. In a YAML literal block scalar, all content lines must share the indentation level established by the first content line. If the indentation is genuinely short by 2 spaces, YAML will interpret the line as outside the run: block, causing either a parse failure or the command being silently dropped from the shell script. This would prevent the React Doctor badge from being copied into the Pages artifact, breaking badge deployment on every master push.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ba07612. Configure here.

@tomcasaburi tomcasaburi merged commit 556973a into master May 10, 2026
11 checks passed
@tomcasaburi tomcasaburi deleted the codex/fix/react-doctor-score branch May 10, 2026 11:25
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.

1 participant