Current section

Files

Jump to
ckeditor5_phoenix dist index.mjs
Raw

dist/index.mjs

function b(a, t) {
let e = null;
return (...r) => {
e && clearTimeout(e), e = setTimeout(() => {
t(...r);
}, a);
};
}
class g {
/**
* The DOM element the hook is attached to.
* It includes an `instance` property to hold the hook instance.
*/
el;
/**
* The LiveView socket instance, providing connection to the server.
*/
liveSocket;
/**
* Pushes an event from the client to the LiveView server process.
* @param _event The name of the event.
* @param _payload The data to send with the event.
* @param _callback An optional function to be called with the server's reply.
*/
pushEvent;
/**
* Pushes an event to another hook on the page.
* @param _selector The CSS selector of the target element with the hook.
* @param _event The name of the event.
* @param _payload The data to send with the event.
* @param _callback An optional function to be called with the reply.
*/
pushEventTo;
/**
* Registers a handler for an event pushed from the server.
* @param _event The name of the event to handle.
* @param _callback The function to execute when the event is received.
*/
handleEvent;
}
function f(a) {
return {
/**
* The mounted lifecycle callback for the LiveView hook object.
* It creates an instance of the user-defined hook class and sets up the necessary properties and methods.
*/
mounted() {
const t = new a();
this.el.instance = t, t.el = this.el, t.liveSocket = this.liveSocket, t.pushEvent = (e, r, i) => this.pushEvent?.(e, r, i), t.pushEventTo = (e, r, i, n) => this.pushEventTo?.(e, r, i, n), t.handleEvent = (e, r) => this.handleEvent?.(e, r), t.mounted?.();
},
/**
* The beforeUpdate lifecycle callback that delegates to the hook instance.
*/
beforeUpdate() {
this.el.instance.beforeUpdate?.();
},
/**
* The destroyed lifecycle callback that delegates to the hook instance.
*/
destroyed() {
this.el.instance.destroyed?.();
},
/**
* The disconnected lifecycle callback that delegates to the hook instance.
*/
disconnected() {
this.el.instance.disconnected?.();
},
/**
* The reconnected lifecycle callback that delegates to the hook instance.
*/
reconnected() {
this.el.instance.reconnected?.();
}
};
}
function I(a, t) {
const e = Object.entries(a).map(([r, i]) => [r, t(i, r)]);
return Object.fromEntries(e);
}
function v(a) {
if (a === null)
return null;
const t = Number.parseInt(a, 10);
return Number.isNaN(t) ? null : t;
}
class u {
static the = new u();
/**
* Map of registered editors.
*/
editors = /* @__PURE__ */ new Map();
/**
* Map of callbacks that are waiting for an editor to be registered.
*/
callbacks = /* @__PURE__ */ new Map();
/**
* Private constructor to enforce singleton pattern.
*/
constructor() {
}
/**
* Executes a function on an editor.
* If the editor is not yet registered, it will wait for it to be registered.
*
* @param editorId The ID of the editor.
* @param fn The function to execute.
* @returns A promise that resolves with the result of the function.
*/
execute(t, e) {
const { callbacks: r, editors: i } = this, n = i.get(t);
return n ? Promise.resolve(e(n)) : new Promise((o) => {
const s = async (l) => o(await e(l));
this.callbacks.has(t) || r.set(t, []), r.set(t, [
...r.get(t),
s
]);
});
}
/**
* Registers an editor.
*
* @param editorId The ID of the editor.
* @param editor The editor instance.
*/
register(t, e) {
const { editors: r, callbacks: i } = this, n = i.get(t);
if (r.has(t))
throw new Error(`Editor with ID "${t}" is already registered.`);
r.set(t, e), n && (n.forEach((o) => o(e)), i.delete(t)), this.editors.size === 1 && this.register(null, e);
}
/**
* Un-registers an editor.
*
* @param editorId The ID of the editor.
*/
unregister(t) {
const { editors: e, callbacks: r } = this;
if (!e.has(t))
throw new Error(`Editor with ID "${t}" is not registered.`);
t && this.editors.get(null) === e.get(t) && this.unregister(null), e.delete(t), r.delete(t);
}
/**
* Gets all registered editors.
*/
getEditors() {
return Array.from(this.editors.values());
}
/**
* Checks if an editor with the given ID is registered.
*
* @param editorId The ID of the editor.
* @returns `true` if the editor is registered, `false` otherwise.
*/
hasEditor(t) {
return this.editors.has(t);
}
/**
* Gets a promise that resolves with the editor instance for the given ID.
* If the editor is not registered yet, it will wait for it to be registered.
*
* @param editorId The ID of the editor.
* @returns A promise that resolves with the editor instance.
*/
waitForEditor(t) {
return this.execute(t, (e) => e);
}
/**
* Destroys all registered editors and clears the registry.
* This will call the `destroy` method on each editor.
*/
async destroyAllEditors() {
const t = Array.from(this.editors.values()).map((e) => e.destroy());
this.editors.clear(), this.callbacks.clear(), await Promise.all(t);
}
}
class j extends g {
/**
* The name of the hook.
*/
mountedPromise = null;
/**
* Attributes for the editable instance.
*/
get attrs() {
const t = {
editableId: this.el.getAttribute("id"),
editorId: this.el.getAttribute("data-cke-editor-id") || null,
rootName: this.el.getAttribute("data-cke-editable-root-name"),
initialValue: this.el.getAttribute("data-cke-editable-initial-value") || ""
};
return Object.defineProperty(this, "attrs", {
value: t,
writable: !1,
configurable: !1,
enumerable: !0
}), t;
}
/**
* Mounts the editable component.
*/
async mounted() {
const { editableId: t, editorId: e, rootName: r, initialValue: i } = this.attrs, n = this.el.querySelector(`#${t}_input`);
this.mountedPromise = u.the.execute(e, (o) => {
const { ui: s, editing: l, model: d } = o;
if (d.document.getRoot(r))
return;
o.addRoot(r, {
isUndoable: !1,
data: i
});
const p = this.el.querySelector("[data-cke-editable-content]"), w = s.view.createEditable(r, p);
s.addEditable(w), l.view.forceRender(), n && H(n, o, r);
});
}
/**
* Destroys the editable component. Unmounts root from the editor.
*/
async destroyed() {
const { editorId: t, rootName: e } = this.attrs;
this.el.style.display = "none", await this.mountedPromise, this.mountedPromise = null, await u.the.execute(t, (r) => {
const i = r.model.document.getRoot(e);
i && (r.detachEditable(i), r.detachRoot(e, !1));
});
}
}
const T = f(j);
function H(a, t, e) {
const r = () => {
a.value = t.getData({ rootName: e });
};
t.model.document.on("change:data", b(100, r)), r();
}
function k(a) {
return ["inline", "classic", "balloon", "decoupled"].includes(a);
}
async function R(a) {
const t = await import("ckeditor5"), r = {
inline: t.InlineEditor,
balloon: t.BalloonEditor,
classic: t.ClassicEditor,
decoupled: t.DecoupledEditor,
multiroot: t.MultiRootEditor
}[a];
if (!r)
throw new Error(`Unsupported editor type: ${a}`);
return r;
}
async function S(a) {
const t = await import("ckeditor5");
let e = null;
const r = a.map(async (i) => {
const { [i]: n } = t;
if (n)
return n;
if (!e)
try {
e = await import("ckeditor5-premium-features");
} catch (s) {
console.error(`Failed to load premium package: ${s}`);
}
const { [i]: o } = e || {};
if (o)
return o;
throw new Error(`Plugin "${i}" not found in base or premium packages.`);
});
return {
loadedPlugins: await Promise.all(r),
hasPremium: !!e
};
}
async function P(a, t) {
return await Promise.all(
t.filter((e) => e !== "en").map(async (e) => {
const r = await D(a, e);
return r?.default ?? r;
}).filter(Boolean)
);
}
async function D(a, t) {
try {
if (a === "ckeditor5")
switch (t) {
case "af":
return await import("ckeditor5/translations/af.js");
case "ar":
return await import("ckeditor5/translations/ar.js");
case "ast":
return await import("ckeditor5/translations/ast.js");
case "az":
return await import("ckeditor5/translations/az.js");
case "bg":
return await import("ckeditor5/translations/bg.js");
case "bn":
return await import("ckeditor5/translations/bn.js");
case "bs":
return await import("ckeditor5/translations/bs.js");
case "ca":
return await import("ckeditor5/translations/ca.js");
case "cs":
return await import("ckeditor5/translations/cs.js");
case "da":
return await import("ckeditor5/translations/da.js");
case "de":
return await import("ckeditor5/translations/de.js");
case "de-ch":
return await import("ckeditor5/translations/de-ch.js");
case "el":
return await import("ckeditor5/translations/el.js");
case "en":
return await import("ckeditor5/translations/en.js");
case "en-au":
return await import("ckeditor5/translations/en-au.js");
case "en-gb":
return await import("ckeditor5/translations/en-gb.js");
case "eo":
return await import("ckeditor5/translations/eo.js");
case "es":
return await import("ckeditor5/translations/es.js");
case "es-co":
return await import("ckeditor5/translations/es-co.js");
case "et":
return await import("ckeditor5/translations/et.js");
case "eu":
return await import("ckeditor5/translations/eu.js");
case "fa":
return await import("ckeditor5/translations/fa.js");
case "fi":
return await import("ckeditor5/translations/fi.js");
case "fr":
return await import("ckeditor5/translations/fr.js");
case "gl":
return await import("ckeditor5/translations/gl.js");
case "gu":
return await import("ckeditor5/translations/gu.js");
case "he":
return await import("ckeditor5/translations/he.js");
case "hi":
return await import("ckeditor5/translations/hi.js");
case "hr":
return await import("ckeditor5/translations/hr.js");
case "hu":
return await import("ckeditor5/translations/hu.js");
case "hy":
return await import("ckeditor5/translations/hy.js");
case "id":
return await import("ckeditor5/translations/id.js");
case "it":
return await import("ckeditor5/translations/it.js");
case "ja":
return await import("ckeditor5/translations/ja.js");
case "jv":
return await import("ckeditor5/translations/jv.js");
case "kk":
return await import("ckeditor5/translations/kk.js");
case "km":
return await import("ckeditor5/translations/km.js");
case "kn":
return await import("ckeditor5/translations/kn.js");
case "ko":
return await import("ckeditor5/translations/ko.js");
case "ku":
return await import("ckeditor5/translations/ku.js");
case "lt":
return await import("ckeditor5/translations/lt.js");
case "lv":
return await import("ckeditor5/translations/lv.js");
case "ms":
return await import("ckeditor5/translations/ms.js");
case "nb":
return await import("ckeditor5/translations/nb.js");
case "ne":
return await import("ckeditor5/translations/ne.js");
case "nl":
return await import("ckeditor5/translations/nl.js");
case "no":
return await import("ckeditor5/translations/no.js");
case "oc":
return await import("ckeditor5/translations/oc.js");
case "pl":
return await import("ckeditor5/translations/pl.js");
case "pt":
return await import("ckeditor5/translations/pt.js");
case "pt-br":
return await import("ckeditor5/translations/pt-br.js");
case "ro":
return await import("ckeditor5/translations/ro.js");
case "ru":
return await import("ckeditor5/translations/ru.js");
case "si":
return await import("ckeditor5/translations/si.js");
case "sk":
return await import("ckeditor5/translations/sk.js");
case "sl":
return await import("ckeditor5/translations/sl.js");
case "sq":
return await import("ckeditor5/translations/sq.js");
case "sr":
return await import("ckeditor5/translations/sr.js");
case "sr-latn":
return await import("ckeditor5/translations/sr-latn.js");
case "sv":
return await import("ckeditor5/translations/sv.js");
case "th":
return await import("ckeditor5/translations/th.js");
case "tk":
return await import("ckeditor5/translations/tk.js");
case "tr":
return await import("ckeditor5/translations/tr.js");
case "tt":
return await import("ckeditor5/translations/tt.js");
case "ug":
return await import("ckeditor5/translations/ug.js");
case "uk":
return await import("ckeditor5/translations/uk.js");
case "ur":
return await import("ckeditor5/translations/ur.js");
case "uz":
return await import("ckeditor5/translations/uz.js");
case "vi":
return await import("ckeditor5/translations/vi.js");
case "zh":
return await import("ckeditor5/translations/zh.js");
case "zh-cn":
return await import("ckeditor5/translations/zh-cn.js");
default:
return console.warn(`Language ${t} not found in ckeditor5 translations`), null;
}
else
switch (t) {
case "af":
return await import("ckeditor5-premium-features/translations/af.js");
case "ar":
return await import("ckeditor5-premium-features/translations/ar.js");
case "ast":
return await import("ckeditor5-premium-features/translations/ast.js");
case "az":
return await import("ckeditor5-premium-features/translations/az.js");
case "bg":
return await import("ckeditor5-premium-features/translations/bg.js");
case "bn":
return await import("ckeditor5-premium-features/translations/bn.js");
case "bs":
return await import("ckeditor5-premium-features/translations/bs.js");
case "ca":
return await import("ckeditor5-premium-features/translations/ca.js");
case "cs":
return await import("ckeditor5-premium-features/translations/cs.js");
case "da":
return await import("ckeditor5-premium-features/translations/da.js");
case "de":
return await import("ckeditor5-premium-features/translations/de.js");
case "de-ch":
return await import("ckeditor5-premium-features/translations/de-ch.js");
case "el":
return await import("ckeditor5-premium-features/translations/el.js");
case "en":
return await import("ckeditor5-premium-features/translations/en.js");
case "en-au":
return await import("ckeditor5-premium-features/translations/en-au.js");
case "en-gb":
return await import("ckeditor5-premium-features/translations/en-gb.js");
case "eo":
return await import("ckeditor5-premium-features/translations/eo.js");
case "es":
return await import("ckeditor5-premium-features/translations/es.js");
case "es-co":
return await import("ckeditor5-premium-features/translations/es-co.js");
case "et":
return await import("ckeditor5-premium-features/translations/et.js");
case "eu":
return await import("ckeditor5-premium-features/translations/eu.js");
case "fa":
return await import("ckeditor5-premium-features/translations/fa.js");
case "fi":
return await import("ckeditor5-premium-features/translations/fi.js");
case "fr":
return await import("ckeditor5-premium-features/translations/fr.js");
case "gl":
return await import("ckeditor5-premium-features/translations/gl.js");
case "gu":
return await import("ckeditor5-premium-features/translations/gu.js");
case "he":
return await import("ckeditor5-premium-features/translations/he.js");
case "hi":
return await import("ckeditor5-premium-features/translations/hi.js");
case "hr":
return await import("ckeditor5-premium-features/translations/hr.js");
case "hu":
return await import("ckeditor5-premium-features/translations/hu.js");
case "hy":
return await import("ckeditor5-premium-features/translations/hy.js");
case "id":
return await import("ckeditor5-premium-features/translations/id.js");
case "it":
return await import("ckeditor5-premium-features/translations/it.js");
case "ja":
return await import("ckeditor5-premium-features/translations/ja.js");
case "jv":
return await import("ckeditor5-premium-features/translations/jv.js");
case "kk":
return await import("ckeditor5-premium-features/translations/kk.js");
case "km":
return await import("ckeditor5-premium-features/translations/km.js");
case "kn":
return await import("ckeditor5-premium-features/translations/kn.js");
case "ko":
return await import("ckeditor5-premium-features/translations/ko.js");
case "ku":
return await import("ckeditor5-premium-features/translations/ku.js");
case "lt":
return await import("ckeditor5-premium-features/translations/lt.js");
case "lv":
return await import("ckeditor5-premium-features/translations/lv.js");
case "ms":
return await import("ckeditor5-premium-features/translations/ms.js");
case "nb":
return await import("ckeditor5-premium-features/translations/nb.js");
case "ne":
return await import("ckeditor5-premium-features/translations/ne.js");
case "nl":
return await import("ckeditor5-premium-features/translations/nl.js");
case "no":
return await import("ckeditor5-premium-features/translations/no.js");
case "oc":
return await import("ckeditor5-premium-features/translations/oc.js");
case "pl":
return await import("ckeditor5-premium-features/translations/pl.js");
case "pt":
return await import("ckeditor5-premium-features/translations/pt.js");
case "pt-br":
return await import("ckeditor5-premium-features/translations/pt-br.js");
case "ro":
return await import("ckeditor5-premium-features/translations/ro.js");
case "ru":
return await import("ckeditor5-premium-features/translations/ru.js");
case "si":
return await import("ckeditor5-premium-features/translations/si.js");
case "sk":
return await import("ckeditor5-premium-features/translations/sk.js");
case "sl":
return await import("ckeditor5-premium-features/translations/sl.js");
case "sq":
return await import("ckeditor5-premium-features/translations/sq.js");
case "sr":
return await import("ckeditor5-premium-features/translations/sr.js");
case "sr-latn":
return await import("ckeditor5-premium-features/translations/sr-latn.js");
case "sv":
return await import("ckeditor5-premium-features/translations/sv.js");
case "th":
return await import("ckeditor5-premium-features/translations/th.js");
case "tk":
return await import("ckeditor5-premium-features/translations/tk.js");
case "tr":
return await import("ckeditor5-premium-features/translations/tr.js");
case "tt":
return await import("ckeditor5-premium-features/translations/tt.js");
case "ug":
return await import("ckeditor5-premium-features/translations/ug.js");
case "uk":
return await import("ckeditor5-premium-features/translations/uk.js");
case "ur":
return await import("ckeditor5-premium-features/translations/ur.js");
case "uz":
return await import("ckeditor5-premium-features/translations/uz.js");
case "vi":
return await import("ckeditor5-premium-features/translations/vi.js");
case "zh":
return await import("ckeditor5-premium-features/translations/zh.js");
case "zh-cn":
return await import("ckeditor5-premium-features/translations/zh-cn.js");
default:
return console.warn(`Language ${t} not found in premium translations`), await import("ckeditor5-premium-features/translations/en.js");
}
} catch (e) {
return console.error(`Failed to load translation for ${a}/${t}:`, e), null;
}
}
function h(a) {
const t = document.querySelectorAll(
[
`[data-cke-editor-id="${a}"][data-cke-editable-root-name]`,
"[data-cke-editable-root-name]:not([data-cke-editor-id])"
].join(", ")
);
return Array.from(t).reduce((e, r) => {
const i = r.getAttribute("data-cke-editable-root-name"), n = r.getAttribute("data-cke-editable-initial-value") || "", o = r.querySelector("[data-cke-editable-content]");
return !i || !o ? e : {
...e,
[i]: {
content: o,
initialValue: n
}
};
}, /* @__PURE__ */ Object.create({}));
}
const A = ["inline", "classic", "balloon", "decoupled", "multiroot"];
function N(a) {
const t = a.getAttribute("cke-preset");
if (!t)
throw new Error('CKEditor5 hook requires a "cke-preset" attribute on the element.');
const { type: e, config: r, license: i } = JSON.parse(t);
if (!e || !r || !i)
throw new Error('CKEditor5 hook configuration must include "editor", "config", and "license" properties.');
if (!A.includes(e))
throw new Error(`Invalid editor type: ${e}. Must be one of: ${A.join(", ")}.`);
return {
type: e,
config: r,
license: i
};
}
function O(a, t) {
const { editing: e } = a;
e.view.change((r) => {
r.setStyle("height", `${t}px`, e.view.document.getRoot());
});
}
class x extends g {
/**
* The name of the hook.
*/
editorPromise = null;
/**
* Attributes for the editor instance.
*/
get attrs() {
const t = {
editorId: this.el.getAttribute("id"),
preset: N(this.el),
editableHeight: v(this.el.getAttribute("cke-editable-height")),
changeEvent: this.el.getAttribute("cke-change-event") !== null,
saveDebounceMs: v(this.el.getAttribute("cke-save-debounce-ms")) ?? 400,
language: {
ui: this.el.getAttribute("cke-language") || "en",
content: this.el.getAttribute("cke-content-language") || "en"
}
};
return Object.defineProperty(this, "attrs", {
value: t,
writable: !1,
configurable: !1,
enumerable: !0
}), t;
}
/**
* Mounts the editor component.
*/
async mounted() {
return this.editorPromise = this.createEditor(), u.the.register(this.attrs.editorId, await this.editorPromise), this;
}
/**
* Destroys the editor instance when the component is destroyed.
* This is important to prevent memory leaks and ensure that the editor is properly cleaned up.
*/
async destroyed() {
this.el.style.display = "none", (await this.editorPromise)?.destroy(), this.editorPromise = null, u.the.unregister(this.attrs.editorId);
}
/**
* Creates the CKEditor instance.
*/
async createEditor() {
const { preset: t, editorId: e, editableHeight: r, changeEvent: i, saveDebounceMs: n, language: o } = this.attrs, { type: s, license: l, config: { plugins: d, ...p } } = t, w = await R(s), $ = q(e, s), { loadedPlugins: C, hasPremium: V } = await S(d), E = [o.ui, o.content], y = await Promise.all(
[
P("ckeditor5", E),
/* v8 ignore next */
V && P("ckeditor5-premium-features", E)
].filter((c) => !!c)
).then((c) => c.flat()), m = await w.create(
$,
{
...p,
initialData: K(e, s),
licenseKey: l.key,
plugins: C,
language: o,
...y.length && {
translations: y
}
}
);
if (i && this.setupContentPush(e, m, n), this.handleEvent("ckeditor5:set-data", ({ data: c }) => {
m.setData(c);
}), k(s)) {
const c = document.getElementById(`${e}_input`);
c && z(c, m, n), r && O(m, r);
}
return m;
}
/**
* Setups the content push event for the editor.
*/
setupContentPush(t, e, r) {
const i = () => {
this.pushEvent(
"ckeditor5:change",
{
editorId: t,
data: U(e)
}
);
};
e.model.document.on("change:data", b(r, i)), i();
}
}
function U(a) {
return a.model.document.getRootNames().reduce((e, r) => (e[r] = a.getData({ rootName: r }), e), /* @__PURE__ */ Object.create({}));
}
function z(a, t, e) {
const r = () => {
const i = t.getData();
a.value = i, a.dispatchEvent(new Event("input", { bubbles: !0 }));
};
t.model.document.on("change:data", b(e, r)), M(a)?.addEventListener("submit", r), r();
}
function M(a) {
return a.closest("form");
}
function q(a, t) {
if (k(t))
return document.getElementById(`${a}_editor`);
const e = h(a);
return I(e, ({ content: r }) => r);
}
function K(a, t) {
if (t === "decoupled") {
const r = h(a).main?.initialValue;
if (r)
return r;
}
if (k(t))
return document.getElementById(a)?.getAttribute("cke-initial-value") || "";
const e = h(a);
return I(e, ({ initialValue: r }) => r);
}
const B = f(x);
class F extends g {
/**
* The name of the hook.
*/
mountedPromise = null;
/**
* Attributes for the editable instance.
*/
get attrs() {
const t = {
editorId: this.el.getAttribute("data-cke-editor-id") || null,
name: this.el.getAttribute("data-cke-ui-part-name")
};
return Object.defineProperty(this, "attrs", {
value: t,
writable: !1,
configurable: !1,
enumerable: !0
}), t;
}
/**
* Mounts the editable component.
*/
async mounted() {
const { editorId: t, name: e } = this.attrs;
this.mountedPromise = u.the.execute(t, (r) => {
const { ui: i } = r, n = L(e), o = i.view[n];
if (!o) {
console.error(`Unknown UI part name: "${e}". Supported names are "toolbar" and "menubar".`);
return;
}
this.el.appendChild(o.element);
});
}
/**
* Destroys the editable component. Unmounts root from the editor.
*/
async destroyed() {
this.el.style.display = "none", await this.mountedPromise, this.mountedPromise = null, this.el.innerHTML = "";
}
}
function L(a) {
switch (a) {
case "toolbar":
return "toolbar";
case "menubar":
return "menuBarView";
default:
return null;
}
}
const _ = f(F), G = {
CKEditor5: B,
CKEditable: T,
CKUIPart: _
};
export {
u as EditorsRegistry,
G as Hooks
};
//# sourceMappingURL=index.mjs.map