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
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
A richtext value renders as a BLANK grid cell — the type is routed to MarkdownCellRenderer, whose pipeline drops the stored HTML #5452
Found while measuring objectui#5415 (record-grid row heights); a different defect class, filed separately and not fixed there.
Measured
Real browser (Chromium, apps/console vite dev, ObjectGrid with inline data and a mock getObjectSchema). One row, one column, the stored value is the showcase seed's own richtext specimen (examples/app-showcase/src/data/seed/index.ts, f_richtext):
value stored: p-wrapped Rich + strong-wrapped text
column field type
cell textContent
cell inner HTML
richtext
"" (empty)
div.prose … empty
html
Rich text
div.prose containing the real p / strong markup
markdown (control, markdown-shaped input **bold** and _em_)
bold and em
rendered markup
So a populated richtext field shows the user nothing at all in a grid cell. Neighbouring html — same stored bytes, different declared type — renders it correctly, which is what rules out "the value never arrived".
Mechanism
packages/fields/src/index.tsx, getCellRenderer's standard map:
markdown: MarkdownCellRenderer,
html: HtmlCellRenderer,
richtext: MarkdownCellRenderer, <-- here
richtext stores HTML (that is what RichTextField writes, and what the showcase seed carries), but it is dispatched to the markdown renderer, which hands the string to the sanitizing GFM pipeline (MarkdownContent). Raw HTML is dropped there, and since the value is entirely HTML, everything is dropped and the cell renders empty. The title attribute on the shared cell wrapper still carries the raw string, so the value is reachable on hover — which is why this reads as a styling nit rather than data loss until you look at the cell body.
HtmlCellRenderer already exists two functions below and handles exactly this shape (it sanitizes with sanitizeHtml and keeps the markup).
Why it matters
Failure direction is the bad one: no error, no fallback, no console warning — a populated field reads as an empty field. Anyone auditing data through a grid concludes the records are blank.
Note
Do not "fix" this by making the markdown pipeline pass raw HTML through — that would change every markdown cell's trust boundary. The question is which renderer richtext should map to, and that is a one-line decision in the map above (plus whatever the read side of the detail page does with the same type — not checked here).
Repro harness was untracked and removed; it is ~40 lines of ObjectGrid with data: { provider: 'value', items } plus a getObjectSchema stub, following the existing apps/console/src/dev/DevRowActions.tsx pattern.
Triage: queued, type Bug — a populated richtext field renders as an empty grid cell (silent data-invisibility, measured with an html-typed control on the same bytes). Fix locus is the getCellRenderer map in packages/fields/src/index.tsx; the body's ⛔ (do not loosen the markdown pipeline's trust boundary) is the load-bearing constraint, and the detail-page read side of the same type should be checked in the same diff. Size/model suggestion: S, sonnet.
Activity
os-zhuang commentedon Aug 21, 2026
Triage: queued, type Bug — a populated
richtextfield renders as an empty grid cell (silent data-invisibility, measured with anhtml-typed control on the same bytes). Fix locus is thegetCellRenderermap inpackages/fields/src/index.tsx; the body's ⛔ (do not loosen the markdown pipeline's trust boundary) is the load-bearing constraint, and the detail-page read side of the same type should be checked in the same diff. Size/model suggestion: S, sonnet.Generated by Claude Code
Route `richtext` cells to the HTML renderer, not the markdown one (ob…