A rehype plugin that applies lightweight syntax highlighting to inline <code> elements without adding line gutters, frame wrappers, or precomputed data attributes.
The transformHtmlCodeInlineHighlighted plugin transforms plain inline code into beautifully syntax-highlighted code using Starry Night. Unlike transformHtmlCodePrecomputed, this plugin is optimized for inline code snippets and type expressions.
data-highlighting-prefix attribute for proper type contextclassName attribute (e.g., language-ts)This plugin is part of @mui/internal-docs-infra and doesn't need separate installation.
import { unified } from 'unified';
import rehypeParse from 'rehype-parse';
import rehypeStringify from 'rehype-stringify';
import transformHtmlCodeInlineHighlighted from '@mui/internal-docs-infra/pipeline/transformHtmlCodeInlineHighlighted';
const processor = unified()
.use(rehypeParse, { fragment: true })
.use(transformHtmlCodeInlineHighlighted)
.use(rehypeStringify);
const result = await processor.process('<code class="language-ts">string | number</code>');
console.log(String(result));
// Output: <code class="language-ts"><span class="pl-c1">string</span> | <span class="pl-c1">number</span></code>
For type expressions that need context for proper highlighting:
const html = `
<code class="language-ts" data-highlighting-prefix="type _ = ">
{ foo: string; bar: number }
</code>
`;
const result = await processor.process(html);
// The prefix is used during highlighting but removed from output:
// <code class="language-ts">
// <span class="pl-k">{</span> foo<span class="pl-k">:</span> <span class="pl-c1">string</span><span class="pl-k">;</span> ...
// </code>
The plugin automatically initializes Starry Night on first use. This means:
globalThis for sharing across all processingThe plugin supports all languages defined in grammars.ts:
.ts, .tsx).js, .jsx).css).html).json).md).sh, .bash).yaml, .yml)<code> elements in the HAST treedata-highlighting-prefix attribute if presentdata-highlighting-prefix attributeThe removePrefixFromHighlightedNodes helper removes prefix characters by:
// Input
<code class="language-ts">boolean</code>
// Output
<code class="language-ts"><span class="pl-c1">boolean</span></code>
// Input
<code class="language-ts">string | number | boolean</code>
// Output
<code class="language-ts">
<span class="pl-c1">string</span> <span class="pl-k">|</span> <span class="pl-c1">number</span> <span class="pl-k">|</span> <span class="pl-c1">boolean</span>
</code>
// Input
<code class="language-ts" data-highlighting-prefix="type _ = ">
{ foo: string }
</code>
// Highlighted with prefix: "type _ = { foo: string }"
// Prefix removed from output: "{ foo: string }"
// Output
<code class="language-ts">
<span class="pl-k">{</span> foo<span class="pl-k">:</span> <span class="pl-c1">string</span> <span class="pl-k">}</span>
</code>
// Input
<code class="language-ts" data-highlighting-prefix="type _ = ">
(event: React.MouseEvent) => void
</code>
// Output
<code class="language-ts">
((<span class="pl-v">event</span><span class="pl-k">:</span> <span class="pl-en">React</span>.<span class="pl-en">MouseEvent</span>) <span class="pl-k">=></span> <span class="pl-c1">void</span>)
</code>
Highlight type expressions in API documentation:
const processor = unified().use(transformHtmlCodeInlineHighlighted);
// Highlight prop types
await processor.process('<code class="language-ts">string | number</code>');
// Highlight complex types
await processor.process(
'<code class="language-ts" data-highlighting-prefix="type _ = ">{ foo: string; bar: number }</code>',
);
Apply highlighting to inline code in HTML tables:
<table>
<tr>
<th>Prop</th>
<th>Type</th>
</tr>
<tr>
<td>variant</td>
<td><code class="language-ts">'primary' | 'secondary'</code></td>
</tr>
<tr>
<td>onChange</td>
<td>
<code class="language-ts" data-highlighting-prefix="type _ = ">
(event: React.ChangeEvent) => void
</code>
</td>
</tr>
</table>
Highlight type expressions in programmatically generated documentation:
const typeCell = `<code class="language-ts" data-highlighting-prefix="type _ = ">${propType}</code>`;
// propType might be: "{ value: string; onChange: (v: string) => void }"
// The prefix ensures proper object/function type highlighting
function transformHtmlCodeInlineHighlighted(): (tree: Root) => Promise<void>;
Returns a unified transformer that highlights <code> elements.
Parameters: None
Returns: A transformer function that processes the HAST tree
Side Effects:
globalThis.__docs_infra_starry_night_instance__The plugin uses a lazy singleton Starry Night instance stored in globalThis:
const STARRY_NIGHT_KEY = '__docs_infra_starry_night_instance__';
async function getStarryNight(): Promise<StarryNight> {
if (!(globalThis as any)[STARRY_NIGHT_KEY]) {
(globalThis as any)[STARRY_NIGHT_KEY] = await createStarryNight(grammars);
}
return (globalThis as any)[STARRY_NIGHT_KEY];
}
Benefits:
The data-highlighting-prefix attribute solves a key challenge: TypeScript types need context for proper syntax highlighting.
Problem: Highlighting string | number in isolation may not recognize it as a type expression.
Solution: Add context prefix type _ = string | number, highlight the complete string, then remove the prefix.
Example:
// Without prefix: may highlight incorrectly
<code class="language-ts">{ foo: string }</code>
// With prefix: highlights as proper type
<code class="language-ts" data-highlighting-prefix="type _ = ">
{ foo: string }
</code>
// After processing: prefix removed but highlighting preserved
<code class="language-ts">
<span class="pl-k">{</span> foo<span class="pl-k">:</span> ...
</code>
Optimization: The plugin only processes <code> elements with language classes, skipping:
class="language-*"| Feature | transformHtmlCodeInlineHighlighted | transformHtmlCodePrecomputed |
|---|---|---|
| Use case | Inline code snippets | Multi-line code blocks |
| Line gutters | No | Yes |
| Frame wrapper | No | Yes |
| Data attributes | No | Yes (dataPrecompute) |
| Prefix support | Yes | No |
| Performance | Fast | Slower (more features) |
| Output size | Smaller | Larger |
When to use transformHtmlCodeInlineHighlighted:
When to use transformHtmlCodePrecomputed:
// ✓ Good: Minimal prefix for context
<code class="language-ts" data-highlighting-prefix="type _ = ">
string | number
</code>
// ✗ Bad: Long unnecessary prefix
<code class="language-ts" data-highlighting-prefix="export type MyVeryLongTypeName = ">
string | number
</code>
// ✓ Good: Explicit language
<code class="language-ts">string</code>
// ✗ Bad: No language (won't highlight)
<code>string</code>
// ✓ Good: Short inline code
<code class="language-ts">string | number</code>
// ✗ Bad: Multi-line code (use transformHtmlCodePrecomputed)
<code class="language-ts">
function example() {
// 50 lines of code
}
</code>
Problem: Code remains plain text without highlighting.
Solutions:
Check language class exists:
<!-- ✓ Good -->
<code class="language-ts">string</code>
<!-- ✗ Bad: missing class -->
<code>string</code>
Confirm language is supported:
// Supported: ts, js, tsx, jsx, css, html, json, md, sh, yaml
// Unsupported: python, ruby, go, rust
Problem: Prefix appears in output.
Solutions:
Verify attribute name is exact:
<!-- ✓ Good -->
<code data-highlighting-prefix="type _ = ">string</code>
<!-- ✗ Bad: wrong attribute name -->
<code data-prefix="type _ = ">string</code>
Check prefix length matches actual characters:
// Prefix removal counts characters, not bytes
// "type _ = " is 9 characters (including spaces)
Problem: Highlighting differs from expected.
Solutions:
Add appropriate prefix for context:
<!-- Without prefix: might highlight as variable -->
<code class="language-ts">{ foo: string }</code>
<!-- With prefix: highlights as type -->
<code class="language-ts" data-highlighting-prefix="type _ = "> { foo: string } </code>
Check language matches content:
<!-- ✗ Bad: JSX with wrong language -->
<code class="language-js"><button /></code>
<!-- ✓ Good: JSX with correct language -->
<code class="language-tsx"><button /></code>
transformHtmlCodePrecomputed - For multi-line code blocks with line guttersparseSource - Underlying syntax highlighting functionformatProperties - Uses this for type highlighting