fix(core): pass markdown fg through to table cells (#1503)

Fixes #1432.

`MarkdownRenderable` passes its `fg` to prose, code blocks and quotes,
but not to tables, so table text always comes out in
`TextTableRenderable`'s `#FFFFFF` default.

- pass `fg` when the table is created and when table options are
re-applied
- add an `fg` setter to `TextTableRenderable` that updates existing
cells, so changing `fg` on the markdown later recolours the table too
(the style rerender reuses the table, so a constructor option alone
isn't enough)

Added a test that checks header and body cells use the markdown `fg`,
then changes it. It fails on `main` and passes with this. `bun test
src/renderables` and `bun run typecheck` pass locally (Windows, prebuilt
0.5.11 native lib).
This commit is contained in:
Yusuf Efe
2026-09-15 21:35:52 +03:00
committed by GitHub
parent 0491dc19e9
commit f532fa7b2b
3 changed files with 44 additions and 0 deletions
@@ -223,6 +223,7 @@ interface ResolvedTableRenderableOptions {
showBorders: boolean
borderStyle: BorderStyle
borderColor: ColorInput
fg?: RGBA
selectable: boolean
}
@@ -1514,6 +1515,7 @@ export class MarkdownRenderable extends Renderable {
showBorders: borders,
borderStyle: this._tableOptions?.borderStyle ?? "single",
borderColor: this._tableOptions?.borderColor ?? this.getStyle("conceal")?.fg ?? "#888888",
fg: this._fg,
selectable: this._tableOptions?.selectable ?? true,
}
}
@@ -1533,6 +1535,7 @@ export class MarkdownRenderable extends Renderable {
tableRenderable.showBorders = options.showBorders
tableRenderable.borderStyle = options.borderStyle
tableRenderable.borderColor = options.borderColor
tableRenderable.fg = options.fg
tableRenderable.selectable = options.selectable
}
@@ -1575,6 +1578,7 @@ export class MarkdownRenderable extends Renderable {
showBorders: options.showBorders,
borderStyle: options.borderStyle,
borderColor: options.borderColor,
fg: options.fg,
selectable: options.selectable,
})
this._ownedStructuredRenderables.add(table)
@@ -337,6 +337,22 @@ export class TextTableRenderable extends Renderable {
this.invalidateRasterOnly()
}
public get fg(): RGBA {
return this._defaultFg
}
public set fg(value: ColorInput | undefined) {
const next = parseColor(value ?? this._defaultOptions.fg)
if (this._defaultFg.equals(next)) return
this._defaultFg = next
for (const row of this._cells) {
for (const cell of row) {
cell.textBuffer.setDefaultFg(next)
}
}
this.invalidateRasterOnly()
}
public shouldStartSelection(x: number, y: number): boolean {
if (!this.selectable) return false
@@ -1903,6 +1903,30 @@ test("blockquote updates quote text and bar colors when syntaxStyle changes", as
expect(findSpanContaining(captureSpans(), "Quote text")?.fg?.toInts()).toEqual(quoteColor2.toInts())
})
test("table cells use the markdown fg and follow fg changes", async () => {
const fg1 = RGBA.fromValues(0.25, 0.5, 0.75, 1)
const fg2 = RGBA.fromValues(0.75, 0.5, 0.25, 1)
const md = createMarkdownRenderable({
id: "markdown-table-fg",
content: "| Head |\n| --- |\n| Cell |",
syntaxStyle: SyntaxStyle.fromStyles({}),
fg: fg1,
})
renderer.root.add(md)
await renderMarkdownRenderable(md)
expect(md._blockStates[0]?.renderable).toBeInstanceOf(TextTableRenderable)
expect(findSpanContaining(captureSpans(), "Head")?.fg?.toInts()).toEqual(fg1.toInts())
expect(findSpanContaining(captureSpans(), "Cell")?.fg?.toInts()).toEqual(fg1.toInts())
md.fg = fg2
renderer.requestRender()
await renderMarkdownRenderable(md)
expect(findSpanContaining(captureSpans(), "Head")?.fg?.toInts()).toEqual(fg2.toInts())
expect(findSpanContaining(captureSpans(), "Cell")?.fg?.toInts()).toEqual(fg2.toInts())
})
test("fenced diff blocks color added and removed lines", async () => {
const mockTreeSitterClient = createMockTreeSitterClient()
mockTreeSitterClient.setMockResult({