SvelteKit中为数据库存储的Markdown添加语法高亮遇阻求助
问题
我正在开发一款带浏览器端Markdown编辑器的博客,用marked等解析器能正常渲染Markdown内容,但给代码块加语法高亮时碰到了问题。我用marked自定义了解析器,但getHighlighter没有从node_modules读取资源,反而去请求我的API路由,报404错误。
我试过highlight.js、prism等多款高亮工具,还有mark-it等同类型解析器,多数都没法实现语法高亮,不确定是SvelteKit的问题还是高亮工具的问题。
相关代码:
// utils.ts import {Marked} from 'marked' import {getHighlighter} from 'shiki' export const marked = new Marked( markedHighlight({ async: true, async highlight(code, lang) { const highlighter = await getHighlighter({ theme: 'nord' }); const html = highlighter.codeToHtml(code, { lang }); return html; } }) ); // +page.ts async function load({params}){ ... return await marked.parse(txt) }
报错信息:
SvelteKitError: Not found: /themes/nord.json at resolve (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\respond.js:495:13) at resolve (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\respond.js:295:5) at #options.hooks.handle (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\index.js:63:56) at Module.respond (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\respond.js:292:40) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { status: 404, text: 'Not Found' } SvelteKitError: Not found: /dist/onig.wasm at resolve (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\respond.js:495:13) at resolve (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\respond.js:295:5) at #options.hooks.handle (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\index.js:63:56) at Module.respond (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\respond.js:292:40) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { status: 404, text: 'Not Found' } SvelteKitError: Not found: /themes/nord.json at resolve (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\respond.js:495:13) at resolve (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runruntime\server\respond.js:295:5) at #options.hooks.handle (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\index.js:63:56) at Module.respond (C:\Users\leung\OneDrive\Desktop\Programming\mdsvex\markdown-blog-mdsvex-ts\node_modules\@sveltejs\kit\src\runtime\server\respond.js:292:40) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { status: 404, text: 'Not Found' }
解决方案
针对Shiki的问题
Shiki在浏览器环境默认会从CDN加载主题和语法文件,但SvelteKit的路由规则会把这些请求当成API路由处理,导致404。解决方法有两种:
1. 预加载主题和语法(推荐服务端渲染场景)
在服务端预加载所需的主题和语法,避免浏览器端请求资源。修改utils.ts:
import {Marked} from 'marked' import {getHighlighter, loadTheme, loadLanguage} from 'shiki' // 预加载主题和常用语言 const nordTheme = await loadTheme('node_modules/shiki/themes/nord.json'); const tsLanguage = await loadLanguage('typescript'); const jsLanguage = await loadLanguage('javascript'); export const marked = new Marked( markedHighlight({ async: true, async highlight(code, lang) { const highlighter = await getHighlighter({ themes: [nordTheme], languages: [tsLanguage, jsLanguage], defaultTheme: 'nord' }); return highlighter.codeToHtml(code, { lang }); } }) );
注意:这种方式要确保代码在服务端运行,如果是客户端组件,需要用load函数在服务端完成解析,或者把高亮逻辑放到服务端。
2. 配置Shiki的资源加载路径
如果要在客户端使用Shiki,需要把Shiki的资源文件(主题、onig.wasm)复制到SvelteKit的static目录,然后指定资源路径:
import {getHighlighter} from 'shiki' const highlighter = await getHighlighter({ theme: 'nord', paths: { // 假设把shiki的themes和dist目录复制到static/shiki下 themes: '/shiki/themes/', wasm: '/shiki/dist/onig.wasm' } });
改用更适配SvelteKit的方案
如果Shiki配置太麻烦,可以试试mdsvex(你项目里已经有相关目录),它内置了语法高亮支持,配合rehype-highlight或者rehype-shiki就能快速实现:
- 安装依赖:
npm install mdsvex rehype-highlight
- 在
svelte.config.js里配置mdsvex:
import {mdsvex} from 'mdsvex'; import rehypeHighlight from 'rehype-highlight'; export default { extensions: ['.svelte', '.md'], preprocess: mdsvex({ rehypePlugins: [rehypeHighlight] }) };
这样直接写Markdown文件就能自动高亮代码块,不用手动调用marked解析。
其他高亮工具的注意点
- highlight.js:确保在客户端组件里初始化,或者在服务端渲染时直接生成带高亮类的HTML,然后引入对应的CSS文件。
- Prism.js:需要在客户端引入Prism的JS和CSS,并且确保代码块在DOM加载完成后调用
Prism.highlightAll()。
内容的提问来源于stack exchange,提问作者marcopopo
相关产品推荐
相关产品推荐

