feat(theme): support light shiki themes (#2319)

BREAKING CHANGE: Styling for code blocks might break, especially if you were earlier overriding it for light theme. Those workarounds are no longer required. VitePress will now show code blocks and groups in light mode too if a light shiki theme is specified.
pull/2323/head
Divyansh Singh 1 year ago committed by GitHub
parent 3b3bfea94c
commit d0f0012aea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -491,7 +491,7 @@
z-index: 2;
font-size: 12px;
font-weight: 500;
color: var(--vp-c-text-dark-3);
color: var(--vp-c-code-dimm);
transition: color 0.4s, opacity 0.4s;
}

@ -208,6 +208,7 @@
:root {
--vp-code-line-height: 1.7;
--vp-code-font-size: 0.875em;
--vp-c-code-dimm: var(--vp-c-text-dark-3);
--vp-code-block-color: var(--vp-c-text-dark-1);
--vp-code-block-bg: #292b30;
@ -215,7 +216,7 @@
--vp-code-block-divider-color: #000000;
--vp-code-line-highlight-color: rgba(0, 0, 0, 0.5);
--vp-code-line-number-color: var(--vp-c-text-dark-3);
--vp-code-line-number-color: var(--vp-c-code-dimm);
--vp-code-line-diff-add-color: var(--vp-c-green-dimm-2);
--vp-code-line-diff-add-symbol-color: var(--vp-c-green);
@ -244,6 +245,27 @@
--vp-code-block-bg: #161618;
}
:root:not(.dark) .vp-adaptive-theme {
--vp-c-code-dimm: var(--vp-c-text-2);
--vp-code-block-color: var(--vp-c-text-1);
--vp-code-block-bg: #f8f8f8;
--vp-code-block-divider-color: var(--vp-c-divider);
--vp-code-line-highlight-color: #ececec;
--vp-code-line-number-color: var(--vp-c-code-dimm);
--vp-code-copy-code-bg: #e2e2e2;
--vp-code-copy-code-hover-bg: #dcdcdc;
--vp-code-copy-code-active-text: var(--vp-c-text-2);
--vp-code-tab-divider: var(--vp-c-divider);
--vp-code-tab-text-color: var(--vp-c-text-2);
--vp-code-tab-bg: var(--vp-code-block-bg);
--vp-code-tab-hover-text-color: var(--vp-c-text-1);
--vp-code-tab-active-text-color: var(--vp-c-text-1);
}
/**
* Component: Button
* -------------------------------------------------------------------------- */

@ -60,13 +60,16 @@ export const createMarkdownRenderer = async (
base = '/',
logger: Pick<Logger, 'warn'> = console
): Promise<MarkdownRenderer> => {
const theme = options.theme ?? 'material-theme-palenight'
const hasSingleTheme = typeof theme === 'string' || 'name' in theme
const md = MarkdownIt({
html: true,
linkify: true,
highlight:
options.highlight ||
(await highlight(
options.theme,
theme,
options.languages,
options.defaultHighlightLang,
logger
@ -79,9 +82,9 @@ export const createMarkdownRenderer = async (
// custom plugins
md.use(componentPlugin)
.use(highlightLinePlugin)
.use(preWrapperPlugin)
.use(preWrapperPlugin, { hasSingleTheme })
.use(snippetPlugin, srcDir)
.use(containerPlugin)
.use(containerPlugin, { hasSingleTheme })
.use(imagePlugin)
.use(
linkPlugin,

@ -3,9 +3,13 @@ import type { RenderRule } from 'markdown-it/lib/renderer'
import type Token from 'markdown-it/lib/token'
import container from 'markdown-it-container'
import { nanoid } from 'nanoid'
import { extractTitle } from './preWrapper'
import {
extractTitle,
getAdaptiveThemeMarker,
type Options
} from './preWrapper'
export const containerPlugin = (md: MarkdownIt) => {
export const containerPlugin = (md: MarkdownIt, options: Options) => {
md.use(...createContainer('tip', 'TIP', md))
.use(...createContainer('info', 'INFO', md))
.use(...createContainer('warning', 'WARNING', md))
@ -20,7 +24,7 @@ export const containerPlugin = (md: MarkdownIt) => {
render: (tokens: Token[], idx: number) =>
tokens[idx].nesting === 1 ? `<div class="vp-raw">\n` : `</div>\n`
})
.use(...createCodeGroup())
.use(...createCodeGroup(options))
}
type ContainerArgs = [typeof container, string, { render: RenderRule }]
@ -51,7 +55,7 @@ function createContainer(
]
}
function createCodeGroup(): ContainerArgs {
function createCodeGroup(options: Options): ContainerArgs {
return [
container,
'code-group',
@ -82,7 +86,9 @@ function createCodeGroup(): ContainerArgs {
}
}
return `<div class="vp-code-group"><div class="tabs">${tabs}</div><div class="blocks">\n`
return `<div class="vp-code-group${getAdaptiveThemeMarker(
options
)}"><div class="tabs">${tabs}</div><div class="blocks">\n`
}
return `</div></div>\n`
}

@ -62,7 +62,7 @@ const errorLevelProcessor = defineProcessor({
})
export async function highlight(
theme: ThemeOptions = 'material-theme-palenight',
theme: ThemeOptions,
languages: ILanguageRegistration[] = [],
defaultLang: string = '',
logger: Pick<Logger, 'warn'> = console

@ -1,6 +1,10 @@
import type MarkdownIt from 'markdown-it'
export function preWrapperPlugin(md: MarkdownIt) {
export interface Options {
hasSingleTheme: boolean
}
export function preWrapperPlugin(md: MarkdownIt, options: Options) {
const fence = md.renderer.rules.fence!
md.renderer.rules.fence = (...args) => {
const [tokens, idx] = args
@ -10,17 +14,21 @@ export function preWrapperPlugin(md: MarkdownIt) {
const lang = extractLang(token.info)
const rawCode = fence(...args)
return `<div class="language-${lang}${
return `<div class="language-${lang}${getAdaptiveThemeMarker(options)}${
/ active( |$)/.test(token.info) ? ' active' : ''
}"><button title="Copy Code" class="copy"></button><span class="lang">${lang}</span>${rawCode}</div>`
}
}
export function getAdaptiveThemeMarker(options: Options) {
return options.hasSingleTheme ? '' : ' vp-adaptive-theme'
}
export function extractTitle(info: string) {
return info.match(/\[(.*)\]/)?.[1] || extractLang(info) || 'txt'
}
const extractLang = (info: string) => {
function extractLang(info: string) {
return info
.trim()
.replace(/:(no-)?line-numbers({| |$).*/, '')

Loading…
Cancel
Save