@mario9/tiptap-editor 0.1.6 → 1.0.0

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.
@@ -1,242 +1,21 @@
1
- import { defineComponent as c, computed as V, ref as H, createVNode as e, createTextVNode as m, mergeProps as k, inject as B, watch as D, nextTick as P, watchEffect as G, Fragment as de, provide as z } from "vue";
2
- import pe from "@tiptap/starter-kit";
3
- import { nodeViewProps as Ce, NodeViewWrapper as ve, VueNodeViewRenderer as fe, useEditor as he, EditorContent as ge } from "@tiptap/vue-3";
4
- import { TaskList as me, TaskItem as we } from "@tiptap/extension-list";
5
- import { TextAlign as be } from "@tiptap/extension-text-align";
1
+ import { defineComponent as c, createVNode as e, mergeProps as b, inject as H, computed as T, provide as P, watch as R, ref as k, nextTick as z, createTextVNode as m, watchEffect as G, Fragment as de, h as pe } from "vue";
2
+ import Ce from "@tiptap/starter-kit";
3
+ import { useEditor as ve, EditorContent as fe, nodeViewProps as he, NodeViewWrapper as me, VueNodeViewRenderer as ge } from "@tiptap/vue-3";
4
+ import { TaskList as we, TaskItem as be } from "@tiptap/extension-list";
5
+ import { TextAlign as xe } from "@tiptap/extension-text-align";
6
6
  import { Placeholder as ke } from "@tiptap/extension-placeholder";
7
- import { CodeBlockLowlight as xe } from "@tiptap/extension-code-block-lowlight";
8
- import { createLowlight as He, common as Be } from "lowlight";
7
+ import { BubbleMenu as He } from "@tiptap/vue-3/menus";
8
+ import { ElTooltip as D, ElButton as Z, ElPopover as J, ElInput as X, ElDropdown as j, ElDropdownMenu as W, ElDropdownItem as E, ElDialog as Be, ElRadioGroup as ye, ElRadioButton as q } from "element-plus";
9
9
  import { Image as Ae } from "@tiptap/extension-image";
10
- import { Plugin as ye, NodeSelection as Me } from "@tiptap/pm/state";
11
- import { Decoration as Ie, DecorationSet as Le } from "@tiptap/pm/view";
12
- import { TableRow as Ee, TableHeader as Fe, TableCell as Ve, Table as Te } from "@tiptap/extension-table";
13
- import { Mathematics as Ze } from "@tiptap/extension-mathematics";
14
- import { Node as Re, mergeAttributes as De } from "@tiptap/core";
15
- import { ElTooltip as R, ElButton as Z, ElPopover as J, ElInput as X, ElDropdown as j, ElDropdownMenu as W, ElDropdownItem as E, ElDialog as Se, ElRadioGroup as Ue, ElRadioButton as q } from "element-plus";
10
+ import { Plugin as Me, NodeSelection as Ie } from "@tiptap/pm/state";
11
+ import { Decoration as Le, DecorationSet as Ee } from "@tiptap/pm/view";
12
+ import { CodeBlockLowlight as Fe } from "@tiptap/extension-code-block-lowlight";
13
+ import { createLowlight as Te, common as Ve } from "lowlight";
14
+ import { TableRow as Ze, TableHeader as De, TableCell as Re, Table as Se } from "@tiptap/extension-table";
15
+ import { Mathematics as Ue } from "@tiptap/extension-mathematics";
16
16
  import _e from "katex";
17
- import { BubbleMenu as Pe } from "@tiptap/vue-3/menus";
18
- const ze = Ae.extend({
19
- addAttributes() {
20
- return {
21
- ...this.parent?.(),
22
- align: {
23
- default: "left",
24
- parseHTML: (t) => t.getAttribute("data-align") ?? "left",
25
- renderHTML: (t) => ({ "data-align": t.align })
26
- }
27
- };
28
- },
29
- addProseMirrorPlugins() {
30
- const t = this.name;
31
- return [
32
- new ye({
33
- props: {
34
- decorations(l) {
35
- const n = [];
36
- return l.doc.descendants((o, u) => {
37
- o.type.name === t && o.attrs.align && n.push(
38
- Ie.node(u, u + o.nodeSize, {
39
- "data-align": o.attrs.align
40
- })
41
- );
42
- }), Le.create(l.doc, n);
43
- }
44
- }
45
- })
46
- ];
47
- }
48
- }), Oe = /* @__PURE__ */ c({
49
- name: "ImageUploadView",
50
- props: Ce,
51
- setup(t) {
52
- const l = V(() => t.node.attrs.accept), n = V(() => t.node.attrs.limit), o = V(() => t.node.attrs.maxSize), u = H([]), s = H(), f = H(!1), g = async (a) => {
53
- if (o.value > 0 && a.size > o.value)
54
- return t.extension.options.onError?.(new Error(`文件大小超出限制 ${o.value / 1024 / 1024}MB`)), null;
55
- const d = crypto.randomUUID();
56
- u.value.push({
57
- id: d,
58
- file: a,
59
- progress: 0,
60
- status: "uploading"
61
- });
62
- try {
63
- const v = t.extension.options.upload;
64
- if (!v) throw new Error("未配置 upload 函数");
65
- const h = await v(a);
66
- if (!h) throw new Error("上传失败:未返回 URL");
67
- const A = u.value.find((T) => T.id === d);
68
- return A && (A.status = "success", A.progress = 100), t.extension.options.onSuccess?.(h), h;
69
- } catch (v) {
70
- const h = u.value.find((A) => A.id === d);
71
- return h && (h.status = "error", h.progress = 0), t.extension.options.onError?.(v instanceof Error ? v : new Error("上传失败")), null;
72
- }
73
- }, r = async (a) => {
74
- if (!a.length) return;
75
- if (a.length > n.value) {
76
- t.extension.options.onError?.(new Error(`最多上传 ${n.value} 个文件`));
77
- return;
78
- }
79
- const d = (await Promise.all(a.map(g))).filter((v) => !!v);
80
- if (d.length > 0) {
81
- const v = t.getPos();
82
- if (typeof v != "number") return;
83
- const h = d.map((A) => ({
84
- type: "image",
85
- attrs: {
86
- src: A
87
- }
88
- }));
89
- t.editor.chain().focus().deleteRange({
90
- from: v,
91
- to: v + t.node.nodeSize
92
- }).insertContentAt(v, h).run();
93
- }
94
- }, C = () => {
95
- u.value.length === 0 && s.value && (s.value.value = "", s.value.click());
96
- }, i = (a) => {
97
- const d = a.target.files;
98
- d && r(Array.from(d));
99
- }, p = (a) => {
100
- a.preventDefault(), f.value = !0;
101
- }, w = (a) => {
102
- a.currentTarget.contains(a.relatedTarget) || (f.value = !1);
103
- }, I = (a) => {
104
- a.preventDefault(), f.value = !1;
105
- const d = Array.from(a.dataTransfer?.files ?? []);
106
- d.length && r(d);
107
- }, x = (a) => {
108
- u.value = u.value.filter((d) => d.id !== a);
109
- };
110
- return () => e(ve, {
111
- class: "tiptap-image-upload"
112
- }, {
113
- default: () => [e("div", {
114
- onClick: C
115
- }, [u.value.length ? e("div", {
116
- class: "tiptap-image-upload-previews"
117
- }, [u.value.map((a) => e("div", {
118
- key: a.id,
119
- class: "tiptap-image-upload-preview"
120
- }, [a.status === "uploading" && e("div", {
121
- class: "tiptap-image-upload-progress",
122
- style: {
123
- width: `${a.progress}%`
124
- }
125
- }, null), e("div", {
126
- class: "tiptap-image-upload-preview-content"
127
- }, [e("span", {
128
- class: "tiptap-image-upload-text"
129
- }, [a.file.name]), e("span", {
130
- class: "tiptap-image-upload-subtext"
131
- }, [a.status === "uploading" ? `${a.progress}%` : a.status === "error" ? "上传失败" : "上传成功"]), e("button", {
132
- class: "tiptap-image-upload-remove",
133
- onClick: (d) => {
134
- d.stopPropagation(), x(a.id);
135
- }
136
- }, [m("×")])])]))]) : e("div", {
137
- class: ["tiptap-image-upload-drag-area", {
138
- "drag-active": f.value
139
- }],
140
- onDragover: p,
141
- onDragleave: w,
142
- onDrop: I
143
- }, [e("div", {
144
- class: "tiptap-image-upload-content"
145
- }, [e("span", {
146
- class: "tiptap-image-upload-text"
147
- }, [e("em", null, [m("点击上传")]), m(" 或拖拽图片到此处")]), e("span", {
148
- class: "tiptap-image-upload-subtext"
149
- }, [m("最多 "), n.value, m(" 个文件"), o.value ? `,每个不超过 ${o.value / 1024 / 1024}MB` : ""])])]), e("input", {
150
- ref: s,
151
- type: "file",
152
- accept: l.value,
153
- multiple: n.value > 1,
154
- onChange: i,
155
- onClick: (a) => a.stopPropagation()
156
- }, null)])]
157
- });
158
- }
159
- }), $e = Re.create({
160
- name: "imageUpload",
161
- group: "block",
162
- draggable: !0,
163
- selectable: !0,
164
- atom: !0,
165
- addOptions() {
166
- return {
167
- type: "image",
168
- accept: "image/*",
169
- limit: 1,
170
- maxSize: 0,
171
- upload: (t) => new Promise((l) => {
172
- const n = new FileReader();
173
- n.onloadend = () => l(n.result), n.readAsDataURL(t);
174
- }),
175
- onError: void 0,
176
- onSuccess: void 0,
177
- HTMLAttributes: {}
178
- };
179
- },
180
- addAttributes() {
181
- return {
182
- accept: {
183
- default: this.options.accept
184
- },
185
- limit: {
186
- default: this.options.limit
187
- },
188
- maxSize: {
189
- default: this.options.maxSize
190
- }
191
- };
192
- },
193
- parseHTML() {
194
- return [{
195
- tag: 'div[data-type="image-upload"]'
196
- }];
197
- },
198
- renderHTML({
199
- HTMLAttributes: t
200
- }) {
201
- return ["div", De({
202
- "data-type": "image-upload"
203
- }, t)];
204
- },
205
- addNodeView() {
206
- return fe(Oe);
207
- },
208
- addCommands() {
209
- return {
210
- setImageUploadNode: () => ({
211
- commands: t
212
- }) => t.insertContent({
213
- type: this.name
214
- })
215
- };
216
- },
217
- addKeyboardShortcuts() {
218
- return {
219
- Enter: ({
220
- editor: t
221
- }) => {
222
- const {
223
- selection: l
224
- } = t.state, {
225
- nodeAfter: n
226
- } = l.$from;
227
- if (n?.type.name === "imageUpload" && t.isActive("imageUpload")) {
228
- const o = t.view.nodeDOM(l.$from.pos);
229
- if (o instanceof HTMLElement) {
230
- const u = o.firstChild;
231
- if (u instanceof HTMLElement)
232
- return u.click(), !0;
233
- }
234
- }
235
- return !1;
236
- }
237
- };
238
- }
239
- }), Ne = {
17
+ import { Node as Pe, mergeAttributes as ze } from "@tiptap/core";
18
+ const Oe = {
240
19
  icon: {
241
20
  type: Object,
242
21
  required: !0
@@ -255,11 +34,11 @@ const ze = Ae.extend({
255
34
  onClick: {
256
35
  type: Function
257
36
  }
258
- }, b = /* @__PURE__ */ c({
37
+ }, w = /* @__PURE__ */ c({
259
38
  name: "IconButton",
260
- props: Ne,
39
+ props: Oe,
261
40
  setup(t) {
262
- return () => e(R, {
41
+ return () => e(D, {
263
42
  showArrow: !1,
264
43
  offset: 6,
265
44
  content: t.tooltip
@@ -275,12 +54,247 @@ const ze = Ae.extend({
275
54
  }, null)]
276
55
  });
277
56
  }
57
+ }), Q = /* @__PURE__ */ c({
58
+ name: "BoldIcon",
59
+ setup(t, {
60
+ attrs: l
61
+ }) {
62
+ return () => e("svg", b({
63
+ width: "24",
64
+ height: "24",
65
+ viewBox: "0 0 24 24",
66
+ fill: "currentColor",
67
+ xmlns: "http://www.w3.org/2000/svg"
68
+ }, l), [e("path", {
69
+ "fill-rule": "evenodd",
70
+ "clip-rule": "evenodd",
71
+ d: "M6 2.5C5.17157 2.5 4.5 3.17157 4.5 4V20C4.5 20.8284 5.17157 21.5 6 21.5H15C16.4587 21.5 17.8576 20.9205 18.8891 19.8891C19.9205 18.8576 20.5 17.4587 20.5 16C20.5 14.5413 19.9205 13.1424 18.8891 12.1109C18.6781 11.9 18.4518 11.7079 18.2128 11.5359C19.041 10.5492 19.5 9.29829 19.5 8C19.5 6.54131 18.9205 5.14236 17.8891 4.11091C16.8576 3.07946 15.4587 2.5 14 2.5H6ZM14 10.5C14.663 10.5 15.2989 10.2366 15.7678 9.76777C16.2366 9.29893 16.5 8.66304 16.5 8C16.5 7.33696 16.2366 6.70107 15.7678 6.23223C15.2989 5.76339 14.663 5.5 14 5.5H7.5V10.5H14ZM7.5 18.5V13.5H15C15.663 13.5 16.2989 13.7634 16.7678 14.2322C17.2366 14.7011 17.5 15.337 17.5 16C17.5 16.663 17.2366 17.2989 16.7678 17.7678C16.2989 18.2366 15.663 18.5 15 18.5H7.5Z",
72
+ fill: "currentColor"
73
+ }, null)]);
74
+ }
75
+ }), Y = /* @__PURE__ */ c({
76
+ name: "ItalicIcon",
77
+ setup(t, {
78
+ attrs: l
79
+ }) {
80
+ return () => e("svg", b({
81
+ width: "24",
82
+ height: "24",
83
+ viewBox: "0 0 24 24",
84
+ fill: "currentColor",
85
+ xmlns: "http://www.w3.org/2000/svg"
86
+ }, l), [e("path", {
87
+ d: "M15.0222 3H19C19.5523 3 20 3.44772 20 4C20 4.55228 19.5523 5 19 5H15.693L10.443 19H14C14.5523 19 15 19.4477 15 20C15 20.5523 14.5523 21 14 21H9.02418C9.00802 21.0004 8.99181 21.0004 8.97557 21H5C4.44772 21 4 20.5523 4 20C4 19.4477 4.44772 19 5 19H8.30704L13.557 5H10C9.44772 5 9 4.55228 9 4C9 3.44772 9.44772 3 10 3H14.9782C14.9928 2.99968 15.0075 2.99967 15.0222 3Z",
88
+ fill: "currentColor"
89
+ }, null)]);
90
+ }
91
+ }), ee = /* @__PURE__ */ c({
92
+ name: "StrikeIcon",
93
+ setup(t, {
94
+ attrs: l
95
+ }) {
96
+ return () => e("svg", b({
97
+ width: "24",
98
+ height: "24",
99
+ viewBox: "0 0 24 24",
100
+ fill: "currentColor",
101
+ xmlns: "http://www.w3.org/2000/svg"
102
+ }, l), [e("path", {
103
+ d: "M9.00039 3H16.0001C16.5524 3 17.0001 3.44772 17.0001 4C17.0001 4.55229 16.5524 5 16.0001 5H9.00011C8.68006 4.99983 8.36412 5.07648 8.07983 5.22349C7.79555 5.37051 7.55069 5.5836 7.36585 5.84487C7.181 6.10614 7.06155 6.40796 7.01754 6.72497C6.97352 7.04198 7.00623 7.36492 7.11292 7.66667C7.29701 8.18737 7.02414 8.75872 6.50344 8.94281C5.98274 9.1269 5.4114 8.85403 5.2273 8.33333C5.01393 7.72984 4.94851 7.08396 5.03654 6.44994C5.12456 5.81592 5.36346 5.21229 5.73316 4.68974C6.10285 4.1672 6.59256 3.74101 7.16113 3.44698C7.72955 3.15303 8.36047 2.99975 9.00039 3Z",
104
+ fill: "currentColor"
105
+ }, null), e("path", {
106
+ d: "M18 13H20C20.5523 13 21 12.5523 21 12C21 11.4477 20.5523 11 20 11H4C3.44772 11 3 11.4477 3 12C3 12.5523 3.44772 13 4 13H14C14.7956 13 15.5587 13.3161 16.1213 13.8787C16.6839 14.4413 17 15.2044 17 16C17 16.7956 16.6839 17.5587 16.1213 18.1213C15.5587 18.6839 14.7956 19 14 19H6C5.44772 19 5 19.4477 5 20C5 20.5523 5.44772 21 6 21H14C15.3261 21 16.5979 20.4732 17.5355 19.5355C18.4732 18.5979 19 17.3261 19 16C19 14.9119 18.6453 13.8604 18 13Z",
107
+ fill: "currentColor"
108
+ }, null)]);
109
+ }
110
+ }), te = /* @__PURE__ */ c({
111
+ name: "UnderlineIcon",
112
+ setup(t, {
113
+ attrs: l
114
+ }) {
115
+ return () => e("svg", b({
116
+ width: "24",
117
+ height: "24",
118
+ viewBox: "0 0 24 24",
119
+ fill: "currentColor",
120
+ xmlns: "http://www.w3.org/2000/svg"
121
+ }, l), [e("path", {
122
+ "fill-rule": "evenodd",
123
+ "clip-rule": "evenodd",
124
+ d: "M7 4C7 3.44772 6.55228 3 6 3C5.44772 3 5 3.44772 5 4V10C5 11.8565 5.7375 13.637 7.05025 14.9497C8.36301 16.2625 10.1435 17 12 17C13.8565 17 15.637 16.2625 16.9497 14.9497C18.2625 13.637 19 11.8565 19 10V4C19 3.44772 18.5523 3 18 3C17.4477 3 17 3.44772 17 4V10C17 11.3261 16.4732 12.5979 15.5355 13.5355C14.5979 14.4732 13.3261 15 12 15C10.6739 15 9.40215 14.4732 8.46447 13.5355C7.52678 12.5979 7 11.3261 7 10V4ZM4 19C3.44772 19 3 19.4477 3 20C3 20.5523 3.44772 21 4 21H20C20.5523 21 21 20.5523 21 20C21 19.4477 20.5523 19 20 19H4Z",
125
+ fill: "currentColor"
126
+ }, null)]);
127
+ }
128
+ }), $e = /* @__PURE__ */ c({
129
+ name: "BubbleMenuBar",
130
+ setup() {
131
+ const t = H("editor"), l = H("readonly");
132
+ return () => t?.value ? e(He, {
133
+ editor: t.value,
134
+ class: "bubble-menu",
135
+ options: {
136
+ placement: "top",
137
+ offset: {
138
+ mainAxis: 8
139
+ }
140
+ },
141
+ shouldShow: (n) => {
142
+ if (l?.value) return !1;
143
+ const {
144
+ editor: o,
145
+ from: i,
146
+ to: r
147
+ } = n;
148
+ return !(i === r || o.isActive("image") || o.isActive("table"));
149
+ }
150
+ }, {
151
+ default: () => [e("div", {
152
+ class: "bubble-menu-content"
153
+ }, [e(w, {
154
+ icon: Q,
155
+ tooltip: "粗体",
156
+ isActive: t.value.isActive("bold"),
157
+ onClick: () => t.value?.chain().focus().toggleBold().run()
158
+ }, null), e(w, {
159
+ icon: Y,
160
+ tooltip: "斜体",
161
+ isActive: t.value.isActive("italic"),
162
+ onClick: () => t.value?.chain().focus().toggleItalic().run()
163
+ }, null), e(w, {
164
+ icon: ee,
165
+ tooltip: "删除线",
166
+ isActive: t.value.isActive("strike"),
167
+ onClick: () => t.value?.chain().focus().toggleStrike().run()
168
+ }, null), e(w, {
169
+ icon: te,
170
+ tooltip: "下划线",
171
+ isActive: t.value.isActive("underline"),
172
+ onClick: () => t.value?.chain().focus().toggleUnderline().run()
173
+ }, null)])]
174
+ }) : null;
175
+ }
176
+ }), qt = /* @__PURE__ */ c({
177
+ name: "TiptapEditor",
178
+ props: {
179
+ modelValue: {
180
+ type: String,
181
+ default: ""
182
+ },
183
+ placeholder: {
184
+ type: String,
185
+ default: "请输入内容..."
186
+ },
187
+ readonly: {
188
+ type: Boolean,
189
+ default: !1
190
+ },
191
+ features: {
192
+ type: Array,
193
+ default: () => []
194
+ }
195
+ },
196
+ emits: ["update:modelValue"],
197
+ setup(t, {
198
+ emit: l
199
+ }) {
200
+ const n = T(() => t.readonly ?? !1);
201
+ P("readonly", n);
202
+ const o = t.features.map((r) => ({
203
+ plugin: r,
204
+ result: r.install({
205
+ readonly: n,
206
+ provide: (v, p) => P(v, p)
207
+ })
208
+ })), i = ve({
209
+ content: t.modelValue,
210
+ editable: !t.readonly,
211
+ extensions: [Ce.configure({
212
+ codeBlock: !1,
213
+ link: {
214
+ openOnClick: !1,
215
+ enableClickSelection: !0
216
+ }
217
+ }), ke.configure({
218
+ placeholder: t.placeholder
219
+ }), xe.configure({
220
+ types: ["heading", "paragraph"]
221
+ }), we, be.configure({
222
+ nested: !0
223
+ }), ...o.flatMap(({
224
+ result: r
225
+ }) => r.extensions)],
226
+ onUpdate: ({
227
+ editor: r
228
+ }) => {
229
+ l("update:modelValue", r.getHTML());
230
+ }
231
+ });
232
+ return P("editor", i), R(() => t.modelValue, (r) => {
233
+ i.value && r !== i.value.getHTML() && i.value.commands.setContent(r, {
234
+ emitUpdate: !1
235
+ });
236
+ }), R(() => t.readonly, (r) => {
237
+ i.value?.setEditable(!r);
238
+ }), () => e("div", {
239
+ class: "tiptap-editor"
240
+ }, [!t.readonly && e("div", {
241
+ class: "tiptap-toolbar"
242
+ }, [o.map(({
243
+ plugin: r
244
+ }) => {
245
+ const v = r.toolbarComponent;
246
+ return v ? e(v, {
247
+ key: r.name
248
+ }, null) : null;
249
+ })]), e(fe, {
250
+ class: "tiptap-content",
251
+ editor: i.value
252
+ }, null), e($e, null, null), o.map(({
253
+ plugin: r,
254
+ result: v
255
+ }) => {
256
+ const p = v.controlComponent;
257
+ return p ? e(p, {
258
+ key: `${r.name}-control`
259
+ }, null) : null;
260
+ })]);
261
+ }
262
+ }), Ne = Ae.extend({
263
+ addAttributes() {
264
+ return {
265
+ ...this.parent?.(),
266
+ align: {
267
+ default: "left",
268
+ parseHTML: (t) => t.getAttribute("data-align") ?? "left",
269
+ renderHTML: (t) => ({ "data-align": t.align })
270
+ }
271
+ };
272
+ },
273
+ addProseMirrorPlugins() {
274
+ const t = this.name;
275
+ return [
276
+ new Me({
277
+ props: {
278
+ decorations(l) {
279
+ const n = [];
280
+ return l.doc.descendants((o, i) => {
281
+ o.type.name === t && o.attrs.align && n.push(
282
+ Le.node(i, i + o.nodeSize, {
283
+ "data-align": o.attrs.align
284
+ })
285
+ );
286
+ }), Ee.create(l.doc, n);
287
+ }
288
+ }
289
+ })
290
+ ];
291
+ }
278
292
  }), je = /* @__PURE__ */ c({
279
293
  name: "UndoIcon",
280
294
  setup(t, {
281
295
  attrs: l
282
296
  }) {
283
- return () => e("svg", k({
297
+ return () => e("svg", b({
284
298
  width: "24",
285
299
  height: "24",
286
300
  viewBox: "0 0 24 24",
@@ -298,7 +312,7 @@ const ze = Ae.extend({
298
312
  setup(t, {
299
313
  attrs: l
300
314
  }) {
301
- return () => e("svg", k({
315
+ return () => e("svg", b({
302
316
  width: "24",
303
317
  height: "24",
304
318
  viewBox: "0 0 24 24",
@@ -314,25 +328,29 @@ const ze = Ae.extend({
314
328
  }), qe = /* @__PURE__ */ c({
315
329
  name: "UndoRedoButton",
316
330
  setup() {
317
- const t = B("editor"), l = V(() => t?.value?.can().undo() ?? !1), n = V(() => t?.value?.can().redo() ?? !1);
318
- return () => e("div", null, [e(b, {
331
+ const t = H("editor"), l = T(() => t?.value?.can().undo() ?? !1), n = T(() => t?.value?.can().redo() ?? !1);
332
+ return () => e("div", null, [e(w, {
319
333
  icon: je,
320
334
  tooltip: "撤销",
321
335
  disabled: !l.value,
322
336
  onClick: () => t?.value?.chain().focus().undo().run()
323
- }, null), e(b, {
337
+ }, null), e(w, {
324
338
  icon: We,
325
339
  tooltip: "重做",
326
340
  disabled: !n.value,
327
341
  onClick: () => t?.value?.chain().focus().redo().run()
328
342
  }, null)]);
329
343
  }
330
- }), Ke = /* @__PURE__ */ c({
344
+ }), Kt = {
345
+ name: "undo-redo",
346
+ install: () => ({ extensions: [] }),
347
+ toolbarComponent: qe
348
+ }, Ke = /* @__PURE__ */ c({
331
349
  name: "LinkIcon",
332
350
  setup(t, {
333
351
  attrs: l
334
352
  }) {
335
- return () => e("svg", k({
353
+ return () => e("svg", b({
336
354
  width: "24",
337
355
  height: "24",
338
356
  viewBox: "0 0 24 24",
@@ -351,7 +369,7 @@ const ze = Ae.extend({
351
369
  setup(t, {
352
370
  attrs: l
353
371
  }) {
354
- return () => e("svg", k({
372
+ return () => e("svg", b({
355
373
  width: "24",
356
374
  height: "24",
357
375
  viewBox: "0 0 24 24",
@@ -372,7 +390,7 @@ const ze = Ae.extend({
372
390
  setup(t, {
373
391
  attrs: l
374
392
  }) {
375
- return () => e("svg", k({
393
+ return () => e("svg", b({
376
394
  width: "24",
377
395
  height: "24",
378
396
  viewBox: "0 0 24 24",
@@ -398,7 +416,7 @@ const ze = Ae.extend({
398
416
  setup(t, {
399
417
  attrs: l
400
418
  }) {
401
- return () => e("svg", k({
419
+ return () => e("svg", b({
402
420
  width: "24",
403
421
  height: "24",
404
422
  viewBox: "0 0 24 24",
@@ -417,49 +435,49 @@ const ze = Ae.extend({
417
435
  }), Qe = /* @__PURE__ */ c({
418
436
  name: "LinkPopover",
419
437
  setup() {
420
- const t = B("editor"), l = H(!1), n = H("");
438
+ const t = H("editor"), l = k(!1), n = k("");
421
439
  let o = !1;
422
- D(() => t?.value?.isActive("link"), (i) => {
423
- o || i && (n.value = t?.value?.getAttributes("link").href ?? "", P(() => {
440
+ R(() => t?.value?.isActive("link"), (u) => {
441
+ o || u && (n.value = t?.value?.getAttributes("link").href ?? "", z(() => {
424
442
  l.value = !0;
425
443
  }));
426
444
  });
427
- const u = () => {
428
- const i = t?.value;
429
- if (!i || !n.value) return;
445
+ const i = () => {
446
+ const u = t?.value;
447
+ if (!u || !n.value) return;
430
448
  o = !0;
431
449
  const {
432
- empty: p
433
- } = i.state.selection;
434
- let w = i.chain().focus().extendMarkRange("link").setLink({
450
+ empty: C
451
+ } = u.state.selection;
452
+ let g = u.chain().focus().extendMarkRange("link").setLink({
435
453
  href: n.value
436
454
  });
437
- p && (w = w.insertContent({
455
+ C && (g = g.insertContent({
438
456
  type: "text",
439
457
  text: n.value
440
- })), w.run(), l.value = !1, P(() => {
458
+ })), g.run(), l.value = !1, z(() => {
441
459
  o = !1;
442
460
  });
443
- }, s = () => {
444
- const i = t?.value;
445
- i && (o = !0, i.chain().focus().extendMarkRange("link").unsetLink().run(), n.value = "", l.value = !1, P(() => {
461
+ }, r = () => {
462
+ const u = t?.value;
463
+ u && (o = !0, u.chain().focus().extendMarkRange("link").unsetLink().run(), n.value = "", l.value = !1, z(() => {
446
464
  o = !1;
447
465
  }));
448
- }, f = () => {
449
- const i = t?.value?.getAttributes("link").href;
450
- i && window.open(i, "_blank", "noopener,noreferrer");
451
- }, g = (i) => {
452
- i.key === "Enter" && (i.preventDefault(), u());
453
- }, r = (i) => {
454
- i && (n.value = t?.value?.getAttributes("link").href ?? ""), l.value = i;
455
- }, C = (i) => {
456
- n.value = i;
466
+ }, v = () => {
467
+ const u = t?.value?.getAttributes("link").href;
468
+ u && window.open(u, "_blank", "noopener,noreferrer");
469
+ }, p = (u) => {
470
+ u.key === "Enter" && (u.preventDefault(), i());
471
+ }, s = (u) => {
472
+ u && (n.value = t?.value?.getAttributes("link").href ?? ""), l.value = u;
473
+ }, y = (u) => {
474
+ n.value = u;
457
475
  };
458
476
  return () => {
459
- const i = t?.value?.isActive("link") ?? !1;
477
+ const u = t?.value?.isActive("link") ?? !1;
460
478
  return e(J, {
461
479
  visible: l.value,
462
- "onUpdate:visible": r,
480
+ "onUpdate:visible": s,
463
481
  placement: "bottom",
464
482
  width: 300,
465
483
  trigger: "click",
@@ -467,26 +485,26 @@ const ze = Ae.extend({
467
485
  popperClass: "link-popover-popper",
468
486
  offset: 6
469
487
  }, {
470
- reference: () => e("span", null, [e(b, {
488
+ reference: () => e("span", null, [e(w, {
471
489
  tooltip: "链接",
472
490
  icon: Ke,
473
491
  class: ["tiptap-button", {
474
- "is-active": i
492
+ "is-active": u
475
493
  }]
476
494
  }, null)]),
477
495
  default: () => e("div", {
478
496
  class: "link-popover-inner"
479
497
  }, [e(X, {
480
498
  modelValue: n.value,
481
- "onUpdate:modelValue": C,
499
+ "onUpdate:modelValue": y,
482
500
  type: "url",
483
501
  placeholder: "请输入链接...",
484
502
  size: "small",
485
503
  autofocus: !0,
486
- onKeydown: g
504
+ onKeydown: p
487
505
  }, null), e("div", {
488
506
  class: "link-popover-actions"
489
- }, [e(R, {
507
+ }, [e(D, {
490
508
  content: "确认",
491
509
  showArrow: !1,
492
510
  offset: 4
@@ -495,9 +513,9 @@ const ze = Ae.extend({
495
513
  text: !0,
496
514
  icon: Ge,
497
515
  disabled: !n.value,
498
- onClick: u
516
+ onClick: i
499
517
  }, null)]
500
- }), e(R, {
518
+ }), e(D, {
501
519
  content: "在新标签页打开",
502
520
  showArrow: !1,
503
521
  offset: 4
@@ -505,10 +523,10 @@ const ze = Ae.extend({
505
523
  default: () => [e(Z, {
506
524
  text: !0,
507
525
  icon: Je,
508
- disabled: !n.value && !i,
509
- onClick: f
526
+ disabled: !n.value && !u,
527
+ onClick: v
510
528
  }, null)]
511
- }), e(R, {
529
+ }), e(D, {
512
530
  content: "移除链接",
513
531
  showArrow: !1,
514
532
  offset: 4
@@ -516,116 +534,49 @@ const ze = Ae.extend({
516
534
  default: () => [e(Z, {
517
535
  text: !0,
518
536
  icon: Xe,
519
- disabled: !i,
520
- onClick: s
537
+ disabled: !u,
538
+ onClick: r
521
539
  }, null)]
522
540
  })])])
523
541
  });
524
542
  };
525
543
  }
526
- }), Q = /* @__PURE__ */ c({
527
- name: "BoldIcon",
528
- setup(t, {
529
- attrs: l
530
- }) {
531
- return () => e("svg", k({
532
- width: "24",
533
- height: "24",
534
- viewBox: "0 0 24 24",
535
- fill: "currentColor",
536
- xmlns: "http://www.w3.org/2000/svg"
537
- }, l), [e("path", {
538
- "fill-rule": "evenodd",
539
- "clip-rule": "evenodd",
540
- d: "M6 2.5C5.17157 2.5 4.5 3.17157 4.5 4V20C4.5 20.8284 5.17157 21.5 6 21.5H15C16.4587 21.5 17.8576 20.9205 18.8891 19.8891C19.9205 18.8576 20.5 17.4587 20.5 16C20.5 14.5413 19.9205 13.1424 18.8891 12.1109C18.6781 11.9 18.4518 11.7079 18.2128 11.5359C19.041 10.5492 19.5 9.29829 19.5 8C19.5 6.54131 18.9205 5.14236 17.8891 4.11091C16.8576 3.07946 15.4587 2.5 14 2.5H6ZM14 10.5C14.663 10.5 15.2989 10.2366 15.7678 9.76777C16.2366 9.29893 16.5 8.66304 16.5 8C16.5 7.33696 16.2366 6.70107 15.7678 6.23223C15.2989 5.76339 14.663 5.5 14 5.5H7.5V10.5H14ZM7.5 18.5V13.5H15C15.663 13.5 16.2989 13.7634 16.7678 14.2322C17.2366 14.7011 17.5 15.337 17.5 16C17.5 16.663 17.2366 17.2989 16.7678 17.7678C16.2989 18.2366 15.663 18.5 15 18.5H7.5Z",
541
- fill: "currentColor"
542
- }, null)]);
543
- }
544
- }), Y = /* @__PURE__ */ c({
545
- name: "ItalicIcon",
546
- setup(t, {
547
- attrs: l
548
- }) {
549
- return () => e("svg", k({
550
- width: "24",
551
- height: "24",
552
- viewBox: "0 0 24 24",
553
- fill: "currentColor",
554
- xmlns: "http://www.w3.org/2000/svg"
555
- }, l), [e("path", {
556
- d: "M15.0222 3H19C19.5523 3 20 3.44772 20 4C20 4.55228 19.5523 5 19 5H15.693L10.443 19H14C14.5523 19 15 19.4477 15 20C15 20.5523 14.5523 21 14 21H9.02418C9.00802 21.0004 8.99181 21.0004 8.97557 21H5C4.44772 21 4 20.5523 4 20C4 19.4477 4.44772 19 5 19H8.30704L13.557 5H10C9.44772 5 9 4.55228 9 4C9 3.44772 9.44772 3 10 3H14.9782C14.9928 2.99968 15.0075 2.99967 15.0222 3Z",
557
- fill: "currentColor"
558
- }, null)]);
559
- }
560
- }), ee = /* @__PURE__ */ c({
561
- name: "StrikeIcon",
562
- setup(t, {
563
- attrs: l
564
- }) {
565
- return () => e("svg", k({
566
- width: "24",
567
- height: "24",
568
- viewBox: "0 0 24 24",
569
- fill: "currentColor",
570
- xmlns: "http://www.w3.org/2000/svg"
571
- }, l), [e("path", {
572
- d: "M9.00039 3H16.0001C16.5524 3 17.0001 3.44772 17.0001 4C17.0001 4.55229 16.5524 5 16.0001 5H9.00011C8.68006 4.99983 8.36412 5.07648 8.07983 5.22349C7.79555 5.37051 7.55069 5.5836 7.36585 5.84487C7.181 6.10614 7.06155 6.40796 7.01754 6.72497C6.97352 7.04198 7.00623 7.36492 7.11292 7.66667C7.29701 8.18737 7.02414 8.75872 6.50344 8.94281C5.98274 9.1269 5.4114 8.85403 5.2273 8.33333C5.01393 7.72984 4.94851 7.08396 5.03654 6.44994C5.12456 5.81592 5.36346 5.21229 5.73316 4.68974C6.10285 4.1672 6.59256 3.74101 7.16113 3.44698C7.72955 3.15303 8.36047 2.99975 9.00039 3Z",
573
- fill: "currentColor"
574
- }, null), e("path", {
575
- d: "M18 13H20C20.5523 13 21 12.5523 21 12C21 11.4477 20.5523 11 20 11H4C3.44772 11 3 11.4477 3 12C3 12.5523 3.44772 13 4 13H14C14.7956 13 15.5587 13.3161 16.1213 13.8787C16.6839 14.4413 17 15.2044 17 16C17 16.7956 16.6839 17.5587 16.1213 18.1213C15.5587 18.6839 14.7956 19 14 19H6C5.44772 19 5 19.4477 5 20C5 20.5523 5.44772 21 6 21H14C15.3261 21 16.5979 20.4732 17.5355 19.5355C18.4732 18.5979 19 17.3261 19 16C19 14.9119 18.6453 13.8604 18 13Z",
576
- fill: "currentColor"
577
- }, null)]);
578
- }
579
- }), te = /* @__PURE__ */ c({
580
- name: "UnderlineIcon",
581
- setup(t, {
582
- attrs: l
583
- }) {
584
- return () => e("svg", k({
585
- width: "24",
586
- height: "24",
587
- viewBox: "0 0 24 24",
588
- fill: "currentColor",
589
- xmlns: "http://www.w3.org/2000/svg"
590
- }, l), [e("path", {
591
- "fill-rule": "evenodd",
592
- "clip-rule": "evenodd",
593
- d: "M7 4C7 3.44772 6.55228 3 6 3C5.44772 3 5 3.44772 5 4V10C5 11.8565 5.7375 13.637 7.05025 14.9497C8.36301 16.2625 10.1435 17 12 17C13.8565 17 15.637 16.2625 16.9497 14.9497C18.2625 13.637 19 11.8565 19 10V4C19 3.44772 18.5523 3 18 3C17.4477 3 17 3.44772 17 4V10C17 11.3261 16.4732 12.5979 15.5355 13.5355C14.5979 14.4732 13.3261 15 12 15C10.6739 15 9.40215 14.4732 8.46447 13.5355C7.52678 12.5979 7 11.3261 7 10V4ZM4 19C3.44772 19 3 19.4477 3 20C3 20.5523 3.44772 21 4 21H20C20.5523 21 21 20.5523 21 20C21 19.4477 20.5523 19 20 19H4Z",
594
- fill: "currentColor"
595
- }, null)]);
596
- }
597
544
  }), Ye = /* @__PURE__ */ c({
598
545
  name: "TextStyleButton",
599
546
  setup() {
600
- const t = B("editor");
601
- return () => e("div", null, [e(b, {
547
+ const t = H("editor");
548
+ return () => e("div", null, [e(w, {
602
549
  icon: Q,
603
550
  tooltip: "粗体",
604
551
  isActive: t?.value?.isActive("bold"),
605
552
  onClick: () => t?.value?.chain().focus().toggleBold().run()
606
- }, null), e(b, {
553
+ }, null), e(w, {
607
554
  icon: Y,
608
555
  tooltip: "斜体",
609
556
  isActive: t?.value?.isActive("italic"),
610
557
  onClick: () => t?.value?.chain().focus().toggleItalic().run()
611
- }, null), e(b, {
558
+ }, null), e(w, {
612
559
  icon: ee,
613
560
  tooltip: "删除线",
614
561
  isActive: t?.value?.isActive("strike"),
615
562
  onClick: () => t?.value?.chain().focus().toggleStrike().run()
616
- }, null), e(b, {
563
+ }, null), e(w, {
617
564
  icon: te,
618
565
  tooltip: "下划线",
619
566
  isActive: t?.value?.isActive("underline"),
620
567
  onClick: () => t?.value?.chain().focus().toggleUnderline().run()
621
568
  }, null), e(Qe, null, null)]);
622
569
  }
623
- }), le = /* @__PURE__ */ c({
570
+ }), Gt = {
571
+ name: "text-style",
572
+ install: () => ({ extensions: [] }),
573
+ toolbarComponent: Ye
574
+ }, le = /* @__PURE__ */ c({
624
575
  name: "AlignLeftIcon",
625
576
  setup(t, {
626
577
  attrs: l
627
578
  }) {
628
- return () => e("svg", k({
579
+ return () => e("svg", b({
629
580
  width: "24",
630
581
  height: "24",
631
582
  viewBox: "0 0 24 24",
@@ -653,7 +604,7 @@ const ze = Ae.extend({
653
604
  setup(t, {
654
605
  attrs: l
655
606
  }) {
656
- return () => e("svg", k({
607
+ return () => e("svg", b({
657
608
  width: "24",
658
609
  height: "24",
659
610
  viewBox: "0 0 24 24",
@@ -681,7 +632,7 @@ const ze = Ae.extend({
681
632
  setup(t, {
682
633
  attrs: l
683
634
  }) {
684
- return () => e("svg", k({
635
+ return () => e("svg", b({
685
636
  width: "24",
686
637
  height: "24",
687
638
  viewBox: "0 0 24 24",
@@ -704,12 +655,12 @@ const ze = Ae.extend({
704
655
  fill: "currentColor"
705
656
  }, null)]);
706
657
  }
707
- }), e1 = /* @__PURE__ */ c({
658
+ }), et = /* @__PURE__ */ c({
708
659
  name: "AlignJustifyIcon",
709
660
  setup(t, {
710
661
  attrs: l
711
662
  }) {
712
- return () => e("svg", k({
663
+ return () => e("svg", b({
713
664
  width: "24",
714
665
  height: "24",
715
666
  viewBox: "0 0 24 24",
@@ -732,33 +683,33 @@ const ze = Ae.extend({
732
683
  fill: "currentColor"
733
684
  }, null)]);
734
685
  }
735
- }), t1 = /* @__PURE__ */ c({
686
+ }), tt = /* @__PURE__ */ c({
736
687
  name: "TextAlignButton",
737
688
  setup() {
738
- const t = B("editor");
739
- return () => e("div", null, [e(b, {
689
+ const t = H("editor");
690
+ return () => e("div", null, [e(w, {
740
691
  icon: le,
741
692
  tooltip: "左边对齐",
742
693
  isActive: t?.value?.isActive({
743
694
  textAlign: "left"
744
695
  }),
745
696
  onClick: () => t?.value?.chain().focus().setTextAlign("left").run()
746
- }, null), e(b, {
697
+ }, null), e(w, {
747
698
  icon: ne,
748
699
  tooltip: "中间对齐",
749
700
  isActive: t?.value?.isActive({
750
701
  textAlign: "center"
751
702
  }),
752
703
  onClick: () => t?.value?.chain().focus().setTextAlign("center").run()
753
- }, null), e(b, {
704
+ }, null), e(w, {
754
705
  icon: oe,
755
706
  tooltip: "右边对齐",
756
707
  isActive: t?.value?.isActive({
757
708
  textAlign: "right"
758
709
  }),
759
710
  onClick: () => t?.value?.chain().focus().setTextAlign("right").run()
760
- }, null), e(b, {
761
- icon: e1,
711
+ }, null), e(w, {
712
+ icon: et,
762
713
  tooltip: "两端对齐",
763
714
  isActive: t?.value?.isActive({
764
715
  textAlign: "justify"
@@ -766,12 +717,16 @@ const ze = Ae.extend({
766
717
  onClick: () => t?.value?.chain().focus().setTextAlign("justify").run()
767
718
  }, null)]);
768
719
  }
769
- }), l1 = /* @__PURE__ */ c({
720
+ }), Jt = {
721
+ name: "text-align",
722
+ install: () => ({ extensions: [] }),
723
+ toolbarComponent: tt
724
+ }, lt = /* @__PURE__ */ c({
770
725
  name: "ListIcon",
771
726
  setup(t, {
772
727
  attrs: l
773
728
  }) {
774
- return () => e("svg", k({
729
+ return () => e("svg", b({
775
730
  width: "24",
776
731
  height: "24",
777
732
  viewBox: "0 0 24 24",
@@ -809,12 +764,12 @@ const ze = Ae.extend({
809
764
  fill: "currentColor"
810
765
  }, null)]);
811
766
  }
812
- }), n1 = /* @__PURE__ */ c({
767
+ }), nt = /* @__PURE__ */ c({
813
768
  name: "ListOrderedIcon",
814
769
  setup(t, {
815
770
  attrs: l
816
771
  }) {
817
- return () => e("svg", k({
772
+ return () => e("svg", b({
818
773
  width: "24",
819
774
  height: "24",
820
775
  viewBox: "0 0 24 24",
@@ -852,12 +807,12 @@ const ze = Ae.extend({
852
807
  fill: "currentColor"
853
808
  }, null)]);
854
809
  }
855
- }), o1 = /* @__PURE__ */ c({
810
+ }), ot = /* @__PURE__ */ c({
856
811
  name: "ListTodoIcon",
857
812
  setup(t, {
858
813
  attrs: l
859
814
  }) {
860
- return () => e("svg", k({
815
+ return () => e("svg", b({
861
816
  width: "24",
862
817
  height: "24",
863
818
  viewBox: "0 0 24 24",
@@ -890,61 +845,75 @@ const ze = Ae.extend({
890
845
  fill: "currentColor"
891
846
  }, null)]);
892
847
  }
893
- }), i1 = /* @__PURE__ */ c({
848
+ }), it = /* @__PURE__ */ c({
894
849
  name: "ListButton",
895
850
  setup() {
896
- const t = B("editor");
897
- return () => e("div", null, [e(b, {
898
- icon: l1,
851
+ const t = H("editor");
852
+ return () => e("div", null, [e(w, {
853
+ icon: lt,
899
854
  tooltip: "无序列表",
900
855
  isActive: t?.value?.isActive("bulletList"),
901
856
  onClick: () => t?.value?.chain().focus().toggleBulletList().run()
902
- }, null), e(b, {
903
- icon: n1,
857
+ }, null), e(w, {
858
+ icon: nt,
904
859
  tooltip: "有序列表",
905
860
  isActive: t?.value?.isActive("orderedList"),
906
861
  onClick: () => t?.value?.chain().focus().toggleOrderedList().run()
907
- }, null), e(b, {
908
- icon: o1,
862
+ }, null), e(w, {
863
+ icon: ot,
909
864
  tooltip: "任务列表",
910
865
  isActive: t?.value?.isActive("taskList"),
911
866
  onClick: () => t?.value?.chain().focus().toggleTaskList().run()
912
867
  }, null)]);
913
868
  }
914
- }), u1 = /* @__PURE__ */ c({
915
- name: "ImagePlusIcon",
869
+ }), Xt = {
870
+ name: "list",
871
+ install: () => ({ extensions: [] }),
872
+ toolbarComponent: it
873
+ }, rt = /* @__PURE__ */ c({
874
+ name: "CodeBlockIcon",
916
875
  setup(t, {
917
876
  attrs: l
918
877
  }) {
919
- return () => e("svg", k({
878
+ return () => e("svg", b({
920
879
  width: "24",
921
880
  height: "24",
922
881
  viewBox: "0 0 24 24",
923
- fill: "currentColor",
882
+ fill: "none",
883
+ stroke: "currentColor",
884
+ "stroke-width": "2",
885
+ "stroke-linecap": "round",
886
+ "stroke-linejoin": "round",
924
887
  xmlns: "http://www.w3.org/2000/svg"
925
- }, l), [e("path", {
926
- "fill-rule": "evenodd",
927
- "clip-rule": "evenodd",
928
- d: "M20 2C20 1.44772 19.5523 1 19 1C18.4477 1 18 1.44772 18 2V4H16C15.4477 4 15 4.44772 15 5C15 5.55228 15.4477 6 16 6H18V8C18 8.55228 18.4477 9 19 9C19.5523 9 20 8.55228 20 8V6H22C22.5523 6 23 5.55228 23 5C23 4.44772 22.5523 4 22 4H20V2ZM5 4C4.73478 4 4.48043 4.10536 4.29289 4.29289C4.10536 4.48043 4 4.73478 4 5V19C4 19.2652 4.10536 19.5196 4.29289 19.7071C4.48043 19.8946 4.73478 20 5 20H5.58579L14.379 11.2068C14.9416 10.6444 15.7045 10.3284 16.5 10.3284C17.2955 10.3284 18.0584 10.6444 18.621 11.2068L20 12.5858V12C20 11.4477 20.4477 11 21 11C21.5523 11 22 11.4477 22 12V14.998C22 14.9994 22 15.0007 22 15.002V19C22 19.7957 21.6839 20.5587 21.1213 21.1213C20.5587 21.6839 19.7957 22 19 22H6.00219C6.00073 22 5.99927 22 5.99781 22H5C4.20435 22 3.44129 21.6839 2.87868 21.1213C2.31607 20.5587 2 19.7957 2 19V5C2 4.20435 2.31607 3.44129 2.87868 2.87868C3.44129 2.31607 4.20435 2 5 2H12C12.5523 2 13 2.44772 13 3C13 3.55228 12.5523 4 12 4H5ZM8.41422 20H19C19.2652 20 19.5196 19.8946 19.7071 19.7071C19.8946 19.5196 20 19.2652 20 19V15.4142L17.207 12.6212C17.0195 12.4338 16.7651 12.3284 16.5 12.3284C16.2349 12.3284 15.9806 12.4337 15.7931 12.6211L8.41422 20ZM6.87868 6.87868C7.44129 6.31607 8.20435 6 9 6C9.79565 6 10.5587 6.31607 11.1213 6.87868C11.6839 7.44129 12 8.20435 12 9C12 9.79565 11.6839 10.5587 11.1213 11.1213C10.5587 11.6839 9.79565 12 9 12C8.20435 12 7.44129 11.6839 6.87868 11.1213C6.31607 10.5587 6 9.79565 6 9C6 8.20435 6.31607 7.44129 6.87868 6.87868ZM9 8C8.73478 8 8.48043 8.10536 8.29289 8.29289C8.10536 8.48043 8 8.73478 8 9C8 9.26522 8.10536 9.51957 8.29289 9.70711C8.48043 9.89464 8.73478 10 9 10C9.26522 10 9.51957 9.89464 9.70711 9.70711C9.89464 9.51957 10 9.26522 10 9C10 8.73478 9.89464 8.48043 9.70711 8.29289C9.51957 8.10536 9.26522 8 9 8Z",
929
- fill: "currentColor"
888
+ }, l), [e("polyline", {
889
+ points: "16 18 22 12 16 6"
890
+ }, null), e("polyline", {
891
+ points: "8 6 2 12 8 18"
930
892
  }, null)]);
931
893
  }
932
- }), r1 = /* @__PURE__ */ c({
933
- name: "ImageButton",
894
+ }), ut = /* @__PURE__ */ c({
895
+ name: "CodeBlockButton",
934
896
  setup() {
935
- const t = B("editor");
936
- return () => e("div", null, [e(b, {
937
- icon: u1,
938
- tooltip: "图片",
939
- onClick: () => t?.value?.commands.setImageUploadNode()
940
- }, null)]);
897
+ const t = H("editor");
898
+ return () => e(w, {
899
+ icon: rt,
900
+ tooltip: "代码块",
901
+ isActive: t?.value?.isActive("codeBlock"),
902
+ onClick: () => t?.value?.chain().focus().toggleCodeBlock().run()
903
+ }, null);
941
904
  }
942
- }), a1 = /* @__PURE__ */ c({
905
+ }), at = Te(Ve), Qt = {
906
+ name: "code-block",
907
+ install: () => ({
908
+ extensions: [Fe.configure({ lowlight: at, defaultLanguage: "plaintext" })]
909
+ }),
910
+ toolbarComponent: ut
911
+ }, st = /* @__PURE__ */ c({
943
912
  name: "TableIcon",
944
913
  setup(t, {
945
914
  attrs: l
946
915
  }) {
947
- return () => e("svg", k({
916
+ return () => e("svg", b({
948
917
  width: "24",
949
918
  height: "24",
950
919
  viewBox: "0 0 24 24",
@@ -957,30 +926,30 @@ const ze = Ae.extend({
957
926
  fill: "currentColor"
958
927
  }, null)]);
959
928
  }
960
- }), s1 = 8, c1 = 8, d1 = /* @__PURE__ */ c({
929
+ }), ct = 8, dt = 8, pt = /* @__PURE__ */ c({
961
930
  name: "TableButton",
962
931
  setup() {
963
- const t = B("editor"), l = H(!1), n = H(0), o = H(0), u = (g, r) => {
964
- n.value = g, o.value = r;
965
- }, s = () => {
932
+ const t = H("editor"), l = k(!1), n = k(0), o = k(0), i = (p, s) => {
933
+ n.value = p, o.value = s;
934
+ }, r = () => {
966
935
  n.value = 0, o.value = 0;
967
- }, f = (g, r) => {
936
+ }, v = (p, s) => {
968
937
  t?.value?.chain().focus().insertTable({
969
- rows: r,
970
- cols: g,
938
+ rows: s,
939
+ cols: p,
971
940
  withHeaderRow: !0
972
941
  }).run(), l.value = !1;
973
942
  };
974
943
  return () => e(J, {
975
944
  visible: l.value,
976
- "onUpdate:visible": (g) => l.value = g,
945
+ "onUpdate:visible": (p) => l.value = p,
977
946
  trigger: "click",
978
947
  placement: "bottom-start",
979
948
  popperClass: "table-picker-popper",
980
949
  width: "auto",
981
950
  showArrow: !1
982
951
  }, {
983
- reference: () => e("span", null, [e(R, {
952
+ reference: () => e("span", null, [e(D, {
984
953
  content: "表格",
985
954
  showArrow: !1,
986
955
  offset: 6,
@@ -992,7 +961,7 @@ const ze = Ae.extend({
992
961
  "is-active": l.value
993
962
  }]
994
963
  }, {
995
- default: () => [e(a1, {
964
+ default: () => [e(st, {
996
965
  class: "tiptap-button-icon"
997
966
  }, null)]
998
967
  })]
@@ -1001,21 +970,21 @@ const ze = Ae.extend({
1001
970
  class: "table-picker"
1002
971
  }, [e("div", {
1003
972
  class: "table-picker-grid",
1004
- onMouseleave: s
973
+ onMouseleave: r
1005
974
  }, [Array.from({
1006
- length: c1
1007
- }, (g, r) => e("div", {
1008
- key: r,
975
+ length: dt
976
+ }, (p, s) => e("div", {
977
+ key: s,
1009
978
  class: "table-picker-row"
1010
979
  }, [Array.from({
1011
- length: s1
1012
- }, (C, i) => e("div", {
1013
- key: i,
980
+ length: ct
981
+ }, (y, u) => e("div", {
982
+ key: u,
1014
983
  class: ["table-picker-cell", {
1015
- "is-active": i < n.value && r < o.value
984
+ "is-active": u < n.value && s < o.value
1016
985
  }],
1017
- onMouseenter: () => u(i + 1, r + 1),
1018
- onClick: () => f(i + 1, r + 1)
986
+ onMouseenter: () => i(u + 1, s + 1),
987
+ onClick: () => v(u + 1, s + 1)
1019
988
  }, null))]))]), e("div", {
1020
989
  class: "table-picker-footer"
1021
990
  }, [e("div", {
@@ -1028,7 +997,7 @@ const ze = Ae.extend({
1028
997
  });
1029
998
  }
1030
999
  });
1031
- function p1(t) {
1000
+ function Ct(t) {
1032
1001
  let l = t.nodeType === Node.TEXT_NODE ? t.parentElement : t;
1033
1002
  for (; l && l instanceof HTMLElement; ) {
1034
1003
  if (l.tagName === "TD" || l.tagName === "TH") return l;
@@ -1036,24 +1005,24 @@ function p1(t) {
1036
1005
  }
1037
1006
  return null;
1038
1007
  }
1039
- function C1(t) {
1008
+ function vt(t) {
1040
1009
  if (!t.isActive("tableCell") && !t.isActive("tableHeader")) return null;
1041
1010
  const {
1042
1011
  node: l
1043
- } = t.view.domAtPos(t.state.selection.from), n = p1(l);
1012
+ } = t.view.domAtPos(t.state.selection.from), n = Ct(l);
1044
1013
  if (!n) return null;
1045
- const o = n.parentElement, u = o.parentElement, s = n.closest("table");
1046
- if (!s) return null;
1047
- const f = Array.from(o.children).indexOf(n), g = Array.from(u.children).indexOf(o), r = o.children.length, C = u.children.length, i = n.getBoundingClientRect(), p = s.getBoundingClientRect(), w = t.view.dom.closest(".tiptap-editor").getBoundingClientRect();
1014
+ const o = n.parentElement, i = o.parentElement, r = n.closest("table");
1015
+ if (!r) return null;
1016
+ const v = Array.from(o.children).indexOf(n), p = Array.from(i.children).indexOf(o), s = o.children.length, y = i.children.length, u = n.getBoundingClientRect(), C = r.getBoundingClientRect(), g = t.view.dom.closest(".tiptap-editor").getBoundingClientRect();
1048
1017
  return {
1049
1018
  cell: n,
1050
- colIndex: f,
1051
- rowIndex: g,
1052
- totalCols: r,
1053
- totalRows: C,
1054
- cellRect: i,
1055
- tableRect: p,
1056
- editorRect: w
1019
+ colIndex: v,
1020
+ rowIndex: p,
1021
+ totalCols: s,
1022
+ totalRows: y,
1023
+ cellRect: u,
1024
+ tableRect: C,
1025
+ editorRect: g
1057
1026
  };
1058
1027
  }
1059
1028
  function K(t) {
@@ -1061,81 +1030,81 @@ function K(t) {
1061
1030
  state: l
1062
1031
  } = t, n = l.selection.from;
1063
1032
  let o = null;
1064
- return l.doc.nodesBetween(0, l.doc.content.size, (u, s) => {
1065
- if (u.type.name === "table" && s <= n && n <= s + u.nodeSize)
1033
+ return l.doc.nodesBetween(0, l.doc.content.size, (i, r) => {
1034
+ if (i.type.name === "table" && r <= n && n <= r + i.nodeSize)
1066
1035
  return o = {
1067
- node: u,
1068
- pos: s
1036
+ node: i,
1037
+ pos: r
1069
1038
  }, !1;
1070
1039
  }), o;
1071
1040
  }
1072
- const v1 = /* @__PURE__ */ c({
1041
+ const ft = /* @__PURE__ */ c({
1073
1042
  name: "TableControls",
1074
1043
  setup() {
1075
- const t = B("editor"), l = B("readonly"), n = H(null), o = H(null);
1076
- function u() {
1077
- const i = t?.value;
1078
- if (o.value && (o.value.classList.remove("tcc-cell-focused"), o.value = null), !i) {
1044
+ const t = H("editor"), l = H("readonly"), n = k(null), o = k(null);
1045
+ function i() {
1046
+ const u = t?.value;
1047
+ if (o.value && (o.value.classList.remove("tcc-cell-focused"), o.value = null), !u) {
1079
1048
  n.value = null;
1080
1049
  return;
1081
1050
  }
1082
- const p = C1(i);
1083
- n.value = p, p && (p.cell.classList.add("tcc-cell-focused"), o.value = p.cell);
1051
+ const C = vt(u);
1052
+ n.value = C, C && (C.cell.classList.add("tcc-cell-focused"), o.value = C.cell);
1084
1053
  }
1085
- G((i) => {
1086
- const p = t?.value;
1087
- p && (p.on("selectionUpdate", u), p.on("transaction", u), i(() => {
1088
- p.off("selectionUpdate", u), p.off("transaction", u), o.value && (o.value.classList.remove("tcc-cell-focused"), o.value = null);
1054
+ G((u) => {
1055
+ const C = t?.value;
1056
+ C && (C.on("selectionUpdate", i), C.on("transaction", i), u(() => {
1057
+ C.off("selectionUpdate", i), C.off("transaction", i), o.value && (o.value.classList.remove("tcc-cell-focused"), o.value = null);
1089
1058
  }));
1090
1059
  });
1091
- function s(i) {
1092
- const p = t?.value;
1093
- if (!p || !n.value) return;
1060
+ function r(u) {
1061
+ const C = t?.value;
1062
+ if (!C || !n.value) return;
1094
1063
  const {
1095
- colIndex: w,
1064
+ colIndex: g,
1096
1065
  totalCols: I
1097
- } = n.value, x = i === "left" ? w - 1 : w + 1;
1066
+ } = n.value, x = u === "left" ? g - 1 : g + 1;
1098
1067
  if (x < 0 || x >= I) return;
1099
- const a = K(p);
1068
+ const a = K(C);
1100
1069
  if (!a) return;
1101
1070
  const {
1102
1071
  node: d,
1103
- pos: v
1072
+ pos: f
1104
1073
  } = a, h = [];
1105
1074
  d.forEach((L) => {
1106
1075
  if (L.type.name !== "tableRow") {
1107
1076
  h.push(L);
1108
1077
  return;
1109
1078
  }
1110
- const y = [];
1111
- L.forEach((U) => y.push(U));
1112
- const S = y[w];
1113
- y[w] = y[x], y[x] = S, h.push(L.type.create(L.attrs, y, L.marks));
1079
+ const A = [];
1080
+ L.forEach((U) => A.push(U));
1081
+ const S = A[g];
1082
+ A[g] = A[x], A[x] = S, h.push(L.type.create(L.attrs, A, L.marks));
1114
1083
  });
1115
- const A = d.type.create(d.attrs, h, d.marks), T = p.state.tr.replaceWith(v, v + d.nodeSize, A);
1116
- p.view.dispatch(T);
1084
+ const B = d.type.create(d.attrs, h, d.marks), V = C.state.tr.replaceWith(f, f + d.nodeSize, B);
1085
+ C.view.dispatch(V);
1117
1086
  }
1118
- function f(i) {
1119
- const p = t?.value;
1120
- if (!p || !n.value) return;
1087
+ function v(u) {
1088
+ const C = t?.value;
1089
+ if (!C || !n.value) return;
1121
1090
  const {
1122
- rowIndex: w,
1091
+ rowIndex: g,
1123
1092
  totalRows: I
1124
- } = n.value, x = i === "up" ? w - 1 : w + 1;
1093
+ } = n.value, x = u === "up" ? g - 1 : g + 1;
1125
1094
  if (x < 0 || x >= I) return;
1126
- const a = K(p);
1095
+ const a = K(C);
1127
1096
  if (!a) return;
1128
1097
  const {
1129
1098
  node: d,
1130
- pos: v
1099
+ pos: f
1131
1100
  } = a, h = [];
1132
- d.forEach((y) => h.push(y));
1133
- const A = h[w];
1134
- h[w] = h[x], h[x] = A;
1135
- const T = d.type.create(d.attrs, h, d.marks), L = p.state.tr.replaceWith(v, v + d.nodeSize, T);
1136
- p.view.dispatch(L);
1101
+ d.forEach((A) => h.push(A));
1102
+ const B = h[g];
1103
+ h[g] = h[x], h[x] = B;
1104
+ const V = d.type.create(d.attrs, h, d.marks), L = C.state.tr.replaceWith(f, f + d.nodeSize, V);
1105
+ C.view.dispatch(L);
1137
1106
  }
1138
- const g = () => e("svg", {
1107
+ const p = () => e("svg", {
1139
1108
  width: "16",
1140
1109
  height: "4",
1141
1110
  viewBox: "0 0 16 4",
@@ -1152,7 +1121,7 @@ const v1 = /* @__PURE__ */ c({
1152
1121
  cx: "14",
1153
1122
  cy: "2",
1154
1123
  r: "1.5"
1155
- }, null)]), r = () => e("svg", {
1124
+ }, null)]), s = () => e("svg", {
1156
1125
  width: "4",
1157
1126
  height: "16",
1158
1127
  viewBox: "0 0 4 16",
@@ -1169,7 +1138,7 @@ const v1 = /* @__PURE__ */ c({
1169
1138
  cx: "2",
1170
1139
  cy: "14",
1171
1140
  r: "1.5"
1172
- }, null)]), C = () => e("svg", {
1141
+ }, null)]), y = () => e("svg", {
1173
1142
  width: "10",
1174
1143
  height: "10",
1175
1144
  viewBox: "0 0 10 10",
@@ -1182,33 +1151,33 @@ const v1 = /* @__PURE__ */ c({
1182
1151
  }, null)]);
1183
1152
  return () => {
1184
1153
  if (l?.value) return null;
1185
- const i = n.value;
1186
- if (!i) return null;
1154
+ const u = n.value;
1155
+ if (!u) return null;
1187
1156
  const {
1188
- colIndex: p,
1189
- rowIndex: w,
1157
+ colIndex: C,
1158
+ rowIndex: g,
1190
1159
  totalCols: I,
1191
1160
  totalRows: x,
1192
1161
  cellRect: a,
1193
1162
  tableRect: d,
1194
- editorRect: v
1195
- } = i, h = d.top - v.top, A = d.left - v.left, T = d.right - v.left, L = d.bottom - v.top, y = a.left - v.left, S = a.top - v.top, U = a.width, O = a.height, ie = {
1163
+ editorRect: f
1164
+ } = u, h = d.top - f.top, B = d.left - f.left, V = d.right - f.left, L = d.bottom - f.top, A = a.left - f.left, S = a.top - f.top, U = a.width, O = a.height, ie = {
1196
1165
  position: "absolute",
1197
1166
  top: `${h - 20}px`,
1198
- left: `${y + U / 2 - 18}px`
1199
- }, ue = {
1167
+ left: `${A + U / 2 - 18}px`
1168
+ }, re = {
1200
1169
  position: "absolute",
1201
1170
  top: `${S + O / 2 - 18}px`,
1202
- left: `${A - 20}px`
1203
- }, re = {
1171
+ left: `${B - 20}px`
1172
+ }, ue = {
1204
1173
  position: "absolute",
1205
1174
  top: `${S + O / 2 - 12}px`,
1206
- left: `${T + 6}px`
1175
+ left: `${V + 6}px`
1207
1176
  }, ae = {
1208
1177
  position: "absolute",
1209
1178
  top: `${L + 6}px`,
1210
- left: `${y + U / 2 - 12}px`
1211
- }, se = p === 0, $ = p === I - 1, ce = w === 0, N = w === x - 1, F = t?.value;
1179
+ left: `${A + U / 2 - 12}px`
1180
+ }, se = C === 0, $ = C === I - 1, ce = g === 0, N = g === x - 1, F = t?.value;
1212
1181
  return e("div", {
1213
1182
  class: "table-cell-controls"
1214
1183
  }, [e(j, {
@@ -1216,12 +1185,12 @@ const v1 = /* @__PURE__ */ c({
1216
1185
  placement: "bottom",
1217
1186
  style: ie,
1218
1187
  onCommand: (M) => {
1219
- M === "move-left" ? s("left") : M === "move-right" ? s("right") : M === "insert-left" ? F?.chain().focus().addColumnBefore().run() : M === "insert-right" ? F?.chain().focus().addColumnAfter().run() : M === "delete" && F?.chain().focus().deleteColumn().run();
1188
+ M === "move-left" ? r("left") : M === "move-right" ? r("right") : M === "insert-left" ? F?.chain().focus().addColumnBefore().run() : M === "insert-right" ? F?.chain().focus().addColumnAfter().run() : M === "delete" && F?.chain().focus().deleteColumn().run();
1220
1189
  }
1221
1190
  }, {
1222
1191
  default: () => [e("button", {
1223
1192
  class: "tcc-btn tcc-btn--col"
1224
- }, [e(g, null, null)])],
1193
+ }, [e(p, null, null)])],
1225
1194
  dropdown: () => e(W, null, {
1226
1195
  default: () => [e(E, {
1227
1196
  command: "move-left",
@@ -1251,14 +1220,14 @@ const v1 = /* @__PURE__ */ c({
1251
1220
  }), e(j, {
1252
1221
  trigger: "click",
1253
1222
  placement: "right",
1254
- style: ue,
1223
+ style: re,
1255
1224
  onCommand: (M) => {
1256
- M === "move-up" ? f("up") : M === "move-down" ? f("down") : M === "insert-above" ? F?.chain().focus().addRowBefore().run() : M === "insert-below" ? F?.chain().focus().addRowAfter().run() : M === "delete" && F?.chain().focus().deleteRow().run();
1225
+ M === "move-up" ? v("up") : M === "move-down" ? v("down") : M === "insert-above" ? F?.chain().focus().addRowBefore().run() : M === "insert-below" ? F?.chain().focus().addRowAfter().run() : M === "delete" && F?.chain().focus().deleteRow().run();
1257
1226
  }
1258
1227
  }, {
1259
1228
  default: () => [e("button", {
1260
1229
  class: "tcc-btn tcc-btn--row"
1261
- }, [e(r, null, null)])],
1230
+ }, [e(s, null, null)])],
1262
1231
  dropdown: () => e(W, null, {
1263
1232
  default: () => [e(E, {
1264
1233
  command: "move-up",
@@ -1287,21 +1256,404 @@ const v1 = /* @__PURE__ */ c({
1287
1256
  })
1288
1257
  }), $ && e("button", {
1289
1258
  class: "tcc-btn tcc-btn--add",
1290
- style: re,
1259
+ style: ue,
1291
1260
  onClick: () => F?.chain().focus().addColumnAfter().run()
1292
- }, [e(C, null, null)]), N && e("button", {
1261
+ }, [e(y, null, null)]), N && e("button", {
1293
1262
  class: "tcc-btn tcc-btn--add",
1294
1263
  style: ae,
1295
1264
  onClick: () => F?.chain().focus().addRowAfter().run()
1296
- }, [e(C, null, null)])]);
1265
+ }, [e(y, null, null)])]);
1266
+ };
1267
+ }
1268
+ }), Yt = {
1269
+ name: "table",
1270
+ install: () => ({
1271
+ extensions: [Se.configure({ resizable: !0 }), Ze, De, Re],
1272
+ controlComponent: ft
1273
+ }),
1274
+ toolbarComponent: pt
1275
+ }, ht = /* @__PURE__ */ c({
1276
+ name: "MathIcon",
1277
+ setup(t, {
1278
+ attrs: l
1279
+ }) {
1280
+ return () => e("svg", b({
1281
+ width: "24",
1282
+ height: "24",
1283
+ viewBox: "0 0 24 24",
1284
+ fill: "currentColor",
1285
+ xmlns: "http://www.w3.org/2000/svg"
1286
+ }, l), [e("path", {
1287
+ "fill-rule": "evenodd",
1288
+ "clip-rule": "evenodd",
1289
+ d: "M9 4.8c.1-.5.5-.8 1-.8h10a1 1 0 1 1 0 2h-9.2L8.3 19.2a1 1 0 0 1-1.7.4l-3.4-4.2a1 1 0 0 1 1.6-1.2l2 2.5L9 4.8Zm9.7 5.5c.4.4.4 1 0 1.4L17 13.5l1.8 1.8a1 1 0 1 1-1.4 1.4L15.5 15l-1.8 1.8a1 1 0 0 1-1.4-1.4l1.8-1.8-1.8-1.8a1 1 0 0 1 1.4-1.4l1.8 1.8 1.8-1.8a1 1 0 0 1 1.4 0Z",
1290
+ fill: "currentColor"
1291
+ }, null)]);
1292
+ }
1293
+ }), mt = /* @__PURE__ */ c({
1294
+ name: "MathButton",
1295
+ setup() {
1296
+ const t = H("editor"), l = H("openMathDialog");
1297
+ return () => e(w, {
1298
+ icon: ht,
1299
+ tooltip: "数学公式",
1300
+ isActive: t?.value?.isActive("inlineMath") || t?.value?.isActive("blockMath"),
1301
+ onClick: () => l?.()
1302
+ }, null);
1303
+ }
1304
+ }), gt = /* @__PURE__ */ c({
1305
+ name: "MathEditDialog",
1306
+ props: {
1307
+ visible: {
1308
+ type: Boolean,
1309
+ required: !0
1310
+ },
1311
+ latex: {
1312
+ type: String,
1313
+ required: !0
1314
+ },
1315
+ pos: {
1316
+ type: Number,
1317
+ default: null
1318
+ },
1319
+ type: {
1320
+ type: String,
1321
+ required: !0
1322
+ }
1323
+ },
1324
+ emits: ["update:visible"],
1325
+ setup(t, {
1326
+ emit: l
1327
+ }) {
1328
+ const n = H("editor"), o = k(""), i = k("inline");
1329
+ R(() => t.latex, (s) => {
1330
+ o.value = s;
1331
+ }, {
1332
+ immediate: !0
1333
+ }), R(() => t.type, (s) => {
1334
+ i.value = s;
1335
+ }, {
1336
+ immediate: !0
1337
+ });
1338
+ const r = T(() => t.pos === null), v = T(() => o.value.trim() ? _e.renderToString(o.value, {
1339
+ displayMode: i.value === "block",
1340
+ throwOnError: !1
1341
+ }) : ""), p = () => {
1342
+ const s = n?.value;
1343
+ if (!(!s || !o.value.trim())) {
1344
+ if (r.value)
1345
+ i.value === "inline" ? s.chain().focus().insertInlineMath({
1346
+ latex: o.value
1347
+ }).run() : s.chain().focus().insertBlockMath({
1348
+ latex: o.value
1349
+ }).run();
1350
+ else if (i.value === t.type)
1351
+ t.type === "inline" ? s.commands.updateInlineMath({
1352
+ latex: o.value,
1353
+ pos: t.pos
1354
+ }) : s.commands.updateBlockMath({
1355
+ latex: o.value,
1356
+ pos: t.pos
1357
+ });
1358
+ else {
1359
+ const y = t.pos;
1360
+ t.type === "inline" ? s.chain().focus().deleteInlineMath({
1361
+ pos: y
1362
+ }).insertBlockMath({
1363
+ latex: o.value
1364
+ }).run() : s.chain().focus().deleteBlockMath({
1365
+ pos: y
1366
+ }).insertInlineMath({
1367
+ latex: o.value
1368
+ }).run();
1369
+ }
1370
+ l("update:visible", !1);
1371
+ }
1372
+ };
1373
+ return () => e(Be, {
1374
+ modelValue: t.visible,
1375
+ title: r.value ? "插入数学公式" : "编辑数学公式",
1376
+ width: "520px",
1377
+ "onUpdate:modelValue": (s) => l("update:visible", s)
1378
+ }, {
1379
+ default: () => [e("div", {
1380
+ class: "math-dialog"
1381
+ }, [e(ye, {
1382
+ modelValue: i.value,
1383
+ "onUpdate:modelValue": (s) => {
1384
+ i.value = s;
1385
+ }
1386
+ }, {
1387
+ default: () => [e(q, {
1388
+ value: "inline"
1389
+ }, {
1390
+ default: () => [m("行内公式")]
1391
+ }), e(q, {
1392
+ value: "block"
1393
+ }, {
1394
+ default: () => [m("块级公式")]
1395
+ })]
1396
+ }), e(X, {
1397
+ modelValue: o.value,
1398
+ type: "textarea",
1399
+ rows: 3,
1400
+ placeholder: "请输入 LaTeX 公式,例如:E=mc^2",
1401
+ "onUpdate:modelValue": (s) => {
1402
+ o.value = s;
1403
+ }
1404
+ }, null), e("div", {
1405
+ class: ["math-preview", {
1406
+ "math-preview--empty": !v.value
1407
+ }]
1408
+ }, [v.value ? e("div", {
1409
+ innerHTML: v.value
1410
+ }, null) : e("span", {
1411
+ class: "math-preview__placeholder"
1412
+ }, [m("预览将在此处显示")])])])],
1413
+ footer: () => e(de, null, [e(Z, {
1414
+ onClick: () => l("update:visible", !1)
1415
+ }, {
1416
+ default: () => [m("取消")]
1417
+ }), e(Z, {
1418
+ type: "primary",
1419
+ disabled: !o.value.trim(),
1420
+ onClick: p
1421
+ }, {
1422
+ default: () => [m("确认")]
1423
+ })])
1424
+ });
1425
+ }
1426
+ }), e1 = {
1427
+ name: "math",
1428
+ toolbarComponent: mt,
1429
+ install(t) {
1430
+ const l = k(!1), n = k(""), o = k(null), i = k("inline"), r = (p = {}) => {
1431
+ t.readonly.value || (n.value = p.latex ?? "", o.value = p.pos ?? null, i.value = p.type ?? "inline", l.value = !0);
1432
+ };
1433
+ t.provide("openMathDialog", r);
1434
+ const v = c({
1435
+ name: "MathEditDialogWrapper",
1436
+ setup: () => () => pe(gt, {
1437
+ visible: l.value,
1438
+ latex: n.value,
1439
+ pos: o.value,
1440
+ type: i.value,
1441
+ "onUpdate:visible": (p) => {
1442
+ l.value = p;
1443
+ }
1444
+ })
1445
+ });
1446
+ return {
1447
+ extensions: [
1448
+ Ue.configure({
1449
+ inlineOptions: {
1450
+ onClick: (p, s) => r({ latex: p.attrs.latex, pos: s, type: "inline" })
1451
+ },
1452
+ blockOptions: {
1453
+ onClick: (p, s) => r({ latex: p.attrs.latex, pos: s, type: "block" })
1454
+ }
1455
+ })
1456
+ ],
1457
+ controlComponent: v
1458
+ };
1459
+ }
1460
+ }, wt = /* @__PURE__ */ c({
1461
+ name: "ImageUploadView",
1462
+ props: he,
1463
+ setup(t) {
1464
+ const l = T(() => t.node.attrs.accept), n = T(() => t.node.attrs.limit), o = T(() => t.node.attrs.maxSize), i = k([]), r = k(), v = k(!1), p = async (a) => {
1465
+ if (o.value > 0 && a.size > o.value)
1466
+ return t.extension.options.onError?.(new Error(`文件大小超出限制 ${o.value / 1024 / 1024}MB`)), null;
1467
+ const d = crypto.randomUUID();
1468
+ i.value.push({
1469
+ id: d,
1470
+ file: a,
1471
+ progress: 0,
1472
+ status: "uploading"
1473
+ });
1474
+ try {
1475
+ const f = t.extension.options.upload;
1476
+ if (!f) throw new Error("未配置 upload 函数");
1477
+ const h = await f(a);
1478
+ if (!h) throw new Error("上传失败:未返回 URL");
1479
+ const B = i.value.find((V) => V.id === d);
1480
+ return B && (B.status = "success", B.progress = 100), t.extension.options.onSuccess?.(h), h;
1481
+ } catch (f) {
1482
+ const h = i.value.find((B) => B.id === d);
1483
+ return h && (h.status = "error", h.progress = 0), t.extension.options.onError?.(f instanceof Error ? f : new Error("上传失败")), null;
1484
+ }
1485
+ }, s = async (a) => {
1486
+ if (!a.length) return;
1487
+ if (a.length > n.value) {
1488
+ t.extension.options.onError?.(new Error(`最多上传 ${n.value} 个文件`));
1489
+ return;
1490
+ }
1491
+ const d = (await Promise.all(a.map(p))).filter((f) => !!f);
1492
+ if (d.length > 0) {
1493
+ const f = t.getPos();
1494
+ if (typeof f != "number") return;
1495
+ const h = d.map((B) => ({
1496
+ type: "image",
1497
+ attrs: {
1498
+ src: B
1499
+ }
1500
+ }));
1501
+ t.editor.chain().focus().deleteRange({
1502
+ from: f,
1503
+ to: f + t.node.nodeSize
1504
+ }).insertContentAt(f, h).run();
1505
+ }
1506
+ }, y = () => {
1507
+ i.value.length === 0 && r.value && (r.value.value = "", r.value.click());
1508
+ }, u = (a) => {
1509
+ const d = a.target.files;
1510
+ d && s(Array.from(d));
1511
+ }, C = (a) => {
1512
+ a.preventDefault(), v.value = !0;
1513
+ }, g = (a) => {
1514
+ a.currentTarget.contains(a.relatedTarget) || (v.value = !1);
1515
+ }, I = (a) => {
1516
+ a.preventDefault(), v.value = !1;
1517
+ const d = Array.from(a.dataTransfer?.files ?? []);
1518
+ d.length && s(d);
1519
+ }, x = (a) => {
1520
+ i.value = i.value.filter((d) => d.id !== a);
1521
+ };
1522
+ return () => e(me, {
1523
+ class: "tiptap-image-upload"
1524
+ }, {
1525
+ default: () => [e("div", {
1526
+ onClick: y
1527
+ }, [i.value.length ? e("div", {
1528
+ class: "tiptap-image-upload-previews"
1529
+ }, [i.value.map((a) => e("div", {
1530
+ key: a.id,
1531
+ class: "tiptap-image-upload-preview"
1532
+ }, [a.status === "uploading" && e("div", {
1533
+ class: "tiptap-image-upload-progress",
1534
+ style: {
1535
+ width: `${a.progress}%`
1536
+ }
1537
+ }, null), e("div", {
1538
+ class: "tiptap-image-upload-preview-content"
1539
+ }, [e("span", {
1540
+ class: "tiptap-image-upload-text"
1541
+ }, [a.file.name]), e("span", {
1542
+ class: "tiptap-image-upload-subtext"
1543
+ }, [a.status === "uploading" ? `${a.progress}%` : a.status === "error" ? "上传失败" : "上传成功"]), e("button", {
1544
+ class: "tiptap-image-upload-remove",
1545
+ onClick: (d) => {
1546
+ d.stopPropagation(), x(a.id);
1547
+ }
1548
+ }, [m("×")])])]))]) : e("div", {
1549
+ class: ["tiptap-image-upload-drag-area", {
1550
+ "drag-active": v.value
1551
+ }],
1552
+ onDragover: C,
1553
+ onDragleave: g,
1554
+ onDrop: I
1555
+ }, [e("div", {
1556
+ class: "tiptap-image-upload-content"
1557
+ }, [e("span", {
1558
+ class: "tiptap-image-upload-text"
1559
+ }, [e("em", null, [m("点击上传")]), m(" 或拖拽图片到此处")]), e("span", {
1560
+ class: "tiptap-image-upload-subtext"
1561
+ }, [m("最多 "), n.value, m(" 个文件"), o.value ? `,每个不超过 ${o.value / 1024 / 1024}MB` : ""])])]), e("input", {
1562
+ ref: r,
1563
+ type: "file",
1564
+ accept: l.value,
1565
+ multiple: n.value > 1,
1566
+ onChange: u,
1567
+ onClick: (a) => a.stopPropagation()
1568
+ }, null)])]
1569
+ });
1570
+ }
1571
+ }), bt = Pe.create({
1572
+ name: "imageUpload",
1573
+ group: "block",
1574
+ draggable: !0,
1575
+ selectable: !0,
1576
+ atom: !0,
1577
+ addOptions() {
1578
+ return {
1579
+ type: "image",
1580
+ accept: "image/*",
1581
+ limit: 1,
1582
+ maxSize: 0,
1583
+ upload: (t) => new Promise((l) => {
1584
+ const n = new FileReader();
1585
+ n.onloadend = () => l(n.result), n.readAsDataURL(t);
1586
+ }),
1587
+ onError: void 0,
1588
+ onSuccess: void 0,
1589
+ HTMLAttributes: {}
1590
+ };
1591
+ },
1592
+ addAttributes() {
1593
+ return {
1594
+ accept: {
1595
+ default: this.options.accept
1596
+ },
1597
+ limit: {
1598
+ default: this.options.limit
1599
+ },
1600
+ maxSize: {
1601
+ default: this.options.maxSize
1602
+ }
1603
+ };
1604
+ },
1605
+ parseHTML() {
1606
+ return [{
1607
+ tag: 'div[data-type="image-upload"]'
1608
+ }];
1609
+ },
1610
+ renderHTML({
1611
+ HTMLAttributes: t
1612
+ }) {
1613
+ return ["div", ze({
1614
+ "data-type": "image-upload"
1615
+ }, t)];
1616
+ },
1617
+ addNodeView() {
1618
+ return ge(wt);
1619
+ },
1620
+ addCommands() {
1621
+ return {
1622
+ setImageUploadNode: () => ({
1623
+ commands: t
1624
+ }) => t.insertContent({
1625
+ type: this.name
1626
+ })
1627
+ };
1628
+ },
1629
+ addKeyboardShortcuts() {
1630
+ return {
1631
+ Enter: ({
1632
+ editor: t
1633
+ }) => {
1634
+ const {
1635
+ selection: l
1636
+ } = t.state, {
1637
+ nodeAfter: n
1638
+ } = l.$from;
1639
+ if (n?.type.name === "imageUpload" && t.isActive("imageUpload")) {
1640
+ const o = t.view.nodeDOM(l.$from.pos);
1641
+ if (o instanceof HTMLElement) {
1642
+ const i = o.firstChild;
1643
+ if (i instanceof HTMLElement)
1644
+ return i.click(), !0;
1645
+ }
1646
+ }
1647
+ return !1;
1648
+ }
1297
1649
  };
1298
1650
  }
1299
- }), f1 = /* @__PURE__ */ c({
1300
- name: "MathIcon",
1651
+ }), xt = /* @__PURE__ */ c({
1652
+ name: "ImagePlusIcon",
1301
1653
  setup(t, {
1302
1654
  attrs: l
1303
1655
  }) {
1304
- return () => e("svg", k({
1656
+ return () => e("svg", b({
1305
1657
  width: "24",
1306
1658
  height: "24",
1307
1659
  viewBox: "0 0 24 24",
@@ -1310,144 +1662,21 @@ const v1 = /* @__PURE__ */ c({
1310
1662
  }, l), [e("path", {
1311
1663
  "fill-rule": "evenodd",
1312
1664
  "clip-rule": "evenodd",
1313
- d: "M9 4.8c.1-.5.5-.8 1-.8h10a1 1 0 1 1 0 2h-9.2L8.3 19.2a1 1 0 0 1-1.7.4l-3.4-4.2a1 1 0 0 1 1.6-1.2l2 2.5L9 4.8Zm9.7 5.5c.4.4.4 1 0 1.4L17 13.5l1.8 1.8a1 1 0 1 1-1.4 1.4L15.5 15l-1.8 1.8a1 1 0 0 1-1.4-1.4l1.8-1.8-1.8-1.8a1 1 0 0 1 1.4-1.4l1.8 1.8 1.8-1.8a1 1 0 0 1 1.4 0Z",
1665
+ d: "M20 2C20 1.44772 19.5523 1 19 1C18.4477 1 18 1.44772 18 2V4H16C15.4477 4 15 4.44772 15 5C15 5.55228 15.4477 6 16 6H18V8C18 8.55228 18.4477 9 19 9C19.5523 9 20 8.55228 20 8V6H22C22.5523 6 23 5.55228 23 5C23 4.44772 22.5523 4 22 4H20V2ZM5 4C4.73478 4 4.48043 4.10536 4.29289 4.29289C4.10536 4.48043 4 4.73478 4 5V19C4 19.2652 4.10536 19.5196 4.29289 19.7071C4.48043 19.8946 4.73478 20 5 20H5.58579L14.379 11.2068C14.9416 10.6444 15.7045 10.3284 16.5 10.3284C17.2955 10.3284 18.0584 10.6444 18.621 11.2068L20 12.5858V12C20 11.4477 20.4477 11 21 11C21.5523 11 22 11.4477 22 12V14.998C22 14.9994 22 15.0007 22 15.002V19C22 19.7957 21.6839 20.5587 21.1213 21.1213C20.5587 21.6839 19.7957 22 19 22H6.00219C6.00073 22 5.99927 22 5.99781 22H5C4.20435 22 3.44129 21.6839 2.87868 21.1213C2.31607 20.5587 2 19.7957 2 19V5C2 4.20435 2.31607 3.44129 2.87868 2.87868C3.44129 2.31607 4.20435 2 5 2H12C12.5523 2 13 2.44772 13 3C13 3.55228 12.5523 4 12 4H5ZM8.41422 20H19C19.2652 20 19.5196 19.8946 19.7071 19.7071C19.8946 19.5196 20 19.2652 20 19V15.4142L17.207 12.6212C17.0195 12.4338 16.7651 12.3284 16.5 12.3284C16.2349 12.3284 15.9806 12.4337 15.7931 12.6211L8.41422 20ZM6.87868 6.87868C7.44129 6.31607 8.20435 6 9 6C9.79565 6 10.5587 6.31607 11.1213 6.87868C11.6839 7.44129 12 8.20435 12 9C12 9.79565 11.6839 10.5587 11.1213 11.1213C10.5587 11.6839 9.79565 12 9 12C8.20435 12 7.44129 11.6839 6.87868 11.1213C6.31607 10.5587 6 9.79565 6 9C6 8.20435 6.31607 7.44129 6.87868 6.87868ZM9 8C8.73478 8 8.48043 8.10536 8.29289 8.29289C8.10536 8.48043 8 8.73478 8 9C8 9.26522 8.10536 9.51957 8.29289 9.70711C8.48043 9.89464 8.73478 10 9 10C9.26522 10 9.51957 9.89464 9.70711 9.70711C9.89464 9.51957 10 9.26522 10 9C10 8.73478 9.89464 8.48043 9.70711 8.29289C9.51957 8.10536 9.26522 8 9 8Z",
1314
1666
  fill: "currentColor"
1315
1667
  }, null)]);
1316
1668
  }
1317
- }), h1 = /* @__PURE__ */ c({
1318
- name: "MathButton",
1669
+ }), kt = /* @__PURE__ */ c({
1670
+ name: "ImageButton",
1319
1671
  setup() {
1320
- const t = B("editor"), l = B("openMathDialog");
1321
- return () => e(b, {
1322
- icon: f1,
1323
- tooltip: "数学公式",
1324
- isActive: t?.value?.isActive("inlineMath") || t?.value?.isActive("blockMath"),
1325
- onClick: () => l?.()
1326
- }, null);
1327
- }
1328
- }), g1 = /* @__PURE__ */ c({
1329
- name: "MathEditDialog",
1330
- props: {
1331
- visible: {
1332
- type: Boolean,
1333
- required: !0
1334
- },
1335
- latex: {
1336
- type: String,
1337
- required: !0
1338
- },
1339
- pos: {
1340
- type: Number,
1341
- default: null
1342
- },
1343
- type: {
1344
- type: String,
1345
- required: !0
1346
- }
1347
- },
1348
- emits: ["update:visible"],
1349
- setup(t, {
1350
- emit: l
1351
- }) {
1352
- const n = B("editor"), o = H(""), u = H("inline");
1353
- D(() => t.latex, (r) => {
1354
- o.value = r;
1355
- }, {
1356
- immediate: !0
1357
- }), D(() => t.type, (r) => {
1358
- u.value = r;
1359
- }, {
1360
- immediate: !0
1361
- });
1362
- const s = V(() => t.pos === null), f = V(() => o.value.trim() ? _e.renderToString(o.value, {
1363
- displayMode: u.value === "block",
1364
- throwOnError: !1
1365
- }) : ""), g = () => {
1366
- const r = n?.value;
1367
- if (!(!r || !o.value.trim())) {
1368
- if (s.value)
1369
- u.value === "inline" ? r.chain().focus().insertInlineMath({
1370
- latex: o.value
1371
- }).run() : r.chain().focus().insertBlockMath({
1372
- latex: o.value
1373
- }).run();
1374
- else if (u.value === t.type)
1375
- t.type === "inline" ? r.commands.updateInlineMath({
1376
- latex: o.value,
1377
- pos: t.pos
1378
- }) : r.commands.updateBlockMath({
1379
- latex: o.value,
1380
- pos: t.pos
1381
- });
1382
- else {
1383
- const C = t.pos;
1384
- t.type === "inline" ? r.chain().focus().deleteInlineMath({
1385
- pos: C
1386
- }).insertBlockMath({
1387
- latex: o.value
1388
- }).run() : r.chain().focus().deleteBlockMath({
1389
- pos: C
1390
- }).insertInlineMath({
1391
- latex: o.value
1392
- }).run();
1393
- }
1394
- l("update:visible", !1);
1395
- }
1396
- };
1397
- return () => e(Se, {
1398
- modelValue: t.visible,
1399
- title: s.value ? "插入数学公式" : "编辑数学公式",
1400
- width: "520px",
1401
- "onUpdate:modelValue": (r) => l("update:visible", r)
1402
- }, {
1403
- default: () => [e("div", {
1404
- class: "math-dialog"
1405
- }, [e(Ue, {
1406
- modelValue: u.value,
1407
- "onUpdate:modelValue": (r) => {
1408
- u.value = r;
1409
- }
1410
- }, {
1411
- default: () => [e(q, {
1412
- value: "inline"
1413
- }, {
1414
- default: () => [m("行内公式")]
1415
- }), e(q, {
1416
- value: "block"
1417
- }, {
1418
- default: () => [m("块级公式")]
1419
- })]
1420
- }), e(X, {
1421
- modelValue: o.value,
1422
- type: "textarea",
1423
- rows: 3,
1424
- placeholder: "请输入 LaTeX 公式,例如:E=mc^2",
1425
- "onUpdate:modelValue": (r) => {
1426
- o.value = r;
1427
- }
1428
- }, null), e("div", {
1429
- class: ["math-preview", {
1430
- "math-preview--empty": !f.value
1431
- }]
1432
- }, [f.value ? e("div", {
1433
- innerHTML: f.value
1434
- }, null) : e("span", {
1435
- class: "math-preview__placeholder"
1436
- }, [m("预览将在此处显示")])])])],
1437
- footer: () => e(de, null, [e(Z, {
1438
- onClick: () => l("update:visible", !1)
1439
- }, {
1440
- default: () => [m("取消")]
1441
- }), e(Z, {
1442
- type: "primary",
1443
- disabled: !o.value.trim(),
1444
- onClick: g
1445
- }, {
1446
- default: () => [m("确认")]
1447
- })])
1448
- });
1672
+ const t = H("editor");
1673
+ return () => e("div", null, [e(w, {
1674
+ icon: xt,
1675
+ tooltip: "图片",
1676
+ onClick: () => t?.value?.commands.setImageUploadNode()
1677
+ }, null)]);
1449
1678
  }
1450
- }), m1 = [{
1679
+ }), Ht = [{
1451
1680
  value: "left",
1452
1681
  title: "居左",
1453
1682
  Icon: le
@@ -1460,12 +1689,12 @@ const v1 = /* @__PURE__ */ c({
1460
1689
  title: "居右",
1461
1690
  Icon: oe
1462
1691
  }], _ = (t) => t.preventDefault();
1463
- function w1(t) {
1692
+ function Bt(t) {
1464
1693
  if (!t.isActive("image")) return null;
1465
1694
  const {
1466
1695
  selection: l
1467
1696
  } = t.state;
1468
- if (!(l instanceof Me) || l.node.type.name !== "image") return null;
1697
+ if (!(l instanceof Ie) || l.node.type.name !== "image") return null;
1469
1698
  const n = l.node;
1470
1699
  return {
1471
1700
  pos: l.from,
@@ -1474,11 +1703,11 @@ function w1(t) {
1474
1703
  align: n.attrs.align ?? "left"
1475
1704
  };
1476
1705
  }
1477
- function b1(t) {
1706
+ function yt(t) {
1478
1707
  const l = t.startsWith("data:") ? "image.png" : t.split("/").pop()?.split("?")[0] || "image.png", n = document.createElement("a");
1479
1708
  n.href = t, n.download = l, document.body.appendChild(n), n.click(), document.body.removeChild(n);
1480
1709
  }
1481
- const k1 = () => e("svg", {
1710
+ const At = () => e("svg", {
1482
1711
  width: "16",
1483
1712
  height: "16",
1484
1713
  viewBox: "0 0 24 24",
@@ -1496,7 +1725,7 @@ const k1 = () => e("svg", {
1496
1725
  y1: "15",
1497
1726
  x2: "12",
1498
1727
  y2: "3"
1499
- }, null)]), x1 = () => e("svg", {
1728
+ }, null)]), Mt = () => e("svg", {
1500
1729
  width: "16",
1501
1730
  height: "16",
1502
1731
  viewBox: "0 0 24 24",
@@ -1509,7 +1738,7 @@ const k1 = () => e("svg", {
1509
1738
  points: "1 4 1 10 7 10"
1510
1739
  }, null), e("path", {
1511
1740
  d: "M3.51 15a9 9 0 1 0 .49-4.1L1 10"
1512
- }, null)]), H1 = () => e("svg", {
1741
+ }, null)]), It = () => e("svg", {
1513
1742
  width: "16",
1514
1743
  height: "16",
1515
1744
  viewBox: "0 0 24 24",
@@ -1526,38 +1755,38 @@ const k1 = () => e("svg", {
1526
1755
  d: "M10 11v6M14 11v6"
1527
1756
  }, null), e("path", {
1528
1757
  d: "M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"
1529
- }, null)]), B1 = /* @__PURE__ */ c({
1758
+ }, null)]), Lt = /* @__PURE__ */ c({
1530
1759
  name: "ImageControls",
1531
1760
  setup() {
1532
- const t = B("editor"), l = B("readonly"), n = H(null);
1761
+ const t = H("editor"), l = H("readonly"), n = k(null);
1533
1762
  function o() {
1534
- const u = t?.value;
1535
- if (!u) {
1763
+ const i = t?.value;
1764
+ if (!i) {
1536
1765
  n.value = null;
1537
1766
  return;
1538
1767
  }
1539
- n.value = w1(u);
1768
+ n.value = Bt(i);
1540
1769
  }
1541
- return G((u) => {
1542
- const s = t?.value;
1543
- s && (s.on("transaction", o), u(() => {
1544
- s.off("transaction", o);
1770
+ return G((i) => {
1771
+ const r = t?.value;
1772
+ r && (r.on("transaction", o), i(() => {
1773
+ r.off("transaction", o);
1545
1774
  }));
1546
1775
  }), () => {
1547
- const u = n.value;
1548
- if (!u) return null;
1549
- const s = t?.value;
1550
- if (!s) return null;
1776
+ const i = n.value;
1777
+ if (!i) return null;
1778
+ const r = t?.value;
1779
+ if (!r) return null;
1551
1780
  const {
1552
- pos: f,
1553
- nodeSize: g,
1554
- src: r,
1555
- align: C
1556
- } = u, i = l?.value ?? !1, p = s.view.nodeDOM(f);
1557
- if (!p || !(p instanceof HTMLElement)) return null;
1558
- const w = p.querySelector("[data-resize-wrapper]") ?? p, I = s.view.dom.closest(".tiptap-editor");
1781
+ pos: v,
1782
+ nodeSize: p,
1783
+ src: s,
1784
+ align: y
1785
+ } = i, u = l?.value ?? !1, C = r.view.nodeDOM(v);
1786
+ if (!C || !(C instanceof HTMLElement)) return null;
1787
+ const g = C.querySelector("[data-resize-wrapper]") ?? C, I = r.view.dom.closest(".tiptap-editor");
1559
1788
  if (!I) return null;
1560
- const x = w.getBoundingClientRect(), a = I.getBoundingClientRect(), d = {
1789
+ const x = g.getBoundingClientRect(), a = I.getBoundingClientRect(), d = {
1561
1790
  position: "absolute",
1562
1791
  top: `${x.top - a.top}px`,
1563
1792
  left: `${x.left - a.left + x.width / 2}px`,
@@ -1567,243 +1796,92 @@ const k1 = () => e("svg", {
1567
1796
  return e("div", {
1568
1797
  class: "image-controls",
1569
1798
  style: d
1570
- }, [!i && m1.map(({
1571
- value: v,
1799
+ }, [!u && Ht.map(({
1800
+ value: f,
1572
1801
  title: h,
1573
- Icon: A
1802
+ Icon: B
1574
1803
  }) => e("button", {
1575
- key: v,
1576
- class: ["image-controls-btn", C === v && "is-active"],
1804
+ key: f,
1805
+ class: ["image-controls-btn", y === f && "is-active"],
1577
1806
  title: h,
1578
1807
  onMousedown: _,
1579
- onClick: () => s.chain().focus().updateAttributes("image", {
1580
- align: v
1808
+ onClick: () => r.chain().focus().updateAttributes("image", {
1809
+ align: f
1581
1810
  }).run()
1582
- }, [e(A, null, null)])), !i && e("span", {
1811
+ }, [e(B, null, null)])), !u && e("span", {
1583
1812
  class: "image-controls-separator"
1584
1813
  }, null), e("button", {
1585
1814
  class: "image-controls-btn",
1586
1815
  title: "下载",
1587
1816
  onMousedown: _,
1588
- onClick: () => b1(r)
1589
- }, [e(k1, null, null)]), !i && e("button", {
1817
+ onClick: () => yt(s)
1818
+ }, [e(At, null, null)]), !u && e("button", {
1590
1819
  class: "image-controls-btn",
1591
1820
  title: "重新上传",
1592
1821
  onMousedown: _,
1593
- onClick: () => s.chain().focus().deleteRange({
1594
- from: f,
1595
- to: f + g
1596
- }).insertContentAt(f, {
1822
+ onClick: () => r.chain().focus().deleteRange({
1823
+ from: v,
1824
+ to: v + p
1825
+ }).insertContentAt(v, {
1597
1826
  type: "imageUpload"
1598
1827
  }).run()
1599
- }, [e(x1, null, null)]), !i && e("button", {
1828
+ }, [e(Mt, null, null)]), !u && e("button", {
1600
1829
  class: "image-controls-btn",
1601
1830
  title: "删除",
1602
1831
  onMousedown: _,
1603
- onClick: () => s.chain().focus().deleteRange({
1604
- from: f,
1605
- to: f + g
1832
+ onClick: () => r.chain().focus().deleteRange({
1833
+ from: v,
1834
+ to: v + p
1606
1835
  }).run()
1607
- }, [e(H1, null, null)])]);
1608
- };
1609
- }
1610
- }), A1 = /* @__PURE__ */ c({
1611
- name: "CodeBlockIcon",
1612
- setup(t, {
1613
- attrs: l
1614
- }) {
1615
- return () => e("svg", k({
1616
- width: "24",
1617
- height: "24",
1618
- viewBox: "0 0 24 24",
1619
- fill: "none",
1620
- stroke: "currentColor",
1621
- "stroke-width": "2",
1622
- "stroke-linecap": "round",
1623
- "stroke-linejoin": "round",
1624
- xmlns: "http://www.w3.org/2000/svg"
1625
- }, l), [e("polyline", {
1626
- points: "16 18 22 12 16 6"
1627
- }, null), e("polyline", {
1628
- points: "8 6 2 12 8 18"
1629
- }, null)]);
1630
- }
1631
- }), y1 = /* @__PURE__ */ c({
1632
- name: "CodeBlockButton",
1633
- setup() {
1634
- const t = B("editor");
1635
- return () => e(b, {
1636
- icon: A1,
1637
- tooltip: "代码块",
1638
- isActive: t?.value?.isActive("codeBlock"),
1639
- onClick: () => t?.value?.chain().focus().toggleCodeBlock().run()
1640
- }, null);
1641
- }
1642
- }), M1 = /* @__PURE__ */ c({
1643
- name: "BubbleMenuBar",
1644
- setup() {
1645
- const t = B("editor"), l = B("readonly");
1646
- return () => t?.value ? e(Pe, {
1647
- editor: t.value,
1648
- class: "bubble-menu",
1649
- options: {
1650
- placement: "top",
1651
- offset: {
1652
- mainAxis: 8
1653
- }
1654
- },
1655
- shouldShow: (n) => {
1656
- if (l?.value) return !1;
1657
- const {
1658
- editor: o,
1659
- from: u,
1660
- to: s
1661
- } = n;
1662
- return !(u === s || o.isActive("image") || o.isActive("table"));
1663
- }
1664
- }, {
1665
- default: () => [e("div", {
1666
- class: "bubble-menu-content"
1667
- }, [e(b, {
1668
- icon: Q,
1669
- tooltip: "粗体",
1670
- isActive: t.value.isActive("bold"),
1671
- onClick: () => t.value?.chain().focus().toggleBold().run()
1672
- }, null), e(b, {
1673
- icon: Y,
1674
- tooltip: "斜体",
1675
- isActive: t.value.isActive("italic"),
1676
- onClick: () => t.value?.chain().focus().toggleItalic().run()
1677
- }, null), e(b, {
1678
- icon: ee,
1679
- tooltip: "删除线",
1680
- isActive: t.value.isActive("strike"),
1681
- onClick: () => t.value?.chain().focus().toggleStrike().run()
1682
- }, null), e(b, {
1683
- icon: te,
1684
- tooltip: "下划线",
1685
- isActive: t.value.isActive("underline"),
1686
- onClick: () => t.value?.chain().focus().toggleUnderline().run()
1687
- }, null)])]
1688
- }) : null;
1689
- }
1690
- }), I1 = He(Be), W1 = /* @__PURE__ */ c({
1691
- name: "TiptapEditor",
1692
- props: {
1693
- modelValue: {
1694
- type: String,
1695
- default: ""
1696
- },
1697
- placeholder: {
1698
- type: String,
1699
- default: "请输入内容..."
1700
- },
1701
- upload: {
1702
- type: Function,
1703
- default: void 0
1704
- },
1705
- readonly: {
1706
- type: Boolean,
1707
- default: !1
1708
- }
1709
- },
1710
- emits: ["update:modelValue"],
1711
- setup(t, {
1712
- emit: l
1713
- }) {
1714
- const n = H(!1), o = H(""), u = H(null), s = H("inline"), f = V(() => t.readonly ?? !1), g = (C = {}) => {
1715
- f.value || (o.value = C.latex ?? "", u.value = C.pos ?? null, s.value = C.type ?? "inline", n.value = !0);
1836
+ }, [e(It, null, null)])]);
1716
1837
  };
1717
- z("openMathDialog", g), z("readonly", f);
1718
- const r = he({
1719
- content: t.modelValue,
1720
- editable: !t.readonly,
1721
- extensions: [pe.configure({
1722
- codeBlock: !1,
1723
- link: {
1724
- openOnClick: !1,
1725
- enableClickSelection: !0
1726
- }
1727
- }), ke.configure({
1728
- placeholder: t.placeholder
1729
- }), xe.configure({
1730
- lowlight: I1,
1731
- defaultLanguage: "plaintext"
1732
- }), be.configure({
1733
- types: ["heading", "paragraph"]
1734
- }), me, we.configure({
1735
- nested: !0
1736
- }), ze.configure({
1737
- allowBase64: !0,
1738
- resize: {
1739
- enabled: !0,
1740
- directions: ["top", "right", "bottom", "left", "top-right", "top-left", "bottom-right", "bottom-left"],
1741
- minWidth: 50,
1742
- minHeight: 50,
1743
- alwaysPreserveAspectRatio: !1
1744
- }
1745
- }), $e.configure({
1746
- ...t.upload ? {
1747
- upload: t.upload
1748
- } : {}
1749
- }), Te.configure({
1750
- resizable: !0
1751
- }), Ee, Fe, Ve, Ze.configure({
1752
- inlineOptions: {
1753
- onClick: (C, i) => g({
1754
- latex: C.attrs.latex,
1755
- pos: i,
1756
- type: "inline"
1757
- })
1758
- },
1759
- blockOptions: {
1760
- onClick: (C, i) => g({
1761
- latex: C.attrs.latex,
1762
- pos: i,
1763
- type: "block"
1764
- })
1765
- }
1766
- })],
1767
- onUpdate: ({
1768
- editor: C
1769
- }) => {
1770
- l("update:modelValue", C.getHTML());
1771
- }
1772
- });
1773
- return z("editor", r), D(() => t.modelValue, (C) => {
1774
- r.value && C !== r.value.getHTML() && r.value.commands.setContent(C, {
1775
- emitUpdate: !1
1776
- });
1777
- }), D(() => t.readonly, (C) => {
1778
- r.value?.setEditable(!C);
1779
- }), () => e("div", {
1780
- class: "tiptap-editor"
1781
- }, [!t.readonly && e("div", {
1782
- class: "tiptap-toolbar"
1783
- }, [e(qe, null, null), e("div", {
1784
- class: "tiptap-separator"
1785
- }, null), e(Ye, null, null), e(y1, null, null), e("div", {
1786
- class: "tiptap-separator"
1787
- }, null), e(i1, null, null), e("div", {
1788
- class: "tiptap-separator"
1789
- }, null), e(t1, null, null), e("div", {
1790
- class: "tiptap-separator"
1791
- }, null), e(r1, null, null), e(d1, null, null), e(h1, null, null)]), e(ge, {
1792
- class: "tiptap-content",
1793
- editor: r.value
1794
- }, null), e(M1, null, null), e(v1, null, null), e(B1, null, null), e(g1, {
1795
- visible: n.value,
1796
- latex: o.value,
1797
- pos: u.value,
1798
- type: s.value,
1799
- "onUpdate:visible": (C) => {
1800
- n.value = C;
1801
- }
1802
- }, null)]);
1803
1838
  }
1804
1839
  });
1840
+ function t1(t) {
1841
+ return {
1842
+ name: "image",
1843
+ install: () => ({
1844
+ extensions: [
1845
+ Ne.configure({
1846
+ allowBase64: !0,
1847
+ resize: {
1848
+ enabled: !0,
1849
+ directions: ["top", "right", "bottom", "left", "top-right", "top-left", "bottom-right", "bottom-left"],
1850
+ minWidth: 50,
1851
+ minHeight: 50,
1852
+ alwaysPreserveAspectRatio: !1
1853
+ }
1854
+ }),
1855
+ bt.configure({ ...t ? { upload: t } : {} })
1856
+ ],
1857
+ controlComponent: Lt
1858
+ }),
1859
+ toolbarComponent: kt
1860
+ };
1861
+ }
1862
+ const l1 = {
1863
+ name: "separator",
1864
+ install: () => ({
1865
+ extensions: []
1866
+ }),
1867
+ toolbarComponent: /* @__PURE__ */ c({
1868
+ name: "ToolbarSeparator",
1869
+ setup: () => () => e("div", {
1870
+ class: "tiptap-separator"
1871
+ }, null)
1872
+ })
1873
+ };
1805
1874
  export {
1806
- b as IconButton,
1807
- ze as ImageWithAlign,
1808
- W1 as TiptapEditor
1875
+ Qt as CodeBlockFeature,
1876
+ w as IconButton,
1877
+ t1 as ImageFeature,
1878
+ Ne as ImageWithAlign,
1879
+ Xt as ListFeature,
1880
+ e1 as MathFeature,
1881
+ l1 as SeparatorFeature,
1882
+ Yt as TableFeature,
1883
+ Jt as TextAlignFeature,
1884
+ Gt as TextStyleFeature,
1885
+ qt as TiptapEditor,
1886
+ Kt as UndoRedoFeature
1809
1887
  };