Code Block Since v4.1.0
Highlighted code with an optional header, copy button, line numbers and diff lines, for source, commands and output inside messages and traces.
Usage
Requires shiki, @shikijs/langs and @shikijs/themes.
Add provideHighlighter() to your application providers.
import { provideHighlighter } from '@/bui/ui/code-block';
export const appConfig: ApplicationConfig = {
providers: [
provideHighlighter(),
],
};import {
BuiCodeBlock,
BuiCodeBlockActions,
BuiCodeBlockContent,
BuiCodeBlockCopyButton,
BuiCodeBlockFooter,
BuiCodeBlockHeader,
BuiCodeBlockIcon,
BuiCodeBlockLine,
BuiCodeBlockTitle,
} from '@/bui/ui/code-block';<div buiCodeBlock>
<pre buiCodeBlockContent lang="typescript" [code]="code"></pre>
</div> A text size class on buiCodeBlock, such as text-sm, sizes the whole block.
Example
buiCodeBlockHeader holds an optional icon, the title and the actions at the end.
<div buiCodeBlock>
<div buiCodeBlockHeader>
<mat-icon buiCodeBlockIcon svgIcon="file-code" />
<span buiCodeBlockTitle>overdue.ts</span>
<div buiCodeBlockActions>
<button matIconButton buiCodeBlockCopyButton class="small" [value]="code">
<mat-icon svgIcon="copy" />
</button>
</div>
</div>
<pre buiCodeBlockContent lang="typescript" [code]="code"></pre>
</div>Languages and themes
Each language loads the first time it is used, and code shows as plain text until then.
Catppuccin Latte and Macchiato are the light and dark themes. Pass langs to add languages or themes to replace both.
provideHighlighter({
langs: {
rust: () => import('@shikijs/langs/rust'),
},
themes: {
light: () => import('@shikijs/themes/github-light'),
dark: () => import('@shikijs/themes/github-dark'),
},
}); Angular, Bash, CSS, Diff, HTML, JavaScript, JSON, JSX, Markdown, Python, SCSS, SQL, TypeScript, TSX and YAML are included. Use ansi for terminal output with colors. Unknown languages and content without lang render as plain text.
Copy button
buiCodeBlockCopyButton goes on a small matIconButton and copies its value. It announces the copy and sets data-copied for two seconds, so projected icons can swap with group-data-copied/bui-code-block-copy-button: variants. Without a header, the actions float at the top end of the block, shown on hover or focus and always on touch screens.
<div buiCodeBlock>
<div buiCodeBlockActions>
<button matIconButton buiCodeBlockCopyButton class="small" [value]="command">
<mat-icon
svgIcon="copy"
class="group-data-copied/bui-code-block-copy-button:hidden"
/>
<mat-icon
svgIcon="copy-check"
class="hidden text-jade-11 group-data-copied/bui-code-block-copy-button:inline-block"
/>
</button>
</div>
<pre buiCodeBlockContent lang="bash" [code]="command"></pre>
</div>Line numbers
lineNumbers adds a gutter as wide as the widest number, kept out of copied text. startLine sets the first number for an excerpt.
<div buiCodeBlock>
<pre
buiCodeBlockContent
lang="typescript"
lineNumbers
[startLine]="11"
[code]="code"
></pre>
</div>Diff lines
lineVariants maps displayed line numbers to added, removed or highlighted. Added and removed lines get a tint and a marker in the start padding.
<div buiCodeBlock>
<pre
buiCodeBlockContent
lang="typescript"
lineNumbers
[lineVariants]="{ 3: 'removed', 4: 'added' }"
[code]="code"
></pre>
</div> Without code, the content takes hand authored buiCodeBlockLine rows, each with a variant.
<div buiCodeBlock>
<!-- A pre keeps whitespace, so lines sit back to back -->
<pre buiCodeBlockContent>@for (line of lines; track $index) {<span buiCodeBlockLine [variant]="line.variant">{{ line.text }}</span>}</pre>
</div>Streaming
Bind the accumulated text to code. Finished lines keep their tokens and only the lines after them are tokenized again as the code grows. Disable the copy button until the code is complete.
<div buiCodeBlock>
<div buiCodeBlockHeader>
<span buiCodeBlockTitle>send-reminders.ts</span>
<div buiCodeBlockActions>
<button
matIconButton
buiCodeBlockCopyButton
class="small"
[value]="code()"
[disabled]="streaming()"
>
<mat-icon svgIcon="copy" />
</button>
</div>
</div>
<pre buiCodeBlockContent lang="typescript" [code]="code()"></pre>
</div>API Reference
buiCodeBlock
The frame. A text size class on it sizes the whole block.
buiCodeBlockHeader
Optional top row for the icon, title and actions.
buiCodeBlockIcon
Leading icon in the header, such as a file icon.
buiCodeBlockTitle
The file name or label. Truncates.
buiCodeBlockActions
Buttons at the end of the header, or floating at the top end without one.
buiCodeBlockCopyButton
Copies its value and announces it.
| Input | Type | Default | Description |
|---|---|---|---|
value | string | Required | The text to copy. |
buiCodeBlockContent
Goes on a pre. Renders and highlights the code.
| Input | Type | Default | Description |
|---|---|---|---|
code | string | '' | The code to render. |
lang | string | — | The language to highlight with. |
wrap | boolean | false | Wraps long lines instead of scrolling horizontally. |
lineNumbers | boolean | false | Shows the line number gutter. |
startLine | number | 1 | The number of the first line. |
lineVariants | Record<number, 'added' | 'removed' | 'highlighted'> | {} | Variants by displayed line number. |
buiCodeBlockLine
A hand authored line with a variant.
| Input | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'added' | 'removed' | 'highlighted' | 'default' | The state of the line. |
buiCodeBlockFooter
Optional bottom row, such as a show more button.