@mario9/tiptap-editor 0.2.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @mario9/tiptap-editor
2
2
 
3
- 基于 Tiptap + Vue 3 的富文本编辑器组件。
3
+ 基于 Tiptap + Vue 3 的富文本编辑器组件,支持 Feature Plugin 架构,消费方可按需引入功能模块实现 tree-shaking。
4
4
 
5
5
  ## 安装
6
6
 
@@ -16,17 +16,44 @@ pnpm add vue element-plus katex lowlight @tiptap/core @tiptap/starter-kit @tipta
16
16
 
17
17
  ## 快速开始
18
18
 
19
+ 不传 `features` 时编辑器只有基础输入能力(无工具栏)。通过 `:features` 按需组合功能:
20
+
19
21
  ```vue
20
22
  <script setup lang="ts">
21
23
  import { ref } from 'vue'
22
- import { TiptapEditor } from '@mario9/tiptap-editor'
24
+ import {
25
+ TiptapEditor,
26
+ UndoRedoFeature,
27
+ TextStyleFeature,
28
+ TextAlignFeature,
29
+ ListFeature,
30
+ CodeBlockFeature,
31
+ TableFeature,
32
+ MathFeature,
33
+ ImageFeature,
34
+ SeparatorFeature,
35
+ } from '@mario9/tiptap-editor'
23
36
  import '@mario9/tiptap-editor/tiptap-editor.css'
24
37
 
25
38
  const content = ref('')
26
39
  </script>
27
40
 
28
41
  <template>
29
- <TiptapEditor v-model="content" placeholder="请输入内容..." />
42
+ <TiptapEditor
43
+ v-model="content"
44
+ :features="[
45
+ UndoRedoFeature,
46
+ TextStyleFeature,
47
+ SeparatorFeature,
48
+ TextAlignFeature,
49
+ ListFeature,
50
+ CodeBlockFeature,
51
+ SeparatorFeature,
52
+ TableFeature,
53
+ MathFeature,
54
+ ImageFeature,
55
+ ]"
56
+ />
30
57
  </template>
31
58
  ```
32
59
 
@@ -36,52 +63,78 @@ const content = ref('')
36
63
  |------|------|--------|------|
37
64
  | `modelValue` | `string` | `''` | 编辑器内容(HTML 格式),支持 `v-model` 双向绑定 |
38
65
  | `placeholder` | `string` | `'请输入内容...'` | 编辑器占位符文本 |
39
- | `upload` | `(file: File) => Promise<string>` | Base64 转换 | 图片上传函数,返回图片 URL |
40
- | `readonly` | `boolean` | `false` | 只读模式:隐藏工具栏,禁止编辑,图片控件仅保留下载,表格控件隐藏,数学公式不可编辑 |
66
+ | `upload` | `(file: File) => Promise<string>` | `undefined` | 图片上传函数,传给 `ImageFeature` 使用,不传则默认转为 Base64 |
67
+ | `features` | `FeaturePlugin[]` | `[]` | 功能插件列表,决定工具栏内容和注册的扩展 |
68
+
69
+ ## Feature Plugins
41
70
 
42
- ## 自定义图片上传
71
+ | 导出名 | 说明 | 用法 |
72
+ |--------|------|------|
73
+ | `UndoRedoFeature` | 撤销 / 重做 | `UndoRedoFeature` |
74
+ | `TextStyleFeature` | 粗体、斜体、删除线、下划线、链接 | `TextStyleFeature` |
75
+ | `TextAlignFeature` | 文本对齐(左 / 中 / 右 / 两端) | `TextAlignFeature` |
76
+ | `ListFeature` | 有序、无序、任务列表 | `ListFeature` |
77
+ | `CodeBlockFeature` | 代码块(含语法高亮) | `CodeBlockFeature` |
78
+ | `TableFeature` | 表格(含行列增删、移动) | `TableFeature` |
79
+ | `MathFeature` | 数学公式(内联 / 块级,基于 KaTeX) | `MathFeature` |
80
+ | `ImageFeature` | 图片插入(支持自定义上传,默认 Base64) | `ImageFeature` |
81
+ | `SeparatorFeature` | 工具栏分隔符 | `SeparatorFeature` |
43
82
 
44
- 不传 `upload` 时,图片默认转为 Base64 Data URL。传入自定义函数可将图片上传到服务器:
83
+ `upload` 通过 `TiptapEditor` 的 `upload` prop 传入,`ImageFeature` 会自动从 context 中读取:
45
84
 
46
85
  ```vue
47
- <script setup lang="ts">
48
- import { ref } from 'vue'
49
- import { TiptapEditor, type UploadFn } from '@mario9/tiptap-editor'
50
- import '@mario9/tiptap-editor/tiptap-editor.css'
86
+ <TiptapEditor v-model="content" :upload="myUpload" :features="[..., ImageFeature]" />
87
+ ```
51
88
 
52
- const content = ref('')
89
+ ```typescript
90
+ import { type UploadFn } from '@mario9/tiptap-editor'
53
91
 
54
- const upload: UploadFn = async (file) => {
92
+ const myUpload: UploadFn = async (file) => {
55
93
  const formData = new FormData()
56
94
  formData.append('file', file)
57
95
  const res = await fetch('/api/upload', { method: 'POST', body: formData })
58
96
  const data = await res.json()
59
97
  return data.url
60
98
  }
61
- </script>
99
+ ```
62
100
 
63
- <template>
64
- <TiptapEditor v-model="content" :upload="upload" />
65
- </template>
101
+ 不传 `upload` 时图片默认转为 Base64。
102
+
103
+ ## 自定义 Feature Plugin
104
+
105
+ 实现 `FeaturePlugin` 接口即可创建自定义功能插件:
106
+
107
+ ```typescript
108
+ import type { FeaturePlugin } from '@mario9/tiptap-editor'
109
+ import MyButton from './MyButton.vue'
110
+ import MyExtension from './MyExtension'
111
+
112
+ export const MyFeature: FeaturePlugin = {
113
+ name: 'my-feature',
114
+ install: () => ({
115
+ extensions: [MyExtension],
116
+ }),
117
+ toolbarComponent: MyButton,
118
+ }
66
119
  ```
67
120
 
68
- ## 内置功能
121
+ `install()` 接收 `PluginInstallContext`(含 `readonly`、`provide`、`upload`),返回 `{ extensions, controlComponent? }`。
122
+
123
+ ## 内置功能(始终启用)
124
+
125
+ 以下功能无需通过 `features` 配置,始终注册:
69
126
 
70
- - 撤销 / 重做
71
- - 文本样式:粗体、斜体、删除线、下划线、行内代码
72
127
  - 标题(H1–H6)
73
- - 列表:有序、无序、任务列表
74
- - 文本对齐:左、中、右、两端
75
- - 链接(点击弹出编辑框)
76
- - 图片插入(支持自定义上传函数,默认转为 Base64)
77
- - 表格(含行列增删、移动操作)
78
- - 数学公式(内联 / 块级,基于 KaTeX)
79
- - 代码块(支持语法高亮,见下方说明)
80
- - 气泡菜单(选中文本时快速格式化)
128
+ - 段落、水平线
129
+ - 任务列表(TaskList / TaskItem)
130
+ - 文本对齐扩展(TextAlign)
131
+ - 链接(StarterKit 内置)
132
+ - 气泡菜单(选中文本时浮现)
133
+ - Placeholder
81
134
 
82
135
  ### 代码高亮
83
136
 
84
- 编辑器使用 `lowlight` 提供语法高亮,默认支持以下常见语言:
137
+ `CodeBlockFeature` 使用 `lowlight` 提供语法高亮,默认支持以下常见语言:
85
138
 
86
139
  **Web 开发**: JavaScript, TypeScript, HTML, CSS, SCSS, JSON, XML
87
140
  **后端**: Python, Java, C, C++, C#, Go, Rust, PHP, Ruby, Swift, Kotlin
@@ -89,22 +142,6 @@ const upload: UploadFn = async (file) => {
89
142
  **数据库**: SQL
90
143
  **其他**: Markdown, Diff, Plaintext
91
144
 
92
- 如需支持更多语言,可以自定义 `lowlight` 实例:
93
-
94
- ```typescript
95
- import { createLowlight } from 'lowlight'
96
- import javascript from 'highlight.js/lib/languages/javascript'
97
- import python from 'highlight.js/lib/languages/python'
98
- // 按需导入其他语言...
99
-
100
- const customLowlight = createLowlight()
101
- customLowlight.register('javascript', javascript)
102
- customLowlight.register('python', python)
103
-
104
- // 在编辑器配置中使用自定义实例
105
- // 注意:这需要修改库源码或 fork 后自定义
106
- ```
107
-
108
145
  ## 技术栈
109
146
 
110
147
  - vue 3.5.25
@@ -115,18 +152,25 @@ customLowlight.register('python', python)
115
152
 
116
153
  ```
117
154
  src/
118
- ├── App.vue # 初始化编辑器,渲染工具栏 + 编辑器内容
155
+ ├── TiptapEditor.tsx # 编辑器主组件(feature plugin 驱动)
119
156
  ├── editor.scss # 工具栏和编辑器样式
157
+ ├── features/ # Feature plugin 实现
158
+ │ ├── UndoRedoFeature.ts
159
+ │ ├── TextStyleFeature.ts
160
+ │ ├── TextAlignFeature.ts
161
+ │ ├── ListFeature.ts
162
+ │ ├── CodeBlockFeature.ts
163
+ │ ├── TableFeature.ts
164
+ │ ├── MathFeature.ts # 含对话框状态管理
165
+ │ ├── ImageFeature.ts # 工厂函数,接受 upload 参数
166
+ │ └── SeparatorFeature.tsx
167
+ ├── types/
168
+ │ └── plugin.ts # FeaturePlugin 接口定义
120
169
  ├── components/
121
170
  │ └── IconButton.tsx # 基础按钮,包裹 ElButton 和 ElTooltip
122
- ├── tiptap-ui/ # 工具栏按钮组
123
- ├── UndoRedoButton.tsx # 撤销重做
124
- │ ├── TextStyleButton.tsx # 加粗、斜体、删除线、下划线、链接
125
- ├── TextAlignButton.tsx # 左边对齐、中间对齐、右边对齐、两端对齐
126
- │ ├── ListButton.tsx # 无序列表、有序列表、任务列表
127
- │ ├── CodeBlockButton.tsx # 代码块(含语法高亮)
128
- │ ├── ImageButton.tsx # 图片上传
129
- │ └── BubbleMenuBar.tsx # 气泡菜单(选中文本时浮现)
130
- ├── tiptap-icons/ # SVG 图标组件 (TSX)
131
- └── tiptap-extension/ # Tiptap extensions
171
+ ├── tiptap-ui/ # 工具栏按钮组件(TSX)
172
+ ├── tiptap-icons/ # SVG 图标组件(TSX)
173
+ └── tiptap-extension/ # 自定义 Tiptap 扩展
174
+ ├── ImageWithAlign.ts # 带对齐属性的图片扩展
175
+ └── ImageUpload.tsx # 图片上传节点
132
176
  ```
package/dist/index.d.ts CHANGED
@@ -1,37 +1,32 @@
1
- import { BuiltinToolbarItem } from './types';
2
- import { default as CodeBlockButton } from './tiptap-ui/CodeBlockButton';
1
+ import { CodeBlockFeature } from './features/CodeBlockFeature';
3
2
  import { Component } from 'vue';
4
3
  import { ComponentOptionsMixin } from 'vue';
5
4
  import { ComponentProvideOptions } from 'vue';
6
- import { CustomToolbarItem } from './types';
7
- import { DEFAULT_TOOLBAR_CONFIG } from './types/toolbar';
8
5
  import { DefineComponent } from 'vue';
9
6
  import { ExtractPropTypes } from 'vue';
10
- import { default as ImageButton } from './tiptap-ui/ImageButton';
7
+ import { FeaturePlugin } from './types/plugin';
8
+ import { ImageFeature } from './features/ImageFeature';
11
9
  import { ImageOptions } from '@tiptap/extension-image';
12
10
  import { JSX } from 'vue/jsx-runtime';
13
- import { default as ListButton } from './tiptap-ui/ListButton';
14
- import { default as MathButton } from './tiptap-ui/MathButton';
11
+ import { ListFeature } from './features/ListFeature';
12
+ import { MathFeature } from './features/MathFeature';
13
+ import { MathType } from './types';
15
14
  import { Node as Node_2 } from '@tiptap/core';
15
+ import { PluginInstallContext } from './types/plugin';
16
+ import { PluginInstallResult } from './types/plugin';
16
17
  import { PropType } from 'vue';
17
18
  import { PublicProps } from 'vue';
18
- import { default as TableButton } from './tiptap-ui/TableButton';
19
- import { default as TextAlignButton } from './tiptap-ui/TextAlignButton';
20
- import { default as TextStyleButton } from './tiptap-ui/TextStyleButton';
19
+ import { SeparatorFeature } from './features/SeparatorFeature';
20
+ import { TableFeature } from './features/TableFeature';
21
+ import { TextAlignFeature } from './features/TextAlignFeature';
22
+ import { TextStyleFeature } from './features/TextStyleFeature';
21
23
  import { default as TiptapEditor } from './TiptapEditor';
22
- import { ToolbarConfig } from './types';
23
- import { ToolbarItem } from './types';
24
- import { ToolbarSeparator } from './types';
25
- import { default as UndoRedoButton } from './tiptap-ui/UndoRedoButton';
24
+ import { UndoRedoFeature } from './features/UndoRedoFeature';
26
25
  import { UploadFn } from './types';
27
26
 
28
- export { BuiltinToolbarItem }
27
+ export { CodeBlockFeature }
29
28
 
30
- export { CodeBlockButton }
31
-
32
- export { CustomToolbarItem }
33
-
34
- export { DEFAULT_TOOLBAR_CONFIG }
29
+ export { FeaturePlugin }
35
30
 
36
31
  export declare const IconButton: DefineComponent<ExtractPropTypes< {
37
32
  icon: {
@@ -76,29 +71,31 @@ isActive: boolean;
76
71
  disabled: boolean;
77
72
  }, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
78
73
 
79
- export { ImageButton }
74
+ export { ImageFeature }
80
75
 
81
76
  export declare const ImageWithAlign: Node_2<ImageOptions, any>;
82
77
 
83
- export { ListButton }
78
+ export { ListFeature }
84
79
 
85
- export { MathButton }
80
+ export { MathFeature }
86
81
 
87
- export { TableButton }
82
+ export { MathType }
88
83
 
89
- export { TextAlignButton }
84
+ export { PluginInstallContext }
90
85
 
91
- export { TextStyleButton }
86
+ export { PluginInstallResult }
92
87
 
93
- export { TiptapEditor }
88
+ export { SeparatorFeature }
94
89
 
95
- export { ToolbarConfig }
90
+ export { TableFeature }
96
91
 
97
- export { ToolbarItem }
92
+ export { TextAlignFeature }
98
93
 
99
- export { ToolbarSeparator }
94
+ export { TextStyleFeature }
95
+
96
+ export { TiptapEditor }
100
97
 
101
- export { UndoRedoButton }
98
+ export { UndoRedoFeature }
102
99
 
103
100
  export { UploadFn }
104
101