在这里,我们有一个新的富文本编辑器 Editable ,它没有使用原生的可编辑属性
contenteditable,而是采用自定义的渲染器。这样做可以更好地控制编辑器的行为。am-editor
一个支持协同编辑的富文本编辑器,可以自由的使用React、Vue 等前端常用库扩展定义插件。 English · Demo · QQ群 907664876 ·
广告: 科学上网,方便、快捷的上网冲浪 稳定、可靠,访问 Github 或者其它外网资源很方便。
Vue2DEMO https://github.com/zb201307/am-editor-vue2
Vue3DEMO https://github.com/red-axe/am-editor-vue3-demo
ReactDEMO https://github.com/big-camel/am-editor/tree/master/examples/react
Vue2 DEMOhttps://github.com/big-camel/am-editor-demo-vue2
Vue2 Nuxt DEMOhttps://github.com/big-camel/am-editor-nuxt🎁 开箱即用,提供几十种丰富的插件来满足大部分需求 🚀 高扩展性,除了 markinlineblock类型基础插件外,我们还提供card组件结合ReactVue等前端库渲染插件 UI🎨 丰富的多媒体支持,不仅支持图片和音视频,更支持插入嵌入式多媒体内容 📝 支持 Markdown语法🌍 支持国际化 💻 引擎纯 JavaScript编写,不依赖任何前端库,插件可以使用ReactVue等前端库渲染。复杂架构轻松应对👥 内置协同编辑方案,轻量配置即可使用 📱 兼容大部分最新移动端浏览器 我们按照惯例先输出一个
Hello world!import React, { useEffect, useRef, useState } from 'react'; import Engine, { EngineInterface } from '@aomao/engine'; const EngineDemo = () => { //编辑器容器 const ref = useRef<HTMLDivElement | null>(null); //引擎实例 const [engine, setEngine] = useState<EngineInterface>(); //编辑器内容 const [content, setContent] = useState<string>('<p>Hello world!</p>'); useEffect(() => { if (!ref.current) return; //实例化引擎 const engine = new Engine(ref.current); //设置编辑器值 engine.setValue(content); //监听编辑器值改变事件 engine.on('change', () => { const value = engine.getValue(); setContent(value); console.log(`value:${value}`); }); //设置引擎实例 setEngine(engine); }, []); return <div ref={ref} />; export default EngineDemo;引入
@aomao/plugin-bold加粗插件import Bold from '@aomao/plugin-bold';把
Bold插件加入引擎//实例化引擎 const engine = new Engine(ref.current, { plugins: [Bold], });卡片是编辑器中的一个独立区域,其 UI 和逻辑在卡片内部可以使用
React、Vue或其他前端库自定义渲染内容,最后再挂载到编辑器上。我们引入了
@aomao/plugin-codeblock代码块插件,该插件的语言下拉框使用React渲染,因此有所区别。Vue3 则使用@aomao/plugin-codeblock-vue。import CodeBlock, { CodeBlockComponent } from '@aomao/plugin-codeblock';把
CodeBlock插件和CodeBlockComponent卡片组件加入引擎//实例化引擎 const engine = new Engine(ref.current, { plugins: [CodeBlock], cards: [CodeBlockComponent], });
CodeBlock插件默认支持markdown,在编辑器一行开头位置输入代码块语法```javascript空格后即可触发。为了更方便的管理节点,降低复杂性。编辑器抽象化了节点属性和功能,制定了
markinlineblockcard4 种类型节点,他们由不同的属性、样式或html结构组成,并统一使用schema对它们进行约束。一个简单的
name : 'p' , // 节点名称 type : 'block' // 节点类型schema看起来像是这样:除此之外,还可以描述属性、样式等,比如:
name : 'span' , // 节点名称 type : 'mark' , // 节点类型 attributes : { // 节点有一个 style 属性 style : { // 必须包含一个color的样式 color : { required : true , // 必须包含 value : '@color' // 值是一个符合css规范的颜色值,@color 是编辑器内部定义的颜色效验,此处也可以使用方法、正则表达式去判断是否符合需要的规则 // 可选的包含一个 test 属性,他的值可以是任意的,但不是必须的 test : '*'下面这几种节点都符合上面的规则:
<span style="color:#fff"></span> <span style="color:#fff" test="test123" test1="test1"></span> <span style="color:#fff;background-color:#000;"></span> <span style="color:#fff;background-color:#000;" test="test123"></span>但是除了在 color 和 test 已经在
schema中定义外,其它的属性(background-color、test1)在处理时都会被编辑器过滤掉。可编辑器区域内的节点通过
schema规则,制定了markinlineblockcard4 种组合节点,他们由不同的属性、样式或html结构组成,并对它们的嵌套进行了一定的约束。引入
@aomao/toolbar工具栏,工具栏由于交互复杂,基本上都是使用React+AntdUI 组件渲染,Vue3使用@aomao/toolbar-vue工具栏除了 UI 交互外,大部分工作只是对不同的按钮事件触发后调用了引擎执行对应的插件命令,在需求比较复杂或需要重新定制 UI 的情况下,Fork 后修改起来也比较容易。
import Toolbar, { ToolbarPlugin, ToolbarComponent } from '@aomao/toolbar';把
ToolbarPlugin插件和ToolbarComponent卡片组件加入引擎,它可以让我们在编辑器中可以使用快捷键/唤醒出卡片工具栏//实例化引擎 const engine = new Engine(ref.current, { plugins: [ToolbarPlugin], cards: [ToolbarComponent], });渲染工具栏,工具栏已配置好所有插件,这里我们只需要传入插件名称即可
return ( engine && ( <Toolbar engine={engine} items={[ ['collapse'], 'bold',更复杂的工具栏配置请查看文档 https://editor.aomao.com/zh-CN/config/toolbar
该开源库通过监听编辑区域(contenteditable 根节点)内的 html 结构的变化,使用
MutationObserver反推数据结构,并通过WebSocket与 Yjs 连接交互,实现多用户协同编辑的功能。每位编辑者作为 客户端 通过
@aomao/plugin-yjs-websocket插件中的Websocket与 服务端 进行通信交互。@aomao/yjs实现编辑器与Yjs数据的转换@aomao/plugin-yjs-websocket提供编辑器与Yjs的WebSocket客户端功能@aomao/plugin-yjs-websocket/server提供Yjs的WebSocket服务端,使用 Node.js 编写,并支持使用MongoDB和LevelDB存储数据。React
在使用该开源库之前,需要先在项目根目录中安装依赖。
yarn install lerna bootstrap依赖安装好后,只需要在根目录执行以下命令即可启动项目:
yarn start该开源库的开发目录结构如下:
packages存放引擎和工具栏相关代码plugins存放所有的插件api提供一些插件所需要的 API 访问,默认使用 https://editor.aomao.com 作为 API 服务yjs-server存放协同服务端代码,可通过yarn dev启动服务。感谢 pleasedmi、Elena211314、zb201307、cheon 的捐赠
如果您愿意,可以在这里留下你的名字。
PayPal