<bs-datatable #tabel [columns]="columns" [fetch]="fetchArtists"
[(sortColumns)]="sortColumns" pagination>
<ng-container *bsDatatableRow="let artist">
<td class="text-nowrap">{{ artist.name }}</td>
<td class="text-nowrap">{{ artist.yearStarted }}</td>
<td class="text-nowrap">{{ artist.yearQuit }}</td>
</ng-container>
</bs-datatable>
Highlighting comes from highlight.js. Only its core is loaded up front; the grammar for the language you ask for is fetched on demand, so a page with one ts snippet pays for one grammar rather than all 36.
Off by default — a one-line install command gains nothing from a 1 beside it.
export function total(items: Item[]): number {
let sum = 0;
for (const item of items) {
if (item.taxable) {
sum += item.price * 1.21;
} else {
sum += item.price;
}
}
return sum;
}
<bs-code-snippet [code]="source" [language]="'ts'" [lineNumbers]="true" />
The block follows the page's data-bs-theme with no wiring — flip the theme switch in the topbar and this snippet follows it. Pass [theme]="'light'" or 'dark' to pin it instead.
export function total(items: Item[]): number {
let sum = 0;
for (const item of items) {
if (item.taxable) {
sum += item.price * 1.21;
} else {
sum += item.price;
}
}
return sum;
}
export function total(items: Item[]): number {
let sum = 0;
for (const item of items) {
if (item.taxable) {
sum += item.price * 1.21;
} else {
sum += item.price;
}
}
return sum;
}
<!-- follows data-bs-theme by default -->
<bs-code-snippet [code]="source" [language]="'ts'" />
<!-- or pin it -->
<bs-code-snippet [code]="source" [language]="'ts'" [theme]="'dark'" />
Each line can carry a kind, up to two gutter labels and a description. kind is an opaque string — the component ships no colours for it, so you style the row class annotation-<kind> from your own stylesheet and the component stays coverage-agnostic.
Keyboard: Tab reaches the active line, then the arrow keys move between line links and Home / End jump to the first and last. Clicking a line number sets the active line here; the underlying link is a real href, so middle-click still opens it.
1
export function total(items: Item[]): number {
2
let sum = 0;
3
for (const item of items) {
4
if (item.taxable) {
Branches: 1 of 2 taken
5
sum += item.price * 1.21;
6
} else {
7
sum += item.price;
8
}
9
}
10
return sum;
11
}
<bs-code-snippet
[code]="source"
[language]="'ts'"
[lineNumbers]="true"
[annotations]="coverage"
[activeLine]="activeLine()"
[lineHref]="lineHref"
(lineActivate)="onLineActivate($event)" />
readonly coverage: CodeLineAnnotation[] = [
{ line: 4, kind: 'partial', label: '4×', secondaryLabel: '1/2',
description: 'Branches: 1 of 2 taken' },
{ line: 6, kind: 'uncovered', label: '0' },
];
// `kind` is opaque: it becomes the row class annotation-<kind>,
// styled from your own stylesheet:
// .coverage ::ng-deep .annotation-uncovered { … }
lineHref = (line: number) => `#L${line}`;
// Prevent the link's navigation when you handle the activation yourself.
// Modified and middle clicks never reach here, so open-in-new-tab keeps working.
onLineActivate(event: CodeLineActivation) {
event.preventDefault();
this.activeLine.set(event.line);
}
// A fragment does NOT scroll to the line. Read it on navigation and drive
// the snippet explicitly instead:
// viewChild(BsCodeSnippetComponent).scrollToLine(n)
Give the component a height or max-height and the listing scrolls vertically inside it; constrain the width and long lines scroll horizontally. Both scrollbars belong to the code area, so the copy button and the line-number gutter stay put while you scroll.
<bs-datatable #tabel [columns]="columns" [fetch]="fetchArtists"
[(sortColumns)]="sortColumns" pagination>
<ng-container *bsDatatableRow="let artist">
<td class="text-nowrap">{{ artist.name }}</td>
<td class="text-nowrap">{{ artist.yearStarted }}</td>
<td class="text-nowrap">{{ artist.yearQuit }}</td>
</ng-container>
</bs-datatable>
<bs-code-snippet
class="sized-snippet"
[code]="source"
[language]="'html'"
[lineNumbers]="true" />
/* Any height constraint works — the code area scrolls inside it. */
.sized-snippet {
max-height: 220px;
}