如何给代码添加语法高亮

使用 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 Highlighter 和 Prism 作为底层高亮器。这个决定与我使用 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)

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