GithubHelp home page GithubHelp logo

textbus / textbus Goto Github PK

View Code? Open in Web Editor NEW
1.0K 25.0 119.0 5.54 MB

Textbus 是一个组件化的、数据驱动的富文本框架,支持在线协同编辑,拥有非常好的扩展性和可定制性,可使用 Viewfly、Vue 或 React 直接渲染富文本,是构建复杂富文本的不二之选!

Home Page: https://textbus.io

License: GNU General Public License v3.0

JavaScript 0.86% HTML 0.34% TypeScript 98.58% SCSS 0.18% Shell 0.03%
rich-text-editor rich-text wysiwyg wysiwyg-editor wysiwyg-html-editor collaborative-framework collaborative-editing collaboration

textbus's Introduction

Textbus

🚀 Textbus 是一个组件化、跨平台、数据驱动的富文本框架,支持使用 Viewfly、Vue、React 渲染富文本内容,并坚定的支持在线多人协作。你可以在 Textbus 中轻松创建出类似钉钉文档、石墨文档、飞书文档等完全自定义的编辑器。

官方文档

Textbus 官方文档

XNote 编辑器

XNote 是 Textbus 官方基于最新 4.0 版本开发的一个无头的、高性能的开源富文本编辑器。提供了开箱即用的大多数功能。也为需要自己开发编辑器的开发者提供了第一手的参考资料,仓库地址: https://github.com/textbus/xnote

你也可以直接查看在线演示:在线演示

介绍

我们一直致力于让富文本开发也能像普通前端框架一样,通过简明易懂的 api 和少量的约定,即可开发出使用流畅、交互丰富的富文本应用。

为了解决传统富文本开发的难题,Textbus 首次在富文本中引入了组件的概念,这让富文本开发就像拼积木一样,不再是前端领域不可跨越的天坑。不管你是富文本开发领域的老鸟,亦或是前端的新手,Textbus 都将帮助你把富文本做得更好。

Textbus 的特点

  • 组件化:根据富文本的特点而专门开发的组件化系统,让富文本编辑支持复杂布局,插入特殊控件等就像现代前端框架一样,非常的简单。
  • 完全可控:由于 Textbus 采用完全的数据驱动,输入输出完全依赖内核来完成,在不同的浏览器上,不会存在不一样的行为和结果。
  • 易扩展:hooks 风格的扩展代码,让你在不同上下文中对同样事件定制不同的行为变得异常简单。原生支持多种前端框架渲染,让你编写复杂交互更容易。
  • 语法糖支持:高度灵活的语法糖支持,你可以非常灵活的定制输入实时转换功能,如 Markdown 中的 # 号 + 空格变为标题等,你也可以完全自创语法,只要你开心。
  • 格式兼容:完全可定制的文档解析能力,可以让你最大可能的保持从网页、word 等其它页面复制过来的内容和格式。
  • 格式限制:既可以做到组件深层次嵌套,也可以做到像现在大多数编辑器一样 block 化。
  • 转换便捷:内置功能强大的格式转换能力,这也是富文本的难点之一,尤其是对于支持树状数据结构的编辑器来说,要实现这一点非常复杂。
  • 支持在线协作:Textbus 官方目前提供了基于 Yjs 的协作能力支持,你也可以采用其它的协作方案来对接 Textbus 的数据模型。
  • 高度抽象:完全抽象的光标和选区系统,你不需要再关心浏览器复杂的选区问题。

模块

模块 作用
@textbus/core 核心模块,提供了组件、插槽、格式、属性的数据模型抽象和选区、格式变换、渲染、组件生命周期管理、编辑器控制、历史记录、快捷键管理、语法糖管理、输出转换等富文本核心能力的实现
@textbus/platform-browser 浏览器支持中间层,提供了基本的视图层,桥接了选区、光标、和 DOM 渲染能力
@textbus/collaborate 协作支持模块,提供了基于 Yjs 的协作对接能力
@textbus/adapter-viewfly Textbus 视图渲染 Viewlfy 适配器,可使用 Viewfly 渲染富文本内容
@textbus/adapter-vue Textbus 视图渲染 vue 适配器,可使用 vue 渲染富文本内容
@textbus/adapter-react Textbus 视图渲染 react 适配器,可使用 react 渲染富文本内容
@textbus/platform-node 适用于 node 后台运行的 Textbus 的实用工具集

本地开发

Textbus 采用 pnpm 作为多模块管理,全局安装 pnpm。

npm install pnpm -g

克隆 Textbus 仓库,并安装依赖。

git clone [email protected]:textbus/textbus.git
cd textbus
pnpm install

启动开发环境。

npm start

赞助

Textbus 的成长离不开社会的支持,如果 Textbus 为你带来了帮助,并且你也认同为知识付费,同时鼓励我们做的更好,欢迎通过下面的二维码表达你的支持

textbus's People

Contributors

faxinwang avatar r4ggj avatar tbhuabi avatar textbus avatar tinycricetus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

textbus's Issues

Vue 项目切换路由页面后无法编辑内容

使用版本:"@tanbo/textbus": "^1.0.0-alpha.5",
操作步骤:

  • 打开编辑器页面
  • 切换到其它页面(不是a标签跳转,而且vue 路由切换)
  • 在进入到编辑器页面(vue路由切换)
    编辑器内容无法编辑,但是图片大小可以调整

直接引用js, 定制toolbar时出错

var editor = textbus.createEditor(document.getElementById('editor'),{ toolbar:[ ['historyBackTool', 'historyForwardTool'], ['insertObjectTool'], ['headingTool'], ['boldTool', 'italicTool', 'strikeThroughTool', 'underlineTool'], ['olTool', 'ulTool'], ['fontSizeTool', 'textIndentTool','textAlignTool'], ['colorTool', 'textBackgroundTool'], ['linkTool', 'unlinkTool'], ['imageTool','emojiTool'], ['tableTool'], ['findTool'], ['cleanTool'] ] });

报错:
Uncaught [TextBusError: Tool]: tool type is not supported. at t.createHandler (http://www.test7.com/static/textbus/textbus.min.js:24:176580) at http://www.test7.com/static/textbus/textbus.min.js:24:175753 at Array.map (<anonymous>) at t.createHandlers (http://www.test7.com/static/textbus/textbus.min.js:24:175727) at http://www.test7.com/static/textbus/textbus.min.js:24:175488 at Array.forEach (<anonymous>) at t.createToolbar (http://www.test7.com/static/textbus/textbus.min.js:24:175370) at new t (http://www.test7.com/static/textbus/textbus.min.js:24:172564) at http://www.test7.com/static/textbus/textbus.min.js:1:12754

卡片组件bug:当编辑区域卡片组件位于文档开头时,Ctrl+A 无法选中编辑区域全部内容,并报 textbus.min.js:24 Uncaught TypeError: Cannot read property 'getContentAtIndex' of undefined 错误

操作环境

  • textbus 版本: 公测版 0.1.0-alpha.5
  • 组件及版本 (如果是组件相关问题): 卡片组件
  • 浏览器及运行版本: XXX

[NOTE: 如果你正在使用旧版本 textbus,建议升级到最新版本,可能在新版本中已经解决了这个问题 ]

期望行为

可正常选择编辑区域全部内容

当前行为

当编辑区域卡片组件位于文档开头时,Ctrl+A 无法选中编辑区域全部内容,并报 textbus.min.js:24 Uncaught TypeError: Cannot read property 'getContentAtIndex' of undefined 错误

image

可复现问题的操作步骤

[NOTE: 请提供最小化可复现问题的代码片段,这将会对定位与排查问题 非常 有帮助 ]

  1. 清空编辑区域的文本内容
  2. 从右侧组件区域选择卡片组件。此时卡片组件将呈现在编辑区域
  3. 激活编辑区域,在键盘上按 Ctrl+A

日志

请将错误日志粘贴在下方。点击前面的三角号可展开/折叠日志信息

Uncaught TypeError: Cannot read property 'getContentAtIndex' of undefined
    at t.findFirstPosition (textbus.min.js:24)
    at t.findFirstPosition (textbus.min.js:24)
    at t.selectAll (textbus.min.js:24)
    at Object.action (textbus.min.js:24)
    at e._next (textbus.min.js:24)
    at e.__tryOrUnsub (textbus.min.js:16)
    at e.next (textbus.min.js:16)
    at e._next (textbus.min.js:16)
    at e.next (textbus.min.js:16)
    at e._next (textbus.min.js:55)

toolbar无法显示文本

package版本是 "@textbus/textbus": "^1.1.4",
QQ截图20211221145106

使用示例如下

import {
  Editor,
  EditorOptions,
  createEditor,
  ListComponent, // ul、ol 列表组件
  BlockComponent, // 支持 div,p,h1,h2,h3,h4,h5,h6,blockquote,article,section,nav,header,footer 的块级元素组件
  PreComponent, // 代码块组件
  AudioComponent, // 音频组件
  VideoComponent, // 视频组件
  ImageComponent, // 图片组件
  TableComponent, // 表格组件
  AlertComponent,
  KatexComponent,
  StepComponent,
  ProgressComponent,
  TimelineComponent,
  WordExplainComponent,
  JumbotronComponent,
  BaiduMapComponent,
  TodoListComponent,
  ImageCardComponent,
  fontFamilyFormatter, // 字体
  boldFormatter, // 加粗
  linkFormatter, // 超链接
  backgroundColorFormatter, // 文字背景颜色
  blockBackgroundColorFormatter, // 块背景颜色
  codeFormatter, // 行内代码
  colorFormatter, // 字体颜色
  fontSizeFormatter, // 字体大小
  italicFormatter, // 斜体
  letterSpacingFormatter, // 文字间距
  lineHeightFormatter, // 行高
  strikeThroughFormatter, // 中划线
  subscriptFormatter, // 上角标
  superscriptFormatter, // 下角标
  textAlignFormatter, // 文字对齐方式
  textIndentFormatter, // 首行缩进
  underlineFormatter, // 下划线
  dirFormatter, // 内容排版方向
  tdBorderColorFormatter, // 表格边框颜色
  Toolbar,
  TOOLS,
  historyBackTool,
  historyForwardTool,
  insertObjectTool,
  headingTool,
  boldTool,
  italicTool,
  strikeThroughTool,
  underlineTool,
  olTool,
  ulTool,
  fontSizeTool,
  textIndentTool,
  colorTool,
  textBackgroundTool,
  insertParagraphBeforeTool,
  insertParagraphAfterTool,
  fontFamilyTool,
  linkTool,
  unlinkTool,
  imageTool,
  textAlignTool,
  tableTool,
  findTool,
  cleanTool,
  ComponentLibraryPlugin,
  ContextmenuPlugin,
  PasteUploadEmitterPlugin,
  GuardEndBlockPlugin,
  OutlinesPlugin,
  ImageAndVideoDragResizePlugin, // 图片视频拖拽缩放插件
  LinkJumpTipPlugin, // 超链接点击弹出跳转 tip 插件
  TableEditEnhancePlugin, // 表格框选编辑支持插件
  SourcecodeModePlugin, // 源代码编辑模式插件
  imageCardComponentExample,
  todoListComponentExample,
  baiduMapComponentExample,
  jumbotronComponentExample,
  wordExplainComponentExample,
  katexComponentExample,
  timelineComponentExample,
  stepsComponentExample,
  progressComponentExample,
  alertComponentExample,
  COMPONENT_CREATORS,
  i18n_zh_CN,
} from "@textbus/textbus"
import "@textbus/textbus/bundles/textbus.min.css"

const Demo = () => {
  useEffect(() => {
    const options: EditorOptions = {
      theme: "dark", // 可选 'dark' | 'mac-os' | 'mac-os-dark',不传即为默认样式
      i18n: i18n_zh_CN,
      contents: "<p>欢迎你使用 <strong>TextBus 富文本编辑器!</strong></p>",
      providers: [
        {
          provide: TOOLS,
          useValue: [
            [historyBackTool, historyForwardTool],
            [insertObjectTool],
            [headingTool],
            [boldTool, italicTool, strikeThroughTool, underlineTool],
            [olTool, ulTool],
            [fontSizeTool, textIndentTool],
            [colorTool, textBackgroundTool],
            [insertParagraphBeforeTool, insertParagraphAfterTool],
            [fontFamilyTool],
            [linkTool, unlinkTool],
            [imageTool],
            [textAlignTool],
            [tableTool],
            [findTool],
            [cleanTool]
          ]
        }
      ],
      plugins: [
        Toolbar,
      ],
      components: [
        ListComponent, // ul、ol 列表组件
        BlockComponent, // 支持 div,p,h1,h2,h3,h4,h5,h6,blockquote,article,section,nav,header,footer 的块级元素组件
        PreComponent, // 代码块组件
        AudioComponent, // 音频组件
        VideoComponent, // 视频组件
        ImageComponent, // 图片组件
        TableComponent  // 表格组件
      ],
      formatters: [
        fontFamilyFormatter, // 字体
        boldFormatter, // 加粗
        linkFormatter, // 超链接
        backgroundColorFormatter, // 文字背景颜色
        blockBackgroundColorFormatter, // 块背景颜色
        codeFormatter, // 行内代码
        colorFormatter, // 字体颜色
        fontSizeFormatter, // 字体大小
        italicFormatter, // 斜体
        letterSpacingFormatter, // 文字间距
        lineHeightFormatter, // 行高
        strikeThroughFormatter, // 中划线
        subscriptFormatter, // 上角标
        superscriptFormatter, // 下角标
        textAlignFormatter, // 文字对齐方式
        textIndentFormatter, // 首行缩进
        underlineFormatter, // 下划线
        dirFormatter, // 内容排版方向
        tdBorderColorFormatter // 表格边框颜色
      ]
    }
    // @ts-ignore
    const editor = new Editor(document.getElementById("editor"), options)

    editor.onChange.subscribe(() => {
      console.log(editor.getContents())
    })
  }, [])

  return <div style={{ width: 1000 }} id="editor" />
}

文档错误 https://textbus.tanboui.com/

使用版本:"@tanbo/textbus": "^1.0.0-alpha.4"

网站首页文档:const {contents, styleSheets} = editor.getContents();

经过测试应为:const {content, styleSheets} = editor.getContents();

image

【bug】文档为空内容的时候把默认的p标签也删掉之后点击生成有序列表页面报错

具体操作:一直点击退格键 再点击列表
具体报错信息
hostReportError.js?0ca4:3 Uncaught TypeError: Cannot read property 'indexOf' of null at eval (list.commander.js?5cf2:85) at Array.forEach (<anonymous>) at ListCommander.command (list.commander.js?5cf2:10) at SafeSubscriber.eval [as _next] (toolbar.js?856e:132) at SafeSubscriber.__tryOrUnsub (Subscriber.js?1453:192) at SafeSubscriber.next (Subscriber.js?1453:130) at Subscriber._next (Subscriber.js?1453:76) at Subscriber.next (Subscriber.js?1453:53) at Subject.next (Subject.js?2bd2:47) at Object.onChecked (button-tool.js?b84e:14)

关于组件库中有弹框交互的组件,点击“取消”按钮,控制台提示报错的情况讨论

复现步骤

  1. 点击有预先弹窗的组件(如百度地图)

image

  1. 点击弹窗内的取消按钮

image

  1. 看控制台,提示报错

image

版本

当前的 master 和 develop c37fe7a

分析

以百度地图组件为例

  1. src\lib\lib\additional-components\baidu-map.component.ts 文件下 L109-113 ,在关闭弹窗时会执行 reject()
    image

  2. src\lib\lib\workbench\component-stage.ts 文件下 L40,有一个 addExample 方法,这个方法在 src\lib\lib\workbench\component-stage.ts 下 L158-160 Editor 的构造函数下,每个组件都会执行这个方法,大概是初始化(?)

  3. addExample 方法下,有一段绑定点击事件的代码,其中 L46-49 这里只有 then 的拦截,reject 未作处理直接抛出。由于我不知道的原因,生产环境这个错误很难去跟踪

image

image

提问

  1. 查看类似的弹框组件,如 element-ui 、antd 等,均有点击确定 resolve,点击取消 reject 的设计。咱们这个也是同样的设计,这种设计的初衷是什么?

  2. 因为咱们弹框组件的 reject 没有被用户管理,因此有必要区分点击取消按钮的 reject 和组件内部错误的 reject 吗?点击取消按钮是操作正常流程,应该不需要抛出错误吧?

视频自动播放属性问题

视频上传的模块,有一个选择是否自动播放的选项,实际上是无效的,在web上只要有 autoplay 属性就会自动播放,所以源码中写法

render() {
    return (VElement.createElement("video", { src: state.src, ref: ref, autoPlay: state.autoplay, controls: state.controls, style: {
            width: state.width,
            height: state.height
        } }));
}

可以改成

render() {
    let properties = {
      src: state.src,
      ref: ref,
      controls: state.controls,
      style: {
        width: state.width,
        height: state.height,
      },
    }
    if (state.autoplay) {
      properties['autoplay'] = state.autoplay
    }
    return VElement.createElement('video', properties)
 },

工具条面板失焦无法关闭的问题

问题描述:
当工具条的面板打开时,点击内容输入区域,面板无法关闭,比如 链接 的面板,打开之后,点击工具条的空白区域,可以关闭,但是点击内容输入区域则无法关闭。

问题描述图片:
image

期望结果:
希望在点击内容输入区域时,关闭已经打开的面板

看起来很棒! 没有MIT或者类似授权码?

试了一下官网的demo, 功能似乎很全, 而且组件扩展功能似乎很强, 感谢作者的贡献.
问一下授权问题, 没有MIT或者类似的协议吗? 想要商用有何选项? 谢谢.

光标指向对图片有异常

鼠标只有在图片右方点击,光标才会指向图片后面
微信截图_20210719152352
而右上方与右下方都是指向文字后面
微信截图_20210719152424

而且我希望图片可以设置vertical-align 属性设置元素的垂直对齐方式,不然图片与文字对齐蛮奇怪的。

Vue 项目中使用,在源码编辑模式与切换富文本编辑模式切换2次出现错误

使用版本:"@tanbo/textbus": "^1.0.0-alpha.5",

错误提示:

Uncaught TypeError: Cannot read property 'unsubscribe' of undefined
    at eval (fragment.js?219a:382)
    at Array.forEach (<anonymous>)
    at Fragment.cut (fragment.js?219a:379)
    at Fragment.remove (fragment.js?219a:303)
    at Fragment.gourdComponentInSelf (fragment.js?219a:533)
    at Fragment.append (fragment.js?219a:138)
    at SafeSubscriber.eval (viewer.js?ce57:186)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js?54c0:192)
    at SafeSubscriber.next (Subscriber.js?54c0:130)
    at Subscriber._next (Subscriber.js?54c0:76)

官网上的demo也有类似问题。
出现错误后模式并未改变,同时无法在这两种模式间切换~

是否可以支持ol、ul相互嵌套?

现有需求,ol里面需要嵌套ul,或者 ul 里 嵌套 ol,目前好像不支持这种嵌套编辑。

比如 dom 结构如下:

<ul>
  <li>
    <ol>
      <li></li>
      <li></li>
    </ol>
  </li>
  <li></li>
</ul>

关于 setContents 的问题

影响版本

公测版 0.1.0-alpha.6

复现步骤

  1. 当调用 editor.setContents() 时,编辑区域会变成 undefined。

image

此时再次调用 editor.getContents() 时,返回值为

{
  "styleSheets": [此处内容与问题描述无关],
  "content": "undefined<p><br></p>"
}
  1. 调用 setContents() 方法之后,Ctrl+A 选中编辑区域全部内容,之后按 Delete 键,此时光标会在第二行。按一次上方向键,再按一次下方向键。会报如下错误:
textbus.min.js:24 Uncaught TypeError: Cannot read property 'getContext' of undefined

之后再按一次上方向按键,会报如下错误:

textbus.min.js:24 Uncaught Error: DOM 与虚拟节点不同步!

此时屏幕光标闪动,但无法输入内容。当编辑区域失去焦点后,无法再次获得焦点。

演示

** 请点击图片查看演示详情。由于录屏生成 gif 设置成了只播放一次,因此可能看到的是播放完成不动的画面 **

1

打包出来css太大了吧

dist/js/@textbus/core-093b6ebe.js                 97.56 kB
dist/js/@textbus/editor-1abc8627.js              528.86 kB
dist/css/edit-d1bbbc84.css                     1,634.12 kB

这个大小是认真得吗 @textbus 或者说是我姿势不对?

主页演示文档调整图片出错

只是演示文档下面的TextBus 官方群 二维码的图片,选中调整大小后,再次试图选中此图片,失败,此时编辑器变为不可编辑状态, 看console,报错:
polyfills.f78505eef49665b68f41.js:1 Uncaught TypeError: Cannot read property 'fragment' of undefined at e.getOffset (app.f78505eef49665b68f41.js:1) at new e (app.f78505eef49665b68f41.js:1) at new e (app.f78505eef49665b68f41.js:1) at t._tapNext (app.f78505eef49665b68f41.js:1) at t._next (app.f78505eef49665b68f41.js:1) at t.next (app.f78505eef49665b68f41.js:1) at HTMLDocument.<anonymous> (app.f78505eef49665b68f41.js:1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.