0.1.4 • Published 1 year ago

tiptap-vue v0.1.4

Weekly downloads
-
License
MIT
Repository
-
Last release
1 year ago

tiptap-vue

一个基于tiptap2+vue3封装的富文本编辑器

Install

为了拥有更强的拓展能力,已将tiptap2的核心依赖独立出去,因此你在安装tiptap-vue时,需要同时安装tiptap2的依赖。

pnpm i @tiptap/pm @tiptap/core @tiptap/vue-3 @tiptap/suggestion tiptap-vue

Usage

全局安装使用

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import Tiptap from 'tiptap-vue'
import "tiptap-vue/dist/style.css"
import 'tiptap-vue/dist/style/icon/iconfont.css'

const app = createApp(App)
app.use(Tiptap)
app.mount('#app')

或者 单独使用

组件内单独引入

<script lang="ts" setup>

import { ref } from "vue";
import { Tiptap } from "tiptap-vue";
import "tiptap-vue/dist/style.css";
import 'tiptap-vue/dist/style/icon/iconfont.css'

const content = ref("");

</script>

最后使用组件

<template>
  <Tiptap v-model="content"/>
</template>

自定义主题

默认是不引入主题样式的,因此你需要自己引入主题样式或者根据主题css变量自定义主题样式, 内置了3个主题,分别是prose-theme、prose-element、prose-arco

// default theme
import "tiptap-vue/dist/style/prose-theme.scss";
// element-ui theme
import "tiptap-vue/dist/style/prose-element.scss";
// arco-ui theme
import "tiptap-vue/dist/style/prose-arco.scss";

同时需要在你的Tiptap组件上添加theme属性,值为你引入的主题样式的类名

<Tiptap v-model="content" editable theme="prose-element"/>

Props

参数说明类型默认值
v-model编辑器内容双向绑定string-
theme主题stringprose-theme
extensions编辑器插件配置--
autofocus是否自动聚焦boolean \'start' \'end' \'all' \numberfalse
editable是否可编辑booleanfalse
editorPropstiptap文档 prosemirror文档object-
parseOptionsparseOptions--
output输出格式'html' \'json' \'text'html
injectCSSinjectCSSbooleantrue
contentClass内部容器样式string-
footerClass页脚样式string-

v-model

Type: string

编辑器向绑定的内容。

theme

Type: string

Default: prose-theme

主题样式设置。

<Tiptap v-model="content" theme="prose-element"/>

内置了3个主题,分别是 prose-theme prose-element prose-arco

// default theme
import "tiptap-vue/dist/style/prose-theme.scss";
// element-ui theme
import "tiptap-vue/dist/style/prose-element.scss";
// arco-ui theme
import "tiptap-vue/dist/style/prose-arco.scss";

编辑器内部的颜色、边框、圆角等大部分通过css变量调用,默认不包含任何样式文件,请根据需求自行引入或者自定义。

extensions

所有拓展

罗列出目前使用的所有拓展,如果你不想自定义拓展,可以直接使用defaultKit套件,它包含了所有拓展,无需一个个单独引入。

如果你还是坚持自定义拓展,那么你可以参考下面的拓展列表,自行选择需要的拓展。

Required 必须安装的拓展,否则编辑器无法正常运行

Document

Text

Paragraph

marks

Bold

Code

Italic

Strike

Underline

Link

Highlight

Color

Superscript

Subscript

nodes

Heading

Blockquote

BulletList

OrderedList

HorizontalRule

ListItem

TaskItem

TaskList

CodeBlock

Table, TableCell, TableHeader, TableRow

Image

TableOfContents

Functionality

Placeholder

Dropcursor

Gapcursor

History

HardBreak

Typography

TextAlign

TextStyle

FocusClasses

TrailingNode

配置拓展

可以配置大多数扩展。添加一个对象并向其传递一个对象。.configure()

我们已经将以上所有的拓展都封装成了套件defaultKit,你可以直接使用。当你的组件props未设置extensions时,编辑器会自动使用defaultKit

我们强烈建议直接使用defaultKit套件。

  • 它包含了所有的拓展,无需一个个单独引入。
  • 它支持对单个拓展进行禁用或者配置。
  • 目前的气泡菜单和/斜杆菜单内置了许多拓展功能,并未做按需自动展示,如果未引入菜单中的功能拓展,将会导致菜单部分功能无法正常使用。

示例:

<Tiptap v-model="content" :extensions:"extensions" />
<script lang="ts" setup>

import {
  Tiptap,
  defaultKit, // 引入默认套件
} from "tiptap-vue";


const extensions = {

  defaultKit.configure({
    // 修改一个拓展的配置
    Blockquote: {
      HTMLAttributes: {
        class: "blockquote",
      },
    },

  })
}

</script>

你也可以禁用其中一个拓展,设置值为false即可。

示例:

<Tiptap v-model="content" :extensions:"extensions" />
<script lang="ts" setup>

import {
  Tiptap,
  defaultKit, // 引入默认套件
  TaskItem, // 单独引入某个拓展
} from "tiptap-vue";


const extensions = {

  // 禁用其中一个拓展,设置值为false即可
  defaultKit.configure({
    TaskItem: false,
  }),

  // 单独引入某个拓展进行配置,或者二次封装自己的拓展再引入。
  TaskItem.configure({
    HTMLAttributes: {
      class: "task-item",
    },
  }),
}

</script>

autofocus

Type: boolean number 'start' 'end' 'all'

Default: false

编辑器创建时是否自动聚焦。

示例:

<Tiptap v-model="content" autofocus />

editable

Type: boolean

Default: true

编辑器是否可编辑。

示例:

<Tiptap v-model="content" editable />

editorProps

Type: object

Default: undefined

编辑器props设置,功能非常强大,详见tiptap文档prosemirror文档

示例:

<Tiptap v-model="content" :editorProps="editorProps"/>
<script lang="ts" setup>

// ...

// 设置是否开启编辑器的拼写检查

const editorProps = {
  attributes: {
    spellcheck: false,
  },
}

</script>

Events

tiptap文档

编辑器生命周期钩子

<template>
  <Tiptap v-model="content" editable @onCreate="onCreate"/>
</template>

<script lang="ts" setup>

onCreate({ editor }) {
  // console.log(editor)
}

</script>

所有钩子:

onBeforeCreate onCreate onSelectionUpdate onTransaction onFocus onBlur onUpdate onDestroy

Methods

图片拓展方法

图片上传是比较复杂的拓展。

  • 目前支持复制粘贴上传(同时支持粘贴svg代码上传)、粘贴图片链接上传、拖拽上传、/斜杆菜单上传。
  • 如果未配置图片上传方法,默认插入到编辑器的图片将会是base64格式的图片。/斜杆菜单上传会失效。
  • 若希望插入到编辑器中的是网络图片地址,目前只能使用markdown格式的图片链接。

图片上传

一、onUpload?: (image: File | string) => Promise<attrs>

复制复制粘贴、拖拽上传。参数可能是个file对象也可能是一个url图片地址,上传时需要判断类型。

attrs返回一个对象,必须包含srcwidthheight三个属性。可以携带更多的属性,如alttitle等。

二、onCommandUpload?: () => Promise<attrs>

/斜杆菜单上传图片,需要自行处理打开文件选择框的逻辑

图片删除

onDelete?:(attrs) => void,

删除图片时会触发该方法。参数会自动接收到img属性,根据需求进行进一步逻辑处理,例如:从服务器删除图片。

图片属性解析

onParseSrc?: (src:string) => string

大多时候我们只需通过设置HTMLAttributes就可以自定义拓展的属性。但在Image拓展中有时候你可能希望更细粒度的去处理图片的src地址,就可以使用该方法。

该方法参数会接收到图片的src,最后需要return回处理之后的src值,当你希望解析和存储的src地址不需要一致时应该用的到!

方法示例

<Tiptap v-model="content" :extensions:"extensions" />
<script lang="ts" setup>

import {
  Tiptap,
  defaultKit
} from "tiptap-vue";


const extensions = {

  // 在defaultKit套件中引入Image拓展配置上传功能
  defaultKit.configure({
    Image: {
      // 复制粘贴、拖拽上传
      onUpload: (file) => {
        return new Promise((resolve, reject) => {
          // 会自动接收到图片的file对象、svg代码或者网络图片链接,你可以在这里处理上传业务
          // ...
          // 最后需要resolve上传后的图片Promise对象,包含src、width、height三个属性
          resolve({
            src: "https://img.yzcdn.cn/vant/cat.jpeg",
            width: 100,
            height: 100,
          })
        });
      },

      // /斜杆菜单上传
      onCommandUpload: () => {
        return new Promise((resolve, reject) => {
          // 需要处理打开文件选择框的逻辑
          // ...
          // 最后需要resolve上传后的图片Promise对象,必须包含src、width、height三个属性
          resolve({
            src: "https://img.yzcdn.cn/vant/cat.jpeg",
            width: 100,
            height: 100,
            // more...
          })
        });
      },

      // 删除图片事件(当点击删除图片时触发)
      onDelete: (attrs) => {
        // 会接收到图片的所有属性,你可以在这里处理更多的删除业务
        // ...
      },

      // 细粒度处理图片src解析
      onParseSrc:(src) => {
        cosnt suffix = src.split('.')[src.length -1]
        if(suffix === 'jpg'){
          // ...进行逻辑处理
          rerurn ...
        }

        return src
      }
    },
  }),

}

</script>

License

MIT