bridgerte
v0.9.3
Published
Cross-platform rich text editor with WebView bridge support.
Downloads
395
Maintainers
Readme
bridgerte

BridgeRTE 是面向 Web、PC、H5、React Native WebView 和 Flutter WebView 的跨端富文本编辑器。
业务项目只需要安装 bridgerte,不需要额外安装 Lexical 相关包。
它提供三类接入方式:
- DOM 编辑器:直接在 Web、PC、H5 页面里创建富文本编辑器。
- 编辑器和菜单分离:editor 负责内容,toolbar/tabbar 由业务按布局单独挂载。
- WebView / Native:WebView 内运行编辑器,RN/Flutter 原生侧自己渲染菜单并通过 bridge 发命令。
安装
pnpm add bridgerte使用 npm:
npm install bridgerteDOM 编辑器必须显式导入样式:
import 'bridgerte/style.css';推荐导入方式
推荐按能力从 subpath 导入,方便业务打包器按使用边界 tree-shaking:
import { createRichTextEditor, createRichTextToolbar } from 'bridgerte/dom';
import { createWebViewBridgeRuntime } from 'bridgerte/webview';
import { BRIDGERTE_CONTENT_VERSION } from 'bridgerte/core';
import { isBridgeMessage } from 'bridgerte/bridge';
import { defaultMenuSchema, resolveToolbarMenu } from 'bridgerte/native-spec';
import 'bridgerte/style.css';入口说明:
bridgerte/dom:DOM 编辑器、独立 toolbar/tabbar、WebView runtime 的 DOM 实现。bridgerte/webview:WebView 页面内的 bridge runtime。bridgerte/core:内容模型、命令、上传、菜单、参数面板和EditorAPI类型。bridgerte/bridge:WebView 双向消息类型、默认事件节流配置和消息判断工具。bridgerte/native-spec:RN/Flutter 原生菜单 schema、toolbar 解析和命令状态匹配工具。bridgerte/style.css:DOM 默认样式。bridgerte:聚合入口,适合迁移期或小型项目;生产示例优先使用 subpath。
快速开始
页面准备两个容器:一个给 toolbar/tabbar,一个给编辑器内容区。createRichTextEditor()
只创建 editor;菜单必须用 createRichTextToolbar() 单独挂载,并绑定同一个 EditorAPI。
<div id="toolbar"></div>
<div id="editor"></div>import { createRichTextEditor, createRichTextToolbar } from 'bridgerte/dom';
import 'bridgerte/style.css';
const editorContainer = document.querySelector<HTMLElement>('#editor');
const toolbarContainer = document.querySelector<HTMLElement>('#toolbar');
if (!editorContainer) throw new Error('editor container not found');
if (!toolbarContainer) throw new Error('toolbar container not found');
const editor = createRichTextEditor(editorContainer, {
placeholder: '开始输入',
onContentChange(change) {
counter.textContent = `${change.plainTextLength}/${change.maxLength ?? '∞'}`;
saveButton.disabled = !change.dirty;
}
});
const toolbar = createRichTextToolbar(toolbarContainer, {
editor,
placement: 'top'
});
toolbar.update();
window.addEventListener('beforeunload', () => {
toolbar.destroy();
editor.destroy();
});placement: 'top' | 'bottom' 只影响菜单语义、默认样式状态和无障碍命名;DOM 放在哪里、
是否吸顶、吸底或跟随键盘,由业务自己的布局决定。销毁时建议先销毁 toolbar,再销毁 editor。
WebView / RN / Flutter 也是同一心智:WebView 内的 editor 只提供内容和命令能力;原生菜单先读取
ready payload 中的 menuSchema,再订阅后续 editor.commandStateChange 自行渲染,并通过
bridge 发送命令。
基础配置
import { createRichTextEditor } from 'bridgerte/dom';
import type { EditorContent } from 'bridgerte/core';
const initialValue: Partial<EditorContent> = {
html: '<p>Hello BridgeRTE</p>',
plainText: 'Hello BridgeRTE'
};
const editor = createRichTextEditor(container, {
value: initialValue,
readonly: false,
placeholder: '写点什么',
maxLength: 10000,
keyboardShortcuts: true,
onReady(api) {
api.focus();
},
onError(error) {
reportError(error);
},
onFocus() {
console.log('focus');
},
onBlur() {
console.log('blur');
}
});常用选项:
value:初始内容,传Partial<EditorContent>。readonly:只读状态。placeholder:空态提示。maxLength:最大纯文本长度。keyboardShortcuts:是否启用 DOM 基础快捷键,默认关闭。onReady(api):编辑器初始化完成后回传EditorAPI。onContentChange(change):高频轻量内容摘要。onChange(content):兼容旧项目的完整内容回调,大文档不建议逐字依赖。onError(error):运行时错误。onFocus()/onBlur():焦点变化。
Deprecated 兼容字段:
toolbarMode:历史字段,当前在createRichTextEditor()中是 no-op,不再创建或控制 DOM toolbar/tabbar。toolbarConfig:历史 editor 字段,当前不再影响 editor 创建。菜单显示结构请传给createRichTextToolbar()。
内容读写
主动读取完整内容:
const content = editor.getContent();
console.log(content.version);
console.log(content.html);
console.log(content.json);
console.log(content.plainText);
console.log(content.assets);写入内容:
editor.setContent({
html: '<h1>标题</h1><p>正文</p>',
plainText: '标题\n正文'
});高频变化使用轻量摘要:
createRichTextEditor(container, {
maxLength: 5000,
onContentChange(change) {
saveButton.disabled = !change.dirty;
counter.textContent = `${change.plainTextLength}/${change.maxLength ?? '∞'}`;
warning.hidden = !change.isOverMaxLength;
}
});重要边界:
onContentChange不携带完整html、json、plainText,适合驱动 dirty、字数和保存按钮。- 保存、提交、离开页面确认时,再主动调用
getContent()。 onChange(content)会回传完整内容,主要用于兼容旧项目;10w 内容场景不要逐字依赖它保存。- WebView 高频
editor.contentChange也只应依赖轻量摘要;完整内容通过requestContent获取。
EditorAPI
editor.focus();
editor.blur();
editor.setReadonly(true);
editor.executeCommand({ type: 'format.bold' });
const states = editor.getCommandStates();
const unsubscribe = editor.subscribeCommandStateChange((nextStates) => {
renderToolbarState(nextStates);
});
unsubscribe();
editor.destroy();EditorAPI 方法:
getContent():读取完整内容。setContent(content):写入内容。executeCommand(command):执行命令。requestPayloadPanel(request):打开参数面板请求,供自绘菜单复用。getCommandStates():读取当前命令状态。subscribeCommandStateChange(listener):订阅命令状态变化。setReadonly(readonly):切换只读。focus()/blur():焦点控制。destroy():销毁实例。
命令 API
所有菜单最终都会落到 EditorCommand。业务也可以直接调用命令 API。
文本格式:
editor.executeCommand({ type: 'format.bold' });
editor.executeCommand({ type: 'format.italic' });
editor.executeCommand({ type: 'format.underline' });
editor.executeCommand({ type: 'format.strike' });
editor.executeCommand({ type: 'format.inlineCode' });
editor.executeCommand({ type: 'format.superscript' });
editor.executeCommand({ type: 'format.subscript' });
editor.executeCommand({ type: 'format.clear' });
editor.executeCommand({ type: 'format.color', value: '#1677ff' });
editor.executeCommand({ type: 'format.backgroundColor', value: '#e8f3ff' });
editor.executeCommand({ type: 'format.fontSize', value: '18px' });
editor.executeCommand({ type: 'format.fontFamily', value: 'Arial' });
editor.executeCommand({ type: 'format.lineHeight', value: '1.75' });段落、列表、对齐:
editor.executeCommand({ type: 'block.paragraph' });
editor.executeCommand({ type: 'block.heading', level: 1 });
editor.executeCommand({ type: 'block.quote' });
editor.executeCommand({ type: 'block.divider' });
editor.executeCommand({ type: 'block.code', language: 'typescript' });
editor.executeCommand({ type: 'block.setCodeLanguage', language: 'json' });
editor.executeCommand({ type: 'list.ordered' });
editor.executeCommand({ type: 'list.unordered' });
editor.executeCommand({ type: 'list.todo' });
editor.executeCommand({ type: 'align', value: 'left' });
editor.executeCommand({ type: 'align', value: 'center' });
editor.executeCommand({ type: 'align', value: 'right' });
editor.executeCommand({ type: 'align', value: 'justify' });
editor.executeCommand({ type: 'indent.increase' });
editor.executeCommand({ type: 'indent.decrease' });链接、表格、媒体、历史:
editor.executeCommand({ type: 'link.set', href: 'https://example.com', text: 'Example' });
editor.executeCommand({ type: 'link.unset' });
editor.executeCommand({ type: 'link.open' });
editor.executeCommand({ type: 'table.insert', rows: 3, cols: 4 });
editor.executeCommand({ type: 'table.insertRow', direction: 'after', count: 1 });
editor.executeCommand({ type: 'table.insertColumn', direction: 'after', count: 1 });
editor.executeCommand({ type: 'table.deleteRow' });
editor.executeCommand({ type: 'table.deleteColumn' });
editor.executeCommand({ type: 'table.delete' });
editor.executeCommand({
type: 'media.insertImage',
url: 'https://example.com/image.png',
alt: '示例图片',
width: 1200,
height: 800,
displayWidthPercent: 50,
align: 'center'
});
editor.executeCommand({
type: 'media.insertVideo',
url: 'https://example.com/video.mp4',
poster: 'https://example.com/poster.png',
displayWidthPercent: 100
});
editor.executeCommand({ type: 'history.undo' });
editor.executeCommand({ type: 'history.redo' });
editor.executeCommand({ type: 'fullscreen.toggle' });
editor.executeCommand({ type: 'content.clear' });默认 toolbar 不提供图片/视频 URL 插入入口,但保留 media.insertImage 和
media.insertVideo 命令。主动链接编辑也不是当前默认内置重点,业务可以通过自定义菜单调用
link.* 命令。
Toolbar / Tabbar 菜单配置
DOM toolbar/tabbar 只通过 createRichTextToolbar() 创建。它使用同一套菜单 schema/config,
并通过传入的 EditorAPI 订阅状态、执行命令。
const toolbar = createRichTextToolbar(toolbarContainer, {
editor,
placement: 'bottom',
toolbarConfig: {
toolbarKeys: [
'bold',
'italic',
'underline',
'|',
'heading-1',
'quote',
'|',
{
key: 'history',
title: '历史',
icon: 'history',
menuKeys: ['undo', 'redo']
}
],
excludeKeys: ['quote']
}
});
toolbar.update();toolbarConfig 规则:
toolbarKeys:完整控制显示顺序。- 字符串项使用
MenuItem.id;'|'只渲染分割线,不执行命令。 - 分组项使用
{ key, title, icon, menuKeys };DOM toolbar 会渲染一个分组按钮,点击后打开 Y 轴纵向收纳菜单,例如上面的配置会显示[历史]按钮,菜单里是[撤销]、[重做]。 key是分组入口的稳定 id,title是按钮文案和aria-label,icon用于分组按钮图标;menuKeys继续引用已有MenuItem.id,不要为收纳菜单重新声明一套命令。insertKeys:在默认菜单基础上插入。excludeKeys:隐藏默认菜单。
把几个功能收进“更多样式”菜单时,可以这样声明:
createRichTextToolbar(toolbarContainer, {
editor,
toolbarConfig: {
toolbarKeys: [
{
key: 'more-style-group',
title: '更多样式',
icon: 'more',
menuKeys: ['inline-code', 'clear-style']
},
'|',
'undo',
'redo'
]
}
});独立 toolbar:
const toolbar = createRichTextToolbar(toolbarContainer, {
editor,
placement: 'top',
toolbarConfig: {
toolbarKeys: ['bold', 'italic', '|', 'undo', 'redo']
}
});
toolbar.update();自定义菜单、Icon 和文案
import { createRichTextEditor, createRichTextToolbar } from 'bridgerte/dom';
import { defaultMenuSchema, type MenuItem } from 'bridgerte/native-spec';
const customMenu: MenuItem = {
id: 'custom-clear',
command: { type: 'content.clear' },
label: '清空',
icon: 'custom-clear',
group: 'history'
};
const menuSchema = [...defaultMenuSchema, customMenu];
const icons = {
'custom-clear': '<svg aria-hidden="true" viewBox="0 0 24 24"><path d="M4 6h16"/></svg>'
};
const menuLabels = {
'custom-clear': '清空文档',
bold: '加粗文本'
};
const editor = createRichTextEditor(editorContainer, {
menuSchema,
icons,
menuLabels
});
const toolbar = createRichTextToolbar(toolbarContainer, {
editor,
menuSchema,
toolbarConfig: {
insertKeys: {
index: 0,
keys: ['custom-clear', '|']
}
},
icons,
menuLabels
});
toolbar.update();稳定约束:
MenuItem.id是菜单配置使用的稳定 key。MenuItem.icon是稳定 icon key,不是 SVG 字符串。- 业务覆盖 icon 只能通过
iconsmap。 - 业务覆盖文案只能通过
menuLabels。 menuLabels影响按钮文本、tooltip 和aria-label,不改变命令语义。- 缺失 icon 时,DOM 菜单使用 label 文本兜底。
Hoverbar
选中文本 hoverbar 默认开启,复用 menuSchema、icons 和 menuLabels。它有独立的
hoverbarConfig,可以和 toolbar 展示不同菜单。
createRichTextEditor(container, {
hoverbarConfig: {
toolbarKeys: [
'bold',
'italic',
'|',
'color',
'background-color',
'|',
'font-size',
'line-height'
]
}
});关闭内置 hoverbar:
createRichTextEditor(container, {
floatingMenus: {
hoverbar: false
}
});关闭后只是不显示 DOM hoverbar,不影响底层命令 API。H5/WebView 或品牌化项目可以关闭内置 hoverbar 后自绘选区菜单。
参数面板
颜色、背景色、字号、字体、行高、表格和代码语言都通过 PayloadPanelSchema 描述候选项。
DOM 默认 UI 和业务自绘 request 使用同一份 schema。
createRichTextEditor(container, {
payloadPanelConfig: {
'font-size': {
fields: {
value: {
includeValues: ['16px', '20px', '24px'],
optionLabels: {
'16px': '正文',
'24px': '标题'
}
}
}
},
color: {
fields: {
value: {
options: [
{ label: '品牌蓝', value: '#1677ff' },
{ label: '危险红', value: '#ff4d4f' }
]
}
}
},
table: {
fields: {
rows: { defaultValue: '2', max: 6 },
cols: { defaultValue: '3', max: 6 }
}
},
'code-block-language': {
fields: {
language: {
includeValues: ['plain', 'javascript', 'typescript', 'json']
}
}
}
},
onPayloadPanelRequest(request) {
if (request.panel.id === 'color') {
renderColorPanel(request);
return true;
}
}
});自绘接管规则:
createRichTextEditor(container, {
onPayloadPanelRequest(request) {
renderPanel({
title: request.panel.title,
fields: request.panel.fields,
currentValues: request.currentValues,
readonly: request.readonly,
submit: request.submit,
cancel: request.cancel
});
return true;
}
});onPayloadPanelRequest 返回 true 表示业务接管渲染,DOM 默认面板不会显示。业务自绘完成后:
request.submit({ value: '#1677ff' });
request.cancel();readonly 下 request 会带 readonly: true,自绘层应展示只读态;DOM 默认面板不会打开。
代码块语言也可以直接传完整 schema:
createRichTextEditor(container, {
codeBlockLanguagePanel: {
id: 'code-block-language',
title: '代码语言',
fields: [
{
type: 'select',
name: 'language',
label: '语言',
options: [
{ label: '纯文本', value: '' },
{ label: 'Go', value: 'go' },
{ label: 'TSX', value: 'tsx' },
{ label: 'TypeScript', value: 'typescript' },
{ label: 'JSON', value: 'json' }
]
}
]
}
});默认代码块高亮使用 @lexical/code-shiki,语言 schema 只放技术文档高频候选;业务可以继续用
codeBlockLanguagePanel 完整替换。HTML 粘贴会按 Shiki 支持的语言归一化显式 language-* /
data-language 标记,纯文本 fenced code 只在带语言时接管。
当前内置语言候选包括:纯文本、Bash、C、C++、C#、CSS、Dart、Dockerfile、Go、HTML、Java、
JavaScript、JSON、Kotlin、Markdown、PHP、Python、Rust、SQL、Swift、TOML、TSX、TypeScript、
Vue、XML、YAML。粘贴 fenced code 时也会识别常见 alias,
例如 bash/sh 会归一到 shellscript,js 到 javascript,ts 到 typescript,
yml 到 yaml。
图片、视频和上传
BridgeRTE 不内置上传后端。图片/视频上传必须由业务实现 uploadAdapter。
import { createRichTextEditor } from 'bridgerte/dom';
import type { UploadAdapter } from 'bridgerte/core';
const uploadBlob = async (url: string, file: unknown, signal?: AbortSignal) => {
const formData = new FormData();
if (file instanceof Blob) formData.append('file', file);
const response = await fetch(url, {
method: 'POST',
body: formData,
signal
});
return await response.json() as {
url: string;
width?: number;
height?: number;
poster?: string;
};
};
const uploadAdapter: UploadAdapter = {
async uploadImage(file, context) {
return await uploadBlob('/api/upload-image', file.data, context.signal as AbortSignal);
},
async uploadVideo(file, context) {
return await uploadBlob('/api/upload-video', file.data, context.signal as AbortSignal);
}
};
createRichTextEditor(container, {
uploadAdapter,
mediaDefaultWidthPercent: 50
});媒体能力:
- 默认 toolbar 提供本地上传图片/视频入口。
- URL 图片/视频插入使用
media.insertImage/media.insertVideo命令。 - 图片/视频加载前会显示占位和 loading 状态,资源加载完成后再显示真实媒体。
- 上传失败时可以重试或删除。
- 成功态 controls 支持左/中/右对齐、
20%、50%、100%显示比例和删除。 mediaDefaultWidthPercent可设为20 | 50 | 100,默认50。
配置媒体 controls:
createRichTextEditor(container, {
mediaControlsConfig: {
toolbarKeys: [
'media-align-left',
'media-align-center',
'media-align-right',
'|',
'media-remove'
]
},
menuLabels: {
'media-remove': '删除媒体'
}
});media-resize-20、media-resize-50、media-resize-100 是基础尺寸能力,配置中误删时会自动补回。
如果业务完全自绘媒体 controls,也需要提供等价的 20%、50%、100% 尺寸能力。
Mention
@ mention 默认开启。mentionProvider 负责返回候选数据,展示字段由
mentionMenuConfig 控制。
import { createRichTextEditor } from 'bridgerte/dom';
import type { MentionItem } from 'bridgerte/core';
const mentionProvider = async (query: string): Promise<MentionItem[]> => {
const response = await fetch(`/api/members?q=${encodeURIComponent(query)}`);
return await response.json() as MentionItem[];
};
createRichTextEditor(container, {
mentionProvider,
mentionMenuConfig: {
labelField: 'data.displayName',
descriptionField: 'data.role',
avatarField: 'data.avatarUrl',
showAvatar: true,
showDescription: true,
loadingText: '搜索成员中',
emptyText: '没有匹配成员',
errorText: '成员加载失败'
}
});自绘 mention 菜单:
createRichTextEditor(container, {
mentionProvider,
onMentionMenuRequest(request) {
renderMentionPopover(request);
return true;
}
});关闭 mention trigger:
createRichTextEditor(container, {
floatingMenus: {
mention: false
}
});关闭后不会监听 @query,也不会请求 provider;业务仍可主动执行 mention.insert 命令。
Slash Command
/ slash command 默认从菜单 schema 里选择常用结构命令。
createRichTextEditor(container, {
slashCommandConfig: {
toolbarKeys: ['heading-1', 'heading-2', '|', 'quote', 'code-block', 'table']
},
slashCommandMenuConfig: {
showIcon: true,
loadingText: '加载命令中',
emptyText: '没有匹配命令',
errorText: '命令加载失败'
}
});slashCommandMenuConfig.showIcon 只控制默认 DOM / 菜单是否展示图标;schema 和 provider
候选里的 icon key 仍会保留,业务自绘菜单可以继续读取它。想做成纯文字候选:
createRichTextEditor(container, {
slashCommandMenuConfig: {
showIcon: false
}
});追加动态候选:
import type { SlashCommandItem } from 'bridgerte/core';
const slashCommandProvider = async (query: string): Promise<SlashCommandItem[]> => [
{
id: 'insert-template',
label: '插入模板',
description: `按 ${query} 搜索模板`,
icon: 'template',
command: { type: 'block.quote' }
}
];
createRichTextEditor(container, {
slashCommandConfig: {
toolbarKeys: ['quote', 'table']
},
slashCommandProvider
});语义说明:
- 只传
slashCommandProvider时,provider 候选替换默认 slash 列表。 - 传入
slashCommandConfig或自定义menuSchema后,provider 作为动态候选追加。 - provider 失败时,如果静态候选可用,仍显示静态候选。
- 表格这类需要参数的命令会继续走参数面板。
slashCommandConfig复用 toolbar 的显示规则,toolbarKeys、insertKeys、excludeKeys的语义一致;未知 key 会被忽略,首尾或连续分割线会在解析阶段清理。
自绘 slash command:
createRichTextEditor(container, {
onSlashCommandMenuRequest(request) {
renderSlashPopover(request);
return true;
}
});关闭 slash trigger:
createRichTextEditor(container, {
floatingMenus: {
slash: false
}
});WebView
WebView 页面内使用 createWebViewBridgeRuntime() 接 RN/Flutter 外壳消息。
import { createWebViewBridgeRuntime } from 'bridgerte/webview';
import 'bridgerte/style.css';
const runtime = createWebViewBridgeRuntime({
container,
transport: {
postMessage(message) {
window.ReactNativeWebView?.postMessage(JSON.stringify(message));
},
addMessageListener(listener) {
const handleMessage = (event: MessageEvent) => {
listener(JSON.parse(String(event.data)));
};
window.addEventListener('message', handleMessage);
return () => {
window.removeEventListener('message', handleMessage);
};
}
}
});
window.addEventListener('beforeunload', () => {
runtime.destroy();
});也可以不提供 addMessageListener,由业务手动转发消息:
runtime.receive(messageFromNative);原生侧发给编辑器:
editor.initeditor.executeCommandeditor.setContenteditor.setReadonlyeditor.requestContenteditor.payloadPanelResolvededitor.payloadPanelCancelededitor.uploadResolvededitor.uploadRejected
编辑器发给原生侧:
editor.readyeditor.contenteditor.contentChangeeditor.commandStateChangeeditor.payloadPanelRequesteditor.uploadRequesteditor.heightChangeeditor.error
内容消息边界:
- 高频自动
editor.contentChange只传轻量摘要。 - 完整
EditorContent通过原生侧发送editor.requestContent获取。 requestContent的响应消息是editor.content。- 兼容期也会同步发送旧
editor.contentChange完整响应。 - bridge 不传 File、Blob、base64 或大体积二进制文件。
RN / Flutter 原生菜单
RN/Flutter 原生侧可以读取 bridgerte/native-spec 来渲染自己的菜单:
import {
defaultMenuSchema,
defaultToolbarConfig,
resolveToolbarMenu,
isMenuItemCommandState
} from 'bridgerte/native-spec';
const toolbarItems = resolveToolbarMenu(defaultToolbarConfig, defaultMenuSchema);渲染规则:
MenuItem.id是配置和状态匹配的稳定 key。MenuItem.command是完整命令,点击后可以直接发给 WebView。MenuItem.icon是稳定 icon key,RN/Flutter 映射到自己的原生图标。MenuItem.icon不是 SVG 字符串。payloadPanel描述需要原生侧补齐的参数。- 命令状态可用
isMenuItemCommandState(item, state)匹配。
原生菜单不复用 DOM CSS;WebView 内编辑器样式通过 --bridgerte-* CSS Variables 覆盖。
样式和主题
导入默认样式:
import 'bridgerte/style.css';覆盖主题变量:
.editor-shell {
--bridgerte-color-primary: #1677ff;
--bridgerte-color-text: #1f2329;
--bridgerte-color-text-muted: #86909c;
--bridgerte-color-bg: #ffffff;
--bridgerte-color-panel: #ffffff;
--bridgerte-color-border: #e5e6eb;
--bridgerte-color-active-bg: #e8f3ff;
--bridgerte-color-placeholder: #b7bcc5;
--bridgerte-shadow-panel: 0 12px 32px rgb(15 23 42 / 14%);
--bridgerte-font-size: 15px;
--bridgerte-line-height: 1.7;
--bridgerte-radius: 8px;
--bridgerte-toolbar-height: 42px;
--bridgerte-control-height: 32px;
--bridgerte-editor-padding: 12px;
}常用变量:
--bridgerte-color-primary--bridgerte-color-text--bridgerte-color-text-muted--bridgerte-color-bg--bridgerte-color-panel--bridgerte-color-border--bridgerte-color-active-bg--bridgerte-color-placeholder--bridgerte-color-danger--bridgerte-shadow-panel--bridgerte-font-size--bridgerte-line-height--bridgerte-radius--bridgerte-toolbar-height--bridgerte-control-height--bridgerte-hoverbar-button-size--bridgerte-editor-padding
PC/H5 边界:
- DOM 默认样式只服务 Web/PC/H5。
- RN/Flutter 原生菜单不复用 DOM CSS。
- H5 触屏端不依赖 hover tooltip。
- 业务可以在外层容器覆盖 CSS Variables 实现品牌主题。
性能建议
BridgeRTE 按 10w 字符级内容设计输入路径:
- 不要在每次输入时调用
getContent()。 - 不要对 10w 内容逐字依赖
onChange完整保存。 - 高频 UI 状态使用
onContentChange摘要。 - 保存、提交或离开页面确认时再调用
getContent()。 - WebView 高频
editor.contentChange只依赖摘要。 - WebView 完整内容通过
editor.requestContent主动获取。 - bridge 不传 base64、File、Blob 或二进制大文件。
推荐保存:
const save = async () => {
const content = editor.getContent();
await fetch('/api/document', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(content)
});
};当前边界
- 业务项目只安装
bridgerte,不需要安装 Lexical。 - 默认 toolbar 不提供图片/视频 URL 插入入口;业务用命令 API 自定义入口。
- 主动链接编辑不作为默认内置入口;业务用
link.*命令自定义入口。 - BridgeRTE 不内置上传后端,上传必须由业务实现
uploadAdapter。 - WebView bridge 不传大体积二进制和 base64 文件。
