ckeditor5 1.37.5 → 1.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,110 +1,122 @@
1
- function f(e) {
1
+ function d() {
2
+ const i = Promise.withResolvers();
3
+ return i.promise.catch(() => {
4
+ }), i;
5
+ }
6
+ function p(i) {
2
7
  switch (document.readyState) {
3
8
  case "loading":
4
- document.addEventListener("DOMContentLoaded", e, { once: !0 });
9
+ document.addEventListener("DOMContentLoaded", i, { once: !0 });
5
10
  break;
6
11
  case "interactive":
7
12
  case "complete":
8
- setTimeout(e, 0);
13
+ setTimeout(i, 0);
9
14
  break;
10
15
  default:
11
- console.warn("Unexpected document.readyState:", document.readyState), setTimeout(e, 0);
16
+ console.warn("Unexpected document.readyState:", document.readyState), setTimeout(i, 0);
12
17
  }
13
18
  }
14
19
  const E = /* @__PURE__ */ new Map();
15
- function y(e) {
16
- if (E.has(e))
17
- return E.get(e);
18
- const t = new Promise((i, n) => {
19
- const s = document.createElement("script");
20
- s.src = e, s.onload = i, s.onerror = n, document.head.appendChild(s);
20
+ function y(i) {
21
+ if (E.has(i))
22
+ return E.get(i);
23
+ const t = new Promise((e, n) => {
24
+ const r = document.createElement("script");
25
+ r.src = i, r.onload = e, r.onerror = n, document.head.appendChild(r);
21
26
  });
22
- return E.set(e, t), t;
27
+ return E.set(i, t), t;
23
28
  }
24
- function v(e) {
25
- return typeof e == "string" && e !== "__proto__" && e !== "constructor" && e !== "prototype";
29
+ function w(i) {
30
+ return typeof i == "string" && i !== "__proto__" && i !== "constructor" && i !== "prototype";
26
31
  }
27
- function C(e) {
32
+ function v(i) {
28
33
  return Array.from(document.styleSheets).some(
29
- (t) => t.href === e || t.href === new URL(e, window.location.href).href
34
+ (t) => t.href === i || t.href === new URL(i, window.location.href).href
30
35
  );
31
36
  }
32
- function b(e = []) {
33
- const t = e.map(
34
- (i) => new Promise((n, s) => {
35
- if (C(i)) {
37
+ function g(i = []) {
38
+ const t = i.map(
39
+ (e) => new Promise((n, r) => {
40
+ if (v(e)) {
36
41
  n();
37
42
  return;
38
43
  }
39
- const r = document.createElement("link");
40
- r.rel = "stylesheet", r.href = i, r.onerror = s, r.onload = () => n(), document.head.appendChild(r);
44
+ const s = document.createElement("link");
45
+ s.rel = "stylesheet", s.href = e, s.onerror = r, s.onload = () => n(), document.head.appendChild(s);
41
46
  })
42
47
  );
43
48
  return Promise.all(t);
44
49
  }
45
- function h(e = []) {
46
- const t = async ({ url: n, import_name: s, import_as: r, window_name: c, stylesheets: d }) => {
47
- if (d?.length && await b(d), c) {
48
- let a = function() {
49
- return Object.prototype.hasOwnProperty.call(window, c);
50
+ function h(i = []) {
51
+ const t = async ({ url: n, import_name: r, import_as: s, window_name: o, stylesheets: a }) => {
52
+ if (a?.length && await g(a), o) {
53
+ let u = function() {
54
+ return Object.prototype.hasOwnProperty.call(window, o);
50
55
  };
51
- if (n && !a() && await y(n), a() || window.dispatchEvent(
52
- new CustomEvent(`ckeditor:request-cjs-plugin:${c}`)
53
- ), !a())
56
+ if (n && !u() && await y(n), u() || window.dispatchEvent(
57
+ new CustomEvent(`ckeditor:request-cjs-plugin:${o}`)
58
+ ), !u())
54
59
  throw new Error(
55
- `Plugin window['${c}'] not found in global scope. Please ensure the plugin is loaded before CKEditor initialization.`
60
+ `Plugin window['${o}'] not found in global scope. Please ensure the plugin is loaded before CKEditor initialization.`
56
61
  );
57
- return window[c];
62
+ return window[o];
58
63
  }
59
- const o = await import(s), l = o[r || "default"];
60
- if (!l)
64
+ const l = await import(r), c = l[s || "default"];
65
+ if (!c)
61
66
  throw new Error(
62
- `Plugin "${r || "default"}" not found in the ESM module "${s}"! Available imports: ${Object.keys(o).join(", ")}! Consider changing "import_as" value.`
67
+ `Plugin "${s || "default"}" not found in the ESM module "${r}"! Available imports: ${Object.keys(l).join(", ")}! Consider changing "import_as" value.`
63
68
  );
64
- return l;
69
+ return c;
65
70
  };
66
- function i(n) {
71
+ function e(n) {
67
72
  return t(typeof n == "string" ? { import_name: "ckeditor5", import_as: n } : n);
68
73
  }
69
- return Promise.all(e.map(i));
74
+ return Promise.all(i.map(e));
70
75
  }
71
- function m(e) {
72
- if (!e || typeof e != "object")
73
- return e;
74
- if (Array.isArray(e))
75
- return e.map((n) => m(n));
76
- const t = e;
76
+ function f(i) {
77
+ if (!i || typeof i != "object")
78
+ return i;
79
+ if (Array.isArray(i))
80
+ return i.map((n) => f(n));
81
+ const t = i;
77
82
  if (t.$element && typeof t.$element == "string") {
78
83
  const n = document.querySelector(t.$element);
79
84
  return n || console.warn(`Element not found for selector: ${t.$element}`), n || null;
80
85
  }
81
- const i = /* @__PURE__ */ Object.create(null);
82
- for (const [n, s] of Object.entries(e))
83
- i[n] = m(s);
84
- return i;
85
- }
86
- function A() {
87
- return Math.random().toString(36).substring(2);
86
+ const e = /* @__PURE__ */ Object.create(null);
87
+ for (const [n, r] of Object.entries(i))
88
+ e[n] = f(r);
89
+ return e;
88
90
  }
89
- class P extends HTMLElement {
91
+ class C extends HTMLElement {
90
92
  instance = null;
91
- instancePromise = Promise.withResolvers();
93
+ instancePromise = d();
92
94
  #e = /* @__PURE__ */ new Set();
95
+ /**
96
+ * Incremented on every (re)initialization and on disconnect. An initialization that finishes
97
+ * with a different value is stale and destroys the context it created.
98
+ */
99
+ #t = 0;
100
+ /**
101
+ * Unregisters the error callback of the current context instance.
102
+ */
103
+ #i = null;
93
104
  static get observedAttributes() {
94
105
  return ["plugins", "config"];
95
106
  }
96
- async connectedCallback() {
97
- try {
98
- f(() => this.#t());
99
- } catch (t) {
100
- console.error("Failed to initialize context:", t), this.dispatchEvent(new CustomEvent("context-error", { detail: t }));
101
- }
107
+ connectedCallback() {
108
+ p(() => this.#n());
102
109
  }
103
- async attributeChangedCallback(t, i, n) {
104
- i !== null && i !== n && await this.#t();
110
+ async attributeChangedCallback(t, e, n) {
111
+ e !== null && e !== n && await this.#n();
105
112
  }
106
113
  async disconnectedCallback() {
107
- this.instance && (await this.instance.destroy(), this.instance = null);
114
+ this.#t++;
115
+ try {
116
+ await this.#r();
117
+ } catch (t) {
118
+ console.error("Failed to destroy context:", t);
119
+ }
108
120
  }
109
121
  /**
110
122
  * Register editor component with this context
@@ -122,30 +134,67 @@ class P extends HTMLElement {
122
134
  unregisterEditor(t) {
123
135
  this.#e.delete(t);
124
136
  }
137
+ /**
138
+ * Initializes the context and reports failures instead of leaking rejections
139
+ * (lifecycle callbacks are not awaited by the browser).
140
+ */
141
+ async #n() {
142
+ const t = ++this.#t;
143
+ try {
144
+ await this.#c(t);
145
+ } catch (e) {
146
+ if (t !== this.#t)
147
+ return;
148
+ this.instancePromise.reject(e), this.instancePromise = d(), this.#s("Failed to initialize context:", e);
149
+ }
150
+ }
125
151
  /**
126
152
  * Initialize CKEditor context with shared configuration
127
153
  *
128
154
  * @private
155
+ * @param generation - Value of `#generation` assigned to this initialization.
129
156
  */
130
- async #t() {
131
- this.instance && (this.instancePromise = Promise.withResolvers(), await this.instance.destroy(), this.instance = null), window.dispatchEvent(
157
+ async #c(t) {
158
+ await this.#r(), window.dispatchEvent(
132
159
  new CustomEvent("ckeditor:context:attach:before", { detail: { element: this } })
133
160
  );
134
- const { Context: t, ContextWatchdog: i } = await import("ckeditor5"), n = await this.#i(), s = this.#s();
161
+ const { Context: e, onEditorError: n } = await import("ckeditor5"), r = await this.#o(), s = this.#a();
135
162
  window.dispatchEvent(
136
163
  new CustomEvent("ckeditor:context:attach", { detail: { config: s, element: this } })
137
- ), this.instance = new i(t, {
138
- crashNumberLimit: 10
139
- }), await this.instance.create({
164
+ );
165
+ const o = await e.create({
140
166
  ...s,
141
- plugins: n
142
- }), this.instance.on("itemError", (...r) => {
143
- console.error("Context item error:", ...r);
144
- }), this.instancePromise.resolve(this.instance), this.dispatchEvent(new CustomEvent("context-ready", { detail: this.instance })), await Promise.all(
145
- [...this.#e].map((r) => r.reinitializeEditor())
167
+ plugins: r
168
+ });
169
+ if (t !== this.#t) {
170
+ await o.destroy();
171
+ return;
172
+ }
173
+ this.instance = o, this.#i = n(({ error: a, source: l }) => {
174
+ if (l === o) {
175
+ for (const c of o.editors)
176
+ c.enableReadOnlyMode("error-handling");
177
+ this.#s("Context failed:", a);
178
+ }
179
+ }), this.instancePromise.resolve(o), this.dispatchEvent(new CustomEvent("context-ready", { detail: o })), await Promise.all(
180
+ [...this.#e].map((a) => a.reinitializeEditor().catch(() => {
181
+ }))
146
182
  );
147
183
  }
148
- async #i() {
184
+ /**
185
+ * Destroys the current context instance (and all editors created in it).
186
+ */
187
+ async #r() {
188
+ const { instance: t } = this;
189
+ t && (this.#i?.(), this.#i = null, this.instance = null, this.instancePromise = d(), await t.destroy());
190
+ }
191
+ /**
192
+ * Logs the error and dispatches the `context-error` event.
193
+ */
194
+ #s(t, e) {
195
+ console.error(t, e), this.dispatchEvent(new CustomEvent("context-error", { detail: e }));
196
+ }
197
+ async #o() {
149
198
  const t = this.getAttribute("plugins");
150
199
  return h(t ? JSON.parse(t) : []);
151
200
  }
@@ -154,13 +203,13 @@ class P extends HTMLElement {
154
203
  *
155
204
  * @private
156
205
  */
157
- #s() {
206
+ #a() {
158
207
  const t = JSON.parse(this.getAttribute("config") || "{}");
159
- return m(t);
208
+ return f(t);
160
209
  }
161
210
  }
162
- customElements.define("ckeditor-context-component", P);
163
- class x extends HTMLElement {
211
+ customElements.define("ckeditor-context-component", C);
212
+ class A extends HTMLElement {
164
213
  /**
165
214
  * Gets the name of this editable region
166
215
  */
@@ -190,13 +239,13 @@ class x extends HTMLElement {
190
239
  * Sets up the editable element and registers it with the parent editor
191
240
  */
192
241
  connectedCallback() {
193
- f(() => {
242
+ p(() => {
194
243
  const t = this.#e();
195
244
  if (!t)
196
245
  throw new Error("ckeditor-editable-component must be a child of ckeditor-component");
197
246
  if (this.innerHTML = `<div>${this.innerHTML}</div>`, this.style.display = "block", t.isDecoupled())
198
- t.runAfterEditorReady((i) => {
199
- this.appendChild(i.ui.view[this.name].element);
247
+ t.runAfterEditorReady((e) => {
248
+ this.appendChild(e.ui.view[this.name].element);
200
249
  });
201
250
  else if (t.editables) {
202
251
  if (!this.name)
@@ -220,8 +269,8 @@ class x extends HTMLElement {
220
269
  return this.closest("ckeditor-component") || document.body.querySelector("ckeditor-component");
221
270
  }
222
271
  }
223
- customElements.define("ckeditor-editable-component", x);
224
- class w {
272
+ customElements.define("ckeditor-editable-component", A);
273
+ class b {
225
274
  #e;
226
275
  #t;
227
276
  /**
@@ -231,16 +280,16 @@ class w {
231
280
  * @param initialEditables - Initial editable elements
232
281
  * @returns Proxy wrapping the tracker
233
282
  */
234
- constructor(t, i = {}) {
235
- return this.#e = t, this.#t = i, new Proxy(this, {
283
+ constructor(t, e = {}) {
284
+ return this.#e = t, this.#t = e, new Proxy(this, {
236
285
  /**
237
286
  * Handles property access, returns class methods or editable elements
238
287
  *
239
288
  * @param target - The tracker instance
240
289
  * @param name - Property name being accessed
241
290
  */
242
- get(n, s) {
243
- return typeof n[s] == "function" ? n[s].bind(n) : n.#t[s];
291
+ get(n, r) {
292
+ return typeof n[r] == "function" ? n[r].bind(n) : n.#t[r];
244
293
  },
245
294
  /**
246
295
  * Handles setting new editable elements, triggers root attachment
@@ -249,8 +298,8 @@ class w {
249
298
  * @param name - Name of the editable root
250
299
  * @param element - Element to attach as editable
251
300
  */
252
- set(n, s, r) {
253
- return n.#t[s] !== r && (n.attachRoot(s, r), n.#t[s] = r), !0;
301
+ set(n, r, s) {
302
+ return n.#t[r] !== s && (n.attachRoot(r, s), n.#t[r] = s), !0;
254
303
  },
255
304
  /**
256
305
  * Handles removing editable elements, triggers root detachment
@@ -258,8 +307,8 @@ class w {
258
307
  * @param target - The tracker instance
259
308
  * @param name - Name of the root to remove
260
309
  */
261
- deleteProperty(n, s) {
262
- return n.detachRoot(s), delete n.#t[s], !0;
310
+ deleteProperty(n, r) {
311
+ return n.detachRoot(r), delete n.#t[r], !0;
263
312
  }
264
313
  });
265
314
  }
@@ -271,18 +320,18 @@ class w {
271
320
  * @param element - DOM element to use as editable
272
321
  * @returns Resolves when root is attached
273
322
  */
274
- async attachRoot(t, i) {
323
+ async attachRoot(t, e) {
275
324
  return await this.detachRoot(t), this.#e.runAfterEditorReady((n) => {
276
- const { ui: s, editing: r, model: c } = n, d = i.modelElement, o = i.initialData;
325
+ const { ui: r, editing: s, model: o } = n, a = e.modelElement, l = e.initialData;
277
326
  n.addRoot(t, {
278
327
  isUndoable: !1,
279
- initialData: o ?? i.innerHTML,
280
- ...d && { modelElement: d }
328
+ initialData: l ?? e.innerHTML,
329
+ ...a && { modelElement: a }
281
330
  });
282
- const l = c.document.getRoot(t);
283
- s.getEditableElement(t) && n.detachEditable(l);
284
- const a = s.view.createEditable(t, i);
285
- s.addEditable(a), r.view.forceRender();
331
+ const c = o.document.getRoot(t);
332
+ r.getEditableElement(t) && n.detachEditable(c);
333
+ const u = r.view.createEditable(t, e);
334
+ r.addEditable(u), s.view.forceRender();
286
335
  });
287
336
  }
288
337
  /**
@@ -293,9 +342,9 @@ class w {
293
342
  * @returns Resolves when root is detached
294
343
  */
295
344
  async detachRoot(t) {
296
- return this.#e.runAfterEditorReady((i) => {
297
- const n = i.model.document.getRoot(t);
298
- n && (i.detachEditable(n), i.detachRoot(t, !0));
345
+ return this.#e.runAfterEditorReady((e) => {
346
+ const n = e.model.document.getRoot(t);
347
+ n && (e.detachEditable(n), e.detachRoot(t, !0));
299
348
  });
300
349
  }
301
350
  /**
@@ -307,15 +356,22 @@ class w {
307
356
  return this.#t;
308
357
  }
309
358
  }
310
- class p extends HTMLElement {
311
- instancePromise = Promise.withResolvers();
312
- watchdog = null;
359
+ class m extends HTMLElement {
360
+ instancePromise = d();
313
361
  instance = null;
314
362
  editables = /* @__PURE__ */ Object.create(null);
315
363
  #e = "";
316
364
  #t = null;
317
- #i = null;
318
- #s = null;
365
+ /**
366
+ * Incremented on every (re)initialization and on disconnect. An initialization that finishes
367
+ * with a different value is stale and destroys the editor it created.
368
+ */
369
+ #i = 0;
370
+ /**
371
+ * Unregisters the error callback of the current editor instance.
372
+ */
373
+ #n = null;
374
+ #c = null;
319
375
  /**
320
376
  * List of attributes that trigger updates when changed.
321
377
  */
@@ -332,19 +388,19 @@ class p extends HTMLElement {
332
388
  return this.#r("editorchange");
333
389
  }
334
390
  set oneditorchange(t) {
335
- this.#o("editorchange", t);
391
+ this.#s("editorchange", t);
336
392
  }
337
393
  get oneditorready() {
338
394
  return this.#r("editorready");
339
395
  }
340
396
  set oneditorready(t) {
341
- this.#o("editorready", t);
397
+ this.#s("editorready", t);
342
398
  }
343
399
  get oneditorerror() {
344
400
  return this.#r("editorerror");
345
401
  }
346
402
  set oneditorerror(t) {
347
- this.#o("editorerror", t);
403
+ this.#s("editorerror", t);
348
404
  }
349
405
  /**
350
406
  * Gets event handler function from attribute or property
@@ -354,7 +410,7 @@ class p extends HTMLElement {
354
410
  * @returns Event handler or null
355
411
  */
356
412
  #r(t) {
357
- return this.hasAttribute(`on${t}`) ? z(this.getAttribute(`on${t}`)) : this[`#${t}Handler`];
413
+ return this.hasAttribute(`on${t}`) ? j(this.getAttribute(`on${t}`)) : this[`#${t}Handler`];
358
414
  }
359
415
  /**
360
416
  * Sets event handler function
@@ -363,8 +419,8 @@ class p extends HTMLElement {
363
419
  * @param name - Event name without 'on' prefix
364
420
  * @param handler - Event handler
365
421
  */
366
- #o(t, i) {
367
- typeof i == "string" ? this.setAttribute(`on${t}`, i) : (this.removeAttribute(`on${t}`), this[`#${t}Handler`] = i);
422
+ #s(t, e) {
423
+ typeof e == "string" ? this.setAttribute(`on${t}`, e) : (this.removeAttribute(`on${t}`), this[`#${t}Handler`] = e);
368
424
  }
369
425
  /**
370
426
  * Lifecycle callback when element is connected to DOM
@@ -373,16 +429,19 @@ class p extends HTMLElement {
373
429
  * @protected
374
430
  */
375
431
  connectedCallback() {
376
- this.#t = this.closest("ckeditor-context-component"), this.#e = this.innerHTML;
377
- try {
378
- f(async () => {
379
- this.#t && (await this.#t.instancePromise.promise, this.#t.registerEditor(this)), await this.reinitializeEditor();
432
+ this.#t = this.closest("ckeditor-context-component"), this.#e = this.innerHTML, p(async () => {
433
+ if (this.#t) {
434
+ try {
435
+ await this.#t.instancePromise.promise;
436
+ } catch (t) {
437
+ this.#l("Failed to initialize editor:", t);
438
+ return;
439
+ }
440
+ this.#t.registerEditor(this);
441
+ }
442
+ await this.reinitializeEditor().catch(() => {
380
443
  });
381
- } catch (t) {
382
- console.error("Failed to initialize editor:", t);
383
- const i = new CustomEvent("editor-error", { detail: t });
384
- this.dispatchEvent(i), this.oneditorerror?.(i);
385
- }
444
+ });
386
445
  }
387
446
  /**
388
447
  * Handles attribute changes and reinitializes editor if needed
@@ -392,8 +451,9 @@ class p extends HTMLElement {
392
451
  * @param oldValue - Previous attribute value
393
452
  * @param newValue - New attribute value
394
453
  */
395
- async attributeChangedCallback(t, i, n) {
396
- i !== null && i !== n && p.observedAttributes.includes(t) && this.isConnected && await this.reinitializeEditor();
454
+ async attributeChangedCallback(t, e, n) {
455
+ e !== null && e !== n && m.observedAttributes.includes(t) && this.isConnected && await this.reinitializeEditor().catch(() => {
456
+ });
397
457
  }
398
458
  /**
399
459
  * Lifecycle callback when element is removed from DOM
@@ -401,9 +461,9 @@ class p extends HTMLElement {
401
461
  * @protected
402
462
  */
403
463
  async disconnectedCallback() {
404
- this.#t && this.#t.unregisterEditor(this);
464
+ this.#t && this.#t.unregisterEditor(this), this.#i++;
405
465
  try {
406
- await this.#l();
466
+ await this.#a();
407
467
  } catch (t) {
408
468
  console.error("Failed to destroy editor:", t);
409
469
  }
@@ -420,70 +480,67 @@ class p extends HTMLElement {
420
480
  /**
421
481
  * Determines appropriate editor element tag based on editor type
422
482
  */
423
- get #n() {
424
- return S(this.getAttribute("type"));
483
+ get #o() {
484
+ return P(this.getAttribute("type"));
425
485
  }
426
486
  /**
427
- * Gets the CKEditor context instance if available.
487
+ * Destroys the current editor instance, if any.
428
488
  */
429
- get #a() {
430
- return this.#t?.instance;
489
+ async #a() {
490
+ const t = this.#u();
491
+ t && t.state !== "destroyed" && await t.destroy();
492
+ }
493
+ /**
494
+ * Detaches the current editor instance from the component without destroying it.
495
+ *
496
+ * @returns The detached instance or `null` if there was none.
497
+ */
498
+ #u() {
499
+ const { instance: t } = this;
500
+ return t ? (this.#n?.(), this.#n = null, this.instance = null, this.instancePromise = d(), t) : null;
431
501
  }
432
502
  /**
433
- * Destroys the editor instance and watchdog if available
503
+ * Logs the error and dispatches the `editor-error` event.
434
504
  */
435
- async #l() {
436
- this.#i && await this.#a.remove(this.#i), await this.instance?.destroy(), this.watchdog?.destroy();
505
+ #l(t, e) {
506
+ console.error(t, e);
507
+ const n = new CustomEvent("editor-error", { detail: e });
508
+ this.dispatchEvent(n), this.oneditorerror?.(n);
437
509
  }
438
510
  /**
439
511
  * Gets editor configuration with resolved element references
440
512
  */
441
- #d() {
442
- return R(this.getAttribute("config"));
513
+ #h() {
514
+ return x(this.getAttribute("config"));
443
515
  }
444
516
  /**
445
517
  * Creates a new CKEditor instance
446
518
  */
447
- async #h(t) {
519
+ async #m(t) {
520
+ const e = this.#t ? await this.#t.instancePromise.promise : null;
448
521
  await Promise.all([
449
- this.#E(),
450
- this.#b()
522
+ this.#y(),
523
+ this.#w()
451
524
  ]);
452
- const { isMultiroot: i, content: n } = M(t), s = k(n, i);
525
+ const { isMultiroot: n, content: r } = S(t), s = M(r, n);
453
526
  window.dispatchEvent(
454
527
  new CustomEvent("ckeditor:attach:before", { detail: s })
455
528
  );
456
- const r = await this.#v(), [c, d] = await Promise.all([
457
- this.#y(),
458
- this.#w()
459
- ]), o = {
460
- ...this.#d(),
461
- ...d.length && {
462
- translations: d
529
+ const o = await this.#A(), [a, l] = await Promise.all([
530
+ this.#C(),
531
+ this.#v()
532
+ ]), c = {
533
+ ...this.#h(),
534
+ ...l.length && {
535
+ translations: l
463
536
  },
464
- plugins: c
537
+ plugins: a
465
538
  };
466
- D(o, n, i, this.isClassic()), window.dispatchEvent(
467
- new CustomEvent("ckeditor:attach", { detail: { config: o, ...s } })
539
+ return R(c, r, n, this.isClassic()), window.dispatchEvent(
540
+ new CustomEvent("ckeditor:attach", { detail: { config: c, ...s } })
541
+ ), o.create(
542
+ e ? { ...c, context: e } : c
468
543
  );
469
- let l = null, a = null, u = null;
470
- if (this.#t)
471
- u = A(), await this.#a.add({
472
- creator: (g) => r.create(g),
473
- id: u,
474
- type: "editor",
475
- config: o
476
- }), a = this.#a.getItem(u);
477
- else if (this.hasWatchdog()) {
478
- const { EditorWatchdog: g } = await import("ckeditor5");
479
- l = new g(r), await l.create(o), a = l.editor;
480
- } else
481
- a = await r.create(o);
482
- return {
483
- contextId: u,
484
- instance: a,
485
- watchdog: l
486
- };
487
544
  }
488
545
  /**
489
546
  * Re-initializes the editor by destroying existing instance and creating new one
@@ -492,29 +549,43 @@ class p extends HTMLElement {
492
549
  * @returns {Promise<void>}
493
550
  */
494
551
  async reinitializeEditor() {
495
- this.instance && (this.instancePromise = Promise.withResolvers(), await this.#l(), this.instance = null), this.style.display = "block", !this.isMultiroot() && !this.isDecoupled() && (this.innerHTML = `<${this.#n}>${this.#e}</${this.#n}>`, this.#p()), this.isMultiroot() ? this.editables = new w(this, this.#u()) : this.isDecoupled() ? this.editables = null : this.editables = this.#u();
552
+ const t = ++this.#i;
496
553
  try {
497
- const { watchdog: t, instance: i, contextId: n } = await this.#h(this.editables || this.#d().root?.initialData || "");
498
- this.watchdog = t, this.instance = i, this.#i = n, this.#f(), this.#g(), this.#m(), this.instancePromise.resolve(this.instance);
499
- const s = new CustomEvent("editor-ready", { detail: this.instance });
500
- this.dispatchEvent(s), this.oneditorready?.(s);
501
- } catch (t) {
502
- throw this.instancePromise.reject(t), t;
554
+ await this.#a(), this.style.display = "block", !this.isMultiroot() && !this.isDecoupled() && (this.innerHTML = `<${this.#o}>${this.#e}</${this.#o}>`, this.#E()), this.isMultiroot() ? this.editables = new b(this, this.#f()) : this.isDecoupled() ? this.editables = null : this.editables = this.#f();
555
+ const [e, { onEditorError: n }] = await Promise.all([
556
+ this.#m(this.editables || this.#h().root?.initialData || ""),
557
+ import("ckeditor5")
558
+ ]);
559
+ if (t !== this.#i) {
560
+ e.state !== "destroyed" && await e.destroy();
561
+ return;
562
+ }
563
+ this.instance = e, this.#n = n(({ error: s, source: o }) => {
564
+ o === e && (e.enableReadOnlyMode("error-handling"), this.#l("Editor failed:", s));
565
+ }), e.once("destroy", () => {
566
+ this.instance === e && this.#u();
567
+ }), this.#g(), this.#b(), this.#p(), this.instancePromise.resolve(e);
568
+ const r = new CustomEvent("editor-ready", { detail: e });
569
+ this.dispatchEvent(r), this.oneditorready?.(r);
570
+ } catch (e) {
571
+ if (t !== this.#i)
572
+ return;
573
+ throw this.instancePromise.reject(e), this.instancePromise = d(), this.#l("Failed to initialize editor:", e), e;
503
574
  }
504
575
  }
505
576
  /**
506
577
  * Sets up data change listener that broadcasts content changes
507
578
  */
508
- #m() {
509
- const t = (n) => this.instance.getData({ rootName: n }), i = () => this.instance?.model.document.getRootNames().reduce((n, s) => ({
579
+ #p() {
580
+ const t = (n) => this.instance.getData({ rootName: n }), e = () => this.instance?.model.document.getRootNames().reduce((n, r) => ({
510
581
  ...n,
511
- [s]: t(s)
582
+ [r]: t(r)
512
583
  }), {});
513
584
  this.instance?.model.document.on("change:data", () => {
514
585
  const n = new CustomEvent("editor-change", {
515
586
  detail: {
516
587
  editor: this.instance,
517
- data: i()
588
+ data: e()
518
589
  },
519
590
  bubbles: !0
520
591
  });
@@ -545,25 +616,19 @@ class p extends HTMLElement {
545
616
  isDecoupled() {
546
617
  return this.getAttribute("type") === "DecoupledEditor";
547
618
  }
548
- /**
549
- * Checks if current editor has watchdog enabled
550
- */
551
- hasWatchdog() {
552
- return this.getAttribute("watchdog") === "true";
553
- }
554
619
  /**
555
620
  * Queries and validates editable elements
556
621
  */
557
- #u() {
622
+ #f() {
558
623
  if (this.isDecoupled())
559
624
  return {};
560
625
  if (this.isMultiroot()) {
561
- const i = [...this.querySelectorAll("ckeditor-editable-component")];
562
- return H(i);
626
+ const e = [...this.querySelectorAll("ckeditor-editable-component")];
627
+ return D(e);
563
628
  }
564
- const t = this.querySelector(this.#n);
629
+ const t = this.querySelector(this.#o);
565
630
  if (!t)
566
- throw new Error(`No ${this.#n} element found`);
631
+ throw new Error(`No ${this.#o} element found`);
567
632
  return { main: t };
568
633
  }
569
634
  /**
@@ -571,26 +636,26 @@ class p extends HTMLElement {
571
636
  *
572
637
  * @private
573
638
  */
574
- #p() {
639
+ #E() {
575
640
  const t = this.querySelector("textarea");
576
- t && T(this, t, p.inputAttributes);
641
+ t && $(this, t, m.inputAttributes);
577
642
  }
578
643
  /**
579
644
  * Sets up content sync between editor and textarea element.
580
645
  *
581
646
  * @private
582
647
  */
583
- #f() {
648
+ #g() {
584
649
  if (!this.instance)
585
650
  return;
586
651
  const t = this.querySelector("textarea");
587
652
  if (!t)
588
653
  return;
589
- const i = () => {
590
- this.style.position = "relative", t.innerHTML = "", t.value = this.instance.getData(), L(t);
654
+ const e = () => {
655
+ this.style.position = "relative", t.innerHTML = "", t.value = this.instance.getData(), H(t);
591
656
  };
592
- i(), this.instance.model.document.on("change:data", () => {
593
- t.dispatchEvent(new Event("input", { bubbles: !0 })), t.dispatchEvent(new Event("change", { bubbles: !0 })), i();
657
+ e(), this.instance.model.document.on("change:data", () => {
658
+ t.dispatchEvent(new Event("input", { bubbles: !0 })), t.dispatchEvent(new Event("change", { bubbles: !0 })), e();
594
659
  });
595
660
  }
596
661
  /**
@@ -598,102 +663,102 @@ class p extends HTMLElement {
598
663
  *
599
664
  * @private
600
665
  */
601
- #g() {
666
+ #b() {
602
667
  if (!this.isClassic() && !this.isBallon())
603
668
  return;
604
- const t = I(this.getAttribute("editable-height"));
605
- t !== null && O(this.instance, t);
669
+ const t = T(this.getAttribute("editable-height"));
670
+ t !== null && L(this.instance, t);
606
671
  }
607
672
  /**
608
673
  * Gets bundle JSON description from translations attribute
609
674
  */
610
- #c() {
611
- return this.#s ||= q(this.getAttribute("bundle"));
675
+ #d() {
676
+ return this.#c ||= O(this.getAttribute("bundle"));
612
677
  }
613
678
  /**
614
679
  * Checks if all required stylesheets are injected. If not, inject.
615
680
  */
616
- async #E() {
617
- await b(this.#c()?.stylesheets || []);
681
+ async #y() {
682
+ await g(this.#d()?.stylesheets || []);
618
683
  }
619
684
  /**
620
685
  * Checks if all required scripts are injected. If not, inject.
621
686
  */
622
- async #b() {
623
- const t = (this.#c()?.scripts || []).filter((i) => !!i.window_name);
687
+ async #w() {
688
+ const t = (this.#d()?.scripts || []).filter((e) => !!e.window_name);
624
689
  await h(t);
625
690
  }
626
691
  /**
627
692
  * Loads translation modules
628
693
  */
629
- async #w() {
630
- const t = this.#c()?.scripts.filter((i) => i.translation);
694
+ async #v() {
695
+ const t = this.#d()?.scripts.filter((e) => e.translation);
631
696
  return h(t);
632
697
  }
633
698
  /**
634
699
  * Loads plugin modules
635
700
  */
636
- async #y() {
637
- return h(j(this.getAttribute("plugins")));
701
+ async #C() {
702
+ return h(I(this.getAttribute("plugins")));
638
703
  }
639
704
  /**
640
705
  * Gets editor constructor based on type attribute
641
706
  */
642
- async #v() {
707
+ async #A() {
643
708
  const t = await import("ckeditor5");
644
- return N(t, this.getAttribute("type"));
709
+ return q(t, this.getAttribute("type"));
645
710
  }
646
711
  }
647
- function S(e) {
648
- return e === "ClassicEditor" ? "textarea" : "div";
712
+ function P(i) {
713
+ return i === "ClassicEditor" ? "textarea" : "div";
649
714
  }
650
- function R(e) {
651
- const t = JSON.parse(e || "{}");
652
- return m(t);
715
+ function x(i) {
716
+ const t = JSON.parse(i || "{}");
717
+ return f(t);
653
718
  }
654
- function M(e) {
655
- const t = e instanceof w;
656
- let i = e;
657
- return t ? i = e.getAll() : typeof e != "string" && (i = e.main), { isMultiroot: t, content: i };
719
+ function S(i) {
720
+ const t = i instanceof b;
721
+ let e = i;
722
+ return t ? e = i.getAll() : typeof i != "string" && (e = i.main), { isMultiroot: t, content: e };
658
723
  }
659
- function k(e, t) {
724
+ function M(i, t) {
660
725
  return {
661
- ...e instanceof HTMLElement && { element: e },
662
- ...typeof e == "string" && { data: e },
663
- ...t && { editables: e }
726
+ ...i instanceof HTMLElement && { element: i },
727
+ ...typeof i == "string" && { data: i },
728
+ ...t && { editables: i }
664
729
  };
665
730
  }
666
- function D(e, t, i, n) {
667
- i ? e.roots = $(t) : n && t instanceof HTMLElement ? e.attachTo = t : t instanceof HTMLElement ? e.root = { ...e.root, element: t } : typeof t == "string" && (e.root = { ...e.root, initialData: t });
731
+ function R(i, t, e, n) {
732
+ e ? i.roots = k(t) : n && t instanceof HTMLElement ? i.attachTo = t : t instanceof HTMLElement ? i.root = { ...i.root, element: t } : typeof t == "string" && (i.root = { ...i.root, initialData: t });
668
733
  }
669
- function $(e) {
734
+ function k(i) {
670
735
  return Object.fromEntries(
671
- Object.entries(e).map(([t, i]) => {
672
- const n = i.modelElement, s = i.initialData;
736
+ Object.entries(i).map(([t, e]) => {
737
+ const n = e.modelElement, r = e.initialData;
673
738
  return [
674
739
  t,
675
740
  {
676
- element: i,
677
- initialData: s ?? i.innerHTML,
741
+ element: e,
742
+ initialData: r ?? e.innerHTML,
678
743
  ...n && { modelElement: n }
679
744
  }
680
745
  ];
681
746
  })
682
747
  );
683
748
  }
684
- function H(e) {
685
- return e.reduce((t, i) => {
686
- if (!i.name)
749
+ function D(i) {
750
+ return i.reduce((t, e) => {
751
+ if (!e.name)
687
752
  throw new Error('Editable component missing required "name" attribute');
688
- return t[i.name] = i, t;
753
+ return t[e.name] = e, t;
689
754
  }, /* @__PURE__ */ Object.create(null));
690
755
  }
691
- function T(e, t, i) {
692
- for (const n of i)
693
- e.hasAttribute(n) && t.setAttribute(n, e.getAttribute(n));
756
+ function $(i, t, e) {
757
+ for (const n of e)
758
+ i.hasAttribute(n) && t.setAttribute(n, i.getAttribute(n));
694
759
  }
695
- function L(e) {
696
- e.tabIndex = -1, Object.assign(e.style, {
760
+ function H(i) {
761
+ i.tabIndex = -1, Object.assign(i.style, {
697
762
  display: "flex",
698
763
  position: "absolute",
699
764
  bottom: "0",
@@ -707,45 +772,45 @@ function L(e) {
707
772
  border: "none"
708
773
  });
709
774
  }
710
- function I(e) {
711
- if (e === null)
775
+ function T(i) {
776
+ if (i === null)
712
777
  return null;
713
- const t = Number.parseInt(e, 10);
778
+ const t = Number.parseInt(i, 10);
714
779
  return Number.isNaN(t) ? null : t;
715
780
  }
716
- function O(e, t) {
717
- e.editing.view.change((i) => {
718
- i.setStyle("height", `${t}px`, e.editing.view.document.getRoot());
781
+ function L(i, t) {
782
+ i.editing.view.change((e) => {
783
+ e.setStyle("height", `${t}px`, i.editing.view.document.getRoot());
719
784
  });
720
785
  }
721
- function q(e) {
722
- return JSON.parse(e);
786
+ function O(i) {
787
+ return JSON.parse(i);
723
788
  }
724
- function j(e) {
725
- return (e ? JSON.parse(e) : []).map(
726
- (i) => typeof i == "string" ? { import_name: "ckeditor5", import_as: i } : i
789
+ function I(i) {
790
+ return (i ? JSON.parse(i) : []).map(
791
+ (e) => typeof e == "string" ? { import_name: "ckeditor5", import_as: e } : e
727
792
  );
728
793
  }
729
- function N(e, t) {
730
- if (!t || !Object.prototype.hasOwnProperty.call(e, t))
794
+ function q(i, t) {
795
+ if (!t || !Object.prototype.hasOwnProperty.call(i, t))
731
796
  throw new Error(`Invalid editor type: ${t}`);
732
- return e[t];
797
+ return i[t];
733
798
  }
734
- function z(e) {
735
- if (!v(e))
736
- throw new Error(`Unsafe event handler attribute value: ${e}`);
737
- return window[e] || new Function("event", e);
799
+ function j(i) {
800
+ if (!w(i))
801
+ throw new Error(`Unsafe event handler attribute value: ${i}`);
802
+ return window[i] || new Function("event", i);
738
803
  }
739
- customElements.define("ckeditor-component", p);
740
- class B extends HTMLElement {
804
+ customElements.define("ckeditor-component", m);
805
+ class z extends HTMLElement {
741
806
  /**
742
807
  * Lifecycle callback when element is added to DOM.
743
808
  * Adds the toolbar to the editor UI.
744
809
  */
745
810
  connectedCallback() {
746
- f(async () => {
747
- const t = this.getAttribute("name"), i = await this.#e().instancePromise.promise;
748
- this.appendChild(i.ui.view[t].element);
811
+ p(async () => {
812
+ const t = this.getAttribute("name"), e = await this.#e().instancePromise.promise;
813
+ this.appendChild(e.ui.view[t].element);
749
814
  });
750
815
  }
751
816
  /**
@@ -755,5 +820,5 @@ class B extends HTMLElement {
755
820
  return this.closest("ckeditor-component") || document.body.querySelector("ckeditor-component");
756
821
  }
757
822
  }
758
- customElements.define("ckeditor-ui-part-component", B);
823
+ customElements.define("ckeditor-ui-part-component", z);
759
824
  //# sourceMappingURL=index.mjs.map