Warning
This is an internal project, and is not intended for public use. No support or stability guarantees are provided.
The enhanceCodeEmphasis source enhancer adds visual emphasis to specific lines in code examples by marking them with a data-hl attribute. This allows you to highlight important code patterns or call attention to specific sections in demos using simple comment annotations.
@highlight comments@highlight-start / @highlight-end pairs@highlight-text "text"@highlight "description")! at the end of descriptions (e.g., @highlight "We must do this!")import { enhanceCodeEmphasis } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis';
// Use as a source enhancer
const sourceEnhancers = [enhanceCodeEmphasis];
// Pass to CodeHighlighter or use with enhanceCode
The enhancer processes @highlight comments in your source files and adds data-hl to the corresponding line elements in the HAST tree.
Emphasize the line containing the comment:
export default function Button() {
return (
<button className="primary">Click me</button> {/* @highlight */}
);
}
The line with the <button> element will be emphasized.
Add context about what's being emphasized:
export default function Component() {
const [count, setCount] = useState(0); // @highlight "We track state"
return <div>{count}</div>;
}
End a description with ! to mark it as strong emphasis (data-hl="strong"):
export default function Component() {
const apiKey = process.env.API_KEY; // @highlight "We must provide the API key!"
return <div>...</div>;
}
Strong emphasis is useful for highlighting critical code that users must pay attention to or modify.
Emphasize a range of lines between start and end markers:
export default function Component() {
return (
// @highlight-start
<div>
<h1>Heading 1</h1>
<p>Some content</p>
</div>
// @highlight-end
);
}
Lines 4-7 (from <div> through </div>) will be emphasized. The range starts at the first line after @highlight-start and ends at the last line before @highlight-end.
Explain what the emphasized section demonstrates:
export default function Component() {
return (
// @highlight-start "We add a heading with an h1"
<div>
<h1>Heading 1</h1>
</div>
// @highlight-end
);
}
Highlight specific text within a line:
export default function Component() {
return (
<div>
<h1>Heading 1</h1> {/* @highlight-text "Heading 1" */}
</div>
);
}
This wraps the specified text in a <span data-hl=""> element, allowing you to highlight a specific word or phrase within a line rather than the entire line.
The enhancer recognizes these comment patterns:
| Pattern | Effect |
|---|---|
@highlight | Emphasize current line |
@highlight "description" | Emphasize with description |
@highlight-start | Start multi-line block |
@highlight-start "desc" | Start block with description |
@highlight-end | End multi-line block |
@highlight-text "text" | Highlight specific text within the line |
Descriptions are provided as quoted strings:
// @highlight "We initialize the state"
const [value, setValue] = useState(0);
// @highlight-start "We render the component"
<div>
<p>Content</p>
</div>;
// @highlight-end
By default, @highlight comments are stripped from the rendered code. To show the comment syntax in documentation (while still applying the emphasis), use the displayComments code block attribute:
```jsx displayComments
export default function Button() {
return (
<button className="primary">Click me</button> {/* @highlight */}
);
}
```
This is useful for documentation pages where you want to show users the comment syntax itself.
You can emphasize multiple individual lines:
export default function Form() {
const [name, setName] = useState(''); // @highlight
const [email, setEmail] = useState(''); // @highlight
return (
<form>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={email} onChange={(e) => setEmail(e.target.value)} /> {/* @highlight */}
</form>
);
}
The enhancer handles nested emphasis blocks using a stack-based algorithm. Lines that fall within multiple emphasis ranges are automatically marked with strong emphasis (data-hl="strong"):
export default function Component() {
return (
// @highlight-start "outer block"
<div>
<header>Title</header>
{/* @highlight-start "inner block" */}
<main>
<p>Content</p>
</main>
{/* @highlight-end */}
<footer>Footer</footer>
</div>
// @highlight-end
);
}
In this example:
<div>, <header>, <footer>, </div>) get normal emphasis<main>, <p>, </main>) get strong emphasis because they're nested within both rangesdata-hl-position) are preserved from the innermost rangeCombine both patterns in the same file:
export default function Dashboard() {
const [data, setData] = useState([]); // @highlight
return (
<div>
<Header />
{/* @highlight-start */}
<Chart data={data} />
<Table data={data} />
{/* @highlight-end */}
<Footer /> {/* @highlight */}
</div>
);
}
When any emphasis is present, the enhancer splits the code block's frame structure around highlighted lines. Each original frame is broken into typed sub-frames that CSS can target for collapsing, animating, or scrolling to the focused area.
Given a 7-line code block where line 4 is highlighted, the frames are restructured:
| Frame # | Lines | data-frame-type |
|---|---|---|
| 1 | 1–3 | (none) |
| 2 | 4 | highlighted |
| 3 | 5–7 | (none) |
When padding is configured (see Configurable Padding), additional typed frames surround the focused highlight region:
| Frame # | Lines | data-frame-type |
|---|---|---|
| 1 | 1 | (none) |
| 2 | 2–3 | padding-top |
| 3 | 4 | highlighted |
| 4 | 5–6 | padding-bottom |
| 5 | 7 | (none) |
| Attribute | Type | Description |
|---|---|---|
data-frame-type | string | "highlighted" (focused region), "highlighted-unfocused" (non-focused regions), "padding-top", or "padding-bottom". Normal frames have no type attribute. |
data-frame-indent | number | Only on highlighted and highlighted-unfocused frames. The shared indent level of the highlighted lines (min leading spaces ÷ 2). |
Use createEnhanceCodeEmphasis to configure padding frames around the focused highlight region:
import { createEnhanceCodeEmphasis } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis';
const sourceEnhancers = [
createEnhanceCodeEmphasis({
paddingFrameMaxSize: 3,
focusFramesMaxSize: 10,
}),
];
| Option | Type | Default | Description |
|---|---|---|---|
paddingFrameMaxSize | number | 0 | Maximum number of context lines above/below the focused region |
focusFramesMaxSize | number | — | Maximum total lines in the focus area (padding + highlighted). Remaining budget is split floor/ceil (extra line goes to bottom). |
When paddingFrameMaxSize is 0 (the default), no padding frames are created and only highlighted and normal frames are produced.
@focus DirectiveWhen multiple highlight regions exist, padding is added around the first region by default. Add @focus to override which region receives padding:
const theme = getTheme(); // @highlight
const config = getConfig();
// @highlight-start @focus
<ThemeProvider theme={theme}>
<App config={config} />
</ThemeProvider>;
// @highlight-end
In this example, @focus directs the padding frames to surround the ThemeProvider block instead of the theme line.
@focus can be combined with any highlight directive:
// @highlight @focus// @highlight-start @focus// @highlight-start @focus "We render the provider"Target frame types with CSS to create collapsible code blocks:
/* Normal frames and unfocused highlighted frames are hidden by default (collapsed) */
.codeBlock .frame:not([data-frame-type]),
.codeBlock .frame[data-frame-type='highlighted-unfocused'] {
max-height: 0;
overflow: hidden;
opacity: 0;
transition:
max-height 0.3s ease,
opacity 0.3s ease;
}
/* Padding frames appear dimmed when collapsed */
.codeBlock .frame[data-frame-type='padding-top'],
.codeBlock .frame[data-frame-type='padding-bottom'] {
opacity: 0.5;
transition: opacity 0.3s ease;
}
/* When expanded, show all frames */
.expanded .codeBlock .frame:not([data-frame-type]),
.expanded .codeBlock .frame[data-frame-type='highlighted-unfocused'] {
max-height: 500px;
overflow: visible;
opacity: 1;
}
.expanded .codeBlock .frame[data-frame-type='padding-top'],
.expanded .codeBlock .frame[data-frame-type='padding-bottom'] {
opacity: 1;
}
/* Use indent level to shift highlighted frames left when collapsed */
.codeBlock .frame[data-frame-type='highlighted'] {
transition: margin-left 0.3s ease;
}
.codeBlock .frame[data-frame-type='highlighted'][data-frame-indent='1'] {
margin-left: -2ch;
}
.codeBlock .frame[data-frame-type='highlighted'][data-frame-indent='2'] {
margin-left: -4ch;
}
/* Reset indent shift when expanded */
.expanded .codeBlock .frame[data-frame-type='highlighted'] {
margin-left: 0;
}
The following demo shows a code block that starts collapsed, revealing only the highlighted and padding frames. Click Expand to show the full source.
import * as React from 'react';
import { fetchUser } from './api';
interface User {
name: string;
email: string;
}
export function UserProfile({ id }: { id: string }) {
const [user, setUser] = React.useState<User | null>(null);
React.useEffect(() => {
let cancelled = false;
fetchUser(id).then((data) => {
if (!cancelled) {
setUser(data);
}
});
return () => {
cancelled = true;
};
}, [id]);
if (!user) {
return <p>Loading...</p>;
}
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}import * as React from 'react';
import type { Code as CodeType } from '@mui/internal-docs-infra/CodeHighlighter/types';
import { parseImportsAndComments } from '@mui/internal-docs-infra/pipeline/loaderUtils';
import { EMPHASIS_COMMENT_PREFIX } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis';
import { Code } from './Code';
const source = `import * as React from 'react';
import { fetchUser } from './api';
interface User {
name: string;
email: string;
}
export function UserProfile({ id }: { id: string }) {
const [user, setUser] = React.useState<User | null>(null);
// @highlight-start
React.useEffect(() => {
let cancelled = false;
fetchUser(id).then((data) => {
if (!cancelled) {
setUser(data);
}
});
return () => {
cancelled = true;
};
}, [id]);
// @highlight-end
if (!user) {
return <p>Loading...</p>;
}
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}`;
export async function CollapsibleCode() {
const { code: strippedSource, comments } = await parseImportsAndComments(source, '/demo.tsx', {
removeCommentsWithPrefix: [EMPHASIS_COMMENT_PREFIX],
notableCommentsPrefix: [EMPHASIS_COMMENT_PREFIX],
});
const code: CodeType = {
Default: {
language: 'tsx',
source: strippedSource!,
comments,
},
};
return <Code code={code} />;
}
When there are multiple highlight regions, @focus controls which region receives padding frames. In this demo, the useEffect block on the second region is focused — its surrounding lines get padding frames while the first region (formatDate call) does not.
import * as React from 'react';
import { formatDate } from './formatDate';
import { fetchEvents } from './fetchEvents';
const today = formatDate(new Date());
export function Calendar() {
const [events, setEvents] = React.useState([]);
React.useEffect(() => {
fetchEvents(today).then(setEvents);
}, []);
return (
<div className="calendar">
<h2>{today}</h2>
<ul>
{events.map((event) => (
<li key={event.id}>{event.title}</li>
))}
</ul>
</div>
);
}import * as React from 'react';
import type { Code as CodeType } from '@mui/internal-docs-infra/CodeHighlighter/types';
import { parseImportsAndComments } from '@mui/internal-docs-infra/pipeline/loaderUtils';
import { EMPHASIS_COMMENT_PREFIX } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis';
import { Code } from './Code';
const source = `import * as React from 'react';
import { formatDate } from './formatDate';
import { fetchEvents } from './fetchEvents';
const today = formatDate(new Date()); // @highlight
export function Calendar() {
const [events, setEvents] = React.useState([]);
// @highlight-start @focus
React.useEffect(() => {
fetchEvents(today).then(setEvents);
}, []);
// @highlight-end
return (
<div className="calendar">
<h2>{today}</h2>
<ul>
{events.map((event) => (
<li key={event.id}>{event.title}</li>
))}
</ul>
</div>
);
}`;
export async function FocusCode() {
const { code: strippedSource, comments } = await parseImportsAndComments(source, '/demo.tsx', {
removeCommentsWithPrefix: [EMPHASIS_COMMENT_PREFIX],
notableCommentsPrefix: [EMPHASIS_COMMENT_PREFIX],
});
const code: CodeType = {
Default: {
language: 'tsx',
source: strippedSource!,
comments,
},
};
return <Code code={code} />;
}
With no padding configured, only highlighted and normal frames are produced. The data-frame-indent attribute on highlighted frames tells CSS how far the code is indented. This demo highlights an import statement (indent 0) and the deeply nested <DatePicker> usage (indent 3). When collapsed, the JSX frame shifts left by 6ch so it aligns with the left edge, then resets when expanded.
import * as React from 'react';
import { DatePicker } from './DatePicker';
export function ScheduleView() {
const [date, setDate] = React.useState(null);
return (
<main>
<header>
<h1>Schedule</h1>
</header>
<section>
<form>
<label htmlFor="date">Pick a date</label>
<DatePicker
id="date"
value={date}
onChange={setDate}
minDate={new Date()}
format="MM/dd/yyyy"
/>
</form>
</section>
<footer>
<p>All times shown in UTC</p>
</footer>
</main>
);
}import * as React from 'react';
import type { Code as CodeType } from '@mui/internal-docs-infra/CodeHighlighter/types';
import { parseImportsAndComments } from '@mui/internal-docs-infra/pipeline/loaderUtils';
import { EMPHASIS_COMMENT_PREFIX } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis';
import { CodeIndent } from './CodeIndent';
const source = `import * as React from 'react';
import { DatePicker } from './DatePicker'; // @highlight
export function ScheduleView() {
const [date, setDate] = React.useState(null);
return (
<main>
<header>
<h1>Schedule</h1>
</header>
<section>
<form>
<label htmlFor="date">Pick a date</label>
{/* @highlight-start @focus */}
<DatePicker
id="date"
value={date}
onChange={setDate}
minDate={new Date()}
format="MM/dd/yyyy"
/>
{/* @highlight-end */}
</form>
</section>
<footer>
<p>All times shown in UTC</p>
</footer>
</main>
);
}`;
export async function IndentCode() {
const { code: strippedSource, comments } = await parseImportsAndComments(source, '/demo.tsx', {
removeCommentsWithPrefix: [EMPHASIS_COMMENT_PREFIX],
notableCommentsPrefix: [EMPHASIS_COMMENT_PREFIX],
});
const code: CodeType = {
Default: {
language: 'tsx',
source: strippedSource!,
comments,
},
};
return <CodeIndent code={code} />;
}
notableCommentsPrefix: ['@highlight']@highlight, @highlight-start, @highlight-end, and @highlight-text patterns@highlight-start to the last line before @highlight-enddataHl: '' (or dataHl: 'strong' for nested lines or descriptions ending with !) to line elementsLines in the HAST tree have this structure after enhancement:
{
type: 'element',
tagName: 'span',
properties: {
className: 'line',
dataLn: 3, // Line number
dataHl: '', // Added by enhancer (or 'strong' for nested/!)
dataHlDescription: 'We track state', // Optional description
dataHlPosition: 'single', // 'single' | 'start' | 'end' for line position
},
children: [/* code tokens */]
}
For text highlighting with @highlight-text "text", the specified text within the line is wrapped in a span:
{
type: 'element',
tagName: 'span',
properties: { dataHl: '' },
children: [{ type: 'text', value: 'text' }]
}
The enhancer adds these attributes to line elements:
| Attribute | Type | Description |
|---|---|---|
data-hl | string | "" for normal, "strong" if description ends with ! or line is nested |
data-hl-description | string | Description text (if provided in comment) |
data-hl-position | string | "single" for single-line, "start" or "end" for multiline range bounds (from innermost range) |
For single-line emphasis with @highlight:
data-hl is set (or data-hl="strong" if description ends with !)data-hl-description is set if a description was provideddata-hl-position="single" is set to distinguish from multiline range boundariesFor multi-line emphasis with @highlight-start / @highlight-end:
data-hl is set on all lines in the range (or data-hl="strong" if description ends with ! or line is nested)data-hl-description is set on the first line (if provided)data-hl-position="start" is set on the first line (only for ranges with more than one line)data-hl-position="end" is set on the last line (only for ranges with more than one line)For text highlighting with @highlight-text "text":
<span data-hl=""> elementMulti-line directives are paired using a stack:
@highlight-start pushes onto the stack@highlight-end pops from the stack and emphasizes the rangeConfigure in your webpack loader or server-side loading:
import { enhanceCodeEmphasis } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis';
import { createLoadServerSource } from '@mui/internal-docs-infra/pipeline/loadServerSource';
import { loadCodeVariant } from '@mui/internal-docs-infra/pipeline/loadCodeVariant';
const sourceEnhancers = [enhanceCodeEmphasis];
For configurable padding, use the factory:
import { createEnhanceCodeEmphasis } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis';
const sourceEnhancers = [
createEnhanceCodeEmphasis({
paddingFrameMaxSize: 3,
focusFramesMaxSize: 10,
}),
];
Then pass to your loading pipeline:
// Create a loadSource that extracts emphasis comments
const loadSource = createLoadServerSource({
notableCommentsPrefix: ['@highlight'],
removeCommentsWithPrefix: ['@highlight'],
});
// Use with loadCodeVariant
const { code } = await loadCodeVariant(url, variantName, variant, {
loadSource,
sourceEnhancers,
sourceParser,
});
// Or with CodeHighlighter
<CodeHighlighter
sourceEnhancers={sourceEnhancers}
// ... other props
/>
// Or with useCode
const { selectedFile } = useCode(props, {
sourceEnhancers,
});
The default comment prefix is @highlight, exported as EMPHASIS_COMMENT_PREFIX:
import { EMPHASIS_COMMENT_PREFIX } from '@mui/internal-docs-infra/pipeline/enhanceCodeEmphasis';
console.log(EMPHASIS_COMMENT_PREFIX); // '@highlight'
To use a different prefix, you would need to create a custom enhancer based on this implementation.
The data-hl attribute can be targeted with CSS. First, ensure lines are displayed as blocks for proper highlighting:
/* Required: Display lines as blocks for line-based highlighting */
.frame[data-lined] {
display: block;
white-space: normal;
}
.frame[data-lined] .line {
display: block;
white-space: pre;
}
/* Highlight emphasized lines */
.line[data-hl] {
background-color: rgba(255, 255, 0, 0.1);
border-left: 2px solid #ffd700;
padding-left: 8px;
}
/* Strong emphasis for critical lines (descriptions ending with !) */
.line[data-hl='strong'] {
background-color: rgba(255, 100, 100, 0.15);
border-left: 3px solid #ff4444;
}
/* Single-line emphasis - rounded on all corners */
.line[data-hl-position='single'] {
border-radius: 4px;
}
/* Multiline block start - rounded top corners */
.line[data-hl-position='start'] {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
/* Multiline block end - rounded bottom corners */
.line[data-hl-position='end'] {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
/* Dark mode variant */
@media (prefers-color-scheme: dark) {
.line[data-hl] {
background-color: rgba(255, 255, 0, 0.05);
border-left-color: #b8860b;
}
.line[data-hl='strong'] {
background-color: rgba(255, 100, 100, 0.1);
border-left-color: #cc3333;
}
}
You can display the description using CSS ::before:
/* Show description as tooltip */
.line[data-hl-description]::before {
content: attr(data-hl-description);
position: absolute;
/* ... tooltip styles */
}
Use single-line emphasis for specific statements:
// ✓ Good - highlights the important line
const result = await fetchData();
// ✗ Avoid - too vague
function processData() {
const result = await fetchData();
return result;
}
Add context when the emphasis isn't obvious:
// ✓ Good - explains what to notice
<div className="container"> {/* @highlight "We add the container class" */}
// ✗ Less helpful - just marks the line
<div className="container"> {/* @highlight */}
Use multi-line emphasis for logical code blocks:
// ✓ Good - emphasizes the complete pattern
// @highlight-start "We handle the form submission"
<form onSubmit={handleSubmit}>
<input type="text" value={name} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
// @highlight-end
Use the appropriate comment style for your language:
// JSX/TSX - use {/* */} for inline, // for block
<div>{/* @highlight */}</div>
// @highlight-start
// JavaScript/TypeScript - use //
const x = 42; // @highlight
// CSS - use /* */
.button {
color: blue; /* @highlight */
}
Check that:
notableCommentsPrefix: ['@highlight']If you have unmatched @highlight-start or @highlight-end:
@highlight-end → ignored (no effect)@highlight-start → ignored (no matching end)Check your code for balanced pairs.
Verify that:
dataLn properties)Default source enhancer that adds emphasis to code lines based on @highlight comments.
Uses no padding frames by default. Use createEnhanceCodeEmphasis for configurable padding.
| Parameter | Type | Description |
|---|---|---|
| root | | |
| comments | | |
| fileName | |
HastRoot | Promise<HastRoot>The prefix used to identify emphasis comments in source code. Comments starting with this prefix will be processed for emphasis.
type EMPHASIS_COMMENT_PREFIX = '@highlight'Metadata for an emphasized line.
type EmphasisMeta = {
/** Optional description for this emphasis */
description?: string;
/** Position: 'single' for single-line, 'start'/'end' for multiline range bounds, undefined for middle */
position?: 'single' | 'start' | 'end';
/** Whether this is a strong emphasis (description ended with !) */
strong?: boolean;
/** For text highlighting: the specific text to highlight within the line */
highlightText?: string;
/** Whether this line's region is the focused region (for padding) */
focus?: boolean;
}Options for the enhance code emphasis factory.
type EnhanceCodeEmphasisOptions = {
/**
* Maximum number of padding lines above and below the focused highlight region.
* Padding frames provide surrounding context for the highlighted code.
* Set to 0 or omit to disable padding frames.
*/
paddingFrameMaxSize?: number;
/**
* Maximum total number of lines in the focus area (padding-top + highlighted + padding-bottom).
* When set, padding sizes are reduced so the total focus area fits within this limit.
* The remainder after subtracting the highlighted size is split: floor(remainder/2) for
* padding-top and ceil(remainder/2) for padding-bottom.
*/
focusFramesMaxSize?: number;
}A range of lines that forms a frame in the output.
type FrameRange = {
/** First line number (1-based, inclusive) */
startLine: number;
/** Last line number (1-based, inclusive) */
endLine: number;
/** The type of frame */
type:
| 'normal'
| 'padding-top'
| 'highlighted'
| 'highlighted-unfocused'
| 'padding-bottom'
| 'comment';
}