Skip to content

feat: add CodeMirror editor to Base64 tool#21

Merged
rivodotlove merged 2 commits into
mainfrom
feat/riv-5-codemirror-base64
Jun 3, 2026
Merged

feat: add CodeMirror editor to Base64 tool#21
rivodotlove merged 2 commits into
mainfrom
feat/riv-5-codemirror-base64

Conversation

@rivodotlove

@rivodotlove rivodotlove commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Closes RIV-5.

What

Replaces the Base64 tool's plain <textarea> input/output with a shared CodeMirror 6 editor.

  • Line numbers + multi-line editing.
  • Syntax highlighting auto-detected from input (JSON / XML / plain text).
  • Highlight palette + editor chrome follow the app theme (dark/light) via --cm-* CSS vars.
  • Font-size and tab-size come from the existing settings store.
  • Read-only output stays selectable/copyable.

Why

Plain textareas were unreadable for the tool's real workflows — multi-line JSON/XML/config blocks. CodeMirror brings parity with other code-focused tooling.

How it's structured

  • src/shared/ui/code-editor.tsx — generic controlled CodeEditor; fontSize/tabSize are props so shared/ui never imports app state.
  • src/shared/lib/editor/detect-language.ts — pure JSON/XML/text heuristic (+ unit test).
  • src/index.css — per-theme --cm-* syntax token colors.
  • src/modules/base64/ui/base64-tool.tsx — wiring; domain codec untouched.
  • e2e/base64.e2e.ts — extended for CodeMirror.

Verification

  • vp check → 0 lint/type errors
  • vp test → 16 passed (unit)
  • pnpm exec playwright test → 7 passed (e2e: encode/decode, URL-safe, error, persistence, gutter, highlighting)
  • Visually confirmed in-browser (JSON highlighting + line numbers, dark theme).

Plan + Opus gap-review drove this; all blocker/major review gaps folded in. Built with the new write-plan/implement-plan tooling (PR #20).

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced syntax-highlighting code editor supporting JSON, XML, and plain text
    • Added automatic language detection for input content
    • Configurable editor font size and tab size settings
  • Tests

    • Enhanced test coverage for code editor interactions
  • Refactor

    • Replaced text inputs with code editor components
    • Integrated theme-aware syntax highlighting colors

@rivodotlove rivodotlove self-assigned this Jun 3, 2026
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1cbb0c05-7b03-4f11-abc2-b10ed98e21e1

📥 Commits

Reviewing files that changed from the base of the PR and between d672f98 and c879e36.

📒 Files selected for processing (2)
  • .gitignore
  • src/shared/ui/code-editor.tsx
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/shared/ui/code-editor.tsx

📝 Walkthrough

Walkthrough

This pull request integrates CodeMirror as the editor backend for the Base64 tool. It adds CodeMirror dependencies, theme CSS variables, implements language detection for JSON/XML/text, creates a reusable CodeEditor component, migrates the Base64 tool to use it, and updates E2E tests to validate CodeMirror-based editors.

Changes

CodeMirror Editor Integration

Layer / File(s) Summary
Dependencies and CSS theme configuration
package.json, src/index.css
Adds CodeMirror, UIW React wrapper, and Lezer packages to dependencies; introduces CodeMirror syntax token color variables (--cm-*) for both dark and light theme blocks.
Language detection utility and tests
src/shared/lib/editor/detect-language.ts, src/shared/lib/editor/detect-language.test.ts
Implements detectLanguage(text) as a pure heuristic identifying JSON, XML, or text via input prefix and JSON.parse guarding; covers valid/invalid JSON, XML declarations, and text fallback cases in unit tests.
CodeEditor component and barrel export
src/shared/ui/code-editor.tsx, src/shared/ui/index.ts
Adds a memoized CodeEditor React component wrapping @uiw/react-codemirror with language extensions, theme styling via CSS variables, editable and read-only basicSetup modes, sanitized tab size, aria-label support, and exports from the UI barrel.
Base64Tool migration to CodeEditor
src/modules/base64/ui/base64-tool.tsx
Replaces input/output textareas with CodeEditor components; derives inputLang/outputLang from content via detectLanguage, reads fontSize and tabSize from settings store, and wires value/onChange/readOnly bindings.
E2E test updates for CodeMirror editors
e2e/base64.e2e.ts
Refactors Playwright tests to locate editors by aria-label; reads editor output by aggregating CodeMirror line texts; validates encode/decode, URL-safe mode, error states, and persistence via text polling; adds assertions for line-number gutter and JSON syntax-highlighting token spans.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Possibly related PRs

  • rivodotlove/devbox#8: Initial Base64 tool creation—modified src/modules/base64/ui/base64-tool.tsx to introduce the Base64 encode/decode UI, now being enhanced with CodeMirror editor support.

Poem

A rabbit hops through the editor's glow,
CodeMirror syntax now steals the show,
From input to output, the tokens align,
Dark themes and light themes in harmony shine,
Language detection guides every byte,
Base64 dancing in colors so bright! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add CodeMirror editor to Base64 tool' clearly summarizes the main change: introducing CodeMirror as the editor for the Base64 tool, replacing plain textareas. It is specific, concise, and directly reflects the primary focus of the changeset.
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.

✏️ 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 feat/riv-5-codemirror-base64

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

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 3, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
devbox c879e36 Commit Preview URL

Branch Preview URL
Jun 03 2026, 05:08 PM

RIV-5. Replace the input/output textareas with a shared CodeMirror 6
editor: line numbers, multi-line editing, and JSON/XML syntax
highlighting auto-detected from the input. Highlight + chrome follow the
app theme via CSS vars (dark/light), and font-size / tab-size come from
the existing settings store.

- shared/ui/code-editor.tsx: generic, controlled CodeEditor (fontSize/
  tabSize as props so shared/ui stays free of app state).
- shared/lib/editor/detect-language.ts: pure JSON/XML/text heuristic + test.
- index.css: per-theme --cm-* syntax token colors.
- e2e/base64.e2e.ts: encode/decode, URL-safe, error, persistence, gutter,
  and highlighting coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rivodotlove rivodotlove force-pushed the feat/riv-5-codemirror-base64 branch from d73b5e8 to d672f98 Compare June 3, 2026 16:55

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/shared/ui/code-editor.tsx`:
- Around line 96-97: The editor builds an extensions array using indentUnit.of("
".repeat(tabSize)) and keymap.of([indentWithTab]) but it doesn't guard against
invalid tabSize nor set EditorState.tabSize, so repeat can throw and actual tab
width for '\t' will differ; clamp tabSize to a safe integer range (e.g., 1..8)
before using it, replace " ".repeat(tabSize) with the clamped value, and add
EditorState.tabSize.of(clampedTabSize) to the extensions alongside
indentUnit.of(...) (locate the extensions/creation code in
src/shared/ui/code-editor.tsx that references indentUnit.of and keymap.of to
apply the change).
🪄 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 Plus

Run ID: e02321bd-4be9-4efb-8a68-ad279401b218

📥 Commits

Reviewing files that changed from the base of the PR and between e8cc0cb and d73b5e8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • e2e/base64.e2e.ts
  • package.json
  • src/index.css
  • src/modules/base64/ui/base64-tool.tsx
  • src/shared/lib/editor/detect-language.test.ts
  • src/shared/lib/editor/detect-language.ts
  • src/shared/ui/code-editor.tsx
  • src/shared/ui/index.ts

Comment thread src/shared/ui/code-editor.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 @.claude/plans/RIV-5-codemirror-base64-editor.html:
- Line 77: The external anchor element rendering the Linear link currently uses
target="_blank" with only noopener; update the anchor's rel attribute to include
"noreferrer" as well (i.e., rel="noopener noreferrer") to harden external link
behavior — locate the <a ...> element containing the Linear URL text ("View
RIV-5 in Linear ↗") and add "noreferrer" to its rel list.
- Around line 230-240: The detectLanguage function contains an unescaped literal
'<' in the expression t.startsWith("<") which breaks the HTML snippet rendering;
update only the detectLanguage snippet so that any literal angle brackets inside
it are HTML-escaped (replace "<" with &lt; and ">" with &gt; as needed) while
leaving the already-escaped CodeEditor/Record<...> parts untouched — locate the
detectLanguage function and change its t.startsWith("<") (and any other raw
'<'/'>' inside that small snippet) to the corresponding entities.
🪄 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 Plus

Run ID: 445d8256-2074-461d-85a3-c3de7fd167ad

📥 Commits

Reviewing files that changed from the base of the PR and between d73b5e8 and d672f98.

⛔ Files ignored due to path filters (3)
  • .claude/plans/assets/RIV-5-after-1.png is excluded by !**/*.png
  • .claude/plans/assets/RIV-5-current-1.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • .claude/plans/RIV-5-codemirror-base64-editor.html
  • e2e/base64.e2e.ts
  • package.json
  • src/index.css
  • src/modules/base64/ui/base64-tool.tsx
  • src/shared/lib/editor/detect-language.test.ts
  • src/shared/lib/editor/detect-language.ts
  • src/shared/ui/code-editor.tsx
  • src/shared/ui/index.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/shared/ui/index.ts
  • src/shared/lib/editor/detect-language.ts
  • package.json
  • src/shared/lib/editor/detect-language.test.ts
  • src/index.css
  • src/modules/base64/ui/base64-tool.tsx
  • e2e/base64.e2e.ts
  • src/shared/ui/code-editor.tsx

Comment thread .claude/plans/RIV-5-codemirror-base64-editor.html Outdated
Comment thread .claude/plans/RIV-5-codemirror-base64-editor.html Outdated
Guard `" ".repeat(tabSize)` against invalid persisted values (negative/
NaN would throw) and add EditorState.tabSize so literal tabs render at
the configured width, not just indentUnit. Also stop tracking generated
write-plan HTML under .claude/plans (gitignored) — it leaked into this
feature PR. (CodeRabbit, PR #21)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rivodotlove rivodotlove merged commit 7d309fb into main Jun 3, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant