如何给代码添加语法高亮

使用 Shiki 实现语法高亮,帮助您避免常见陷阱

Frontend
如何给代码添加语法高亮

概述

语法高亮是任何包含代码片段的技术博客的基本功能。研究表明,颜色编码的语法可以将代码理解能力提高多达 20%,使读者更容易理解和参与技术内容。它通过使代码视觉上更吸引人且更易读,清楚地区分关键字、字符串和注释等元素来增强参与度。在重建我的博客时,我花费了大量时间研究如何有效地实现语法高亮。

有几个成熟的解决方案可用,例如 Prism 因其基于正则表达式的效率而闻名,React Syntax Highlighter 因其与 React 的无缝集成而著称。但是,由于文档有限以及混合不同解决方案时的冲突(如样式不一致、依赖项重复或客户端和服务器端渲染之间的不兼容性),实现过程可能具有挑战性。在这里,我记录了我成功的方法以供将来参考。

背景

  1. 框架: Next.js

  2. 内容: MDX

  3. 托管: Cloudflare Pages

可用选项

  1. React Syntax Highlighter:在 React 生态系统中广泛使用。

  2. Prism:基于正则表达式的实现,支持服务器端和客户端使用。

  3. Shiki:通常与 Unified 生态系统一起使用,在服务器端工作。

  4. Rehype Highlight:Rehype 的插件,是 HTML 的 Unified 处理器的一部分。

服务器端还是客户端?

语法高亮解决方案可以分类为:

对于服务器端解决方案,最常见的方法是使用 Unified 生态系统。Unified 是一个用于处理 Markdown 或 HTML 等内容的模块化框架,允许解析器、转换器和编译器的无缝集成。有关更多详细信息,请访问 Unified 文档

Unified 架构

ascii

无服务器注意事项

在像 Cloudflare Workers 或 Pages 这样的无服务器环境中,适用某些限制。例如,dangerouslySetInnerHTML 被禁止,因为它可能引入跨站脚本(XSS)等安全漏洞。在无服务器环境中,此限制确保了更高的安全性,但也限制了直接注入预编译 HTML 的能力,需要替代方法来渲染语法高亮的内容。

使用 Shiki 时,请注意 Cloudflare Workers 不支持从二进制数据初始化 WebAssembly。相反,您必须将 WebAssembly(WASM)文件作为资产上传并直接导入,如 Shiki 文档中所解释的。

选择的路径

我选择了 React Syntax HighlighterPrism 作为底层高亮器。这个决定与我使用 Next.js 以及由于无服务器限制而需要客户端解决方案相一致。选择 Prism 是因为其速度和兼容性。

使用 React Syntax Highlighter

Prism.js 还是 Highlight.js?

Prism.js 和 Highlight.js 都是流行的语法高亮库,但它们在关键方面有所不同:

  • Prism.js 更现代、轻量级且可定制。它使用基于正则表达式的解析,支持插件,并需要手动指定语言,使其适用于性能关键的应用程序。

  • Highlight.js 以其自动语言检测而闻名,使其更适合初学者且在需要语言检测时更易于集成。

在这个项目中,我选择了 Highlight.js,因为它支持自动语言检测,在未指定语言的情况下简化了实现。但是,与 Prism.js 相比,Highlight.js 有一些缺点,例如可定制性较差且包大小更大,这可能会在资源受限的环境中影响性能。

样式选项

使用 style 属性

  • 优点: 避免 CSS 冲突。

  • 缺点: 无法重用主题的样式。

使用 className 属性

  • 优点: 允许重用主题的样式。

  • 缺点: 切换主题时可能出现 CSS 冲突。

管理主题特定的 CSS

当在明暗主题之间切换时,例如通过导入不同的 CSS 文件,CSS 文件会发生冲突,因为以前的文件没有被移除。有一个天才的想法来解决这个问题:

tsx

这种方法的一个缺点是我们需要在项目中手动管理 CSS 文件:

bash

语法高亮示例

CPP

cpp

Python

python

JavaScript

javascript

Bash

bash

SQL

sql

JSON

json

YAML

yaml

Markdown

markdown

HTML

html

CSS

css

结论

语法高亮是创建引人入胜且易于访问的技术内容的关键功能。Prism.js 提供现代功能、轻量级性能和可定制性,使其非常适合对语法渲染进行精确控制。相比之下,Highlight.js 提供自动语言检测和易用性,但对于性能关键的应用程序可能效率较低。理解这些权衡有助于确保做出符合特定需求的明智选择。

虽然由于无服务器约束和兼容性问题,实现过程可能很复杂,但像 React Syntax Highlighter 和 Prism 这样的解决方案使其变得可行。通过仔细考虑您的框架、托管环境和定制需求,您可以选择一个既提供功能又具有视觉吸引力的博客策略。通过这次探索,我希望能够澄清这个过程并授权其他人创建更好的技术博客。

Recommended Posts

回复 (0)

还没有评论。成为第一个分享想法的人!