91 lines
2.6 KiB
Text
91 lines
2.6 KiB
Text
![]() |
---
|
||
|
import type * as shiki from 'shiki';
|
||
|
import { renderToHtml } from 'shiki';
|
||
|
import { getHighlighter } from './Shiki.js';
|
||
|
|
||
|
interface Props {
|
||
|
/** The code to highlight. Required. */
|
||
|
code: string;
|
||
|
/**
|
||
|
* The language of your code.
|
||
|
* Supports all languages listed here: https://github.com/shikijs/shiki/blob/main/docs/languages.md#all-languages
|
||
|
* Instructions for loading a custom language: https://github.com/shikijs/shiki/blob/main/docs/languages.md#supporting-your-own-languages-with-shiki
|
||
|
*
|
||
|
* @default "plaintext"
|
||
|
*/
|
||
|
lang?: shiki.Lang | shiki.ILanguageRegistration;
|
||
|
/**
|
||
|
* The styling theme.
|
||
|
* Supports all themes listed here: https://github.com/shikijs/shiki/blob/main/docs/themes.md#all-themes
|
||
|
* Instructions for loading a custom theme: https://github.com/shikijs/shiki/blob/main/docs/themes.md#loading-theme
|
||
|
*
|
||
|
* @default "github-dark"
|
||
|
*/
|
||
|
theme?: shiki.IThemeRegistration;
|
||
|
/**
|
||
|
* Enable word wrapping.
|
||
|
* - true: enabled.
|
||
|
* - false: disabled.
|
||
|
* - null: All overflow styling removed. Code will overflow the element by default.
|
||
|
*
|
||
|
* @default false
|
||
|
*/
|
||
|
wrap?: boolean | null;
|
||
|
/**
|
||
|
* Generate inline code element only, without the pre element wrapper.
|
||
|
*
|
||
|
* @default false
|
||
|
*/
|
||
|
inline?: boolean;
|
||
|
}
|
||
|
|
||
|
const {
|
||
|
code,
|
||
|
lang = 'plaintext',
|
||
|
theme = 'github-dark',
|
||
|
wrap = false,
|
||
|
inline = false,
|
||
|
} = Astro.props;
|
||
|
|
||
|
// 1. Get the shiki syntax highlighter
|
||
|
const highlighter = await getHighlighter({
|
||
|
theme,
|
||
|
// Load custom lang if passed an object, otherwise load the default
|
||
|
langs: typeof lang !== 'string' ? [lang] : undefined,
|
||
|
});
|
||
|
|
||
|
// 2. Turn code into shiki theme tokens
|
||
|
const tokens = highlighter.codeToThemedTokens(code, typeof lang === 'string' ? lang : lang.id);
|
||
|
|
||
|
// 3. Get shiki theme object
|
||
|
const _theme = highlighter.getTheme();
|
||
|
|
||
|
// 4. Render the theme tokens as html
|
||
|
const html = renderToHtml(tokens, {
|
||
|
themeName: _theme.name,
|
||
|
fg: _theme.fg,
|
||
|
bg: _theme.bg,
|
||
|
elements: {
|
||
|
pre({ className, style, children }) {
|
||
|
// Swap to `code` tag if inline
|
||
|
const tag = inline ? 'code' : 'pre';
|
||
|
// Replace "shiki" class naming with "astro-code"
|
||
|
className = className.replace(/shiki/g, 'astro-code');
|
||
|
// Handle code wrapping
|
||
|
// if wrap=null, do nothing.
|
||
|
if (wrap === false) {
|
||
|
style += '; overflow-x: auto;"';
|
||
|
} else if (wrap === true) {
|
||
|
style += '; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;"';
|
||
|
}
|
||
|
return `<${tag} class="${className}" style="${style}" tabindex="0">${children}</${tag}>`;
|
||
|
},
|
||
|
code({ children }) {
|
||
|
return inline ? children : `<code>${children}</code>`;
|
||
|
},
|
||
|
},
|
||
|
});
|
||
|
---
|
||
|
|
||
|
<Fragment set:html={html} />
|