diff options
Diffstat (limited to 'packages/markdown')
-rw-r--r-- | packages/markdown/remark/src/index.ts | 4 | ||||
-rw-r--r-- | packages/markdown/remark/src/remark-shiki.ts | 41 | ||||
-rw-r--r-- | packages/markdown/remark/src/types.ts | 4 |
3 files changed, 44 insertions, 5 deletions
diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts index 78d645227..e8a315ef1 100644 --- a/packages/markdown/remark/src/index.ts +++ b/packages/markdown/remark/src/index.ts @@ -39,7 +39,7 @@ export async function renderMarkdown(content: string, opts?: MarkdownRenderingOp const scopedClassName = opts?.$?.scopedClassName; const mode = opts?.mode ?? 'mdx'; const syntaxHighlight = opts?.syntaxHighlight ?? 'prism'; - const shikiTheme = opts?.shikiTheme ?? 'github-dark'; + const shikiConfig = opts?.shikiConfig ?? {}; const isMDX = mode === 'mdx'; const { headers, rehypeCollectHeaders } = createCollectHeaders(); @@ -70,7 +70,7 @@ export async function renderMarkdown(content: string, opts?: MarkdownRenderingOp if (syntaxHighlight === 'prism') { parser.use([remarkPrism(scopedClassName)]); } else if (syntaxHighlight === 'shiki') { - parser.use([await remarkShiki(shikiTheme)]); + parser.use([await remarkShiki(shikiConfig)]); } parser.use([[markdownToHtml as any, { allowDangerousHtml: true, passThrough: ['raw', 'mdxTextExpression', 'mdxJsxTextElement', 'mdxJsxFlowElement'] }]]); diff --git a/packages/markdown/remark/src/remark-shiki.ts b/packages/markdown/remark/src/remark-shiki.ts index 5becad76d..91f1b76e3 100644 --- a/packages/markdown/remark/src/remark-shiki.ts +++ b/packages/markdown/remark/src/remark-shiki.ts @@ -1,9 +1,41 @@ import shiki from 'shiki'; import { visit } from 'unist-util-visit'; -const remarkShiki = async (theme: shiki.Theme) => { +export interface ShikiConfig { + /** + * The languages loaded to Shiki. + * 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 [] + */ + langs?: 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: enabled. + * - null: All overflow styling removed. Code will overflow the element by default. + * + * @default false + */ + wrap?: boolean | null; +} + +const remarkShiki = async ({ langs = [], theme = 'github-dark', wrap = false }: ShikiConfig) => { const highlighter = await shiki.getHighlighter({ theme }); + for (const lang of langs) { + await highlighter.loadLanguage(lang); + } + return () => (tree: any) => { visit(tree, 'code', (node) => { let html = highlighter.codeToHtml(node.value, { lang: node.lang ?? 'plaintext' }); @@ -12,6 +44,13 @@ const remarkShiki = async (theme: shiki.Theme) => { html = html.replace('<pre class="shiki"', '<pre class="astro-code"'); // Replace "shiki" css variable naming with "astro". html = html.replace(/style="(background-)?color: var\(--shiki-/g, 'style="$1color: var(--astro-code-'); + // Handle code wrapping + // if wrap=null, do nothing. + if (wrap === false) { + html = html.replace(/style="(.*?)"/, 'style="$1; overflow-x: auto;"'); + } else if (wrap === true) { + html = html.replace(/style="(.*?)"/, 'style="$1; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;"'); + } node.type = 'html'; node.value = html; diff --git a/packages/markdown/remark/src/types.ts b/packages/markdown/remark/src/types.ts index 94c3e78a3..040c33b79 100644 --- a/packages/markdown/remark/src/types.ts +++ b/packages/markdown/remark/src/types.ts @@ -1,12 +1,12 @@ import type * as unified from 'unified'; -import type * as shiki from 'shiki'; +import type { ShikiConfig } from './remark-shiki'; export type Plugin = string | [string, any] | unified.Plugin | [unified.Plugin, any]; export interface AstroMarkdownOptions { mode?: 'md' | 'mdx'; syntaxHighlight?: 'prism' | 'shiki' | false; - shikiTheme?: shiki.Theme; + shikiConfig?: ShikiConfig; remarkPlugins?: Plugin[]; rehypePlugins?: Plugin[]; } |