@agent-arts/editor 0.0.5 → 0.1.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.
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
- });
1
+ var I = Object.defineProperty;
2
+ var F = (o, t, e) => t in o ? I(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
3
+ var r = (o, t, e) => F(o, typeof t != "symbol" ? t + "" : t, e);
4
+ import { StateEffect as k, Facet as x, StateField as y, EditorState as R } from "@codemirror/state";
5
+ import { EditorView as u, Decoration as d, WidgetType as E, ViewPlugin as $, keymap as _, drawSelection as G } from "@codemirror/view";
6
+ import { history as W, defaultKeymap as N, historyKeymap as z } from "@codemirror/commands";
7
+ const C = k.define(), A = k.define();
8
+ class g extends E {
9
+ constructor(t, e) {
10
+ super(), this.block = t, this.callbacks = e;
38
11
  }
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;
52
- }
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 e = document.createElement("span");
14
+ e.className = "cm-inline-block", e.setAttribute("data-block-id", this.block.id);
15
+ const i = document.createElement("input");
16
+ i.type = "text", i.className = "block-input", i.value = this.block.presetText || "", i.placeholder = this.block.placeholder || "请输入...";
17
+ const l = (s) => {
18
+ const n = document.createElement("span");
19
+ n.style.visibility = "hidden", n.style.position = "absolute", n.style.whiteSpace = "pre", n.style.font = "inherit", n.textContent = s || i.placeholder, document.body.appendChild(n);
20
+ const c = n.offsetWidth;
21
+ return document.body.removeChild(n), c + 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 i.style.width = `${l(i.value)}px`, i.oninput = (s) => {
24
+ const n = s.target.value;
25
+ i.style.width = `${l(n)}px`, this.callbacks.updateBlockText(this.block.id, n);
26
+ }, i.onfocus = () => {
27
+ const s = e.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
+ }, i.onmousedown = (s) => {
30
+ s.stopPropagation();
31
+ }, i.onclick = (s) => {
32
+ s.stopPropagation();
33
+ const n = e.getBoundingClientRect();
34
+ this.callbacks.openPopup(this.block.id, n);
35
+ }, i.onkeydown = (s) => {
36
+ if (s.key === "Backspace" && i.value === "") {
37
+ s.preventDefault();
38
+ const n = t.posAtDOM(e);
39
+ this.callbacks.deleteBlock(this.block.id), t.dispatch({
40
+ changes: { from: n, to: n + 1 },
41
+ selection: { anchor: n }
42
+ });
116
43
  }
117
- }, t.appendChild(o), t;
118
- }
119
- ignoreEvent(e) {
120
- return !0;
44
+ }, e.appendChild(i), e;
121
45
  }
122
- }
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) {
46
+ ignoreEvent() {
136
47
  return !0;
137
48
  }
138
49
  }
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 = x.define({
51
+ combine: (o) => o[0]
52
+ }), D = x.define({
53
+ combine: (o) => o.length ? o[0] : []
54
+ }), v = y.define({
55
+ create(o) {
56
+ const t = o.facet(w), e = o.facet(D);
57
+ if (!e || e.length === 0) return d.none;
58
+ const i = e.slice().sort((l, s) => l.pos - s.pos).map(({ pos: l, len: s, block: n }) => {
59
+ const c = new g(n, t);
60
+ return d.replace({ widget: c }).range(l, l + (s || 1));
61
+ });
62
+ return d.set(i, !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)
64
+ update(o, t) {
65
+ const e = t.state.facet(w);
66
+ o = o.map(t.changes);
67
+ for (const i of t.effects)
68
+ if (i.is(C)) {
69
+ const l = t.state.selection.main.head - 1, s = d.replace({
70
+ widget: new g(i.value, e)
159
71
  }).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);
72
+ o = o.update({ add: [s] });
73
+ } else if (i.is(A)) {
74
+ const l = i.value;
75
+ let s = null;
76
+ o.between(0, t.state.doc.length, (n, c, a) => {
77
+ const h = a.spec.widget;
78
+ h instanceof g && h.block.id === l.id && (s = n);
79
+ }), s !== null && (o = o.update({
80
+ filter: (n, c, a) => {
81
+ const h = a.spec.widget;
82
+ return !(h instanceof g && h.block.id === l.id);
171
83
  },
172
- add: [p.replace({
173
- widget: new h(l, t)
174
- }).range(i, i + 1)]
84
+ add: [d.replace({
85
+ widget: new g(l, e)
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 o;
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: (o) => u.decorations.from(o)
92
+ }), H = u.theme({
201
93
  ".cm-inline-block": {
202
94
  display: "inline-block",
203
95
  backgroundColor: "#f3f0ff",
@@ -229,76 +121,71 @@ 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 O(o) {
127
+ return [
128
+ w.of(o.callbacks),
129
+ D.of(o.initialBlocks || []),
130
+ v,
131
+ H
251
132
  ];
252
- return C.create({
253
- doc: n,
254
- extensions: o
255
- });
256
133
  }
257
- function q(n, e) {
258
- return new f({
259
- state: e,
260
- parent: n
261
- });
134
+ function j(o) {
135
+ const t = [], e = o.state.field(v, !1);
136
+ return e && e.between(0, o.state.doc.length, (i, l, s) => {
137
+ const n = s.spec.widget;
138
+ n instanceof g && t.push({ pos: i, len: l - i, block: n.block });
139
+ }), t;
262
140
  }
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
- };
141
+ class rt {
142
+ constructor(t) {
143
+ r(this, "editingBlock", { id: "", placeholder: "", presetText: "" });
144
+ this.callbacks = t;
145
+ }
146
+ show(t, e, i) {
147
+ this.editingBlock = { ...t };
148
+ const l = {
149
+ top: `${e.bottom - i.top + 10}px`,
150
+ left: `${e.left - i.left}px`
151
+ };
152
+ this.callbacks.onShow(this.editingBlock, l);
153
+ }
154
+ hide() {
155
+ this.callbacks.onHide();
156
+ }
157
+ updateEditingBlock(t) {
158
+ this.editingBlock = { ...this.editingBlock, ...t };
159
+ }
273
160
  }
274
- class Q {
275
- constructor(e) {
161
+ class at {
162
+ constructor(t) {
276
163
  r(this, "isGenerating", !1);
277
164
  r(this, "aiStreamTimer", null);
278
165
  r(this, "currentResponse", "");
279
- this.callbacks = e;
166
+ this.callbacks = t;
280
167
  }
281
- show(e, t, o) {
168
+ show(t, e, i) {
282
169
  const l = {
283
- top: `${t.bottom - o.top + 10}px`,
284
- left: `${t.left - o.left}px`
170
+ top: `${e.bottom - i.top + 10}px`,
171
+ left: `${e.left - i.left}px`
285
172
  };
286
- this.callbacks.onShow(e, l);
173
+ this.callbacks.onShow(t, l);
287
174
  }
288
175
  hide() {
289
176
  this.stopResponse(), this.callbacks.onHide();
290
177
  }
291
- sendQuestion(e) {
292
- if (!e || this.isGenerating) return;
178
+ sendQuestion(t) {
179
+ if (!t || this.isGenerating) return;
293
180
  this.isGenerating = !0, this.callbacks.onLoading(!0), this.currentResponse = "", this.callbacks.onStream("");
294
- const t = `洲、美洲积累了丰富的在地经验,擅长结合用户需求定制专属旅行方案,曾帮助1000+人解决旅行难题,被旅行者亲切称为"旅行百事通"。
181
+ const e = `你是一个资深旅游向导,积累了丰富的在地经验,擅长结合用户需求定制专属旅行方案,曾帮助1000+人解决旅行难题,被旅行者亲切称为"旅行百事通"。
295
182
 
296
183
  ## 核心性格与风格
297
184
  - **性格特点**:热情开朗、专业耐心,擅长用轻松幽默的方式化解旅行焦虑(如:"别慌!机票改签我有3个小窍门,保准帮你搞定~"),遇到用户疑问会像朋友般细致拆解细节(如:"你担心的高原反应,我去年在西藏徒步时总结过4个缓解方法...")。
298
185
  - **语言风格**:口语化且富有感染力,常用"宝藏地""小众玩法"等旅行圈`;
299
- let o = 0;
186
+ let i = 0;
300
187
  this.aiStreamTimer = setInterval(() => {
301
- this.callbacks.onLoading(!1), o < t.length ? (this.currentResponse += t[o], this.callbacks.onStream(this.currentResponse), o++) : this.finishGeneration();
188
+ this.callbacks.onLoading(!1), i < e.length ? (this.currentResponse += e[i], this.callbacks.onStream(this.currentResponse), i++) : this.finishGeneration();
302
189
  }, 30);
303
190
  }
304
191
  stopResponse() {
@@ -314,8 +201,194 @@ class Q {
314
201
  this.stopResponse();
315
202
  }
316
203
  }
317
- class J {
318
- constructor(e) {
204
+ function V(o) {
205
+ return [
206
+ q(o.onTriggerAIDialog),
207
+ U(o.onTriggerAIDialog),
208
+ K
209
+ ];
210
+ }
211
+ function q(o) {
212
+ return u.updateListener.of((t) => {
213
+ t.docChanged && t.changes.iterChanges((e, i, l, s, n) => {
214
+ if (n.length !== 1) return;
215
+ n.sliceString(0) === "/" && o(e);
216
+ });
217
+ });
218
+ }
219
+ const K = u.theme({
220
+ ".cm-ai-selection-trigger": {
221
+ position: "absolute",
222
+ zIndex: "10",
223
+ display: "none",
224
+ width: "32px",
225
+ height: "32px",
226
+ alignItems: "center",
227
+ justifyContent: "center",
228
+ borderRadius: "8px",
229
+ backgroundColor: "#fff",
230
+ boxShadow: "0 6px 24px rgba(0, 0, 0, 0.12)",
231
+ border: "1px solid rgba(0, 0, 0, 0.06)"
232
+ },
233
+ ".cm-ai-selection-trigger button": {
234
+ width: "100%",
235
+ height: "100%",
236
+ border: "none",
237
+ background: "transparent",
238
+ cursor: "pointer",
239
+ display: "flex",
240
+ alignItems: "center",
241
+ justifyContent: "center",
242
+ padding: "0"
243
+ },
244
+ ".cm-ai-selection-trigger button:hover": {
245
+ backgroundColor: "#f3f4f6",
246
+ borderRadius: "8px"
247
+ }
248
+ });
249
+ function U(o) {
250
+ return $.fromClass(class {
251
+ constructor(t) {
252
+ r(this, "dom");
253
+ r(this, "button");
254
+ r(this, "lastFrom", -1);
255
+ r(this, "lastTo", -1);
256
+ r(this, "measureScheduled", !1);
257
+ this.view = t, this.dom = document.createElement("div"), this.dom.className = "cm-ai-selection-trigger", this.button = document.createElement("button"), this.button.type = "button";
258
+ const e = document.createElementNS("http://www.w3.org/2000/svg", "svg");
259
+ e.setAttribute("width", "16"), e.setAttribute("height", "16"), e.setAttribute("viewBox", "0 0 24 24"), e.setAttribute("fill", "none"), e.setAttribute("stroke", "#111827"), e.setAttribute("stroke-width", "2"), e.setAttribute("stroke-linecap", "round"), e.setAttribute("stroke-linejoin", "round"), e.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(e), this.dom.appendChild(this.button), this.view.dom.appendChild(this.dom), this.dom.addEventListener("mousedown", (i) => {
260
+ i.preventDefault(), i.stopPropagation();
261
+ }), this.button.addEventListener("click", (i) => {
262
+ i.preventDefault(), i.stopPropagation();
263
+ const { from: l, empty: s } = this.view.state.selection.main;
264
+ s || (o(l), this.hide());
265
+ }), this.scheduleMeasure(!0);
266
+ }
267
+ update(t) {
268
+ (t.selectionSet || t.viewportChanged || t.focusChanged || t.docChanged) && this.scheduleMeasure(!1);
269
+ }
270
+ destroy() {
271
+ this.dom.remove();
272
+ }
273
+ hide() {
274
+ this.dom.style.display = "none";
275
+ }
276
+ show() {
277
+ this.dom.style.display = "flex";
278
+ }
279
+ scheduleMeasure(t) {
280
+ const { from: e, to: i, empty: l } = this.view.state.selection.main;
281
+ if (l || !this.view.hasFocus) {
282
+ this.hide();
283
+ return;
284
+ }
285
+ !t && e === this.lastFrom && i === this.lastTo && this.dom.style.display !== "none" || (this.lastFrom = e, this.lastTo = i, !this.measureScheduled && (this.measureScheduled = !0, this.view.requestMeasure({
286
+ read: (s) => {
287
+ const n = s.coordsAtPos(e);
288
+ if (!n) return null;
289
+ const c = s.dom.getBoundingClientRect();
290
+ return { coords: n, editorRect: c };
291
+ },
292
+ write: (s) => {
293
+ this.measureScheduled = !1;
294
+ const { empty: n } = this.view.state.selection.main;
295
+ if (n || !this.view.hasFocus) {
296
+ this.hide();
297
+ return;
298
+ }
299
+ if (!s) {
300
+ this.hide();
301
+ return;
302
+ }
303
+ const { coords: c, editorRect: a } = s, h = 32, m = 32, p = 6, b = Math.min(
304
+ Math.max(c.left - a.left, p),
305
+ Math.max(p, a.width - h - p)
306
+ ), f = Math.max(c.top - a.top - m - 10, p);
307
+ this.dom.style.left = `${b}px`, this.dom.style.top = `${f}px`, this.show();
308
+ }
309
+ })));
310
+ }
311
+ });
312
+ }
313
+ const M = k.define();
314
+ class B extends E {
315
+ constructor(t) {
316
+ super(), this.block = t;
317
+ }
318
+ toDOM() {
319
+ const t = document.createElement("span");
320
+ t.className = `cm-plugin-block cm-plugin-block-${this.block.type}`, t.setAttribute("data-block-id", this.block.id);
321
+ const e = document.createElement("i");
322
+ e.className = this.block.type === "plugin" ? "icon-plugin" : "icon-workflow", t.appendChild(e);
323
+ const i = document.createTextNode(this.block.name);
324
+ return t.appendChild(i), t;
325
+ }
326
+ ignoreEvent() {
327
+ return !0;
328
+ }
329
+ }
330
+ const L = x.define({
331
+ combine: (o) => o.length ? o[0] : []
332
+ }), S = y.define({
333
+ create(o) {
334
+ const t = o.facet(L);
335
+ if (!t || t.length === 0) return d.none;
336
+ const e = t.slice().sort((i, l) => i.pos - l.pos).map(({ pos: i, len: l, block: s }) => d.replace({ widget: new B(s) }).range(i, i + (l || 1)));
337
+ return d.set(e, !0);
338
+ },
339
+ update(o, t) {
340
+ o = o.map(t.changes);
341
+ for (const e of t.effects)
342
+ if (e.is(M)) {
343
+ const { pos: i, block: l } = e.value, s = t.changes.mapPos(i), n = d.replace({
344
+ widget: new B(l)
345
+ }).range(s, s + 1);
346
+ o = o.update({ add: [n] });
347
+ }
348
+ return o;
349
+ },
350
+ provide: (o) => u.decorations.from(o)
351
+ });
352
+ function Q(o) {
353
+ return [
354
+ L.of(o.initialBlocks || []),
355
+ S
356
+ ];
357
+ }
358
+ function J(o) {
359
+ return [
360
+ u.updateListener.of((t) => {
361
+ t.docChanged && t.changes.iterChanges((e, i, l, s, n) => {
362
+ if (n.length !== 1) return;
363
+ n.sliceString(0) === "{" && o.onTriggerPluginPopup(e);
364
+ });
365
+ })
366
+ ];
367
+ }
368
+ function X(o) {
369
+ const t = [], e = o.state.field(S, !1);
370
+ return e && e.between(0, o.state.doc.length, (i, l, s) => {
371
+ const n = s.spec.widget;
372
+ n instanceof B && t.push({ pos: i, len: l - i, block: n.block });
373
+ }), t;
374
+ }
375
+ function Y(o) {
376
+ const t = [], e = /\{\{(.+?)\}\}/g;
377
+ let i;
378
+ for (; (i = e.exec(o)) !== null; )
379
+ t.push({
380
+ pos: i.index,
381
+ len: i[0].length,
382
+ block: {
383
+ id: `var-${i[1]}-${i.index}`,
384
+ name: i[1],
385
+ type: "plugin"
386
+ }
387
+ });
388
+ return t;
389
+ }
390
+ class dt {
391
+ constructor(t) {
319
392
  r(this, "plugins", [
320
393
  { id: "plugin-1", name: "LinkReaderPlugin", type: "plugin" }
321
394
  ]);
@@ -323,15 +396,15 @@ class J {
323
396
  { id: "workflow-1", name: "condition_1_872", type: "workflow" }
324
397
  ]);
325
398
  r(this, "triggerPos", 0);
326
- this.callbacks = e;
399
+ this.callbacks = t;
327
400
  }
328
- show(e, t, o) {
329
- this.triggerPos = e;
401
+ show(t, e, i) {
402
+ this.triggerPos = t;
330
403
  const l = {
331
- top: `${t.bottom - o.top + 10}px`,
332
- left: `${t.left - o.left}px`
404
+ top: `${e.bottom - i.top + 10}px`,
405
+ left: `${e.left - i.left}px`
333
406
  };
334
- this.callbacks.onShow(e, l);
407
+ this.callbacks.onShow(t, l);
335
408
  }
336
409
  hide() {
337
410
  this.callbacks.onHide();
@@ -340,37 +413,177 @@ class J {
340
413
  return this.triggerPos;
341
414
  }
342
415
  }
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 };
416
+ class ht {
417
+ constructor(t) {
418
+ r(this, "view");
419
+ r(this, "allBlocks", /* @__PURE__ */ new Map());
420
+ r(this, "options");
421
+ this.options = t;
422
+ const e = Y(t.initialDoc), i = [
423
+ ...t.initialBlocks || [],
424
+ ...e
425
+ ];
426
+ t.initialBlocks && t.initialBlocks.forEach((n) => {
427
+ "type" in n.block || this.allBlocks.set(n.block.id, n.block);
428
+ });
350
429
  const l = {
351
- top: `${t.bottom - o.top + 10}px`,
352
- left: `${t.left - o.left}px`
430
+ updateBlockText: (n, c) => {
431
+ const a = this.allBlocks.get(n);
432
+ a && (a.presetText = c, this.allBlocks.set(n, a), this.options.onBlockUpdated && this.options.onBlockUpdated(n, c));
433
+ },
434
+ openPopup: (n, c) => {
435
+ this.options.onOpenPopup(n, c);
436
+ },
437
+ deleteBlock: (n) => {
438
+ this.allBlocks.delete(n), this.options.onBlockDeleted && this.options.onBlockDeleted(n);
439
+ }
440
+ }, s = ot(t.initialDoc, l, i);
441
+ this.view = new u({
442
+ state: s.update({
443
+ effects: k.appendConfig.of([
444
+ ...J({ onTriggerPluginPopup: (n) => this.options.onTriggerPluginPopup(n) }),
445
+ ...V({ onTriggerAIDialog: (n) => this.options.onTriggerAIDialog(n) })
446
+ ])
447
+ }).state,
448
+ parent: t.parent
449
+ });
450
+ }
451
+ addBlock() {
452
+ const t = {
453
+ id: Math.random().toString(36).slice(2, 11),
454
+ placeholder: "请输入编辑块内容为空时的提示文案",
455
+ presetText: ""
353
456
  };
354
- this.callbacks.onShow(this.editingBlock, l);
457
+ this.allBlocks.set(t.id, t);
458
+ const { from: e, to: i } = this.view.state.selection.main;
459
+ return this.view.dispatch({
460
+ changes: { from: e, to: i, insert: " " },
461
+ effects: C.of(t),
462
+ selection: { anchor: e + 1 }
463
+ }), this.view.focus(), t;
355
464
  }
356
- hide() {
357
- this.callbacks.onHide();
465
+ addPluginBlock(t, e) {
466
+ return this.view.dispatch({
467
+ changes: { from: t, to: t + 1, insert: " " },
468
+ effects: M.of({ pos: t, block: e }),
469
+ selection: { anchor: t + 1 }
470
+ }), this.view.focus(), e;
471
+ }
472
+ syncBlock(t) {
473
+ this.allBlocks.set(t.id, { ...t }), this.view.dispatch({
474
+ effects: A.of(t)
475
+ });
476
+ }
477
+ getBlock(t) {
478
+ return this.allBlocks.get(t);
479
+ }
480
+ coordsAtPos(t) {
481
+ return this.view.coordsAtPos(t);
482
+ }
483
+ getData() {
484
+ return it(this.view);
485
+ }
486
+ destroy() {
487
+ this.view.destroy();
358
488
  }
359
- updateEditingBlock(e) {
360
- this.editingBlock = { ...this.editingBlock, ...e };
489
+ }
490
+ const Z = (o, t) => {
491
+ const { from: e, empty: i } = o.state.selection.main;
492
+ if (!i) return !1;
493
+ const l = e;
494
+ if (l === 0) return !1;
495
+ let s = null, n = null, c = 1;
496
+ const a = (h) => {
497
+ h && h.between(l - 1, l, (m, p, b) => {
498
+ const f = b.spec.widget;
499
+ if (f && f.block && f.block.id && m < l && p >= l)
500
+ return s = f.block.id, n = m, c = p - m, !1;
501
+ });
502
+ };
503
+ return a(o.state.field(v, !1)), s || a(o.state.field(S, !1)), s && n !== null ? (t.deleteBlock(s), o.dispatch({
504
+ changes: { from: n, to: n + c },
505
+ selection: { anchor: n }
506
+ }), !0) : !1;
507
+ }, tt = u.theme({
508
+ "&": { height: "100%", outline: "none", position: "relative" },
509
+ ".cm-content": { padding: "20px", fontSize: "16px" },
510
+ ".cm-line": { padding: "4px 0" },
511
+ ".cm-header-1": { fontSize: "1.5em", color: "#008c99", fontWeight: "bold" },
512
+ ".cm-bold": { fontWeight: "bold" }
513
+ }), T = d.mark({ class: "cm-bold" });
514
+ function P(o) {
515
+ const t = [];
516
+ for (let e = 1; e <= o.lines; e++) {
517
+ const i = o.line(e), l = i.text;
518
+ /^#+\s+/.test(l) && t.push(T.range(i.from, i.to));
519
+ const s = /\*\*(.*?)\*\*/g;
520
+ let n;
521
+ for (; (n = s.exec(l)) !== null; )
522
+ t.push(T.range(i.from + n.index, i.from + n.index + n[0].length));
361
523
  }
524
+ return d.set(t.sort((e, i) => e.from - i.from), !0);
525
+ }
526
+ const et = y.define({
527
+ create(o) {
528
+ return P(o.doc);
529
+ },
530
+ update(o, t) {
531
+ return t.docChanged ? P(t.state.doc) : o.map(t.changes);
532
+ },
533
+ provide: (o) => u.decorations.from(o)
534
+ });
535
+ function ot(o, t, e = []) {
536
+ const i = e.filter((c) => !("type" in c.block && "name" in c.block)), l = e.filter((c) => "type" in c.block && "name" in c.block), s = [
537
+ W(),
538
+ _.of([
539
+ {
540
+ key: "Backspace",
541
+ run: (c) => Z(c, t)
542
+ },
543
+ ...N,
544
+ ...z
545
+ ]),
546
+ G(),
547
+ ...O({ callbacks: t, initialBlocks: i }),
548
+ ...Q({ initialBlocks: l }),
549
+ et,
550
+ tt
551
+ ];
552
+ return R.create({
553
+ doc: o,
554
+ extensions: s
555
+ });
556
+ }
557
+ function it(o) {
558
+ var l;
559
+ const t = o.state.doc.toString(), e = j(o), i = X(o);
560
+ return {
561
+ content: t,
562
+ editorBlocks: e,
563
+ pluginBlocks: i,
564
+ html: ((l = o.dom.querySelector(".cm-content")) == null ? void 0 : l.innerHTML) || ""
565
+ };
362
566
  }
363
567
  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
568
+ at as AIDialogPlugin,
569
+ ht as CustomEditor,
570
+ rt as EditBlockPlugin,
571
+ dt as LibraryBlockPlugin,
572
+ C as addBlockEffect,
573
+ M as addPluginBlockEffect,
574
+ V as aiDialogExtensions,
575
+ ot as createEditorState,
576
+ O as editBlockExtensions,
577
+ v as editBlockField,
578
+ H as editBlockTheme,
579
+ tt as editorTheme,
580
+ j as getEditorBlocks,
581
+ it as getEditorData,
582
+ X as getPluginBlocks,
583
+ et as markdownStyleField,
584
+ Y as parseTemplateVariables,
585
+ Q as pluginBlockExtensions,
586
+ S as pluginBlockField,
587
+ J as pluginPopupTriggerExtensions,
588
+ A as updateBlockEffect
376
589
  };
@@ -1,5 +1,5 @@
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+人解决旅行难题,被旅行者亲切称为"旅行百事通"。
1
+ (function(c,d){typeof exports=="object"&&typeof module<"u"?d(exports,require("@codemirror/state"),require("@codemirror/view"),require("@codemirror/commands")):typeof define=="function"&&define.amd?define(["exports","@codemirror/state","@codemirror/view","@codemirror/commands"],d):(c=typeof globalThis<"u"?globalThis:c||self,d(c.AgentArtsEditor={},c.CMState,c.CMView,c.CMCommands))})(this,function(c,d,r,w){"use strict";var X=Object.defineProperty;var Y=(c,d,r)=>d in c?X(c,d,{enumerable:!0,configurable:!0,writable:!0,value:r}):c[d]=r;var h=(c,d,r)=>Y(c,typeof d!="symbol"?d+"":d,r);const y=d.StateEffect.define(),E=d.StateEffect.define();class g extends r.WidgetType{constructor(e,i){super(),this.block=e,this.callbacks=i}toDOM(e){const i=document.createElement("span");i.className="cm-inline-block",i.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 l=s=>{const n=document.createElement("span");n.style.visibility="hidden",n.style.position="absolute",n.style.whiteSpace="pre",n.style.font="inherit",n.textContent=s||t.placeholder,document.body.appendChild(n);const a=n.offsetWidth;return document.body.removeChild(n),a+10};return t.style.width=`${l(t.value)}px`,t.oninput=s=>{const n=s.target.value;t.style.width=`${l(n)}px`,this.callbacks.updateBlockText(this.block.id,n)},t.onfocus=()=>{const s=i.getBoundingClientRect();this.callbacks.openPopup(this.block.id,s)},t.onmousedown=s=>{s.stopPropagation()},t.onclick=s=>{s.stopPropagation();const n=i.getBoundingClientRect();this.callbacks.openPopup(this.block.id,n)},t.onkeydown=s=>{if(s.key==="Backspace"&&t.value===""){s.preventDefault();const n=e.posAtDOM(i);this.callbacks.deleteBlock(this.block.id),e.dispatch({changes:{from:n,to:n+1},selection:{anchor:n}})}},i.appendChild(t),i}ignoreEvent(){return!0}}const x=d.Facet.define({combine:o=>o[0]}),D=d.Facet.define({combine:o=>o.length?o[0]:[]}),b=d.StateField.define({create(o){const e=o.facet(x),i=o.facet(D);if(!i||i.length===0)return r.Decoration.none;const t=i.slice().sort((l,s)=>l.pos-s.pos).map(({pos:l,len:s,block:n})=>{const a=new g(n,e);return r.Decoration.replace({widget:a}).range(l,l+(s||1))});return r.Decoration.set(t,!0)},update(o,e){const i=e.state.facet(x);o=o.map(e.changes);for(const t of e.effects)if(t.is(y)){const l=e.state.selection.main.head-1,s=r.Decoration.replace({widget:new g(t.value,i)}).range(l,l+1);o=o.update({add:[s]})}else if(t.is(E)){const l=t.value;let s=null;o.between(0,e.state.doc.length,(n,a,u)=>{const f=u.spec.widget;f instanceof g&&f.block.id===l.id&&(s=n)}),s!==null&&(o=o.update({filter:(n,a,u)=>{const f=u.spec.widget;return!(f instanceof g&&f.block.id===l.id)},add:[r.Decoration.replace({widget:new g(l,i)}).range(s,s+1)]}))}return o},provide:o=>r.EditorView.decorations.from(o)}),C=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 A(o){return[x.of(o.callbacks),D.of(o.initialBlocks||[]),b,C]}function F(o){const e=[],i=o.state.field(b,!1);return i&&i.between(0,o.state.doc.length,(t,l,s)=>{const n=s.spec.widget;n instanceof g&&e.push({pos:t,len:l-t,block:n.block})}),e}class j{constructor(e){h(this,"editingBlock",{id:"",placeholder:"",presetText:""});this.callbacks=e}show(e,i,t){this.editingBlock={...e};const l={top:`${i.bottom-t.top+10}px`,left:`${i.left-t.left}px`};this.callbacks.onShow(this.editingBlock,l)}hide(){this.callbacks.onHide()}updateEditingBlock(e){this.editingBlock={...this.editingBlock,...e}}}class q{constructor(e){h(this,"isGenerating",!1);h(this,"aiStreamTimer",null);h(this,"currentResponse","");this.callbacks=e}show(e,i,t){const l={top:`${i.bottom-t.top+10}px`,left:`${i.left-t.left}px`};this.callbacks.onShow(e,l)}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 i=`你是一个资深旅游向导,积累了丰富的在地经验,擅长结合用户需求定制专属旅行方案,曾帮助1000+人解决旅行难题,被旅行者亲切称为"旅行百事通"。
2
2
 
3
3
  ## 核心性格与风格
4
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"})});
5
+ - **语言风格**:口语化且富有感染力,常用"宝藏地""小众玩法"等旅行圈`;let t=0;this.aiStreamTimer=setInterval(()=>{this.callbacks.onLoading(!1),t<i.length?(this.currentResponse+=i[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()}}function M(o){return[H(o.onTriggerAIDialog),K(o.onTriggerAIDialog),O]}function H(o){return r.EditorView.updateListener.of(e=>{e.docChanged&&e.changes.iterChanges((i,t,l,s,n)=>{if(n.length!==1)return;n.sliceString(0)==="/"&&o(i)})})}const O=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 K(o){return r.ViewPlugin.fromClass(class{constructor(e){h(this,"dom");h(this,"button");h(this,"lastFrom",-1);h(this,"lastTo",-1);h(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 i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("width","16"),i.setAttribute("height","16"),i.setAttribute("viewBox","0 0 24 24"),i.setAttribute("fill","none"),i.setAttribute("stroke","#111827"),i.setAttribute("stroke-width","2"),i.setAttribute("stroke-linecap","round"),i.setAttribute("stroke-linejoin","round"),i.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(i),this.dom.appendChild(this.button),this.view.dom.appendChild(this.dom),this.dom.addEventListener("mousedown",t=>{t.preventDefault(),t.stopPropagation()}),this.button.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const{from:l,empty:s}=this.view.state.selection.main;s||(o(l),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:i,to:t,empty:l}=this.view.state.selection.main;if(l||!this.view.hasFocus){this.hide();return}!e&&i===this.lastFrom&&t===this.lastTo&&this.dom.style.display!=="none"||(this.lastFrom=i,this.lastTo=t,!this.measureScheduled&&(this.measureScheduled=!0,this.view.requestMeasure({read:s=>{const n=s.coordsAtPos(i);if(!n)return null;const a=s.dom.getBoundingClientRect();return{coords:n,editorRect:a}},write:s=>{this.measureScheduled=!1;const{empty:n}=this.view.state.selection.main;if(n||!this.view.hasFocus){this.hide();return}if(!s){this.hide();return}const{coords:a,editorRect:u}=s,f=32,k=32,p=6,P=Math.min(Math.max(a.left-u.left,p),Math.max(p,u.width-f-p)),m=Math.max(a.top-u.top-k-10,p);this.dom.style.left=`${P}px`,this.dom.style.top=`${m}px`,this.show()}})))}})}const S=d.StateEffect.define();class T 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 i=document.createElement("i");i.className=this.block.type==="plugin"?"icon-plugin":"icon-workflow",e.appendChild(i);const t=document.createTextNode(this.block.name);return e.appendChild(t),e}ignoreEvent(){return!0}}const v=d.Facet.define({combine:o=>o.length?o[0]:[]}),B=d.StateField.define({create(o){const e=o.facet(v);if(!e||e.length===0)return r.Decoration.none;const i=e.slice().sort((t,l)=>t.pos-l.pos).map(({pos:t,len:l,block:s})=>r.Decoration.replace({widget:new T(s)}).range(t,t+(l||1)));return r.Decoration.set(i,!0)},update(o,e){o=o.map(e.changes);for(const i of e.effects)if(i.is(S)){const{pos:t,block:l}=i.value,s=e.changes.mapPos(t),n=r.Decoration.replace({widget:new T(l)}).range(s,s+1);o=o.update({add:[n]})}return o},provide:o=>r.EditorView.decorations.from(o)});function L(o){return[v.of(o.initialBlocks||[]),B]}function I(o){return[r.EditorView.updateListener.of(e=>{e.docChanged&&e.changes.iterChanges((i,t,l,s,n)=>{if(n.length!==1)return;n.sliceString(0)==="{"&&o.onTriggerPluginPopup(i)})})]}function $(o){const e=[],i=o.state.field(B,!1);return i&&i.between(0,o.state.doc.length,(t,l,s)=>{const n=s.spec.widget;n instanceof T&&e.push({pos:t,len:l-t,block:n.block})}),e}function R(o){const e=[],i=/\{\{(.+?)\}\}/g;let t;for(;(t=i.exec(o))!==null;)e.push({pos:t.index,len:t[0].length,block:{id:`var-${t[1]}-${t.index}`,name:t[1],type:"plugin"}});return e}class U{constructor(e){h(this,"plugins",[{id:"plugin-1",name:"LinkReaderPlugin",type:"plugin"}]);h(this,"workflows",[{id:"workflow-1",name:"condition_1_872",type:"workflow"}]);h(this,"triggerPos",0);this.callbacks=e}show(e,i,t){this.triggerPos=e;const l={top:`${i.bottom-t.top+10}px`,left:`${i.left-t.left}px`};this.callbacks.onShow(e,l)}hide(){this.callbacks.onHide()}getTriggerPos(){return this.triggerPos}}class Q{constructor(e){h(this,"view");h(this,"allBlocks",new Map);h(this,"options");this.options=e;const i=R(e.initialDoc),t=[...e.initialBlocks||[],...i];e.initialBlocks&&e.initialBlocks.forEach(n=>{"type"in n.block||this.allBlocks.set(n.block.id,n.block)});const l={updateBlockText:(n,a)=>{const u=this.allBlocks.get(n);u&&(u.presetText=a,this.allBlocks.set(n,u),this.options.onBlockUpdated&&this.options.onBlockUpdated(n,a))},openPopup:(n,a)=>{this.options.onOpenPopup(n,a)},deleteBlock:n=>{this.allBlocks.delete(n),this.options.onBlockDeleted&&this.options.onBlockDeleted(n)}},s=N(e.initialDoc,l,t);this.view=new r.EditorView({state:s.update({effects:d.StateEffect.appendConfig.of([...I({onTriggerPluginPopup:n=>this.options.onTriggerPluginPopup(n)}),...M({onTriggerAIDialog:n=>this.options.onTriggerAIDialog(n)})])}).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:i,to:t}=this.view.state.selection.main;return this.view.dispatch({changes:{from:i,to:t,insert:" "},effects:y.of(e),selection:{anchor:i+1}}),this.view.focus(),e}addPluginBlock(e,i){return this.view.dispatch({changes:{from:e,to:e+1,insert:" "},effects:S.of({pos:e,block:i}),selection:{anchor:e+1}}),this.view.focus(),i}syncBlock(e){this.allBlocks.set(e.id,{...e}),this.view.dispatch({effects:E.of(e)})}getBlock(e){return this.allBlocks.get(e)}coordsAtPos(e){return this.view.coordsAtPos(e)}getData(){return z(this.view)}destroy(){this.view.destroy()}}const J=(o,e)=>{const{from:i,empty:t}=o.state.selection.main;if(!t)return!1;const l=i;if(l===0)return!1;let s=null,n=null,a=1;const u=f=>{f&&f.between(l-1,l,(k,p,P)=>{const m=P.spec.widget;if(m&&m.block&&m.block.id&&k<l&&p>=l)return s=m.block.id,n=k,a=p-k,!1})};return u(o.state.field(b,!1)),s||u(o.state.field(B,!1)),s&&n!==null?(e.deleteBlock(s),o.dispatch({changes:{from:n,to:n+a},selection:{anchor:n}}),!0):!1},V=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"}}),_=r.Decoration.mark({class:"cm-bold"});function G(o){const e=[];for(let i=1;i<=o.lines;i++){const t=o.line(i),l=t.text;/^#+\s+/.test(l)&&e.push(_.range(t.from,t.to));const s=/\*\*(.*?)\*\*/g;let n;for(;(n=s.exec(l))!==null;)e.push(_.range(t.from+n.index,t.from+n.index+n[0].length))}return r.Decoration.set(e.sort((i,t)=>i.from-t.from),!0)}const W=d.StateField.define({create(o){return G(o.doc)},update(o,e){return e.docChanged?G(e.state.doc):o.map(e.changes)},provide:o=>r.EditorView.decorations.from(o)});function N(o,e,i=[]){const t=i.filter(a=>!("type"in a.block&&"name"in a.block)),l=i.filter(a=>"type"in a.block&&"name"in a.block),s=[w.history(),r.keymap.of([{key:"Backspace",run:a=>J(a,e)},...w.defaultKeymap,...w.historyKeymap]),r.drawSelection(),...A({callbacks:e,initialBlocks:t}),...L({initialBlocks:l}),W,V];return d.EditorState.create({doc:o,extensions:s})}function z(o){var l;const e=o.state.doc.toString(),i=F(o),t=$(o);return{content:e,editorBlocks:i,pluginBlocks:t,html:((l=o.dom.querySelector(".cm-content"))==null?void 0:l.innerHTML)||""}}c.AIDialogPlugin=q,c.CustomEditor=Q,c.EditBlockPlugin=j,c.LibraryBlockPlugin=U,c.addBlockEffect=y,c.addPluginBlockEffect=S,c.aiDialogExtensions=M,c.createEditorState=N,c.editBlockExtensions=A,c.editBlockField=b,c.editBlockTheme=C,c.editorTheme=V,c.getEditorBlocks=F,c.getEditorData=z,c.getPluginBlocks=$,c.markdownStyleField=W,c.parseTemplateVariables=R,c.pluginBlockExtensions=L,c.pluginBlockField=B,c.pluginPopupTriggerExtensions=I,c.updateBlockEffect=E,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});
package/dist/index.d.ts CHANGED
@@ -13,6 +13,10 @@ pos: number;
13
13
  block: PluginBlock;
14
14
  }>;
15
15
 
16
+ export declare function aiDialogExtensions(options: {
17
+ onTriggerAIDialog: (pos: number) => void;
18
+ }): Extension[];
19
+
16
20
  export declare class AIDialogPlugin {
17
21
  private callbacks;
18
22
  private isGenerating;
@@ -43,21 +47,21 @@ export declare interface AIResponseCallbacks {
43
47
  onHide: () => void;
44
48
  }
45
49
 
46
- export declare const blockField: StateField<DecorationSet>;
47
-
48
50
  export declare interface CodeMirrorCallbacks {
49
51
  updateBlockText: (id: string, text: string) => void;
50
52
  openPopup: (id: string, rect: DOMRect) => void;
51
53
  deleteBlock: (id: string) => void;
52
54
  }
53
55
 
56
+ /**
57
+ * 创建编辑器状态
58
+ */
54
59
  export declare function createEditorState(initialDoc: string, callbacks: CodeMirrorCallbacks, initialBlocks?: {
55
60
  pos: number;
56
- block: EditorBlock;
61
+ len?: number;
62
+ block: EditorBlock | PluginBlock;
57
63
  }[]): EditorState;
58
64
 
59
- export declare function createEditorView(parent: HTMLElement, state: EditorState): EditorView;
60
-
61
65
  export declare class CustomEditor {
62
66
  view: EditorView;
63
67
  allBlocks: Map<string, EditorBlock>;
@@ -69,10 +73,17 @@ export declare class CustomEditor {
69
73
  getBlock(id: string): EditorBlock | undefined;
70
74
  coordsAtPos(pos: number): Rect | null;
71
75
  getData(): {
72
- json: {
73
- content: string;
74
- blocks: EditorBlock[];
75
- };
76
+ content: string;
77
+ editorBlocks: {
78
+ pos: number;
79
+ len?: number;
80
+ block: EditorBlock;
81
+ }[];
82
+ pluginBlocks: {
83
+ pos: number;
84
+ len?: number;
85
+ block: PluginBlock;
86
+ }[];
76
87
  html: string;
77
88
  };
78
89
  destroy(): void;
@@ -83,7 +94,8 @@ export declare interface CustomEditorOptions {
83
94
  initialDoc: string;
84
95
  initialBlocks?: {
85
96
  pos: number;
86
- block: EditorBlock;
97
+ len?: number;
98
+ block: EditorBlock | PluginBlock;
87
99
  }[];
88
100
  onOpenPopup: (id: string, rect: DOMRect) => void;
89
101
  onTriggerPluginPopup: (pos: number) => void;
@@ -100,6 +112,17 @@ export declare interface EditBlockCallbacks {
100
112
  onHide: () => void;
101
113
  }
102
114
 
115
+ export declare function editBlockExtensions(options: {
116
+ callbacks: CodeMirrorCallbacks;
117
+ initialBlocks?: {
118
+ pos: number;
119
+ len?: number;
120
+ block: EditorBlock;
121
+ }[];
122
+ }): Extension[];
123
+
124
+ export declare const editBlockField: StateField<DecorationSet>;
125
+
103
126
  export declare class EditBlockPlugin {
104
127
  private callbacks;
105
128
  editingBlock: EditorBlock;
@@ -109,6 +132,8 @@ export declare class EditBlockPlugin {
109
132
  updateEditingBlock(block: Partial<EditorBlock>): void;
110
133
  }
111
134
 
135
+ export declare const editBlockTheme: Extension;
136
+
112
137
  export declare interface EditorBlock {
113
138
  id: string;
114
139
  placeholder: string;
@@ -117,14 +142,36 @@ export declare interface EditorBlock {
117
142
 
118
143
  export declare const editorTheme: Extension;
119
144
 
120
- export declare function getEditorData(view: EditorView, blocks: Map<string, EditorBlock>): {
121
- json: {
122
- content: string;
123
- blocks: EditorBlock[];
124
- };
145
+ export declare function getEditorBlocks(view: EditorView): {
146
+ pos: number;
147
+ len?: number;
148
+ block: EditorBlock;
149
+ }[];
150
+
151
+ /**
152
+ * 获取编辑器数据
153
+ */
154
+ export declare function getEditorData(view: EditorView): {
155
+ content: string;
156
+ editorBlocks: {
157
+ pos: number;
158
+ len?: number;
159
+ block: EditorBlock;
160
+ }[];
161
+ pluginBlocks: {
162
+ pos: number;
163
+ len?: number;
164
+ block: PluginBlock;
165
+ }[];
125
166
  html: string;
126
167
  };
127
168
 
169
+ export declare function getPluginBlocks(view: EditorView): {
170
+ pos: number;
171
+ len?: number;
172
+ block: PluginBlock;
173
+ }[];
174
+
128
175
  export declare interface LibraryBlockCallbacks {
129
176
  onShow: (pos: number, style: {
130
177
  top: string;
@@ -155,12 +202,34 @@ export declare class LibraryBlockPlugin {
155
202
  getTriggerPos(): number;
156
203
  }
157
204
 
205
+ export declare const markdownStyleField: StateField<DecorationSet>;
206
+
207
+ export declare function parseTemplateVariables(doc: string): {
208
+ pos: number;
209
+ len: number;
210
+ block: PluginBlock;
211
+ }[];
212
+
158
213
  export declare interface PluginBlock {
159
214
  id: string;
160
215
  name: string;
161
216
  type: 'plugin' | 'workflow';
162
217
  }
163
218
 
219
+ export declare function pluginBlockExtensions(options: {
220
+ initialBlocks?: {
221
+ pos: number;
222
+ len?: number;
223
+ block: PluginBlock;
224
+ }[];
225
+ }): Extension[];
226
+
227
+ export declare const pluginBlockField: StateField<DecorationSet>;
228
+
229
+ export declare function pluginPopupTriggerExtensions(options: {
230
+ onTriggerPluginPopup: (pos: number) => void;
231
+ }): Extension[];
232
+
164
233
  export declare const updateBlockEffect: StateEffectType<EditorBlock>;
165
234
 
166
235
  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.0",
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
  },