本文详细介绍轻量级前端语法高亮插件Prism.js的使用方法。涵盖从官网下载、CDN引入到Vue3环境下的具体集成步骤。文中重点解析show-language、line-numbers、copy-to-clipboard等常用插件的配置与API调用,并提供处理script标签转义及按钮样式自定义的实战技巧,帮助开发者快速实现美观的代码展示功能。
介绍
近期开发项目中涉及代码展示功能,经过评估,最终决定采用 Prism.js 来实现代码高亮效果。
Prism 是一款基于现代 Web 标准构建的轻量级且支持扩展的语法高亮工具,在业界拥有广泛的应用。
官方网站地址:https://prismjs.com/
官方文档地址:https://prismjs.com/docs/index.html
示例

<!DOCTYPE html>
<html>
<head>
<!-- 可以通过 CDN 的方式导入 -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Prism Test</title>
<link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.css" rel="external nofollow" rel="external nofollow" rel="stylesheet" />
</head>
<body>
<pre class="line-numbers">
<code class="language-cpp">
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
</code>
</pre>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/normalize-whitespace/prism-normalize-whitespace.min.js"
integrity="sha256-ronWqXsvaeyrdiX7YJfdYj0S5NbeMA5ilQQTrK25Jno="
crossorigin="anonymous"
></script>
</body>
</html>
主题
Prism.js 提供了丰富的主题供开发者选择。

插件
Prism.js 支持多种插件扩展,以下将介绍几种常用插件的使用方法。

1、show-language
该插件用于在代码块中显示当前代码对应的语言名称。
Show Language 插件详情:https://prismjs.com/plugins/show-language

<pre>
<code class="language-js">
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
}
}
};
}
</code>
</pre>2、line-numbers
该插件用于在代码块中显示行号。
Line Numbers 插件详情:https://prismjs.com/plugins/line-numbers/

<pre class="line-numbers">
<code class="language-js">
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
}
}
};
}
</code>
</pre>只需为代码块(<pre><code>)添加 "line-numbers" 类即可显示行号。
若将 "line-numbers" 类添加至 <body> 元素,则页面中所有代码块(<pre><code>)均会自动显示行号。
此外,可通过添加 "no-line-numbers" 类来单独移除特定代码块的行号显示。
3、normalize-whitespace
标准化代码块中的空白字符 Normalize Whitespace 插件详情:https://prismjs.com/plugins/normalize-whitespace/
默认情况下,该插件会裁剪每个代码块首尾的空白字符,并移除每行多余的缩进及尾部空白。
若需禁用该插件的功能,可添加 "no-whitespace-normalization" 类。
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Prism Test</title>
<link href="prism.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet" />
</head>
<body>
<pre>
<code class="language-js">
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
}
}
};
}
</code>
</pre>
<script src="prism.js"></script>
</body>
</html>
未使用 normalize-whitespace 插件时的效果

使用 normalize-whitespace 插件后的效果
对比可见,启用 normalize-whitespace 插件后,代码块前端的空白字符被自动移除,视觉效果更加整洁美观。
4、unescaped-markup
允许编写标记语言而无需进行转义处理。
Unescaped markup 插件详情:https://prismjs.com/plugins/unescaped-markup/

可使用 <script type="text/plain" class="language-markup"> 标签包裹内容进行高亮。
<script type="text/plain" class="language-markup">
<html></html>
<p>Example</p>
<div><button>Hello</button></div>
</script>也可使用 <pre><code class="language-markup"><!-- --></code></pre> 方式包裹内容。
<pre>
<code class="language-markup"><!--
<html></html>
<p>Example</p>
<div><button>Hello</button></div>
--></code>
</pre>5、copy-to-clipboard
该插件在代码块中添加一个按钮,点击即可将代码内容复制到剪贴板。
Copy to Clipboard 插件详情:https://prismjs.com/plugins/copy-to-clipboard/ 默认情况下,插件以英语显示提示信息,并设置 5 秒的复制间隔。
可通过以下属性覆盖默认设置:
- data-prismjs-copy — 定义复制按钮默认显示的文本。
- data-prismjs-copy-error — 定义复制失败时显示的错误信息。
- data-prismjs-copy-success — 定义复制成功时显示的提示信息。
- data-prismjs-copy-timeout — 定义允许两次复制操作之间的最小时间间隔。

<pre>
<code class="language-js"
data-prismjs-copy="复制"
data-prismjs-copy-error="复制失败"
data-prismjs-copy-success="复制成功"
>
let range = new Range();
range.setStart(p1.firstChild, 2);
range.setEndAfter(p2.firstChild);
document.getSelection().addRange(range);
</code>
</pre>6、show-invisibles
该插件用于显示隐藏字符,如制表符和换行符。
Show Invisibles 插件详情:https://prismjs.com/plugins/show-invisibles/

使用
1、直接下载
在下载界面选择所需的编程语言和插件,下载对应的 js 和 css 文件后导入项目使用。
下载页面:https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript

<!DOCTYPE html>
<html>
<head>
...
<link href="prism.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet" />
</head>
<body>
...
<script src="prism.js"></script>
</body>
</html>
2、CDN 方式
可通过 cdnjs、jsDelivr 和 UNPKG 等 CDN 服务直接引入 PrismJS。

<!DOCTYPE html>
<html>
<head>
<!-- 通过 CDN 方式导入 -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Prism Test</title>
<link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.css" rel="external nofollow" rel="external nofollow" rel="stylesheet" />
</head>
<body>
<pre class="line-numbers">
<code class="language-cpp">
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
</code>
</pre>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/normalize-whitespace/prism-normalize-whitespace.min.js"
integrity="sha256-ronWqXsvaeyrdiX7YJfdYj0S5NbeMA5ilQQTrK25Jno="
crossorigin="anonymous"
></script>
</body>
</html>3、Vue3 中使用
npm install prismjs
# 支持 typescript
npm install @types/prismjs -D
npm install vite-plugin-prismjs -D在 vite.config.js 中进行相关配置。
import prismjs from 'vite-plugin-prismjs';
export default defineConfig({
plugins: [
prismjs({
languages: ['javascript', 'css', 'html', 'json', 'sass', 'scss', 'md', 'bash', 'shell', 'ts'],
plugins: [
'toolbar',
'show-language',
'copy-to-clipboard',
'normalize-whitespace',
'line-numbers',
'unescaped-markup'
],
theme: 'tomorrow',
css: true
})
],
});基本使用

<template>
<pre class="line-numbers">
<code class='language-js'>
// JavaScript 代码
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
}
}
};
}
</code>
</pre>
</template>
<script setup>
import { onMounted } from 'vue';
import Prism from 'prismjs';
onMounted(() => {
Prism.highlightAll();
});
</script>
<style lang="scss" scoped></style>
补充
API
Prism.js 提供了一些可用的 API 接口。
详细文档:https://prismjs.com/docs/Prism.html#.manual
例如:
highlight(text, grammar, language) → {string}
// 例子
Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');

按钮样式调节
若对代码块右上角按钮的默认样式不满意,可进行自定义调整。
例如:

将按钮调整为方框样式,并改变鼠标光标类型。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Prism Test</title>
<link href="prism.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet" type="text/css" />
<style>
body {
margin: 0;
padding: 0;
height: 100vh;
}
div.code-toolbar > .toolbar {
opacity: 1;
}
.toolbar .toolbar-item span,
.toolbar .toolbar-item button {
border-radius: 0 !important;
margin: 0 6px;
}
.copy-to-clipboard-button:hover {
cursor: pointer;
}
</style>
</head>
<body>
<pre class="line-numbers">
<code class="language-js"
data-prismjs-copy="复制"
data-prismjs-copy-error="复制失败"
data-prismjs-copy-success="复制成功"
>
let range = new Range();
range.setStart(p1.firstChild, 2);
range.setEndAfter(p2.firstChild);
document.getSelection().addRange(range);
</code>
</pre>
<script src="prism.js"></script>
</body>
</html>
Vue3 代码高亮组件(仅供参考)
在 Vue3 环境中,无法直接使用 <script type="text/plain" class="language-markup"> 方式对标记语言进行高亮。
若需封装代码高亮组件,对于非标记语言,可采用 <pre><code class="language-xxx"></code></pre> 结合 slot 插槽的方式渲染;
对于标记语言,则使用 <pre><code class="language-markup"></code></pre> 结合 props 属性、Prism.highlight API 及 v-html 指令进行渲染。
高亮 script 标签
在使用 <script type="text/plain" class="language-markup"> 方式高亮标记语言时,若内容中包含 <script> 标签,则必须进行转义处理。
例如:

<script type="text/plain" class="language-markup">
<html></html>
<p>Example</p>
<div><button>Hello</button></div>
<script></script>
</script>此外,在 Vue3 中通过 API 渲染 <script> 标签时,转义后的代码可能会触发 eslint 报错。可通过配置 'no-useless-escape': 'off' 等规则解决该问题,具体参考配置规则 - ESLint - 插件化的 JavaScript 代码检查工具。
总结
至此,关于前端语法高亮插件 Prism.js 的详细使用教程介绍完毕。如需了解更多前端语法高亮及 Prism.js 相关内容,欢迎查阅本站过往文章或继续浏览后续文章,感谢大家的支持!