代码高亮是我一直以来都在纠结的问题,市面上的高亮组件特别繁多,我用过例如 syntaxhighlight
、highlight.js
等组件,觉得都不太好用,要么是样式不好看、支持的语法不齐全,要么就是使用太过麻烦等等。
今天经过我的仔细甄选后,终于在 gayhub
上发现了这个宝藏:PrismJS
进入它的官网,你会发现它所支持的几款主题,我非常喜欢 OKAIDIA 这个主题,代码风格如下:
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
public function render($request, Exception $exception)
{
return parent::render($request, $exception);
}
}
是不是有种似曾相识的感觉?没错,很多社区都在用这个组件,例如
终于等到你~嘻嘻,下面开始正文
在 Vue 项目中安装及使用
直接使用 npm 安装 prismjs
及其 babel
:
npm install prismjs
npm install babel-plugin-prismjs
接着在 .babelrc 中配置语言及主题:
"plugins": [
[
"prismjs",
{
"languages": ["html", "css", "javascript", "php", "dart", "bash", "nginx", "sql"],
"theme": "okaidia"
}
]
]
以上是我所用的语言及暗黑主题,可以根据自己的需求自定义,更多语言支持
配置完毕后,在组件中引入 JS:
import Prism from 'prismjs';
引入 CSS:
code[class*="language-"],
pre {
color: #f8f8f2;
background: none;
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Code blocks */
pre {
padding: 1em;
margin: .5em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre) > code[class*="language-"],
pre {
/*background: #272822;*/
background: #384548;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #f8f8f2;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
color: #ffa07a;
}
.token.boolean,
.token.number {
color: #ae81ff;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #a6e22e;
}
.token.operator {
color: #00e0e0;
}
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
color: #f8f8f2;
}
.token.atrule,
.token.attr-value,
.token.function,
.token.class-name {
color: #e6db74;
}
.token.keyword {
color: #66d9ef;
}
.token.regex,
.token.important {
color: #fd971f;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
我对官方的 css 内容做了部分更改,使代码看起来不是那么刺眼,如果你不喜欢我的优化,可以出门左转去官网下载。
即时渲染代码块
正常情况下,我们肯定都是想在编辑器中输入完代码就能渲染出效果,但是编辑器也是各式各样的,也基本不可能内置这个高亮组件,所以我接下来讲解一种可以在任意编辑器中进行即时渲染的做法:那就是借助 MutationObserver
这个强大的 DOM3 API。
无论是 markdown 编辑器还是富文本编辑器,编辑器页面中呈现出来的都有一份 HTML 代码,我们就用 MutationObserver
来监听 HTML 的变化即可,每次发生变化就立刻让 prismjs 对所有 code
标签里的内容重新渲染即可。
具体实现如下:
const languages = ['html', 'css', 'js', 'php', 'dart', 'bash', 'nginx', 'sql'],
content = document.querySelector('.v-show-content'),
codeNodes = content.getElementsByTagName('code');
this.observer = new MutationObserver(() => {
let nodesLength = codeNodes.length, codeNode, language;
while (nodesLength--) {
codeNode = codeNodes[nodesLength];
language = codeNode.className.split('-')[1];
if (languages.includes(language)) {
codeNode.innerHTML = Prism.highlight(codeNode.innerText, Prism.languages[language], language);
}
}
this.html = content.innerHTML;
this.text = content.innerText;
});
this.observer.observe(content, {
childList: true,
characterData: true,
});
以上代码,当 .v-show-content
这个元素的内容发生改变时,就会触发 MutationObserver
的回调函数。
在回调函数中,我对所有 code
标签进行了遍历,每次循环都会判断语言是否支持,支持就直接渲染。
在回调函数的最后部分,渲染完毕将 HTML 内容重新赋值给编辑器组件,提供给外部使用。
