You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The SQL editor is written from scratch, zero-dependency (src/ui/editor.js, ~125 lines): a <textarea> overlaid on a syntax-highlighted <pre> with a line-number gutter, fed by a hand-rolled ~100-line pure tokenizer (src/core/sql-highlight.js). It's fully covered by the 100% test gate and adds nothing to the bundle.
It nails the 90% case — write, highlight, line numbers, Tab-indent, drag-drop schema identifiers, undo, save/share/run wiring. What it lacks: autocomplete (especially schema-aware table/column completion), bracket matching, auto-indent, in-editor search, folding, multi-cursor, error squiggles.
Options surveyed
Library
Size
Fit for this app
Monaco (VS Code editor)
~5–10 MB + web workers
❌ Disqualified. We ship one self-contained HTML file with zero third-party requests (served from ClickHouse user_files); Monaco's size + worker model can't be cleanly inlined and would bloat the ~316 KB artifact ~20×. Unusable on mobile.
✅ Only realistic candidate. Tree-shakeable, no workers, bundles+inlines with esbuild like Chart.js, good on mobile. Used by Prisma Studio, Observable, Replit, Firefox DevTools.
The case for CM6
One real reason: schema-aware autocomplete. It's the single capability that matters for a SQL browser and that the hand-rolled editor can't reasonably match. @codemirror/lang-sql's schemaCompletionSource turns the schema tree we already load into live table.column completion (plus keyword/function completion, bracket matching, search, folding for free). Reimplementing a decent completion engine on the textarea is most of the work of adopting CM6 anyway, with worse results.
The editor DOM wrapper drops below the 100% coverage gate → move it behind an injected seam (app.Editor, exactly the Chart.js precedent), keeping the SQL knowledge (keywords/funcs/schema) pure in core/.
CM6's transaction/extension API is a real integration surface — selection, undo, drag-drop, and the share/save wiring all get rewritten.
Recommendation
Don't migrate now. The current editor is well-matched to the constraints and migrating is a net loss unless we're buying a feature it structurally can't provide.
Adopt CM6 when autocomplete becomes a priority (or we want folding/search/multi-cursor as a set). At that point CM6 is clearly the right pick — not Monaco (size/worker/single-file killer) or Ace — bundled and inlined behind an injected seam like Chart.js, keeping the artifact self-contained.
Middle path (if we only want completion and want to avoid a second dep): keep the textarea and build a small schema-driven completion dropdown ourselves — we already have the schema + tokenizer. Stays zero-dep and on-gate, but won't match CM6's polish and is more maintenance.
Suggested next step
Prototype the CM6 route on a branch behind a seam (lang-sql + schemaCompletionSource wired to the live schema) to measure the real bundle delta and the autocomplete UX before committing.
Context
The SQL editor is written from scratch, zero-dependency (
src/ui/editor.js, ~125 lines): a<textarea>overlaid on a syntax-highlighted<pre>with a line-number gutter, fed by a hand-rolled ~100-line pure tokenizer (src/core/sql-highlight.js). It's fully covered by the 100% test gate and adds nothing to the bundle.It nails the 90% case — write, highlight, line numbers, Tab-indent, drag-drop schema identifiers, undo, save/share/run wiring. What it lacks: autocomplete (especially schema-aware table/column completion), bracket matching, auto-indent, in-editor search, folding, multi-cursor, error squiggles.
Options surveyed
user_files); Monaco's size + worker model can't be cleanly inlined and would bloat the ~316 KB artifact ~20×. Unusable on mobile.The case for CM6
One real reason: schema-aware autocomplete. It's the single capability that matters for a SQL browser and that the hand-rolled editor can't reasonably match.
@codemirror/lang-sql'sschemaCompletionSourceturns the schema tree we already load into livetable.columncompletion (plus keyword/function completion, bracket matching, search, folding for free). Reimplementing a decent completion engine on the textarea is most of the work of adopting CM6 anyway, with worse results.Costs (these cut against the project's grain)
app.Editor, exactly the Chart.js precedent), keeping the SQL knowledge (keywords/funcs/schema) pure incore/.Recommendation
Don't migrate now. The current editor is well-matched to the constraints and migrating is a net loss unless we're buying a feature it structurally can't provide.
Adopt CM6 when autocomplete becomes a priority (or we want folding/search/multi-cursor as a set). At that point CM6 is clearly the right pick — not Monaco (size/worker/single-file killer) or Ace — bundled and inlined behind an injected seam like Chart.js, keeping the artifact self-contained.
Middle path (if we only want completion and want to avoid a second dep): keep the textarea and build a small schema-driven completion dropdown ourselves — we already have the schema + tokenizer. Stays zero-dep and on-gate, but won't match CM6's polish and is more maintenance.
Suggested next step
Prototype the CM6 route on a branch behind a seam (
lang-sql+schemaCompletionSourcewired to the live schema) to measure the real bundle delta and the autocomplete UX before committing.References
🤖 Generated with Claude Code