@agent-arts/editor 0.0.5 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/editor.js CHANGED
@@ -1,203 +1,95 @@
1
- var P = Object.defineProperty;
2
- var T = (n, e, t) => e in n ? P(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
- var r = (n, e, t) => T(n, typeof e != "symbol" ? e + "" : e, t);
4
- import { StateEffect as u, Facet as w, StateField as E, EditorState as C } from "@codemirror/state";
5
- import { EditorView as f, Decoration as p, WidgetType as B, keymap as D } from "@codemirror/view";
6
- import { history as L, defaultKeymap as A, historyKeymap as G } from "@codemirror/commands";
7
- import { markdown as R, markdownLanguage as $ } from "@codemirror/lang-markdown";
8
- import { languages as I } from "@codemirror/language-data";
9
- class j {
10
- constructor(e) {
11
- r(this, "view");
12
- r(this, "allBlocks", /* @__PURE__ */ new Map());
13
- r(this, "options");
14
- this.options = e, e.initialBlocks && e.initialBlocks.forEach((i) => this.allBlocks.set(i.block.id, i.block));
15
- const t = {
16
- updateBlockText: (i, s) => {
17
- const c = this.allBlocks.get(i);
18
- c && (c.presetText = s, this.allBlocks.set(i, c), this.options.onBlockUpdated && this.options.onBlockUpdated(i, s));
19
- },
20
- openPopup: (i, s) => {
21
- this.options.onOpenPopup(i, s);
22
- },
23
- deleteBlock: (i) => {
24
- this.allBlocks.delete(i), this.options.onBlockDeleted && this.options.onBlockDeleted(i);
25
- }
26
- }, o = N(e.initialDoc, t, e.initialBlocks || []), l = f.updateListener.of((i) => {
27
- i.docChanged && i.changes.iterChanges((s, c, d, a, m) => {
28
- const b = m.sliceString(0);
29
- m.length === 1 && (b === "{" ? this.options.onTriggerPluginPopup(s) : b === "/" && this.options.onTriggerAIDialog(s));
30
- });
31
- });
32
- this.view = new f({
33
- state: o.update({
34
- effects: u.appendConfig.of(l)
35
- }).state,
36
- parent: e.parent
37
- });
38
- }
39
- addBlock() {
40
- const e = {
41
- id: Math.random().toString(36).substr(2, 9),
42
- placeholder: "请输入编辑块内容为空时的提示文案",
43
- presetText: ""
44
- };
45
- this.allBlocks.set(e.id, e);
46
- const { from: t, to: o } = this.view.state.selection.main;
47
- return this.view.dispatch({
48
- changes: { from: t, to: o, insert: " " },
49
- effects: y.of(e),
50
- selection: { anchor: t + 1 }
51
- }), this.view.focus(), e;
1
+ var I = Object.defineProperty;
2
+ var L = (e, t, o) => t in e ? I(e, t, { enumerable: !0, configurable: !0, writable: !0, value: o }) : e[t] = o;
3
+ var u = (e, t, o) => L(e, typeof t != "symbol" ? t + "" : t, o);
4
+ import { StateEffect as k, StateField as x, Facet as y, EditorState as R } from "@codemirror/state";
5
+ import { EditorView as h, Decoration as a, WidgetType as T, ViewPlugin as _, keymap as W, drawSelection as N } from "@codemirror/view";
6
+ import { history as $, defaultKeymap as z, historyKeymap as O } from "@codemirror/commands";
7
+ const A = k.define(), D = k.define();
8
+ class g extends T {
9
+ constructor(t, o) {
10
+ super(), this.block = t, this.callbacks = o;
52
11
  }
53
- addPluginBlock(e, t) {
54
- return this.view.dispatch({
55
- changes: { from: e, to: e + 1, insert: " " },
56
- effects: v.of({ pos: e, block: t }),
57
- selection: { anchor: e + 1 }
58
- }), this.view.focus(), t;
59
- }
60
- syncBlock(e) {
61
- this.allBlocks.set(e.id, { ...e }), this.view.dispatch({
62
- effects: x.of(e)
63
- });
64
- }
65
- getBlock(e) {
66
- return this.allBlocks.get(e);
67
- }
68
- coordsAtPos(e) {
69
- return this.view.coordsAtPos(e);
70
- }
71
- getData() {
72
- return H(this.view, this.allBlocks);
73
- }
74
- destroy() {
75
- this.view.destroy();
76
- }
77
- }
78
- const y = u.define(), x = u.define(), v = u.define();
79
- class h extends B {
80
- constructor(e, t) {
81
- super(), this.block = e, this.callbacks = t;
82
- }
83
- toDOM(e) {
84
- const t = document.createElement("span");
85
- t.className = "cm-inline-block", t.setAttribute("data-block-id", this.block.id);
86
- const o = document.createElement("input");
87
- o.type = "text", o.className = "block-input", o.value = this.block.presetText || "", o.placeholder = this.block.placeholder || "请输入...";
88
- const l = (i) => {
89
- const s = document.createElement("span");
90
- s.style.visibility = "hidden", s.style.position = "absolute", s.style.whiteSpace = "pre", s.style.font = "inherit", s.textContent = i || o.placeholder, document.body.appendChild(s);
91
- const c = s.offsetWidth;
92
- return document.body.removeChild(s), c + 10;
12
+ toDOM(t) {
13
+ const o = document.createElement("span");
14
+ o.className = "cm-inline-block", o.setAttribute("data-block-id", this.block.id);
15
+ const n = document.createElement("input");
16
+ n.type = "text", n.className = "block-input", n.value = this.block.presetText || "", n.placeholder = this.block.placeholder || "请输入...";
17
+ const c = (s) => {
18
+ const i = document.createElement("span");
19
+ i.style.visibility = "hidden", i.style.position = "absolute", i.style.whiteSpace = "pre", i.style.font = "inherit", i.textContent = s || n.placeholder, document.body.appendChild(i);
20
+ const l = i.offsetWidth;
21
+ return document.body.removeChild(i), l + 10;
93
22
  };
94
- return o.style.width = `${l(o.value)}px`, o.oninput = (i) => {
95
- const s = i.target.value;
96
- o.style.width = `${l(s)}px`, this.callbacks.updateBlockText(this.block.id, s);
97
- }, o.onfocus = (i) => {
98
- const s = t.getBoundingClientRect();
23
+ return n.style.width = `${c(n.value)}px`, n.oninput = (s) => {
24
+ const i = s.target.value;
25
+ n.style.width = `${c(i)}px`, this.callbacks.updateBlockText(this.block.id, i);
26
+ }, n.onfocus = () => {
27
+ const s = o.getBoundingClientRect();
99
28
  this.callbacks.openPopup(this.block.id, s);
100
- }, o.onmousedown = (i) => {
101
- i.stopPropagation();
102
- }, o.onclick = (i) => {
103
- i.stopPropagation();
104
- const s = t.getBoundingClientRect();
105
- this.callbacks.openPopup(this.block.id, s);
106
- }, o.onkeydown = (i) => {
107
- if (i.key === "Backspace" && o.value === "") {
108
- i.preventDefault();
109
- let s = null;
110
- e.state.field(k).between(0, e.state.doc.length, (c, d, a) => {
111
- a.spec.widget === this && (s = c);
112
- }), s !== null && (this.callbacks.deleteBlock(this.block.id), e.dispatch({
113
- changes: { from: s, to: s + 1 },
114
- selection: { anchor: s }
115
- }));
29
+ }, n.onmousedown = (s) => {
30
+ s.stopPropagation();
31
+ }, n.onclick = (s) => {
32
+ s.stopPropagation();
33
+ const i = o.getBoundingClientRect();
34
+ this.callbacks.openPopup(this.block.id, i);
35
+ }, n.onkeydown = (s) => {
36
+ if (s.key === "Backspace" && n.value === "") {
37
+ s.preventDefault();
38
+ const i = t.posAtDOM(o);
39
+ this.callbacks.deleteBlock(this.block.id), t.dispatch({
40
+ changes: { from: i, to: i + 1 },
41
+ selection: { anchor: i }
42
+ });
116
43
  }
117
- }, t.appendChild(o), t;
44
+ }, o.appendChild(n), o;
118
45
  }
119
- ignoreEvent(e) {
46
+ ignoreEvent() {
120
47
  return !0;
121
48
  }
122
49
  }
123
- class W extends B {
124
- constructor(e) {
125
- super(), this.block = e;
126
- }
127
- toDOM() {
128
- const e = document.createElement("span");
129
- e.className = `cm-plugin-block cm-plugin-block-${this.block.type}`, e.setAttribute("data-block-id", this.block.id);
130
- const t = document.createElement("i");
131
- t.className = this.block.type === "plugin" ? "icon-plugin" : "icon-workflow", e.appendChild(t);
132
- const o = document.createTextNode(this.block.name);
133
- return e.appendChild(o), e;
134
- }
135
- ignoreEvent(e) {
136
- return !0;
137
- }
138
- }
139
- const g = w.define({
140
- combine: (n) => n[0]
141
- }), S = w.define({
142
- combine: (n) => n.length ? n[0] : []
143
- }), k = E.define({
144
- create(n) {
145
- const e = n.facet(g), t = n.facet(S);
146
- if (!t || t.length === 0) return p.none;
147
- const o = t.slice().sort((l, i) => l.pos - i.pos).map(({ pos: l, block: i }) => p.replace({
148
- widget: new h(i, e)
149
- }).range(l, l + 1));
150
- return p.set(o, !0);
50
+ const w = y.define({
51
+ combine: (e) => e[0]
52
+ }), S = y.define({
53
+ combine: (e) => e.length ? e[0] : []
54
+ }), v = x.define({
55
+ create(e) {
56
+ const t = e.facet(w), o = e.facet(S);
57
+ if (!o || o.length === 0) return a.none;
58
+ const n = o.slice().sort((c, s) => c.pos - s.pos).map(({ pos: c, len: s, block: i }) => {
59
+ const l = new g(i, t);
60
+ return a.replace({ widget: l }).range(c, c + (s || 1));
61
+ });
62
+ return a.set(n, !0);
151
63
  },
152
- update(n, e) {
153
- const t = e.state.facet(g);
154
- n = n.map(e.changes);
155
- for (let o of e.effects)
156
- if (o.is(y)) {
157
- const l = e.state.selection.main.head - 1, i = p.replace({
158
- widget: new h(o.value, t)
159
- }).range(l, l + 1);
160
- n = n.update({ add: [i] });
161
- } else if (o.is(x)) {
162
- const l = o.value;
163
- let i = null;
164
- n.between(0, e.state.doc.length, (s, c, d) => {
165
- const a = d.spec.widget;
166
- a instanceof h && a.block.id === l.id && (i = s);
167
- }), i !== null && (n = n.update({
168
- filter: (s, c, d) => {
169
- const a = d.spec.widget;
170
- return !(a instanceof h && a.block.id === l.id);
64
+ update(e, t) {
65
+ const o = t.state.facet(w);
66
+ e = e.map(t.changes);
67
+ for (const n of t.effects)
68
+ if (n.is(A)) {
69
+ const c = t.state.selection.main.head - 1, s = a.replace({
70
+ widget: new g(n.value, o)
71
+ }).range(c, c + 1);
72
+ e = e.update({ add: [s] });
73
+ } else if (n.is(D)) {
74
+ const c = n.value;
75
+ let s = null;
76
+ e.between(0, t.state.doc.length, (i, l, r) => {
77
+ const d = r.spec.widget;
78
+ d instanceof g && d.block.id === c.id && (s = i);
79
+ }), s !== null && (e = e.update({
80
+ filter: (i, l, r) => {
81
+ const d = r.spec.widget;
82
+ return !(d instanceof g && d.block.id === c.id);
171
83
  },
172
- add: [p.replace({
173
- widget: new h(l, t)
174
- }).range(i, i + 1)]
84
+ add: [a.replace({
85
+ widget: new g(c, o)
86
+ }).range(s, s + 1)]
175
87
  }));
176
- } else if (o.is(v)) {
177
- const { pos: l, block: i } = o.value, s = e.changes.mapPos(l), c = p.replace({
178
- widget: new W(i)
179
- }).range(s, s + 1);
180
- n = n.update({ add: [c] });
181
88
  }
182
- return n;
89
+ return e;
183
90
  },
184
- provide: (n) => f.decorations.from(n)
185
- }), F = (n, e) => {
186
- const t = n.state.selection.main.head;
187
- if (t === 0) return !1;
188
- let o = null, l = null;
189
- const i = n.state.field(k, !1);
190
- return i && i.between(t - 1, t, (s, c, d) => {
191
- const a = d.spec.widget;
192
- a instanceof h && (o = a.block.id, l = s);
193
- }), o && l !== null ? (e.deleteBlock(o), n.dispatch({
194
- changes: { from: l, to: l + 1 },
195
- selection: { anchor: l }
196
- }), !0) : !1;
197
- }, M = f.theme({
198
- "&": { height: "100%", outline: "none" },
199
- ".cm-content": { padding: "20px", fontSize: "16px" },
200
- ".cm-line": { padding: "4px 0" },
91
+ provide: (e) => h.decorations.from(e)
92
+ }), j = h.theme({
201
93
  ".cm-inline-block": {
202
94
  display: "inline-block",
203
95
  backgroundColor: "#f3f0ff",
@@ -229,148 +121,360 @@ const g = w.define({
229
121
  ".block-input::placeholder": {
230
122
  color: "#b2a1ff",
231
123
  opacity: 0.7
232
- },
233
- ".cm-header-1": { fontSize: "1.5em", color: "#008c99", fontWeight: "bold" }
124
+ }
234
125
  });
235
- function N(n, e, t = []) {
236
- const o = [
237
- L(),
238
- D.of([
239
- ...A,
240
- ...G,
241
- {
242
- key: "Backspace",
243
- run: (i) => F(i, e)
244
- }
245
- ]),
246
- R({ base: $, codeLanguages: I }),
247
- g.of(e),
248
- S.of(t),
249
- k,
250
- M
126
+ function V(e) {
127
+ return [
128
+ w.of(e.callbacks),
129
+ S.of(e.initialBlocks || []),
130
+ v,
131
+ j
132
+ ];
133
+ }
134
+ function q(e) {
135
+ const t = [], o = e.state.field(v, !1);
136
+ return o && o.between(0, e.state.doc.length, (n, c, s) => {
137
+ const i = s.spec.widget;
138
+ i instanceof g && t.push({ pos: n, len: c - n, block: i.block });
139
+ }), t;
140
+ }
141
+ function H(e) {
142
+ return [
143
+ K(e.onTriggerAIDialog),
144
+ G(e.onTriggerAIDialog),
145
+ U
251
146
  ];
252
- return C.create({
253
- doc: n,
254
- extensions: o
147
+ }
148
+ function K(e) {
149
+ return h.updateListener.of((t) => {
150
+ t.docChanged && t.changes.iterChanges((o, n, c, s, i) => {
151
+ if (i.length !== 1) return;
152
+ i.sliceString(0) === "/" && e(o);
153
+ });
255
154
  });
256
155
  }
257
- function q(n, e) {
258
- return new f({
259
- state: e,
260
- parent: n
156
+ const U = h.theme({
157
+ ".cm-ai-selection-trigger": {
158
+ position: "absolute",
159
+ zIndex: "10",
160
+ display: "none",
161
+ width: "32px",
162
+ height: "32px",
163
+ alignItems: "center",
164
+ justifyContent: "center",
165
+ borderRadius: "8px",
166
+ backgroundColor: "#fff",
167
+ boxShadow: "0 6px 24px rgba(0, 0, 0, 0.12)",
168
+ border: "1px solid rgba(0, 0, 0, 0.06)"
169
+ },
170
+ ".cm-ai-selection-trigger button": {
171
+ width: "100%",
172
+ height: "100%",
173
+ border: "none",
174
+ background: "transparent",
175
+ cursor: "pointer",
176
+ display: "flex",
177
+ alignItems: "center",
178
+ justifyContent: "center",
179
+ padding: "0"
180
+ },
181
+ ".cm-ai-selection-trigger button:hover": {
182
+ backgroundColor: "#f3f4f6",
183
+ borderRadius: "8px"
184
+ }
185
+ });
186
+ function G(e) {
187
+ return _.fromClass(class {
188
+ constructor(t) {
189
+ u(this, "dom");
190
+ u(this, "button");
191
+ u(this, "lastFrom", -1);
192
+ u(this, "lastTo", -1);
193
+ u(this, "measureScheduled", !1);
194
+ this.view = t, this.dom = document.createElement("div"), this.dom.className = "cm-ai-selection-trigger", this.button = document.createElement("button"), this.button.type = "button";
195
+ const o = document.createElementNS("http://www.w3.org/2000/svg", "svg");
196
+ o.setAttribute("width", "16"), o.setAttribute("height", "16"), o.setAttribute("viewBox", "0 0 24 24"), o.setAttribute("fill", "none"), o.setAttribute("stroke", "#111827"), o.setAttribute("stroke-width", "2"), o.setAttribute("stroke-linecap", "round"), o.setAttribute("stroke-linejoin", "round"), o.innerHTML = '<path d="M5 12l1.5.5L7 14l.5-1.5L9 12l-1.5-.5L7 10l-.5 1.5L5 12z"/><path d="M12 4l2 6 6 2-6 2-2 6-2-6-6-2 6-2 2-6z"/>', this.button.appendChild(o), this.dom.appendChild(this.button), this.view.dom.appendChild(this.dom), this.dom.addEventListener("mousedown", (n) => {
197
+ n.preventDefault(), n.stopPropagation();
198
+ }), this.button.addEventListener("click", (n) => {
199
+ n.preventDefault(), n.stopPropagation();
200
+ const { from: c, empty: s } = this.view.state.selection.main;
201
+ s || (e(c), this.hide());
202
+ }), this.scheduleMeasure(!0);
203
+ }
204
+ update(t) {
205
+ (t.selectionSet || t.viewportChanged || t.focusChanged || t.docChanged) && this.scheduleMeasure(!1);
206
+ }
207
+ destroy() {
208
+ this.dom.remove();
209
+ }
210
+ hide() {
211
+ this.dom.style.display = "none";
212
+ }
213
+ show() {
214
+ this.dom.style.display = "flex";
215
+ }
216
+ scheduleMeasure(t) {
217
+ const { from: o, to: n, empty: c } = this.view.state.selection.main;
218
+ if (c || !this.view.hasFocus) {
219
+ this.hide();
220
+ return;
221
+ }
222
+ !t && o === this.lastFrom && n === this.lastTo && this.dom.style.display !== "none" || (this.lastFrom = o, this.lastTo = n, !this.measureScheduled && (this.measureScheduled = !0, this.view.requestMeasure({
223
+ read: (s) => {
224
+ const i = s.coordsAtPos(o);
225
+ if (!i) return null;
226
+ const l = s.dom.getBoundingClientRect();
227
+ return { coords: i, editorRect: l };
228
+ },
229
+ write: (s) => {
230
+ this.measureScheduled = !1;
231
+ const { empty: i } = this.view.state.selection.main;
232
+ if (i || !this.view.hasFocus) {
233
+ this.hide();
234
+ return;
235
+ }
236
+ if (!s) {
237
+ this.hide();
238
+ return;
239
+ }
240
+ const { coords: l, editorRect: r } = s, d = 32, m = 32, p = 6, b = Math.min(
241
+ Math.max(l.left - r.left, p),
242
+ Math.max(p, r.width - d - p)
243
+ ), f = Math.max(l.top - r.top - m - 10, p);
244
+ this.dom.style.left = `${b}px`, this.dom.style.top = `${f}px`, this.show();
245
+ }
246
+ })));
247
+ }
261
248
  });
262
249
  }
263
- function H(n, e) {
264
- var l;
265
- const t = n.state.doc.toString(), o = Array.from(e.values());
266
- return {
267
- json: {
268
- content: t,
269
- blocks: o
270
- },
271
- html: ((l = n.dom.querySelector(".cm-content")) == null ? void 0 : l.innerHTML) || ""
272
- };
250
+ const M = k.define();
251
+ class B extends T {
252
+ constructor(t) {
253
+ super(), this.block = t;
254
+ }
255
+ toDOM() {
256
+ const t = document.createElement("span");
257
+ t.className = `cm-plugin-block cm-plugin-block-${this.block.type}`, t.setAttribute("data-block-id", this.block.id);
258
+ const o = document.createElement("i");
259
+ o.className = this.block.type === "plugin" ? "icon-plugin" : "icon-workflow", t.appendChild(o);
260
+ const n = document.createTextNode(this.block.name);
261
+ return t.appendChild(n), t;
262
+ }
263
+ ignoreEvent() {
264
+ return !0;
265
+ }
266
+ }
267
+ const F = y.define({
268
+ combine: (e) => e.length ? e[0] : []
269
+ }), E = x.define({
270
+ create(e) {
271
+ const t = e.facet(F);
272
+ if (!t || t.length === 0) return a.none;
273
+ const o = t.slice().sort((n, c) => n.pos - c.pos).map(({ pos: n, len: c, block: s }) => a.replace({ widget: new B(s) }).range(n, n + (c || 1)));
274
+ return a.set(o, !0);
275
+ },
276
+ update(e, t) {
277
+ e = e.map(t.changes);
278
+ for (const o of t.effects)
279
+ if (o.is(M)) {
280
+ const { pos: n, block: c } = o.value, s = t.changes.mapPos(n), i = a.replace({
281
+ widget: new B(c)
282
+ }).range(s, s + 1);
283
+ e = e.update({ add: [i] });
284
+ }
285
+ return e;
286
+ },
287
+ provide: (e) => h.decorations.from(e)
288
+ });
289
+ function J(e) {
290
+ return [
291
+ F.of(e.initialBlocks || []),
292
+ E
293
+ ];
294
+ }
295
+ function Q(e) {
296
+ return [
297
+ h.updateListener.of((t) => {
298
+ t.docChanged && t.changes.iterChanges((o, n, c, s, i) => {
299
+ if (i.length !== 1) return;
300
+ i.sliceString(0) === "{" && e.onTriggerPluginPopup(o);
301
+ });
302
+ })
303
+ ];
273
304
  }
274
- class Q {
275
- constructor(e) {
276
- r(this, "isGenerating", !1);
277
- r(this, "aiStreamTimer", null);
278
- r(this, "currentResponse", "");
279
- this.callbacks = e;
305
+ function X(e) {
306
+ const t = [], o = e.state.field(E, !1);
307
+ return o && o.between(0, e.state.doc.length, (n, c, s) => {
308
+ const i = s.spec.widget;
309
+ i instanceof B && t.push({ pos: n, len: c - n, block: i.block });
310
+ }), t;
311
+ }
312
+ function Y(e) {
313
+ const t = [], o = /\{\{(.+?)\}\}/g;
314
+ let n;
315
+ for (; (n = o.exec(e)) !== null; )
316
+ t.push({
317
+ pos: n.index,
318
+ len: n[0].length,
319
+ block: {
320
+ id: `var-${n[1]}-${n.index}`,
321
+ name: n[1],
322
+ type: "plugin"
323
+ }
324
+ });
325
+ return t;
326
+ }
327
+ class rt {
328
+ constructor(t) {
329
+ u(this, "view");
330
+ u(this, "allBlocks", /* @__PURE__ */ new Map());
331
+ u(this, "options");
332
+ this.options = t;
333
+ const o = Y(t.initialDoc), n = [
334
+ ...t.initialBlocks || [],
335
+ ...o
336
+ ];
337
+ t.initialBlocks && t.initialBlocks.forEach((i) => {
338
+ "type" in i.block || this.allBlocks.set(i.block.id, i.block);
339
+ });
340
+ const c = {
341
+ updateBlockText: (i, l) => {
342
+ const r = this.allBlocks.get(i);
343
+ r && (r.presetText = l, this.allBlocks.set(i, r), this.options.onBlockUpdated && this.options.onBlockUpdated(i, l));
344
+ },
345
+ openPopup: (i, l) => {
346
+ this.options.onOpenPopup(i, l);
347
+ },
348
+ deleteBlock: (i) => {
349
+ this.allBlocks.delete(i), this.options.onBlockDeleted && this.options.onBlockDeleted(i);
350
+ }
351
+ }, s = ot(t.initialDoc, c, n);
352
+ this.view = new h({
353
+ state: s.update({
354
+ effects: k.appendConfig.of([
355
+ ...Q({ onTriggerPluginPopup: (i) => this.options.onTriggerPluginPopup(i) }),
356
+ ...H({ onTriggerAIDialog: (i) => this.options.onTriggerAIDialog(i) })
357
+ ])
358
+ }).state,
359
+ parent: t.parent
360
+ });
280
361
  }
281
- show(e, t, o) {
282
- const l = {
283
- top: `${t.bottom - o.top + 10}px`,
284
- left: `${t.left - o.left}px`
362
+ addBlock() {
363
+ const t = {
364
+ id: Math.random().toString(36).slice(2, 11),
365
+ placeholder: "请输入编辑块内容为空时的提示文案",
366
+ presetText: ""
285
367
  };
286
- this.callbacks.onShow(e, l);
368
+ this.allBlocks.set(t.id, t);
369
+ const { from: o, to: n } = this.view.state.selection.main;
370
+ return this.view.dispatch({
371
+ changes: { from: o, to: n, insert: " " },
372
+ effects: A.of(t),
373
+ selection: { anchor: o + 1 }
374
+ }), this.view.focus(), t;
287
375
  }
288
- hide() {
289
- this.stopResponse(), this.callbacks.onHide();
376
+ addPluginBlock(t, o) {
377
+ return this.view.dispatch({
378
+ changes: { from: t, to: t + 1, insert: " " },
379
+ effects: M.of({ pos: t, block: o }),
380
+ selection: { anchor: t + 1 }
381
+ }), this.view.focus(), o;
290
382
  }
291
- sendQuestion(e) {
292
- if (!e || this.isGenerating) return;
293
- this.isGenerating = !0, this.callbacks.onLoading(!0), this.currentResponse = "", this.callbacks.onStream("");
294
- const t = `洲、美洲积累了丰富的在地经验,擅长结合用户需求定制专属旅行方案,曾帮助1000+人解决旅行难题,被旅行者亲切称为"旅行百事通"。
295
-
296
- ## 核心性格与风格
297
- - **性格特点**:热情开朗、专业耐心,擅长用轻松幽默的方式化解旅行焦虑(如:"别慌!机票改签我有3个小窍门,保准帮你搞定~"),遇到用户疑问会像朋友般细致拆解细节(如:"你担心的高原反应,我去年在西藏徒步时总结过4个缓解方法...")。
298
- - **语言风格**:口语化且富有感染力,常用"宝藏地""小众玩法"等旅行圈`;
299
- let o = 0;
300
- this.aiStreamTimer = setInterval(() => {
301
- this.callbacks.onLoading(!1), o < t.length ? (this.currentResponse += t[o], this.callbacks.onStream(this.currentResponse), o++) : this.finishGeneration();
302
- }, 30);
383
+ syncBlock(t) {
384
+ this.allBlocks.set(t.id, { ...t }), this.view.dispatch({
385
+ effects: D.of(t)
386
+ });
303
387
  }
304
- stopResponse() {
305
- this.aiStreamTimer && (clearInterval(this.aiStreamTimer), this.aiStreamTimer = null), this.isGenerating = !1, this.callbacks.onLoading(!1), this.callbacks.onStop();
388
+ getBlock(t) {
389
+ return this.allBlocks.get(t);
306
390
  }
307
- finishGeneration() {
308
- this.aiStreamTimer && (clearInterval(this.aiStreamTimer), this.aiStreamTimer = null), this.isGenerating = !1, this.callbacks.onLoading(!1), this.callbacks.onComplete();
391
+ coordsAtPos(t) {
392
+ return this.view.coordsAtPos(t);
309
393
  }
310
- getIsGenerating() {
311
- return this.isGenerating;
394
+ getData() {
395
+ return nt(this.view);
312
396
  }
313
397
  destroy() {
314
- this.stopResponse();
398
+ this.view.destroy();
315
399
  }
316
400
  }
317
- class J {
318
- constructor(e) {
319
- r(this, "plugins", [
320
- { id: "plugin-1", name: "LinkReaderPlugin", type: "plugin" }
321
- ]);
322
- r(this, "workflows", [
323
- { id: "workflow-1", name: "condition_1_872", type: "workflow" }
324
- ]);
325
- r(this, "triggerPos", 0);
326
- this.callbacks = e;
327
- }
328
- show(e, t, o) {
329
- this.triggerPos = e;
330
- const l = {
331
- top: `${t.bottom - o.top + 10}px`,
332
- left: `${t.left - o.left}px`
333
- };
334
- this.callbacks.onShow(e, l);
335
- }
336
- hide() {
337
- this.callbacks.onHide();
338
- }
339
- getTriggerPos() {
340
- return this.triggerPos;
401
+ const Z = (e, t) => {
402
+ const { from: o, empty: n } = e.state.selection.main;
403
+ if (!n) return !1;
404
+ const c = o;
405
+ if (c === 0) return !1;
406
+ let s = null, i = null, l = 1;
407
+ const r = (d) => {
408
+ d && d.between(c - 1, c, (m, p, b) => {
409
+ const f = b.spec.widget;
410
+ if (f && f.block && f.block.id && m < c && p >= c)
411
+ return s = f.block.id, i = m, l = p - m, !1;
412
+ });
413
+ };
414
+ return r(e.state.field(v, !1)), s || r(e.state.field(E, !1)), s && i !== null ? (t.deleteBlock(s), e.dispatch({
415
+ changes: { from: i, to: i + l },
416
+ selection: { anchor: i }
417
+ }), !0) : !1;
418
+ }, tt = h.theme({
419
+ "&": { height: "100%", outline: "none", position: "relative" },
420
+ ".cm-content": { padding: "20px", fontSize: "16px" },
421
+ ".cm-line": { padding: "4px 0" },
422
+ ".cm-header-1": { fontSize: "1.5em", color: "#008c99", fontWeight: "bold" },
423
+ ".cm-bold": { fontWeight: "bold" }
424
+ }), C = a.mark({ class: "cm-bold" });
425
+ function P(e) {
426
+ const t = [];
427
+ for (let o = 1; o <= e.lines; o++) {
428
+ const n = e.line(o), c = n.text;
429
+ /^#+\s+/.test(c) && t.push(C.range(n.from, n.to));
430
+ const s = /\*\*(.*?)\*\*/g;
431
+ let i;
432
+ for (; (i = s.exec(c)) !== null; )
433
+ t.push(C.range(n.from + i.index, n.from + i.index + i[0].length));
341
434
  }
435
+ return a.set(t.sort((o, n) => o.from - n.from), !0);
342
436
  }
343
- class X {
344
- constructor(e) {
345
- r(this, "editingBlock", { id: "", placeholder: "", presetText: "" });
346
- this.callbacks = e;
347
- }
348
- show(e, t, o) {
349
- this.editingBlock = { ...e };
350
- const l = {
351
- top: `${t.bottom - o.top + 10}px`,
352
- left: `${t.left - o.left}px`
353
- };
354
- this.callbacks.onShow(this.editingBlock, l);
355
- }
356
- hide() {
357
- this.callbacks.onHide();
358
- }
359
- updateEditingBlock(e) {
360
- this.editingBlock = { ...this.editingBlock, ...e };
361
- }
437
+ const et = x.define({
438
+ create(e) {
439
+ return P(e.doc);
440
+ },
441
+ update(e, t) {
442
+ return t.docChanged ? P(t.state.doc) : e.map(t.changes);
443
+ },
444
+ provide: (e) => h.decorations.from(e)
445
+ });
446
+ function ot(e, t, o = []) {
447
+ const n = o.filter((l) => !("type" in l.block && "name" in l.block)), c = o.filter((l) => "type" in l.block && "name" in l.block), s = [
448
+ $(),
449
+ W.of([
450
+ {
451
+ key: "Backspace",
452
+ run: (l) => Z(l, t)
453
+ },
454
+ ...z,
455
+ ...O
456
+ ]),
457
+ N(),
458
+ ...V({ callbacks: t, initialBlocks: n }),
459
+ ...J({ initialBlocks: c }),
460
+ et,
461
+ tt
462
+ ];
463
+ return R.create({
464
+ doc: e,
465
+ extensions: s
466
+ });
467
+ }
468
+ function nt(e) {
469
+ var c;
470
+ const t = e.state.doc.toString(), o = q(e), n = X(e);
471
+ return {
472
+ content: t,
473
+ editorBlocks: o,
474
+ pluginBlocks: n,
475
+ html: ((c = e.dom.querySelector(".cm-content")) == null ? void 0 : c.innerHTML) || ""
476
+ };
362
477
  }
363
478
  export {
364
- Q as AIDialogPlugin,
365
- j as CustomEditor,
366
- X as EditBlockPlugin,
367
- J as LibraryBlockPlugin,
368
- y as addBlockEffect,
369
- v as addPluginBlockEffect,
370
- k as blockField,
371
- N as createEditorState,
372
- q as createEditorView,
373
- M as editorTheme,
374
- H as getEditorData,
375
- x as updateBlockEffect
479
+ rt as CustomEditor
376
480
  };
@@ -1,5 +1 @@
1
- (function(l,a){typeof exports=="object"&&typeof module<"u"?a(exports,require("@codemirror/state"),require("@codemirror/view"),require("@codemirror/commands"),require("@codemirror/lang-markdown"),require("@codemirror/language-data")):typeof define=="function"&&define.amd?define(["exports","@codemirror/state","@codemirror/view","@codemirror/commands","@codemirror/lang-markdown","@codemirror/language-data"],a):(l=typeof globalThis<"u"?globalThis:l||self,a(l.AgentArtsEditor={},l.CMState,l.CMView,l.CMCommands,l.CMLangMarkdown,l.CMLangData))})(this,function(l,a,r,k,y,D){"use strict";var I=Object.defineProperty;var V=(l,a,r)=>a in l?I(l,a,{enumerable:!0,configurable:!0,writable:!0,value:r}):l[a]=r;var p=(l,a,r)=>V(l,typeof a!="symbol"?a+"":a,r);class v{constructor(e){p(this,"view");p(this,"allBlocks",new Map);p(this,"options");this.options=e,e.initialBlocks&&e.initialBlocks.forEach(i=>this.allBlocks.set(i.block.id,i.block));const o={updateBlockText:(i,s)=>{const d=this.allBlocks.get(i);d&&(d.presetText=s,this.allBlocks.set(i,d),this.options.onBlockUpdated&&this.options.onBlockUpdated(i,s))},openPopup:(i,s)=>{this.options.onOpenPopup(i,s)},deleteBlock:i=>{this.allBlocks.delete(i),this.options.onBlockDeleted&&this.options.onBlockDeleted(i)}},t=P(e.initialDoc,o,e.initialBlocks||[]),c=r.EditorView.updateListener.of(i=>{i.docChanged&&i.changes.iterChanges((s,d,u,h,x)=>{const C=x.sliceString(0);x.length===1&&(C==="{"?this.options.onTriggerPluginPopup(s):C==="/"&&this.options.onTriggerAIDialog(s))})});this.view=new r.EditorView({state:t.update({effects:a.StateEffect.appendConfig.of(c)}).state,parent:e.parent})}addBlock(){const e={id:Math.random().toString(36).substr(2,9),placeholder:"请输入编辑块内容为空时的提示文案",presetText:""};this.allBlocks.set(e.id,e);const{from:o,to:t}=this.view.state.selection.main;return this.view.dispatch({changes:{from:o,to:t,insert:" "},effects:m.of(e),selection:{anchor:o+1}}),this.view.focus(),e}addPluginBlock(e,o){return this.view.dispatch({changes:{from:e,to:e+1,insert:" "},effects:w.of({pos:e,block:o}),selection:{anchor:e+1}}),this.view.focus(),o}syncBlock(e){this.allBlocks.set(e.id,{...e}),this.view.dispatch({effects:b.of(e)})}getBlock(e){return this.allBlocks.get(e)}coordsAtPos(e){return this.view.coordsAtPos(e)}getData(){return T(this.view,this.allBlocks)}destroy(){this.view.destroy()}}const m=a.StateEffect.define(),b=a.StateEffect.define(),w=a.StateEffect.define();class f extends r.WidgetType{constructor(e,o){super(),this.block=e,this.callbacks=o}toDOM(e){const o=document.createElement("span");o.className="cm-inline-block",o.setAttribute("data-block-id",this.block.id);const t=document.createElement("input");t.type="text",t.className="block-input",t.value=this.block.presetText||"",t.placeholder=this.block.placeholder||"请输入...";const c=i=>{const s=document.createElement("span");s.style.visibility="hidden",s.style.position="absolute",s.style.whiteSpace="pre",s.style.font="inherit",s.textContent=i||t.placeholder,document.body.appendChild(s);const d=s.offsetWidth;return document.body.removeChild(s),d+10};return t.style.width=`${c(t.value)}px`,t.oninput=i=>{const s=i.target.value;t.style.width=`${c(s)}px`,this.callbacks.updateBlockText(this.block.id,s)},t.onfocus=i=>{const s=o.getBoundingClientRect();this.callbacks.openPopup(this.block.id,s)},t.onmousedown=i=>{i.stopPropagation()},t.onclick=i=>{i.stopPropagation();const s=o.getBoundingClientRect();this.callbacks.openPopup(this.block.id,s)},t.onkeydown=i=>{if(i.key==="Backspace"&&t.value===""){i.preventDefault();let s=null;e.state.field(g).between(0,e.state.doc.length,(d,u,h)=>{h.spec.widget===this&&(s=d)}),s!==null&&(this.callbacks.deleteBlock(this.block.id),e.dispatch({changes:{from:s,to:s+1},selection:{anchor:s}}))}},o.appendChild(t),o}ignoreEvent(e){return!0}}class L extends r.WidgetType{constructor(e){super(),this.block=e}toDOM(){const e=document.createElement("span");e.className=`cm-plugin-block cm-plugin-block-${this.block.type}`,e.setAttribute("data-block-id",this.block.id);const o=document.createElement("i");o.className=this.block.type==="plugin"?"icon-plugin":"icon-workflow",e.appendChild(o);const t=document.createTextNode(this.block.name);return e.appendChild(t),e}ignoreEvent(e){return!0}}const B=a.Facet.define({combine:n=>n[0]}),E=a.Facet.define({combine:n=>n.length?n[0]:[]}),g=a.StateField.define({create(n){const e=n.facet(B),o=n.facet(E);if(!o||o.length===0)return r.Decoration.none;const t=o.slice().sort((c,i)=>c.pos-i.pos).map(({pos:c,block:i})=>r.Decoration.replace({widget:new f(i,e)}).range(c,c+1));return r.Decoration.set(t,!0)},update(n,e){const o=e.state.facet(B);n=n.map(e.changes);for(let t of e.effects)if(t.is(m)){const c=e.state.selection.main.head-1,i=r.Decoration.replace({widget:new f(t.value,o)}).range(c,c+1);n=n.update({add:[i]})}else if(t.is(b)){const c=t.value;let i=null;n.between(0,e.state.doc.length,(s,d,u)=>{const h=u.spec.widget;h instanceof f&&h.block.id===c.id&&(i=s)}),i!==null&&(n=n.update({filter:(s,d,u)=>{const h=u.spec.widget;return!(h instanceof f&&h.block.id===c.id)},add:[r.Decoration.replace({widget:new f(c,o)}).range(i,i+1)]}))}else if(t.is(w)){const{pos:c,block:i}=t.value,s=e.changes.mapPos(c),d=r.Decoration.replace({widget:new L(i)}).range(s,s+1);n=n.update({add:[d]})}return n},provide:n=>r.EditorView.decorations.from(n)}),A=(n,e)=>{const o=n.state.selection.main.head;if(o===0)return!1;let t=null,c=null;const i=n.state.field(g,!1);return i&&i.between(o-1,o,(s,d,u)=>{const h=u.spec.widget;h instanceof f&&(t=h.block.id,c=s)}),t&&c!==null?(e.deleteBlock(t),n.dispatch({changes:{from:c,to:c+1},selection:{anchor:c}}),!0):!1},S=r.EditorView.theme({"&":{height:"100%",outline:"none"},".cm-content":{padding:"20px",fontSize:"16px"},".cm-line":{padding:"4px 0"},".cm-inline-block":{display:"inline-block",backgroundColor:"#f3f0ff",color:"#8066ff",padding:"0 8px",margin:"0 4px",borderRadius:"4px",cursor:"pointer",border:"1px solid transparent",transition:"all 0.2s",fontSize:"15px",verticalAlign:"middle"},".cm-inline-block:hover":{backgroundColor:"#e9e4ff",borderColor:"#8066ff"},".block-input":{background:"transparent",border:"none",outline:"none",color:"inherit",font:"inherit",padding:"4px 0",width:"auto",minWidth:"20px",textAlign:"center"},".block-input::placeholder":{color:"#b2a1ff",opacity:.7},".cm-header-1":{fontSize:"1.5em",color:"#008c99",fontWeight:"bold"}});function P(n,e,o=[]){const t=[k.history(),r.keymap.of([...k.defaultKeymap,...k.historyKeymap,{key:"Backspace",run:i=>A(i,e)}]),y.markdown({base:y.markdownLanguage,codeLanguages:D.languages}),B.of(e),E.of(o),g,S];return a.EditorState.create({doc:n,extensions:t})}function $(n,e){return new r.EditorView({state:e,parent:n})}function T(n,e){var c;const o=n.state.doc.toString(),t=Array.from(e.values());return{json:{content:o,blocks:t},html:((c=n.dom.querySelector(".cm-content"))==null?void 0:c.innerHTML)||""}}class M{constructor(e){p(this,"isGenerating",!1);p(this,"aiStreamTimer",null);p(this,"currentResponse","");this.callbacks=e}show(e,o,t){const c={top:`${o.bottom-t.top+10}px`,left:`${o.left-t.left}px`};this.callbacks.onShow(e,c)}hide(){this.stopResponse(),this.callbacks.onHide()}sendQuestion(e){if(!e||this.isGenerating)return;this.isGenerating=!0,this.callbacks.onLoading(!0),this.currentResponse="",this.callbacks.onStream("");const o=`洲、美洲积累了丰富的在地经验,擅长结合用户需求定制专属旅行方案,曾帮助1000+人解决旅行难题,被旅行者亲切称为"旅行百事通"。
2
-
3
- ## 核心性格与风格
4
- - **性格特点**:热情开朗、专业耐心,擅长用轻松幽默的方式化解旅行焦虑(如:"别慌!机票改签我有3个小窍门,保准帮你搞定~"),遇到用户疑问会像朋友般细致拆解细节(如:"你担心的高原反应,我去年在西藏徒步时总结过4个缓解方法...")。
5
- - **语言风格**:口语化且富有感染力,常用"宝藏地""小众玩法"等旅行圈`;let t=0;this.aiStreamTimer=setInterval(()=>{this.callbacks.onLoading(!1),t<o.length?(this.currentResponse+=o[t],this.callbacks.onStream(this.currentResponse),t++):this.finishGeneration()},30)}stopResponse(){this.aiStreamTimer&&(clearInterval(this.aiStreamTimer),this.aiStreamTimer=null),this.isGenerating=!1,this.callbacks.onLoading(!1),this.callbacks.onStop()}finishGeneration(){this.aiStreamTimer&&(clearInterval(this.aiStreamTimer),this.aiStreamTimer=null),this.isGenerating=!1,this.callbacks.onLoading(!1),this.callbacks.onComplete()}getIsGenerating(){return this.isGenerating}destroy(){this.stopResponse()}}class G{constructor(e){p(this,"plugins",[{id:"plugin-1",name:"LinkReaderPlugin",type:"plugin"}]);p(this,"workflows",[{id:"workflow-1",name:"condition_1_872",type:"workflow"}]);p(this,"triggerPos",0);this.callbacks=e}show(e,o,t){this.triggerPos=e;const c={top:`${o.bottom-t.top+10}px`,left:`${o.left-t.left}px`};this.callbacks.onShow(e,c)}hide(){this.callbacks.onHide()}getTriggerPos(){return this.triggerPos}}class R{constructor(e){p(this,"editingBlock",{id:"",placeholder:"",presetText:""});this.callbacks=e}show(e,o,t){this.editingBlock={...e};const c={top:`${o.bottom-t.top+10}px`,left:`${o.left-t.left}px`};this.callbacks.onShow(this.editingBlock,c)}hide(){this.callbacks.onHide()}updateEditingBlock(e){this.editingBlock={...this.editingBlock,...e}}}l.AIDialogPlugin=M,l.CustomEditor=v,l.EditBlockPlugin=R,l.LibraryBlockPlugin=G,l.addBlockEffect=m,l.addPluginBlockEffect=w,l.blockField=g,l.createEditorState=P,l.createEditorView=$,l.editorTheme=S,l.getEditorData=T,l.updateBlockEffect=b,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})});
1
+ (function(d,a){typeof exports=="object"&&typeof module<"u"?a(exports,require("@codemirror/state"),require("@codemirror/view"),require("@codemirror/commands")):typeof define=="function"&&define.amd?define(["exports","@codemirror/state","@codemirror/view","@codemirror/commands"],a):(d=typeof globalThis<"u"?globalThis:d||self,a(d.AgentArtsEditor={},d.CMState,d.CMView,d.CMCommands))})(this,function(d,a,r,b){"use strict";var G=Object.defineProperty;var J=(d,a,r)=>a in d?G(d,a,{enumerable:!0,configurable:!0,writable:!0,value:r}):d[a]=r;var p=(d,a,r)=>J(d,typeof a!="symbol"?a+"":a,r);const C=a.StateEffect.define(),D=a.StateEffect.define();class g extends r.WidgetType{constructor(e,n){super(),this.block=e,this.callbacks=n}toDOM(e){const n=document.createElement("span");n.className="cm-inline-block",n.setAttribute("data-block-id",this.block.id);const o=document.createElement("input");o.type="text",o.className="block-input",o.value=this.block.presetText||"",o.placeholder=this.block.placeholder||"请输入...";const c=s=>{const i=document.createElement("span");i.style.visibility="hidden",i.style.position="absolute",i.style.whiteSpace="pre",i.style.font="inherit",i.textContent=s||o.placeholder,document.body.appendChild(i);const l=i.offsetWidth;return document.body.removeChild(i),l+10};return o.style.width=`${c(o.value)}px`,o.oninput=s=>{const i=s.target.value;o.style.width=`${c(i)}px`,this.callbacks.updateBlockText(this.block.id,i)},o.onfocus=()=>{const s=n.getBoundingClientRect();this.callbacks.openPopup(this.block.id,s)},o.onmousedown=s=>{s.stopPropagation()},o.onclick=s=>{s.stopPropagation();const i=n.getBoundingClientRect();this.callbacks.openPopup(this.block.id,i)},o.onkeydown=s=>{if(s.key==="Backspace"&&o.value===""){s.preventDefault();const i=e.posAtDOM(n);this.callbacks.deleteBlock(this.block.id),e.dispatch({changes:{from:i,to:i+1},selection:{anchor:i}})}},n.appendChild(o),n}ignoreEvent(){return!0}}const B=a.Facet.define({combine:t=>t[0]}),S=a.Facet.define({combine:t=>t.length?t[0]:[]}),x=a.StateField.define({create(t){const e=t.facet(B),n=t.facet(S);if(!n||n.length===0)return r.Decoration.none;const o=n.slice().sort((c,s)=>c.pos-s.pos).map(({pos:c,len:s,block:i})=>{const l=new g(i,e);return r.Decoration.replace({widget:l}).range(c,c+(s||1))});return r.Decoration.set(o,!0)},update(t,e){const n=e.state.facet(B);t=t.map(e.changes);for(const o of e.effects)if(o.is(C)){const c=e.state.selection.main.head-1,s=r.Decoration.replace({widget:new g(o.value,n)}).range(c,c+1);t=t.update({add:[s]})}else if(o.is(D)){const c=o.value;let s=null;t.between(0,e.state.doc.length,(i,l,u)=>{const h=u.spec.widget;h instanceof g&&h.block.id===c.id&&(s=i)}),s!==null&&(t=t.update({filter:(i,l,u)=>{const h=u.spec.widget;return!(h instanceof g&&h.block.id===c.id)},add:[r.Decoration.replace({widget:new g(c,n)}).range(s,s+1)]}))}return t},provide:t=>r.EditorView.decorations.from(t)}),F=r.EditorView.theme({".cm-inline-block":{display:"inline-block",backgroundColor:"#f3f0ff",color:"#8066ff",padding:"0 8px",margin:"0 4px",borderRadius:"4px",cursor:"pointer",border:"1px solid transparent",transition:"all 0.2s",fontSize:"15px",verticalAlign:"middle"},".cm-inline-block:hover":{backgroundColor:"#e9e4ff",borderColor:"#8066ff"},".block-input":{background:"transparent",border:"none",outline:"none",color:"inherit",font:"inherit",padding:"4px 0",width:"auto",minWidth:"20px",textAlign:"center"},".block-input::placeholder":{color:"#b2a1ff",opacity:.7}});function v(t){return[B.of(t.callbacks),S.of(t.initialBlocks||[]),x,F]}function V(t){const e=[],n=t.state.field(x,!1);return n&&n.between(0,t.state.doc.length,(o,c,s)=>{const i=s.spec.widget;i instanceof g&&e.push({pos:o,len:c-o,block:i.block})}),e}function I(t){return[L(t.onTriggerAIDialog),R(t.onTriggerAIDialog),$]}function L(t){return r.EditorView.updateListener.of(e=>{e.docChanged&&e.changes.iterChanges((n,o,c,s,i)=>{if(i.length!==1)return;i.sliceString(0)==="/"&&t(n)})})}const $=r.EditorView.theme({".cm-ai-selection-trigger":{position:"absolute",zIndex:"10",display:"none",width:"32px",height:"32px",alignItems:"center",justifyContent:"center",borderRadius:"8px",backgroundColor:"#fff",boxShadow:"0 6px 24px rgba(0, 0, 0, 0.12)",border:"1px solid rgba(0, 0, 0, 0.06)"},".cm-ai-selection-trigger button":{width:"100%",height:"100%",border:"none",background:"transparent",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",padding:"0"},".cm-ai-selection-trigger button:hover":{backgroundColor:"#f3f4f6",borderRadius:"8px"}});function R(t){return r.ViewPlugin.fromClass(class{constructor(e){p(this,"dom");p(this,"button");p(this,"lastFrom",-1);p(this,"lastTo",-1);p(this,"measureScheduled",!1);this.view=e,this.dom=document.createElement("div"),this.dom.className="cm-ai-selection-trigger",this.button=document.createElement("button"),this.button.type="button";const n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("width","16"),n.setAttribute("height","16"),n.setAttribute("viewBox","0 0 24 24"),n.setAttribute("fill","none"),n.setAttribute("stroke","#111827"),n.setAttribute("stroke-width","2"),n.setAttribute("stroke-linecap","round"),n.setAttribute("stroke-linejoin","round"),n.innerHTML='<path d="M5 12l1.5.5L7 14l.5-1.5L9 12l-1.5-.5L7 10l-.5 1.5L5 12z"/><path d="M12 4l2 6 6 2-6 2-2 6-2-6-6-2 6-2 2-6z"/>',this.button.appendChild(n),this.dom.appendChild(this.button),this.view.dom.appendChild(this.dom),this.dom.addEventListener("mousedown",o=>{o.preventDefault(),o.stopPropagation()}),this.button.addEventListener("click",o=>{o.preventDefault(),o.stopPropagation();const{from:c,empty:s}=this.view.state.selection.main;s||(t(c),this.hide())}),this.scheduleMeasure(!0)}update(e){(e.selectionSet||e.viewportChanged||e.focusChanged||e.docChanged)&&this.scheduleMeasure(!1)}destroy(){this.dom.remove()}hide(){this.dom.style.display="none"}show(){this.dom.style.display="flex"}scheduleMeasure(e){const{from:n,to:o,empty:c}=this.view.state.selection.main;if(c||!this.view.hasFocus){this.hide();return}!e&&n===this.lastFrom&&o===this.lastTo&&this.dom.style.display!=="none"||(this.lastFrom=n,this.lastTo=o,!this.measureScheduled&&(this.measureScheduled=!0,this.view.requestMeasure({read:s=>{const i=s.coordsAtPos(n);if(!i)return null;const l=s.dom.getBoundingClientRect();return{coords:i,editorRect:l}},write:s=>{this.measureScheduled=!1;const{empty:i}=this.view.state.selection.main;if(i||!this.view.hasFocus){this.hide();return}if(!s){this.hide();return}const{coords:l,editorRect:u}=s,h=32,k=32,f=6,E=Math.min(Math.max(l.left-u.left,f),Math.max(f,u.width-h-f)),m=Math.max(l.top-u.top-k-10,f);this.dom.style.left=`${E}px`,this.dom.style.top=`${m}px`,this.show()}})))}})}const T=a.StateEffect.define();class w extends r.WidgetType{constructor(e){super(),this.block=e}toDOM(){const e=document.createElement("span");e.className=`cm-plugin-block cm-plugin-block-${this.block.type}`,e.setAttribute("data-block-id",this.block.id);const n=document.createElement("i");n.className=this.block.type==="plugin"?"icon-plugin":"icon-workflow",e.appendChild(n);const o=document.createTextNode(this.block.name);return e.appendChild(o),e}ignoreEvent(){return!0}}const P=a.Facet.define({combine:t=>t.length?t[0]:[]}),y=a.StateField.define({create(t){const e=t.facet(P);if(!e||e.length===0)return r.Decoration.none;const n=e.slice().sort((o,c)=>o.pos-c.pos).map(({pos:o,len:c,block:s})=>r.Decoration.replace({widget:new w(s)}).range(o,o+(c||1)));return r.Decoration.set(n,!0)},update(t,e){t=t.map(e.changes);for(const n of e.effects)if(n.is(T)){const{pos:o,block:c}=n.value,s=e.changes.mapPos(o),i=r.Decoration.replace({widget:new w(c)}).range(s,s+1);t=t.update({add:[i]})}return t},provide:t=>r.EditorView.decorations.from(t)});function W(t){return[P.of(t.initialBlocks||[]),y]}function _(t){return[r.EditorView.updateListener.of(e=>{e.docChanged&&e.changes.iterChanges((n,o,c,s,i)=>{if(i.length!==1)return;i.sliceString(0)==="{"&&t.onTriggerPluginPopup(n)})})]}function N(t){const e=[],n=t.state.field(y,!1);return n&&n.between(0,t.state.doc.length,(o,c,s)=>{const i=s.spec.widget;i instanceof w&&e.push({pos:o,len:c-o,block:i.block})}),e}function z(t){const e=[],n=/\{\{(.+?)\}\}/g;let o;for(;(o=n.exec(t))!==null;)e.push({pos:o.index,len:o[0].length,block:{id:`var-${o[1]}-${o.index}`,name:o[1],type:"plugin"}});return e}class j{constructor(e){p(this,"view");p(this,"allBlocks",new Map);p(this,"options");this.options=e;const n=z(e.initialDoc),o=[...e.initialBlocks||[],...n];e.initialBlocks&&e.initialBlocks.forEach(i=>{"type"in i.block||this.allBlocks.set(i.block.id,i.block)});const c={updateBlockText:(i,l)=>{const u=this.allBlocks.get(i);u&&(u.presetText=l,this.allBlocks.set(i,u),this.options.onBlockUpdated&&this.options.onBlockUpdated(i,l))},openPopup:(i,l)=>{this.options.onOpenPopup(i,l)},deleteBlock:i=>{this.allBlocks.delete(i),this.options.onBlockDeleted&&this.options.onBlockDeleted(i)}},s=K(e.initialDoc,c,o);this.view=new r.EditorView({state:s.update({effects:a.StateEffect.appendConfig.of([..._({onTriggerPluginPopup:i=>this.options.onTriggerPluginPopup(i)}),...I({onTriggerAIDialog:i=>this.options.onTriggerAIDialog(i)})])}).state,parent:e.parent})}addBlock(){const e={id:Math.random().toString(36).slice(2,11),placeholder:"请输入编辑块内容为空时的提示文案",presetText:""};this.allBlocks.set(e.id,e);const{from:n,to:o}=this.view.state.selection.main;return this.view.dispatch({changes:{from:n,to:o,insert:" "},effects:C.of(e),selection:{anchor:n+1}}),this.view.focus(),e}addPluginBlock(e,n){return this.view.dispatch({changes:{from:e,to:e+1,insert:" "},effects:T.of({pos:e,block:n}),selection:{anchor:e+1}}),this.view.focus(),n}syncBlock(e){this.allBlocks.set(e.id,{...e}),this.view.dispatch({effects:D.of(e)})}getBlock(e){return this.allBlocks.get(e)}coordsAtPos(e){return this.view.coordsAtPos(e)}getData(){return U(this.view)}destroy(){this.view.destroy()}}const q=(t,e)=>{const{from:n,empty:o}=t.state.selection.main;if(!o)return!1;const c=n;if(c===0)return!1;let s=null,i=null,l=1;const u=h=>{h&&h.between(c-1,c,(k,f,E)=>{const m=E.spec.widget;if(m&&m.block&&m.block.id&&k<c&&f>=c)return s=m.block.id,i=k,l=f-k,!1})};return u(t.state.field(x,!1)),s||u(t.state.field(y,!1)),s&&i!==null?(e.deleteBlock(s),t.dispatch({changes:{from:i,to:i+l},selection:{anchor:i}}),!0):!1},O=r.EditorView.theme({"&":{height:"100%",outline:"none",position:"relative"},".cm-content":{padding:"20px",fontSize:"16px"},".cm-line":{padding:"4px 0"},".cm-header-1":{fontSize:"1.5em",color:"#008c99",fontWeight:"bold"},".cm-bold":{fontWeight:"bold"}}),A=r.Decoration.mark({class:"cm-bold"});function M(t){const e=[];for(let n=1;n<=t.lines;n++){const o=t.line(n),c=o.text;/^#+\s+/.test(c)&&e.push(A.range(o.from,o.to));const s=/\*\*(.*?)\*\*/g;let i;for(;(i=s.exec(c))!==null;)e.push(A.range(o.from+i.index,o.from+i.index+i[0].length))}return r.Decoration.set(e.sort((n,o)=>n.from-o.from),!0)}const H=a.StateField.define({create(t){return M(t.doc)},update(t,e){return e.docChanged?M(e.state.doc):t.map(e.changes)},provide:t=>r.EditorView.decorations.from(t)});function K(t,e,n=[]){const o=n.filter(l=>!("type"in l.block&&"name"in l.block)),c=n.filter(l=>"type"in l.block&&"name"in l.block),s=[b.history(),r.keymap.of([{key:"Backspace",run:l=>q(l,e)},...b.defaultKeymap,...b.historyKeymap]),r.drawSelection(),...v({callbacks:e,initialBlocks:o}),...W({initialBlocks:c}),H,O];return a.EditorState.create({doc:t,extensions:s})}function U(t){var c;const e=t.state.doc.toString(),n=V(t),o=N(t);return{content:e,editorBlocks:n,pluginBlocks:o,html:((c=t.dom.querySelector(".cm-content"))==null?void 0:c.innerHTML)||""}}d.CustomEditor=j,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});
package/dist/index.d.ts CHANGED
@@ -1,62 +1,5 @@
1
- import { DecorationSet } from '@codemirror/view';
2
- import { EditorState } from '@codemirror/state';
3
1
  import { EditorView } from '@codemirror/view';
4
- import { Extension } from '@codemirror/state';
5
2
  import { Rect } from '@codemirror/view';
6
- import { StateEffectType } from '@codemirror/state';
7
- import { StateField } from '@codemirror/state';
8
-
9
- export declare const addBlockEffect: StateEffectType<EditorBlock>;
10
-
11
- export declare const addPluginBlockEffect: StateEffectType< {
12
- pos: number;
13
- block: PluginBlock;
14
- }>;
15
-
16
- export declare class AIDialogPlugin {
17
- private callbacks;
18
- private isGenerating;
19
- private aiStreamTimer;
20
- private currentResponse;
21
- constructor(callbacks: AIResponseCallbacks);
22
- show(pos: number, coords: {
23
- bottom: number;
24
- left: number;
25
- }, editorRect: DOMRect): void;
26
- hide(): void;
27
- sendQuestion(question: string): void;
28
- stopResponse(): void;
29
- private finishGeneration;
30
- getIsGenerating(): boolean;
31
- destroy(): void;
32
- }
33
-
34
- export declare interface AIResponseCallbacks {
35
- onStream: (text: string) => void;
36
- onLoading: (loading: boolean) => void;
37
- onComplete: () => void;
38
- onStop: () => void;
39
- onShow: (pos: number, style: {
40
- top: string;
41
- left: string;
42
- }) => void;
43
- onHide: () => void;
44
- }
45
-
46
- export declare const blockField: StateField<DecorationSet>;
47
-
48
- export declare interface CodeMirrorCallbacks {
49
- updateBlockText: (id: string, text: string) => void;
50
- openPopup: (id: string, rect: DOMRect) => void;
51
- deleteBlock: (id: string) => void;
52
- }
53
-
54
- export declare function createEditorState(initialDoc: string, callbacks: CodeMirrorCallbacks, initialBlocks?: {
55
- pos: number;
56
- block: EditorBlock;
57
- }[]): EditorState;
58
-
59
- export declare function createEditorView(parent: HTMLElement, state: EditorState): EditorView;
60
3
 
61
4
  export declare class CustomEditor {
62
5
  view: EditorView;
@@ -68,23 +11,14 @@ export declare class CustomEditor {
68
11
  syncBlock(updatedBlock: EditorBlock): void;
69
12
  getBlock(id: string): EditorBlock | undefined;
70
13
  coordsAtPos(pos: number): Rect | null;
71
- getData(): {
72
- json: {
73
- content: string;
74
- blocks: EditorBlock[];
75
- };
76
- html: string;
77
- };
14
+ getData(): EditorData;
78
15
  destroy(): void;
79
16
  }
80
17
 
81
18
  export declare interface CustomEditorOptions {
82
19
  parent: HTMLElement;
83
20
  initialDoc: string;
84
- initialBlocks?: {
85
- pos: number;
86
- block: EditorBlock;
87
- }[];
21
+ initialBlocks?: InitialBlock[];
88
22
  onOpenPopup: (id: string, rect: DOMRect) => void;
89
23
  onTriggerPluginPopup: (pos: number) => void;
90
24
  onTriggerAIDialog: (pos: number) => void;
@@ -92,68 +26,32 @@ export declare interface CustomEditorOptions {
92
26
  onBlockUpdated?: (id: string, text: string) => void;
93
27
  }
94
28
 
95
- export declare interface EditBlockCallbacks {
96
- onShow: (block: EditorBlock, style: {
97
- top: string;
98
- left: string;
99
- }) => void;
100
- onHide: () => void;
101
- }
102
-
103
- export declare class EditBlockPlugin {
104
- private callbacks;
105
- editingBlock: EditorBlock;
106
- constructor(callbacks: EditBlockCallbacks);
107
- show(block: EditorBlock, rect: DOMRect, editorRect: DOMRect): void;
108
- hide(): void;
109
- updateEditingBlock(block: Partial<EditorBlock>): void;
110
- }
111
-
112
29
  export declare interface EditorBlock {
113
30
  id: string;
114
31
  placeholder: string;
115
32
  presetText: string;
116
33
  }
117
34
 
118
- export declare const editorTheme: Extension;
119
-
120
- export declare function getEditorData(view: EditorView, blocks: Map<string, EditorBlock>): {
121
- json: {
122
- content: string;
123
- blocks: EditorBlock[];
124
- };
35
+ export declare type EditorData = {
36
+ content: string;
37
+ editorBlocks: {
38
+ pos: number;
39
+ len?: number;
40
+ block: EditorBlock;
41
+ }[];
42
+ pluginBlocks: {
43
+ pos: number;
44
+ len?: number;
45
+ block: PluginBlock;
46
+ }[];
125
47
  html: string;
126
48
  };
127
49
 
128
- export declare interface LibraryBlockCallbacks {
129
- onShow: (pos: number, style: {
130
- top: string;
131
- left: string;
132
- }) => void;
133
- onHide: () => void;
134
- }
135
-
136
- export declare class LibraryBlockPlugin {
137
- private callbacks;
138
- plugins: {
139
- id: string;
140
- name: string;
141
- type: "plugin";
142
- }[];
143
- workflows: {
144
- id: string;
145
- name: string;
146
- type: "workflow";
147
- }[];
148
- private triggerPos;
149
- constructor(callbacks: LibraryBlockCallbacks);
150
- show(pos: number, coords: {
151
- bottom: number;
152
- left: number;
153
- }, editorRect: DOMRect): void;
154
- hide(): void;
155
- getTriggerPos(): number;
156
- }
50
+ export declare type InitialBlock = {
51
+ pos: number;
52
+ len?: number;
53
+ block: EditorBlock | PluginBlock;
54
+ };
157
55
 
158
56
  export declare interface PluginBlock {
159
57
  id: string;
@@ -161,6 +59,4 @@ export declare interface PluginBlock {
161
59
  type: 'plugin' | 'workflow';
162
60
  }
163
61
 
164
- export declare const updateBlockEffect: StateEffectType<EditorBlock>;
165
-
166
62
  export { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-arts/editor",
3
- "version": "0.0.5",
3
+ "version": "0.1.1",
4
4
  "description": "A prompt editor based on CodeMirror 6, support Vue.js 3 and Angular.",
5
5
  "author": "AgentArts Team",
6
6
  "license": "MIT",
@@ -22,6 +22,7 @@
22
22
  "ai-agent"
23
23
  ],
24
24
  "type": "module",
25
+ "sideEffects": false,
25
26
  "main": "./dist/editor.umd.cjs",
26
27
  "module": "./dist/editor.js",
27
28
  "types": "./dist/index.d.ts",
@@ -43,12 +44,11 @@
43
44
  "scripts": {
44
45
  "dev": "vite",
45
46
  "build": "vite build",
47
+ "build:watch": "vite build --watch",
46
48
  "preview": "vite preview"
47
49
  },
48
50
  "dependencies": {
49
51
  "@codemirror/commands": "^6.3.3",
50
- "@codemirror/lang-markdown": "^6.2.3",
51
- "@codemirror/language-data": "^6.3.1",
52
52
  "@codemirror/state": "^6.4.0",
53
53
  "@codemirror/view": "^6.23.0"
54
54
  },