Skip to content

Markdown diff fences ignore sugar-high changed-line annotations #2735

Description

@kongenpei

Summary

Thread Markdown renders fenced diff blocks with sugar-high, which emits semantic classes for added, removed, hunk, and metadata lines. bb defines token colors but no CSS for those line classes, so changed lines have the same background as context lines. Added and removed lines should be visually distinct.

Versions and environment

  • Tested against origin/main at f4bbc2fe81a9b7639ff9a7396e172bddd89109e4
  • bb 0.40.0 from source
  • macOS 26.3, Node v24.6.0
  • bb resolves sugar-high@2.0.1; I also checked the current sugar-high@2.1.0
  • Visual check used an isolated Playwriter headless Chromium page with a standalone Vite mini reproduction

Steps to reproduce

  1. Check out f4bbc2fe81a9b7639ff9a7396e172bddd89109e4 and install dependencies.

  2. Render this Markdown in a thread message:

    ```diff
    diff --git a/src/greet.ts b/src/greet.ts
    --- a/src/greet.ts
    +++ b/src/greet.ts
    @@ -1 +1 @@
    -const greeting: string = "hello";
    +const greeting: string = "hello, sugar";
    ```
  3. Inspect the rendered lines. The HTML contains .sh__line--diff-add, .sh__line--diff-remove, .sh__line--diff-hunk, and .sh__line--diff-meta.

  4. Run git grep -n 'sh__line--diff' f4bbc2fe81a9b7639ff9a7396e172bddd89109e4 -- apps/app. It returns no matches.

Minimal code-path check:

pnpm exec tsx -e 'import assert from "node:assert/strict"; import { highlightMarkdownCode } from "./apps/app/src/components/ui/markdown-code-highlight.ts"; const code = "@@ -1 +1 @@\n-const oldValue = true\n+const newValue = false"; const html = highlightMarkdownCode({ code, language: "diff" }); assert.match(html, /sh__line--diff-add/); assert.match(html, /sh__line--diff-remove/); assert.doesNotMatch(html, /sh__token--keyword/); console.log("bb output: diff line annotations present; embedded keyword tokens absent")'

Expected vs actual

Actual:

bb output: diff line annotations present; embedded keyword tokens absent

Standalone browser probe:
default added-line background: rgba(0, 0, 0, 0)
added-line background after applying consumer CSS: rgb(23, 60, 43)
keyword tokens in diff output: 0
keyword tokens in the TypeScript control: 8

The addition, deletion, hunk, metadata, and context rows use the same background in bb.

Expected:

  • .sh__line--diff-add and .sh__line--diff-remove use theme-derived addition and deletion backgrounds.
  • Hunk and metadata rows remain distinguishable without overpowering the code.
  • Add a behavior-focused render test that proves the diff classes receive the intended styles.

The missing nested TypeScript highlighting is separate. sugar-high's diff preset annotates line roles but does not infer a file language or tokenize each line with that language. Fixing that part needs a different renderer or an explicit nested-language design; passing lang: "diff" differently will not provide it.

Evidence

  • bb correctly resolves the fence and calls highlight(code, { lang: resolved }): markdown-code-highlight.ts
  • The Markdown renderer inserts sugar-high's HTML under .bb-code-highlight: markdown-preview.tsx
  • bb's stylesheet defines token variables only: markdown-code-highlight.css
  • sugar-high 2.0.1 adds the diff annotations in its preset: diff.js
  • The standalone mini ran the same fixture against sugar-high 2.0.1 and 2.1.0. Both versions emitted diff annotations and no embedded TypeScript keyword tokens.

What you ruled out

  • Not a duplicate of Shell fences in chat code blocks are lexed as JavaScript #1751. That issue covered fences falling back to the JavaScript lexer; diff now resolves correctly.
  • Still present in the relevant files on origin/main at f4bbc2fe81a9b7639ff9a7396e172bddd89109e4.
  • React Markdown sanitization does not remove the annotations; they are present in the final DOM.
  • Upgrading sugar-high alone does not fix it; 2.1.0 has the same output contract.

Suggested priority and effort

Medium. It affects every fenced diff in thread Markdown and makes reviews slower, but loses no data. Styling the existing line classes should be low effort; nested source-language highlighting is separate work.

AGENT GENERATED

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-reproBug reproduced independently; see linked reportuiApp shell, sidebar, composer, rendering

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions