@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.
@@ -1,255 +1,21 @@
1
- import { defineComponent as p, computed as F, ref as y, createVNode as e, createTextVNode as g, mergeProps as b, inject as A, watch as D, nextTick as O, watchEffect as K, Fragment as de, provide as P } 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";
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 ye } from "lowlight";
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 x, 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 ke } from "@tiptap/extension-text-align";
6
+ import { Placeholder as xe } from "@tiptap/extension-placeholder";
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 ye, ElRadioGroup as Be, ElRadioButton as q } from "element-plus";
9
9
  import { Image as Ae } from "@tiptap/extension-image";
10
- import { Plugin as Be, NodeSelection as Me } from "@tiptap/pm/state";
11
- import { Decoration as Le, DecorationSet as Ie } from "@tiptap/pm/view";
12
- import { TableRow as Ee, TableHeader as Fe, TableCell as Te, Table as Ve } 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 Oe } from "@tiptap/vue-3/menus";
18
- const Pe = 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 Be({
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
- Le.node(u, u + o.nodeSize, {
39
- "data-align": o.attrs.align
40
- })
41
- );
42
- }), Ie.create(l.doc, n);
43
- }
44
- }
45
- })
46
- ];
47
- }
48
- }), $e = /* @__PURE__ */ p({
49
- name: "ImageUploadView",
50
- props: Ce,
51
- setup(t) {
52
- const l = F(() => t.node.attrs.accept), n = F(() => t.node.attrs.limit), o = F(() => t.node.attrs.maxSize), u = y([]), d = y(), f = y(!1), m = 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 C = crypto.randomUUID();
56
- u.value.push({
57
- id: C,
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 B = u.value.find((V) => V.id === C);
68
- return B && (B.status = "success", B.progress = 100), t.extension.options.onSuccess?.(h), h;
69
- } catch (v) {
70
- const h = u.value.find((B) => B.id === C);
71
- return h && (h.status = "error", h.progress = 0), t.extension.options.onError?.(v instanceof Error ? v : new Error("上传失败")), null;
72
- }
73
- }, c = 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 C = (await Promise.all(a.map(m))).filter((v) => !!v);
80
- if (C.length > 0) {
81
- const v = t.getPos();
82
- if (typeof v != "number") return;
83
- const h = C.map((B) => ({
84
- type: "image",
85
- attrs: {
86
- src: B
87
- }
88
- }));
89
- t.editor.chain().focus().deleteRange({
90
- from: v,
91
- to: v + t.node.nodeSize
92
- }).insertContentAt(v, h).run();
93
- }
94
- }, H = () => {
95
- u.value.length === 0 && d.value && (d.value.value = "", d.value.click());
96
- }, i = (a) => {
97
- const C = a.target.files;
98
- C && c(Array.from(C));
99
- }, s = (a) => {
100
- a.preventDefault(), f.value = !0;
101
- }, r = (a) => {
102
- a.currentTarget.contains(a.relatedTarget) || (f.value = !1);
103
- }, x = (a) => {
104
- a.preventDefault(), f.value = !1;
105
- const C = Array.from(a.dataTransfer?.files ?? []);
106
- C.length && c(C);
107
- }, k = (a) => {
108
- u.value = u.value.filter((C) => C.id !== a);
109
- };
110
- return () => e(ve, {
111
- class: "tiptap-image-upload"
112
- }, {
113
- default: () => [e("div", {
114
- onClick: H
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: (C) => {
134
- C.stopPropagation(), k(a.id);
135
- }
136
- }, [g("×")])])]))]) : e("div", {
137
- class: ["tiptap-image-upload-drag-area", {
138
- "drag-active": f.value
139
- }],
140
- onDragover: s,
141
- onDragleave: r,
142
- onDrop: x
143
- }, [e("div", {
144
- class: "tiptap-image-upload-content"
145
- }, [e("span", {
146
- class: "tiptap-image-upload-text"
147
- }, [e("em", null, [g("点击上传")]), g(" 或拖拽图片到此处")]), e("span", {
148
- class: "tiptap-image-upload-subtext"
149
- }, [g("最多 "), n.value, g(" 个文件"), o.value ? `,每个不超过 ${o.value / 1024 / 1024}MB` : ""])])]), e("input", {
150
- ref: d,
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
- }), ze = 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($e);
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 = [
240
- "undo-redo",
241
- "|",
242
- "text-style",
243
- "code-block",
244
- "|",
245
- "list",
246
- "|",
247
- "text-align",
248
- "|",
249
- "image",
250
- "table",
251
- "math"
252
- ], je = {
17
+ import { Node as Pe, mergeAttributes as ze } from "@tiptap/core";
18
+ const Oe = {
253
19
  icon: {
254
20
  type: Object,
255
21
  required: !0
@@ -268,11 +34,11 @@ const Pe = Ae.extend({
268
34
  onClick: {
269
35
  type: Function
270
36
  }
271
- }, w = /* @__PURE__ */ p({
37
+ }, w = /* @__PURE__ */ c({
272
38
  name: "IconButton",
273
- props: je,
39
+ props: Oe,
274
40
  setup(t) {
275
- return () => e(R, {
41
+ return () => e(D, {
276
42
  showArrow: !1,
277
43
  offset: 6,
278
44
  content: t.tooltip
@@ -288,7 +54,247 @@ const Pe = Ae.extend({
288
54
  }, null)]
289
55
  });
290
56
  }
291
- }), We = /* @__PURE__ */ p({
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: u
147
+ } = n;
148
+ return !(i === u || 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
+ upload: {
192
+ type: Function,
193
+ default: void 0
194
+ },
195
+ features: {
196
+ type: Array,
197
+ default: () => []
198
+ }
199
+ },
200
+ emits: ["update:modelValue"],
201
+ setup(t, {
202
+ emit: l
203
+ }) {
204
+ const n = T(() => t.readonly ?? !1);
205
+ P("readonly", n);
206
+ const o = t.features.map((u) => ({
207
+ plugin: u,
208
+ result: u.install({
209
+ readonly: n,
210
+ provide: (v, p) => P(v, p),
211
+ upload: t.upload
212
+ })
213
+ })), i = ve({
214
+ content: t.modelValue,
215
+ editable: !t.readonly,
216
+ extensions: [Ce.configure({
217
+ codeBlock: !1,
218
+ link: {
219
+ openOnClick: !1,
220
+ enableClickSelection: !0
221
+ }
222
+ }), xe.configure({
223
+ placeholder: t.placeholder
224
+ }), ke.configure({
225
+ types: ["heading", "paragraph"]
226
+ }), we, be.configure({
227
+ nested: !0
228
+ }), ...o.flatMap(({
229
+ result: u
230
+ }) => u.extensions)],
231
+ onUpdate: ({
232
+ editor: u
233
+ }) => {
234
+ l("update:modelValue", u.getHTML());
235
+ }
236
+ });
237
+ return P("editor", i), R(() => t.modelValue, (u) => {
238
+ i.value && u !== i.value.getHTML() && i.value.commands.setContent(u, {
239
+ emitUpdate: !1
240
+ });
241
+ }), R(() => t.readonly, (u) => {
242
+ i.value?.setEditable(!u);
243
+ }), () => e("div", {
244
+ class: "tiptap-editor"
245
+ }, [!t.readonly && e("div", {
246
+ class: "tiptap-toolbar"
247
+ }, [o.map(({
248
+ plugin: u
249
+ }) => {
250
+ const v = u.toolbarComponent;
251
+ return v ? e(v, {
252
+ key: u.name
253
+ }, null) : null;
254
+ })]), e(fe, {
255
+ class: "tiptap-content",
256
+ editor: i.value
257
+ }, null), e($e, null, null), o.map(({
258
+ plugin: u,
259
+ result: v
260
+ }) => {
261
+ const p = v.controlComponent;
262
+ return p ? e(p, {
263
+ key: `${u.name}-control`
264
+ }, null) : null;
265
+ })]);
266
+ }
267
+ }), Ne = Ae.extend({
268
+ addAttributes() {
269
+ return {
270
+ ...this.parent?.(),
271
+ align: {
272
+ default: "left",
273
+ parseHTML: (t) => t.getAttribute("data-align") ?? "left",
274
+ renderHTML: (t) => ({ "data-align": t.align })
275
+ }
276
+ };
277
+ },
278
+ addProseMirrorPlugins() {
279
+ const t = this.name;
280
+ return [
281
+ new Me({
282
+ props: {
283
+ decorations(l) {
284
+ const n = [];
285
+ return l.doc.descendants((o, i) => {
286
+ o.type.name === t && o.attrs.align && n.push(
287
+ Le.node(i, i + o.nodeSize, {
288
+ "data-align": o.attrs.align
289
+ })
290
+ );
291
+ }), Ee.create(l.doc, n);
292
+ }
293
+ }
294
+ })
295
+ ];
296
+ }
297
+ }), je = /* @__PURE__ */ c({
292
298
  name: "UndoIcon",
293
299
  setup(t, {
294
300
  attrs: l
@@ -306,7 +312,7 @@ const Pe = Ae.extend({
306
312
  fill: "currentColor"
307
313
  }, null)]);
308
314
  }
309
- }), qe = /* @__PURE__ */ p({
315
+ }), We = /* @__PURE__ */ c({
310
316
  name: "RedoIcon",
311
317
  setup(t, {
312
318
  attrs: l
@@ -324,23 +330,27 @@ const Pe = Ae.extend({
324
330
  fill: "currentColor"
325
331
  }, null)]);
326
332
  }
327
- }), Ge = /* @__PURE__ */ p({
333
+ }), qe = /* @__PURE__ */ c({
328
334
  name: "UndoRedoButton",
329
335
  setup() {
330
- const t = A("editor"), l = F(() => t?.value?.can().undo() ?? !1), n = F(() => t?.value?.can().redo() ?? !1);
336
+ const t = H("editor"), l = T(() => t?.value?.can().undo() ?? !1), n = T(() => t?.value?.can().redo() ?? !1);
331
337
  return () => e("div", null, [e(w, {
332
- icon: We,
338
+ icon: je,
333
339
  tooltip: "撤销",
334
340
  disabled: !l.value,
335
341
  onClick: () => t?.value?.chain().focus().undo().run()
336
342
  }, null), e(w, {
337
- icon: qe,
343
+ icon: We,
338
344
  tooltip: "重做",
339
345
  disabled: !n.value,
340
346
  onClick: () => t?.value?.chain().focus().redo().run()
341
347
  }, null)]);
342
348
  }
343
- }), Ke = /* @__PURE__ */ p({
349
+ }), Kt = {
350
+ name: "undo-redo",
351
+ install: () => ({ extensions: [] }),
352
+ toolbarComponent: qe
353
+ }, Ke = /* @__PURE__ */ c({
344
354
  name: "LinkIcon",
345
355
  setup(t, {
346
356
  attrs: l
@@ -359,7 +369,7 @@ const Pe = Ae.extend({
359
369
  fill: "currentColor"
360
370
  }, null)]);
361
371
  }
362
- }), Je = /* @__PURE__ */ p({
372
+ }), Ge = /* @__PURE__ */ c({
363
373
  name: "CornerDownLeftIcon",
364
374
  setup(t, {
365
375
  attrs: l
@@ -380,7 +390,7 @@ const Pe = Ae.extend({
380
390
  d: "M20 4v7a4 4 0 0 1-4 4H4"
381
391
  }, null)]);
382
392
  }
383
- }), Xe = /* @__PURE__ */ p({
393
+ }), Je = /* @__PURE__ */ c({
384
394
  name: "ExternalLinkIcon",
385
395
  setup(t, {
386
396
  attrs: l
@@ -406,7 +416,7 @@ const Pe = Ae.extend({
406
416
  y2: "3"
407
417
  }, null)]);
408
418
  }
409
- }), Qe = /* @__PURE__ */ p({
419
+ }), Xe = /* @__PURE__ */ c({
410
420
  name: "TrashIcon",
411
421
  setup(t, {
412
422
  attrs: l
@@ -427,52 +437,52 @@ const Pe = Ae.extend({
427
437
  d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
428
438
  }, null)]);
429
439
  }
430
- }), Ye = /* @__PURE__ */ p({
440
+ }), Qe = /* @__PURE__ */ c({
431
441
  name: "LinkPopover",
432
442
  setup() {
433
- const t = A("editor"), l = y(!1), n = y("");
443
+ const t = H("editor"), l = x(!1), n = x("");
434
444
  let o = !1;
435
- D(() => t?.value?.isActive("link"), (i) => {
436
- o || i && (n.value = t?.value?.getAttributes("link").href ?? "", O(() => {
445
+ R(() => t?.value?.isActive("link"), (r) => {
446
+ o || r && (n.value = t?.value?.getAttributes("link").href ?? "", z(() => {
437
447
  l.value = !0;
438
448
  }));
439
449
  });
440
- const u = () => {
441
- const i = t?.value;
442
- if (!i || !n.value) return;
450
+ const i = () => {
451
+ const r = t?.value;
452
+ if (!r || !n.value) return;
443
453
  o = !0;
444
454
  const {
445
- empty: s
446
- } = i.state.selection;
447
- let r = i.chain().focus().extendMarkRange("link").setLink({
455
+ empty: C
456
+ } = r.state.selection;
457
+ let g = r.chain().focus().extendMarkRange("link").setLink({
448
458
  href: n.value
449
459
  });
450
- s && (r = r.insertContent({
460
+ C && (g = g.insertContent({
451
461
  type: "text",
452
462
  text: n.value
453
- })), r.run(), l.value = !1, O(() => {
463
+ })), g.run(), l.value = !1, z(() => {
454
464
  o = !1;
455
465
  });
456
- }, d = () => {
457
- const i = t?.value;
458
- i && (o = !0, i.chain().focus().extendMarkRange("link").unsetLink().run(), n.value = "", l.value = !1, O(() => {
466
+ }, u = () => {
467
+ const r = t?.value;
468
+ r && (o = !0, r.chain().focus().extendMarkRange("link").unsetLink().run(), n.value = "", l.value = !1, z(() => {
459
469
  o = !1;
460
470
  }));
461
- }, f = () => {
462
- const i = t?.value?.getAttributes("link").href;
463
- i && window.open(i, "_blank", "noopener,noreferrer");
464
- }, m = (i) => {
465
- i.key === "Enter" && (i.preventDefault(), u());
466
- }, c = (i) => {
467
- i && (n.value = t?.value?.getAttributes("link").href ?? ""), l.value = i;
468
- }, H = (i) => {
469
- n.value = i;
471
+ }, v = () => {
472
+ const r = t?.value?.getAttributes("link").href;
473
+ r && window.open(r, "_blank", "noopener,noreferrer");
474
+ }, p = (r) => {
475
+ r.key === "Enter" && (r.preventDefault(), i());
476
+ }, s = (r) => {
477
+ r && (n.value = t?.value?.getAttributes("link").href ?? ""), l.value = r;
478
+ }, B = (r) => {
479
+ n.value = r;
470
480
  };
471
481
  return () => {
472
- const i = t?.value?.isActive("link") ?? !1;
482
+ const r = t?.value?.isActive("link") ?? !1;
473
483
  return e(J, {
474
484
  visible: l.value,
475
- "onUpdate:visible": c,
485
+ "onUpdate:visible": s,
476
486
  placement: "bottom",
477
487
  width: 300,
478
488
  trigger: "click",
@@ -484,133 +494,62 @@ const Pe = Ae.extend({
484
494
  tooltip: "链接",
485
495
  icon: Ke,
486
496
  class: ["tiptap-button", {
487
- "is-active": i
497
+ "is-active": r
488
498
  }]
489
499
  }, null)]),
490
500
  default: () => e("div", {
491
501
  class: "link-popover-inner"
492
502
  }, [e(X, {
493
503
  modelValue: n.value,
494
- "onUpdate:modelValue": H,
504
+ "onUpdate:modelValue": B,
495
505
  type: "url",
496
506
  placeholder: "请输入链接...",
497
507
  size: "small",
498
508
  autofocus: !0,
499
- onKeydown: m
509
+ onKeydown: p
500
510
  }, null), e("div", {
501
511
  class: "link-popover-actions"
502
- }, [e(R, {
512
+ }, [e(D, {
503
513
  content: "确认",
504
514
  showArrow: !1,
505
515
  offset: 4
506
516
  }, {
507
517
  default: () => [e(Z, {
508
518
  text: !0,
509
- icon: Je,
519
+ icon: Ge,
510
520
  disabled: !n.value,
511
- onClick: u
521
+ onClick: i
512
522
  }, null)]
513
- }), e(R, {
523
+ }), e(D, {
514
524
  content: "在新标签页打开",
515
525
  showArrow: !1,
516
526
  offset: 4
517
527
  }, {
518
528
  default: () => [e(Z, {
519
529
  text: !0,
520
- icon: Xe,
521
- disabled: !n.value && !i,
522
- onClick: f
530
+ icon: Je,
531
+ disabled: !n.value && !r,
532
+ onClick: v
523
533
  }, null)]
524
- }), e(R, {
534
+ }), e(D, {
525
535
  content: "移除链接",
526
536
  showArrow: !1,
527
537
  offset: 4
528
538
  }, {
529
539
  default: () => [e(Z, {
530
540
  text: !0,
531
- icon: Qe,
532
- disabled: !i,
533
- onClick: d
541
+ icon: Xe,
542
+ disabled: !r,
543
+ onClick: u
534
544
  }, null)]
535
545
  })])])
536
546
  });
537
547
  };
538
548
  }
539
- }), Q = /* @__PURE__ */ p({
540
- name: "BoldIcon",
541
- setup(t, {
542
- attrs: l
543
- }) {
544
- return () => e("svg", b({
545
- width: "24",
546
- height: "24",
547
- viewBox: "0 0 24 24",
548
- fill: "currentColor",
549
- xmlns: "http://www.w3.org/2000/svg"
550
- }, l), [e("path", {
551
- "fill-rule": "evenodd",
552
- "clip-rule": "evenodd",
553
- 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",
554
- fill: "currentColor"
555
- }, null)]);
556
- }
557
- }), Y = /* @__PURE__ */ p({
558
- name: "ItalicIcon",
559
- setup(t, {
560
- attrs: l
561
- }) {
562
- return () => e("svg", b({
563
- width: "24",
564
- height: "24",
565
- viewBox: "0 0 24 24",
566
- fill: "currentColor",
567
- xmlns: "http://www.w3.org/2000/svg"
568
- }, l), [e("path", {
569
- 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",
570
- fill: "currentColor"
571
- }, null)]);
572
- }
573
- }), ee = /* @__PURE__ */ p({
574
- name: "StrikeIcon",
575
- setup(t, {
576
- attrs: l
577
- }) {
578
- return () => e("svg", b({
579
- width: "24",
580
- height: "24",
581
- viewBox: "0 0 24 24",
582
- fill: "currentColor",
583
- xmlns: "http://www.w3.org/2000/svg"
584
- }, l), [e("path", {
585
- 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",
586
- fill: "currentColor"
587
- }, null), e("path", {
588
- 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",
589
- fill: "currentColor"
590
- }, null)]);
591
- }
592
- }), te = /* @__PURE__ */ p({
593
- name: "UnderlineIcon",
594
- setup(t, {
595
- attrs: l
596
- }) {
597
- return () => e("svg", b({
598
- width: "24",
599
- height: "24",
600
- viewBox: "0 0 24 24",
601
- fill: "currentColor",
602
- xmlns: "http://www.w3.org/2000/svg"
603
- }, l), [e("path", {
604
- "fill-rule": "evenodd",
605
- "clip-rule": "evenodd",
606
- 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",
607
- fill: "currentColor"
608
- }, null)]);
609
- }
610
- }), e1 = /* @__PURE__ */ p({
549
+ }), Ye = /* @__PURE__ */ c({
611
550
  name: "TextStyleButton",
612
551
  setup() {
613
- const t = A("editor");
552
+ const t = H("editor");
614
553
  return () => e("div", null, [e(w, {
615
554
  icon: Q,
616
555
  tooltip: "粗体",
@@ -631,9 +570,13 @@ const Pe = Ae.extend({
631
570
  tooltip: "下划线",
632
571
  isActive: t?.value?.isActive("underline"),
633
572
  onClick: () => t?.value?.chain().focus().toggleUnderline().run()
634
- }, null), e(Ye, null, null)]);
573
+ }, null), e(Qe, null, null)]);
635
574
  }
636
- }), le = /* @__PURE__ */ p({
575
+ }), Gt = {
576
+ name: "text-style",
577
+ install: () => ({ extensions: [] }),
578
+ toolbarComponent: Ye
579
+ }, le = /* @__PURE__ */ c({
637
580
  name: "AlignLeftIcon",
638
581
  setup(t, {
639
582
  attrs: l
@@ -661,7 +604,7 @@ const Pe = Ae.extend({
661
604
  fill: "currentColor"
662
605
  }, null)]);
663
606
  }
664
- }), ne = /* @__PURE__ */ p({
607
+ }), ne = /* @__PURE__ */ c({
665
608
  name: "AlignCenterIcon",
666
609
  setup(t, {
667
610
  attrs: l
@@ -689,7 +632,7 @@ const Pe = Ae.extend({
689
632
  fill: "currentColor"
690
633
  }, null)]);
691
634
  }
692
- }), oe = /* @__PURE__ */ p({
635
+ }), oe = /* @__PURE__ */ c({
693
636
  name: "AlignRightIcon",
694
637
  setup(t, {
695
638
  attrs: l
@@ -717,7 +660,7 @@ const Pe = Ae.extend({
717
660
  fill: "currentColor"
718
661
  }, null)]);
719
662
  }
720
- }), t1 = /* @__PURE__ */ p({
663
+ }), et = /* @__PURE__ */ c({
721
664
  name: "AlignJustifyIcon",
722
665
  setup(t, {
723
666
  attrs: l
@@ -745,10 +688,10 @@ const Pe = Ae.extend({
745
688
  fill: "currentColor"
746
689
  }, null)]);
747
690
  }
748
- }), l1 = /* @__PURE__ */ p({
691
+ }), tt = /* @__PURE__ */ c({
749
692
  name: "TextAlignButton",
750
693
  setup() {
751
- const t = A("editor");
694
+ const t = H("editor");
752
695
  return () => e("div", null, [e(w, {
753
696
  icon: le,
754
697
  tooltip: "左边对齐",
@@ -771,7 +714,7 @@ const Pe = Ae.extend({
771
714
  }),
772
715
  onClick: () => t?.value?.chain().focus().setTextAlign("right").run()
773
716
  }, null), e(w, {
774
- icon: t1,
717
+ icon: et,
775
718
  tooltip: "两端对齐",
776
719
  isActive: t?.value?.isActive({
777
720
  textAlign: "justify"
@@ -779,7 +722,11 @@ const Pe = Ae.extend({
779
722
  onClick: () => t?.value?.chain().focus().setTextAlign("justify").run()
780
723
  }, null)]);
781
724
  }
782
- }), n1 = /* @__PURE__ */ p({
725
+ }), Jt = {
726
+ name: "text-align",
727
+ install: () => ({ extensions: [] }),
728
+ toolbarComponent: tt
729
+ }, lt = /* @__PURE__ */ c({
783
730
  name: "ListIcon",
784
731
  setup(t, {
785
732
  attrs: l
@@ -822,7 +769,7 @@ const Pe = Ae.extend({
822
769
  fill: "currentColor"
823
770
  }, null)]);
824
771
  }
825
- }), o1 = /* @__PURE__ */ p({
772
+ }), nt = /* @__PURE__ */ c({
826
773
  name: "ListOrderedIcon",
827
774
  setup(t, {
828
775
  attrs: l
@@ -865,7 +812,7 @@ const Pe = Ae.extend({
865
812
  fill: "currentColor"
866
813
  }, null)]);
867
814
  }
868
- }), i1 = /* @__PURE__ */ p({
815
+ }), ot = /* @__PURE__ */ c({
869
816
  name: "ListTodoIcon",
870
817
  setup(t, {
871
818
  attrs: l
@@ -903,29 +850,33 @@ const Pe = Ae.extend({
903
850
  fill: "currentColor"
904
851
  }, null)]);
905
852
  }
906
- }), u1 = /* @__PURE__ */ p({
853
+ }), it = /* @__PURE__ */ c({
907
854
  name: "ListButton",
908
855
  setup() {
909
- const t = A("editor");
856
+ const t = H("editor");
910
857
  return () => e("div", null, [e(w, {
911
- icon: n1,
858
+ icon: lt,
912
859
  tooltip: "无序列表",
913
860
  isActive: t?.value?.isActive("bulletList"),
914
861
  onClick: () => t?.value?.chain().focus().toggleBulletList().run()
915
862
  }, null), e(w, {
916
- icon: o1,
863
+ icon: nt,
917
864
  tooltip: "有序列表",
918
865
  isActive: t?.value?.isActive("orderedList"),
919
866
  onClick: () => t?.value?.chain().focus().toggleOrderedList().run()
920
867
  }, null), e(w, {
921
- icon: i1,
868
+ icon: ot,
922
869
  tooltip: "任务列表",
923
870
  isActive: t?.value?.isActive("taskList"),
924
871
  onClick: () => t?.value?.chain().focus().toggleTaskList().run()
925
872
  }, null)]);
926
873
  }
927
- }), r1 = /* @__PURE__ */ p({
928
- name: "ImagePlusIcon",
874
+ }), Xt = {
875
+ name: "list",
876
+ install: () => ({ extensions: [] }),
877
+ toolbarComponent: it
878
+ }, ut = /* @__PURE__ */ c({
879
+ name: "CodeBlockIcon",
929
880
  setup(t, {
930
881
  attrs: l
931
882
  }) {
@@ -933,26 +884,36 @@ const Pe = Ae.extend({
933
884
  width: "24",
934
885
  height: "24",
935
886
  viewBox: "0 0 24 24",
936
- fill: "currentColor",
887
+ fill: "none",
888
+ stroke: "currentColor",
889
+ "stroke-width": "2",
890
+ "stroke-linecap": "round",
891
+ "stroke-linejoin": "round",
937
892
  xmlns: "http://www.w3.org/2000/svg"
938
- }, l), [e("path", {
939
- "fill-rule": "evenodd",
940
- "clip-rule": "evenodd",
941
- 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",
942
- fill: "currentColor"
893
+ }, l), [e("polyline", {
894
+ points: "16 18 22 12 16 6"
895
+ }, null), e("polyline", {
896
+ points: "8 6 2 12 8 18"
943
897
  }, null)]);
944
898
  }
945
- }), a1 = /* @__PURE__ */ p({
946
- name: "ImageButton",
899
+ }), rt = /* @__PURE__ */ c({
900
+ name: "CodeBlockButton",
947
901
  setup() {
948
- const t = A("editor");
949
- return () => e("div", null, [e(w, {
950
- icon: r1,
951
- tooltip: "图片",
952
- onClick: () => t?.value?.commands.setImageUploadNode()
953
- }, null)]);
902
+ const t = H("editor");
903
+ return () => e(w, {
904
+ icon: ut,
905
+ tooltip: "代码块",
906
+ isActive: t?.value?.isActive("codeBlock"),
907
+ onClick: () => t?.value?.chain().focus().toggleCodeBlock().run()
908
+ }, null);
954
909
  }
955
- }), s1 = /* @__PURE__ */ p({
910
+ }), at = Te(Ve), Qt = {
911
+ name: "code-block",
912
+ install: () => ({
913
+ extensions: [Fe.configure({ lowlight: at, defaultLanguage: "plaintext" })]
914
+ }),
915
+ toolbarComponent: rt
916
+ }, st = /* @__PURE__ */ c({
956
917
  name: "TableIcon",
957
918
  setup(t, {
958
919
  attrs: l
@@ -970,30 +931,30 @@ const Pe = Ae.extend({
970
931
  fill: "currentColor"
971
932
  }, null)]);
972
933
  }
973
- }), c1 = 8, d1 = 8, p1 = /* @__PURE__ */ p({
934
+ }), ct = 8, dt = 8, pt = /* @__PURE__ */ c({
974
935
  name: "TableButton",
975
936
  setup() {
976
- const t = A("editor"), l = y(!1), n = y(0), o = y(0), u = (m, c) => {
977
- n.value = m, o.value = c;
978
- }, d = () => {
937
+ const t = H("editor"), l = x(!1), n = x(0), o = x(0), i = (p, s) => {
938
+ n.value = p, o.value = s;
939
+ }, u = () => {
979
940
  n.value = 0, o.value = 0;
980
- }, f = (m, c) => {
941
+ }, v = (p, s) => {
981
942
  t?.value?.chain().focus().insertTable({
982
- rows: c,
983
- cols: m,
943
+ rows: s,
944
+ cols: p,
984
945
  withHeaderRow: !0
985
946
  }).run(), l.value = !1;
986
947
  };
987
948
  return () => e(J, {
988
949
  visible: l.value,
989
- "onUpdate:visible": (m) => l.value = m,
950
+ "onUpdate:visible": (p) => l.value = p,
990
951
  trigger: "click",
991
952
  placement: "bottom-start",
992
953
  popperClass: "table-picker-popper",
993
954
  width: "auto",
994
955
  showArrow: !1
995
956
  }, {
996
- reference: () => e("span", null, [e(R, {
957
+ reference: () => e("span", null, [e(D, {
997
958
  content: "表格",
998
959
  showArrow: !1,
999
960
  offset: 6,
@@ -1005,7 +966,7 @@ const Pe = Ae.extend({
1005
966
  "is-active": l.value
1006
967
  }]
1007
968
  }, {
1008
- default: () => [e(s1, {
969
+ default: () => [e(st, {
1009
970
  class: "tiptap-button-icon"
1010
971
  }, null)]
1011
972
  })]
@@ -1014,34 +975,34 @@ const Pe = Ae.extend({
1014
975
  class: "table-picker"
1015
976
  }, [e("div", {
1016
977
  class: "table-picker-grid",
1017
- onMouseleave: d
978
+ onMouseleave: u
1018
979
  }, [Array.from({
1019
- length: d1
1020
- }, (m, c) => e("div", {
1021
- key: c,
980
+ length: dt
981
+ }, (p, s) => e("div", {
982
+ key: s,
1022
983
  class: "table-picker-row"
1023
984
  }, [Array.from({
1024
- length: c1
1025
- }, (H, i) => e("div", {
1026
- key: i,
985
+ length: ct
986
+ }, (B, r) => e("div", {
987
+ key: r,
1027
988
  class: ["table-picker-cell", {
1028
- "is-active": i < n.value && c < o.value
989
+ "is-active": r < n.value && s < o.value
1029
990
  }],
1030
- onMouseenter: () => u(i + 1, c + 1),
1031
- onClick: () => f(i + 1, c + 1)
991
+ onMouseenter: () => i(r + 1, s + 1),
992
+ onClick: () => v(r + 1, s + 1)
1032
993
  }, null))]))]), e("div", {
1033
994
  class: "table-picker-footer"
1034
995
  }, [e("div", {
1035
996
  class: "table-picker-counter"
1036
- }, [e("span", null, [g("列")]), e("span", null, [n.value || 1])]), e("span", {
997
+ }, [e("span", null, [m("列")]), e("span", null, [n.value || 1])]), e("span", {
1037
998
  class: "table-picker-x"
1038
- }, [g("x")]), e("div", {
999
+ }, [m("x")]), e("div", {
1039
1000
  class: "table-picker-counter"
1040
- }, [e("span", null, [g("行")]), e("span", null, [o.value || 1])])])])
1001
+ }, [e("span", null, [m("行")]), e("span", null, [o.value || 1])])])])
1041
1002
  });
1042
1003
  }
1043
1004
  });
1044
- function C1(t) {
1005
+ function Ct(t) {
1045
1006
  let l = t.nodeType === Node.TEXT_NODE ? t.parentElement : t;
1046
1007
  for (; l && l instanceof HTMLElement; ) {
1047
1008
  if (l.tagName === "TD" || l.tagName === "TH") return l;
@@ -1049,106 +1010,106 @@ function C1(t) {
1049
1010
  }
1050
1011
  return null;
1051
1012
  }
1052
- function v1(t) {
1013
+ function vt(t) {
1053
1014
  if (!t.isActive("tableCell") && !t.isActive("tableHeader")) return null;
1054
1015
  const {
1055
1016
  node: l
1056
- } = t.view.domAtPos(t.state.selection.from), n = C1(l);
1017
+ } = t.view.domAtPos(t.state.selection.from), n = Ct(l);
1057
1018
  if (!n) return null;
1058
- const o = n.parentElement, u = o.parentElement, d = n.closest("table");
1059
- if (!d) return null;
1060
- const f = Array.from(o.children).indexOf(n), m = Array.from(u.children).indexOf(o), c = o.children.length, H = u.children.length, i = n.getBoundingClientRect(), s = d.getBoundingClientRect(), r = t.view.dom.closest(".tiptap-editor").getBoundingClientRect();
1019
+ const o = n.parentElement, i = o.parentElement, u = n.closest("table");
1020
+ if (!u) return null;
1021
+ const v = Array.from(o.children).indexOf(n), p = Array.from(i.children).indexOf(o), s = o.children.length, B = i.children.length, r = n.getBoundingClientRect(), C = u.getBoundingClientRect(), g = t.view.dom.closest(".tiptap-editor").getBoundingClientRect();
1061
1022
  return {
1062
1023
  cell: n,
1063
- colIndex: f,
1064
- rowIndex: m,
1065
- totalCols: c,
1066
- totalRows: H,
1067
- cellRect: i,
1068
- tableRect: s,
1069
- editorRect: r
1024
+ colIndex: v,
1025
+ rowIndex: p,
1026
+ totalCols: s,
1027
+ totalRows: B,
1028
+ cellRect: r,
1029
+ tableRect: C,
1030
+ editorRect: g
1070
1031
  };
1071
1032
  }
1072
- function G(t) {
1033
+ function K(t) {
1073
1034
  const {
1074
1035
  state: l
1075
1036
  } = t, n = l.selection.from;
1076
1037
  let o = null;
1077
- return l.doc.nodesBetween(0, l.doc.content.size, (u, d) => {
1078
- if (u.type.name === "table" && d <= n && n <= d + u.nodeSize)
1038
+ return l.doc.nodesBetween(0, l.doc.content.size, (i, u) => {
1039
+ if (i.type.name === "table" && u <= n && n <= u + i.nodeSize)
1079
1040
  return o = {
1080
- node: u,
1081
- pos: d
1041
+ node: i,
1042
+ pos: u
1082
1043
  }, !1;
1083
1044
  }), o;
1084
1045
  }
1085
- const f1 = /* @__PURE__ */ p({
1046
+ const ft = /* @__PURE__ */ c({
1086
1047
  name: "TableControls",
1087
1048
  setup() {
1088
- const t = A("editor"), l = A("readonly"), n = y(null), o = y(null);
1089
- function u() {
1090
- const i = t?.value;
1091
- if (o.value && (o.value.classList.remove("tcc-cell-focused"), o.value = null), !i) {
1049
+ const t = H("editor"), l = H("readonly"), n = x(null), o = x(null);
1050
+ function i() {
1051
+ const r = t?.value;
1052
+ if (o.value && (o.value.classList.remove("tcc-cell-focused"), o.value = null), !r) {
1092
1053
  n.value = null;
1093
1054
  return;
1094
1055
  }
1095
- const s = v1(i);
1096
- n.value = s, s && (s.cell.classList.add("tcc-cell-focused"), o.value = s.cell);
1056
+ const C = vt(r);
1057
+ n.value = C, C && (C.cell.classList.add("tcc-cell-focused"), o.value = C.cell);
1097
1058
  }
1098
- K((i) => {
1099
- const s = t?.value;
1100
- s && (s.on("selectionUpdate", u), s.on("transaction", u), i(() => {
1101
- s.off("selectionUpdate", u), s.off("transaction", u), o.value && (o.value.classList.remove("tcc-cell-focused"), o.value = null);
1059
+ G((r) => {
1060
+ const C = t?.value;
1061
+ C && (C.on("selectionUpdate", i), C.on("transaction", i), r(() => {
1062
+ C.off("selectionUpdate", i), C.off("transaction", i), o.value && (o.value.classList.remove("tcc-cell-focused"), o.value = null);
1102
1063
  }));
1103
1064
  });
1104
- function d(i) {
1105
- const s = t?.value;
1106
- if (!s || !n.value) return;
1065
+ function u(r) {
1066
+ const C = t?.value;
1067
+ if (!C || !n.value) return;
1107
1068
  const {
1108
- colIndex: r,
1109
- totalCols: x
1110
- } = n.value, k = i === "left" ? r - 1 : r + 1;
1111
- if (k < 0 || k >= x) return;
1112
- const a = G(s);
1069
+ colIndex: g,
1070
+ totalCols: I
1071
+ } = n.value, k = r === "left" ? g - 1 : g + 1;
1072
+ if (k < 0 || k >= I) return;
1073
+ const a = K(C);
1113
1074
  if (!a) return;
1114
1075
  const {
1115
- node: C,
1116
- pos: v
1076
+ node: d,
1077
+ pos: f
1117
1078
  } = a, h = [];
1118
- C.forEach((I) => {
1119
- if (I.type.name !== "tableRow") {
1120
- h.push(I);
1079
+ d.forEach((L) => {
1080
+ if (L.type.name !== "tableRow") {
1081
+ h.push(L);
1121
1082
  return;
1122
1083
  }
1123
- const M = [];
1124
- I.forEach((U) => M.push(U));
1125
- const S = M[r];
1126
- M[r] = M[k], M[k] = S, h.push(I.type.create(I.attrs, M, I.marks));
1084
+ const A = [];
1085
+ L.forEach((U) => A.push(U));
1086
+ const S = A[g];
1087
+ A[g] = A[k], A[k] = S, h.push(L.type.create(L.attrs, A, L.marks));
1127
1088
  });
1128
- const B = C.type.create(C.attrs, h, C.marks), V = s.state.tr.replaceWith(v, v + C.nodeSize, B);
1129
- s.view.dispatch(V);
1089
+ const y = d.type.create(d.attrs, h, d.marks), V = C.state.tr.replaceWith(f, f + d.nodeSize, y);
1090
+ C.view.dispatch(V);
1130
1091
  }
1131
- function f(i) {
1132
- const s = t?.value;
1133
- if (!s || !n.value) return;
1092
+ function v(r) {
1093
+ const C = t?.value;
1094
+ if (!C || !n.value) return;
1134
1095
  const {
1135
- rowIndex: r,
1136
- totalRows: x
1137
- } = n.value, k = i === "up" ? r - 1 : r + 1;
1138
- if (k < 0 || k >= x) return;
1139
- const a = G(s);
1096
+ rowIndex: g,
1097
+ totalRows: I
1098
+ } = n.value, k = r === "up" ? g - 1 : g + 1;
1099
+ if (k < 0 || k >= I) return;
1100
+ const a = K(C);
1140
1101
  if (!a) return;
1141
1102
  const {
1142
- node: C,
1143
- pos: v
1103
+ node: d,
1104
+ pos: f
1144
1105
  } = a, h = [];
1145
- C.forEach((M) => h.push(M));
1146
- const B = h[r];
1147
- h[r] = h[k], h[k] = B;
1148
- const V = C.type.create(C.attrs, h, C.marks), I = s.state.tr.replaceWith(v, v + C.nodeSize, V);
1149
- s.view.dispatch(I);
1106
+ d.forEach((A) => h.push(A));
1107
+ const y = h[g];
1108
+ h[g] = h[k], h[k] = y;
1109
+ const V = d.type.create(d.attrs, h, d.marks), L = C.state.tr.replaceWith(f, f + d.nodeSize, V);
1110
+ C.view.dispatch(L);
1150
1111
  }
1151
- const m = () => e("svg", {
1112
+ const p = () => e("svg", {
1152
1113
  width: "16",
1153
1114
  height: "4",
1154
1115
  viewBox: "0 0 16 4",
@@ -1165,7 +1126,7 @@ const f1 = /* @__PURE__ */ p({
1165
1126
  cx: "14",
1166
1127
  cy: "2",
1167
1128
  r: "1.5"
1168
- }, null)]), c = () => e("svg", {
1129
+ }, null)]), s = () => e("svg", {
1169
1130
  width: "4",
1170
1131
  height: "16",
1171
1132
  viewBox: "0 0 4 16",
@@ -1182,7 +1143,7 @@ const f1 = /* @__PURE__ */ p({
1182
1143
  cx: "2",
1183
1144
  cy: "14",
1184
1145
  r: "1.5"
1185
- }, null)]), H = () => e("svg", {
1146
+ }, null)]), B = () => e("svg", {
1186
1147
  width: "10",
1187
1148
  height: "10",
1188
1149
  viewBox: "0 0 10 10",
@@ -1195,122 +1156,505 @@ const f1 = /* @__PURE__ */ p({
1195
1156
  }, null)]);
1196
1157
  return () => {
1197
1158
  if (l?.value) return null;
1198
- const i = n.value;
1199
- if (!i) return null;
1159
+ const r = n.value;
1160
+ if (!r) return null;
1200
1161
  const {
1201
- colIndex: s,
1202
- rowIndex: r,
1203
- totalCols: x,
1162
+ colIndex: C,
1163
+ rowIndex: g,
1164
+ totalCols: I,
1204
1165
  totalRows: k,
1205
1166
  cellRect: a,
1206
- tableRect: C,
1207
- editorRect: v
1208
- } = i, h = C.top - v.top, B = C.left - v.left, V = C.right - v.left, I = C.bottom - v.top, M = a.left - v.left, S = a.top - v.top, U = a.width, $ = a.height, ie = {
1167
+ tableRect: d,
1168
+ editorRect: f
1169
+ } = r, h = d.top - f.top, y = 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 = {
1209
1170
  position: "absolute",
1210
1171
  top: `${h - 20}px`,
1211
- left: `${M + U / 2 - 18}px`
1172
+ left: `${A + U / 2 - 18}px`
1212
1173
  }, ue = {
1213
1174
  position: "absolute",
1214
- top: `${S + $ / 2 - 18}px`,
1215
- left: `${B - 20}px`
1175
+ top: `${S + O / 2 - 18}px`,
1176
+ left: `${y - 20}px`
1216
1177
  }, re = {
1217
1178
  position: "absolute",
1218
- top: `${S + $ / 2 - 12}px`,
1179
+ top: `${S + O / 2 - 12}px`,
1219
1180
  left: `${V + 6}px`
1220
1181
  }, ae = {
1221
1182
  position: "absolute",
1222
- top: `${I + 6}px`,
1223
- left: `${M + U / 2 - 12}px`
1224
- }, se = s === 0, z = s === x - 1, ce = r === 0, N = r === k - 1, T = t?.value;
1183
+ top: `${L + 6}px`,
1184
+ left: `${A + U / 2 - 12}px`
1185
+ }, se = C === 0, $ = C === I - 1, ce = g === 0, N = g === k - 1, F = t?.value;
1225
1186
  return e("div", {
1226
1187
  class: "table-cell-controls"
1227
1188
  }, [e(j, {
1228
1189
  trigger: "click",
1229
1190
  placement: "bottom",
1230
1191
  style: ie,
1231
- onCommand: (L) => {
1232
- L === "move-left" ? d("left") : L === "move-right" ? d("right") : L === "insert-left" ? T?.chain().focus().addColumnBefore().run() : L === "insert-right" ? T?.chain().focus().addColumnAfter().run() : L === "delete" && T?.chain().focus().deleteColumn().run();
1192
+ onCommand: (M) => {
1193
+ M === "move-left" ? u("left") : M === "move-right" ? u("right") : M === "insert-left" ? F?.chain().focus().addColumnBefore().run() : M === "insert-right" ? F?.chain().focus().addColumnAfter().run() : M === "delete" && F?.chain().focus().deleteColumn().run();
1233
1194
  }
1234
1195
  }, {
1235
1196
  default: () => [e("button", {
1236
1197
  class: "tcc-btn tcc-btn--col"
1237
- }, [e(m, null, null)])],
1198
+ }, [e(p, null, null)])],
1238
1199
  dropdown: () => e(W, null, {
1239
1200
  default: () => [e(E, {
1240
1201
  command: "move-left",
1241
1202
  disabled: se
1242
1203
  }, {
1243
- default: () => [g("移动列到左侧")]
1204
+ default: () => [m("移动列到左侧")]
1244
1205
  }), e(E, {
1245
1206
  command: "move-right",
1246
- disabled: z
1207
+ disabled: $
1247
1208
  }, {
1248
- default: () => [g("移动列到右侧")]
1209
+ default: () => [m("移动列到右侧")]
1249
1210
  }), e(E, {
1250
1211
  command: "insert-left"
1251
1212
  }, {
1252
- default: () => [g("在左侧插入一列")]
1213
+ default: () => [m("在左侧插入一列")]
1253
1214
  }), e(E, {
1254
1215
  command: "insert-right"
1255
1216
  }, {
1256
- default: () => [g("在右侧插入一列")]
1217
+ default: () => [m("在右侧插入一列")]
1257
1218
  }), e(E, {
1258
1219
  command: "delete",
1259
1220
  divided: !0
1260
1221
  }, {
1261
- default: () => [g("删除列")]
1222
+ default: () => [m("删除列")]
1262
1223
  })]
1263
1224
  })
1264
1225
  }), e(j, {
1265
1226
  trigger: "click",
1266
1227
  placement: "right",
1267
1228
  style: ue,
1268
- onCommand: (L) => {
1269
- L === "move-up" ? f("up") : L === "move-down" ? f("down") : L === "insert-above" ? T?.chain().focus().addRowBefore().run() : L === "insert-below" ? T?.chain().focus().addRowAfter().run() : L === "delete" && T?.chain().focus().deleteRow().run();
1229
+ onCommand: (M) => {
1230
+ 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();
1270
1231
  }
1271
1232
  }, {
1272
1233
  default: () => [e("button", {
1273
1234
  class: "tcc-btn tcc-btn--row"
1274
- }, [e(c, null, null)])],
1235
+ }, [e(s, null, null)])],
1275
1236
  dropdown: () => e(W, null, {
1276
1237
  default: () => [e(E, {
1277
1238
  command: "move-up",
1278
1239
  disabled: ce
1279
1240
  }, {
1280
- default: () => [g("上移")]
1241
+ default: () => [m("上移")]
1281
1242
  }), e(E, {
1282
1243
  command: "move-down",
1283
1244
  disabled: N
1284
1245
  }, {
1285
- default: () => [g("下移")]
1246
+ default: () => [m("下移")]
1286
1247
  }), e(E, {
1287
1248
  command: "insert-above"
1288
1249
  }, {
1289
- default: () => [g("在上方插入一行")]
1250
+ default: () => [m("在上方插入一行")]
1290
1251
  }), e(E, {
1291
1252
  command: "insert-below"
1292
1253
  }, {
1293
- default: () => [g("在下方插入一行")]
1254
+ default: () => [m("在下方插入一行")]
1294
1255
  }), e(E, {
1295
1256
  command: "delete",
1296
1257
  divided: !0
1297
1258
  }, {
1298
- default: () => [g("删除行")]
1259
+ default: () => [m("删除行")]
1299
1260
  })]
1300
1261
  })
1301
- }), z && e("button", {
1262
+ }), $ && e("button", {
1302
1263
  class: "tcc-btn tcc-btn--add",
1303
1264
  style: re,
1304
- onClick: () => T?.chain().focus().addColumnAfter().run()
1305
- }, [e(H, null, null)]), N && e("button", {
1265
+ onClick: () => F?.chain().focus().addColumnAfter().run()
1266
+ }, [e(B, null, null)]), N && e("button", {
1306
1267
  class: "tcc-btn tcc-btn--add",
1307
1268
  style: ae,
1308
- onClick: () => T?.chain().focus().addRowAfter().run()
1309
- }, [e(H, null, null)])]);
1269
+ onClick: () => F?.chain().focus().addRowAfter().run()
1270
+ }, [e(B, null, null)])]);
1271
+ };
1272
+ }
1273
+ }), Yt = {
1274
+ name: "table",
1275
+ install: () => ({
1276
+ extensions: [Se.configure({ resizable: !0 }), Ze, De, Re],
1277
+ controlComponent: ft
1278
+ }),
1279
+ toolbarComponent: pt
1280
+ }, ht = /* @__PURE__ */ c({
1281
+ name: "MathIcon",
1282
+ setup(t, {
1283
+ attrs: l
1284
+ }) {
1285
+ return () => e("svg", b({
1286
+ width: "24",
1287
+ height: "24",
1288
+ viewBox: "0 0 24 24",
1289
+ fill: "currentColor",
1290
+ xmlns: "http://www.w3.org/2000/svg"
1291
+ }, l), [e("path", {
1292
+ "fill-rule": "evenodd",
1293
+ "clip-rule": "evenodd",
1294
+ 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",
1295
+ fill: "currentColor"
1296
+ }, null)]);
1297
+ }
1298
+ }), mt = /* @__PURE__ */ c({
1299
+ name: "MathButton",
1300
+ setup() {
1301
+ const t = H("editor"), l = H("openMathDialog");
1302
+ return () => e(w, {
1303
+ icon: ht,
1304
+ tooltip: "数学公式",
1305
+ isActive: t?.value?.isActive("inlineMath") || t?.value?.isActive("blockMath"),
1306
+ onClick: () => l?.()
1307
+ }, null);
1308
+ }
1309
+ }), gt = /* @__PURE__ */ c({
1310
+ name: "MathEditDialog",
1311
+ props: {
1312
+ visible: {
1313
+ type: Boolean,
1314
+ required: !0
1315
+ },
1316
+ latex: {
1317
+ type: String,
1318
+ required: !0
1319
+ },
1320
+ pos: {
1321
+ type: Number,
1322
+ default: null
1323
+ },
1324
+ type: {
1325
+ type: String,
1326
+ required: !0
1327
+ }
1328
+ },
1329
+ emits: ["update:visible"],
1330
+ setup(t, {
1331
+ emit: l
1332
+ }) {
1333
+ const n = H("editor"), o = x(""), i = x("inline");
1334
+ R(() => t.latex, (s) => {
1335
+ o.value = s;
1336
+ }, {
1337
+ immediate: !0
1338
+ }), R(() => t.type, (s) => {
1339
+ i.value = s;
1340
+ }, {
1341
+ immediate: !0
1342
+ });
1343
+ const u = T(() => t.pos === null), v = T(() => o.value.trim() ? _e.renderToString(o.value, {
1344
+ displayMode: i.value === "block",
1345
+ throwOnError: !1
1346
+ }) : ""), p = () => {
1347
+ const s = n?.value;
1348
+ if (!(!s || !o.value.trim())) {
1349
+ if (u.value)
1350
+ i.value === "inline" ? s.chain().focus().insertInlineMath({
1351
+ latex: o.value
1352
+ }).run() : s.chain().focus().insertBlockMath({
1353
+ latex: o.value
1354
+ }).run();
1355
+ else if (i.value === t.type)
1356
+ t.type === "inline" ? s.commands.updateInlineMath({
1357
+ latex: o.value,
1358
+ pos: t.pos
1359
+ }) : s.commands.updateBlockMath({
1360
+ latex: o.value,
1361
+ pos: t.pos
1362
+ });
1363
+ else {
1364
+ const B = t.pos;
1365
+ t.type === "inline" ? s.chain().focus().deleteInlineMath({
1366
+ pos: B
1367
+ }).insertBlockMath({
1368
+ latex: o.value
1369
+ }).run() : s.chain().focus().deleteBlockMath({
1370
+ pos: B
1371
+ }).insertInlineMath({
1372
+ latex: o.value
1373
+ }).run();
1374
+ }
1375
+ l("update:visible", !1);
1376
+ }
1377
+ };
1378
+ return () => e(ye, {
1379
+ modelValue: t.visible,
1380
+ title: u.value ? "插入数学公式" : "编辑数学公式",
1381
+ width: "520px",
1382
+ "onUpdate:modelValue": (s) => l("update:visible", s)
1383
+ }, {
1384
+ default: () => [e("div", {
1385
+ class: "math-dialog"
1386
+ }, [e(Be, {
1387
+ modelValue: i.value,
1388
+ "onUpdate:modelValue": (s) => {
1389
+ i.value = s;
1390
+ }
1391
+ }, {
1392
+ default: () => [e(q, {
1393
+ value: "inline"
1394
+ }, {
1395
+ default: () => [m("行内公式")]
1396
+ }), e(q, {
1397
+ value: "block"
1398
+ }, {
1399
+ default: () => [m("块级公式")]
1400
+ })]
1401
+ }), e(X, {
1402
+ modelValue: o.value,
1403
+ type: "textarea",
1404
+ rows: 3,
1405
+ placeholder: "请输入 LaTeX 公式,例如:E=mc^2",
1406
+ "onUpdate:modelValue": (s) => {
1407
+ o.value = s;
1408
+ }
1409
+ }, null), e("div", {
1410
+ class: ["math-preview", {
1411
+ "math-preview--empty": !v.value
1412
+ }]
1413
+ }, [v.value ? e("div", {
1414
+ innerHTML: v.value
1415
+ }, null) : e("span", {
1416
+ class: "math-preview__placeholder"
1417
+ }, [m("预览将在此处显示")])])])],
1418
+ footer: () => e(de, null, [e(Z, {
1419
+ onClick: () => l("update:visible", !1)
1420
+ }, {
1421
+ default: () => [m("取消")]
1422
+ }), e(Z, {
1423
+ type: "primary",
1424
+ disabled: !o.value.trim(),
1425
+ onClick: p
1426
+ }, {
1427
+ default: () => [m("确认")]
1428
+ })])
1429
+ });
1430
+ }
1431
+ }), e1 = {
1432
+ name: "math",
1433
+ toolbarComponent: mt,
1434
+ install(t) {
1435
+ const l = x(!1), n = x(""), o = x(null), i = x("inline"), u = (p = {}) => {
1436
+ t.readonly.value || (n.value = p.latex ?? "", o.value = p.pos ?? null, i.value = p.type ?? "inline", l.value = !0);
1437
+ };
1438
+ t.provide("openMathDialog", u);
1439
+ const v = c({
1440
+ name: "MathEditDialogWrapper",
1441
+ setup: () => () => pe(gt, {
1442
+ visible: l.value,
1443
+ latex: n.value,
1444
+ pos: o.value,
1445
+ type: i.value,
1446
+ "onUpdate:visible": (p) => {
1447
+ l.value = p;
1448
+ }
1449
+ })
1450
+ });
1451
+ return {
1452
+ extensions: [
1453
+ Ue.configure({
1454
+ inlineOptions: {
1455
+ onClick: (p, s) => u({ latex: p.attrs.latex, pos: s, type: "inline" })
1456
+ },
1457
+ blockOptions: {
1458
+ onClick: (p, s) => u({ latex: p.attrs.latex, pos: s, type: "block" })
1459
+ }
1460
+ })
1461
+ ],
1462
+ controlComponent: v
1463
+ };
1464
+ }
1465
+ }, wt = /* @__PURE__ */ c({
1466
+ name: "ImageUploadView",
1467
+ props: he,
1468
+ setup(t) {
1469
+ const l = T(() => t.node.attrs.accept), n = T(() => t.node.attrs.limit), o = T(() => t.node.attrs.maxSize), i = x([]), u = x(), v = x(!1), p = async (a) => {
1470
+ if (o.value > 0 && a.size > o.value)
1471
+ return t.extension.options.onError?.(new Error(`文件大小超出限制 ${o.value / 1024 / 1024}MB`)), null;
1472
+ const d = crypto.randomUUID();
1473
+ i.value.push({
1474
+ id: d,
1475
+ file: a,
1476
+ progress: 0,
1477
+ status: "uploading"
1478
+ });
1479
+ try {
1480
+ const f = t.extension.options.upload;
1481
+ if (!f) throw new Error("未配置 upload 函数");
1482
+ const h = await f(a);
1483
+ if (!h) throw new Error("上传失败:未返回 URL");
1484
+ const y = i.value.find((V) => V.id === d);
1485
+ return y && (y.status = "success", y.progress = 100), t.extension.options.onSuccess?.(h), h;
1486
+ } catch (f) {
1487
+ const h = i.value.find((y) => y.id === d);
1488
+ return h && (h.status = "error", h.progress = 0), t.extension.options.onError?.(f instanceof Error ? f : new Error("上传失败")), null;
1489
+ }
1490
+ }, s = async (a) => {
1491
+ if (!a.length) return;
1492
+ if (a.length > n.value) {
1493
+ t.extension.options.onError?.(new Error(`最多上传 ${n.value} 个文件`));
1494
+ return;
1495
+ }
1496
+ const d = (await Promise.all(a.map(p))).filter((f) => !!f);
1497
+ if (d.length > 0) {
1498
+ const f = t.getPos();
1499
+ if (typeof f != "number") return;
1500
+ const h = d.map((y) => ({
1501
+ type: "image",
1502
+ attrs: {
1503
+ src: y
1504
+ }
1505
+ }));
1506
+ t.editor.chain().focus().deleteRange({
1507
+ from: f,
1508
+ to: f + t.node.nodeSize
1509
+ }).insertContentAt(f, h).run();
1510
+ }
1511
+ }, B = () => {
1512
+ i.value.length === 0 && u.value && (u.value.value = "", u.value.click());
1513
+ }, r = (a) => {
1514
+ const d = a.target.files;
1515
+ d && s(Array.from(d));
1516
+ }, C = (a) => {
1517
+ a.preventDefault(), v.value = !0;
1518
+ }, g = (a) => {
1519
+ a.currentTarget.contains(a.relatedTarget) || (v.value = !1);
1520
+ }, I = (a) => {
1521
+ a.preventDefault(), v.value = !1;
1522
+ const d = Array.from(a.dataTransfer?.files ?? []);
1523
+ d.length && s(d);
1524
+ }, k = (a) => {
1525
+ i.value = i.value.filter((d) => d.id !== a);
1526
+ };
1527
+ return () => e(me, {
1528
+ class: "tiptap-image-upload"
1529
+ }, {
1530
+ default: () => [e("div", {
1531
+ onClick: B
1532
+ }, [i.value.length ? e("div", {
1533
+ class: "tiptap-image-upload-previews"
1534
+ }, [i.value.map((a) => e("div", {
1535
+ key: a.id,
1536
+ class: "tiptap-image-upload-preview"
1537
+ }, [a.status === "uploading" && e("div", {
1538
+ class: "tiptap-image-upload-progress",
1539
+ style: {
1540
+ width: `${a.progress}%`
1541
+ }
1542
+ }, null), e("div", {
1543
+ class: "tiptap-image-upload-preview-content"
1544
+ }, [e("span", {
1545
+ class: "tiptap-image-upload-text"
1546
+ }, [a.file.name]), e("span", {
1547
+ class: "tiptap-image-upload-subtext"
1548
+ }, [a.status === "uploading" ? `${a.progress}%` : a.status === "error" ? "上传失败" : "上传成功"]), e("button", {
1549
+ class: "tiptap-image-upload-remove",
1550
+ onClick: (d) => {
1551
+ d.stopPropagation(), k(a.id);
1552
+ }
1553
+ }, [m("×")])])]))]) : e("div", {
1554
+ class: ["tiptap-image-upload-drag-area", {
1555
+ "drag-active": v.value
1556
+ }],
1557
+ onDragover: C,
1558
+ onDragleave: g,
1559
+ onDrop: I
1560
+ }, [e("div", {
1561
+ class: "tiptap-image-upload-content"
1562
+ }, [e("span", {
1563
+ class: "tiptap-image-upload-text"
1564
+ }, [e("em", null, [m("点击上传")]), m(" 或拖拽图片到此处")]), e("span", {
1565
+ class: "tiptap-image-upload-subtext"
1566
+ }, [m("最多 "), n.value, m(" 个文件"), o.value ? `,每个不超过 ${o.value / 1024 / 1024}MB` : ""])])]), e("input", {
1567
+ ref: u,
1568
+ type: "file",
1569
+ accept: l.value,
1570
+ multiple: n.value > 1,
1571
+ onChange: r,
1572
+ onClick: (a) => a.stopPropagation()
1573
+ }, null)])]
1574
+ });
1575
+ }
1576
+ }), bt = Pe.create({
1577
+ name: "imageUpload",
1578
+ group: "block",
1579
+ draggable: !0,
1580
+ selectable: !0,
1581
+ atom: !0,
1582
+ addOptions() {
1583
+ return {
1584
+ type: "image",
1585
+ accept: "image/*",
1586
+ limit: 1,
1587
+ maxSize: 0,
1588
+ upload: (t) => new Promise((l) => {
1589
+ const n = new FileReader();
1590
+ n.onloadend = () => l(n.result), n.readAsDataURL(t);
1591
+ }),
1592
+ onError: void 0,
1593
+ onSuccess: void 0,
1594
+ HTMLAttributes: {}
1595
+ };
1596
+ },
1597
+ addAttributes() {
1598
+ return {
1599
+ accept: {
1600
+ default: this.options.accept
1601
+ },
1602
+ limit: {
1603
+ default: this.options.limit
1604
+ },
1605
+ maxSize: {
1606
+ default: this.options.maxSize
1607
+ }
1608
+ };
1609
+ },
1610
+ parseHTML() {
1611
+ return [{
1612
+ tag: 'div[data-type="image-upload"]'
1613
+ }];
1614
+ },
1615
+ renderHTML({
1616
+ HTMLAttributes: t
1617
+ }) {
1618
+ return ["div", ze({
1619
+ "data-type": "image-upload"
1620
+ }, t)];
1621
+ },
1622
+ addNodeView() {
1623
+ return ge(wt);
1624
+ },
1625
+ addCommands() {
1626
+ return {
1627
+ setImageUploadNode: () => ({
1628
+ commands: t
1629
+ }) => t.insertContent({
1630
+ type: this.name
1631
+ })
1632
+ };
1633
+ },
1634
+ addKeyboardShortcuts() {
1635
+ return {
1636
+ Enter: ({
1637
+ editor: t
1638
+ }) => {
1639
+ const {
1640
+ selection: l
1641
+ } = t.state, {
1642
+ nodeAfter: n
1643
+ } = l.$from;
1644
+ if (n?.type.name === "imageUpload" && t.isActive("imageUpload")) {
1645
+ const o = t.view.nodeDOM(l.$from.pos);
1646
+ if (o instanceof HTMLElement) {
1647
+ const i = o.firstChild;
1648
+ if (i instanceof HTMLElement)
1649
+ return i.click(), !0;
1650
+ }
1651
+ }
1652
+ return !1;
1653
+ }
1310
1654
  };
1311
1655
  }
1312
- }), h1 = /* @__PURE__ */ p({
1313
- name: "MathIcon",
1656
+ }), kt = /* @__PURE__ */ c({
1657
+ name: "ImagePlusIcon",
1314
1658
  setup(t, {
1315
1659
  attrs: l
1316
1660
  }) {
@@ -1323,144 +1667,21 @@ const f1 = /* @__PURE__ */ p({
1323
1667
  }, l), [e("path", {
1324
1668
  "fill-rule": "evenodd",
1325
1669
  "clip-rule": "evenodd",
1326
- 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",
1670
+ 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",
1327
1671
  fill: "currentColor"
1328
1672
  }, null)]);
1329
1673
  }
1330
- }), g1 = /* @__PURE__ */ p({
1331
- name: "MathButton",
1674
+ }), xt = /* @__PURE__ */ c({
1675
+ name: "ImageButton",
1332
1676
  setup() {
1333
- const t = A("editor"), l = A("openMathDialog");
1334
- return () => e(w, {
1335
- icon: h1,
1336
- tooltip: "数学公式",
1337
- isActive: t?.value?.isActive("inlineMath") || t?.value?.isActive("blockMath"),
1338
- onClick: () => l?.()
1339
- }, null);
1340
- }
1341
- }), m1 = /* @__PURE__ */ p({
1342
- name: "MathEditDialog",
1343
- props: {
1344
- visible: {
1345
- type: Boolean,
1346
- required: !0
1347
- },
1348
- latex: {
1349
- type: String,
1350
- required: !0
1351
- },
1352
- pos: {
1353
- type: Number,
1354
- default: null
1355
- },
1356
- type: {
1357
- type: String,
1358
- required: !0
1359
- }
1360
- },
1361
- emits: ["update:visible"],
1362
- setup(t, {
1363
- emit: l
1364
- }) {
1365
- const n = A("editor"), o = y(""), u = y("inline");
1366
- D(() => t.latex, (c) => {
1367
- o.value = c;
1368
- }, {
1369
- immediate: !0
1370
- }), D(() => t.type, (c) => {
1371
- u.value = c;
1372
- }, {
1373
- immediate: !0
1374
- });
1375
- const d = F(() => t.pos === null), f = F(() => o.value.trim() ? _e.renderToString(o.value, {
1376
- displayMode: u.value === "block",
1377
- throwOnError: !1
1378
- }) : ""), m = () => {
1379
- const c = n?.value;
1380
- if (!(!c || !o.value.trim())) {
1381
- if (d.value)
1382
- u.value === "inline" ? c.chain().focus().insertInlineMath({
1383
- latex: o.value
1384
- }).run() : c.chain().focus().insertBlockMath({
1385
- latex: o.value
1386
- }).run();
1387
- else if (u.value === t.type)
1388
- t.type === "inline" ? c.commands.updateInlineMath({
1389
- latex: o.value,
1390
- pos: t.pos
1391
- }) : c.commands.updateBlockMath({
1392
- latex: o.value,
1393
- pos: t.pos
1394
- });
1395
- else {
1396
- const H = t.pos;
1397
- t.type === "inline" ? c.chain().focus().deleteInlineMath({
1398
- pos: H
1399
- }).insertBlockMath({
1400
- latex: o.value
1401
- }).run() : c.chain().focus().deleteBlockMath({
1402
- pos: H
1403
- }).insertInlineMath({
1404
- latex: o.value
1405
- }).run();
1406
- }
1407
- l("update:visible", !1);
1408
- }
1409
- };
1410
- return () => e(Se, {
1411
- modelValue: t.visible,
1412
- title: d.value ? "插入数学公式" : "编辑数学公式",
1413
- width: "520px",
1414
- "onUpdate:modelValue": (c) => l("update:visible", c)
1415
- }, {
1416
- default: () => [e("div", {
1417
- class: "math-dialog"
1418
- }, [e(Ue, {
1419
- modelValue: u.value,
1420
- "onUpdate:modelValue": (c) => {
1421
- u.value = c;
1422
- }
1423
- }, {
1424
- default: () => [e(q, {
1425
- value: "inline"
1426
- }, {
1427
- default: () => [g("行内公式")]
1428
- }), e(q, {
1429
- value: "block"
1430
- }, {
1431
- default: () => [g("块级公式")]
1432
- })]
1433
- }), e(X, {
1434
- modelValue: o.value,
1435
- type: "textarea",
1436
- rows: 3,
1437
- placeholder: "请输入 LaTeX 公式,例如:E=mc^2",
1438
- "onUpdate:modelValue": (c) => {
1439
- o.value = c;
1440
- }
1441
- }, null), e("div", {
1442
- class: ["math-preview", {
1443
- "math-preview--empty": !f.value
1444
- }]
1445
- }, [f.value ? e("div", {
1446
- innerHTML: f.value
1447
- }, null) : e("span", {
1448
- class: "math-preview__placeholder"
1449
- }, [g("预览将在此处显示")])])])],
1450
- footer: () => e(de, null, [e(Z, {
1451
- onClick: () => l("update:visible", !1)
1452
- }, {
1453
- default: () => [g("取消")]
1454
- }), e(Z, {
1455
- type: "primary",
1456
- disabled: !o.value.trim(),
1457
- onClick: m
1458
- }, {
1459
- default: () => [g("确认")]
1460
- })])
1461
- });
1677
+ const t = H("editor");
1678
+ return () => e("div", null, [e(w, {
1679
+ icon: kt,
1680
+ tooltip: "图片",
1681
+ onClick: () => t?.value?.commands.setImageUploadNode()
1682
+ }, null)]);
1462
1683
  }
1463
- }), w1 = [{
1684
+ }), Ht = [{
1464
1685
  value: "left",
1465
1686
  title: "居左",
1466
1687
  Icon: le
@@ -1473,12 +1694,12 @@ const f1 = /* @__PURE__ */ p({
1473
1694
  title: "居右",
1474
1695
  Icon: oe
1475
1696
  }], _ = (t) => t.preventDefault();
1476
- function b1(t) {
1697
+ function yt(t) {
1477
1698
  if (!t.isActive("image")) return null;
1478
1699
  const {
1479
1700
  selection: l
1480
1701
  } = t.state;
1481
- if (!(l instanceof Me) || l.node.type.name !== "image") return null;
1702
+ if (!(l instanceof Ie) || l.node.type.name !== "image") return null;
1482
1703
  const n = l.node;
1483
1704
  return {
1484
1705
  pos: l.from,
@@ -1487,11 +1708,11 @@ function b1(t) {
1487
1708
  align: n.attrs.align ?? "left"
1488
1709
  };
1489
1710
  }
1490
- function k1(t) {
1711
+ function Bt(t) {
1491
1712
  const l = t.startsWith("data:") ? "image.png" : t.split("/").pop()?.split("?")[0] || "image.png", n = document.createElement("a");
1492
1713
  n.href = t, n.download = l, document.body.appendChild(n), n.click(), document.body.removeChild(n);
1493
1714
  }
1494
- const x1 = () => e("svg", {
1715
+ const At = () => e("svg", {
1495
1716
  width: "16",
1496
1717
  height: "16",
1497
1718
  viewBox: "0 0 24 24",
@@ -1509,7 +1730,7 @@ const x1 = () => e("svg", {
1509
1730
  y1: "15",
1510
1731
  x2: "12",
1511
1732
  y2: "3"
1512
- }, null)]), H1 = () => e("svg", {
1733
+ }, null)]), Mt = () => e("svg", {
1513
1734
  width: "16",
1514
1735
  height: "16",
1515
1736
  viewBox: "0 0 24 24",
@@ -1522,7 +1743,7 @@ const x1 = () => e("svg", {
1522
1743
  points: "1 4 1 10 7 10"
1523
1744
  }, null), e("path", {
1524
1745
  d: "M3.51 15a9 9 0 1 0 .49-4.1L1 10"
1525
- }, null)]), y1 = () => e("svg", {
1746
+ }, null)]), It = () => e("svg", {
1526
1747
  width: "16",
1527
1748
  height: "16",
1528
1749
  viewBox: "0 0 24 24",
@@ -1539,38 +1760,38 @@ const x1 = () => e("svg", {
1539
1760
  d: "M10 11v6M14 11v6"
1540
1761
  }, null), e("path", {
1541
1762
  d: "M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"
1542
- }, null)]), A1 = /* @__PURE__ */ p({
1763
+ }, null)]), Lt = /* @__PURE__ */ c({
1543
1764
  name: "ImageControls",
1544
1765
  setup() {
1545
- const t = A("editor"), l = A("readonly"), n = y(null);
1766
+ const t = H("editor"), l = H("readonly"), n = x(null);
1546
1767
  function o() {
1547
- const u = t?.value;
1548
- if (!u) {
1768
+ const i = t?.value;
1769
+ if (!i) {
1549
1770
  n.value = null;
1550
1771
  return;
1551
1772
  }
1552
- n.value = b1(u);
1773
+ n.value = yt(i);
1553
1774
  }
1554
- return K((u) => {
1555
- const d = t?.value;
1556
- d && (d.on("transaction", o), u(() => {
1557
- d.off("transaction", o);
1775
+ return G((i) => {
1776
+ const u = t?.value;
1777
+ u && (u.on("transaction", o), i(() => {
1778
+ u.off("transaction", o);
1558
1779
  }));
1559
1780
  }), () => {
1560
- const u = n.value;
1781
+ const i = n.value;
1782
+ if (!i) return null;
1783
+ const u = t?.value;
1561
1784
  if (!u) return null;
1562
- const d = t?.value;
1563
- if (!d) return null;
1564
1785
  const {
1565
- pos: f,
1566
- nodeSize: m,
1567
- src: c,
1568
- align: H
1569
- } = u, i = l?.value ?? !1, s = d.view.nodeDOM(f);
1570
- if (!s || !(s instanceof HTMLElement)) return null;
1571
- const r = s.querySelector("[data-resize-wrapper]") ?? s, x = d.view.dom.closest(".tiptap-editor");
1572
- if (!x) return null;
1573
- const k = r.getBoundingClientRect(), a = x.getBoundingClientRect(), C = {
1786
+ pos: v,
1787
+ nodeSize: p,
1788
+ src: s,
1789
+ align: B
1790
+ } = i, r = l?.value ?? !1, C = u.view.nodeDOM(v);
1791
+ if (!C || !(C instanceof HTMLElement)) return null;
1792
+ const g = C.querySelector("[data-resize-wrapper]") ?? C, I = u.view.dom.closest(".tiptap-editor");
1793
+ if (!I) return null;
1794
+ const k = g.getBoundingClientRect(), a = I.getBoundingClientRect(), d = {
1574
1795
  position: "absolute",
1575
1796
  top: `${k.top - a.top}px`,
1576
1797
  left: `${k.left - a.left + k.width / 2}px`,
@@ -1579,203 +1800,52 @@ const x1 = () => e("svg", {
1579
1800
  };
1580
1801
  return e("div", {
1581
1802
  class: "image-controls",
1582
- style: C
1583
- }, [!i && w1.map(({
1584
- value: v,
1803
+ style: d
1804
+ }, [!r && Ht.map(({
1805
+ value: f,
1585
1806
  title: h,
1586
- Icon: B
1807
+ Icon: y
1587
1808
  }) => e("button", {
1588
- key: v,
1589
- class: ["image-controls-btn", H === v && "is-active"],
1809
+ key: f,
1810
+ class: ["image-controls-btn", B === f && "is-active"],
1590
1811
  title: h,
1591
1812
  onMousedown: _,
1592
- onClick: () => d.chain().focus().updateAttributes("image", {
1593
- align: v
1813
+ onClick: () => u.chain().focus().updateAttributes("image", {
1814
+ align: f
1594
1815
  }).run()
1595
- }, [e(B, null, null)])), !i && e("span", {
1816
+ }, [e(y, null, null)])), !r && e("span", {
1596
1817
  class: "image-controls-separator"
1597
1818
  }, null), e("button", {
1598
1819
  class: "image-controls-btn",
1599
1820
  title: "下载",
1600
1821
  onMousedown: _,
1601
- onClick: () => k1(c)
1602
- }, [e(x1, null, null)]), !i && e("button", {
1822
+ onClick: () => Bt(s)
1823
+ }, [e(At, null, null)]), !r && e("button", {
1603
1824
  class: "image-controls-btn",
1604
1825
  title: "重新上传",
1605
1826
  onMousedown: _,
1606
- onClick: () => d.chain().focus().deleteRange({
1607
- from: f,
1608
- to: f + m
1609
- }).insertContentAt(f, {
1827
+ onClick: () => u.chain().focus().deleteRange({
1828
+ from: v,
1829
+ to: v + p
1830
+ }).insertContentAt(v, {
1610
1831
  type: "imageUpload"
1611
1832
  }).run()
1612
- }, [e(H1, null, null)]), !i && e("button", {
1833
+ }, [e(Mt, null, null)]), !r && e("button", {
1613
1834
  class: "image-controls-btn",
1614
1835
  title: "删除",
1615
1836
  onMousedown: _,
1616
- onClick: () => d.chain().focus().deleteRange({
1617
- from: f,
1618
- to: f + m
1837
+ onClick: () => u.chain().focus().deleteRange({
1838
+ from: v,
1839
+ to: v + p
1619
1840
  }).run()
1620
- }, [e(y1, null, null)])]);
1841
+ }, [e(It, null, null)])]);
1621
1842
  };
1622
1843
  }
1623
- }), B1 = /* @__PURE__ */ p({
1624
- name: "CodeBlockIcon",
1625
- setup(t, {
1626
- attrs: l
1627
- }) {
1628
- return () => e("svg", b({
1629
- width: "24",
1630
- height: "24",
1631
- viewBox: "0 0 24 24",
1632
- fill: "none",
1633
- stroke: "currentColor",
1634
- "stroke-width": "2",
1635
- "stroke-linecap": "round",
1636
- "stroke-linejoin": "round",
1637
- xmlns: "http://www.w3.org/2000/svg"
1638
- }, l), [e("polyline", {
1639
- points: "16 18 22 12 16 6"
1640
- }, null), e("polyline", {
1641
- points: "8 6 2 12 8 18"
1642
- }, null)]);
1643
- }
1644
- }), M1 = /* @__PURE__ */ p({
1645
- name: "CodeBlockButton",
1646
- setup() {
1647
- const t = A("editor");
1648
- return () => e(w, {
1649
- icon: B1,
1650
- tooltip: "代码块",
1651
- isActive: t?.value?.isActive("codeBlock"),
1652
- onClick: () => t?.value?.chain().focus().toggleCodeBlock().run()
1653
- }, null);
1654
- }
1655
- }), L1 = /* @__PURE__ */ p({
1656
- name: "BubbleMenuBar",
1657
- setup() {
1658
- const t = A("editor"), l = A("readonly");
1659
- return () => t?.value ? e(Oe, {
1660
- editor: t.value,
1661
- class: "bubble-menu",
1662
- options: {
1663
- placement: "top",
1664
- offset: {
1665
- mainAxis: 8
1666
- }
1667
- },
1668
- shouldShow: (n) => {
1669
- if (l?.value) return !1;
1670
- const {
1671
- editor: o,
1672
- from: u,
1673
- to: d
1674
- } = n;
1675
- return !(u === d || o.isActive("image") || o.isActive("table"));
1676
- }
1677
- }, {
1678
- default: () => [e("div", {
1679
- class: "bubble-menu-content"
1680
- }, [e(w, {
1681
- icon: Q,
1682
- tooltip: "粗体",
1683
- isActive: t.value.isActive("bold"),
1684
- onClick: () => t.value?.chain().focus().toggleBold().run()
1685
- }, null), e(w, {
1686
- icon: Y,
1687
- tooltip: "斜体",
1688
- isActive: t.value.isActive("italic"),
1689
- onClick: () => t.value?.chain().focus().toggleItalic().run()
1690
- }, null), e(w, {
1691
- icon: ee,
1692
- tooltip: "删除线",
1693
- isActive: t.value.isActive("strike"),
1694
- onClick: () => t.value?.chain().focus().toggleStrike().run()
1695
- }, null), e(w, {
1696
- icon: te,
1697
- tooltip: "下划线",
1698
- isActive: t.value.isActive("underline"),
1699
- onClick: () => t.value?.chain().focus().toggleUnderline().run()
1700
- }, null)])]
1701
- }) : null;
1702
- }
1703
- }), I1 = He(ye), q1 = /* @__PURE__ */ p({
1704
- name: "TiptapEditor",
1705
- props: {
1706
- modelValue: {
1707
- type: String,
1708
- default: ""
1709
- },
1710
- placeholder: {
1711
- type: String,
1712
- default: "请输入内容..."
1713
- },
1714
- upload: {
1715
- type: Function,
1716
- default: void 0
1717
- },
1718
- readonly: {
1719
- type: Boolean,
1720
- default: !1
1721
- },
1722
- toolbar: {
1723
- type: Array,
1724
- default: void 0
1725
- }
1726
- },
1727
- emits: ["update:modelValue"],
1728
- setup(t, {
1729
- emit: l
1730
- }) {
1731
- const n = {
1732
- "undo-redo": Ge,
1733
- "text-style": e1,
1734
- "code-block": M1,
1735
- list: u1,
1736
- "text-align": l1,
1737
- image: a1,
1738
- table: p1,
1739
- math: g1
1740
- }, o = F(() => t.toolbar ?? Ne), u = (r, x) => {
1741
- if (r === "|")
1742
- return e("div", {
1743
- key: `separator-${x}`,
1744
- class: "tiptap-separator"
1745
- }, null);
1746
- if (typeof r == "object" && r.type === "custom") {
1747
- const a = r.component;
1748
- return e(a, {
1749
- key: r.key ?? `custom-${x}`
1750
- }, null);
1751
- }
1752
- const k = n[r];
1753
- return k ? e(k, {
1754
- key: r
1755
- }, null) : null;
1756
- }, d = y(!1), f = y(""), m = y(null), c = y("inline"), H = F(() => t.readonly ?? !1), i = (r = {}) => {
1757
- H.value || (f.value = r.latex ?? "", m.value = r.pos ?? null, c.value = r.type ?? "inline", d.value = !0);
1758
- };
1759
- P("openMathDialog", i), P("readonly", H);
1760
- const s = he({
1761
- content: t.modelValue,
1762
- editable: !t.readonly,
1763
- extensions: [pe.configure({
1764
- codeBlock: !1,
1765
- link: {
1766
- openOnClick: !1,
1767
- enableClickSelection: !0
1768
- }
1769
- }), ke.configure({
1770
- placeholder: t.placeholder
1771
- }), xe.configure({
1772
- lowlight: I1,
1773
- defaultLanguage: "plaintext"
1774
- }), be.configure({
1775
- types: ["heading", "paragraph"]
1776
- }), me, we.configure({
1777
- nested: !0
1778
- }), Pe.configure({
1844
+ }), t1 = {
1845
+ name: "image",
1846
+ install: (t) => ({
1847
+ extensions: [
1848
+ Ne.configure({
1779
1849
  allowBase64: !0,
1780
1850
  resize: {
1781
1851
  enabled: !0,
@@ -1784,69 +1854,35 @@ const x1 = () => e("svg", {
1784
1854
  minHeight: 50,
1785
1855
  alwaysPreserveAspectRatio: !1
1786
1856
  }
1787
- }), ze.configure({
1788
- ...t.upload ? {
1789
- upload: t.upload
1790
- } : {}
1791
- }), Ve.configure({
1792
- resizable: !0
1793
- }), Ee, Fe, Te, Ze.configure({
1794
- inlineOptions: {
1795
- onClick: (r, x) => i({
1796
- latex: r.attrs.latex,
1797
- pos: x,
1798
- type: "inline"
1799
- })
1800
- },
1801
- blockOptions: {
1802
- onClick: (r, x) => i({
1803
- latex: r.attrs.latex,
1804
- pos: x,
1805
- type: "block"
1806
- })
1807
- }
1808
- })],
1809
- onUpdate: ({
1810
- editor: r
1811
- }) => {
1812
- l("update:modelValue", r.getHTML());
1813
- }
1814
- });
1815
- return P("editor", s), D(() => t.modelValue, (r) => {
1816
- s.value && r !== s.value.getHTML() && s.value.commands.setContent(r, {
1817
- emitUpdate: !1
1818
- });
1819
- }), D(() => t.readonly, (r) => {
1820
- s.value?.setEditable(!r);
1821
- }), () => e("div", {
1822
- class: "tiptap-editor"
1823
- }, [!t.readonly && e("div", {
1824
- class: "tiptap-toolbar"
1825
- }, [o.value.map((r, x) => u(r, x))]), e(ge, {
1826
- class: "tiptap-content",
1827
- editor: s.value
1828
- }, null), e(L1, null, null), e(f1, null, null), e(A1, null, null), e(m1, {
1829
- visible: d.value,
1830
- latex: f.value,
1831
- pos: m.value,
1832
- type: c.value,
1833
- "onUpdate:visible": (r) => {
1834
- d.value = r;
1835
- }
1836
- }, null)]);
1837
- }
1838
- });
1857
+ }),
1858
+ bt.configure({ ...t.upload ? { upload: t.upload } : {} })
1859
+ ],
1860
+ controlComponent: Lt
1861
+ }),
1862
+ toolbarComponent: xt
1863
+ }, l1 = {
1864
+ name: "separator",
1865
+ install: () => ({
1866
+ extensions: []
1867
+ }),
1868
+ toolbarComponent: /* @__PURE__ */ c({
1869
+ name: "ToolbarSeparator",
1870
+ setup: () => () => e("div", {
1871
+ class: "tiptap-separator"
1872
+ }, null)
1873
+ })
1874
+ };
1839
1875
  export {
1840
- M1 as CodeBlockButton,
1841
- Ne as DEFAULT_TOOLBAR_CONFIG,
1876
+ Qt as CodeBlockFeature,
1842
1877
  w as IconButton,
1843
- a1 as ImageButton,
1844
- Pe as ImageWithAlign,
1845
- u1 as ListButton,
1846
- g1 as MathButton,
1847
- p1 as TableButton,
1848
- l1 as TextAlignButton,
1849
- e1 as TextStyleButton,
1850
- q1 as TiptapEditor,
1851
- Ge as UndoRedoButton
1878
+ t1 as ImageFeature,
1879
+ Ne as ImageWithAlign,
1880
+ Xt as ListFeature,
1881
+ e1 as MathFeature,
1882
+ l1 as SeparatorFeature,
1883
+ Yt as TableFeature,
1884
+ Jt as TextAlignFeature,
1885
+ Gt as TextStyleFeature,
1886
+ qt as TiptapEditor,
1887
+ Kt as UndoRedoFeature
1852
1888
  };