@mario9/tiptap-editor 0.2.0 → 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,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";
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 ye } 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 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,242 @@ 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: 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
+ }
292
+ }), je = /* @__PURE__ */ c({
292
293
  name: "UndoIcon",
293
294
  setup(t, {
294
295
  attrs: l
@@ -306,7 +307,7 @@ const Pe = Ae.extend({
306
307
  fill: "currentColor"
307
308
  }, null)]);
308
309
  }
309
- }), qe = /* @__PURE__ */ p({
310
+ }), We = /* @__PURE__ */ c({
310
311
  name: "RedoIcon",
311
312
  setup(t, {
312
313
  attrs: l
@@ -324,23 +325,27 @@ const Pe = Ae.extend({
324
325
  fill: "currentColor"
325
326
  }, null)]);
326
327
  }
327
- }), Ge = /* @__PURE__ */ p({
328
+ }), qe = /* @__PURE__ */ c({
328
329
  name: "UndoRedoButton",
329
330
  setup() {
330
- const t = A("editor"), l = F(() => t?.value?.can().undo() ?? !1), n = F(() => t?.value?.can().redo() ?? !1);
331
+ const t = H("editor"), l = T(() => t?.value?.can().undo() ?? !1), n = T(() => t?.value?.can().redo() ?? !1);
331
332
  return () => e("div", null, [e(w, {
332
- icon: We,
333
+ icon: je,
333
334
  tooltip: "撤销",
334
335
  disabled: !l.value,
335
336
  onClick: () => t?.value?.chain().focus().undo().run()
336
337
  }, null), e(w, {
337
- icon: qe,
338
+ icon: We,
338
339
  tooltip: "重做",
339
340
  disabled: !n.value,
340
341
  onClick: () => t?.value?.chain().focus().redo().run()
341
342
  }, null)]);
342
343
  }
343
- }), Ke = /* @__PURE__ */ p({
344
+ }), Kt = {
345
+ name: "undo-redo",
346
+ install: () => ({ extensions: [] }),
347
+ toolbarComponent: qe
348
+ }, Ke = /* @__PURE__ */ c({
344
349
  name: "LinkIcon",
345
350
  setup(t, {
346
351
  attrs: l
@@ -359,7 +364,7 @@ const Pe = Ae.extend({
359
364
  fill: "currentColor"
360
365
  }, null)]);
361
366
  }
362
- }), Je = /* @__PURE__ */ p({
367
+ }), Ge = /* @__PURE__ */ c({
363
368
  name: "CornerDownLeftIcon",
364
369
  setup(t, {
365
370
  attrs: l
@@ -380,7 +385,7 @@ const Pe = Ae.extend({
380
385
  d: "M20 4v7a4 4 0 0 1-4 4H4"
381
386
  }, null)]);
382
387
  }
383
- }), Xe = /* @__PURE__ */ p({
388
+ }), Je = /* @__PURE__ */ c({
384
389
  name: "ExternalLinkIcon",
385
390
  setup(t, {
386
391
  attrs: l
@@ -406,7 +411,7 @@ const Pe = Ae.extend({
406
411
  y2: "3"
407
412
  }, null)]);
408
413
  }
409
- }), Qe = /* @__PURE__ */ p({
414
+ }), Xe = /* @__PURE__ */ c({
410
415
  name: "TrashIcon",
411
416
  setup(t, {
412
417
  attrs: l
@@ -427,52 +432,52 @@ const Pe = Ae.extend({
427
432
  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
433
  }, null)]);
429
434
  }
430
- }), Ye = /* @__PURE__ */ p({
435
+ }), Qe = /* @__PURE__ */ c({
431
436
  name: "LinkPopover",
432
437
  setup() {
433
- const t = A("editor"), l = y(!1), n = y("");
438
+ const t = H("editor"), l = k(!1), n = k("");
434
439
  let o = !1;
435
- D(() => t?.value?.isActive("link"), (i) => {
436
- o || i && (n.value = t?.value?.getAttributes("link").href ?? "", O(() => {
440
+ R(() => t?.value?.isActive("link"), (u) => {
441
+ o || u && (n.value = t?.value?.getAttributes("link").href ?? "", z(() => {
437
442
  l.value = !0;
438
443
  }));
439
444
  });
440
- const u = () => {
441
- const i = t?.value;
442
- if (!i || !n.value) return;
445
+ const i = () => {
446
+ const u = t?.value;
447
+ if (!u || !n.value) return;
443
448
  o = !0;
444
449
  const {
445
- empty: s
446
- } = i.state.selection;
447
- let r = i.chain().focus().extendMarkRange("link").setLink({
450
+ empty: C
451
+ } = u.state.selection;
452
+ let g = u.chain().focus().extendMarkRange("link").setLink({
448
453
  href: n.value
449
454
  });
450
- s && (r = r.insertContent({
455
+ C && (g = g.insertContent({
451
456
  type: "text",
452
457
  text: n.value
453
- })), r.run(), l.value = !1, O(() => {
458
+ })), g.run(), l.value = !1, z(() => {
454
459
  o = !1;
455
460
  });
456
- }, d = () => {
457
- const i = t?.value;
458
- i && (o = !0, i.chain().focus().extendMarkRange("link").unsetLink().run(), n.value = "", l.value = !1, O(() => {
461
+ }, r = () => {
462
+ const u = t?.value;
463
+ u && (o = !0, u.chain().focus().extendMarkRange("link").unsetLink().run(), n.value = "", l.value = !1, z(() => {
459
464
  o = !1;
460
465
  }));
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;
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;
470
475
  };
471
476
  return () => {
472
- const i = t?.value?.isActive("link") ?? !1;
477
+ const u = t?.value?.isActive("link") ?? !1;
473
478
  return e(J, {
474
479
  visible: l.value,
475
- "onUpdate:visible": c,
480
+ "onUpdate:visible": s,
476
481
  placement: "bottom",
477
482
  width: 300,
478
483
  trigger: "click",
@@ -484,133 +489,62 @@ const Pe = Ae.extend({
484
489
  tooltip: "链接",
485
490
  icon: Ke,
486
491
  class: ["tiptap-button", {
487
- "is-active": i
492
+ "is-active": u
488
493
  }]
489
494
  }, null)]),
490
495
  default: () => e("div", {
491
496
  class: "link-popover-inner"
492
497
  }, [e(X, {
493
498
  modelValue: n.value,
494
- "onUpdate:modelValue": H,
499
+ "onUpdate:modelValue": y,
495
500
  type: "url",
496
501
  placeholder: "请输入链接...",
497
502
  size: "small",
498
503
  autofocus: !0,
499
- onKeydown: m
504
+ onKeydown: p
500
505
  }, null), e("div", {
501
506
  class: "link-popover-actions"
502
- }, [e(R, {
507
+ }, [e(D, {
503
508
  content: "确认",
504
509
  showArrow: !1,
505
510
  offset: 4
506
511
  }, {
507
512
  default: () => [e(Z, {
508
513
  text: !0,
509
- icon: Je,
514
+ icon: Ge,
510
515
  disabled: !n.value,
511
- onClick: u
516
+ onClick: i
512
517
  }, null)]
513
- }), e(R, {
518
+ }), e(D, {
514
519
  content: "在新标签页打开",
515
520
  showArrow: !1,
516
521
  offset: 4
517
522
  }, {
518
523
  default: () => [e(Z, {
519
524
  text: !0,
520
- icon: Xe,
521
- disabled: !n.value && !i,
522
- onClick: f
525
+ icon: Je,
526
+ disabled: !n.value && !u,
527
+ onClick: v
523
528
  }, null)]
524
- }), e(R, {
529
+ }), e(D, {
525
530
  content: "移除链接",
526
531
  showArrow: !1,
527
532
  offset: 4
528
533
  }, {
529
534
  default: () => [e(Z, {
530
535
  text: !0,
531
- icon: Qe,
532
- disabled: !i,
533
- onClick: d
536
+ icon: Xe,
537
+ disabled: !u,
538
+ onClick: r
534
539
  }, null)]
535
540
  })])])
536
541
  });
537
542
  };
538
543
  }
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({
544
+ }), Ye = /* @__PURE__ */ c({
611
545
  name: "TextStyleButton",
612
546
  setup() {
613
- const t = A("editor");
547
+ const t = H("editor");
614
548
  return () => e("div", null, [e(w, {
615
549
  icon: Q,
616
550
  tooltip: "粗体",
@@ -631,9 +565,13 @@ const Pe = Ae.extend({
631
565
  tooltip: "下划线",
632
566
  isActive: t?.value?.isActive("underline"),
633
567
  onClick: () => t?.value?.chain().focus().toggleUnderline().run()
634
- }, null), e(Ye, null, null)]);
568
+ }, null), e(Qe, null, null)]);
635
569
  }
636
- }), le = /* @__PURE__ */ p({
570
+ }), Gt = {
571
+ name: "text-style",
572
+ install: () => ({ extensions: [] }),
573
+ toolbarComponent: Ye
574
+ }, le = /* @__PURE__ */ c({
637
575
  name: "AlignLeftIcon",
638
576
  setup(t, {
639
577
  attrs: l
@@ -661,7 +599,7 @@ const Pe = Ae.extend({
661
599
  fill: "currentColor"
662
600
  }, null)]);
663
601
  }
664
- }), ne = /* @__PURE__ */ p({
602
+ }), ne = /* @__PURE__ */ c({
665
603
  name: "AlignCenterIcon",
666
604
  setup(t, {
667
605
  attrs: l
@@ -689,7 +627,7 @@ const Pe = Ae.extend({
689
627
  fill: "currentColor"
690
628
  }, null)]);
691
629
  }
692
- }), oe = /* @__PURE__ */ p({
630
+ }), oe = /* @__PURE__ */ c({
693
631
  name: "AlignRightIcon",
694
632
  setup(t, {
695
633
  attrs: l
@@ -717,7 +655,7 @@ const Pe = Ae.extend({
717
655
  fill: "currentColor"
718
656
  }, null)]);
719
657
  }
720
- }), t1 = /* @__PURE__ */ p({
658
+ }), et = /* @__PURE__ */ c({
721
659
  name: "AlignJustifyIcon",
722
660
  setup(t, {
723
661
  attrs: l
@@ -745,10 +683,10 @@ const Pe = Ae.extend({
745
683
  fill: "currentColor"
746
684
  }, null)]);
747
685
  }
748
- }), l1 = /* @__PURE__ */ p({
686
+ }), tt = /* @__PURE__ */ c({
749
687
  name: "TextAlignButton",
750
688
  setup() {
751
- const t = A("editor");
689
+ const t = H("editor");
752
690
  return () => e("div", null, [e(w, {
753
691
  icon: le,
754
692
  tooltip: "左边对齐",
@@ -771,7 +709,7 @@ const Pe = Ae.extend({
771
709
  }),
772
710
  onClick: () => t?.value?.chain().focus().setTextAlign("right").run()
773
711
  }, null), e(w, {
774
- icon: t1,
712
+ icon: et,
775
713
  tooltip: "两端对齐",
776
714
  isActive: t?.value?.isActive({
777
715
  textAlign: "justify"
@@ -779,7 +717,11 @@ const Pe = Ae.extend({
779
717
  onClick: () => t?.value?.chain().focus().setTextAlign("justify").run()
780
718
  }, null)]);
781
719
  }
782
- }), n1 = /* @__PURE__ */ p({
720
+ }), Jt = {
721
+ name: "text-align",
722
+ install: () => ({ extensions: [] }),
723
+ toolbarComponent: tt
724
+ }, lt = /* @__PURE__ */ c({
783
725
  name: "ListIcon",
784
726
  setup(t, {
785
727
  attrs: l
@@ -822,7 +764,7 @@ const Pe = Ae.extend({
822
764
  fill: "currentColor"
823
765
  }, null)]);
824
766
  }
825
- }), o1 = /* @__PURE__ */ p({
767
+ }), nt = /* @__PURE__ */ c({
826
768
  name: "ListOrderedIcon",
827
769
  setup(t, {
828
770
  attrs: l
@@ -865,7 +807,7 @@ const Pe = Ae.extend({
865
807
  fill: "currentColor"
866
808
  }, null)]);
867
809
  }
868
- }), i1 = /* @__PURE__ */ p({
810
+ }), ot = /* @__PURE__ */ c({
869
811
  name: "ListTodoIcon",
870
812
  setup(t, {
871
813
  attrs: l
@@ -903,29 +845,33 @@ const Pe = Ae.extend({
903
845
  fill: "currentColor"
904
846
  }, null)]);
905
847
  }
906
- }), u1 = /* @__PURE__ */ p({
848
+ }), it = /* @__PURE__ */ c({
907
849
  name: "ListButton",
908
850
  setup() {
909
- const t = A("editor");
851
+ const t = H("editor");
910
852
  return () => e("div", null, [e(w, {
911
- icon: n1,
853
+ icon: lt,
912
854
  tooltip: "无序列表",
913
855
  isActive: t?.value?.isActive("bulletList"),
914
856
  onClick: () => t?.value?.chain().focus().toggleBulletList().run()
915
857
  }, null), e(w, {
916
- icon: o1,
858
+ icon: nt,
917
859
  tooltip: "有序列表",
918
860
  isActive: t?.value?.isActive("orderedList"),
919
861
  onClick: () => t?.value?.chain().focus().toggleOrderedList().run()
920
862
  }, null), e(w, {
921
- icon: i1,
863
+ icon: ot,
922
864
  tooltip: "任务列表",
923
865
  isActive: t?.value?.isActive("taskList"),
924
866
  onClick: () => t?.value?.chain().focus().toggleTaskList().run()
925
867
  }, null)]);
926
868
  }
927
- }), r1 = /* @__PURE__ */ p({
928
- name: "ImagePlusIcon",
869
+ }), Xt = {
870
+ name: "list",
871
+ install: () => ({ extensions: [] }),
872
+ toolbarComponent: it
873
+ }, rt = /* @__PURE__ */ c({
874
+ name: "CodeBlockIcon",
929
875
  setup(t, {
930
876
  attrs: l
931
877
  }) {
@@ -933,26 +879,36 @@ const Pe = Ae.extend({
933
879
  width: "24",
934
880
  height: "24",
935
881
  viewBox: "0 0 24 24",
936
- fill: "currentColor",
882
+ fill: "none",
883
+ stroke: "currentColor",
884
+ "stroke-width": "2",
885
+ "stroke-linecap": "round",
886
+ "stroke-linejoin": "round",
937
887
  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"
943
- }, null)]);
944
- }
945
- }), a1 = /* @__PURE__ */ p({
946
- name: "ImageButton",
947
- setup() {
948
- const t = A("editor");
949
- return () => e("div", null, [e(w, {
950
- icon: r1,
951
- tooltip: "图片",
952
- onClick: () => t?.value?.commands.setImageUploadNode()
888
+ }, l), [e("polyline", {
889
+ points: "16 18 22 12 16 6"
890
+ }, null), e("polyline", {
891
+ points: "8 6 2 12 8 18"
953
892
  }, null)]);
954
893
  }
955
- }), s1 = /* @__PURE__ */ p({
894
+ }), ut = /* @__PURE__ */ c({
895
+ name: "CodeBlockButton",
896
+ setup() {
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);
904
+ }
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({
956
912
  name: "TableIcon",
957
913
  setup(t, {
958
914
  attrs: l
@@ -970,30 +926,30 @@ const Pe = Ae.extend({
970
926
  fill: "currentColor"
971
927
  }, null)]);
972
928
  }
973
- }), c1 = 8, d1 = 8, p1 = /* @__PURE__ */ p({
929
+ }), ct = 8, dt = 8, pt = /* @__PURE__ */ c({
974
930
  name: "TableButton",
975
931
  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 = () => {
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 = () => {
979
935
  n.value = 0, o.value = 0;
980
- }, f = (m, c) => {
936
+ }, v = (p, s) => {
981
937
  t?.value?.chain().focus().insertTable({
982
- rows: c,
983
- cols: m,
938
+ rows: s,
939
+ cols: p,
984
940
  withHeaderRow: !0
985
941
  }).run(), l.value = !1;
986
942
  };
987
943
  return () => e(J, {
988
944
  visible: l.value,
989
- "onUpdate:visible": (m) => l.value = m,
945
+ "onUpdate:visible": (p) => l.value = p,
990
946
  trigger: "click",
991
947
  placement: "bottom-start",
992
948
  popperClass: "table-picker-popper",
993
949
  width: "auto",
994
950
  showArrow: !1
995
951
  }, {
996
- reference: () => e("span", null, [e(R, {
952
+ reference: () => e("span", null, [e(D, {
997
953
  content: "表格",
998
954
  showArrow: !1,
999
955
  offset: 6,
@@ -1005,7 +961,7 @@ const Pe = Ae.extend({
1005
961
  "is-active": l.value
1006
962
  }]
1007
963
  }, {
1008
- default: () => [e(s1, {
964
+ default: () => [e(st, {
1009
965
  class: "tiptap-button-icon"
1010
966
  }, null)]
1011
967
  })]
@@ -1014,34 +970,34 @@ const Pe = Ae.extend({
1014
970
  class: "table-picker"
1015
971
  }, [e("div", {
1016
972
  class: "table-picker-grid",
1017
- onMouseleave: d
973
+ onMouseleave: r
1018
974
  }, [Array.from({
1019
- length: d1
1020
- }, (m, c) => e("div", {
1021
- key: c,
975
+ length: dt
976
+ }, (p, s) => e("div", {
977
+ key: s,
1022
978
  class: "table-picker-row"
1023
979
  }, [Array.from({
1024
- length: c1
1025
- }, (H, i) => e("div", {
1026
- key: i,
980
+ length: ct
981
+ }, (y, u) => e("div", {
982
+ key: u,
1027
983
  class: ["table-picker-cell", {
1028
- "is-active": i < n.value && c < o.value
984
+ "is-active": u < n.value && s < o.value
1029
985
  }],
1030
- onMouseenter: () => u(i + 1, c + 1),
1031
- onClick: () => f(i + 1, c + 1)
986
+ onMouseenter: () => i(u + 1, s + 1),
987
+ onClick: () => v(u + 1, s + 1)
1032
988
  }, null))]))]), e("div", {
1033
989
  class: "table-picker-footer"
1034
990
  }, [e("div", {
1035
991
  class: "table-picker-counter"
1036
- }, [e("span", null, [g("列")]), e("span", null, [n.value || 1])]), e("span", {
992
+ }, [e("span", null, [m("列")]), e("span", null, [n.value || 1])]), e("span", {
1037
993
  class: "table-picker-x"
1038
- }, [g("x")]), e("div", {
994
+ }, [m("x")]), e("div", {
1039
995
  class: "table-picker-counter"
1040
- }, [e("span", null, [g("行")]), e("span", null, [o.value || 1])])])])
996
+ }, [e("span", null, [m("行")]), e("span", null, [o.value || 1])])])])
1041
997
  });
1042
998
  }
1043
999
  });
1044
- function C1(t) {
1000
+ function Ct(t) {
1045
1001
  let l = t.nodeType === Node.TEXT_NODE ? t.parentElement : t;
1046
1002
  for (; l && l instanceof HTMLElement; ) {
1047
1003
  if (l.tagName === "TD" || l.tagName === "TH") return l;
@@ -1049,106 +1005,106 @@ function C1(t) {
1049
1005
  }
1050
1006
  return null;
1051
1007
  }
1052
- function v1(t) {
1008
+ function vt(t) {
1053
1009
  if (!t.isActive("tableCell") && !t.isActive("tableHeader")) return null;
1054
1010
  const {
1055
1011
  node: l
1056
- } = t.view.domAtPos(t.state.selection.from), n = C1(l);
1012
+ } = t.view.domAtPos(t.state.selection.from), n = Ct(l);
1057
1013
  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();
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();
1061
1017
  return {
1062
1018
  cell: n,
1063
- colIndex: f,
1064
- rowIndex: m,
1065
- totalCols: c,
1066
- totalRows: H,
1067
- cellRect: i,
1068
- tableRect: s,
1069
- editorRect: r
1019
+ colIndex: v,
1020
+ rowIndex: p,
1021
+ totalCols: s,
1022
+ totalRows: y,
1023
+ cellRect: u,
1024
+ tableRect: C,
1025
+ editorRect: g
1070
1026
  };
1071
1027
  }
1072
- function G(t) {
1028
+ function K(t) {
1073
1029
  const {
1074
1030
  state: l
1075
1031
  } = t, n = l.selection.from;
1076
1032
  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)
1033
+ return l.doc.nodesBetween(0, l.doc.content.size, (i, r) => {
1034
+ if (i.type.name === "table" && r <= n && n <= r + i.nodeSize)
1079
1035
  return o = {
1080
- node: u,
1081
- pos: d
1036
+ node: i,
1037
+ pos: r
1082
1038
  }, !1;
1083
1039
  }), o;
1084
1040
  }
1085
- const f1 = /* @__PURE__ */ p({
1041
+ const ft = /* @__PURE__ */ c({
1086
1042
  name: "TableControls",
1087
1043
  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) {
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) {
1092
1048
  n.value = null;
1093
1049
  return;
1094
1050
  }
1095
- const s = v1(i);
1096
- n.value = s, s && (s.cell.classList.add("tcc-cell-focused"), o.value = s.cell);
1051
+ const C = vt(u);
1052
+ n.value = C, C && (C.cell.classList.add("tcc-cell-focused"), o.value = C.cell);
1097
1053
  }
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);
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);
1102
1058
  }));
1103
1059
  });
1104
- function d(i) {
1105
- const s = t?.value;
1106
- if (!s || !n.value) return;
1060
+ function r(u) {
1061
+ const C = t?.value;
1062
+ if (!C || !n.value) return;
1107
1063
  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);
1064
+ colIndex: g,
1065
+ totalCols: I
1066
+ } = n.value, x = u === "left" ? g - 1 : g + 1;
1067
+ if (x < 0 || x >= I) return;
1068
+ const a = K(C);
1113
1069
  if (!a) return;
1114
1070
  const {
1115
- node: C,
1116
- pos: v
1071
+ node: d,
1072
+ pos: f
1117
1073
  } = a, h = [];
1118
- C.forEach((I) => {
1119
- if (I.type.name !== "tableRow") {
1120
- h.push(I);
1074
+ d.forEach((L) => {
1075
+ if (L.type.name !== "tableRow") {
1076
+ h.push(L);
1121
1077
  return;
1122
1078
  }
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));
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));
1127
1083
  });
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);
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);
1130
1086
  }
1131
- function f(i) {
1132
- const s = t?.value;
1133
- if (!s || !n.value) return;
1087
+ function v(u) {
1088
+ const C = t?.value;
1089
+ if (!C || !n.value) return;
1134
1090
  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);
1091
+ rowIndex: g,
1092
+ totalRows: I
1093
+ } = n.value, x = u === "up" ? g - 1 : g + 1;
1094
+ if (x < 0 || x >= I) return;
1095
+ const a = K(C);
1140
1096
  if (!a) return;
1141
1097
  const {
1142
- node: C,
1143
- pos: v
1098
+ node: d,
1099
+ pos: f
1144
1100
  } = 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);
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);
1150
1106
  }
1151
- const m = () => e("svg", {
1107
+ const p = () => e("svg", {
1152
1108
  width: "16",
1153
1109
  height: "4",
1154
1110
  viewBox: "0 0 16 4",
@@ -1165,7 +1121,7 @@ const f1 = /* @__PURE__ */ p({
1165
1121
  cx: "14",
1166
1122
  cy: "2",
1167
1123
  r: "1.5"
1168
- }, null)]), c = () => e("svg", {
1124
+ }, null)]), s = () => e("svg", {
1169
1125
  width: "4",
1170
1126
  height: "16",
1171
1127
  viewBox: "0 0 4 16",
@@ -1182,7 +1138,7 @@ const f1 = /* @__PURE__ */ p({
1182
1138
  cx: "2",
1183
1139
  cy: "14",
1184
1140
  r: "1.5"
1185
- }, null)]), H = () => e("svg", {
1141
+ }, null)]), y = () => e("svg", {
1186
1142
  width: "10",
1187
1143
  height: "10",
1188
1144
  viewBox: "0 0 10 10",
@@ -1195,122 +1151,505 @@ const f1 = /* @__PURE__ */ p({
1195
1151
  }, null)]);
1196
1152
  return () => {
1197
1153
  if (l?.value) return null;
1198
- const i = n.value;
1199
- if (!i) return null;
1154
+ const u = n.value;
1155
+ if (!u) return null;
1200
1156
  const {
1201
- colIndex: s,
1202
- rowIndex: r,
1203
- totalCols: x,
1204
- totalRows: k,
1157
+ colIndex: C,
1158
+ rowIndex: g,
1159
+ totalCols: I,
1160
+ totalRows: x,
1205
1161
  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 = {
1162
+ tableRect: d,
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 = {
1209
1165
  position: "absolute",
1210
1166
  top: `${h - 20}px`,
1211
- left: `${M + U / 2 - 18}px`
1212
- }, ue = {
1167
+ left: `${A + U / 2 - 18}px`
1168
+ }, re = {
1213
1169
  position: "absolute",
1214
- top: `${S + $ / 2 - 18}px`,
1170
+ top: `${S + O / 2 - 18}px`,
1215
1171
  left: `${B - 20}px`
1216
- }, re = {
1172
+ }, ue = {
1217
1173
  position: "absolute",
1218
- top: `${S + $ / 2 - 12}px`,
1174
+ top: `${S + O / 2 - 12}px`,
1219
1175
  left: `${V + 6}px`
1220
1176
  }, ae = {
1221
1177
  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;
1178
+ top: `${L + 6}px`,
1179
+ left: `${A + U / 2 - 12}px`
1180
+ }, se = C === 0, $ = C === I - 1, ce = g === 0, N = g === x - 1, F = t?.value;
1225
1181
  return e("div", {
1226
1182
  class: "table-cell-controls"
1227
1183
  }, [e(j, {
1228
1184
  trigger: "click",
1229
1185
  placement: "bottom",
1230
1186
  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();
1187
+ onCommand: (M) => {
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();
1233
1189
  }
1234
1190
  }, {
1235
1191
  default: () => [e("button", {
1236
1192
  class: "tcc-btn tcc-btn--col"
1237
- }, [e(m, null, null)])],
1193
+ }, [e(p, null, null)])],
1238
1194
  dropdown: () => e(W, null, {
1239
1195
  default: () => [e(E, {
1240
1196
  command: "move-left",
1241
1197
  disabled: se
1242
1198
  }, {
1243
- default: () => [g("移动列到左侧")]
1199
+ default: () => [m("移动列到左侧")]
1244
1200
  }), e(E, {
1245
1201
  command: "move-right",
1246
- disabled: z
1202
+ disabled: $
1247
1203
  }, {
1248
- default: () => [g("移动列到右侧")]
1204
+ default: () => [m("移动列到右侧")]
1249
1205
  }), e(E, {
1250
1206
  command: "insert-left"
1251
1207
  }, {
1252
- default: () => [g("在左侧插入一列")]
1208
+ default: () => [m("在左侧插入一列")]
1253
1209
  }), e(E, {
1254
1210
  command: "insert-right"
1255
1211
  }, {
1256
- default: () => [g("在右侧插入一列")]
1212
+ default: () => [m("在右侧插入一列")]
1257
1213
  }), e(E, {
1258
1214
  command: "delete",
1259
1215
  divided: !0
1260
1216
  }, {
1261
- default: () => [g("删除列")]
1217
+ default: () => [m("删除列")]
1262
1218
  })]
1263
1219
  })
1264
1220
  }), e(j, {
1265
1221
  trigger: "click",
1266
1222
  placement: "right",
1267
- 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();
1223
+ style: re,
1224
+ onCommand: (M) => {
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();
1270
1226
  }
1271
1227
  }, {
1272
1228
  default: () => [e("button", {
1273
1229
  class: "tcc-btn tcc-btn--row"
1274
- }, [e(c, null, null)])],
1230
+ }, [e(s, null, null)])],
1275
1231
  dropdown: () => e(W, null, {
1276
1232
  default: () => [e(E, {
1277
1233
  command: "move-up",
1278
1234
  disabled: ce
1279
1235
  }, {
1280
- default: () => [g("上移")]
1236
+ default: () => [m("上移")]
1281
1237
  }), e(E, {
1282
1238
  command: "move-down",
1283
1239
  disabled: N
1284
1240
  }, {
1285
- default: () => [g("下移")]
1241
+ default: () => [m("下移")]
1286
1242
  }), e(E, {
1287
1243
  command: "insert-above"
1288
1244
  }, {
1289
- default: () => [g("在上方插入一行")]
1245
+ default: () => [m("在上方插入一行")]
1290
1246
  }), e(E, {
1291
1247
  command: "insert-below"
1292
1248
  }, {
1293
- default: () => [g("在下方插入一行")]
1249
+ default: () => [m("在下方插入一行")]
1294
1250
  }), e(E, {
1295
1251
  command: "delete",
1296
1252
  divided: !0
1297
1253
  }, {
1298
- default: () => [g("删除行")]
1254
+ default: () => [m("删除行")]
1299
1255
  })]
1300
1256
  })
1301
- }), z && e("button", {
1257
+ }), $ && e("button", {
1302
1258
  class: "tcc-btn tcc-btn--add",
1303
- style: re,
1304
- onClick: () => T?.chain().focus().addColumnAfter().run()
1305
- }, [e(H, null, null)]), N && e("button", {
1259
+ style: ue,
1260
+ onClick: () => F?.chain().focus().addColumnAfter().run()
1261
+ }, [e(y, null, null)]), N && e("button", {
1306
1262
  class: "tcc-btn tcc-btn--add",
1307
1263
  style: ae,
1308
- onClick: () => T?.chain().focus().addRowAfter().run()
1309
- }, [e(H, null, null)])]);
1264
+ onClick: () => F?.chain().focus().addRowAfter().run()
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
+ }
1310
1649
  };
1311
1650
  }
1312
- }), h1 = /* @__PURE__ */ p({
1313
- name: "MathIcon",
1651
+ }), xt = /* @__PURE__ */ c({
1652
+ name: "ImagePlusIcon",
1314
1653
  setup(t, {
1315
1654
  attrs: l
1316
1655
  }) {
@@ -1323,144 +1662,21 @@ const f1 = /* @__PURE__ */ p({
1323
1662
  }, l), [e("path", {
1324
1663
  "fill-rule": "evenodd",
1325
1664
  "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",
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",
1327
1666
  fill: "currentColor"
1328
1667
  }, null)]);
1329
1668
  }
1330
- }), g1 = /* @__PURE__ */ p({
1331
- name: "MathButton",
1669
+ }), kt = /* @__PURE__ */ c({
1670
+ name: "ImageButton",
1332
1671
  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
- });
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)]);
1462
1678
  }
1463
- }), w1 = [{
1679
+ }), Ht = [{
1464
1680
  value: "left",
1465
1681
  title: "居左",
1466
1682
  Icon: le
@@ -1473,12 +1689,12 @@ const f1 = /* @__PURE__ */ p({
1473
1689
  title: "居右",
1474
1690
  Icon: oe
1475
1691
  }], _ = (t) => t.preventDefault();
1476
- function b1(t) {
1692
+ function Bt(t) {
1477
1693
  if (!t.isActive("image")) return null;
1478
1694
  const {
1479
1695
  selection: l
1480
1696
  } = t.state;
1481
- if (!(l instanceof Me) || l.node.type.name !== "image") return null;
1697
+ if (!(l instanceof Ie) || l.node.type.name !== "image") return null;
1482
1698
  const n = l.node;
1483
1699
  return {
1484
1700
  pos: l.from,
@@ -1487,11 +1703,11 @@ function b1(t) {
1487
1703
  align: n.attrs.align ?? "left"
1488
1704
  };
1489
1705
  }
1490
- function k1(t) {
1706
+ function yt(t) {
1491
1707
  const l = t.startsWith("data:") ? "image.png" : t.split("/").pop()?.split("?")[0] || "image.png", n = document.createElement("a");
1492
1708
  n.href = t, n.download = l, document.body.appendChild(n), n.click(), document.body.removeChild(n);
1493
1709
  }
1494
- const x1 = () => e("svg", {
1710
+ const At = () => e("svg", {
1495
1711
  width: "16",
1496
1712
  height: "16",
1497
1713
  viewBox: "0 0 24 24",
@@ -1509,7 +1725,7 @@ const x1 = () => e("svg", {
1509
1725
  y1: "15",
1510
1726
  x2: "12",
1511
1727
  y2: "3"
1512
- }, null)]), H1 = () => e("svg", {
1728
+ }, null)]), Mt = () => e("svg", {
1513
1729
  width: "16",
1514
1730
  height: "16",
1515
1731
  viewBox: "0 0 24 24",
@@ -1522,7 +1738,7 @@ const x1 = () => e("svg", {
1522
1738
  points: "1 4 1 10 7 10"
1523
1739
  }, null), e("path", {
1524
1740
  d: "M3.51 15a9 9 0 1 0 .49-4.1L1 10"
1525
- }, null)]), y1 = () => e("svg", {
1741
+ }, null)]), It = () => e("svg", {
1526
1742
  width: "16",
1527
1743
  height: "16",
1528
1744
  viewBox: "0 0 24 24",
@@ -1539,314 +1755,133 @@ const x1 = () => e("svg", {
1539
1755
  d: "M10 11v6M14 11v6"
1540
1756
  }, null), e("path", {
1541
1757
  d: "M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"
1542
- }, null)]), A1 = /* @__PURE__ */ p({
1758
+ }, null)]), Lt = /* @__PURE__ */ c({
1543
1759
  name: "ImageControls",
1544
1760
  setup() {
1545
- const t = A("editor"), l = A("readonly"), n = y(null);
1761
+ const t = H("editor"), l = H("readonly"), n = k(null);
1546
1762
  function o() {
1547
- const u = t?.value;
1548
- if (!u) {
1763
+ const i = t?.value;
1764
+ if (!i) {
1549
1765
  n.value = null;
1550
1766
  return;
1551
1767
  }
1552
- n.value = b1(u);
1768
+ n.value = Bt(i);
1553
1769
  }
1554
- return K((u) => {
1555
- const d = t?.value;
1556
- d && (d.on("transaction", o), u(() => {
1557
- d.off("transaction", o);
1770
+ return G((i) => {
1771
+ const r = t?.value;
1772
+ r && (r.on("transaction", o), i(() => {
1773
+ r.off("transaction", o);
1558
1774
  }));
1559
1775
  }), () => {
1560
- const u = n.value;
1561
- if (!u) return null;
1562
- const d = t?.value;
1563
- if (!d) return null;
1776
+ const i = n.value;
1777
+ if (!i) return null;
1778
+ const r = t?.value;
1779
+ if (!r) return null;
1564
1780
  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 = {
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");
1788
+ if (!I) return null;
1789
+ const x = g.getBoundingClientRect(), a = I.getBoundingClientRect(), d = {
1574
1790
  position: "absolute",
1575
- top: `${k.top - a.top}px`,
1576
- left: `${k.left - a.left + k.width / 2}px`,
1791
+ top: `${x.top - a.top}px`,
1792
+ left: `${x.left - a.left + x.width / 2}px`,
1577
1793
  transform: "translate(-50%, calc(-100% - 8px))",
1578
1794
  zIndex: 20
1579
1795
  };
1580
1796
  return e("div", {
1581
1797
  class: "image-controls",
1582
- style: C
1583
- }, [!i && w1.map(({
1584
- value: v,
1798
+ style: d
1799
+ }, [!u && Ht.map(({
1800
+ value: f,
1585
1801
  title: h,
1586
1802
  Icon: B
1587
1803
  }) => e("button", {
1588
- key: v,
1589
- class: ["image-controls-btn", H === v && "is-active"],
1804
+ key: f,
1805
+ class: ["image-controls-btn", y === f && "is-active"],
1590
1806
  title: h,
1591
1807
  onMousedown: _,
1592
- onClick: () => d.chain().focus().updateAttributes("image", {
1593
- align: v
1808
+ onClick: () => r.chain().focus().updateAttributes("image", {
1809
+ align: f
1594
1810
  }).run()
1595
- }, [e(B, null, null)])), !i && e("span", {
1811
+ }, [e(B, null, null)])), !u && e("span", {
1596
1812
  class: "image-controls-separator"
1597
1813
  }, null), e("button", {
1598
1814
  class: "image-controls-btn",
1599
1815
  title: "下载",
1600
1816
  onMousedown: _,
1601
- onClick: () => k1(c)
1602
- }, [e(x1, null, null)]), !i && e("button", {
1817
+ onClick: () => yt(s)
1818
+ }, [e(At, null, null)]), !u && e("button", {
1603
1819
  class: "image-controls-btn",
1604
1820
  title: "重新上传",
1605
1821
  onMousedown: _,
1606
- onClick: () => d.chain().focus().deleteRange({
1607
- from: f,
1608
- to: f + m
1609
- }).insertContentAt(f, {
1822
+ onClick: () => r.chain().focus().deleteRange({
1823
+ from: v,
1824
+ to: v + p
1825
+ }).insertContentAt(v, {
1610
1826
  type: "imageUpload"
1611
1827
  }).run()
1612
- }, [e(H1, null, null)]), !i && e("button", {
1828
+ }, [e(Mt, null, null)]), !u && e("button", {
1613
1829
  class: "image-controls-btn",
1614
1830
  title: "删除",
1615
1831
  onMousedown: _,
1616
- onClick: () => d.chain().focus().deleteRange({
1617
- from: f,
1618
- to: f + m
1832
+ onClick: () => r.chain().focus().deleteRange({
1833
+ from: v,
1834
+ to: v + p
1619
1835
  }).run()
1620
- }, [e(y1, null, null)])]);
1621
- };
1622
- }
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);
1836
+ }, [e(It, null, null)])]);
1758
1837
  };
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({
1779
- allowBase64: !0,
1780
- resize: {
1781
- enabled: !0,
1782
- directions: ["top", "right", "bottom", "left", "top-right", "top-left", "bottom-right", "bottom-left"],
1783
- minWidth: 50,
1784
- minHeight: 50,
1785
- alwaysPreserveAspectRatio: !1
1786
- }
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
  }
1838
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
+ };
1839
1874
  export {
1840
- M1 as CodeBlockButton,
1841
- Ne as DEFAULT_TOOLBAR_CONFIG,
1875
+ Qt as CodeBlockFeature,
1842
1876
  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
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
1852
1887
  };