mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(docs-infra): use shiki for highlighting
Use shiki to perform highlighting instead of a postprocessing action
This commit is contained in:
committed by
Kirill Cherkashin
parent
a8f46e598a
commit
fee79e37d5
@@ -41,11 +41,9 @@ export function ClassReference(
|
||||
<div className={SECTION_CONTAINER + ' docs-reference-api-section'}>
|
||||
<SectionHeading name="Pipe usage" />
|
||||
<RawHtml
|
||||
value={codeToHtml(
|
||||
getHighlighterInstance(),
|
||||
(entry as PipeEntry).usage,
|
||||
'angular-html',
|
||||
)}
|
||||
value={codeToHtml(getHighlighterInstance(), (entry as PipeEntry).usage, {
|
||||
language: 'angular-html',
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -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(/^(<pre class="shiki)/, '$1 docs-mini-scroll-track');
|
||||
|
||||
return <RawHtml value={withScrollTrack} className="docs-code" />;
|
||||
|
||||
@@ -92,7 +92,7 @@ export async function addRenderableCodeToc<T extends DocEntry & HasModuleName>(
|
||||
let codeWithSyntaxHighlighting = codeToHtml(
|
||||
getHighlighterInstance(),
|
||||
formattedCode ?? metadata?.contents,
|
||||
'typescript',
|
||||
{language: 'typescript'},
|
||||
);
|
||||
|
||||
if (isDecoratorEntry(entry)) {
|
||||
|
||||
@@ -25,9 +25,12 @@ export function highlightCode(highlighter: HighlighterGeneric<any, any>, 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<any, any>, 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<any, any>, token:
|
||||
if (isAddedLine) {
|
||||
el.classList.add(lineAddedClassName);
|
||||
}
|
||||
if (isHighlighted) {
|
||||
el.classList.add(lineHighlightedClassName);
|
||||
}
|
||||
};
|
||||
|
||||
const currentline = lines[lineIndex];
|
||||
|
||||
@@ -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 */);
|
||||
}
|
||||
|
||||
@@ -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<HighlighterGeneric<any, any>> {
|
||||
export function codeToHtml(
|
||||
highlighter: HighlighterGeneric<any, any>,
|
||||
code: string,
|
||||
language: string | undefined,
|
||||
config: {
|
||||
language?: string;
|
||||
highlight?: Set<number>;
|
||||
},
|
||||
): 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<number>): ShikiTransformer {
|
||||
return {
|
||||
line(node, lineNumber) {
|
||||
if (highlight?.has(lineNumber)) {
|
||||
this.addClassToHast(node, 'highlighted');
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user