赞
踩
目录
最近项目有代码高亮的需求,这边是选用 Prism.js 来进行代码高亮。
Prism 是一款轻量级、可扩展的语法高亮器,根据现代 Web 标准构建,应用广泛。
文档: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="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 有多种插件可以使用,这里介绍几个常用的插件。
在代码块中显示代码块对应语言的名称
Show Language ▲ Prism pluginshttps://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>
在代码块中显示行号
Line Numbers ▲ Prism pluginshttps://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>
通过添加 "line-numbers" class 来为代码块(<pre><code>)添加行号。
如果将 "line-numbers" class 添加到 <body> 中,则为所有代码块(<pre><code>)添加行号。
此外,我们可以使用 "no-line-numbers" class 来移除行号。
标准化代码块中的空白字符Normalize Whitespace ▲ Prism pluginshttps://prismjs.com/plugins/normalize-whitespace/
默认情况下,该插件会裁剪每个代码块的所有前端和尾部空白字符,并移除每行上多余的缩进和尾部空白字符。
可以通过添加 "no-whitespace-normalization" class 来阻止该插件生效。
示例代码
- <!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="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 插件情况下,代码块前端的空白字符被移除,更为美观。
编写标记语言而无需转义任何内容
Unescaped markup ▲ Prism pluginshttps://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>
添加一个按钮,可以在单击时将代码块内容复制到剪贴板
Copy to Clipboard ▲ Prism pluginshttps://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>
显示隐藏字符,例如制表符和换行符
Show Invisibles ▲ Prism pluginshttps://prismjs.com/plugins/show-invisibles/
在下载界面选择需要的语言和插件,下载 js 和 css, 然后导入使用
- <!DOCTYPE html>
- <html>
- <head>
- ...
- <link href="prism.css" rel="stylesheet" />
- </head>
- <body>
- ...
- <script src="prism.js"></script>
- </body>
- </html>
可以使用 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="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>
- 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>
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="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 中无法使用 <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 + v-html 来渲染标记语言。
使用 <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 代码检查工具。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。