当前位置:   article > 正文

【前端】语法高亮 Prism.js 使用

prism.js

目录

介绍

示例

主题

插件

1、show-language

2、line-numbers

3、normalize-whitespace

4、unescaped-markup

5、copy-to-clipboard

6、show-invisibles

使用

1、直接下载

2、CDN 方式

3、Vue3 中使用

 补充

API

按钮样式调节

Vue3 代码高亮组件(仅供参考)

高亮 script 标签


介绍

最近项目有代码高亮的需求,这边是选用 Prism.js 来进行代码高亮。

Prism 是一款轻量级、可扩展的语法高亮器,根据现代 Web 标准构建,应用广泛。

官网:https://prismjs.com/

文档:https://prismjs.com/docs/index.html

示例

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- 可以通过 CDN 的方式导入 -->
  5. <meta charset="utf-8" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1" />
  7. <title>Prism Test</title>
  8. <link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.css" rel="stylesheet" />
  9. </head>
  10. <body>
  11. <pre class="line-numbers">
  12. <code class="language-cpp">
  13. #include &lt;iostream>
  14. using namespace std;
  15. struct ListNode {
  16. int val;
  17. ListNode *next;
  18. ListNode() : val(0), next(nullptr) {}
  19. ListNode(int x) : val(x), next(nullptr) {}
  20. ListNode(int x, ListNode *next) : val(x), next(next) {}
  21. };
  22. </code>
  23. </pre>
  24. <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js"></script>
  25. <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
  26. <script
  27. src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/normalize-whitespace/prism-normalize-whitespace.min.js"
  28. integrity="sha256-ronWqXsvaeyrdiX7YJfdYj0S5NbeMA5ilQQTrK25Jno="
  29. crossorigin="anonymous"
  30. ></script>
  31. </body>
  32. </html>

主题

Prism.js 支持多种主题

插件

Prism.js 有多种插件可以使用,这里介绍几个常用的插件。

1、show-language

在代码块中显示代码块对应语言的名称

Show Language ▲ Prism pluginsicon-default.png?t=N7T8https://prismjs.com/plugins/show-language

  1. <pre>
  2. <code class="language-js">
  3. function curry(func) {
  4. return function curried(...args) {
  5. if (args.length >= func.length) {
  6. return func.apply(this, args);
  7. } else {
  8. return function(...args2) {
  9. return curried.apply(this, args.concat(args2));
  10. }
  11. }
  12. };
  13. }
  14. </code>
  15. </pre>

2、line-numbers

在代码块中显示行号

Line Numbers ▲ Prism pluginsicon-default.png?t=N7T8https://prismjs.com/plugins/line-numbers/

  1. <pre class="line-numbers">
  2. <code class="language-js">
  3. function curry(func) {
  4. return function curried(...args) {
  5. if (args.length >= func.length) {
  6. return func.apply(this, args);
  7. } else {
  8. return function(...args2) {
  9. return curried.apply(this, args.concat(args2));
  10. }
  11. }
  12. };
  13. }
  14. </code>
  15. </pre>

通过添加  "line-numbers" class 来为代码块(<pre><code>)添加行号。

如果将 "line-numbers" class 添加到 <body> 中,则为所有代码块(<pre><code>)添加行号。

此外,我们可以使用 "no-line-numbers" class 来移除行号。

3、normalize-whitespace

标准化代码块中的空白字符Normalize Whitespace ▲ Prism pluginsicon-default.png?t=N7T8https://prismjs.com/plugins/normalize-whitespace/

默认情况下,该插件会裁剪每个代码块的所有前端和尾部空白字符,并移除每行上多余的缩进和尾部空白字符。

可以通过添加 "no-whitespace-normalization" class 来阻止该插件生效。

示例代码

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1" />
  6. <title>Prism Test</title>
  7. <link href="prism.css" rel="stylesheet" />
  8. </head>
  9. <body>
  10. <pre>
  11. <code class="language-js">
  12. function curry(func) {
  13. return function curried(...args) {
  14. if (args.length >= func.length) {
  15. return func.apply(this, args);
  16. } else {
  17. return function(...args2) {
  18. return curried.apply(this, args.concat(args2));
  19. }
  20. }
  21. };
  22. }
  23. </code>
  24. </pre>
  25. <script src="prism.js"></script>
  26. </body>
  27. </html>
 不使用 normalize-whitespace 插件情况
使用  normalize-whitespace 插件情况

可以看到在使用  normalize-whitespace 插件情况下,代码块前端的空白字符被移除,更为美观。

4、unescaped-markup

编写标记语言而无需转义任何内容

Unescaped markup ▲ Prism pluginsicon-default.png?t=N7T8https://prismjs.com/plugins/unescaped-markup/

可以使用 <script type="text/plain" class="language-markup"> 方式

  1. <script type="text/plain" class="language-markup">
  2. <html></html>
  3. <p>Example</p>
  4. <div><button>Hello</button></div>
  5. </script>

 也可以使用 <pre><code class="language-markup"><!-- --></code></pre> 方式

  1. <pre>
  2. <code class="language-markup"><!--
  3. <html></html>
  4. <p>Example</p>
  5. <div><button>Hello</button></div>
  6. --></code>
  7. </pre>

5、copy-to-clipboard

添加一个按钮,可以在单击时将代码块内容复制到剪贴板

Copy to Clipboard ▲ Prism pluginsicon-default.png?t=N7T8https://prismjs.com/plugins/copy-to-clipboard/默认情况下,插件以英语显示消息,并设置 5 秒的间隔复制时间。

可以使用以下属性来覆盖默认设置:

data-prismjs-copy — 默认情况下复制按钮显示的文字
data-prismjs-copy-error — 复制失败时显示的信息
data-prismjs-copy-success — 复制成功时显示的信息
data-prismjs-copy-timeout — 两次复制允许的间隔时间

  1. <pre>
  2. <code class="language-js"
  3. data-prismjs-copy="复制"
  4. data-prismjs-copy-error="复制失败"
  5. data-prismjs-copy-success="复制成功"
  6. >
  7. let range = new Range();
  8. range.setStart(p1.firstChild, 2);
  9. range.setEndAfter(p2.firstChild);
  10. document.getSelection().addRange(range);
  11. </code>
  12. </pre>

6、show-invisibles

显示隐藏字符,例如制表符和换行符

Show Invisibles ▲ Prism pluginsicon-default.png?t=N7T8https://prismjs.com/plugins/show-invisibles/

使用

1、直接下载

在下载界面选择需要的语言和插件,下载 js 和 css, 然后导入使用

Download ▲ Prismicon-default.png?t=N7T8https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. ...
  5. <link href="prism.css" rel="stylesheet" />
  6. </head>
  7. <body>
  8. ...
  9. <script src="prism.js"></script>
  10. </body>
  11. </html>

2、CDN 方式

可以使用 cdnjs、jsDelivr 和 UNPKG 等 cdn 导入 PrismJS

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- 通过 CDN 方式导入 -->
  5. <meta charset="utf-8" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1" />
  7. <title>Prism Test</title>
  8. <link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.css" rel="stylesheet" />
  9. </head>
  10. <body>
  11. <pre class="line-numbers">
  12. <code class="language-cpp">
  13. #include &lt;iostream>
  14. using namespace std;
  15. struct ListNode {
  16. int val;
  17. ListNode *next;
  18. ListNode() : val(0), next(nullptr) {}
  19. ListNode(int x) : val(x), next(nullptr) {}
  20. ListNode(int x, ListNode *next) : val(x), next(next) {}
  21. };
  22. </code>
  23. </pre>
  24. <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js"></script>
  25. <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
  26. <script
  27. src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/normalize-whitespace/prism-normalize-whitespace.min.js"
  28. integrity="sha256-ronWqXsvaeyrdiX7YJfdYj0S5NbeMA5ilQQTrK25Jno="
  29. crossorigin="anonymous"
  30. ></script>
  31. </body>
  32. </html>

3、Vue3 中使用

  1. npm install prismjs
  2. # 支持 typescript
  3. npm install @types/prismjs -D
  4. npm install vite-plugin-prismjs -D

vite.config.js 中配置

  1. import prismjs from 'vite-plugin-prismjs';
  2. export default defineConfig({
  3. plugins: [
  4. prismjs({
  5. languages: ['javascript', 'css', 'html', 'json', 'sass', 'scss', 'md', 'bash', 'shell', 'ts'],
  6. plugins: [
  7. 'toolbar',
  8. 'show-language',
  9. 'copy-to-clipboard',
  10. 'normalize-whitespace',
  11. 'line-numbers',
  12. 'unescaped-markup'
  13. ],
  14. theme: 'tomorrow',
  15. css: true
  16. })
  17. ],
  18. });

基本使用

  1. <template>
  2. <pre class="line-numbers">
  3. <code class='language-js'>
  4. // JavaScript 代码
  5. function curry(func) {
  6. return function curried(...args) {
  7. if (args.length >= func.length) {
  8. return func.apply(this, args);
  9. } else {
  10. return function(...args2) {
  11. return curried.apply(this, args.concat(args2));
  12. }
  13. }
  14. };
  15. }
  16. </code>
  17. </pre>
  18. </template>
  19. <script setup>
  20. import { onMounted } from 'vue';
  21. import Prism from 'prismjs';
  22. onMounted(() => {
  23. Prism.highlightAll();
  24. });
  25. </script>
  26. <style lang="scss" scoped></style>

 补充

API

Prism.js 提供了一些 API

详见:https://prismjs.com/docs/Prism.html#.manual

如:

highlight(text, grammar, language) → {string}

  1. // 例子
  2. Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');

按钮样式调节

我们可能对代码块右上角按钮的样式不太满意,可以对此进行一定的调整。

如:

按钮变为方框,改变光标类型
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1" />
  6. <title>Prism Test</title>
  7. <link href="prism.css" rel="stylesheet" type="text/css" />
  8. <style>
  9. body {
  10. margin: 0;
  11. padding: 0;
  12. height: 100vh;
  13. }
  14. div.code-toolbar > .toolbar {
  15. opacity: 1;
  16. }
  17. .toolbar .toolbar-item span,
  18. .toolbar .toolbar-item button {
  19. border-radius: 0 !important;
  20. margin: 0 6px;
  21. }
  22. .copy-to-clipboard-button:hover {
  23. cursor: pointer;
  24. }
  25. </style>
  26. </head>
  27. <body>
  28. <pre class="line-numbers">
  29. <code class="language-js"
  30. data-prismjs-copy="复制"
  31. data-prismjs-copy-error="复制失败"
  32. data-prismjs-copy-success="复制成功"
  33. >
  34. let range = new Range();
  35. range.setStart(p1.firstChild, 2);
  36. range.setEndAfter(p2.firstChild);
  37. document.getSelection().addRange(range);
  38. </code>
  39. </pre>
  40. <script src="prism.js"></script>
  41. </body>
  42. </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 +  v-html 来渲染标记语言。

高亮 script 标签

使用 <script type="text/plain" class="language-markup"> 方式高亮标记语言时,如果要高亮 <script> 标签则需要转义。

  1. <script type="text/plain" class="language-markup">
  2. <html></html>
  3. <p>Example</p>
  4. <div><button>Hello</button></div>
  5. <script>&lt;/script>
  6. </script>

此外,在 Vue3 中通过 API 渲染 <script> 标签时,转义后,可能会引起 eslint 报错,可以通过配置 'no-useless-escape': 'off' 等方式解决,见 配置规则 - ESLint - 插件化的 JavaScript 代码检查工具

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/754609
推荐阅读
相关标签
  

闽ICP备14008679号