tiptap text editor on vuejs and vuetify
npm install vuetify-pro-tiptap一个 Vue.js 的基于 tiptap 和 vuetify 的 「所见即所得」 富文本编辑器




!LICENSE


English | 中文
👉https://yikoyu.github.io/vuetify-pro-tiptap/develop/
en, zhHans, nl, tr, de, fr, it, pt, hu)shell
pnpm add vuetify-pro-tiptap
或者
yarn add vuetify-pro-tiptap
或者
npm i vuetify-pro-tiptap -S
`$3
tiptap.ts
`TypeScript
import { markRaw } from 'vue'
import { VuetifyTiptap, VuetifyViewer, createVuetifyProTipTap } from 'vuetify-pro-tiptap'
import { BaseKit, Bold, Italic, Underline, Strike, Color, Highlight, Heading, TextAlign, FontFamily, FontSize, SubAndSuperScript, BulletList, OrderedList, TaskList, Indent, Link, Image, Video, Table, Blockquote, HorizontalRule, Code, CodeBlock, Clear, Fullscreen, History } from 'vuetify-pro-tiptap'
import 'vuetify-pro-tiptap/style.css'
import SelectImage from './components/SelectImage.vue'export const vuetifyProTipTap = createVuetifyProTipTap({
lang: 'zhHans',
fallbackLang: 'en',
components: {
VuetifyTiptap,
VuetifyViewer
},
extensions: [
BaseKit.configure({
placeholder: {
placeholder: 'Enter some text...'
}
}),
Bold,
Italic,
Underline,
Strike,
Code.configure({ divider: true }),
Heading,
TextAlign,
FontFamily,
FontSize,
Color,
Highlight.configure({ divider: true }),
SubAndSuperScript.configure({ divider: true }),
Clear.configure({ divider: true }),
BulletList,
OrderedList,
TaskList,
Indent.configure({ divider: true }),
Link,
Image.configure({
imageTabs: [{ name: 'SELECT', component: markRaw(SelectImage) }],
// hiddenTabs: ['upload'],
upload(file: File) {
const url = URL.createObjectURL(file)
console.log('mock upload api :>> ', url)
return Promise.resolve(url)
}
}),
Video,
Table.configure({ divider: true }),
Blockquote,
HorizontalRule,
CodeBlock.configure({ divider: true }),
History.configure({ divider: true }),
Fullscreen
]
})
`
main.ts
`typescript
import { createApp } from 'vue'
import { createVuetify } from 'vuetify'
import App from './App.vue'
import { vuetifyProTipTap } from './tiptap'import 'vuetify/styles'
const vuetify = createVuetify()
const app = createApp(App)
app.use(vuetify)
app.use(vuetifyProTipTap)
// fix warning injected property "decorationClasses" is a ref and will be auto-unwrapped
// https://github.com/ueberdosis/tiptap/issues/1719
app.config.unwrapInjectedRef = true
app.mount('#app')
`全局设置
`TypeScript
import { markRaw } from 'vue'
import { VuetifyTiptap, VuetifyViewer, createVuetifyProTipTap, defaultBubbleList } from 'vuetify-pro-tiptap'
import { BaseKit, Image, Fullscreen } from 'vuetify-pro-tiptap'
import 'vuetify-pro-tiptap/style.css'
import SelectImage from './components/SelectImage.vue'export const vuetifyProTipTap = createVuetifyProTipTap({
// Set default lang
lang: 'zhHans',
// Set default fallback lang
fallbackLang: 'en',
// Set markdown theme
markdownTheme: 'github',
// Global registration app.component
components: {
VuetifyTiptap,
VuetifyViewer
},
// Global registration extensions
extensions: [
BaseKit.configure({
placeholder: {
placeholder: 'Enter some text...'
},
bubble: {
// default config
list: {
image: [ 'float-left', 'float-none', 'float-right', 'divider', 'size-small', 'size-medium', 'size-large', 'divider', 'textAlign', 'divider', 'image', 'image-aspect-ratio', 'remove'],
text: ['bold', 'italic', 'underline', 'strike', 'divider', 'color', 'highlight', 'textAlign', 'divider', 'link'],
video: ['video', 'remove']
},
defaultBubbleList: editor => {
// You can customize the bubble menu here
return defaultBubbleList(editor) // default customize bubble list
}
}
}),
Image.configure({
// Generate a VDivider after the button
divider: true,
// Custom image tabs
imageTabs: [{ name: 'SELECT', component: markRaw(SelectImage) }],
// hidden default tab
hiddenTabs: ['upload'],
// custom upload function
upload(file) {
const url = URL.createObjectURL(file)
console.log('mock upload api :>> ', url)
return Promise.resolve(url)
}
}),
Fullscreen.configure({
// Generate a VSpacer after the button
spacer: true
})
]
})
`Extensions
你可以只使用需要的 extension,对应的菜单按钮将会按照你声明的顺序被添加。
所有可用的 extensions:
BaseKit
- Bold
- Italic
- Underline
- Strike
- Color
- Highlight
- Heading
- TextAlign
- FontFamily
- FontSize
- SubAndSuperScript
- BulletList
- OrderedList
- TaskList
- Indent
- Link
- MarkdownTheme
- Image
- Video
- Table
- Blockquote
- HorizontalRule
- Code
- CodeBlock
- Clear
- Fullscreen
- History自定义主题
创建 github.scss
`scss
$value: 'github';.vuetify-pro-tiptap-editor__content.markdown-theme-#{$value} {
&.__dark {
// your dark mode custom styles
}
.tiptap.ProseMirror,
.content {
// your custom styles
}
}
`在 ts 中导入 github.scss
`typescript
// import 'vuetify-pro-tiptap/style.css' // 导入全部(editor 和 markdown)样式
import 'vuetify-pro-tiptap/styles/editor.css' // 只使用 editor 样式,不使用 markdown 样式
import './styles/markdown/github.scss'
`在组件中使用
`vue
`自定义 extension
PreviewActionButton.vue
`vue
{{
svg:${mdiFileCodeOutline} }}
{{ svg:${mdiClose} }}
`
preview.ts
`typescript
import type { GeneralOptions } from 'vuetify-pro-tiptap'
import { Extension } from '@tiptap/core'import PreviewActionButton from '../components/PreviewActionButton.vue'
export type PreviewOptions = GeneralOptions
export default Extension.create({
name: 'preview',
addOptions() {
return {
divider: false,
spacer: false,
button: ({ editor }) => ({
component: PreviewActionButton,
componentProps: {
editor,
},
}),
}
},
})
`国际化
$3
你可以在安装插件的时候声明
`TypeScript
import { createVuetifyProTipTap } from 'vuetify-pro-tiptap'const VuetifyProTipTap = createVuetifyProTipTap({
lang: 'zhHans',
fallbackLang: 'en'
})
`
或者调用方法动态修改
`TypeScript
import { locale } from 'vuetify-pro-tiptap'locale.setLang('en')
`
可用的语言:
- en (默认)
- zhHans
- nl
- tr
- de
- fr
- it
- pt
- hu$3
当前语言暂未提供时,可以使用 setMessage 进行设置
`TypeScript
import { locale } from 'vuetify-pro-tiptap'locale.setMessage('zhHant', {
// 国际化文本
})
locale.setLang('zhHant')
`用法
`vue
`Props
$3
#### Props
| 名称 | 类型 | 默认值 | 说明 |
| -------------------- | ------------------------------------------ | --------- | ---------------------------- |
| modelValue | string | '' | 输入的值 |
| markdownTheme | string \| false | 'default' | markdown主题 |
| output | 'html' \| 'json' \| 'text' | 'html' | 输出格式 |
| dark | boolean | false | 是否为深色主题 |
| dense | boolean | false | 是否为紧凑模式 |
| outlined | boolean | true | 将轮廓样式应用于输入 |
| flat | boolean | true | 移除卡片的 elevation |
| disabled | boolean | false | 禁用输入 |
| label | string | undefined | 设置输入标签 |
| hideToolbar | boolean | false | 隐藏工具栏 |
| disableToolbar | boolean | false | 禁用工具栏 |
| hideBubble | boolean | false | 隐藏气泡菜单 |
| removeDefaultWrapper | boolean | false | 删除编辑器为空时默认的包装器 |
| maxWidth | string \| number | undefined | 输入框最大宽度 |
| minHeight | string \| number | undefined | 输入框最小高度 |
| maxHeight | string \| number | undefined | 输入框最大高度 |
| extensions | AnyExtension[] | [] | tiptap插件 |
| editorClass | string \| string[] \| Record\ | undefined | 编辑器class |
#### Slots
| 名称 | 说明 |
| ------ | ---------------------- |
| editor | 自定义编辑器的插槽 |
| bottom | 自定义编辑器底部的插槽 |
#### Event
| 名称 | 类型 | 说明 |
| -------------------- | ------------------------------------------------- | ------------------------ |
| update:modelValue | string \| JSONContent | 编辑器 onUpdate 时处触发 |
| update:markdownTheme | string | 切换主题时触发 |
| change | { editor: Editor, output: string \| JSONContent } | 编辑器 onUpdate 时处触发 |
| enter | | 键盘输入回车时触发 |
$3
#### Props
| 名称 | 类型 | 默认值 | 说明 |
| ------------- | --------------------- | ------------ | --------------- |
| value | string \| JSONContent | '' | 预览的值 |
| dark | boolean | false | 是否为深色主题 |
| dense | boolean | false | 是否为紧凑模式 |
| markdownTheme | string \| false | 'default' | markdown主题 |
| xss | boolean | true | 是否开启xss过滤 |
| xssOptions | xss.IWhiteList | 内置默认规则 | xss过滤规则配置 |
| maxWidth | string \| number | undefined | 预览最大宽度 |
| extensions | AnyExtension[] | [] | tiptap插件 |
#### Slots
| 名称 | 说明 |
| ------ | -------------- |
| before | 在顶部添加内容 |
| after | 在底部添加内容 |
🏗 贡献代码
1. 🍴Fork it
2. 🔀Create your branch:
git checkout -b your-branch
3. 🎨Make your changes
4. 📝Commit your changes with Semantic Commit Messages (recommended)
5. 🚀Push to the branch: git push origin your-branch
6. 🎉Submit a PR to develop` branch