当前位置: 首页 > news >正文

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

文章目录

  • 特点
    • 基于区块
    • 干净的数据
  • 界面与交互
    • 插件
    • 标题和文本
    • 图片
    • 列表
    • Todo
    • 表格
  • 使用
    • 安装
    • 创建编辑器实例
    • 配置工具
    • 本地化
    • 自定义样式

今天介绍一个开源好用的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安装。

在这里插入图片描述

标题和文本

在这里插入图片描述

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

{"id" : "zcKCF1S7X8","type" : "header","data" : {"text" : "Editor.js","level" : 1}
},
{"id" : "b6ji-DvaKb","type" : "paragraph","data" : {"text" : "支持文本,标题,列表,代办,表格,图片,链接,代码片段,引用片段等等"}
},

在这里插入图片描述

{"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两种方式上传图片

在这里插入图片描述

{"id" : "VYsWoLL7yj","type" : "image","data" : {"url" : "data:image/png;base64, ...","caption" : "codex2x.png","withBorder" : false,"withBackground" : false,"stretched" : false}
}

列表

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

在这里插入图片描述

无序列表:

{"id" : "i_cVQxn3Tb","type" : "list","data" : {"style" : "unordered","items" : [{"content" : " 香蕉🍌","items" : []},{"content" : " 苹果🍎","items" : []},{"content" : " 葡萄🍇  ","items" : []}]}},

有序列表:

        {"id" : "nOTdryosj2","type" : "list","data" : {"style" : "ordered","items" : [{"content" : "洗手心","items" : []},{"content" : "搓手背","items" : []},{"content" : "洗指缝","items" : []}]}},

嵌套列表:

        {"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

在这里插入图片描述

{"id" : "Hitrs4RqXw","type" : "checklist","data" : {"items" : [{"text" : "满意😊","checked" : true},{"text" : "一般😐","checked" : false},{"text" : "不满意☹️","checked" : false}]}},

表格

在这里插入图片描述

不代表头:

{"id" : "xPAQ6AkUiK","type" : "paragraph","data" : {"text" : "<b>不带表头</b>"}
},
{"id" : "_MMoOqlgXs","type" : "table","data" : {"withHeadings" : false,"content" : [["<b>重要紧急</b>","<b>重要不紧急</b>"],["吃饭睡觉","订生日蛋糕"],["<b>不重要但紧急</b>","<b>不重要不紧急</b>"],["上班前定好闹钟","总结这一周的工作"]]}
},

带表头:

{"id" : "fvfQSljMK8","type" : "table","data" : {"withHeadings" : true,"content" : [["星期一","星期二","星期三","星期四","星期五"],["a","b","c","d","e"]]}
},

使用

安装

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

yarn add @editorjs/editorjs

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

创建编辑器实例

在页面创建编辑器


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

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

配置工具

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

在这里插入图片描述

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


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

配置工具

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

    /*** 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配置对象来设置编辑器的本地化。以下是一个较为完整的中文化示例:


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 改变弹出框样式等。

: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

文章目录 特点基于区块干净的数据 界面与交互插件标题和文本图片列表Todo表格 使用安装创建编辑器实例配置工具本地化自定义样式 今天介绍一个开源好用的Web所见即所得(WYSIWYG)编辑器&#xff1a; Editor.js Editor.js 是一个基于 Web 的所见即所得富文本编辑器&#xff0c;它…...

sqlite 损坏 修复

步骤1 SQLite Download Page下载sqlite3 对应的系统版本 2.参考怎么恢复sqlite 数据库文件✅ - 有乐数据恢复网 sqlite3 dbname > .mode insert > .output dbdump.sql > .dump > .exit 恢复方法1 1.创建一个新的数据库 例如名字叫 test.db 2sqlite3 test.…...

初学Vue——Vue路由

0 什么是Vue路由 类似于Html中的超链接(<a>)一样&#xff0c;可以跳转页面的一种方式。 前端路由&#xff1a;URL中hash(#号之后的内容)与组件之间的对应关系&#xff0c;如下图&#xff1a; 当我们点击左侧导航栏时&#xff0c;浏览器的地址栏会发生变化&#xff0c;路…...

如何使用宝塔面板搭建Discuz并结合cpolar实现远程访问本地论坛

文章目录 前言1.安装基础环境2.一键部署Discuz3.安装cpolar工具4.配置域名访问Discuz5.固定域名公网地址6.配置Discuz论坛 前言 Crossday Discuz! Board&#xff08;以下简称 Discuz!&#xff09;是一套通用的社区论坛软件系统&#xff0c;用户可以在不需要任何编程的基础上&a…...

llc的基波分析法

对于我们之前分析的 LLC等效谐振电路的分析&#xff0c;其实我们发现分析的并不是完整的方波输入&#xff0c;而是用正弦波来分的 那么为何用基波来分析呢&#xff0c;因为对于方波而言&#xff0c;根据傅里叶级数它是可以分解成基波、 1次、3次、5次.......等各种奇次谐波的入…...

一键清除JavaScript代码中的注释:使用正则表达式实现

这个正则表达式可以有效地匹配 JavaScript 代码中的各种注释&#xff0c;并且跳过了以 http: 或 https: 开头的链接。 /\/\*[\s\S]*?\*\/|\/\/[^\n]*|<!--[\s\S]*?-->|(?<!http:|https:)\/\/[^\n]*/gvscode 实战&#xff0c;ctrlF 调出查找替换工具&#xff0c;点…...

第七次作业

IPSEC VPPN实验配置 目标&#xff1a;在FW5和FW3之间建立一条IPSEC通道&#xff0c;保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 1.FW1和FW2进行双机热备&#xff08;之前实验没保存&#xff0c;可看上个实验&#xff09; 还有一些配置前面实验有。 2.场景选择点对点…...

在jupyternotebook中,如何解决作图时负号无法显示的问题?

输入以下代码即可。 import matplotlib as mpl mpl.rcParams[axes.unicode_minus] False 原文链接&#xff1a;在jupyternotebook中&#xff0c;如何解决作图时负号无法显示的问题&#xff1f;...

ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。

发生的错误信息&#xff1a; File "C:\Users\malongqiang\.conda\envs\ObjectDetection\lib\ssl.py", line 1309, in do_handshakeself._sslobj.do_handshake() ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。 分析原因&#xff1a; …...

主流开发语言与环境介绍

主流开发语言与环境介绍 1. 引言 随着计算机科学的不断发展&#xff0c;各种编程语言和开发环境层出不穷。选择一种适合自己的主流开发语言和环境是每个开发者都必须面临的问题。本文将为大家介绍几种目前最为流行的主流开发语言和环境&#xff0c;帮助读者选择合适的工具进行…...

Unity性能优化篇(九) 模型优化之LOD技术概述以及操作方法

LOD模型优化技术概述: 1.LOD技术可以根据摄像头远近来显示不同精度的模型(例如吃鸡游戏 随着跳伞高度 来显示下面树木以及建筑的模型精度) LOD模型优化技术操作方法: 可使用Unity自带的LOD Group组件&#xff0c;并根据项目的情况来调整该组件的属性。Untiy资源商店也有一些其…...

就业班 2401--3.11 Linux Day15--ftp数据传输测试server和client+谷歌验证码登录远程连接

文件服务器 路漫漫其修远兮&#xff0c;吾将上下而求索.构建NFS远程共享存储 一、NFS介绍 文件系统级别共享&#xff08;是NAS存储&#xff09; --------- 已经做好了格式化&#xff0c;可以直接用。 速度慢比如&#xff1a;nfs&#xff0c;sambaNFS NFS&#xff1a;Networ…...

有点NB的免费wordpress主题模板

一个不错的黄色模板&#xff0c;用WP免费主题模板搭建家政服务公司网站。 https://www.wpniu.com/themes/15.html...

安全防御第七次作业

拓扑图如图所示&#xff1a; 问题&#xff1a;在FW7和FW8之间建立一条IPSEC通道保证10.0.2.0/24网段 可以正常访问到192.168.1.0/24 注&#xff1a;基础配置我在此省略了 一、NAT配置 FW4&#xff1a; FW6&#xff1a; 二、在FW4上做服务器映射 三、配置IPSEC FW5&#xff…...

解决跨域问题的FastAPI应用及常见报错解析

介绍&#xff1a; 跨域问题在前后端分离的Web应用中经常会遇到。FastAPI作为一个快速、现代化的Python Web框架&#xff0c;在处理跨域问题上也提供了一些解决方案。本文将介绍如何使用FastAPI来解决跨域问题&#xff0c;并分析一些常见的报错及解决方法。 正文&#xff1a; …...

NXP iMX8MM Cortex-M4 核心 GPT Capture 测试

By Toradex秦海 1). 简介 NXP i.MX8 系列处理器均为异构多核架构 SoC&#xff0c;除了可以运行 Linux 等复杂操作系统的 Cortax-A 核心&#xff0c;还包含了可以运行实时操作系统比如 FreeRTOS 的 Cortex-M 核心&#xff0c;本文就演示通过 NXP i.MX8MM 处理器集成的 Cortex-…...

2步破解官方sublime4

sublime简要破解流程 1.下载sublime官方最新版2. 破解流程 1.下载sublime官方最新版 打开 官方网站下载 portable version 版&#xff0c;省的安装。。解压到任意位置&#xff0c;备份 sublime_text.exe 文件 2. 破解流程 打开网址把文件 sublime_text.exe 拖入网页搜索替换…...

【智能家居】东胜物联ODM定制ZigBee网关,助力能源管理解决方案商,提升市场占有率

背景 本文案例服务的客户是专业从事智能家居能源管理的解决方案商&#xff0c;其产品与服务旨在帮助用户监测、管理和优化能源消耗&#xff0c;以提高能源使用效率。 随着公司的扩张&#xff0c;为了增加市场占有率&#xff0c;他们希望找到更好的硬件服务支持&#xff0c;以…...

Python爬虫实战第三例【三】【上】

零.实现目标 爬取视频网站视频 视频网站你们随意&#xff0c;在这里我选择飞某速&#xff08;狗头保命&#xff09;。 例如&#xff0c;作者上半年看过的“铃芽之旅”&#xff0c;突然想看了&#xff0c;但是在正版网站看要VIP&#xff0c;在盗版网站看又太卡了&#xff0c;…...

解释器模式

解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为型设计模式&#xff0c;它用于定义一种语言的文法&#xff0c;并提供一个解释器来解释该语言中的表达式。这个模式主要用于解决问题领域中存在的特定语言或表达式的解释和执行问题。它将一个问题分解成一系列的…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...