https://github.com/kanweiwei/easy-editor
基于slate框架的富文本编辑器
https://github.com/kanweiwei/easy-editor
editor react rich-text-editor slate
Last synced: about 1 year ago
JSON representation
基于slate框架的富文本编辑器
- Host: GitHub
- URL: https://github.com/kanweiwei/easy-editor
- Owner: kanweiwei
- License: apache-2.0
- Created: 2020-06-13T14:45:08.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2024-03-05T11:21:04.000Z (over 2 years ago)
- Last Synced: 2025-03-25T09:11:57.140Z (over 1 year ago)
- Topics: editor, react, rich-text-editor, slate
- Language: TypeScript
- Homepage:
- Size: 4.66 MB
- Stars: 40
- Watchers: 2
- Forks: 5
- Open Issues: 23
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
Easy Editor
A rich text editor based on slate

[Demo](https://kanweiwei.github.io/easy-editor/example/)
## Quick Start
### npm
```bash
npm install @camol/easy-editor --save
```
### yarn
```bash
yarn add @camol/easy-editor -S
```
### Examples
```bash
git clone https://github.com/kanweiwei/easy-editor.git
cd easy-editor
yarn && yarn build && yarn example
```
### with React
```typescript
import * as React from "react";
import ReactDom from "react-dom";
import EasyEditor from "@camol/easy-editor";
class Editor extends React.Component {
html = "";
handleChange = (v: any) => {
console.log("change=>>>", v);
if (this.editorRef.current) {
// value to html
console.log(this.editorRef.current.convertor.serialize(v.change.value));
}
};
render() {
return 123"} onChange={this.handleChange} />;
}
}
ReactDom.render(, document.getElementById("root"));
```
### Custom toolbar
For convenience, some tools have been built in the toolbar.
tool| instructions|
-|:-:|
fontSize| 字号|
fontColor| 字体颜色|
bold| 加粗|
italic| 斜体|
u| 下划线|
sup| 上标 |
sub | 下标 |
left|文字居左|
right|文字居右|
center|文字居中|
justify|两端对齐|
image| 插入图片|
video | 插入音频(mp4、webm)|
pdf | 插入 pdf|
math | 插入 latex 数学公式 |
#### How to add a custom tool ?
```typescript
import * as React from "react";
import ReactDom from "react-dom";
import EasyEditor from "@camol/easy-editor";
// audio tool
class AudioControl extends React.Component {
inputRef = React.createRef();
handleClick = () => {
if (inputRef.current) {
inputRef.current.click();
}
};
handleChange = (e: React.ChangeEvent) => {
const file = e.target.files[0];
e.target.value = "";
if (file) {
if (this.props.beforeUpload) {
let url = await this.props.beforeUpload(file);
if (url) {
let change = this.props.change.focus().insertInline({
object: "inline",
type: "audio",
isVoid: true,
data: {
src: url,
},
});
this.props.update(change);
}
}
}
};
render() {
return (
);
}
}
class Editor extends React.Component {
html = "";
handleChange = (v: any) => {
console.log("change=>>>", v);
if (this.editorRef.current) {
// value to html
console.log(this.editorRef.current.convertor.serialize(v.change.value));
}
};
render() {
return (
123"}
onChange={this.handleChange}
controls={[
["bold", "u", "image"],
[
{
type: "audio",
component: AudioControl,
},
],
]}
/>
);
}
}
```
---
### Custom Node Plugin
```typescript
import * as React from "react";
import { AST } from "parse5";
const plugin = {
type: "node", // node, mark
object: "inline",
nodeType: "super-audio",
importer(el: AST.Default.Element, next: Function): any {
if (el.tagName.toLowerCase() === "audio") {
return {
object: "inline", // block、inline,
type: "super-audio",
isVoid: true,
data: {
src: el?.attrs?.find((n) => n.name === "src")?.value,
},
nodes: next(el.childNodes),
};
}
},
exporter(node: any, children: any): any {
let { className, src } = node.data.toJS();
return ;
},
render(
editor: any,
props: { attributes: any; children: any; node: any; isSelected: any }
): any {
// @ts-ignore
const { attributes, children, node, isSelected } = props;
const src = node.data.get("src");
return (
{children}
);
},
};
export default plugin;
```
---
### License
Apache 2.0