开源好用的所见即所得(WYSIWYG)编辑器:Editor.js

今天介绍一个开源好用的Web所见即所得(WYSIWYG)编辑器:Editor.js

Editor.js 是一个基于 Web 的所见即所得富文本编辑器,它由CodeX团队开发。源代码托管于Github:https://github.com/codex-team/editor.js

特点

它有两个显著的特点,一个是基于区块(block-styled)的编辑模式,另一个是可以输出干净的数据。

基于区块

基于区块官网是这样解释的:

Editor.js工作区由单独的区块组成:段落、标题、图像、列表、引号等。它们中的每一个都是由 Plugin 提供的独立元素(或更复杂的结构)并由 Editor’s Core 连结。

干净的数据

Editor.js 输出干净的json数据而不是 HTML 标记,虽然对浏览器来说,HTML 是更直观的,但对服务器来说,json更精简更关注内容本身,易于重复使用,存储和传输。

对于控件本身也更易于实现,比如在文本“加粗”和“常规”来回切换,基于json的更改一个属性,总要比基于HTML反复添加和删除标记更简单吧?

界面与交互

在编辑区域,Editor.js提供了区块工具栏(Block Tools),内联工具栏(Inline Tools)和区块编辑栏(Block Tunes)

在这里插入图片描述

他们分别通过 加号 + 按钮,选中区块内容和菜单(六个点和尚按钮)来访问

在这里插入图片描述

插件

每个区块都通过插件提供支持,官方提供了常用的插件,当然也可以自己写插件。

官方提供的插件如下图,在sample中,都以cdn方式引入了这些插件,也可以通过npm安装。

在这里插入图片描述

标题和文本

在这里插入图片描述

序列化后的数据如下图所示,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"id" : "zcKCF1S7X8",
"type" : "header",
"data" : {
"text" : "Editor.js",
"level" : 1
}
},
{
"id" : "b6ji-DvaKb",
"type" : "paragraph",
"data" : {
"text" : "支持文本,标题,列表,代办,表格,图片,链接,代码片段,引用片段等等"
}
},

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"id" : "SSBSguGvP7",
"type" : "list",
"data" : {
"style" : "ordered",
"items" : [
{
"content" : "支持普通文本,<i>斜体文本</i>,<b>加粗</b>",
"items" : []
},
{
"content" : "支持<mark class=\"cdx-marker\">文本高亮</mark>、<a href=\"https://baidu.com\">文本链接</a>、<code class=\"inline-code\">代码片段</code><mark class=\"cdx-marker\"></mark>",
"items" : []
}
]
}
},

图片

图片支持Base64编码,和url两种方式上传图片

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
{
"id" : "VYsWoLL7yj",
"type" : "image",
"data" : {
"url" : "data:image/png;base64, ...",
"caption" : "codex2x.png",
"withBorder" : false,
"withBackground" : false,
"stretched" : false
}
}

列表

支持有序和无序列表,列表支持嵌套

在这里插入图片描述

无序列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"id" : "i_cVQxn3Tb",
"type" : "list",
"data" : {
"style" : "unordered",
"items" : [
{
"content" : " 香蕉",
"items" : []
},
{
"content" : " 苹果",
"items" : []
},
{
"content" : " 葡萄 ",
"items" : []
}
]
}
},

有序列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"id" : "nOTdryosj2",
"type" : "list",
"data" : {
"style" : "ordered",
"items" : [
{
"content" : "洗手心",
"items" : []
},
{
"content" : "搓手背",
"items" : []
},
{
"content" : "洗指缝",
"items" : []
}
]
}
},

嵌套列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
"id" : "LJjzlmGa-3",
"type" : "list",
"data" : {
"style" : "unordered",
"items" : [
{
"content" : "序章",
"items" : []
},
{
"content" : "第一章",
"items" : [
{
"content" : "第一节",
"items" : [
{
"content" : "a)",
"items" : []
},
{
"content" : "b)",
"items" : []
},
{
"content" : "c)",
"items" : []
}
]
},
{
"content" : "第二节",
"items" : []
}
]
}
]
}
},

Todo

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"id" : "Hitrs4RqXw",
"type" : "checklist",
"data" : {
"items" : [
{
"text" : "满意",
"checked" : true
},
{
"text" : "一般",
"checked" : false
},
{
"text" : "不满意☹️",
"checked" : false
}
]
}
},

表格

在这里插入图片描述

不代表头:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"id" : "xPAQ6AkUiK",
"type" : "paragraph",
"data" : {
"text" : "<b>不带表头</b>"
}
},
{
"id" : "_MMoOqlgXs",
"type" : "table",
"data" : {
"withHeadings" : false,
"content" : [
[
"<b>重要紧急</b>",
"<b>重要不紧急</b>"
],
[
"吃饭睡觉",
"订生日蛋糕"
],
[
"<b>不重要但紧急</b>",
"<b>不重要不紧急</b>"
],
[
"上班前定好闹钟",
"总结这一周的工作"
]
]
}
},

带表头:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"id" : "fvfQSljMK8",
"type" : "table",
"data" : {
"withHeadings" : true,
"content" : [
[
"星期一",
"星期二",
"星期三",
"星期四",
"星期五"
],
[
"a",
"b",
"c",
"d",
"e"
]
]
}
},

使用

安装

页面中引用Editor.js Core库,可通过npm安装。也可以编译项目,然后引入编译后的js文件。

1
yarn add @editorjs/editorjs

1
2
<script src="lib/editorjs/editorjs.umd.js"></script>

创建编辑器实例

在页面创建编辑器

1
2
3
4
5
6
7
8
9
10

import EditorJS from '@editorjs/editorjs';


const editor = new EditorJS({
/**
* Id of Element that should contain Editor instance
*/
holder: 'editorjs'
});

这是一个最小化的示例。你会发现没有那些默认的工具。因此需要在配置中指定工具。

配置工具

可以通过传入配置对象创建编辑器实例。以下是示例

在这里插入图片描述

holder指定编辑器的容器元素。

1
2
3
4
5
6
7

window.editor = new window.EditorJS({
/**
* Wrapper of Editor
*/
holder: 'editorjs',

配置工具

配置完成后,区块工具栏将呈现一个较为完整的工具列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    /**
* Tools list
*/
tools: {
paragraph: {
config: {
placeholder: "Enter something"
}
},

header: {
class: Header,
inlineToolbar: ['link'],
config: {
placeholder: 'Header'
},
shortcut: 'CMD+SHIFT+H'
},

/**
* Or pass class directly without any configuration
*/
image: ImageTool,

list: {
class: NestedList,
inlineToolbar: true,
shortcut: 'CMD+SHIFT+L'
},

checklist: {
class: Checklist,
inlineToolbar: true,
},

quote: {
class: Quote,
inlineToolbar: true,
config: {
quotePlaceholder: 'Enter a quote',
captionPlaceholder: 'Quote\'s author',
},
shortcut: 'CMD+SHIFT+O'
},


marker: {
class: Marker,
shortcut: 'CMD+SHIFT+M'
},

code: {
class: CodeTool,
shortcut: 'CMD+SHIFT+C'
},

delimiter: Delimiter,

inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+C'
},

linkTool: LinkTool,

embed: Embed,

table: {
class: Table,
inlineToolbar: true,
shortcut: 'CMD+ALT+T'
},

},


/**
* Initial Editor data
*/
data: obj,
onReady: function () {
saveButton.click();
},
});

本地化

可以通过传入i18n配置对象来设置编辑器的本地化。以下是一个较为完整的中文化示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

i18n: {
messages: {
"ui": {
"blockTunes": {
"toggler": {
"Click to tune": "点击转换",
"or drag to move": "拖动调整"
},
},
"inlineToolbar": {
"converter": {
"Convert to": "转换成"
}
},
"toolbar": {
"toolbox": {
"Add": "添加",
"Filter": "过滤",
"Nothing found": "无内容"
},
"popover": {
"Filter": "过滤",
"Nothing found": "无内容"
}
}
},
"toolNames": {
"Text": "段落",
"Heading": "标题",
"List": "列表",
"Warning": "警告",
"Checklist": "清单",
"Quote": "引用",
"Code": "代码",
"Delimiter": "分割线",
"Raw HTML": "HTML片段",
"Table": "表格",
"Link": "链接",
"Marker": "突出显示",
"Bold": "加粗",
"Italic": "倾斜",
"InlineCode": "代码片段",
"Image": "图片"
},
"tools": {
"link": {
"Add a link": "添加链接"
},
"stub": {
'The block can not be displayed correctly.': '该模块不能放置在这里'
},
"image": {
"Caption": "图片说明",
"Select an Image": "选择图片",
"With border": "添加边框",
"Stretch image": "拉伸图像",
"With background": "添加背景",
},
"code": {
"Enter a code": "输入代码",
},
"linkTool": {
"Link": "请输入链接地址",
"Couldn't fetch the link data": "获取链接数据失败",
"Couldn't get this link data, try the other one": "该链接不能访问,请修改",
"Wrong response format from the server": "错误响应",
},
"header": {
"Header": "标题",
"Heading 2": "二级标题",
"Heading 3": "三级标题",
"Heading 4": "四级标题",
"Heading 5": "五级标题",
},
"paragraph": {
"Enter something": "请输入笔记内容",
},
"list": {
"Ordered": "有序列表",
"Unordered": "无序列表",
},
"table": {
"Heading": "标题",
"Add column to left": "在左侧插入列",
"Add column to right": "在右侧插入列",
"Delete column": "删除列",
"Add row above": "在上方插入行",
"Add row below": "在下方插入行",
"Delete row": "删除行",
"With headings": "有标题",
"Without headings": "无标题",
},
"quote": {
"Align Left": "左对齐",
"Align Center": "居中对齐",
}
},
"blockTunes": {
"delete": {
"Delete": "删除",
'Click to delete': "点击删除"
},
"moveUp": {
"Move up": "向上移"
},
"moveDown": {
"Move down": "向下移"
},
"filter": {
"Filter": "过滤"
}
},
}
}

自定义样式

varaiables.css中包含了大部分的样式变量,更改这些变量可以实现自定义样式。

在这里插入图片描述

如通过重写 .root样式选择器可以实现自定义的背景色, 重写.ce-popover 改变弹出框样式等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
:root {
--color-bg-main: #F0F0F0;
--color-border-light: #E8E8EB;
--color-text-main: #000;
--selectionColor: #e1f2ff;
}


.ce-popover {
--border-radius: 6px;
--width: 200px;
--max-height: 270px;
--padding: 6px;
--offset-from-target: 8px;
--color-border: #e8e8eb;
--color-shadow: rgba(13,20,33,0.13);
--color-background: white;
--color-text-primary: black;
--color-text-secondary: #707684;
--color-border-icon: rgb(201 201 204 / 48%);
--color-border-icon-disabled: #EFF0F1;
--color-text-icon-active: #388AE5;
--color-background-icon-active: rgba(56, 138, 229, 0.1);
--color-background-item-focus: rgba(34, 186, 255, 0.08);
--color-shadow-item-focus: rgba(7, 161, 227, 0.08);
--color-background-item-hover: #eff2f5;
--color-background-item-confirm: #E24A4A;
--color-background-item-confirm-hover: #CE4343;
}
.dark-mode {
--color-border-light: rgba(255, 255, 255,.08);
--color-bg-main: #1c1e24;
--color-text-main: #737886;
}

在这里插入图片描述

在这里插入图片描述
– 完 –

开源好用的所见即所得(WYSIWYG)编辑器:Editor.js

https://blog.matoapp.net/posts/d2c2fe0c/

作者

林晓lx

发布于

2024-03-11

更新于

2024-09-11

许可协议

评论