Product
Socket Now Supports uv.lock Files
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
braft-editor
Advanced tools
<br>
而非<p></p>
移步: http://margox.github.io/braft-editor/
# 使用yarn安装
yarn add braft-editor
# 使用npm安装
npm install braft-editor --save
# 运行dev-server
yarn start
# 启动上传服务器
cd example/server
node index.js
# 访问 http://localhost:5998
# 打包编译
yarn build
import React from 'react'
import ReactDOM from 'react-dom'
// 引入编辑器以及编辑器样式
import BraftEditor from 'braft-editor'
import 'braft-editor/dist/braft.css'
class Demo extends React.Component {
render () {
const editorProps = {
height: 500,
contentFormat: 'html',
initialContent: '<p>Hello World!</p>',
onChange: this.handleChange,
onRawChange: this.handleRawChange
}
return (
<div className="demo">
<BraftEditor {...editorProps}/>
</div>
)
}
handleChange = (content) => {
console.log(content)
}
handleRawChange = (rawContent) => {
console.log(rawContent)
}
}
用于指定initialContent和onChange的内容格式,raw表示使用编辑器原始数据作为输入和输出类型, html表示使用HTML字符串作为输入和输出类型,默认为raw。
为了保证内容的可编辑性,强烈建议使用raw格式,并通过onHTMLChange获取HTML格式的内容
编辑器的初始内容,根据contentFormat类型传入html字符串或者raw字符串。 在默认情况下initialContent值只会在第一次传入的时候生效,如果需要多次生效,需要与contentId属性配合使用。
由于编辑器默认的contentFormat为'raw',如果需要传入html格式的initialContent,请将contentFormat指定为'html'
指定当前内容的唯一id,只有contentId发生变化时,编辑器才会使用新的initialContent。
建议直接传入文章id等类似的内容,确保编辑不同内容时,传入的initialContent能生效
指定编辑器内容发生变化时候的回调
指定编辑器内容发生变化时候的回调,参数为Raw格式的编辑器内容
指定编辑器内容发生变化时候的回调,参数为HTML格式的编辑器内容
指定在编辑器内按下tab键时的回调,参数为按键事件对象
在编辑器内的代码块中按tab键不会触发此回调
指定一个函数,通常用于保存操作,在编辑器处于焦点时按下command/ctrl + s会执行此函数
指定控制栏组件,默认值如下:
[
'undo', 'redo', 'split', 'font-size', 'font-family', 'line-height', 'letter-spacing',
'indent','text-color', 'bold', 'italic', 'underline', 'strike-through',
'superscript', 'subscript', 'remove-styles', 'emoji', 'text-align', 'split', 'headings', 'list_ul',
'list_ol', 'blockquote', 'code', 'split', 'link', 'split', 'hr', 'split', 'media', 'clear'
]
指定不需要显示的控制栏组件,默认为空[]
指定自定义控制组件,目前支持分割线[split]、按钮[button]、下拉框[dropdown]、模态框[modal]和完全自定义的组件[component]。 示例:
[
{
type: 'split'
},
{
type: 'button',
text: 'Hello',
html: '<span style="color:red;">Hello</span>',
hoverTitle: 'Hello World!',
className: 'preview-button',
onClick: () => console.log('Hello World!')
}, {
type: 'dropdown',
text: 'Foo',
html: '<span style="color:blue;">Foo</span>',
hoverTitle: 'Hello World!',
showDropDownArrow: false, // 是否展示下拉组件顶部的小箭头
autoHide: false, // 是否在下拉组件失去焦点后自动关闭下拉组件
component: <YourComponent />
}, {
type: 'component',
component: <YourComponent/> // 此处指定的组件将会直接渲染到工具栏中
}, {
type: 'modal',
text: 'Bar',
html: '<span style="color:green;">Bar</span>',
hoverTitle: 'Hello World!',
modal: {
id: 'test-modal', // v1.4.0新增,必选
title: '这是一个弹出框',
showClose: true,
showCancel: true,
showConfirm: true,
confirmable: true,
onCreate: (modalInstance) => {},
onConfirm: () => console.log(1),
onCancel: () => console.log(2),
onClose: () => console.log(3),
children: (
<div style={{width: 480, height: 320, padding: 30}}>
<span>Hello World!</span>
</div>
)
}
}
]
使用自定义的弹窗组件时,必须为modal指定一个id,以保证modal内容能动态更新
添加自定义的编辑器显示组件,用来支持一些比较复杂的编辑需求。通过这种方式编辑的内容,只能通过raw方式读取和存储。
class CustomAtomic extends React.Component {
// 需要通过设置readonly来保证组件内部文本框可交互
onMouseOver() {
this.props.editor.setEditorProp('readOnly', true)
}
onMouseLeave() {
this.props.editor.setEditorProp('readOnly', false)
}
render() {
return (
<div className="braft-custom-atomic"
onMouseOver={this.onMouseOver.bind(this)}
onMouseLeave={this.onMouseLeave.bind(this)}>
hello world
<input type="text"/>
</div>
)
}
}
const extendAtomic = [
{
type: 'CUSTOM',
component: CustomAtomic
}
]
// 然后将extendAtomics作为props传入即可使用
<BraftEditor extendAtomics={extendAtomics} ref={(instance) => this.editorInstance = instance} {...otherProps} />
// 添加组件
this.editorInstance.insertMedias([{
type: 'CUSTOM',
name: 'CustomElement',
}]);
是否禁用编辑功能,默认false
指定编辑区域的高度,不包括控制栏,默认是500。
如果需要编辑器自动适应内容高度,可以将此属性设置为0,同时通过外部CSS设置编辑器的最小与最大高度以免下拉菜单工具展示异常。
指定编辑器的语言,目前支持zh、zh-hant和en,默认zh
设置placeholder文本
指定编辑器的包裹容器的选择器字符串(例如'#wrapper', '.container'),用于下拉菜单等组件的位置自适应,默认为编辑器自身
指定编辑器编辑代码块时按下tab插入的缩进空格数,默认是2
指定是否启用强制空行,该属性为true时按回车键将会插入<br>
而非<p></p>
,默认为false
指定可使用的文字对齐方式,默认值如下:
['left', 'center', 'right', 'justify']
指定编辑器可用的颜色列表,用于设定文本颜色和文本背景颜色,只支持6位16进制写法,默认可用颜色:
[
'#000000', '#333333', '#666666', '#999999', '#cccccc', '#ffffff',
'#61a951', '#16a085', '#07a9fe', '#003ba5', '#8e44ad', '#f32784',
'#c0392b', '#d35400', '#f39c12', '#fdda00', '#7f8c8d', '#2c3e50'
]
是否允许设置文本的背景颜色,默认是true
指定编辑器可用的字号列表,用于设定文本内容的字号,默认可用字号:
[
12, 14, 16, 18, 20, 24,
28, 30, 32, 36, 40, 48,
56, 64, 72, 96, 120, 144
]
指定编辑器可用的行高列表,用于设定文本内容的行高,默认可用行高:
[
'1', '1.2', '1.5', '1.75',
'2', '2.5', '3', '4'
],
指定编辑器可用的字符间隔列表,用于设定文本的字符间隔,默认可用间隔值:
[0, 2, 4, 6]
指定编辑器可用的两端缩进列表,用于设定文本段落的两端缩进,默认可用缩进值:
[0, 14, 21, 28]
指定编辑器可用的字体列表,用于设定文本内容的字体,默认可用字体:
[
{
name: 'Araial',
family: 'Arial, Helvetica, sans-serif'
}, {
name: 'Georgia',
family: 'Georgia, serif'
}, {
name: 'Impact',
family: 'Impact, serif'
}, {
name: 'Monospace',
family: '"Courier New", Courier, monospace'
}, {
name: 'Tahoma',
family: "tahoma, arial, 'Hiragino Sans GB', 宋体, sans-serif"
}
]
配置编辑器可用的表情列表,默认可用表情:
[
"🤣","🙌","💚","💛","👏","😉","💯",
"💕","💞","💘","💙","💝","🖤","💜",
"❤️","😍","😻","💓","💗","😋","😇",
"😂","😹","😘","💖","😁","😀","🤞",
"😲","😄","😊","👍","😌","😃","😅",
"✌️","🤗","💋","😗","😽","😚","🤠",
"😙","😺","👄","😸","😏","😼","👌",
"😎","😆","😛","🙏","🤝","🙂","🤑",
"😝","😐","😑","🤤","😤","🙃","🤡",
"😶","😪","😴","😵","😓","👊","😦",
"😷","🤐","😜","🤓","👻","😥","🙄",
"🤔","🤒","🙁","😔","😯","☹️","☠️",
"😰","😩","😖","😕","😒","😣","😢",
"😮","😿","🤧","😫","🤥","😞","😬",
"👎","💀","😳","😨","🤕","🤢","😱",
"😭","😠","😈","😧","💔","😟","🙀",
"💩","👿","😡","😾","🖕"
]
此默认列表不保证全平台正常显示,请按需调整
指定粘贴模式,如果为text,则粘贴的时候会过滤掉HTML格式,默认为空
配置编辑器的多媒体插入功能:
{
allowPasteImage: true, // 是否允许直接粘贴剪贴板图片(例如QQ截图等)到编辑器
image: true, // 开启图片插入功能
video: true, // 开启视频插入功能
audio: true, // 开启音频插入功能
validateFn: null, // 指定本地校验函数,说明见下文
uploadFn: null, // 指定上传函数,说明见下文
removeConfirmFn: null, // 指定删除前的确认函数,说明见下文
onRemove: null, // 指定媒体库文件被删除时的回调,参数为被删除的媒体文件列表(数组)
onChange: null, // 指定媒体库文件列表发生变化时的回调,参数为媒体库文件列表(数组)
onInsert: null, // 指定从媒体库插入文件到编辑器时的回调,参数为被插入的媒体文件列表(数组)
}
粘贴的图片依然会通过media.uploadFn上传到服务器,但是暂时不会调用media.validateFn来进行校验
在选择文件之后,编辑器会调用此函数对每一个选择的文件进行校验,如果该函数返回false,则对应的文件不会被添加到媒体库:
// 示例,不允许选择大于100K的文件
const validateFn = (file) => {
return file.size < 1024 * 100
}
指定上传函数,未指定时无法上传视频和音频,可上传图片,但只限本地预览。
编辑器在调用media.uploadFn时,会传入一个包含文件体、文件在媒体库的ID、进度回调、成功回调和失败回调的对象作为参数:
{
file: [File Object],
progress: function (progress) {
// progress为0到100
},
libraryId: 'XXXXX',
success: function (res) {
// res须为一个包含已上传文件url属性的对象:
},
error: function (err) {
}
}
uploadFn示例:
const uploadFn = (param) => {
const serverURL = 'http://upload-server'
const xhr = new XMLHttpRequest
const fd = new FormData()
// libraryId可用于通过mediaLibrary示例来操作对应的媒体内容
console.log(param.libraryId)
const successFn = (response) => {
// 假设服务端直接返回文件上传后的地址
// 上传成功后调用param.success并传入上传后的文件地址
param.success({
url: xhr.responseText,
meta: {
id: 'xxx',
title: 'xxx',
alt: 'xxx',
loop: true, // 指定音视频是否循环播放
autoPlay: true, // 指定音视频是否自动播放
controls: true, // 指定音视频是否显示控制栏
poster: 'http://xxx/xx.png', // 指定视频播放器的封面
}
})
}
const progressFn = (event) => {
// 上传进度发生变化时调用param.progress
param.progress(event.loaded / event.total * 100)
}
const errorFn = (response) => {
// 上传发生错误时调用param.error
param.error({
msg: 'unable to upload.'
})
}
xhr.upload.addEventListener("progress", progressFn, false)
xhr.addEventListener("load", successFn, false)
xhr.addEventListener("error", errorFn, false)
xhr.addEventListener("abort", errorFn, false)
fd.append('file', param.file)
xhr.open('POST', serverURL, true)
xhr.send(fd)
}
指定媒体库文件的删除确认函数,未指定时,删除单个和多个媒体库文件都不需要确认
编辑器在调用media.removeConfirmFn时,会将待删除的文件和确认删除回调作为参数传过来,以下是一个删除确认函数示例:
const removeConfirmFn = (param) => {
if (param.items.length > 1) {
// 调用原生confirm对话框
if (confirm('确认删除这些文件么?')) {
// 告知编辑器确认删除文件
param.confirm()
}
} else if (param.items.length === 1) {
// 调用原生confirm对话框
if (confirm('确认删除这个文件么?')) {
// 告知编辑器确认删除文件
param.confirm()
}
}
}
从媒体库插入媒体资源到编辑器时会执行此回调,可以在此回调中修改需要插入的媒体对象,示例如下:
media.onInsert = (files) => {
// 只插入前3个媒体对象
return files.slice(0, 3)
// 取消插入并保留媒体库弹窗
return false
// 取消插入并关闭媒体库弹窗
return []
}
配置编辑器可插入的外部网络媒体类型,默认值如下:
{
image: true,
audio: true,
video: true,
embed: true
}
// 如果以上四个值皆为false,则不允许插入任何外部媒体,也不会显示插入外部媒体的入口
配置图片工具栏(tooltip)可用的按钮,默认值如下:
{
floatLeft: true,
floatRight: true,
alignLeft: true,
alignCenter: true,
alignRight: true,
link: true,
size: true
}
指定编辑器获得焦点时的回调
指定编辑器失去焦点时的回调
绝大多数的非get类方法都会返回编辑器实例,即支持链式调用
<BraftEditor ref={instance => this.editorInstance = instance}/>
// 获取指定格式的内容,format为获取内容的格式,默认与contentFormat一致, 另有getHTMLContent和getRawContent方法可用
this.editorInstance.getContent(format)
// 设置编辑器内容,用于需要异步填入编辑器内容的场景,format为填入内容的格式,默认与contentFormat一致
this.editorInstance.setContent(content, format)
获取编辑器实例的editorState,一般情况下无需使用
this.editorInstance.getEditorState()
强制编辑器内容重新渲染,一般情况下无需使用
this.editorInstance.forceRender()
获取draft内核的实例,用于调用draft的API
const draftInstance = this.editorInstance.getDraftInstance()
// 使编辑器获得焦点
draftInstance.focus()
更多关于draft的资料,请参阅:https://draftjs.org/
获取内置媒体库实例,可用于外部操作媒体库内容
// 示例
const mediaLibrary = this.editorInstance.getMediaLibraryInstance()
const libraryId = new Date().getTime()
// 往媒体库添加一个图片
mediaLibrary.addItem({
id: libraryId,
type: 'IMAGE',
name: 'Foo',
url: 'http://path/to/image',
thumbnail: 'http://path/to/thumbnail'
})
// 从媒体库删除先前插入的图片
setTimeout(() => {
mediaLibrary.removeItem(libraryId)
}, 1000)
媒体库实例的具体使用请参阅:https://github.com/margox/braft-editor/tree/master/src/helpers/MediaLibrary/index.js
判断当前是否选中内容
this.editorInstance.selectionCollapsed()
获取选中内容的区块类型
this.editorInstance.getSelectionBlockType()
切换选中内容的区块类型,可用的区块类型请参见可用区块类型
this.editorInstance.toggleSelectionBlockType('blockquote')
获取选中内容的行内样式
this.editorInstance.getSelectionInlineStyle()
判断选中内容是否包含指定的行内样式
this.editorInstance.selectionHasInlineStyle('BOLD')
切换选中内容的行内样式, 同时可传入一个需要移除的样式数组
// 加粗文字,同时移除文字斜体样式
this.editorInstance.toggleSelectionInlineStyle('BOLD', ['ITALIC'])
切换选中内容的文本对齐方式,参数可以是left/center/right
this.editorInstance.toggleSelectionAlignment('center')
切换选中内容的文字颜色,参数为可用颜色中的一个
this.editorInstance.toggleSelectionColor('#ffffff')
切换选中内容的文字背景颜色,参数为可用颜色中的一个
this.editorInstance.toggleSelectionBackgroundColor('#000000')
切换选中内容的文字大小,参数为可用字号中的一个
this.editorInstance.toggleSelectionFontSize(24)
切换选中内容的文字字体,参数为可用字体中的一个(name)
this.editorInstance.toggleSelectionFontFamily('Impact')
为选中内容添加超链接
this.editorInstance.toggleSelectionLink('http://www.baidu.com', '_blank')
// 移除所选内容的超链接
this.editorInstance.toggleSelectionLink(false)
插入纯文本内容到光标之后,如果当前已选中内容并且replace为true,则会替换被选中内容,replace默认为true
this.editorInstance.insertText('Hello World!')
插入HTML片段到光标之后
this.editorInstance.insertHTML('<p><span color="#ff0000;">Hello World!</span></p>')
由于框架限制,此方法并不一定能满足所有场景的需求,请自行尝试后再决定是否使用
插入媒体内容到编辑器,medias为数组,格式如下:
this.editorInstance.insertMedias([
{
type: 'IMAGE',
name: 'New Photo',
url: 'http://path/to/image.png'
}, {
type: 'VIDEO',
name: 'New Video',
url: 'http://path/to/image-2.mp4'
}, {
type: 'AUDIO',
name: 'New Audio',
url: 'http://path/to/image-2.mp3'
}
])
判断编辑器内容是否为空
this.editorInstance.isEmpty()
由于draft框架的原因,该方法返回true时,依然可以从编辑器获取到一对空的p标签
<p></p>
,反之亦然
清空编辑器内容
this.editorInstance.clear()
通过此方法进行清空后,可以通过撤销操作来还原编辑器内容,若需要不可撤销地清空,请使用
editorInstance.setContent('', 'html')
插销一次操作
this.editorInstance.undo()
重做一次操作
this.editorInstance.redo()
使编辑器获得焦点
this.editorInstance.focus()
使编辑器失去焦点
this.editorInstance.blur()
[
'header-one',
'header-two',
'header-three',
'header-four',
'header-five',
'header-six',
'unstyled',
'blockquote',
'code-block',
'unordered-list-item',
'ordered-list-item'
]
FAQs
Rich Text Editor Based On Draft.js
The npm package braft-editor receives a total of 2,271 weekly downloads. As such, braft-editor popularity was classified as popular.
We found that braft-editor demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
Research
Security News
Socket researchers have discovered multiple malicious npm packages targeting Solana private keys, abusing Gmail to exfiltrate the data and drain Solana wallets.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.