feat(markdown): support custom display-name for fenced code blocks (#4960)

---------

Co-authored-by: Divyansh Singh <40380293+brc-dd@users.noreply.github.com>
pull/4968/head
Elecmonkey 2 months ago committed by GitHub
parent 612c45895d
commit 3d61619ec0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -365,7 +365,7 @@ export default {
A [list of valid languages](https://shiki.style/languages) is available on Shiki's repository.
You may also customize syntax highlight theme in app config. Please see [`markdown` options](../reference/site-config#markdown) for more details.
You may also customize syntax highlight theme, configure language aliases, and set custom language labels in app config. Please see [`markdown` options](../reference/site-config#markdown) for more details.
## Line Highlighting in Code Blocks

@ -343,7 +343,7 @@ export default {
在 Shiki 的代码仓库中,可以找到[合法的编程语言列表](https://shiki.style/languages)。
还可以全局配置中自定义语法高亮主题。有关详细信息,参见 [`markdown` 选项](../reference/site-config#markdown)得到更多信息。
还可以全局配置中自定义语法高亮主题、配置语言别名和自定义语言标签。有关详细信息,参见 [`markdown` 选项](../reference/site-config#markdown)得到更多信息。
## 在代码块中实现行高亮 {#line-highlighting-in-code-blocks}

@ -87,12 +87,37 @@ export interface MarkdownOptions extends Options {
*/
languages?: (LanguageInput | BuiltinLanguage)[]
/**
* Custom language aliases.
* Custom language aliases for syntax highlighting.
* Maps custom language names to existing languages.
* Alias lookup is case-insensitive and underscores in language names are displayed as spaces.
*
* @example
*
* Maps `my_lang` to use Python syntax highlighting.
* ```js
* { 'my_lang': 'python' }
* ```
*
* Usage in markdown:
* ````md
* ```My_Lang
* # This will be highlighted as Python code
* # and will show "My Lang" as the language label
* print("Hello, World!")
* ```
* ````
*
* @example { 'my-lang': 'js' }
* @see https://shiki.style/guide/load-lang#custom-language-aliases
*/
languageAlias?: Record<string, string>
/**
* Custom language labels for display.
* Overrides the default language label shown in code blocks.
* Keys are case-insensitive.
*
* @example { 'vue': 'Vue SFC' }
*/
languageLabel?: Record<string, string>
/**
* Show line numbers in code blocks
* @default false
@ -249,7 +274,10 @@ export async function createMarkdownRenderer(
// custom plugins
md.use(componentPlugin, { ...options.component })
.use(highlightLinePlugin)
.use(preWrapperPlugin, { codeCopyButtonTitle })
.use(preWrapperPlugin, {
codeCopyButtonTitle,
languageLabel: options.languageLabel
})
.use(snippetPlugin, srcDir)
.use(containerPlugin, options.container)
.use(imagePlugin, options.image)

@ -59,16 +59,18 @@ export async function highlight(
codeTransformers: userTransformers = []
} = options
const langAlias = Object.fromEntries(
Object.entries(options.languageAlias || {}) //
.map(([k, v]) => [k.toLowerCase(), v])
)
const highlighter = await createHighlighter({
themes:
typeof theme === 'object' && 'light' in theme && 'dark' in theme
? [theme.light, theme.dark]
: [theme],
langs: [
...(options.languages || []),
...Object.values(options.languageAlias || {})
],
langAlias: options.languageAlias
langs: [...(options.languages || []), ...Object.values(langAlias)],
langAlias
})
await options?.shikiSetup?.(highlighter)

@ -2,9 +2,15 @@ import type { MarkdownItAsync } from 'markdown-it-async'
export interface Options {
codeCopyButtonTitle: string
languageLabel?: Record<string, string>
}
export function preWrapperPlugin(md: MarkdownItAsync, options: Options) {
const langLabel = Object.fromEntries(
Object.entries(options.languageLabel || {}) //
.map(([k, v]) => [k.toLowerCase(), v])
)
const fence = md.renderer.rules.fence!
md.renderer.rules.fence = (...args) => {
const [tokens, idx] = args
@ -17,11 +23,12 @@ export function preWrapperPlugin(md: MarkdownItAsync, options: Options) {
token.info = token.info.replace(/ active$/, '').replace(/ active /, ' ')
const lang = extractLang(token.info)
const label = langLabel[lang.toLowerCase()] || lang.replace(/_/g, ' ')
return (
`<div class="language-${lang}${active}">` +
`<button title="${options.codeCopyButtonTitle}" class="copy"></button>` +
`<span class="lang">${lang}</span>` +
`<span class="lang">${label}</span>` +
fence(...args) +
'</div>'
)

Loading…
Cancel
Save