Project Icon

mui-tiptap

基于Material UI和Tiptap的可定制富文本编辑器

mui-tiptap是基于Material UI和Tiptap的富文本编辑器组件,提供可定制样式和丰富功能。支持图片调整、标题锚点、字体控制等特性,具备实时协作和跨平台兼容能力。该组件可根据MUI主题自动适应颜色和暗黑模式,为开发者提供全面的富文本编辑方案,支持快速集成和深度定制。

mui-tiptap标志

mui-tiptap:一个可定制的Material UI风格的所见即所得富文本编辑器,使用Tiptap

npm mui-tiptap包 npm类型定义 GitHub工作流状态 项目许可证

- :sparkles: 基于您自己的MUI主题样式(颜色、字体、亮暗模式等) - :hammer_and_wrench: 建立在强大的Tiptap和ProseMirror基础之上(可扩展、实时协作编辑、跨平台支持等) **特性:** - :toolbox: 一体化的`RichTextEditor`组件,可立即开始使用(无需其他组件或钩子!),或使用单独的模块化组件以满足您的定制需求 - :sunglasses: 内置Tiptap扩展的样式(文本格式化、列表、表格、类似Google Docs的协作光标等) - :arrow_forward: 标准Tiptap扩展的可组合和可扩展的菜单按钮和控件 - :framed_picture: [`ResizableImage`扩展](#resizableimage),用于直接在编辑器中添加和调整图像大小 - :anchor: [`HeadingWithAnchor`扩展](#headingwithanchor),为添加的每个标题生成类似GitHub的动态锚链接 - :link: [`LinkBubbleMenu`](#components),使添加和编辑链接变得轻而易举 - :1234: [`FontSize`扩展](#fontsize),用于控制文本大小 - :white_square_button: [`TableImproved`扩展](#tableimproved),[修复](https://github.com/ueberdosis/tiptap/issues/2041)[了](https://github.com/ueberdosis/tiptap/issues/2301)底层Tiptap `Table`扩展的问题 - :pencil: [`TableBubbleMenu`](#components),用于交互式编辑富文本表格 - :speech_balloon: 通用的[`ControlledBubbleMenu`](#components),用于构建您自己的自定义菜单,[解决了](https://github.com/ueberdosis/tiptap/issues/2305#issuecomment-1020665146)Tiptap `BubbleMenu`的一些缺陷 - 以及更多!
README目录 - [演示](#demo) - [安装](#installation) - [开始使用](#get-started) - [使用一体化组件](#use-the-all-in-one-component) - [自行创建和提供`editor`](#create-and-provide-the-editor-yourself) - [渲染只读富文本内容](#render-read-only-rich-text-content) - [mui-tiptap扩展和组件](#mui-tiptap-extensions-and-components) - [Tiptap扩展](#tiptap-extensions) - [`HeadingWithAnchor`](#headingwithanchor) - [`FontSize`](#fontsize) - [`LinkBubbleMenuHandler`](#linkbubblemenuhandler) - [`ResizableImage`](#resizableimage) - [`TableImproved`](#tableimproved) - [组件](#components) - [控件组件](#controls-components) - [本地化](#localization) - [提示和建议](#tips-and-suggestions) - [选择您的编辑器`extensions`](#choosing-your-editor-extensions) - [扩展优先级和排序](#extension-precedence-and-ordering) - [其他扩展提示](#other-extension-tips) - [图像的拖放和粘贴](#drag-and-drop-and-paste-for-images) - [`content`变化时重新渲染`RichTextEditor`](#re-rendering-richtexteditor-when-content-changes) - [贡献](#contributing)
## 演示 在这个 **[CodeSandbox 在线演示](https://codesandbox.io/p/sandbox/mui-tiptap-demo-3zl2l6)** 中亲自尝试! ![mui-tiptap 演示](https://github.com/sjdemartini/mui-tiptap/assets/1647130/b25d33e0-4cdc-4fde-95bc-ec8403da7ccd) ## 安装 ```shell npm install mui-tiptap ``` 或 ```shell yarn add mui-tiptap ``` 此包有一些对等依赖,包括 [`@mui/material`](https://www.npmjs.com/package/@mui/material) 和 [`@mui/icons-material`](https://www.npmjs.com/package/@mui/icons-material)(以及它们的 `@emotion/` 对等依赖),还有 [`@tiptap/`](https://tiptap.dev/installation/react) 相关包。如果你使用的是 npm 7+ 或 pnpm,这些依赖应该会自动安装。否则,如果你的项目还没有使用这些依赖,你可以通过以下命令安装:
npm install @mui/material @mui/icons-material @emotion/react @emotion/styled @tiptap/react @tiptap/extension-heading @tiptap/extension-image @tiptap/extension-table @tiptap/pm @tiptap/core

yarn add @mui/material @mui/icons-material @emotion/react @emotion/styled @tiptap/react @tiptap/extension-heading @tiptap/extension-image @tiptap/extension-table @tiptap/pm @tiptap/core

开始使用

使用一体化组件

渲染富文本编辑器最简单的方法是使用 RichTextEditor 组件:

import { Button } from "@mui/material";
import StarterKit from "@tiptap/starter-kit";
import {
  MenuButtonBold,
  MenuButtonItalic,
  MenuControlsContainer,
  MenuDivider,
  MenuSelectHeading,
  RichTextEditor,
  type RichTextEditorRef,
} from "mui-tiptap";
import { useRef } from "react";

function App() {
  const rteRef = useRef<RichTextEditorRef>(null);

  return (
    <div>
      <RichTextEditor
        ref={rteRef}
        extensions={[StarterKit]} // 或任何你想要的 Tiptap 扩展!
        content="<p>Hello world</p>" // 编辑器的初始内容
        // 可选包含 `renderControls` 以在编辑器顶部显示菜单栏:
        renderControls={() => (
          <MenuControlsContainer>
            <MenuSelectHeading />
            <MenuDivider />
            <MenuButtonBold />
            <MenuButtonItalic />
            {/* 在此处添加更多你选择的控件 */}
          </MenuControlsContainer>
        )}
      />

      <Button onClick={() => console.log(rteRef.current?.editor?.getHTML())}>
        记录 HTML
      </Button>
    </div>
  );
}

查看下面的 mui-tiptap 扩展和组件 了解更多可以使用的 Tiptap 扩展和组件(比如更多可以包含在 renderControls 中的内容)。查看 src/demo/Editor.tsx 获取使用 RichTextEditor 的更详细示例。

自行创建和提供 editor

如果你需要更多自定义选项,你可以使用 Tiptap 的 useEditor 钩子定义你的编辑器,并使用一系列 mui-tiptap 组件(和/或你自己的组件)来布局你的 UI。

editor 传递给组件树顶部的 mui-tiptapRichTextEditorProvider 组件。然后,在提供者内渲染符合你需求的任何子组件。

最简单的选项是 RichTextField 组件,这也是 RichTextEditor 在底层使用的组件:

import { useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import {
  MenuButtonBold,
  MenuButtonItalic,
  MenuControlsContainer,
  MenuDivider,
  MenuSelectHeading,
  RichTextEditorProvider,
  RichTextField,
} from "mui-tiptap";

function App() {
  const editor = useEditor({
    extensions: [StarterKit],
    content: "<p>Hello <b>world</b>!</p>",
  });
  return (
    <RichTextEditorProvider editor={editor}>
      <RichTextField
        controls={
          <MenuControlsContainer>
            <MenuSelectHeading />
            <MenuDivider />
            <MenuButtonBold />
            <MenuButtonItalic />
            {/* 在此处添加更多你选择的控件 */}
          </MenuControlsContainer>
        }
      />
    </RichTextEditorProvider>
  );
}

或者如果你想完全控制 UI,你可以自己构建编辑器区域,然后只在你想要显示(经过样式处理的)可编辑富文本内容的地方使用 <RichTextContent /> 组件。RichTextContent 是 Tiptap 的 EditorContent 组件的 MUI 主题版本。

渲染只读富文本内容

使用 RichTextReadOnly 组件,只需传入你的 HTML 或 ProseMirror JSON 以及你配置的 Tiptap 扩展,如:

<RichTextReadOnly content="<p>Hello world</p>" extensions={[StarterKit]} />

或者,你可以将 RichTextEditoreditable 属性(或 useEditoreditable 选项)设置为 false,以获得更可配置的只读选项。在以下情况下使用 RichTextReadOnly

  • 你只想直接高效地渲染编辑器 HTML/JSON 内容,而不需要任何轮廓字段样式、控件设置、额外的监听器逻辑、访问 editor 对象等。(如果 content 为空,该组件还会跳过创建 Tiptap editor,这可以提高性能。)
  • 你想要一种方便的方式来渲染内容,使其随 content 属性的变化而更新。(相比之下,RichTextEditor 不会在 content 变化时自动重新渲染,如下面所述。)

mui-tiptap 扩展和组件

Tiptap 扩展

HeadingWithAnchor

这是 Tiptap 的 Heading 扩展 的修改版本,为每个添加的标题提供动态的 GitHub 风格锚点链接。当 editoreditable 设置为 false 时,鼠标悬停在标题上会在其左侧显示一个锚点链接按钮。这允许用户分享链接并跳转到编辑器内容中的特定标题。

FontSize

设置文本字体大小。此扩展需要安装 @tiptap/extension-text-style 包,并在 extensions 中包含其 TextStyle 标记。 可以通过 MenuSelectFontSize 组件 进行控制。

命令
  • setFontSize():设置文本字体大小(使用有效的 CSS font-size 属性)。例如:"12px""2em""small"
  • unsetFontSize():移除先前设置的字体大小,恢复为给定标记的默认大小。

LinkBubbleMenuHandler

LinkBubbleMenu 组件 配合使用,此扩展提供编辑器命令来控制链接气泡菜单的状态。

命令
  • openLinkBubbleMenu():打开/显示链接气泡菜单。如果当前光标选择处没有链接,则创建一个链接;如果已存在链接,则编辑现有链接。
  • editLinkInBubbleMenu():在气泡菜单中编辑现有链接,用于已打开的气泡菜单中查看链接时。
  • closeLinkBubbleMenu():关闭/隐藏链接气泡菜单,取消任何正在进行的编辑。

ResizableImage

这是 Tiptap 的 Image 扩展 的修改版本,增加了直接在编辑器中调整图片大小的功能。点击图片时,右下角会出现一个拖动手柄,用户可以交互式地更改大小。

TableImproved

这是 Tiptap 的 Table 扩展 的修改版本,修复了与列调整大小和可编辑状态相关的问题。 具体而言,此版本的扩展与 mui-tiptap CSS 样式相结合,确保:

  1. 即使编辑器处于 editable=false 状态,列也能保持其调整后的宽度
  2. 无论初始编辑器状态如何,从 editable=false 切换到 editable=true 时,都可以进行列宽调整 (解决了这些已报告的 Tiptap 问题:123。)

组件

组件描述
RichTextEditor一个直接渲染 MUI 风格 Tiptap 富文本编辑器字段的一体化组件。内部使用了许多下面的组件。参见上面的"开始使用"注意事项。简而言之:<RichTextEditor ref={rteRef} content="<p>Hello world</p>" extensions={[...]} />
RichTextReadOnly一个直接渲染只读 Tiptap 编辑器内容的一体化组件。虽然 RichTextEditor(或 useEditorRichTextEditorProviderRichTextContent)可以通过编辑器的 editable 属性设置为只读,但这是一个更简单和高效的版本,只渲染内容而不做其他操作(例如,不实例化工具栏、气泡菜单等在只读环境中可能不需要的内容,如果没有内容显示,它甚至不会实例化编辑器)。
RichTextEditorProvider使用 React context 使 Tiptap editor 对任何嵌套组件可用,这样就不需要在每个层级手动传递 editor。除了一体化的 RichTextEditorRichTextReadOnly 之外,大多数 mui-tiptap 组件都需要它作为父组件。通过 useRichTextEditorContext() 钩子在你自己的组件中使用提供的 editor
RichTextField渲染 Tiptap 富文本编辑器内容和控制菜单栏。使用 "outlined" 变体时,渲染类似于 Material UI TextField 的带边框 UI。"standard" 变体没有轮廓/边框。
MenuBar一个可折叠的、可选固定的容器,用于在编辑器内容顶部显示编辑器控件。(此组件用于包含 RichTextEditorrenderControlsRichTextFieldcontrols,但如果你想做一些更自定义的操作,也可以直接使用。)
RichTextContent渲染 Material UI 样式的 Tiptap 富文本编辑器内容。应用所有用于格式化的 CSS 规则,作为 Tiptap 的 <EditorContent /> 组件的样式替代品。(在 RichTextEditorRichTextField 中自动使用。)
LinkBubbleMenu在查看、创建或编辑链接时渲染气泡菜单。需要 Tiptap Link 扩展@tiptap/extension-link)和 mui-tiptap 的 LinkBubbleMenuHandler 扩展。与 <MenuButtonEditLink /> 组件 配合使用效果很好。

如果你使用 RichTextEditor,通过 RichTextEditorchildren 渲染属性包含此组件。否则,将 LinkBubbleMenu 作为调用 useEditor 并渲染 RichTextFieldRichTextContent 的组件的子组件。(只要在 Tiptap editor 强制更新时重新渲染,气泡菜单本身就会被适当定位,如果它是使用 useEditor 的组件的子组件,就会发生这种情况)。参见 src/demo/Editor.tsx 中的示例。
TableBubbleMenu当用户的光标/选择位于表格内时,渲染一个气泡菜单来操作表格内容(添加或删除列或行、合并单元格等)。用于 mui-tiptap 的 TableImproved 扩展 或 Tiptap 的 @tiptap/extension-table 扩展。

如果你使用 RichTextEditor,通过 RichTextEditorchildren 渲染属性包含此组件。否则,将 TableBubbleMenu 作为调用 useEditor 并渲染 RichTextFieldRichTextContent 的组件的子组件。(只要在 Tiptap editor 强制更新时重新渲染,气泡菜单本身就会被适当定位,如果它是使用 useEditor 的组件的子组件,就会发生这种情况)。参见 src/demo/Editor.tsx 中的示例。
ControlledBubbleMenu用于构建自定义气泡菜单的通用组件,解决了 Tiptap 的 BubbleMenu 的一些缺点。这是 LinkBubbleMenuTableBubbleMenu 在底层使用的组件。
ColorPicker一个包含色相/饱和度/透明度渐变选择器的颜色选择器(通过 react-colorful),还有一个直接输入颜色的文本输入框,以及可选的 swatchColors 用于颜色预设。在底层被 MenuButtonColorPicker/MenuButtonTextColor/MenuButtonHighlightColor 使用。重要的属性:
swatchColors:显示为预设按钮的颜色数组。
colorToHex:覆盖默认的将给定 CSS 颜色字符串转换为十六进制格式字符串的实现(例如 "#ff0000")。如果给定的颜色无法解析为有效颜色,应返回 null。详见 ColorPickerProps 定义,如使用更全功能库如 colordtinycolor2 的示例。
disableAlpha:如果为 true,禁用透明度滑块。
value/onChange:受控的颜色值字符串(未设置时为空字符串)及其变更回调。
ColorSwatchButton渲染一个显示并允许选择颜色预设的按钮。被 ColorPicker 用于其 swatchColors

控件组件

这些控件组件帮助你快速组装菜单栏,用于你可能想使用的各种 Tiptap 扩展。 你可以覆盖这些组件的所有属性(例如更改 IconComponenttooltipLabel、显示哪个快捷键的 tooltipShortcutKeysonClick 行为等)。或者使用基础的 MenuButtonMenuSelect 组件轻松创建适用于你自己的扩展和用例的控件。

扩展mui-tiptap 组件
@tiptap/extension-blockquoteMenuButtonBlockquote
@tiptap/extension-boldMenuButtonBold
@tiptap/extension-bullet-listMenuButtonBulletedList
@tiptap/extension-colorMenuButtonTextColor(接受可选的 defaultTextColor 属性。其他自定义详情请参见下面的 MenuButtonColorPicker。)
@tiptap/extension-codeMenuButtonCode
@tiptap/extension-code-blockMenuButtonCodeBlock
@tiptap/extension-font-familyMenuSelectFontFamily(使用 options 属性指定可选择的字体系列,如 [{ label: "等宽字体", value: "monospace" }, ...]
mui-tiptap 的 FontSizeMenuSelectFontSize(使用 options 属性覆盖默认的大小选项)
mui-tiptap 的 HeadingWithAnchor
@tiptap/extension-heading
MenuSelectHeading
@tiptap/extension-highlightMenuButtonHighlightColor:用于Highlightmulticolor: true模式。接受可选的defaultMarkColor。有关其他自定义详情,请参见下面的MenuButtonColorPicker
MenuButtonHighlightToggle:用于Highlight的默认multicolor: false模式
@tiptap/extension-historyMenuButtonRedoMenuButtonUndo
@tiptap/extension-horizontal-ruleMenuButtonHorizontalRule
mui-tiptap的ResizableImage
@tiptap/extension-image
MenuButtonAddImage:通用按钮。提供自己的onClick行为(例如,像这样让用户提供图片URL)。
MenuButtonImageUpload:上传图片。提供onUploadFiles属性来处理文件上传并返回可服务的URL。
另请参见mui-tiptap的insertImages工具,用于在Tiptap编辑器内容中插入图片。
@tiptap/extension-italicMenuButtonItalic
@tiptap/extension-linkMenuButtonEditLink(需要mui-tiptap的LinkBubbleMenuHandler扩展<LinkBubbleMenu />组件
@tiptap/extension-list-itemMenuButtonIndentMenuButtonUnindent
@tiptap/extension-ordered-listMenuButtonOrderedList
@tiptap/extension-paragraphMenuSelectHeading
@tiptap/extension-strikeMenuButtonStrikethrough
@tiptap/extension-subscriptMenuButtonSubscript
@tiptap/extension-superscriptMenuButtonSuperscript
mui-tiptap的TableImproved
@tiptap/extension-table
• 插入新表格:MenuButtonAddTable
• 编辑表格(添加列、合并单元格等):TableBubbleMenu,或如果需要替代气泡菜单的UI,则使用TableMenuControls
@tiptap/extension-task-listMenuButtonTaskList
@tiptap/extension-text-alignMenuSelectTextAlign(一体化选择)
MenuButtonAlignLeftMenuButtonAlignCenterMenuButtonAlignRightMenuButtonAlignJustify(单独按钮)
@tiptap/extension-underlineMenuButtonUnderline
其他控件组件:
  • MenuButtonColorPicker:一个用于打开mui-tiptap ColorPicker的按钮,让用户选择颜色。被MenuButtonTextColorMenuButtonHighlightColor使用,它们的属性扩展了MenuButtonColorPicker。重要属性:
    • swatchColors:显示为"预设"颜色按钮的颜色选项数组。
    • value/onChange:当前颜色(CSS字符串)及其变更回调。这是一个受控组件,因此必须提供这些属性,除非您使用MenuButtonTextColorMenuButtonHighlightColor,它们会处理该逻辑。
    • popperId:点击此按钮时显示的颜色选择器弹出框的唯一HTML ID(用于无障碍访问的aria-describedby)。
    • PopperProps:覆盖容纳颜色选择器的弹出框的属性。
    • ColorPickerProps:覆盖mui-tiptap ColorPicker的属性,如colorToHex以自定义颜色解析逻辑。
  • MenuButtonRemoveFormatting:一个控制按钮,用于移除所有内联格式标记(调用Tiptap的unsetAllMarks()
  • MenuDivider:渲染一个垂直线分隔符,用于分隔菜单栏的不同部分并隐式地分组不同的控件。
  • MenuControlsContainer:为作为children提供的不同编辑器控件组件提供一致的间距。 通常,您将像这样定义控件(用于RichTextEditorrenderControlsRichTextFieldcontrols):
<MenuControlsContainer>
  <MenuSelectHeading />
  <MenuDivider />
  <MenuButtonBold />
  <MenuButtonItalic />
  {/* 在这里添加更多您选择的控件 */}
</MenuControlsContainer>

本地化

所有的菜单按钮、选择组件和气泡菜单都允许你通过props覆盖它们的默认标签和内容。以下是一些示例。

按钮

通常情况下,使用 tooltipLabel

<MenuButtonBold tooltipLabel="切换粗体" />

MenuButtonTextColorMenuButtonHighlightColor 组件还有一个 labels prop,用于覆盖颜色选择器弹出窗口的内容。

<MenuButtonTextColor
tooltipLabel="文字颜色"
labels={{
cancelButton: "取消",
removeColorButton: "重置",
removeColorButtonTooltipTitle: "移除颜色",
saveButton: "确定",
textFieldPlaceholder: '例如: "#7cb5ec"',
}}
/>
选择器
<MenuSelectFontFamily
options={[
{ label: "等宽字体", value: "monospace" },
{ label: "衬线字体", value: "serif" },
]}
aria-label="字体系列"
emptyLabel="字体系列"
tooltipTitle="更改字体系列"
unsetOptionLabel="重置"
/>
<MenuSelectFontSize
aria-label="字体大小"
tooltipTitle="更改字体大小"
unsetOptionLabel="重置"
/>
<MenuSelectHeading
aria-label="标题类型"
tooltipTitle="更改标题类型"
labels={{
empty: "更改为…",
paragraph: "普通文本",
heading1: "标题1",
heading2: "标题2",
heading3: "标题3",
heading4: "标题4",
heading5: "标题5",
heading6: "标题6",
}}
/>
<MenuSelectTextAlign
aria-label="文本对齐方式"
tooltipTitle="更改文本对齐方式"
options={[
{
value: "left",
label: "左对齐",
shortcutKeys: ["mod", "Shift", "L"],
IconComponent: MyCustomLeftAlignIcon,
},
{
value: "right",
label: "右对齐",
shortcutKeys: ["mod", "Shift", "R"],
IconComponent: MyCustomRightAlignIcon,
},
]}
/>
气泡菜单
<LinkBubbleMenu
labels={{
viewLinkEditButtonLabel: "编辑链接",
viewLinkRemoveButtonLabel: "移除链接",
editLinkAddTitle: "添加新链接",
editLinkEditTitle: "更新此链接",
editLinkCancelButtonLabel: "取消更改",
editLinkTextInputLabel: "文本内容",
editLinkHrefInputLabel: "URL",
editLinkSaveButtonLabel: "保存更改",
}}
/>
<TableBubbleMenu
labels={{
insertColumnBefore: "在此之前添加新列",
insertColumnAfter: "在此之后添加新列",
deleteColumn: "删除当前列",
// 还有更多选项。详情请查看props类型定义!
}}
/>
## 提示和建议

选择编辑器扩展

浏览Tiptap官方扩展,并查看mui-tiptap的额外扩展。最简单的入门方式是安装并使用Tiptap的StarterKit扩展,它捆绑了几个常用的Tiptap扩展。

要使用扩展,你需要(1)安装其包,(2)在实例化编辑器时将扩展包含在extensions数组中(通过<RichTextEditor extensions={[]} />useEditor({ extensions: [] }))。

扩展优先级和顺序

需要更高优先级的扩展(用于其键盘快捷键等)应该在你的扩展数组中靠后放置。(参见Tiptap关于扩展插件优先级和顺序的一般说明此处。)例如:

  • TableImproved(或Table)扩展放在数组的第一位。
  • 如底层prosemirror-tables包中所述,表格编辑插件应具有最低优先级,因为它依赖于键盘和鼠标事件,但其他插件可能需要先处理这些事件。例如,如果你想在表格内缩进或取消缩进列表项,你应该能够通过按Tab键来实现,只有在不在这样的嵌套节点内时,Tab键才会在表格单元格间移动。
  • Blockquote扩展放在Bold扩展之后,这样Blockquote的键盘快捷键优先级更高。
  • 否则,Blockquote的键盘快捷键(Cmd+Shift+B)会错误地切换粗体标记(由于其"重叠"的Cmd+b快捷键)。(参见相关Tiptap问题这里这里。)
  • Mention扩展放在列表相关扩展(TaskListTaskItemBulletListOrderedListListItem等)之后,这样在提及建议上按"Enter"键将选择它,而不是创建新的列表项(当试图在现有列表项内@提及某人时)。

其他扩展提示

  • 如果你希望SubscriptSuperscript扩展互斥,使文本不能同时为上标和下标,请使用excludes配置参数来相互排除。
  • 此Tiptap问题中所述。例如:
const CustomSubscript = Subscript.extend({
  excludes: "superscript",
});
const CustomSuperscript = Superscript.extend({
  excludes: "subscript",
});
  • 如果你更喜欢能够为内联Code标记添加样式(例如,使其加粗、添加链接、更改字体大小),你应该扩展该扩展并覆盖excludes字段,因为默认情况下它使用"_"使其与所有其他标记互斥。例如,要允许你将Code与任何其他内联标记一起应用,使用excludes: "",或要使其与除斜体以外的所有标记一起工作,使用:
Code.extend({ excludes: "italic" });

图片的拖放和粘贴

你可以为RichTextEditor组件或useEditor提供editorProps,并提供handleDrophandlePaste选项,以分别添加对图片文件拖放和粘贴的支持。查看mui-tiptap示例以了解其实际应用。mui-tiptap的insertImages工具在这方面很有用,可以将上传的文件插入到编辑器内容中。

content变化时重新渲染RichTextEditor

默认情况下,RichTextEditor使用content的方式与Tiptap的useEditor相同:它设置编辑器的初始内容,而content变量的后续更改将_不会_改变渲染的内容。(只有用户的编辑器交互才会改变。)这可以避免在用户主动输入或编辑时覆盖内容的烦恼。

RichTextEditor/useEditor用作完全"受控组件"(即在编辑器的每次onUpdate调用时更改content)并不高效,因为编辑器内容必须序列化以获取HTML字符串(getHTML())或ProseMirror JSON(getJSON())(参见Tiptap文档这个讨论)。

但如果你在某些情况下需要这种行为,比如你在组件外部改变了content且与用户的编辑器交互无关,你可以在钩子中调用editor.commands.setContent(content)文档)来更新编辑器文档。

例如,你可以使用类似以下的代码,它(1)只在编辑器处于只读状态或未聚焦时调用setContent(旨在避免丢失用户正在进行的任何更改,但请记住isFocused本身的变化不会导致重新渲染,因此不会重新运行效果),以及(2)尝试保留用户当前的选择/光标位置:

const editor = rteRef.current?.editor;
useEffect(() => {
  if (!editor || editor.isDestroyed) {
    return;
  }
  if (!editor.isFocused || !editor.isEditable) {
    // 使用queueMicrotask,参考 https://github.com/ueberdosis/tiptap/issues/3764#issuecomment-1546854730
    queueMicrotask(() => {
      const currentSelection = editor.state.selection;
      editor
        .chain()
        .setContent(content)
        .setTextSelection(currentSelection)
        .run();
    });
  }
}, [content, editor, editor?.isEditable, editor?.isFocused]);

你也可以通过<RichTextEditor … editorDependencies={[content]} />(或等效地将其包含在你的useEditor依赖数组中)将content作为编辑器依赖项传递,这将在值发生变化时强制重新创建整个编辑器。这是一个效率较低的选项,可能会导致编辑器重建时出现视觉"闪烁"。

请注意,如果这些内容更新来自其他用户的更改(例如保存到数据库),使用Yjs的协作编辑功能可能会更好,而不是依赖于content

贡献

这里开始。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号