feat(markdown): expose Shiki color replacements in markdown options (#5153)

pull/5154/head
Divyansh Singh 5 months ago committed by GitHub
parent 6dd3632960
commit fccc617102
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,26 @@
import { highlight } from 'node/markdown/plugins/highlight'
describe('node/markdown/plugins/highlight', () => {
test('passes color replacements through markdown options', async () => {
const [render, dispose] = await highlight(
{ light: 'github-light', dark: 'github-dark' },
{
colorReplacements: {
'github-light': {
'#005cc5': '#000000'
}
}
}
)
try {
const html = await render('const a = 1', 'js', '')
expect(html).toContain('--shiki-light:#000000')
expect(html).toContain('--shiki-dark:#79B8FF')
expect(html).not.toContain('--shiki-light:#005CC5')
} finally {
dispose()
}
})
})

@ -16,6 +16,6 @@
"postcss-rtlcss": "^5.7.1",
"vitepress": "workspace:*",
"vitepress-plugin-group-icons": "^1.7.1",
"vitepress-plugin-llms": "^1.11.0"
"vitepress-plugin-llms": "^1.11.1"
}
}

@ -1,30 +1,30 @@
┌ Welcome to VitePress!
│
◇ Where should VitePress initialize the config?
│ ./docs
◇ Where should VitePress initialize the config?
│ ./docs
│
◇ Where should VitePress look for your markdown files?
│ ./docs
◇ Where should VitePress look for your markdown files?
│ ./docs
│
◇ Site title:
│ My Awesome Project
◇ Site title:
│ My Awesome Project
│
◇ Site description:
│ A VitePress Site
◇ Site description:
│ A VitePress Site
│
◇ Theme:
│ Default Theme
◇ Theme:
│ Default Theme
│
◇ Use TypeScript for config and theme files?
│ Yes
◇ Use TypeScript for config and theme files?
│ Yes
│
◇ Add VitePress npm scripts to package.json?
│ Yes
◇ Add VitePress npm scripts to package.json?
│ Yes
│
◇ Add a prefix for VitePress npm scripts?
│ Yes
◇ Add a prefix for VitePress npm scripts?
│ Yes
│
◇ Prefix for VitePress npm scripts:
│ docs
◇ Prefix for VitePress npm scripts:
│ docs
│
└ Done! Now run pnpm run docs:dev and start writing.
└ Done! Now run pnpm run docs:dev and start writing.

@ -96,28 +96,28 @@
"*": "prettier --experimental-cli --ignore-unknown --write"
},
"dependencies": {
"@docsearch/css": "^4.5.3",
"@docsearch/js": "^4.5.3",
"@docsearch/sidepanel-js": "^4.5.3",
"@iconify-json/simple-icons": "^1.2.69",
"@shikijs/core": "^3.22.0",
"@shikijs/transformers": "^3.22.0",
"@shikijs/types": "^3.22.0",
"@docsearch/css": "^4.6.0",
"@docsearch/js": "^4.6.0",
"@docsearch/sidepanel-js": "^4.6.0",
"@iconify-json/simple-icons": "^1.2.74",
"@shikijs/core": "^4.0.2",
"@shikijs/transformers": "^4.0.2",
"@shikijs/types": "^4.0.2",
"@types/markdown-it": "^14.1.2",
"@vitejs/plugin-vue": "^6.0.4",
"@vue/devtools-api": "^8.0.5",
"@vue/shared": "^3.5.27",
"@vueuse/core": "^14.2.0",
"@vueuse/integrations": "^14.2.0",
"@vitejs/plugin-vue": "^6.0.5",
"@vue/devtools-api": "^8.1.0",
"@vue/shared": "^3.5.30",
"@vueuse/core": "^14.2.1",
"@vueuse/integrations": "^14.2.1",
"focus-trap": "^8.0.0",
"mark.js": "8.11.1",
"minisearch": "^7.2.0",
"shiki": "^3.22.0",
"shiki": "^4.0.2",
"vite": "^7.3.1",
"vue": "^3.5.27"
"vue": "^3.5.30"
},
"devDependencies": {
"@clack/prompts": "^1.0.0",
"@clack/prompts": "^1.1.0",
"@iconify/utils": "^3.1.0",
"@mdit-vue/plugin-component": "^3.0.2",
"@mdit-vue/plugin-frontmatter": "^3.0.2",
@ -128,7 +128,7 @@
"@mdit-vue/shared": "^3.0.2",
"@polka/compression": "^1.0.0-next.28",
"@rollup/plugin-alias": "^6.0.0",
"@rollup/plugin-commonjs": "^29.0.0",
"@rollup/plugin-commonjs": "^29.0.2",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.3",
"@rollup/plugin-replace": "^6.0.3",
@ -140,58 +140,58 @@
"@types/markdown-it-container": "^4.0.0",
"@types/markdown-it-emoji": "^3.0.1",
"@types/minimist": "^1.2.5",
"@types/node": "^25.2.0",
"@types/node": "^25.5.0",
"@types/picomatch": "^4.0.2",
"@types/prompts": "^2.4.9",
"chokidar": "^4.0.3",
"conventional-changelog": "^7.1.1",
"conventional-changelog-angular": "^8.1.0",
"chokidar": "^5.0.0",
"conventional-changelog": "^7.2.0",
"conventional-changelog-angular": "^8.3.0",
"cross-spawn": "^7.0.6",
"esbuild": "^0.27.2",
"esbuild": "^0.27.4",
"execa": "^9.6.1",
"fs-extra": "^11.3.3",
"fs-extra": "^11.3.4",
"get-port": "^7.1.0",
"gray-matter": "^4.0.3",
"lint-staged": "^16.2.7",
"lint-staged": "^16.4.0",
"lodash.template": "^4.5.0",
"lru-cache": "^11.2.5",
"markdown-it": "^14.1.0",
"lru-cache": "^11.2.7",
"markdown-it": "^14.1.1",
"markdown-it-anchor": "^9.2.0",
"markdown-it-async": "^2.2.0",
"markdown-it-attrs": "^4.3.1",
"markdown-it-cjk-friendly": "^2.0.1",
"markdown-it-cjk-friendly": "^2.0.2",
"markdown-it-container": "^4.0.0",
"markdown-it-emoji": "^3.0.0",
"markdown-it-mathjax3": "^4.3.2",
"minimist": "^1.2.8",
"nanoid": "^5.1.6",
"nanoid": "^5.1.7",
"obug": "^2.1.1",
"ora": "^9.1.0",
"ora": "^9.3.0",
"oxc-minify": "^0.98.0",
"p-map": "^7.0.4",
"package-directory": "^8.2.0",
"path-to-regexp": "^6.3.0",
"picocolors": "^1.1.1",
"picomatch": "^4.0.3",
"playwright-chromium": "^1.58.1",
"playwright-chromium": "^1.58.2",
"polka": "^1.0.0-next.28",
"postcss": "^8.5.6",
"postcss-selector-parser": "^7.1.1",
"prettier": "^3.8.1",
"prompts": "^2.4.2",
"punycode": "^2.3.1",
"rollup": "^4.57.1",
"rollup": "^4.59.0",
"rollup-plugin-dts": "6.1.1",
"rollup-plugin-esbuild": "^6.2.1",
"semver": "^7.7.3",
"semver": "^7.7.4",
"simple-git-hooks": "^2.13.1",
"sirv": "^3.0.2",
"sitemap": "^9.0.0",
"sitemap": "^9.0.1",
"tinyglobby": "^0.2.15",
"typescript": "^5.9.3",
"vitest": "4.0.0-beta.4",
"vue-tsc": "^3.2.4",
"wait-on": "^9.0.3"
"vue-tsc": "^3.2.6",
"wait-on": "^9.0.4"
},
"peerDependencies": {
"markdown-it-mathjax3": "^4",
@ -209,5 +209,5 @@
"optional": true
}
},
"packageManager": "pnpm@10.28.2"
"packageManager": "pnpm@10.32.1"
}

File diff suppressed because it is too large Load Diff

@ -1,7 +1,11 @@
.dark .shiki span {
color: var(--shiki-dark, inherit);
text-decoration: var(--shiki-dark-text-decoration, inherit);
font-weight: var(--shiki-dark-font-weight, inherit);
}
html:not(.dark) .shiki span {
color: var(--shiki-light, inherit);
text-decoration: var(--shiki-light-text-decoration, inherit);
font-weight: var(--shiki-light-font-weight, inherit);
}

@ -15,6 +15,7 @@ import { titlePlugin } from '@mdit-vue/plugin-title'
import { tocPlugin, type TocPluginOptions } from '@mdit-vue/plugin-toc'
import { slugify as defaultSlugify } from '@mdit-vue/shared'
import type {
CodeToHastOptions,
LanguageInput,
ShikiTransformer,
ThemeRegistrationAny
@ -131,6 +132,12 @@ export interface MarkdownOptions extends MarkdownItAsyncOptions {
* @see https://shiki.style/guide/transformers
*/
codeTransformers?: ShikiTransformer[]
/**
* Color replacements applied during syntax highlighting.
* Accepts either a flat color map or per-theme replacements.
* @see https://shiki.style/guide/theme-colors#color-replacements
*/
colorReplacements?: CodeToHastOptions['colorReplacements']
/**
* Setup Shiki instance
*/

@ -193,7 +193,29 @@ export async function highlight(
meta: { __raw: attrs },
...(typeof theme === 'object' && 'light' in theme && 'dark' in theme
? { themes: theme, defaultColor: false }
: { theme })
: { theme }),
colorReplacements: {
'github-light': {
'#959da5': '#6c676f',
'#28a745': '#0e790b',
'#b08800': '#846312',
'#e36209': '#c13617',
'#3192aa': '#05728b',
'#d73a49': '#c62739',
'#22863a': '#11782a',
'#6a737d': '#62687b',
'#1b7c83': '#06747a',
'#0366d6': '#0663d0',
'#cb2431': '#c82430'
},
'github-dark': {
'#586069': '#5b93a3',
'#6a737d': '#818e99',
'#ea4a5a': '#ef5564',
'#2188ff': '#268bf9'
},
...options.colorReplacements
}
})
return restoreMustache(highlighted)

Loading…
Cancel
Save