Nuxt.js中使用CKEditor并添加代码高亮功能

初衷是为了给本博客系统找一款支持代码编辑和高亮的富文本框组件,基于此,首先是寻找富文本框组件,以前在
Vue中用过CKEditor和wangEditor,前者功能全面强大,后者简洁易用。又搜索了一翻,从熟悉程度、文档完整性、更新支持程度最终选择了CKEditor。

打开CKEditor官网,发现有两个版本可供选择:CKEditor4和CKEditor5。从官方文档了解到,CKEditor5几乎完全重写,更组件化,更符合现代框架,并且有官方出品的ckeditor-vue组件加持,更易使用和集成,于是首先选择了CKEditor5。

Nuxt.js中添加和使用CKEditor5的步骤

1、NPM安装CKEditor5及ckeditor5-vue组件:

1
npm install @ckeditor/ckeditor5-build-classic @ckeditor/ckeditor5-vue --save

注:此处选择官方已构建好的classic版本,官方构建的其它版本还有 ckeditor5-build-inlineckeditor5-build-balloonckeditor5-build-decoupled-document,另外也可以自行构建,参考官方文档:Creating custom builds

2、在项目中plugins目录下创建ckeditor.js(作为ckeditor5-vue引入的插件),代码如下:

1
2
3
import Vue from 'vue'
import CKEditor from '@ckeditor/ckeditor5-vue'
Vue.use(CKEditor)

3、在nuxt.config.js中配置,plugins中增加一行如下:

1
{ src: '~/plugins/ckeditor', ssr: false }

4、在vue文件中使用CKEditor,参考官方文档:Rich text editor component for Vue.js

在Nuxt.js中惟一不同的是需要将

1
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'

替换为:

1
2
3
4
let ClassicEditor
if (process.browser) {
ClassicEditor = require('@ckeditor/ckeditor5-build-classic')
}

否则会报 ‘window is not defined’ 错误,这是因为服务端渲染并没有window对象,而CKEditor源码中使用到了window对象,因此需要判断在浏览器端渲染时才引入CKEditor。此问题的官方说明参考:Window 或 Document 对象未定义?

至此,搞定了富文本编辑器,接下来就是代码高亮功能了。百度和Google了一圈,发现CKEditor5并没有官方支持的代码高亮解决方案,并且在Github上的issue中,官方开发人员将此功能加入到Roadmap中,承诺将在后续版本中开发,见贴:Code blocks #436,其中可见从17年12月到现在快一年时间了,仍没有等到该功能的加入。

随后发现另外两个大牛写的扩展:opf/ckeditor5-code-blockYeolar/ckeditor5-code-block,但是都报错,无法使用,只得继续搜索,终于发现这篇博文:CKEditor代码高亮显示插件Code Snippet安装及使用方法,看到了一丝曙光,于是果断放弃CKEditor5,改用CKEditor4。

Nuxt.js中添加和使用CKEditor4的步骤

1、到CKEditor官网CodeSnippet插件下载包含了Code Snippet插件的CKEditor4压缩包,具体步骤见上面的博文链接;

2、将压缩包解压后放到Nuxt项目中static目录下;

3、配置nuxt.config.js中的head节,增加script标签对static中ckeditor.js的引用,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
head: {
title: 'hello,world',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'hello,world' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
],
// 添加如下代码,对ckeditor.js的引用
script: [
{ src: '/ckeditor/ckeditor.js' }
]
}

4、在.vue文件中使用ckeditor4,为了避免烦琐的初始化、事件监听等步骤,可直接使用开源的vue-ckeditor2

终于经过一番折腾,搞定了代码高亮的编辑,接下来就是代码高的显示问题了,支持代码高亮的库有prismjshighlight.js等,这两个库都支持CodeSnippet插件生成的代码格式,经过比较之后选择了prismjs。

Nuxt.js中使用prismjs处理代码高亮的步骤

1、使用npm安装prismjs:

1
npm install --save prismjs

2、在.vue文件是引入prismjs及其样式:

1
2
import Prism from 'prismjs'
import 'prismjs/themes/prism.css'

3、如果需要显示行号和支持copy功能,则继续引入插件,不需要则忽略此步:

1
2
3
4
5
import 'prismjs/plugins/line-numbers/prism-line-numbers'
import 'prismjs/plugins/line-numbers/prism-line-numbers.css'
import 'prismjs/plugins/toolbar/prism-toolbar'
import 'prismjs/plugins/toolbar/prism-toolbar.css'
import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard'

注:line-numbers为显示代码行号的插件;copy-to-clipboard为复制到粘贴板的插件,其依赖于toolbar插件,需要一并引入。

4、渲染pre代码块,在mounted钩子中加入如下代码:

1
2
3
4
5
6
7
mounted () {
let pres = document.querySelectorAll('pre')
for (let i = 0; i < pres.length; i++) {
pres[i].className += ' line-numbers'
}
Prism.highlightAll()
}

注:如果没有使用任何prismjs插件,可省略此步骤,因为prismjs会自动渲染。

至此,关于代码高亮的编辑和查看就大功告成!