Skip to content

toolcraft-design: add opt-in syntax highlighting for Markdown HTML code fences #437

Description

@kamilio

Summary

toolcraft-design should add lightweight, opt-in syntax highlighting to renderMarkdownHtml for fenced code blocks.

The API should be only an on/off toggle. No modes, themes, inline-style mode, custom callback, or bundled CSS requirement.

Proposed API

renderMarkdownHtml(markdown, { syntaxHighlight: true })

Default behavior stays exactly as it is today:

renderMarkdownHtml(markdown)

continues to render escaped code inside:

<pre><code class="language-js">const x = &quot;hello&quot;;</code></pre>

Desired behavior

When syntaxHighlight: true is set, fenced code blocks should be tokenized based on the fence language and rendered with safe inline <span> wrappers using stable classes:

<pre><code class="language-js"><span class="tc-token-keyword">const</span> x = <span class="tc-token-string">&quot;hello&quot;</span>;</code></pre>

If the consumer provides no CSS, this should still look like normal code because plain <span> elements have no default visual styling. Consumers that want highlighting can style the token classes themselves.

Toolcraft should not need to ship or inject CSS for this feature.

Constraints

  • Default remains off and byte-for-byte behavior should stay as close to current output as practical.
  • The only public configuration should be the boolean toggle.
  • Source text must still be escaped; only Toolcraft-generated <span> wrappers should be emitted as HTML.
  • Do not use tags with default visual styling like <strong>, <em>, <q>, etc. Use neutral spans.
  • Preserve whitespace exactly inside code blocks.
  • Keep it lightweight. Avoid pulling in large grammar/theme systems unless there is a strong reason.

Initial language scope

A simple tokenizer is enough to start. Useful first targets:

  • js, ts, jsx, tsx
  • json
  • yaml, yml
  • css
  • sh, bash
  • python
  • sql

Unknown languages can fall back to the current escaped plain code output.

Why

Consumers like claude-artifacts render Markdown/YAML/CSV/JSON/source files into Claude artifacts using renderMarkdownHtml. The renderer already preserves class="language-*"; adding an opt-in span-based highlighter in Toolcraft keeps the feature in the right layer and avoids consumer-side HTML post-processing.

The key design point: classes mode does not look broken without CSS, because spans are visually neutral. It only becomes highlighted when a consumer stylesheet defines the token classes.

Acceptance criteria

  • renderMarkdownHtml(markdown) keeps current code-block rendering by default.
  • renderMarkdownHtml(markdown, { syntaxHighlight: true }) emits token spans for supported fenced languages.
  • No CSS is automatically bundled, injected, or required.
  • Output remains safe HTML.
  • Tests cover escaping, whitespace preservation, unknown-language fallback, and at least JS plus one data language such as JSON/YAML.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions