ts-glitter 13.8.54 → 13.8.55

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/lowcode/Entry.js CHANGED
@@ -64,7 +64,7 @@ export class Entry {
64
64
  }
65
65
  window.renderClock = (_a = window.renderClock) !== null && _a !== void 0 ? _a : clockF();
66
66
  console.log(`Entry-time:`, window.renderClock.stop());
67
- glitter.share.editerVersion = 'V_13.8.54';
67
+ glitter.share.editerVersion = 'V_13.8.55';
68
68
  glitter.share.start = new Date();
69
69
  const vm = {
70
70
  appConfig: [],
package/lowcode/Entry.ts CHANGED
@@ -64,7 +64,7 @@ export class Entry {
64
64
  }
65
65
  (window as any).renderClock = (window as any).renderClock ?? clockF();
66
66
  console.log(`Entry-time:`, (window as any).renderClock.stop());
67
- glitter.share.editerVersion = 'V_13.8.54';
67
+ glitter.share.editerVersion = 'V_13.8.55';
68
68
  glitter.share.start = new Date();
69
69
  const vm: {
70
70
  appConfig: any;
@@ -229,48 +229,53 @@ export class AiMessage {
229
229
  (AiMessage.vm.select_bt === 'page_editor') ? (() => {
230
230
  const html = String.raw;
231
231
  let message = '';
232
- return ` <div class="p-2">
232
+ return ` <div class="p-5">
233
233
  ${[
234
234
  html `
235
- <lottie-player src="lottie/ai.json" class="mx-auto my-n4" speed="1"
236
- style="max-width: 100%;width: 250px;height:300px;" loop
237
- autoplay></lottie-player>`,
238
- EditorElem.editeText({
235
+ <lottie-player src="lottie/ai.json" class="mx-auto my-n4" speed="1"
236
+ style="max-width: 100%;width: 250px;height:250px;" loop
237
+ autoplay></lottie-player>`,
238
+ `<div class="w-100 d-flex align-items-center justify-content-center my-3">${BgWidget.grayNote('點擊想要調整的元件之後,在輸入 AI 語句進行調整', `font-weight: 500;`)}</div>`,
239
+ html `
240
+ <div class="w-100" onclick="${gvc.event(() => {
241
+ if (!gvc.glitter.share.editorViewModel.selectItem) {
242
+ const dialog = new ShareDialog(gvc.glitter);
243
+ dialog.errorMessage({ text: '請先點擊要編輯的元件' });
244
+ }
245
+ })}">
246
+ ${EditorElem.editeText({
239
247
  gvc: gvc,
240
248
  title: '',
241
249
  default: '',
242
- placeHolder: `範例:字體大小20px,距離左邊20px,背景顏色黃色,字體顏色藍色,標題為歡迎來到SHOPNEX開店平台.
243
- `,
250
+ placeHolder: `字體大小20px,距離左邊20px,背景顏色黃色,字體顏色藍色,標題為歡迎來到SHOPNEX開店平台.`,
244
251
  callback: (text) => {
245
252
  message = text;
246
253
  },
247
- min_height: 300
248
- }),
254
+ min_height: 100
255
+ })}
256
+ </div>`,
249
257
  `<div class="w-100 d-flex align-items-center justify-content-end">
250
258
  ${BgWidget.save(gvc.event(() => {
251
259
  const dialog = new ShareDialog(gvc.glitter);
260
+ if (!message) {
261
+ dialog.errorMessage({ text: '請輸入描述語句' });
262
+ return;
263
+ }
252
264
  dialog.dataLoading({ visible: true });
253
- AiChat.generateHtml({
254
- app_name: window.appName,
255
- text: message
256
- }).then((res) => {
257
- if (res.result && res.response.data.usage === 0) {
258
- dialog.dataLoading({ visible: false });
259
- dialog.errorMessage({ text: `很抱歉你的AI代幣不足,請先前往加值` });
260
- }
261
- else if (res.result && (!res.response.data.obj.result)) {
265
+ gvc.glitter.getModule(new URL('./editor/ai-editor.js', gvc.glitter.root_path).href, (AiEditor) => {
266
+ AiEditor.editView(message, gvc.glitter.share.editorViewModel.selectItem, (result) => {
262
267
  dialog.dataLoading({ visible: false });
263
- dialog.errorMessage({ text: `AI無法理解你的需求,請給出具體一點的描述` });
264
- }
265
- else if (!res.result) {
266
- dialog.dataLoading({ visible: false });
267
- dialog.errorMessage({ text: `發生錯誤` });
268
- }
269
- else {
270
- dialog.successMessage({ text: `AI生成完畢,使用了『${res.response.data.usage}』點 AI Points.` });
271
- }
268
+ if (result) {
269
+ dialog.successMessage({ text: `已為你調整元件『${result}』` });
270
+ gvc.glitter.share.editorViewModel.selectItem.refreshComponent();
271
+ gvc.glitter.closeDrawer();
272
+ }
273
+ else {
274
+ dialog.errorMessage({ text: 'AI無法理解你的意思,請輸入更確切的需求' });
275
+ }
276
+ });
272
277
  });
273
- }), "調整元素")}
278
+ }), "調整元素", "w-100 mt-3 py-2")}
274
279
  </div>`
275
280
  ].join('<div class="my-2"></div>')}
276
281
  </div>`;
@@ -6,6 +6,7 @@ import {AiChat} from '../glitter-base/route/ai-chat.js';
6
6
  import {ShareDialog} from '../glitterBundle/dialog/ShareDialog.js';
7
7
  import {AiPointsApi} from "../glitter-base/route/ai-points-api.js";
8
8
  import {EditorElem} from "../glitterBundle/plugins/editor-elem.js";
9
+ import {AiEditor} from "../editor/ai-editor.js";
9
10
 
10
11
  export class AiMessage {
11
12
  public static config: any = {
@@ -74,17 +75,17 @@ export class AiMessage {
74
75
  })}"
75
76
  >
76
77
  ${(() => {
77
- return AiMessage.detail({
78
- gvc: gvc,
79
- user_id: 'manager',
80
- containerHeight: ($('body').height() as any) + 10 + 'px',
81
- document: document,
82
- goBack: () => {
83
- },
84
- close: () => {
85
- gvc.glitter.closeDrawer()
86
- },
87
- })
78
+ return AiMessage.detail({
79
+ gvc: gvc,
80
+ user_id: 'manager',
81
+ containerHeight: ($('body').height() as any) + 10 + 'px',
82
+ document: document,
83
+ goBack: () => {
84
+ },
85
+ close: () => {
86
+ gvc.glitter.closeDrawer()
87
+ },
88
+ })
88
89
  })()}
89
90
  </div>
90
91
  </div>`, () => {
@@ -263,55 +264,82 @@ export class AiMessage {
263
264
  },
264
265
  };
265
266
  }),
266
- (AiMessage.vm.select_bt==='page_editor') ? (()=>{
267
+ (AiMessage.vm.select_bt === 'page_editor') ? (() => {
267
268
  const html = String.raw
268
269
  let message = ''
269
- return ` <div class="p-2">
270
+ return ` <div class="p-5">
270
271
  ${[
271
272
  html`
272
- <lottie-player src="lottie/ai.json" class="mx-auto my-n4" speed="1"
273
- style="max-width: 100%;width: 250px;height:300px;" loop
274
- autoplay></lottie-player>`,
275
- EditorElem.editeText({
276
- gvc: gvc,
277
- title: '',
278
- default: '',
279
- placeHolder: `範例:字體大小20px,距離左邊20px,背景顏色黃色,字體顏色藍色,標題為歡迎來到SHOPNEX開店平台.
280
- `,
281
- callback: (text) => {
282
- message = text
283
-
284
- },
285
- min_height: 300
286
- }),
273
+ <lottie-player src="lottie/ai.json" class="mx-auto my-n4" speed="1"
274
+ style="max-width: 100%;width: 250px;height:250px;" loop
275
+ autoplay></lottie-player>`,
276
+ `<div class="w-100 d-flex align-items-center justify-content-center my-3">${BgWidget.grayNote('點擊想要調整的元件之後,在輸入 AI 語句進行調整', `font-weight: 500;`)}</div>`,
277
+ html`
278
+ <div class="w-100" onclick="${gvc.event(() => {
279
+ if (!gvc.glitter.share.editorViewModel.selectItem) {
280
+ const dialog = new ShareDialog(gvc.glitter)
281
+ dialog.errorMessage({text: '請先點擊要編輯的元件'})
282
+ }
283
+ })}">
284
+ ${EditorElem.editeText({
285
+ gvc: gvc,
286
+ title: '',
287
+ default: '',
288
+ placeHolder: `字體大小20px,距離左邊20px,背景顏色黃色,字體顏色藍色,標題為歡迎來到SHOPNEX開店平台.`,
289
+ callback: (text) => {
290
+ message = text;
291
+ },
292
+ min_height: 100
293
+ })}
294
+ </div>`,
287
295
  `<div class="w-100 d-flex align-items-center justify-content-end">
288
296
  ${BgWidget.save(gvc.event(() => {
289
297
  const dialog = new ShareDialog(gvc.glitter)
298
+ if (!message) {
299
+ dialog.errorMessage({text: '請輸入描述語句'})
300
+ return
301
+ }
302
+
290
303
  dialog.dataLoading({visible: true})
291
- AiChat.generateHtml({
292
- app_name: (window as any).appName,
293
- text: message
294
- }).then((res) => {
295
- if (res.result && res.response.data.usage === 0) {
304
+ gvc.glitter.getModule(new URL('./editor/ai-editor.js', gvc.glitter.root_path).href, (AiEditor) => {
305
+ AiEditor.editView(message, gvc.glitter.share.editorViewModel.selectItem, (result:any) => {
296
306
  dialog.dataLoading({visible: false})
297
- dialog.errorMessage({text: `很抱歉你的AI代幣不足,請先前往加值`})
298
- } else if (res.result && (!res.response.data.obj.result)) {
299
- dialog.dataLoading({visible: false})
300
- dialog.errorMessage({text: `AI無法理解你的需求,請給出具體一點的描述`})
301
- } else if (!res.result) {
302
- dialog.dataLoading({visible: false})
303
- dialog.errorMessage({text: `發生錯誤`})
304
- } else {
307
+ if (result) {
308
+ dialog.successMessage({text: `已為你調整元件『${result}』`})
309
+ gvc.glitter.share.editorViewModel.selectItem.refreshComponent()
310
+ gvc.glitter.closeDrawer()
311
+ } else {
312
+ dialog.errorMessage({text: 'AI無法理解你的意思,請輸入更確切的需求'})
313
+ }
305
314
 
306
- dialog.successMessage({text: `AI生成完畢,使用了『${res.response.data.usage}』點 AI Points.`})
307
-
308
- }
315
+ })
309
316
  })
310
- }), "調整元素")}
317
+ // const dialog = new ShareDialog(gvc.glitter)
318
+ // dialog.dataLoading({visible: true})
319
+ // AiChat.generateHtml({
320
+ // app_name: (window as any).appName,
321
+ // text: message
322
+ // }).then((res) => {
323
+ // if (res.result && res.response.data.usage === 0) {
324
+ // dialog.dataLoading({visible: false})
325
+ // dialog.errorMessage({text: `很抱歉你的AI代幣不足,請先前往加值`})
326
+ // } else if (res.result && (!res.response.data.obj.result)) {
327
+ // dialog.dataLoading({visible: false})
328
+ // dialog.errorMessage({text: `AI無法理解你的需求,請給出具體一點的描述`})
329
+ // } else if (!res.result) {
330
+ // dialog.dataLoading({visible: false})
331
+ // dialog.errorMessage({text: `發生錯誤`})
332
+ // } else {
333
+ //
334
+ // dialog.successMessage({text: `AI生成完畢,使用了『${res.response.data.usage}』點 AI Points.`})
335
+ //
336
+ // }
337
+ // })
338
+ }), "調整元素", "w-100 mt-3 py-2")}
311
339
  </div>`
312
340
  ].join('<div class="my-2"></div>')}
313
341
  </div>`
314
- })():gvc.bindView(() => {
342
+ })() : gvc.bindView(() => {
315
343
  const viewId = gvc.glitter.getUUID();
316
344
  const messageID = gvc.glitter.getUUID();
317
345
  const vm: {
@@ -0,0 +1,379 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { Storage } from '../glitterBundle/helper/storage.js';
11
+ import { AiChat } from "../glitter-base/route/ai-chat.js";
12
+ export class AiEditor {
13
+ static editView(text, items, callback) {
14
+ return __awaiter(this, void 0, void 0, function* () {
15
+ const og_schema = yield AiEditor.getRequestConfig((items.type === 'component') ? items.data.tag : '', items);
16
+ AiChat.editorHtml({
17
+ text: text,
18
+ format: {
19
+ "name": "html_element_modification",
20
+ "strict": true,
21
+ "schema": (() => {
22
+ const schema = JSON.parse(JSON.stringify(og_schema));
23
+ schema.required.map((dd) => {
24
+ console.log(`schema.properties[dd]=>`, schema.properties[dd]);
25
+ schema.properties[dd].event = undefined;
26
+ });
27
+ return schema;
28
+ })()
29
+ }
30
+ }).then((dd) => {
31
+ var _a, _b;
32
+ if (!dd.result || !dd.response.result) {
33
+ callback(false);
34
+ }
35
+ else {
36
+ const obj = dd.response.data.obj;
37
+ const data = (() => {
38
+ if (Storage.view_type === 'mobile') {
39
+ return items.mobile_editable.find((dd) => {
40
+ return dd === '_container_margin';
41
+ }) ? items.mobile.data : items.data;
42
+ }
43
+ else {
44
+ return items.desktop_editable.find((dd) => {
45
+ return dd === '_container_margin';
46
+ }) ? items.desktop.data : items.data;
47
+ }
48
+ })();
49
+ for (const b of ['margin_left', 'margin_right', 'margin_top', 'margin_bottom']) {
50
+ data._padding = data._padding || {};
51
+ if (obj[b] && !obj[b].includes('none')) {
52
+ switch (b) {
53
+ case 'margin_left':
54
+ data._padding.left = obj[b].replace('px', '');
55
+ break;
56
+ case 'margin_right':
57
+ data._padding.right = obj[b].replace('px', '');
58
+ break;
59
+ case 'margin_top':
60
+ data._padding.top = obj[b].replace('px', '');
61
+ break;
62
+ case 'margin_bottom':
63
+ data._padding.bottom = obj[b].replace('px', '');
64
+ break;
65
+ }
66
+ }
67
+ console.log(`data._padding.==>`, data._padding);
68
+ }
69
+ if (obj.width && !obj.width.includes('none')) {
70
+ data._max_width = (_a = data._max_width) !== null && _a !== void 0 ? _a : '';
71
+ data._max_width = data._max_width.replace('px', '');
72
+ }
73
+ if (obj.height && !obj.height.includes('none')) {
74
+ data._max_height = (_b = data._max_height) !== null && _b !== void 0 ? _b : '';
75
+ data._max_height = data._max_height.replace('px', '');
76
+ }
77
+ if (obj.background && !obj.background.includes('none')) {
78
+ data._background_setting = { "type": "color", "value": `${obj.background}` };
79
+ }
80
+ Object.keys(obj).map((ch) => {
81
+ if (obj[ch] && !`${obj[ch]}`.includes('none') && og_schema.properties[ch].event) {
82
+ og_schema.properties[ch].event(ch, obj[ch]);
83
+ }
84
+ });
85
+ callback(obj.fix_what);
86
+ }
87
+ });
88
+ });
89
+ }
90
+ static getRequestConfig(label, items) {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ const schema = {
93
+ "type": "object",
94
+ "properties": {
95
+ "background": {
96
+ "type": "string",
97
+ "description": "背景顏色的色號,格式為HEX,未輸入則為none"
98
+ },
99
+ "margin_left": {
100
+ "type": "string",
101
+ "description": "左側間隔距離,未輸入則為none"
102
+ },
103
+ "margin_right": {
104
+ "type": "string",
105
+ "description": "右側間隔距離,未輸入則為none"
106
+ },
107
+ "margin_top": {
108
+ "type": "string",
109
+ "description": "上方間隔距離,未輸入則為none"
110
+ },
111
+ "margin_bottom": {
112
+ "type": "string",
113
+ "description": "下方間隔距離,未輸入則為none"
114
+ },
115
+ "result": {
116
+ "type": "boolean",
117
+ "description": "是否有成功執行"
118
+ },
119
+ "fix_what": {
120
+ "type": "string",
121
+ "description": "修改了哪些項目"
122
+ },
123
+ "width": {
124
+ "type": "string",
125
+ "description": "修改寬度,單位為px、%或vw,未輸入則為none"
126
+ },
127
+ "height": {
128
+ "type": "string",
129
+ "description": "修改高度,單位為px、%或vw,未輸入則為none"
130
+ }
131
+ },
132
+ "required": [
133
+ "margin_left",
134
+ "width",
135
+ "height",
136
+ "margin_right",
137
+ "margin_top",
138
+ "margin_bottom",
139
+ "result",
140
+ "background",
141
+ "fix_what"
142
+ ],
143
+ "additionalProperties": false
144
+ };
145
+ let formFormat = [];
146
+ if (label) {
147
+ formFormat = yield new Promise((resolve, reject) => {
148
+ window.glitterInitialHelper.getPageData({
149
+ tag: label,
150
+ appName: items.data.refer_app
151
+ }, (d2) => {
152
+ const pageData = d2.response.result[0];
153
+ console.log(`pageData==>`, pageData);
154
+ const page_config = pageData.page_config;
155
+ resolve(page_config.formFormat);
156
+ });
157
+ });
158
+ }
159
+ function changeValue(key, value) {
160
+ if (items[`${Storage.view_type}_editable`].find((d1) => {
161
+ return d1 === key;
162
+ })) {
163
+ items[Storage.view_type].data.refer_form_data[key] = value;
164
+ }
165
+ else {
166
+ items.data.refer_form_data[key] = value;
167
+ }
168
+ }
169
+ console.log(`formFormat==>`, formFormat);
170
+ switch (label) {
171
+ case 'basic-title':
172
+ case 'content':
173
+ (() => {
174
+ const b = [
175
+ {
176
+ key: 'title',
177
+ type: 'string',
178
+ description: '標題或內文,未輸入則為none',
179
+ event: (key, data) => {
180
+ changeValue(key, data);
181
+ }
182
+ },
183
+ {
184
+ key: "size_pc",
185
+ type: 'string',
186
+ description: '字體大小,範圍為0到100,未輸入則為none',
187
+ event: (key, data) => {
188
+ changeValue(key, data.replace('px', ''));
189
+ }
190
+ },
191
+ {
192
+ key: "weight",
193
+ type: 'string',
194
+ "enum": [
195
+ "100",
196
+ "200",
197
+ "300",
198
+ "400",
199
+ "500",
200
+ "600",
201
+ "700",
202
+ "none"
203
+ ],
204
+ description: '字體粗細度,未輸入則為none',
205
+ event: (key, data) => {
206
+ changeValue(key, data);
207
+ }
208
+ },
209
+ {
210
+ key: "letter_space",
211
+ type: 'string',
212
+ description: '文字間隔距離,未輸入則為none',
213
+ event: (key, data) => {
214
+ changeValue(key, data);
215
+ }
216
+ },
217
+ {
218
+ key: 'justify',
219
+ type: 'string',
220
+ "enum": [
221
+ "left",
222
+ "center",
223
+ "right",
224
+ "none"
225
+ ],
226
+ description: '元素位置,未輸入則為none',
227
+ event: (key, data) => {
228
+ changeValue(key, data);
229
+ }
230
+ },
231
+ {
232
+ key: "import_",
233
+ type: 'string',
234
+ "enum": [
235
+ "true",
236
+ "false",
237
+ "none"
238
+ ],
239
+ description: '是否為重點標題,未輸入則為none',
240
+ event: (key, data) => {
241
+ changeValue(key, data);
242
+ }
243
+ },
244
+ {
245
+ key: "auto_next",
246
+ type: 'string',
247
+ "enum": [
248
+ "true",
249
+ "false",
250
+ "none"
251
+ ],
252
+ description: '是否自動換行,未輸入則為none',
253
+ event: (key, data) => {
254
+ changeValue(key, data);
255
+ }
256
+ },
257
+ {
258
+ key: "color",
259
+ type: 'string',
260
+ description: '字體顏色的色號,格式為HEX,未輸入則為none',
261
+ event: (key, data) => {
262
+ changeValue(key, {
263
+ "id": "custom-color",
264
+ "title": data,
265
+ "content": "#000000",
266
+ "sec-title": "#000000",
267
+ "background": "#ffffff",
268
+ "sec-background": "#FFFFFF",
269
+ "solid-button-bg": "#000000",
270
+ "border-button-bg": "#000000",
271
+ "solid-button-text": "#ffffff",
272
+ "border-button-text": "#000000"
273
+ });
274
+ }
275
+ },
276
+ ];
277
+ b.map((d) => {
278
+ schema.required.push(d.key);
279
+ schema.properties[d.key] = {
280
+ type: d.type,
281
+ description: d.description,
282
+ enum: d.enum,
283
+ event: d.event
284
+ };
285
+ });
286
+ })();
287
+ break;
288
+ case 'sy00-btn':
289
+ (() => {
290
+ const theme = {
291
+ "id": "custom-theme",
292
+ "solid-button-bg": "#000000",
293
+ "solid-button-text": "#ffffff"
294
+ };
295
+ const b = [
296
+ {
297
+ key: "btn_bg",
298
+ type: 'string',
299
+ description: '按鈕背景顏色的色號,格式為HEX,未輸入則為none',
300
+ event: (key, data) => {
301
+ theme["solid-button-bg"] = data;
302
+ changeValue("theme", theme);
303
+ }
304
+ },
305
+ {
306
+ key: "btn_text",
307
+ type: 'string',
308
+ description: '按鈕字體顏色的色號,格式為HEX,未輸入則為none',
309
+ event: (key, data) => {
310
+ theme["solid-button-text"] = data;
311
+ changeValue("theme", theme);
312
+ }
313
+ },
314
+ {
315
+ key: 'title',
316
+ type: 'string',
317
+ description: '按鈕標題或內文,未輸入則為none',
318
+ event: (key, data) => {
319
+ changeValue(key, data);
320
+ }
321
+ },
322
+ {
323
+ key: "font-size",
324
+ type: 'number',
325
+ description: '字體大小,範圍為0到100,未輸入則為0',
326
+ event: (key, data) => {
327
+ changeValue(key, data.replace('px', ''));
328
+ }
329
+ },
330
+ {
331
+ key: "btn_width",
332
+ type: 'number',
333
+ description: '按鈕寬度,未輸入則為0',
334
+ event: (key, data) => {
335
+ changeValue('width', { "unit": "px", "value": `${data}px`, "number": `${data}` });
336
+ }
337
+ },
338
+ {
339
+ key: "btn_height",
340
+ type: 'number',
341
+ description: '按鈕高度,未輸入則為0',
342
+ event: (key, data) => {
343
+ changeValue('height', { "unit": "px", "value": `${data.replace('px', '')}px`, "number": data.replace('px', '') });
344
+ }
345
+ },
346
+ {
347
+ key: "radius",
348
+ type: 'string',
349
+ description: '按鈕圓角,未輸入則為none',
350
+ event: (key, data) => {
351
+ changeValue(key, data.replace('px', ''));
352
+ }
353
+ },
354
+ {
355
+ key: "link",
356
+ type: 'string',
357
+ description: '按鈕連結,未輸入則為none',
358
+ event: (key, data) => {
359
+ changeValue(key, data);
360
+ }
361
+ },
362
+ ];
363
+ b.map((d) => {
364
+ schema.required.push(d.key);
365
+ schema.properties[d.key] = {
366
+ type: d.type,
367
+ description: d.description,
368
+ enum: d.enum,
369
+ event: d.event
370
+ };
371
+ });
372
+ })();
373
+ break;
374
+ }
375
+ return schema;
376
+ });
377
+ }
378
+ }
379
+ window.glitter.setModule(import.meta.url, AiEditor);