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
exact source preserved separately from formatted output;
deterministic classification;
manual requestedMode overrides Auto detection.
Auto-detection priority
Auto mode must be conservative and deterministic.
Use this priority:
1. strong ClickHouse type hint
2. strict JSON / JSONL parsing
3. strong SQL content with optional column-name support
4. existing HTML heuristic
5. conservative XML heuristic
6. plain text
Do not auto-detect Markdown from arbitrary prose.
Markdown remains available through the explicit mode selector.
Auto-detection should remain conservative for scalar roots. A scalar should normally require a JSON type hint or manual JSON mode; otherwise ordinary values such as true or 123 should remain Text.
JSON Lines / NDJSON
When the source contains multiple non-empty lines and every line independently parses as JSON:
classify as jsonl;
format each record independently;
preserve record boundaries;
retain exact Raw source;
ignore blank lines for parsing;
do not create phantom records for blank lines.
Suggested formatted output:
{
"record": 1
}
────────
{
"record": 2
}
The separator may differ, but records must remain visually distinct.
A single invalid non-empty line makes JSONL parsing fail.
Do not classify arbitrary multi-line prose as JSONL because one line happens to parse.
Invalid JSON
When JSON mode is selected by:
a JSON-bearing ClickHouse type;
strict Auto classification;
manual JSON override;
and parsing fails, show:
a visible error banner;
the complete exact Raw source.
Example:
Invalid JSON — Unexpected token "'" at position 123
Requirements:
do not show an empty viewer;
do not show partially formatted output;
do not repair invalid escapes;
do not remove trailing commas;
do not alter whitespace or line endings in Raw;
do not silently switch to Text;
expose the error with role="alert" or equivalent;
Copy always returns the exact original value.
SQL detection
SQL Auto detection must combine syntax and context.
Do not detect SQL with a broad regular expression such as:
/select|from|where/i
That would misclassify logs, prose, stack traces, and JSON strings.
Reuse the existing SQL lexical infrastructure:
scanSpans()
splitStatements()
leadingKeyword()
These already understand:
ClickHouse single-quoted strings;
heredocs;
quoted identifiers;
line comments;
nested block comments;
semicolons inside literals;
multi-statement scripts.
Strong SQL keywords
Treat the following leading keywords as strong SQL signals:
SELECT
INSERT
CREATE
ALTER
DROP
TRUNCATE
RENAME
ATTACH
DETACH
OPTIMIZE
EXPLAIN
DESCRIBE
DESC
SHOW
EXISTS
SYSTEM
KILL
GRANT
REVOKE
BACKUP
RESTORE
CHECK
WATCH
The exact set may reuse existing keyword tables where appropriate.
Ambiguous SQL keywords
These are valid SQL beginnings but can appear in ordinary text:
WITH
SET
USE
VALUES
Require supporting context for these, such as a recognized SQL-bearing column name.
SQL-bearing column names
Treat these names as strong supporting hints, case-insensitively:
Also support common suffix patterns conservatively:
*_query
*_sql
*_ddl
Do not allow a column name alone to classify arbitrary prose as SQL.
Recommended rule:
functionlooksLikeSql({ name, text }){conststatements=splitStatements(text);if(!statements.length)returnfalse;constkeyword=leadingKeyword(statements[0]);if(STRONG_SQL_KEYWORDS.has(keyword))returntrue;returnisSqlColumnName(name)&&AMBIGUOUS_SQL_KEYWORDS.has(keyword);}
A multi-statement script is SQL when every non-empty statement has a recognized SQL leading keyword.
SQL source rendering
SQL mode uses the existing read-only CodeMirror viewer:
main result table drawer
detached Data-view drawer
SQL auto-format
JSON Pretty/Raw
HTML Rendered/Source
No schema change.
No saved-query migration.
No new runtime dependency.
No local SQL formatter.
Tests
Auto classification
Verify:
query + SELECT ... resolves to SQL;
statement + CREATE TABLE ... resolves to SQL;
view_query + WITH ... SELECT ... resolves to SQL;
arbitrary prose containing the word select remains Text;
a log line beginning with WITH remains Text unless column context supports SQL;
multi-statement SQL resolves to SQL;
comments before a SQL keyword are skipped correctly;
semicolons inside strings do not break detection;
heredocs do not break detection;
empty strings resolve to Text.
JSON
Verify:
object;
array;
valid scalar with JSON type hint;
nested JSON-bearing ClickHouse types;
valid JSONL;
blank JSONL lines;
invalid JSON;
invalid JSONL;
truncated JSON;
malformed escape sequences;
exact Raw preservation;
Pretty uses two-space indentation;
Copy uses Raw.
SQL formatting
Verify:
raw SQL viewer appears synchronously;
formatting request starts after render;
successful response replaces the Formatted view;
Raw remains exact;
Formatted/Raw toggle works;
failed request retains Raw;
empty formatter result retains Raw;
close aborts request;
mode switch aborts request;
stale response cannot repaint;
cached SQL does not issue another request;
cache is bounded;
value above size limit does not issue a request;
formatter request does not execute the source SQL;
log_queries=0 is attempted where configured;
inability to suppress logging does not fail formatting;
no editor/history/result state changes occur.
Manual overrides
Verify every selector mode:
Auto
Text
JSON
SQL
Markdown
HTML
XML
Manual selection must override Auto without modifying the source.
CodeMirror
Verify correct language IDs:
text
json
sql
xml
html
markdown
Verify:
one active viewer maximum;
mode switch destroys prior viewer;
tab switch destroys prior viewer;
close destroys viewer;
detached-document ownership;
search;
wrapping;
selection and copy.
HTML
Verify:
Auto HTML detection;
sandboxed Rendered mode;
CodeMirror Source mode;
exact source;
switching destroys old content;
scripts do not execute.
XML
Verify:
declaration-based detection;
conservative root detection;
HTML wins over XML;
source-only behavior;
no iframe;
no external-resource fetch.
Markdown
Verify:
never auto-detected;
manual Rendered mode;
manual Source mode;
Text panel and drawer use the same renderer;
unsafe links remain blocked;
raw HTML remains inert;
no duplicate renderer implementation.
Existing drawer behavior
Verify:
resize persistence;
Escape;
backdrop close;
close button;
stacked drawers;
only top drawer closes;
detached Data view;
exact column name and ClickHouse type remain shown.
Non-goals
Do not include:
local SQL formatting;
third-party SQL formatter packages;
hand-written SQL whitespace formatting;
editable cell values;
executing cell SQL;
opening SQL automatically in a new editor tab;
persisting drawer mode by column;
persisting formatted content;
YAML;
CSV/TSV table previews;
XML rendering;
XSLT;
full CommonMark or GFM expansion;
JSON repair;
JSON5;
per-format user preferences;
semantic SQL validation;
schema-aware SQL completion in the drawer.
Acceptance criteria
Cell detail offers Auto, Text, JSON, SQL, Markdown, HTML, and XML modes.
Auto mode visibly reports its resolved format.
JSON-bearing ClickHouse types are recognized through structured type analysis.
Valid JSON supports Pretty and exact Raw views.
Valid JSONL supports formatted and exact Raw views.
Invalid JSON remains in JSON mode and shows an error plus complete Raw source.
SQL is conservatively auto-detected using lexical syntax and optional column-name evidence.
SQL values open immediately in a read-only highlighted viewer.
SQL is formatted only through ClickHouse formatQuery().
No local SQL formatter or new formatting dependency is added.
SQL formatting is cancellable, bounded, cached, and best-effort.
SQL formatting failure leaves exact Raw SQL visible.
Formatted/Raw SQL toggle is available after successful formatting.
Copy always returns the original raw cell value.
HTML keeps sandboxed Rendered mode and gains CodeMirror Source.
XML is source-only.
Markdown is manual-only and shares the existing safe renderer with Text panels.
Text, JSON, SQL, XML, HTML source, and Markdown source use the shared CodeMirror viewer.
Only one active viewer exists per drawer.
Active viewer and formatting request are destroyed/aborted on every transition and close.
Main and detached document behavior remains correct.
Existing resize, Escape, backdrop, close, and stacking behavior remains correct.
No schema or saved-query migration is required.
No new runtime dependency is added.
Relevant unit and browser tests pass.
npm test passes.
npm run build succeeds.
Definition of done
Clicking a result-table cell opens a structured-content drawer that automatically recognizes common JSON, SQL, HTML, XML, and plain-text values.
JSON is formatted locally. SQL is highlighted immediately and formatted best-effort by the connected ClickHouse server, with exact Raw source always available. The drawer uses the existing read-only CodeMirror viewer, preserves all current drawer lifecycle behavior, and introduces no local SQL formatter.
Problem
Clicking a result-table cell opens the right-side cell-detail drawer, but the drawer currently has only limited presentation logic:
Rendered | Source;{or[is parsed and reindented;<pre>.This is inadequate for common ClickHouse result values such as:
system.query_log.query;statement,create_table_query, or similar fields;A SQL value such as:
currently appears as an unformatted block of plain text even when:
query;formatQuery()path;The drawer should identify common structured content conservatively and present it using the appropriate renderer.
Goal
Turn the cell-detail drawer into a type-aware structured-content viewer with:
The initial supported modes are:
YAML is explicitly out of scope.
Existing foundation
The application already has:
with:
The current
prettyValue():JSON.parse()only for text beginning with{or[;The application also already has:
with a reusable read-only CodeMirror surface.
Supported language identifiers are currently:
Current language behavior:
textjsonsqlxmlhtmlmarkdownThe viewer already provides:
The application injects it through:
The drawer should consume this existing seam rather than constructing another editor/viewer implementation.
Content-analysis model
Replace the current string-only formatting decision with a pure descriptor.
Suggested API:
Suggested return shape:
For valid JSON:
For invalid JSON selected through a type hint or manual mode:
Requirements:
requestedModeoverrides Auto detection.Auto-detection priority
Auto mode must be conservative and deterministic.
Use this priority:
Do not auto-detect Markdown from arbitrary prose.
Markdown remains available through the explicit mode selector.
ClickHouse type hints
JSON-bearing types
Treat the following as JSON-bearing:
Support nested transparent wrappers where valid.
Use the existing ClickHouse type-expression parser or a small projection over it.
Do not classify by broad substring matching such as:
because that can misclassify unrelated type names or malformed expressions.
A JSON-bearing type must stay in JSON mode even when parsing fails.
Do not silently fall back to Text mode.
String-like SQL values
ClickHouse type alone is not enough to identify SQL because SQL commonly arrives as:
Use column name and content signals for SQL.
JSON detection and formatting
Strict JSON document
For a single JSON value:
Support any valid JSON root:
Auto-detection should remain conservative for scalar roots. A scalar should normally require a JSON type hint or manual JSON mode; otherwise ordinary values such as
trueor123should remain Text.JSON Lines / NDJSON
When the source contains multiple non-empty lines and every line independently parses as JSON:
jsonl;Suggested formatted output:
The separator may differ, but records must remain visually distinct.
A single invalid non-empty line makes JSONL parsing fail.
Do not classify arbitrary multi-line prose as JSONL because one line happens to parse.
Invalid JSON
When JSON mode is selected by:
and parsing fails, show:
Example:
Requirements:
role="alert"or equivalent;SQL detection
SQL Auto detection must combine syntax and context.
Do not detect SQL with a broad regular expression such as:
/select|from|where/iThat would misclassify logs, prose, stack traces, and JSON strings.
Reuse the existing SQL lexical infrastructure:
These already understand:
Strong SQL keywords
Treat the following leading keywords as strong SQL signals:
The exact set may reuse existing keyword tables where appropriate.
Ambiguous SQL keywords
These are valid SQL beginnings but can appear in ordinary text:
Require supporting context for these, such as a recognized SQL-bearing column name.
SQL-bearing column names
Treat these names as strong supporting hints, case-insensitively:
Also support common suffix patterns conservatively:
Do not allow a column name alone to classify arbitrary prose as SQL.
Recommended rule:
A multi-statement script is SQL when every non-empty statement has a recognized SQL leading keyword.
SQL source rendering
SQL mode uses the existing read-only CodeMirror viewer:
It must provide:
Do not make the cell value editable.
Do not reuse the main SQL editor with history, completion, schema loading, hover, or drag/drop.
SQL formatting
There will be no local SQL formatter in this issue.
Do not add:
Use ClickHouse itself:
or the existing equivalent helper.
Behavior
When Auto or manual mode resolves to SQL:
Formatting…status;Request requirements
The formatting request must:
formatQuery();Query logging
Formatting a
system.query_log.queryvalue can itself create another query-log entry.Where supported, run the formatter with:
or an equivalent request-level setting.
If the connected user cannot set it, formatting should still work; failure to suppress query logging must not make the feature fail.
Do not use a separate hidden database connection.
Cache
Cache successful formatted SQL for the current page session.
Suggested key:
A bounded cache is sufficient.
Suggested bounds:
Equivalent conservative limits are acceptable.
Do not persist formatted SQL to localStorage or the saved-query Spec.
Size limit
Do not auto-format extremely large SQL values.
Suggested maximum:
For larger values:
Formatting skipped for values over 1 MiB;Formatting result
A successful formatter response must be a non-empty string.
If the server returns:
retain Raw mode and surface a compact status.
Manual mode selector
Add a local drawer mode selector:
The selected value is local drawer state.
It must not:
Manual modes always override Auto detection.
Examples:
Drawer layout
Recommended layout:
The Auto option should expose the resolved mode:
This makes the classification visible without requiring another status label.
Controls by mode
Copy
Copy always copies:
It never copies:
Copy must work in the main drawer and detached Data view.
Wrap
Wrap is local drawer state.
Recommended defaults:
Changing mode may apply the mode default only until the user explicitly changes Wrap during the current drawer session.
HTML
Keep the existing:
behavior.
Rendered mode continues using:
Source mode must use the shared read-only CodeMirror viewer with:
Requirements:
The existing
looksLikeHtml()heuristic remains an Auto signal.XML
XML mode is source-only.
Use:
Provide:
Do not:
XML Auto detection
Auto-detect only strong signals:
HTML detection takes precedence over XML when the content looks like HTML.
Markdown
Markdown is never auto-detected from arbitrary text.
Manual Markdown mode provides:
Rendered mode must reuse the application’s existing safe Markdown implementation.
The application already has:
and a DOM renderer currently associated with Text panels.
Extract the renderer to a shared module, for example:
Suggested exports:
renderMarkdownText()must call the existing parser.Then:
renderMarkdownText();renderMarkdownText().Preserve the current Markdown-lite security and feature contract:
Markdown Source uses the CodeMirror viewer with:
It may remain plain source highlighting unless a dedicated Markdown language package is added separately.
Text
Text mode uses the shared CodeMirror viewer with:
This covers:
Do not use a plain
<pre>for the new source path.The viewer provides consistent:
Lifecycle
The drawer owns at most:
Before:
perform the required teardown:
Viewer destruction must be explicit and idempotent.
A late formatting response must not modify a closed drawer or a drawer that has switched to another cell/mode.
Use a generation token or request identity guard in addition to
AbortController.Existing drawer behavior to preserve
Keep the existing:
No change to table-cell click behavior.
Suggested implementation
src/core/cell.jsReplace or extend
prettyValue()with:Retain
looksLikeHtml().Compatibility helper functions may remain if other callers use them.
src/ui/results.jsRefactor
openCellDetail()to own:Avoid putting detection logic directly into this UI module.
src/editor/code-viewer.jsConsume the existing API.
Only extend it if the drawer requires a narrowly reusable capability such as:
Do not add application state or formatting logic to the viewer.
src/ui/markdown-view.jsExtract the existing safe Markdown DOM renderer.
Both Text panels and cell-detail Markdown rendering must use it.
SQL formatter helper
Add a focused helper in an appropriate network/core boundary, for example:
or an app action:
It must not reuse the active editor action if that action:
The helper should only return:
or throw a normal request error.
Error behavior
JSON error
Show:
with
role="alert".Keep Raw visible.
SQL formatting error
Show a non-blocking compact message:
Do not use
role="alert"unless the interaction requires it.Do not expose the complete authorization/token response body.
Viewer failure
If CodeMirror construction fails unexpectedly:
<pre>;This is a defensive fallback, not the normal path.
Performance
Requirements:
The drawer must remain responsive for values up to at least 1 MiB.
Accessibility
Requirements:
role="status"or equivalent;Files
Expected changes:
Expected tests:
Add focused browser coverage for:
No schema change.
No saved-query migration.
No new runtime dependency.
No local SQL formatter.
Tests
Auto classification
Verify:
query+SELECT ...resolves to SQL;statement+CREATE TABLE ...resolves to SQL;view_query+WITH ... SELECT ...resolves to SQL;selectremains Text;WITHremains Text unless column context supports SQL;JSON
Verify:
SQL formatting
Verify:
log_queries=0is attempted where configured;Manual overrides
Verify every selector mode:
Manual selection must override Auto without modifying the source.
CodeMirror
Verify correct language IDs:
Verify:
HTML
Verify:
XML
Verify:
Markdown
Verify:
Existing drawer behavior
Verify:
Non-goals
Do not include:
Acceptance criteria
formatQuery().npm testpasses.npm run buildsucceeds.Definition of done
Clicking a result-table cell opens a structured-content drawer that automatically recognizes common JSON, SQL, HTML, XML, and plain-text values.
JSON is formatted locally. SQL is highlighted immediately and formatted best-effort by the connected ClickHouse server, with exact Raw source always available. The drawer uses the existing read-only CodeMirror viewer, preserves all current drawer lifecycle behavior, and introduces no local SQL formatter.