Warning
This is an internal project, and is not intended for public use. No support or stability guarantees are provided.
A rehype plugin that applies lightweight syntax highlighting to inline <code> elements without adding line gutters, frame wrappers, or precomputed data attributes.
The transformHtmlCodeInline plugin transforms plain inline code into beautifully syntax-highlighted code using Starry Night. Unlike transformHtmlCodeBlock, 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 transformHtmlCodeInline from '@mui/internal-docs-infra/pipeline/transformHtmlCodeInline';
const processor = unified()
.use(rehypeParse, { fragment: true })
.use(transformHtmlCodeInline)
.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(transformHtmlCodeInline);
// 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
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 | transformHtmlCodeInline | transformHtmlCodeBlock |
|---|---|---|
| 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 transformHtmlCodeInline:
When to use transformHtmlCodeBlock:
// ✓ 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 transformHtmlCodeBlock)
<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>
A rehype plugin that applies inline syntax highlighting to code elements. Unlike transformHtmlCodeBlock, this does NOT add line gutters or precomputed data. It’s meant for inline code snippets that should be highlighted but remain lightweight.
Processes code elements and replaces their text content with syntax-highlighted HAST nodes.
| Property | Type | Description |
|---|---|---|
| includePreElements | | When true, also processes code elements inside pre elements. By default, code inside pre is skipped (handled by transformHtmlCodeBlock). When enabled, code inside pre will NOT get the data-inline attribute. |
((tree: Root) => Promise<void>)A unified transformer function
Options for the transformHtmlCodeInline plugin.
type TransformHtmlCodeInlineOptions = {
/**
* When true, also processes code elements inside pre elements.
* By default, code inside pre is skipped (handled by transformHtmlCodeBlock).
* When enabled, code inside pre will NOT get the data-inline attribute.
* @default false
*/
includePreElements?: boolean;
}transformHtmlCodeBlock - For multi-line code blocks with line guttersparseSource - Underlying syntax highlighting functionformatProperties - Uses this for type highlighting