Current section

Files

Jump to
ckeditor5_phoenix dist index.cjs.map
Raw

dist/index.cjs.map

{"version":3,"file":"index.cjs","sources":["../src/shared/async-registry.ts","../src/shared/camel-case.ts","../src/shared/debounce.ts","../src/shared/is-plain-object.ts","../src/shared/deep-camel-case-keys.ts","../src/shared/hook.ts","../src/shared/is-empty-object.ts","../src/shared/map-object-values.ts","../src/shared/parse-int-if-not-null.ts","../src/shared/uid.ts","../src/hooks/editor/utils/create-editor-in-context.ts","../src/hooks/editor/utils/is-single-editing-like-editor.ts","../src/hooks/editor/utils/load-editor-constructor.ts","../src/hooks/editor/custom-editor-plugins.ts","../src/hooks/editor/utils/load-editor-plugins.ts","../src/hooks/editor/utils/load-editor-translations.ts","../src/hooks/editor/utils/normalize-custom-translations.ts","../src/hooks/editor/utils/query-all-editor-editables.ts","../src/hooks/editor/typings.ts","../src/hooks/editor/utils/read-preset-or-throw.ts","../src/hooks/editor/utils/resolve-editor-config-elements-references.ts","../src/hooks/editor/utils/set-editor-editable-height.ts","../src/hooks/editor/utils/wrap-with-watchdog.ts","../src/hooks/context/contexts-registry.ts","../src/hooks/context/utils/read-context-config-or-throw.ts","../src/hooks/context/context.ts","../src/hooks/editor/editors-registry.ts","../src/hooks/editable.ts","../src/hooks/editor/editor.ts","../src/hooks/ui-part.ts","../src/hooks/index.ts"],"sourcesContent":["/**\n * Generic async registry for objects with an async destroy method.\n * Provides a way to register, unregister, and execute callbacks on objects by ID.\n */\n/**\n * Generic async registry for objects with an async destroy method.\n * Provides a way to register, unregister, and execute callbacks on objects by ID.\n */\nexport class AsyncRegistry<T extends Destructible> {\n /**\n * Map of registered items.\n */\n private readonly items = new Map<RegistryId | null, T>();\n\n /**\n * Map of callbacks that are waiting for an item to be registered.\n */\n private readonly callbacks = new Map<RegistryId | null, RegistryCallback<T>[]>();\n\n /**\n * Set of watchers that observe changes to the registry.\n */\n private readonly watchers = new Set<RegistryWatcher<T>>();\n\n /**\n * Executes a function on an item.\n * If the item is not yet registered, it will wait for it to be registered.\n *\n * @param id The ID of the item.\n * @param fn The function to execute.\n * @returns A promise that resolves with the result of the function.\n */\n execute<R, E extends T = T>(id: RegistryId | null, fn: (item: E) => R): Promise<Awaited<R>> {\n const { callbacks, items } = this;\n const item = items.get(id);\n\n if (item) {\n return Promise.resolve(fn(item as E));\n }\n\n return new Promise((resolve) => {\n const callback = async (item: T) => resolve(await fn(item as E));\n\n if (!this.callbacks.has(id)) {\n callbacks.set(id, []);\n }\n\n callbacks.set(id, [\n ...callbacks.get(id)!,\n callback,\n ]);\n });\n }\n\n /**\n * Registers an item.\n *\n * @param id The ID of the item.\n * @param item The item instance.\n */\n register(id: RegistryId | null, item: T): void {\n const { items, callbacks } = this;\n const callbacksForItem = callbacks.get(id);\n\n if (items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is already registered.`);\n }\n\n items.set(id, item);\n\n if (callbacksForItem) {\n callbacksForItem.forEach(callback => callback(item));\n callbacks.delete(id);\n }\n\n // Register the first item as the default item (null ID).\n if (this.items.size === 1) {\n this.register(null, item);\n }\n\n this.notifyWatchers();\n }\n\n /**\n * Un-registers an item.\n *\n * @param id The ID of the item.\n */\n unregister(id: RegistryId | null): void {\n const { items, callbacks } = this;\n\n if (!items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is not registered.`);\n }\n\n if (id && this.items.get(null) === items.get(id)) {\n this.unregister(null);\n }\n\n items.delete(id);\n callbacks.delete(id);\n\n this.notifyWatchers();\n }\n\n /**\n * Gets all registered items.\n */\n getItems(): T[] {\n return Array.from(this.items.values());\n }\n\n /**\n * Checks if an item with the given ID is registered.\n *\n * @param id The ID of the item.\n * @returns `true` if the item is registered, `false` otherwise.\n */\n hasItem(id: RegistryId | null): boolean {\n return this.items.has(id);\n }\n\n /**\n * Gets a promise that resolves with the item instance for the given ID.\n * If the item is not registered yet, it will wait for it to be registered.\n *\n * @param id The ID of the item.\n * @returns A promise that resolves with the item instance.\n */\n waitFor<E extends T = T>(id: RegistryId | null): Promise<E> {\n return this.execute(id, item => item) as Promise<E>;\n }\n\n /**\n * Destroys all registered items and clears the registry.\n * This will call the `destroy` method on each item.\n */\n async destroyAll() {\n const promises = (\n Array\n .from(new Set(this.items.values()))\n .map(item => item.destroy())\n );\n\n this.items.clear();\n this.callbacks.clear();\n\n await Promise.all(promises);\n\n this.notifyWatchers();\n };\n\n /**\n * Registers a watcher that will be called whenever the registry changes.\n *\n * @param watcher The watcher function to register.\n * @returns A function to unregister the watcher.\n */\n watch(watcher: RegistryWatcher<T>): () => void {\n this.watchers.add(watcher);\n\n // Call the watcher immediately with the current state\n watcher(new Map(this.items));\n\n return this.unwatch.bind(this, watcher);\n }\n\n /**\n * Un-registers a watcher.\n *\n * @param watcher The watcher function to unregister.\n */\n unwatch(watcher: RegistryWatcher<T>): void {\n this.watchers.delete(watcher);\n }\n\n /**\n * Notifies all watchers about changes to the registry.\n */\n private notifyWatchers(): void {\n const itemsCopy = new Map(this.items);\n this.watchers.forEach(watcher => watcher(itemsCopy));\n }\n}\n\n/**\n * Interface for objects that can be destroyed.\n */\nexport type Destructible = {\n destroy: () => Promise<any>;\n};\n\n/**\n * Identifier of the registry item.\n */\ntype RegistryId = string;\n\n/**\n * Callback type for registry operations.\n */\ntype RegistryCallback<T> = (item: T) => void;\n\n/**\n * Callback type for watching registry changes.\n */\ntype RegistryWatcher<T> = (items: Map<RegistryId | null, T>) => void;\n","/**\n * Converts a string to camelCase.\n *\n * @param str The string to convert\n * @returns The camelCased string\n */\nexport function camelCase(str: string): string {\n return str\n .replace(/[-_\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\n .replace(/^./, m => m.toLowerCase());\n}\n","export function debounce<T extends (...args: any[]) => any>(\n delay: number,\n callback: T,\n): (...args: Parameters<T>) => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return (...args: Parameters<T>): void => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n timeoutId = setTimeout(() => {\n callback(...args);\n }, delay);\n };\n}\n","/**\n * Utility to check if a value is a plain object (not an array, not null, not a class instance).\n *\n * @param value The value to check.\n * @returns True if the value is a plain object, false otherwise.\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (Object.prototype.toString.call(value) !== '[object Object]') {\n return false;\n }\n\n const proto = Object.getPrototypeOf(value);\n\n return proto === Object.prototype || proto === null;\n}\n","import { camelCase } from './camel-case';\nimport { isPlainObject } from './is-plain-object';\n\n/**\n * Recursively converts all keys of a plain object or array to camelCase.\n * Skips class instances and leaves them untouched.\n *\n * @param input The object or array to process\n */\nexport function deepCamelCaseKeys<T>(input: T): T {\n if (Array.isArray(input)) {\n return input.map(deepCamelCaseKeys) as unknown as T;\n }\n\n if (isPlainObject(input)) {\n const result: Record<string, unknown> = Object.create(null);\n\n for (const [key, value] of Object.entries(input)) {\n result[camelCase(key)] = deepCamelCaseKeys(value);\n }\n\n return result as T;\n }\n\n return input;\n}\n","import type { Hook, LiveSocket } from 'phoenix_live_view';\n\nimport type { RequiredBy } from '../types';\n\n/**\n * An abstract class that provides a class-based API for creating Phoenix LiveView hooks.\n *\n * This class defines the structure and lifecycle methods of a hook, which can be extended\n * to implement custom client-side behavior that integrates with LiveView.\n */\nexport abstract class ClassHook {\n /**\n * The current state of the hook.\n */\n state: ClassHookState = 'mounting';\n\n /**\n * The DOM element the hook is attached to.\n * It includes an `instance` property to hold the hook instance.\n */\n el: HTMLElement & { instance: Hook; };\n\n /**\n * The LiveView socket instance, providing connection to the server.\n */\n liveSocket: LiveSocket;\n\n /**\n * Pushes an event from the client to the LiveView server process.\n * @param _event The name of the event.\n * @param _payload The data to send with the event.\n * @param _callback An optional function to be called with the server's reply.\n */\n pushEvent!: (\n _event: string,\n _payload: any,\n _callback?: (reply: any, ref: number) => void,\n ) => void;\n\n /**\n * Pushes an event to another hook on the page.\n * @param _selector The CSS selector of the target element with the hook.\n * @param _event The name of the event.\n * @param _payload The data to send with the event.\n * @param _callback An optional function to be called with the reply.\n */\n pushEventTo!: (\n _selector: string,\n _event: string,\n _payload: any,\n _callback?: (reply: any, ref: number) => void,\n ) => void;\n\n /**\n * Registers a handler for an event pushed from the server.\n * @param _event The name of the event to handle.\n * @param _callback The function to execute when the event is received.\n */\n handleEvent!: (\n _event: string,\n _callback: (payload: any) => void,\n ) => void;\n\n /**\n * Called when the hook has been mounted to the DOM.\n * This is the ideal place for initialization code.\n */\n abstract mounted(): any;\n\n /**\n * Called when the element has been removed from the DOM.\n * Perfect for cleanup tasks.\n */\n abstract destroyed(): any;\n\n /**\n * Called before the element is updated by a LiveView patch.\n */\n beforeUpdate?(): void;\n\n /**\n * Called when the client has disconnected from the server.\n */\n disconnected?(): void;\n\n /**\n * Called when the client has reconnected to the server.\n */\n reconnected?(): void;\n\n /**\n * Checks if the hook is in the process of being destroyed.\n */\n isBeingDestroyed(): boolean {\n return this.state === 'destroyed' || this.state === 'destroying';\n }\n}\n\n/**\n * A type that represents the state of a class-based hook.\n */\nexport type ClassHookState = 'mounting' | 'mounted' | 'destroying' | 'destroyed';\n\n/**\n * A factory function that adapts a class-based hook to the object-based API expected by Phoenix LiveView.\n *\n * @param constructor The constructor of the class that extends the `Hook` abstract class.\n */\nexport function makeHook(constructor: new () => ClassHook): RequiredBy<Hook<any>, 'mounted' | 'destroyed'> {\n return {\n /**\n * The mounted lifecycle callback for the LiveView hook object.\n * It creates an instance of the user-defined hook class and sets up the necessary properties and methods.\n */\n async mounted(this: any) {\n const instance = new constructor();\n\n this.el.instance = instance;\n\n instance.el = this.el;\n instance.liveSocket = this.liveSocket;\n\n instance.pushEvent = (event, payload, callback) => this.pushEvent?.(event, payload, callback);\n instance.pushEventTo = (selector, event, payload, callback) => this.pushEventTo?.(selector, event, payload, callback);\n instance.handleEvent = (event, callback) => this.handleEvent?.(event, callback);\n\n instance.state = 'mounting';\n const result = await instance.mounted?.();\n instance.state = 'mounted';\n\n return result;\n },\n\n /**\n * The beforeUpdate lifecycle callback that delegates to the hook instance.\n */\n beforeUpdate(this: any) {\n this.el.instance.beforeUpdate?.();\n },\n\n /**\n * The destroyed lifecycle callback that delegates to the hook instance.\n */\n async destroyed(this: any) {\n const { instance } = this.el;\n\n instance.state = 'destroying';\n await instance.destroyed?.();\n instance.state = 'destroyed';\n },\n\n /**\n * The disconnected lifecycle callback that delegates to the hook instance.\n */\n disconnected(this: any) {\n this.el.instance.disconnected?.();\n },\n\n /**\n * The reconnected lifecycle callback that delegates to the hook instance.\n */\n reconnected(this: any) {\n this.el.instance.reconnected?.();\n },\n };\n}\n","export function isEmptyObject(obj: Record<string, unknown>): boolean {\n return Object.keys(obj).length === 0 && obj.constructor === Object;\n}\n","/**\n * Maps the values of an object using a provided mapper function.\n *\n * @param obj The object whose values will be mapped.\n * @param mapper A function that takes a value and its key, and returns a new value.\n * @template T The type of the original values in the object.\n * @template U The type of the new values in the object.\n * @returns A new object with the same keys as the original, but with values transformed by\n */\nexport function mapObjectValues<T, U>(\n obj: Record<string, T>,\n mapper: (value: T, key: string) => U,\n): Record<string, U> {\n const mappedEntries = Object\n .entries(obj)\n .map(([key, value]) => [key, mapper(value, key)] as const);\n\n return Object.fromEntries(mappedEntries);\n}\n","export function parseIntIfNotNull(value: string | null): number | null {\n if (value === null) {\n return null;\n }\n\n const parsed = Number.parseInt(value, 10);\n\n return Number.isNaN(parsed) ? null : parsed;\n}\n","/**\n * Generates a unique identifier string\n *\n * @returns Random string that can be used as unique identifier\n */\nexport function uid() {\n return Math.random().toString(36).substring(2);\n}\n","import type { Context, ContextWatchdog, Editor, EditorConfig } from 'ckeditor5';\n\nimport type { EditorCreator } from './wrap-with-watchdog';\n\nimport { uid } from '../../../shared';\n\n/**\n * Symbol used to store the context watchdog on the editor instance.\n * Internal use only.\n */\nconst CONTEXT_EDITOR_WATCHDOG_SYMBOL = Symbol.for('context-editor-watchdog');\n\n/**\n * Creates a CKEditor 5 editor instance within a given context watchdog.\n *\n * @param params Parameters for editor creation.\n * @param params.element The DOM element or data for the editor.\n * @param params.context The context watchdog instance.\n * @param params.creator The editor creator utility.\n * @param params.config The editor configuration object.\n * @returns The created editor instance.\n */\nexport async function createEditorInContext({ element, context, creator, config }: Attrs) {\n const editorContextId = uid();\n\n await context.add({\n creator: (_element, _config) => creator.create(_element, _config),\n id: editorContextId,\n sourceElementOrData: element,\n type: 'editor',\n config,\n });\n\n const editor = context.getItem(editorContextId) as Editor;\n const contextDescriptor: EditorContextDescriptor = {\n state: 'available',\n editorContextId,\n context,\n };\n\n (editor as any)[CONTEXT_EDITOR_WATCHDOG_SYMBOL] = contextDescriptor;\n\n // Destroying of context is async. There can be situation when the destroy of the context\n // and the destroy of the editor is called in parallel. It often happens during unmounting of\n // phoenix hooks. Let's make sure that descriptor informs other components, that context is being\n // destroyed.\n const originalDestroy = context.destroy.bind(context);\n context.destroy = async () => {\n contextDescriptor.state = 'unavailable';\n return originalDestroy();\n };\n\n return {\n ...contextDescriptor,\n editor,\n };\n}\n\n/**\n * Retrieves the context watchdog from an editor instance, if available.\n *\n * @param editor The editor instance.\n * @returns The context watchdog or null if not found.\n */\nexport function unwrapEditorContext(editor: Editor): EditorContextDescriptor | null {\n if (CONTEXT_EDITOR_WATCHDOG_SYMBOL in editor) {\n return (editor as any)[CONTEXT_EDITOR_WATCHDOG_SYMBOL];\n }\n\n return null;\n}\n\n/**\n * Parameters for creating an editor in a context.\n */\ntype Attrs = {\n context: ContextWatchdog<Context>;\n creator: EditorCreator;\n element: HTMLElement;\n config: EditorConfig;\n};\n\n/**\n * Descriptor for an editor context.\n */\ntype EditorContextDescriptor = {\n state: 'available' | 'unavailable';\n editorContextId: string;\n context: ContextWatchdog<Context>;\n};\n","import type { EditorType } from '../typings';\n\n/**\n * Checks if the given editor type is one of the single editing-like editors.\n *\n * @param editorType - The type of the editor to check.\n * @returns `true` if the editor type is 'inline', 'classic', or 'balloon', otherwise `false`.\n */\nexport function isSingleEditingLikeEditor(editorType: EditorType): boolean {\n return ['inline', 'classic', 'balloon', 'decoupled'].includes(editorType);\n}\n","import type { EditorType } from '../typings';\n\n/**\n * Returns the constructor for the specified CKEditor5 editor type.\n *\n * @param type - The type of the editor to load.\n * @returns A promise that resolves to the editor constructor.\n */\nexport async function loadEditorConstructor(type: EditorType) {\n const PKG = await import('ckeditor5');\n\n const editorMap = {\n inline: PKG.InlineEditor,\n balloon: PKG.BalloonEditor,\n classic: PKG.ClassicEditor,\n decoupled: PKG.DecoupledEditor,\n multiroot: PKG.MultiRootEditor,\n } as const;\n\n const EditorConstructor = editorMap[type];\n\n if (!EditorConstructor) {\n throw new Error(`Unsupported editor type: ${type}`);\n }\n\n return EditorConstructor;\n}\n","import type { PluginConstructor } from 'ckeditor5';\n\nimport type { CanBePromise } from '../../types';\n\ntype PluginReader = () => CanBePromise<PluginConstructor>;\n\n/**\n * Registry for custom CKEditor plugins.\n * Allows registration and retrieval of custom plugins that can be used alongside built-in plugins.\n */\nexport class CustomEditorPluginsRegistry {\n static readonly the = new CustomEditorPluginsRegistry();\n\n /**\n * Map of registered custom plugins.\n */\n private readonly plugins = new Map<string, PluginReader>();\n\n /**\n * Private constructor to enforce singleton pattern.\n */\n private constructor() {}\n\n /**\n * Registers a custom plugin for the CKEditor.\n *\n * @param name The name of the plugin.\n * @param reader The plugin reader function that returns the plugin constructor.\n * @returns A function to unregister the plugin.\n */\n register(name: string, reader: PluginReader): () => void {\n if (this.plugins.has(name)) {\n throw new Error(`Plugin with name \"${name}\" is already registered.`);\n }\n\n this.plugins.set(name, reader);\n\n return this.unregister.bind(this, name);\n }\n\n /**\n * Removes a custom plugin by its name.\n *\n * @param name The name of the plugin to unregister.\n * @throws Will throw an error if the plugin is not registered.\n */\n unregister(name: string): void {\n if (!this.plugins.has(name)) {\n throw new Error(`Plugin with name \"${name}\" is not registered.`);\n }\n\n this.plugins.delete(name);\n }\n\n /**\n * Removes all custom editor plugins.\n * This is useful for cleanup in tests or when reloading plugins.\n */\n unregisterAll(): void {\n this.plugins.clear();\n }\n\n /**\n * Retrieves a custom plugin by its name.\n *\n * @param name The name of the plugin.\n * @returns The plugin constructor or undefined if not found.\n */\n async get(name: string): Promise<PluginConstructor | undefined> {\n const reader = this.plugins.get(name);\n\n return reader?.();\n }\n\n /**\n * Checks if a plugin with the given name is registered.\n *\n * @param name The name of the plugin.\n * @returns `true` if the plugin is registered, `false` otherwise.\n */\n has(name: string): boolean {\n return this.plugins.has(name);\n }\n}\n","import type { PluginConstructor } from 'ckeditor5';\n\nimport type { EditorPlugin } from '../typings';\n\nimport { CustomEditorPluginsRegistry } from '../custom-editor-plugins';\n\n/**\n * Loads CKEditor plugins from base and premium packages.\n * First tries to load from the base 'ckeditor5' package, then falls back to 'ckeditor5-premium-features'.\n *\n * @param plugins - Array of plugin names to load\n * @returns Promise that resolves to an array of loaded Plugin instances\n * @throws Error if a plugin is not found in either package\n */\nexport async function loadEditorPlugins(plugins: EditorPlugin[]): Promise<LoadedPlugins> {\n const basePackage = await import('ckeditor5');\n let premiumPackage: Record<string, any> | null = null;\n\n const loaders = plugins.map(async (plugin) => {\n // Let's first try to load the plugin from the base package.\n // Coverage is disabled due to Vitest issues with mocking dynamic imports.\n\n // If the plugin is not found in the base package, try custom plugins.\n const customPlugin = await CustomEditorPluginsRegistry.the.get(plugin);\n\n if (customPlugin) {\n return customPlugin;\n }\n\n // If not found, try to load from the base package.\n const { [plugin]: basePkgImport } = basePackage as Record<string, unknown>;\n\n if (basePkgImport) {\n return basePkgImport as PluginConstructor;\n }\n\n // Plugin not found in base package, try premium package.\n if (!premiumPackage) {\n try {\n premiumPackage = await import('ckeditor5-premium-features');\n /* v8 ignore next 6 */\n }\n catch (error) {\n console.error(`Failed to load premium package: ${error}`);\n }\n }\n\n /* v8 ignore next */\n const { [plugin]: premiumPkgImport } = premiumPackage || {};\n\n if (premiumPkgImport) {\n return premiumPkgImport as PluginConstructor;\n }\n\n // Plugin not found in either package, throw an error.\n throw new Error(`Plugin \"${plugin}\" not found in base or premium packages.`);\n });\n\n return {\n loadedPlugins: await Promise.all(loaders),\n hasPremium: !!premiumPackage,\n };\n}\n\n/**\n * Type representing the loaded plugins and whether premium features are available.\n */\ntype LoadedPlugins = {\n loadedPlugins: PluginConstructor<any>[];\n hasPremium: boolean;\n};\n","/**\n * Loads all required translations for the editor based on the language configuration.\n *\n * @param language - The language configuration object containing UI and content language codes.\n * @param language.ui - The UI language code.\n * @param language.content - The content language code.\n * @param hasPremium - Whether premium features are enabled and premium translations should be loaded.\n * @returns A promise that resolves to an array of loaded translation objects.\n */\nexport async function loadAllEditorTranslations(\n language: { ui: string; content: string; },\n hasPremium: boolean,\n) {\n const translations = [language.ui, language.content];\n const loadedTranslations = await Promise.all(\n [\n loadEditorPkgTranslations('ckeditor5', translations),\n /* v8 ignore next */\n hasPremium && loadEditorPkgTranslations('ckeditor5-premium-features', translations),\n ].filter(pkg => !!pkg),\n )\n .then(translations => translations.flat());\n\n return loadedTranslations;\n}\n\n/**\n * Loads the editor translations for the given languages.\n *\n * Make sure this function is properly compiled and bundled in self hosted environments!\n *\n * @param pkg - The package to load translations from ('ckeditor5' or 'ckeditor5-premium-features').\n * @param translations - The list of language codes to load translations for.\n * @returns A promise that resolves to an array of loaded translation packs.\n */\nasync function loadEditorPkgTranslations(\n pkg: EditorPkgName,\n translations: string[],\n) {\n /* v8 ignore next */\n return await Promise.all(\n translations\n .filter(lang => lang !== 'en') // 'en' is the default language, no need to load it.\n .map(async (lang) => {\n const pack = await loadEditorTranslation(pkg, lang);\n\n /* v8 ignore next */\n return pack?.default ?? pack;\n })\n .filter(Boolean),\n );\n}\n\n/**\n * Type representing the package name for CKEditor 5.\n */\ntype EditorPkgName = 'ckeditor5' | 'ckeditor5-premium-features';\n\n/**\n * Load translation for CKEditor 5\n * @param pkg - Package type: 'ckeditor5' or 'premium'\n * @param lang - Language code (e.g., 'pl', 'en', 'de')\n * @returns Translation object or null if failed\n */\nasync function loadEditorTranslation(pkg: EditorPkgName, lang: string): Promise<any> {\n try {\n /* v8 ignore next 2 */\n if (pkg === 'ckeditor5') {\n /* v8 ignore next 79 */\n switch (lang) {\n case 'af': return await import('ckeditor5/translations/af.js');\n case 'ar': return await import('ckeditor5/translations/ar.js');\n case 'ast': return await import('ckeditor5/translations/ast.js');\n case 'az': return await import('ckeditor5/translations/az.js');\n case 'bg': return await import('ckeditor5/translations/bg.js');\n case 'bn': return await import('ckeditor5/translations/bn.js');\n case 'bs': return await import('ckeditor5/translations/bs.js');\n case 'ca': return await import('ckeditor5/translations/ca.js');\n case 'cs': return await import('ckeditor5/translations/cs.js');\n case 'da': return await import('ckeditor5/translations/da.js');\n case 'de': return await import('ckeditor5/translations/de.js');\n case 'de-ch': return await import('ckeditor5/translations/de-ch.js');\n case 'el': return await import('ckeditor5/translations/el.js');\n case 'en': return await import('ckeditor5/translations/en.js');\n case 'en-au': return await import('ckeditor5/translations/en-au.js');\n case 'en-gb': return await import('ckeditor5/translations/en-gb.js');\n case 'eo': return await import('ckeditor5/translations/eo.js');\n case 'es': return await import('ckeditor5/translations/es.js');\n case 'es-co': return await import('ckeditor5/translations/es-co.js');\n case 'et': return await import('ckeditor5/translations/et.js');\n case 'eu': return await import('ckeditor5/translations/eu.js');\n case 'fa': return await import('ckeditor5/translations/fa.js');\n case 'fi': return await import('ckeditor5/translations/fi.js');\n case 'fr': return await import('ckeditor5/translations/fr.js');\n case 'gl': return await import('ckeditor5/translations/gl.js');\n case 'gu': return await import('ckeditor5/translations/gu.js');\n case 'he': return await import('ckeditor5/translations/he.js');\n case 'hi': return await import('ckeditor5/translations/hi.js');\n case 'hr': return await import('ckeditor5/translations/hr.js');\n case 'hu': return await import('ckeditor5/translations/hu.js');\n case 'hy': return await import('ckeditor5/translations/hy.js');\n case 'id': return await import('ckeditor5/translations/id.js');\n case 'it': return await import('ckeditor5/translations/it.js');\n case 'ja': return await import('ckeditor5/translations/ja.js');\n case 'jv': return await import('ckeditor5/translations/jv.js');\n case 'kk': return await import('ckeditor5/translations/kk.js');\n case 'km': return await import('ckeditor5/translations/km.js');\n case 'kn': return await import('ckeditor5/translations/kn.js');\n case 'ko': return await import('ckeditor5/translations/ko.js');\n case 'ku': return await import('ckeditor5/translations/ku.js');\n case 'lt': return await import('ckeditor5/translations/lt.js');\n case 'lv': return await import('ckeditor5/translations/lv.js');\n case 'ms': return await import('ckeditor5/translations/ms.js');\n case 'nb': return await import('ckeditor5/translations/nb.js');\n case 'ne': return await import('ckeditor5/translations/ne.js');\n case 'nl': return await import('ckeditor5/translations/nl.js');\n case 'no': return await import('ckeditor5/translations/no.js');\n case 'oc': return await import('ckeditor5/translations/oc.js');\n case 'pl': return await import('ckeditor5/translations/pl.js');\n case 'pt': return await import('ckeditor5/translations/pt.js');\n case 'pt-br': return await import('ckeditor5/translations/pt-br.js');\n case 'ro': return await import('ckeditor5/translations/ro.js');\n case 'ru': return await import('ckeditor5/translations/ru.js');\n case 'si': return await import('ckeditor5/translations/si.js');\n case 'sk': return await import('ckeditor5/translations/sk.js');\n case 'sl': return await import('ckeditor5/translations/sl.js');\n case 'sq': return await import('ckeditor5/translations/sq.js');\n case 'sr': return await import('ckeditor5/translations/sr.js');\n case 'sr-latn': return await import('ckeditor5/translations/sr-latn.js');\n case 'sv': return await import('ckeditor5/translations/sv.js');\n case 'th': return await import('ckeditor5/translations/th.js');\n case 'tk': return await import('ckeditor5/translations/tk.js');\n case 'tr': return await import('ckeditor5/translations/tr.js');\n case 'tt': return await import('ckeditor5/translations/tt.js');\n case 'ug': return await import('ckeditor5/translations/ug.js');\n case 'uk': return await import('ckeditor5/translations/uk.js');\n case 'ur': return await import('ckeditor5/translations/ur.js');\n case 'uz': return await import('ckeditor5/translations/uz.js');\n case 'vi': return await import('ckeditor5/translations/vi.js');\n case 'zh': return await import('ckeditor5/translations/zh.js');\n case 'zh-cn': return await import('ckeditor5/translations/zh-cn.js');\n default:\n console.warn(`Language ${lang} not found in ckeditor5 translations`);\n return null;\n }\n }\n /* v8 ignore next 79 */\n else {\n // Premium features translations\n switch (lang) {\n case 'af': return await import('ckeditor5-premium-features/translations/af.js');\n case 'ar': return await import('ckeditor5-premium-features/translations/ar.js');\n case 'ast': return await import('ckeditor5-premium-features/translations/ast.js');\n case 'az': return await import('ckeditor5-premium-features/translations/az.js');\n case 'bg': return await import('ckeditor5-premium-features/translations/bg.js');\n case 'bn': return await import('ckeditor5-premium-features/translations/bn.js');\n case 'bs': return await import('ckeditor5-premium-features/translations/bs.js');\n case 'ca': return await import('ckeditor5-premium-features/translations/ca.js');\n case 'cs': return await import('ckeditor5-premium-features/translations/cs.js');\n case 'da': return await import('ckeditor5-premium-features/translations/da.js');\n case 'de': return await import('ckeditor5-premium-features/translations/de.js');\n case 'de-ch': return await import('ckeditor5-premium-features/translations/de-ch.js');\n case 'el': return await import('ckeditor5-premium-features/translations/el.js');\n case 'en': return await import('ckeditor5-premium-features/translations/en.js');\n case 'en-au': return await import('ckeditor5-premium-features/translations/en-au.js');\n case 'en-gb': return await import('ckeditor5-premium-features/translations/en-gb.js');\n case 'eo': return await import('ckeditor5-premium-features/translations/eo.js');\n case 'es': return await import('ckeditor5-premium-features/translations/es.js');\n case 'es-co': return await import('ckeditor5-premium-features/translations/es-co.js');\n case 'et': return await import('ckeditor5-premium-features/translations/et.js');\n case 'eu': return await import('ckeditor5-premium-features/translations/eu.js');\n case 'fa': return await import('ckeditor5-premium-features/translations/fa.js');\n case 'fi': return await import('ckeditor5-premium-features/translations/fi.js');\n case 'fr': return await import('ckeditor5-premium-features/translations/fr.js');\n case 'gl': return await import('ckeditor5-premium-features/translations/gl.js');\n case 'gu': return await import('ckeditor5-premium-features/translations/gu.js');\n case 'he': return await import('ckeditor5-premium-features/translations/he.js');\n case 'hi': return await import('ckeditor5-premium-features/translations/hi.js');\n case 'hr': return await import('ckeditor5-premium-features/translations/hr.js');\n case 'hu': return await import('ckeditor5-premium-features/translations/hu.js');\n case 'hy': return await import('ckeditor5-premium-features/translations/hy.js');\n case 'id': return await import('ckeditor5-premium-features/translations/id.js');\n case 'it': return await import('ckeditor5-premium-features/translations/it.js');\n case 'ja': return await import('ckeditor5-premium-features/translations/ja.js');\n case 'jv': return await import('ckeditor5-premium-features/translations/jv.js');\n case 'kk': return await import('ckeditor5-premium-features/translations/kk.js');\n case 'km': return await import('ckeditor5-premium-features/translations/km.js');\n case 'kn': return await import('ckeditor5-premium-features/translations/kn.js');\n case 'ko': return await import('ckeditor5-premium-features/translations/ko.js');\n case 'ku': return await import('ckeditor5-premium-features/translations/ku.js');\n case 'lt': return await import('ckeditor5-premium-features/translations/lt.js');\n case 'lv': return await import('ckeditor5-premium-features/translations/lv.js');\n case 'ms': return await import('ckeditor5-premium-features/translations/ms.js');\n case 'nb': return await import('ckeditor5-premium-features/translations/nb.js');\n case 'ne': return await import('ckeditor5-premium-features/translations/ne.js');\n case 'nl': return await import('ckeditor5-premium-features/translations/nl.js');\n case 'no': return await import('ckeditor5-premium-features/translations/no.js');\n case 'oc': return await import('ckeditor5-premium-features/translations/oc.js');\n case 'pl': return await import('ckeditor5-premium-features/translations/pl.js');\n case 'pt': return await import('ckeditor5-premium-features/translations/pt.js');\n case 'pt-br': return await import('ckeditor5-premium-features/translations/pt-br.js');\n case 'ro': return await import('ckeditor5-premium-features/translations/ro.js');\n case 'ru': return await import('ckeditor5-premium-features/translations/ru.js');\n case 'si': return await import('ckeditor5-premium-features/translations/si.js');\n case 'sk': return await import('ckeditor5-premium-features/translations/sk.js');\n case 'sl': return await import('ckeditor5-premium-features/translations/sl.js');\n case 'sq': return await import('ckeditor5-premium-features/translations/sq.js');\n case 'sr': return await import('ckeditor5-premium-features/translations/sr.js');\n case 'sr-latn': return await import('ckeditor5-premium-features/translations/sr-latn.js');\n case 'sv': return await import('ckeditor5-premium-features/translations/sv.js');\n case 'th': return await import('ckeditor5-premium-features/translations/th.js');\n case 'tk': return await import('ckeditor5-premium-features/translations/tk.js');\n case 'tr': return await import('ckeditor5-premium-features/translations/tr.js');\n case 'tt': return await import('ckeditor5-premium-features/translations/tt.js');\n case 'ug': return await import('ckeditor5-premium-features/translations/ug.js');\n case 'uk': return await import('ckeditor5-premium-features/translations/uk.js');\n case 'ur': return await import('ckeditor5-premium-features/translations/ur.js');\n case 'uz': return await import('ckeditor5-premium-features/translations/uz.js');\n case 'vi': return await import('ckeditor5-premium-features/translations/vi.js');\n case 'zh': return await import('ckeditor5-premium-features/translations/zh.js');\n case 'zh-cn': return await import('ckeditor5-premium-features/translations/zh-cn.js');\n default:\n console.warn(`Language ${lang} not found in premium translations`);\n return await import('ckeditor5-premium-features/translations/en.js'); // fallback to English\n }\n }\n /* v8 ignore next 7 */\n }\n catch (error) {\n console.error(`Failed to load translation for ${pkg}/${lang}:`, error);\n return null;\n }\n}\n","import type { Translations } from 'ckeditor5';\n\nimport type { EditorCustomTranslationsDictionary } from '../typings';\n\nimport { mapObjectValues } from '../../../shared';\n\n/**\n * This function takes a custom translations object and maps it to the format expected by CKEditor5.\n * Each translation dictionary is wrapped in an object with a `dictionary` key.\n *\n * @param translations - The custom translations to normalize.\n * @returns A normalized translations object suitable for CKEditor5.\n */\nexport function normalizeCustomTranslations(translations: EditorCustomTranslationsDictionary): Translations {\n return mapObjectValues(translations, dictionary => ({\n dictionary,\n }));\n}\n","import type { EditorId } from '../typings';\n\n/**\n * Queries all editable elements within a specific editor instance.\n *\n * @param editorId The ID of the editor to query.\n * @returns An object mapping editable names to their corresponding elements and initial values.\n */\nexport function queryAllEditorEditables(editorId: EditorId): Record<string, EditableItem> {\n const iterator = document.querySelectorAll<HTMLElement>(\n [\n `[data-cke-editor-id=\"${editorId}\"][data-cke-editable-root-name]`,\n '[data-cke-editable-root-name]:not([data-cke-editor-id])',\n ]\n .join(', '),\n );\n\n return (\n Array\n .from(iterator)\n .reduce<Record<string, EditableItem>>((acc, element) => {\n const name = element.getAttribute('data-cke-editable-root-name');\n const initialValue = element.getAttribute('data-cke-editable-initial-value') || '';\n const content = element.querySelector('[data-cke-editable-content]') as HTMLElement;\n\n if (!name || !content) {\n return acc;\n }\n\n return {\n ...acc,\n [name]: {\n content,\n initialValue,\n },\n };\n }, Object.create({}))\n );\n}\n\n/**\n * Type representing an editable item within an editor.\n */\nexport type EditableItem = {\n content: HTMLElement;\n initialValue: string;\n};\n","/**\n * List of supported CKEditor5 editor types.\n */\nexport const EDITOR_TYPES = ['inline', 'classic', 'balloon', 'decoupled', 'multiroot'] as const;\n\n/**\n * Represents a unique identifier for a CKEditor5 editor instance.\n * This is typically the ID of the HTML element that the editor is attached to.\n */\nexport type EditorId = string;\n\n/**\n * Defines editor type supported by CKEditor5. It must match list of available\n * editor types specified in `preset/parser.ex` file.\n */\nexport type EditorType = (typeof EDITOR_TYPES)[number];\n\n/**\n * Represents a CKEditor5 plugin as a string identifier.\n */\nexport type EditorPlugin = string;\n\n/**\n * Configuration object for CKEditor5 editor instance.\n */\nexport type EditorConfig = {\n /**\n * Array of plugin identifiers to be loaded by the editor.\n */\n plugins: EditorPlugin[];\n\n /**\n * Other configuration options are flexible and can be any key-value pairs.\n */\n [key: string]: any;\n};\n\n/**\n * Represents a license key for CKEditor5.\n */\nexport type EditorLicense = {\n key: string;\n};\n\n/**\n * Configuration object for the CKEditor5 hook.\n */\nexport type EditorPreset = {\n /**\n * The type of CKEditor5 editor to use.\n * Must be one of the predefined types: 'inline', 'classic', 'balloon', 'decoupled', or 'multiroot'.\n */\n type: EditorType;\n\n /**\n * The configuration object for the CKEditor5 editor.\n * This should match the configuration expected by CKEditor5.\n */\n config: EditorConfig;\n\n /**\n * The license key for CKEditor5.\n * This is required for using CKEditor5 with a valid license.\n */\n license: EditorLicense;\n\n /**\n * Optional custom translations for the editor.\n * This allows for localization of the editor interface.\n */\n customTranslations?: {\n dictionary: EditorCustomTranslationsDictionary;\n };\n};\n\n/**\n * Represents custom translations for the editor.\n */\nexport type EditorCustomTranslationsDictionary = {\n [language: string]: {\n [key: string]: string | ReadonlyArray<string>;\n };\n};\n","import type { EditorPreset } from '../typings';\n\nimport { deepCamelCaseKeys } from '../../../shared/deep-camel-case-keys';\nimport { EDITOR_TYPES } from '../typings';\n\n/**\n * Reads the hook configuration from the element's attribute and parses it as JSON.\n *\n * @param element - The HTML element that contains the hook configuration.\n * @returns The parsed hook configuration.\n */\nexport function readPresetOrThrow(element: HTMLElement): EditorPreset {\n const attributeValue = element.getAttribute('cke-preset');\n\n if (!attributeValue) {\n throw new Error('CKEditor5 hook requires a \"cke-preset\" attribute on the element.');\n }\n\n const { type, config, license, ...rest } = JSON.parse(attributeValue);\n\n if (!type || !config || !license) {\n throw new Error('CKEditor5 hook configuration must include \"editor\", \"config\", and \"license\" properties.');\n }\n\n if (!EDITOR_TYPES.includes(type)) {\n throw new Error(`Invalid editor type: ${type}. Must be one of: ${EDITOR_TYPES.join(', ')}.`);\n }\n\n return {\n type,\n license,\n config: deepCamelCaseKeys(config),\n customTranslations: rest.customTranslations || rest.custom_translations,\n };\n}\n","/**\n * Resolves element references in configuration object.\n * Looks for objects with { $element: \"selector\" } format and replaces them with actual DOM elements.\n *\n * @param obj - Configuration object to process\n * @returns Processed configuration object with resolved element references\n */\nexport function resolveEditorConfigElementReferences<T>(obj: T): T {\n if (!obj || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => resolveEditorConfigElementReferences(item)) as T;\n }\n\n const anyObj = obj as any;\n\n if (anyObj.$element && typeof anyObj.$element === 'string') {\n const element = document.querySelector(anyObj.$element);\n\n if (!element) {\n console.warn(`Element not found for selector: ${anyObj.$element}`);\n }\n\n return (element || null) as T;\n }\n\n const result = Object.create(null);\n\n for (const [key, value] of Object.entries(obj)) {\n result[key] = resolveEditorConfigElementReferences(value);\n }\n\n return result as T;\n}\n","import type { Editor } from 'ckeditor5';\n\n/**\n * Sets the height of the editable area in the CKEditor instance.\n *\n * @param instance - The CKEditor instance to modify.\n * @param height - The height in pixels to set for the editable area.\n */\nexport function setEditorEditableHeight(instance: Editor, height: number): void {\n const { editing } = instance;\n\n editing.view.change((writer) => {\n writer.setStyle('height', `${height}px`, editing.view.document.getRoot()!);\n });\n}\n","import type { Editor, EditorWatchdog } from 'ckeditor5';\n\nconst EDITOR_WATCHDOG_SYMBOL = Symbol.for('elixir-editor-watchdog');\n\n/**\n * Wraps an Editor creator with a watchdog for automatic recovery.\n *\n * @param Editor - The Editor creator to wrap.\n * @returns The Editor creator wrapped with a watchdog.\n */\nexport async function wrapWithWatchdog(Editor: EditorCreator) {\n const { EditorWatchdog } = await import('ckeditor5');\n const watchdog = new EditorWatchdog(Editor);\n\n watchdog.setCreator(async (...args: Parameters<typeof Editor['create']>) => {\n const editor = await Editor.create(...args);\n\n (editor as any)[EDITOR_WATCHDOG_SYMBOL] = watchdog;\n\n return editor;\n });\n\n return {\n watchdog,\n Constructor: {\n create: async (...args: Parameters<typeof Editor['create']>) => {\n await watchdog.create(...args);\n\n return watchdog.editor!;\n },\n },\n };\n}\n\n/**\n * Unwraps the EditorWatchdog from the editor instance.\n */\nexport function unwrapEditorWatchdog(editor: Editor): EditorWatchdog | null {\n if (EDITOR_WATCHDOG_SYMBOL in editor) {\n return (editor as any)[EDITOR_WATCHDOG_SYMBOL] as EditorWatchdog;\n }\n\n return null;\n}\n\n/**\n * Type representing an Editor creator with a create method.\n */\nexport type EditorCreator = {\n create: (...args: any) => Promise<Editor>;\n};\n","import type { Context, ContextWatchdog } from 'ckeditor5';\n\nimport { AsyncRegistry } from '../../shared';\n\n/**\n * It provides a way to register contexts and execute callbacks on them when they are available.\n */\nexport class ContextsRegistry extends AsyncRegistry<ContextWatchdog<Context>> {\n static readonly the = new ContextsRegistry();\n}\n","import type { ContextConfig } from '../typings';\n\nimport { deepCamelCaseKeys } from '../../../shared/deep-camel-case-keys';\n\n/**\n * Reads the hook configuration from the element's attribute and parses it as JSON.\n *\n * @param element - The HTML element that contains the hook configuration.\n * @returns The parsed hook configuration.\n */\nexport function readContextConfigOrThrow(element: HTMLElement): ContextConfig {\n const attributeValue = element.getAttribute('cke-context');\n\n if (!attributeValue) {\n throw new Error('CKEditor5 hook requires a \"cke-context\" attribute on the element.');\n }\n\n const { config, ...rest } = JSON.parse(attributeValue);\n\n return {\n config: deepCamelCaseKeys(config),\n customTranslations: rest.customTranslations || rest.custom_translations,\n watchdogConfig: rest.watchdogConfig || rest.watchdog_config,\n };\n}\n","import type { Context, ContextWatchdog } from 'ckeditor5';\n\nimport { ClassHook, isEmptyObject, makeHook } from '../../shared';\nimport {\n loadAllEditorTranslations,\n loadEditorPlugins,\n normalizeCustomTranslations,\n} from '../editor/utils';\nimport { ContextsRegistry } from './contexts-registry';\nimport { readContextConfigOrThrow } from './utils';\n\n/**\n * Context hook for Phoenix LiveView. It allows you to create contexts for collaboration editors.\n */\nclass ContextHookImpl extends ClassHook {\n /**\n * The promise that resolves to the context instance.\n */\n private contextPromise: Promise<ContextWatchdog<Context>> | null = null;\n\n /**\n * Attributes for the context instance.\n */\n private get attrs() {\n const get = (attr: string) => this.el.getAttribute(attr) || null;\n const value = {\n id: this.el.id,\n config: readContextConfigOrThrow(this.el),\n language: {\n ui: get('cke-language') || 'en',\n content: get('cke-content-language') || 'en',\n },\n };\n\n Object.defineProperty(this, 'attrs', {\n value,\n writable: false,\n configurable: false,\n enumerable: true,\n });\n\n return value;\n }\n\n /**\n * Mounts the context component.\n */\n override async mounted() {\n const { id, language } = this.attrs;\n const { customTranslations, watchdogConfig, config: { plugins, ...config } } = this.attrs.config;\n const { loadedPlugins, hasPremium } = await loadEditorPlugins(plugins ?? []);\n\n // Mix custom translations with loaded translations.\n const loadedTranslations = await loadAllEditorTranslations(language, hasPremium);\n const mixedTranslations = [\n ...loadedTranslations,\n normalizeCustomTranslations(customTranslations?.dictionary || {}),\n ]\n .filter(translations => !isEmptyObject(translations));\n\n // Initialize context.\n this.contextPromise = (async () => {\n const { ContextWatchdog, Context } = await import('ckeditor5');\n const instance = new ContextWatchdog(Context, {\n crashNumberLimit: 10,\n ...watchdogConfig,\n });\n\n await instance.create({\n ...config,\n language,\n plugins: loadedPlugins,\n ...mixedTranslations.length && {\n translations: mixedTranslations,\n },\n });\n\n instance.on('itemError', (...args) => {\n console.error('Context item error:', ...args);\n });\n\n return instance;\n })();\n\n const context = await this.contextPromise;\n\n if (!this.isBeingDestroyed()) {\n ContextsRegistry.the.register(id, context);\n }\n }\n\n /**\n * Destroys the context component. Unmounts root from the editor.\n */\n override async destroyed() {\n const { id } = this.attrs;\n\n // Let's hide the element during destruction to prevent flickering.\n this.el.style.display = 'none';\n\n // Let's wait for the mounted promise to resolve before proceeding with destruction.\n try {\n const context = await this.contextPromise;\n\n await context?.destroy();\n }\n finally {\n this.contextPromise = null;\n\n if (ContextsRegistry.the.hasItem(id)) {\n ContextsRegistry.the.unregister(id);\n }\n }\n }\n}\n\n/**\n * Type guard to check if an element is a context hook HTMLElement.\n */\nfunction isContextHookHTMLElement(el: HTMLElement): el is HTMLElement & { instance: ContextHookImpl; } {\n return el.hasAttribute('cke-context');\n}\n\n/**\n * Gets the nearest context hook parent element.\n */\nfunction getNearestContextParent(el: HTMLElement) {\n let parent: HTMLElement | null = el;\n\n while (parent) {\n if (isContextHookHTMLElement(parent)) {\n return parent;\n }\n\n parent = parent.parentElement;\n }\n\n return null;\n}\n\n/**\n * Gets the nearest context parent element as a promise.\n */\nexport async function getNearestContextParentPromise(el: HTMLElement): Promise<ContextWatchdog<Context> | null> {\n const parent = getNearestContextParent(el);\n\n if (!parent) {\n return null;\n }\n\n return ContextsRegistry.the.waitFor(parent.id);\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5 context elements.\n */\nexport const ContextHook = makeHook(ContextHookImpl);\n","import type { Editor } from 'ckeditor5';\n\nimport { AsyncRegistry } from '../../shared/async-registry';\n\n/**\n * It provides a way to register editors and execute callbacks on them when they are available.\n */\nexport class EditorsRegistry extends AsyncRegistry<Editor> {\n static readonly the = new EditorsRegistry();\n}\n","import type { MultiRootEditor } from 'ckeditor5';\n\nimport { ClassHook, debounce, makeHook } from '../shared';\nimport { EditorsRegistry } from './editor/editors-registry';\n\n/**\n * Editable hook for Phoenix LiveView. It allows you to create editables for multi-root editors.\n */\nclass EditableHookImpl extends ClassHook {\n /**\n * The name of the hook.\n */\n private editorPromise: Promise<MultiRootEditor> | null = null;\n\n /**\n * Attributes for the editable instance.\n */\n private get attrs() {\n const value = {\n editableId: this.el.getAttribute('id')!,\n editorId: this.el.getAttribute('data-cke-editor-id') || null,\n rootName: this.el.getAttribute('data-cke-editable-root-name')!,\n initialValue: this.el.getAttribute('data-cke-editable-initial-value') || '',\n };\n\n Object.defineProperty(this, 'attrs', {\n value,\n writable: false,\n configurable: false,\n enumerable: true,\n });\n\n return value;\n }\n\n /**\n * Mounts the editable component.\n */\n override async mounted() {\n const { editableId, editorId, rootName, initialValue } = this.attrs;\n const input = this.el.querySelector<HTMLInputElement>(`#${editableId}_input`);\n\n // If the editor is not registered yet, we will wait for it to be registered.\n this.editorPromise = EditorsRegistry.the.execute(editorId, (editor: MultiRootEditor) => {\n const { ui, editing, model } = editor;\n\n if (model.document.getRoot(rootName)) {\n return editor;\n }\n\n editor.addRoot(rootName, {\n isUndoable: false,\n data: initialValue,\n });\n\n const contentElement = this.el.querySelector('[data-cke-editable-content]') as HTMLElement | null;\n const editable = ui.view.createEditable(rootName, contentElement!);\n\n ui.addEditable(editable);\n editing.view.forceRender();\n\n if (input) {\n syncEditorRootToInput(input, editor, rootName);\n }\n\n return editor;\n });\n }\n\n /**\n * Destroys the editable component. Unmounts root from the editor.\n */\n override async destroyed() {\n const { rootName } = this.attrs;\n\n // Let's hide the element during destruction to prevent flickering.\n this.el.style.display = 'none';\n\n // Let's wait for the mounted promise to resolve before proceeding with destruction.\n const editor = await this.editorPromise;\n this.editorPromise = null;\n\n // Unmount root from the editor.\n if (editor && editor.state !== 'destroyed') {\n const root = editor.model.document.getRoot(rootName);\n\n if (root && 'detachEditable' in editor) {\n editor.detachEditable(root);\n editor.detachRoot(rootName, false);\n }\n }\n }\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5 editable elements.\n */\nexport const EditableHook = makeHook(EditableHookImpl);\n\n/**\n * Synchronizes the editor's root data to the corresponding input element.\n * This is used to keep the input value in sync with the editor's content.\n *\n * @param input - The input element to synchronize with the editor.\n * @param editor - The CKEditor instance.\n * @param rootName - The name of the root to synchronize.\n */\nfunction syncEditorRootToInput(input: HTMLInputElement, editor: MultiRootEditor, rootName: string) {\n const sync = () => {\n input.value = editor.getData({ rootName });\n };\n\n editor.model.document.on('change:data', debounce(100, sync));\n sync();\n}\n","import type { Editor } from 'ckeditor5';\n\nimport type { EditorId, EditorType } from './typings';\nimport type { EditorCreator } from './utils';\n\nimport {\n debounce,\n isEmptyObject,\n mapObjectValues,\n parseIntIfNotNull,\n} from '../../shared';\nimport { ClassHook, makeHook } from '../../shared/hook';\nimport { ContextsRegistry, getNearestContextParentPromise } from '../context';\nimport { EditorsRegistry } from './editors-registry';\nimport {\n createEditorInContext,\n isSingleEditingLikeEditor,\n loadAllEditorTranslations,\n loadEditorConstructor,\n loadEditorPlugins,\n normalizeCustomTranslations,\n queryAllEditorEditables,\n readPresetOrThrow,\n resolveEditorConfigElementReferences,\n setEditorEditableHeight,\n unwrapEditorContext,\n unwrapEditorWatchdog,\n wrapWithWatchdog,\n} from './utils';\n\n/**\n * Editor hook for Phoenix LiveView.\n *\n * This class is a hook that can be used with Phoenix LiveView to integrate\n * the CKEditor 5 WYSIWYG editor.\n */\nclass EditorHookImpl extends ClassHook {\n /**\n * The promise that resolves to the editor instance.\n */\n private editorPromise: Promise<Editor> | null = null;\n\n /**\n * Attributes for the editor instance.\n */\n private get attrs() {\n const { el } = this;\n const get = el.getAttribute.bind(el);\n const has = el.hasAttribute.bind(el);\n\n const value = {\n editorId: get('id')!,\n contextId: get('cke-context-id'),\n preset: readPresetOrThrow(el),\n editableHeight: parseIntIfNotNull(get('cke-editable-height')),\n watchdog: has('cke-watchdog'),\n events: {\n change: has('cke-change-event'),\n blur: has('cke-blur-event'),\n focus: has('cke-focus-event'),\n },\n saveDebounceMs: parseIntIfNotNull(get('cke-save-debounce-ms')) ?? 400,\n language: {\n ui: get('cke-language') || 'en',\n content: get('cke-content-language') || 'en',\n },\n };\n\n Object.defineProperty(this, 'attrs', {\n value,\n writable: false,\n configurable: false,\n enumerable: true,\n });\n\n return value;\n }\n\n /**\n * Mounts the editor component.\n */\n override async mounted() {\n const { editorId } = this.attrs;\n this.editorPromise = this.createEditor();\n\n const editor = await this.editorPromise;\n\n // Do not even try to broadcast about the registration of the editor\n // if hook was immediately destroyed.\n if (!this.isBeingDestroyed()) {\n EditorsRegistry.the.register(editorId, editor);\n\n editor.once('destroy', () => {\n if (EditorsRegistry.the.hasItem(editorId)) {\n EditorsRegistry.the.unregister(editorId);\n }\n });\n }\n\n return this;\n }\n\n /**\n * Destroys the editor instance when the component is destroyed.\n * This is important to prevent memory leaks and ensure that the editor is properly cleaned up.\n */\n override async destroyed() {\n // Let's hide the element during destruction to prevent flickering.\n this.el.style.display = 'none';\n\n // Let's wait for the mounted promise to resolve before proceeding with destruction.\n try {\n const editor = (await this.editorPromise)!;\n const editorContext = unwrapEditorContext(editor);\n const watchdog = unwrapEditorWatchdog(editor);\n\n if (editorContext) {\n // If context is present, make sure it's not in unmounting phase, as it'll kill the editors.\n // If it's being destroyed, don't do anything, as the context will take care of it.\n if (editorContext.state !== 'unavailable') {\n await editorContext.context.remove(editorContext.editorContextId);\n }\n }\n else if (watchdog) {\n await watchdog.destroy();\n }\n else {\n await editor.destroy();\n }\n }\n finally {\n this.editorPromise = null;\n }\n }\n\n /**\n * Creates the CKEditor instance.\n */\n private async createEditor() {\n const { preset, editorId, contextId, editableHeight, events, saveDebounceMs, language, watchdog } = this.attrs;\n const { customTranslations, type, license, config: { plugins, ...config } } = preset;\n\n // Wrap editor creator with watchdog if needed.\n let Constructor: EditorCreator = await loadEditorConstructor(type);\n const context = await (\n contextId\n ? ContextsRegistry.the.waitFor(contextId)\n : getNearestContextParentPromise(this.el)\n );\n\n // Do not use editor specific watchdog if context is attached, as the context is by default protected.\n if (watchdog && !context) {\n const wrapped = await wrapWithWatchdog(Constructor);\n\n ({ Constructor } = wrapped);\n wrapped.watchdog.on('restart', () => {\n const newInstance = wrapped.watchdog.editor!;\n\n this.editorPromise = Promise.resolve(newInstance);\n\n EditorsRegistry.the.register(editorId, newInstance);\n });\n }\n\n const { loadedPlugins, hasPremium } = await loadEditorPlugins(plugins);\n\n // Mix custom translations with loaded translations.\n const loadedTranslations = await loadAllEditorTranslations(language, hasPremium);\n const mixedTranslations = [\n ...loadedTranslations,\n normalizeCustomTranslations(customTranslations?.dictionary || {}),\n ]\n .filter(translations => !isEmptyObject(translations));\n\n // Let's query all elements, and create basic configuration.\n const sourceElementOrData = getInitialRootsContentElements(editorId, type);\n const parsedConfig = {\n ...resolveEditorConfigElementReferences(config),\n initialData: getInitialRootsValues(editorId, type),\n licenseKey: license.key,\n plugins: loadedPlugins,\n language,\n ...mixedTranslations.length && {\n translations: mixedTranslations,\n },\n };\n\n // Depending of the editor type, and parent lookup for nearest context or initialize it without it.\n const editor = await (async () => {\n if (!context || !(sourceElementOrData instanceof HTMLElement)) {\n return Constructor.create(sourceElementOrData as any, parsedConfig);\n }\n\n const result = await createEditorInContext({\n context,\n element: sourceElementOrData,\n creator: Constructor,\n config: parsedConfig,\n });\n\n return result.editor;\n })();\n\n if (events.change) {\n this.setupTypingContentPush(editorId, editor, saveDebounceMs);\n }\n\n if (events.blur) {\n this.setupEventPush(editorId, editor, 'blur');\n }\n\n if (events.focus) {\n this.setupEventPush(editorId, editor, 'focus');\n }\n\n // Handle incoming data from the server.\n this.handleEvent('ckeditor5:set-data', ({ data }) => {\n editor.setData(data);\n });\n\n if (isSingleEditingLikeEditor(type)) {\n const input = document.getElementById(`${editorId}_input`) as HTMLInputElement | null;\n\n if (input) {\n syncEditorToInput(input, editor, saveDebounceMs);\n }\n\n if (editableHeight) {\n setEditorEditableHeight(editor, editableHeight);\n }\n }\n\n return editor;\n };\n\n /**\n * Setups the content push event for the editor.\n */\n private setupTypingContentPush(editorId: EditorId, editor: Editor, saveDebounceMs: number) {\n const pushContentChange = () => {\n this.pushEvent(\n 'ckeditor5:change',\n {\n editorId,\n data: getEditorRootsValues(editor),\n },\n );\n };\n\n editor.model.document.on('change:data', debounce(saveDebounceMs, pushContentChange));\n pushContentChange();\n }\n\n /**\n * Setups the event push for the editor.\n */\n private setupEventPush(editorId: EditorId, editor: Editor, eventType: 'focus' | 'blur') {\n const pushEvent = () => {\n const { isFocused } = editor.ui.focusTracker;\n const currentType = isFocused ? 'focus' : 'blur';\n\n if (currentType !== eventType) {\n return;\n }\n\n this.pushEvent(\n `ckeditor5:${eventType}`,\n {\n editorId,\n data: getEditorRootsValues(editor),\n },\n );\n };\n\n editor.ui.focusTracker.on('change:isFocused', pushEvent);\n }\n}\n\n/**\n * Gets the values of the editor's roots.\n *\n * @param editor The CKEditor instance.\n * @returns An object mapping root names to their content.\n */\nfunction getEditorRootsValues(editor: Editor) {\n const roots = editor.model.document.getRootNames();\n\n return roots.reduce<Record<string, string>>((acc, rootName) => {\n acc[rootName] = editor.getData({ rootName });\n return acc;\n }, Object.create({}));\n}\n\n/**\n * Synchronizes the editor's content with a hidden input field.\n *\n * @param input The input element to synchronize with the editor.\n * @param editor The CKEditor instance.\n */\nfunction syncEditorToInput(input: HTMLInputElement, editor: Editor, saveDebounceMs: number) {\n const sync = () => {\n const newValue = editor.getData();\n\n input.value = newValue;\n input.dispatchEvent(new Event('input', { bubbles: true }));\n };\n\n editor.model.document.on('change:data', debounce(saveDebounceMs, sync));\n getParentFormElement(input)?.addEventListener('submit', sync);\n\n sync();\n}\n\n/**\n * Gets the parent form element of the given HTML element.\n *\n * @param element The HTML element to find the parent form for.\n * @returns The parent form element or null if not found.\n */\nfunction getParentFormElement(element: HTMLElement) {\n return element.closest('form') as HTMLFormElement | null;\n}\n\n/**\n * Gets the initial root elements for the editor based on its type.\n *\n * @param editorId The editor's ID.\n * @param type The type of the editor.\n * @returns The root element(s) for the editor.\n */\nfunction getInitialRootsContentElements(editorId: EditorId, type: EditorType) {\n // While the `decoupled` editor is a single editing-like editor, it has a different structure\n // and requires special handling to get the main editable.\n if (type === 'decoupled') {\n const { content } = queryDecoupledMainEditableOrThrow(editorId);\n\n return content;\n }\n\n if (isSingleEditingLikeEditor(type)) {\n return document.getElementById(`${editorId}_editor`)!;\n }\n\n const editables = queryAllEditorEditables(editorId);\n\n return mapObjectValues(editables, ({ content }) => content);\n}\n\n/**\n * Gets the initial data for the roots of the editor. If the editor is a single editing-like editor,\n * it retrieves the initial value from the element's attribute. Otherwise, it returns an object mapping\n * editable names to their initial values.\n *\n * @param editorId The editor's ID.\n * @param type The type of the editor.\n * @returns The initial values for the editor's roots.\n */\nfunction getInitialRootsValues(editorId: EditorId, type: EditorType) {\n // While the `decoupled` editor is a single editing-like editor, it has a different structure\n // and requires special handling to get the main editable.\n if (type === 'decoupled') {\n const { initialValue } = queryDecoupledMainEditableOrThrow(editorId);\n\n // If initial value is not set, then pick it from the editor element.\n if (initialValue) {\n return initialValue;\n }\n }\n\n // Let's check initial value assigned to the editor element.\n if (isSingleEditingLikeEditor(type)) {\n const initialValue = document.getElementById(editorId)?.getAttribute('cke-initial-value') || '';\n\n return initialValue;\n }\n\n const editables = queryAllEditorEditables(editorId);\n\n return mapObjectValues(editables, ({ initialValue }) => initialValue);\n}\n\n/**\n * Queries the main editable for a decoupled editor and throws an error if not found.\n *\n * @param editorId The ID of the editor to query.\n */\nfunction queryDecoupledMainEditableOrThrow(editorId: EditorId) {\n const mainEditable = queryAllEditorEditables(editorId)['main'];\n\n if (!mainEditable) {\n throw new Error(`No \"main\" editable found for editor with ID \"${editorId}\".`);\n }\n\n return mainEditable;\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5.\n */\nexport const EditorHook = makeHook(EditorHookImpl);\n","import { ClassHook, makeHook } from '../shared';\nimport { EditorsRegistry } from './editor/editors-registry';\n\n/**\n * UI Part hook for Phoenix LiveView. It allows you to create UI parts for multi-root editors.\n */\nclass UIPartHookImpl extends ClassHook {\n /**\n * The name of the hook.\n */\n private mountedPromise: Promise<void> | null = null;\n\n /**\n * Attributes for the editable instance.\n */\n private get attrs() {\n const value = {\n editorId: this.el.getAttribute('data-cke-editor-id') || null,\n name: this.el.getAttribute('data-cke-ui-part-name')!,\n };\n\n Object.defineProperty(this, 'attrs', {\n value,\n writable: false,\n configurable: false,\n enumerable: true,\n });\n\n return value;\n }\n\n /**\n * Mounts the editable component.\n */\n override async mounted() {\n const { editorId, name } = this.attrs;\n\n // If the editor is not registered yet, we will wait for it to be registered.\n this.mountedPromise = EditorsRegistry.the.execute(editorId, (editor) => {\n const { ui } = editor;\n\n const uiViewName = mapUIPartView(name);\n const uiPart = (ui.view as any)[uiViewName!];\n\n if (!uiPart) {\n console.error(`Unknown UI part name: \"${name}\". Supported names are \"toolbar\" and \"menubar\".`);\n return;\n }\n\n this.el.appendChild(uiPart.element);\n });\n }\n\n /**\n * Destroys the editable component. Unmounts root from the editor.\n */\n override async destroyed() {\n // Let's hide the element during destruction to prevent flickering.\n this.el.style.display = 'none';\n\n // Let's wait for the mounted promise to resolve before proceeding with destruction.\n await this.mountedPromise;\n this.mountedPromise = null;\n\n // Unmount all UI parts from the editor.\n this.el.innerHTML = '';\n }\n}\n\n/**\n * Maps the UI part name to the corresponding view in the editor.\n */\nfunction mapUIPartView(name: string): string | null {\n switch (name) {\n case 'toolbar':\n return 'toolbar';\n\n case 'menubar':\n return 'menuBarView';\n\n default:\n return null;\n }\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5 UI parts.\n */\nexport const UIPartHook = makeHook(UIPartHookImpl);\n","import { ContextHook } from './context';\nimport { EditableHook } from './editable';\nimport { EditorHook } from './editor';\nimport { UIPartHook } from './ui-part';\n\nexport const Hooks = {\n CKEditor5: EditorHook,\n CKEditable: EditableHook,\n CKUIPart: UIPartHook,\n CKContext: ContextHook,\n};\n"],"names":["AsyncRegistry","id","fn","callbacks","items","item","resolve","callback","callbacksForItem","promises","watcher","itemsCopy","camelCase","str","_","c","m","debounce","delay","timeoutId","args","isPlainObject","value","proto","deepCamelCaseKeys","input","result","key","ClassHook","makeHook","constructor","instance","event","payload","selector","isEmptyObject","obj","mapObjectValues","mapper","mappedEntries","parseIntIfNotNull","parsed","uid","CONTEXT_EDITOR_WATCHDOG_SYMBOL","createEditorInContext","element","context","creator","config","editorContextId","_element","_config","editor","contextDescriptor","originalDestroy","unwrapEditorContext","isSingleEditingLikeEditor","editorType","loadEditorConstructor","type","PKG","EditorConstructor","CustomEditorPluginsRegistry","name","reader","loadEditorPlugins","plugins","basePackage","premiumPackage","loaders","plugin","customPlugin","basePkgImport","error","premiumPkgImport","loadAllEditorTranslations","language","hasPremium","translations","loadEditorPkgTranslations","pkg","lang","pack","loadEditorTranslation","normalizeCustomTranslations","dictionary","queryAllEditorEditables","editorId","iterator","acc","initialValue","content","EDITOR_TYPES","readPresetOrThrow","attributeValue","license","rest","resolveEditorConfigElementReferences","anyObj","setEditorEditableHeight","height","editing","writer","EDITOR_WATCHDOG_SYMBOL","wrapWithWatchdog","Editor","EditorWatchdog","watchdog","unwrapEditorWatchdog","ContextsRegistry","readContextConfigOrThrow","ContextHookImpl","get","attr","customTranslations","watchdogConfig","loadedPlugins","mixedTranslations","ContextWatchdog","Context","isContextHookHTMLElement","el","getNearestContextParent","parent","getNearestContextParentPromise","ContextHook","EditorsRegistry","EditableHookImpl","editableId","rootName","ui","model","contentElement","editable","syncEditorRootToInput","root","EditableHook","sync","EditorHookImpl","has","editorContext","preset","contextId","editableHeight","events","saveDebounceMs","Constructor","wrapped","newInstance","sourceElementOrData","getInitialRootsContentElements","parsedConfig","getInitialRootsValues","data","syncEditorToInput","pushContentChange","getEditorRootsValues","eventType","pushEvent","isFocused","newValue","getParentFormElement","queryDecoupledMainEditableOrThrow","editables","mainEditable","EditorHook","UIPartHookImpl","uiViewName","mapUIPartView","uiPart","UIPartHook","Hooks"],"mappings":"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kD,EACpF,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,QAAS,OAA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"}