header-bg.jpg
Vue 中使用 prismjs 代码高亮组件
发表于 2019-08-05 01:03
|
分类于 JavaScript
|
评论次数 0
|
阅读次数 935

prismjs.png

代码高亮是我一直以来都在纠结的问题,市面上的高亮组件特别繁多,我用过例如 syntaxhighlighthighlight.js 等组件,觉得都不太好用,要么是样式不好看、支持的语法不齐全,要么就是使用太过麻烦等等。

今天经过我的仔细甄选后,终于在 gayhub 上发现了这个宝藏:PrismJS

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);
    }
}

是不是有种似曾相识的感觉?没错,很多社区都在用这个组件,例如

LearnKu

ReactJS

终于等到你~嘻嘻,下面开始正文

在 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"
      }
    ]
  ]

以上是我所用的语言及暗黑主题,可以根据自己的需求自定义,更多语言支持

.babelrc 使用文档

配置完毕后,在组件中引入 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 内容重新赋值给编辑器组件,提供给外部使用。

发布评论
还没有评论,快来抢沙发吧!