diff --git a/adev/shared-docs/pipeline/api-gen/rendering/templates/class-reference.tsx b/adev/shared-docs/pipeline/api-gen/rendering/templates/class-reference.tsx
index a0825efd7b3..3a00f75661e 100644
--- a/adev/shared-docs/pipeline/api-gen/rendering/templates/class-reference.tsx
+++ b/adev/shared-docs/pipeline/api-gen/rendering/templates/class-reference.tsx
@@ -41,11 +41,9 @@ export function ClassReference(
>
diff --git a/adev/shared-docs/pipeline/api-gen/rendering/templates/highlight-ts.tsx b/adev/shared-docs/pipeline/api-gen/rendering/templates/highlight-ts.tsx
index 78023aefda5..1a91e5d3f49 100644
--- a/adev/shared-docs/pipeline/api-gen/rendering/templates/highlight-ts.tsx
+++ b/adev/shared-docs/pipeline/api-gen/rendering/templates/highlight-ts.tsx
@@ -13,7 +13,7 @@ import {getHighlighterInstance} from '../shiki/shiki.mjs';
/** Component to render a header of the CLI page. */
export function HighlightTypeScript(props: {code: string}) {
- const result = codeToHtml(getHighlighterInstance(), props.code, 'typescript');
+ const result = codeToHtml(getHighlighterInstance(), props.code, {language: 'typescript'});
const withScrollTrack = result.replace(/^(;
diff --git a/adev/shared-docs/pipeline/api-gen/rendering/transforms/code-transforms.mts b/adev/shared-docs/pipeline/api-gen/rendering/transforms/code-transforms.mts
index 299019b943a..bf94457e958 100644
--- a/adev/shared-docs/pipeline/api-gen/rendering/transforms/code-transforms.mts
+++ b/adev/shared-docs/pipeline/api-gen/rendering/transforms/code-transforms.mts
@@ -92,7 +92,7 @@ export async function addRenderableCodeToc(
let codeWithSyntaxHighlighting = codeToHtml(
getHighlighterInstance(),
formattedCode ?? metadata?.contents,
- 'typescript',
+ {language: 'typescript'},
);
if (isDecoratorEntry(entry)) {
diff --git a/adev/shared-docs/pipeline/shared/marked/extensions/docs-code/format/highlight.mts b/adev/shared-docs/pipeline/shared/marked/extensions/docs-code/format/highlight.mts
index e4083208128..c4dba1cf9c4 100644
--- a/adev/shared-docs/pipeline/shared/marked/extensions/docs-code/format/highlight.mts
+++ b/adev/shared-docs/pipeline/shared/marked/extensions/docs-code/format/highlight.mts
@@ -25,9 +25,12 @@ export function highlightCode(highlighter: HighlighterGeneric, token:
if (token.language !== 'none' && token.language !== 'file') {
// Decode the code content to replace HTML entities to characters
const language = token.language ?? guessLanguageFromPath(token.path);
+ /** The set of all lines which should be highlighted. */
+ const highlight = token.highlight
+ ? new Set(expandRangeStringValues(token.highlight))
+ : undefined;
- const codeAsHtml = codeToHtml(highlighter, token.code, language);
- token.code = codeAsHtml;
+ token.code = codeToHtml(highlighter, token.code, {language, highlight});
}
const dom = new JSDOM(token.code);
@@ -45,12 +48,9 @@ export function highlightCode(highlighter: HighlighterGeneric, token:
let lineIndex = 0;
let resultFileLineIndex = 1;
- const highlightedLineRanges = token.highlight ? expandRangeStringValues(token.highlight) : [];
-
do {
const isRemovedLine = token.diffMetadata?.linesRemoved.includes(lineIndex);
const isAddedLine = token.diffMetadata?.linesAdded.includes(lineIndex);
- const isHighlighted = highlightedLineRanges.includes(lineIndex);
const addClasses = (el: Element) => {
if (isRemovedLine) {
el.classList.add(lineRemovedClassName);
@@ -58,9 +58,6 @@ export function highlightCode(highlighter: HighlighterGeneric, token:
if (isAddedLine) {
el.classList.add(lineAddedClassName);
}
- if (isHighlighted) {
- el.classList.add(lineHighlightedClassName);
- }
};
const currentline = lines[lineIndex];
diff --git a/adev/shared-docs/pipeline/shared/marked/extensions/docs-code/format/range.mts b/adev/shared-docs/pipeline/shared/marked/extensions/docs-code/format/range.mts
index 5f2ba3cb577..7892cee942c 100644
--- a/adev/shared-docs/pipeline/shared/marked/extensions/docs-code/format/range.mts
+++ b/adev/shared-docs/pipeline/shared/marked/extensions/docs-code/format/range.mts
@@ -7,7 +7,7 @@
*/
/**
- * Expand a provided set of range values into a singel array of all values in the range.
+ * Expand a provided set of range values into a single array of all values in the range.
*
* For example, [[1,3], [12-13]] is expanded to [1,2,3,12,13].
*/
@@ -18,7 +18,7 @@ export function expandRangeStringValues(rangeString: string | undefined): number
const getAllValuesFromRange = (range: any[]) => {
const [start, end] = range;
for (let i = start; i <= end; i++) {
- result.push(i - 1);
+ result.push(i);
}
};
@@ -40,7 +40,7 @@ export function expandRangeStringValues(rangeString: string | undefined): number
if (Array.isArray(range) && range.length === 2) {
getAllValuesFromRange(range);
} else if (!Number.isNaN(range)) {
- result.push(Number(range - 1));
+ result.push(Number(range));
} else {
throw new Error('Input has wrong format!\n' /* range */);
}
diff --git a/adev/shared-docs/pipeline/shared/shiki.mts b/adev/shared-docs/pipeline/shared/shiki.mts
index 66476e57d6c..5e500077aaa 100644
--- a/adev/shared-docs/pipeline/shared/shiki.mts
+++ b/adev/shared-docs/pipeline/shared/shiki.mts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
-import {HighlighterGeneric} from 'shiki';
+import {HighlighterGeneric, ShikiTransformer} from 'shiki';
const LIGHT_THEME = 'github-light';
const DARK_THEME = 'github-dark';
@@ -35,17 +35,32 @@ export async function initHighlighter(): Promise> {
export function codeToHtml(
highlighter: HighlighterGeneric,
code: string,
- language: string | undefined,
+ config: {
+ language?: string;
+ highlight?: Set;
+ },
): string {
const html = highlighter.codeToHtml(code, {
- lang: language ?? 'text',
+ lang: config.language ?? 'text',
themes: {
light: LIGHT_THEME,
dark: DARK_THEME,
},
cssVariablePrefix: '--shiki-',
defaultColor: false,
+ transformers: [highlightTransformer(config.highlight)],
});
return html;
}
+
+/** A custom transformer which will mark all of the provided line numbers in a set as highlighted. */
+function highlightTransformer(highlight?: Set): ShikiTransformer {
+ return {
+ line(node, lineNumber) {
+ if (highlight?.has(lineNumber)) {
+ this.addClassToHast(node, 'highlighted');
+ }
+ },
+ };
+}