ckeditor5-phoenix 1.15.0 → 1.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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/is-nil.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 */\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 initialization errors for items that failed to register.\n */\n private readonly initializationErrors = new Map<RegistryId | null, any>();\n\n /**\n * Map of pending callbacks waiting for items to be registered or fail.\n */\n private readonly pendingCallbacks = new Map<RegistryId | null, PendingCallbacks<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 onSuccess The function to execute.\n * @param onError Optional error callback.\n * @returns A promise that resolves with the result of the function.\n */\n execute<R, E extends T = T>(\n id: RegistryId | null,\n onSuccess: (item: E) => R,\n onError?: (error: any) => void,\n ): Promise<Awaited<R>> {\n const item = this.items.get(id);\n const error = this.initializationErrors.get(id);\n\n // If error exists and callback provided, invoke it immediately.\n if (error) {\n onError?.(error);\n return Promise.reject(error);\n }\n\n // If item exists, invoke callback immediately (synchronously via Promise.resolve).\n if (item) {\n return Promise.resolve(onSuccess(item as E));\n }\n\n // Item not ready yet - queue the callbacks.\n return new Promise((resolve, reject) => {\n const pending = this.getPendingCallbacks(id);\n\n pending.success.push(async (item: T) => {\n resolve(await onSuccess(item as E));\n });\n\n if (onError) {\n pending.error.push(onError);\n }\n else {\n pending.error.push(reject);\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 if (this.items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is already registered.`);\n }\n\n this.resetErrors(id);\n this.items.set(id, item);\n\n // Execute all pending callbacks for this item (synchronously).\n const pending = this.pendingCallbacks.get(id);\n\n if (pending) {\n pending.success.forEach(callback => callback(item));\n this.pendingCallbacks.delete(id);\n }\n\n // Register the first item as the default item (null ID).\n this.registerAsDefault(id, item);\n this.notifyWatchers();\n }\n\n /**\n * Registers an error for an item.\n *\n * @param id The ID of the item.\n * @param error The error to register.\n */\n error(id: RegistryId | null, error: any): void {\n this.items.delete(id);\n this.initializationErrors.set(id, error);\n\n // Execute all pending error callbacks for this item.\n const pending = this.pendingCallbacks.get(id);\n\n if (pending) {\n pending.error.forEach(callback => callback(error));\n this.pendingCallbacks.delete(id);\n }\n\n // Set as default error if this is the first error and no items exist.\n if (this.initializationErrors.size === 1 && !this.items.size) {\n this.error(null, error);\n }\n\n // Notify watchers about the error state.\n this.notifyWatchers();\n }\n\n /**\n * Resets errors for an item.\n *\n * @param id The ID of the item.\n */\n resetErrors(id: RegistryId | null): void {\n const { initializationErrors } = this;\n\n // Clear default error if it's the same as the specific error.\n if (initializationErrors.has(null) && initializationErrors.get(null) === initializationErrors.get(id)) {\n initializationErrors.delete(null);\n }\n\n initializationErrors.delete(id);\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 if (!this.items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is not registered.`);\n }\n\n // If unregistering the default item, clear it.\n if (id && this.items.get(null) === this.items.get(id)) {\n this.unregister(null);\n }\n\n this.items.delete(id);\n this.pendingCallbacks.delete(id);\n\n this.notifyWatchers();\n }\n\n /**\n * Gets all registered items.\n *\n * @returns An array of 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 new Promise<E>((resolve, reject) => {\n void this.execute(id, resolve as (value: E) => void, reject);\n });\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.pendingCallbacks.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(\n new Map(this.items),\n new Map(this.initializationErrors),\n );\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 this.watchers.forEach(\n watcher => watcher(\n new Map(this.items),\n new Map(this.initializationErrors),\n ),\n );\n }\n\n /**\n * Gets or creates pending callbacks for a specific ID.\n *\n * @param id The ID of the item.\n * @returns The pending callbacks structure.\n */\n private getPendingCallbacks(id: RegistryId | null): PendingCallbacks<T> {\n let pending = this.pendingCallbacks.get(id);\n\n if (!pending) {\n pending = { success: [], error: [] };\n this.pendingCallbacks.set(id, pending);\n }\n\n return pending;\n }\n\n /**\n * Registers an item as the default (null ID) item if it's the first one.\n *\n * @param id The ID of the item being registered.\n * @param item The item instance.\n */\n private registerAsDefault(id: RegistryId | null, item: T): void {\n if (this.items.size === 1 && id !== null) {\n this.register(null, item);\n }\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 * Structure holding pending success and error callbacks for an item.\n */\ntype PendingCallbacks<T> = {\n success: Array<(item: T) => void>;\n error: Array<(error: Error) => void>;\n};\n\n/**\n * Callback type for watching registry changes.\n */\ntype RegistryWatcher<T> = (\n items: Map<RegistryId | null, T>,\n errors: Map<RegistryId | null, Error>,\n) => 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","export function isNil(value: any): value is null | undefined {\n return value === null || value === undefined;\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 isNil,\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\n EditorsRegistry.the.resetErrors(editorId);\n\n try {\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 catch (error: any) {\n this.editorPromise = null;\n EditorsRegistry.the.error(editorId, error);\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\n if (!editor) {\n return;\n }\n\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', ({ editorId, data }) => {\n if (isNil(editorId) || editorId === this.attrs.editorId) {\n editor.setData(data);\n }\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","onSuccess","onError","item","error","resolve","reject","pending","callback","initializationErrors","promises","watcher","camelCase","str","_","c","m","debounce","delay","timeoutId","args","isPlainObject","value","proto","deepCamelCaseKeys","input","result","key","ClassHook","makeHook","constructor","instance","event","payload","selector","isEmptyObject","obj","isNil","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","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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IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,IAAK,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QA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"}
|
|
1
|
+
{"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/is-nil.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 */\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 initialization errors for items that failed to register.\n */\n private readonly initializationErrors = new Map<RegistryId | null, any>();\n\n /**\n * Map of pending callbacks waiting for items to be registered or fail.\n */\n private readonly pendingCallbacks = new Map<RegistryId | null, PendingCallbacks<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 onSuccess The function to execute.\n * @param onError Optional error callback.\n * @returns A promise that resolves with the result of the function.\n */\n execute<R, E extends T = T>(\n id: RegistryId | null,\n onSuccess: (item: E) => R,\n onError?: (error: any) => void,\n ): Promise<Awaited<R>> {\n const item = this.items.get(id);\n const error = this.initializationErrors.get(id);\n\n // If error exists and callback provided, invoke it immediately.\n if (error) {\n onError?.(error);\n return Promise.reject(error);\n }\n\n // If item exists, invoke callback immediately (synchronously via Promise.resolve).\n if (item) {\n return Promise.resolve(onSuccess(item as E));\n }\n\n // Item not ready yet - queue the callbacks.\n return new Promise((resolve, reject) => {\n const pending = this.getPendingCallbacks(id);\n\n pending.success.push(async (item: T) => {\n resolve(await onSuccess(item as E));\n });\n\n if (onError) {\n pending.error.push(onError);\n }\n else {\n pending.error.push(reject);\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 if (this.items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is already registered.`);\n }\n\n this.resetErrors(id);\n this.items.set(id, item);\n\n // Execute all pending callbacks for this item (synchronously).\n const pending = this.pendingCallbacks.get(id);\n\n if (pending) {\n pending.success.forEach(callback => callback(item));\n this.pendingCallbacks.delete(id);\n }\n\n // Register the first item as the default item (null ID).\n this.registerAsDefault(id, item);\n this.notifyWatchers();\n }\n\n /**\n * Registers an error for an item.\n *\n * @param id The ID of the item.\n * @param error The error to register.\n */\n error(id: RegistryId | null, error: any): void {\n this.items.delete(id);\n this.initializationErrors.set(id, error);\n\n // Execute all pending error callbacks for this item.\n const pending = this.pendingCallbacks.get(id);\n\n if (pending) {\n pending.error.forEach(callback => callback(error));\n this.pendingCallbacks.delete(id);\n }\n\n // Set as default error if this is the first error and no items exist.\n if (this.initializationErrors.size === 1 && !this.items.size) {\n this.error(null, error);\n }\n\n // Notify watchers about the error state.\n this.notifyWatchers();\n }\n\n /**\n * Resets errors for an item.\n *\n * @param id The ID of the item.\n */\n resetErrors(id: RegistryId | null): void {\n const { initializationErrors } = this;\n\n // Clear default error if it's the same as the specific error.\n if (initializationErrors.has(null) && initializationErrors.get(null) === initializationErrors.get(id)) {\n initializationErrors.delete(null);\n }\n\n initializationErrors.delete(id);\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 if (!this.items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is not registered.`);\n }\n\n // If unregistering the default item, clear it.\n if (id && this.items.get(null) === this.items.get(id)) {\n this.unregister(null);\n }\n\n this.items.delete(id);\n this.pendingCallbacks.delete(id);\n\n this.notifyWatchers();\n }\n\n /**\n * Gets all registered items.\n *\n * @returns An array of 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 new Promise<E>((resolve, reject) => {\n void this.execute(id, resolve as (value: E) => void, reject);\n });\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.pendingCallbacks.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(\n new Map(this.items),\n new Map(this.initializationErrors),\n );\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 this.watchers.forEach(\n watcher => watcher(\n new Map(this.items),\n new Map(this.initializationErrors),\n ),\n );\n }\n\n /**\n * Gets or creates pending callbacks for a specific ID.\n *\n * @param id The ID of the item.\n * @returns The pending callbacks structure.\n */\n private getPendingCallbacks(id: RegistryId | null): PendingCallbacks<T> {\n let pending = this.pendingCallbacks.get(id);\n\n if (!pending) {\n pending = { success: [], error: [] };\n this.pendingCallbacks.set(id, pending);\n }\n\n return pending;\n }\n\n /**\n * Registers an item as the default (null ID) item if it's the first one.\n *\n * @param id The ID of the item being registered.\n * @param item The item instance.\n */\n private registerAsDefault(id: RegistryId | null, item: T): void {\n if (this.items.size === 1 && id !== null) {\n this.register(null, item);\n }\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 * Structure holding pending success and error callbacks for an item.\n */\ntype PendingCallbacks<T> = {\n success: Array<(item: T) => void>;\n error: Array<(error: Error) => void>;\n};\n\n/**\n * Callback type for watching registry changes.\n */\ntype RegistryWatcher<T> = (\n items: Map<RegistryId | null, T>,\n errors: Map<RegistryId | null, Error>,\n) => 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","export function isNil(value: any): value is null | undefined {\n return value === null || value === undefined;\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 // Try custom plugins before checking packages.\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 isNil,\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\n EditorsRegistry.the.resetErrors(editorId);\n\n try {\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 catch (error: any) {\n this.editorPromise = null;\n EditorsRegistry.the.error(editorId, error);\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\n if (!editor) {\n return;\n }\n\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', ({ editorId, data }) => {\n if (isNil(editorId) || editorId === this.attrs.editorId) {\n editor.setData(data);\n }\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","onSuccess","onError","item","error","resolve","reject","pending","callback","initializationErrors","promises","watcher","camelCase","str","_","c","m","debounce","delay","timeoutId","args","isPlainObject","value","proto","deepCamelCaseKeys","input","result","key","ClassHook","makeHook","constructor","instance","event","payload","selector","isEmptyObject","obj","isNil","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","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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IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,IAAK,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QA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"}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","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/is-nil.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 */\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 initialization errors for items that failed to register.\n */\n private readonly initializationErrors = new Map<RegistryId | null, any>();\n\n /**\n * Map of pending callbacks waiting for items to be registered or fail.\n */\n private readonly pendingCallbacks = new Map<RegistryId | null, PendingCallbacks<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 onSuccess The function to execute.\n * @param onError Optional error callback.\n * @returns A promise that resolves with the result of the function.\n */\n execute<R, E extends T = T>(\n id: RegistryId | null,\n onSuccess: (item: E) => R,\n onError?: (error: any) => void,\n ): Promise<Awaited<R>> {\n const item = this.items.get(id);\n const error = this.initializationErrors.get(id);\n\n // If error exists and callback provided, invoke it immediately.\n if (error) {\n onError?.(error);\n return Promise.reject(error);\n }\n\n // If item exists, invoke callback immediately (synchronously via Promise.resolve).\n if (item) {\n return Promise.resolve(onSuccess(item as E));\n }\n\n // Item not ready yet - queue the callbacks.\n return new Promise((resolve, reject) => {\n const pending = this.getPendingCallbacks(id);\n\n pending.success.push(async (item: T) => {\n resolve(await onSuccess(item as E));\n });\n\n if (onError) {\n pending.error.push(onError);\n }\n else {\n pending.error.push(reject);\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 if (this.items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is already registered.`);\n }\n\n this.resetErrors(id);\n this.items.set(id, item);\n\n // Execute all pending callbacks for this item (synchronously).\n const pending = this.pendingCallbacks.get(id);\n\n if (pending) {\n pending.success.forEach(callback => callback(item));\n this.pendingCallbacks.delete(id);\n }\n\n // Register the first item as the default item (null ID).\n this.registerAsDefault(id, item);\n this.notifyWatchers();\n }\n\n /**\n * Registers an error for an item.\n *\n * @param id The ID of the item.\n * @param error The error to register.\n */\n error(id: RegistryId | null, error: any): void {\n this.items.delete(id);\n this.initializationErrors.set(id, error);\n\n // Execute all pending error callbacks for this item.\n const pending = this.pendingCallbacks.get(id);\n\n if (pending) {\n pending.error.forEach(callback => callback(error));\n this.pendingCallbacks.delete(id);\n }\n\n // Set as default error if this is the first error and no items exist.\n if (this.initializationErrors.size === 1 && !this.items.size) {\n this.error(null, error);\n }\n\n // Notify watchers about the error state.\n this.notifyWatchers();\n }\n\n /**\n * Resets errors for an item.\n *\n * @param id The ID of the item.\n */\n resetErrors(id: RegistryId | null): void {\n const { initializationErrors } = this;\n\n // Clear default error if it's the same as the specific error.\n if (initializationErrors.has(null) && initializationErrors.get(null) === initializationErrors.get(id)) {\n initializationErrors.delete(null);\n }\n\n initializationErrors.delete(id);\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 if (!this.items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is not registered.`);\n }\n\n // If unregistering the default item, clear it.\n if (id && this.items.get(null) === this.items.get(id)) {\n this.unregister(null);\n }\n\n this.items.delete(id);\n this.pendingCallbacks.delete(id);\n\n this.notifyWatchers();\n }\n\n /**\n * Gets all registered items.\n *\n * @returns An array of 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 new Promise<E>((resolve, reject) => {\n void this.execute(id, resolve as (value: E) => void, reject);\n });\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.pendingCallbacks.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(\n new Map(this.items),\n new Map(this.initializationErrors),\n );\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 this.watchers.forEach(\n watcher => watcher(\n new Map(this.items),\n new Map(this.initializationErrors),\n ),\n );\n }\n\n /**\n * Gets or creates pending callbacks for a specific ID.\n *\n * @param id The ID of the item.\n * @returns The pending callbacks structure.\n */\n private getPendingCallbacks(id: RegistryId | null): PendingCallbacks<T> {\n let pending = this.pendingCallbacks.get(id);\n\n if (!pending) {\n pending = { success: [], error: [] };\n this.pendingCallbacks.set(id, pending);\n }\n\n return pending;\n }\n\n /**\n * Registers an item as the default (null ID) item if it's the first one.\n *\n * @param id The ID of the item being registered.\n * @param item The item instance.\n */\n private registerAsDefault(id: RegistryId | null, item: T): void {\n if (this.items.size === 1 && id !== null) {\n this.register(null, item);\n }\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 * Structure holding pending success and error callbacks for an item.\n */\ntype PendingCallbacks<T> = {\n success: Array<(item: T) => void>;\n error: Array<(error: Error) => void>;\n};\n\n/**\n * Callback type for watching registry changes.\n */\ntype RegistryWatcher<T> = (\n items: Map<RegistryId | null, T>,\n errors: Map<RegistryId | null, Error>,\n) => 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","export function isNil(value: any): value is null | undefined {\n return value === null || value === undefined;\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 isNil,\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\n EditorsRegistry.the.resetErrors(editorId);\n\n try {\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 catch (error: any) {\n this.editorPromise = null;\n EditorsRegistry.the.error(editorId, error);\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\n if (!editor) {\n return;\n }\n\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', ({ editorId, data }) => {\n if (isNil(editorId) || editorId === this.attrs.editorId) {\n editor.setData(data);\n }\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","onSuccess","onError","item","error","resolve","reject","pending","callback","initializationErrors","promises","watcher","camelCase","str","_","c","m","debounce","delay","timeoutId","args","isPlainObject","value","proto","deepCamelCaseKeys","input","result","key","ClassHook","makeHook","constructor","instance","event","payload","selector","isEmptyObject","obj","isNil","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","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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A,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","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/is-nil.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 */\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 initialization errors for items that failed to register.\n */\n private readonly initializationErrors = new Map<RegistryId | null, any>();\n\n /**\n * Map of pending callbacks waiting for items to be registered or fail.\n */\n private readonly pendingCallbacks = new Map<RegistryId | null, PendingCallbacks<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 onSuccess The function to execute.\n * @param onError Optional error callback.\n * @returns A promise that resolves with the result of the function.\n */\n execute<R, E extends T = T>(\n id: RegistryId | null,\n onSuccess: (item: E) => R,\n onError?: (error: any) => void,\n ): Promise<Awaited<R>> {\n const item = this.items.get(id);\n const error = this.initializationErrors.get(id);\n\n // If error exists and callback provided, invoke it immediately.\n if (error) {\n onError?.(error);\n return Promise.reject(error);\n }\n\n // If item exists, invoke callback immediately (synchronously via Promise.resolve).\n if (item) {\n return Promise.resolve(onSuccess(item as E));\n }\n\n // Item not ready yet - queue the callbacks.\n return new Promise((resolve, reject) => {\n const pending = this.getPendingCallbacks(id);\n\n pending.success.push(async (item: T) => {\n resolve(await onSuccess(item as E));\n });\n\n if (onError) {\n pending.error.push(onError);\n }\n else {\n pending.error.push(reject);\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 if (this.items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is already registered.`);\n }\n\n this.resetErrors(id);\n this.items.set(id, item);\n\n // Execute all pending callbacks for this item (synchronously).\n const pending = this.pendingCallbacks.get(id);\n\n if (pending) {\n pending.success.forEach(callback => callback(item));\n this.pendingCallbacks.delete(id);\n }\n\n // Register the first item as the default item (null ID).\n this.registerAsDefault(id, item);\n this.notifyWatchers();\n }\n\n /**\n * Registers an error for an item.\n *\n * @param id The ID of the item.\n * @param error The error to register.\n */\n error(id: RegistryId | null, error: any): void {\n this.items.delete(id);\n this.initializationErrors.set(id, error);\n\n // Execute all pending error callbacks for this item.\n const pending = this.pendingCallbacks.get(id);\n\n if (pending) {\n pending.error.forEach(callback => callback(error));\n this.pendingCallbacks.delete(id);\n }\n\n // Set as default error if this is the first error and no items exist.\n if (this.initializationErrors.size === 1 && !this.items.size) {\n this.error(null, error);\n }\n\n // Notify watchers about the error state.\n this.notifyWatchers();\n }\n\n /**\n * Resets errors for an item.\n *\n * @param id The ID of the item.\n */\n resetErrors(id: RegistryId | null): void {\n const { initializationErrors } = this;\n\n // Clear default error if it's the same as the specific error.\n if (initializationErrors.has(null) && initializationErrors.get(null) === initializationErrors.get(id)) {\n initializationErrors.delete(null);\n }\n\n initializationErrors.delete(id);\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 if (!this.items.has(id)) {\n throw new Error(`Item with ID \"${id}\" is not registered.`);\n }\n\n // If unregistering the default item, clear it.\n if (id && this.items.get(null) === this.items.get(id)) {\n this.unregister(null);\n }\n\n this.items.delete(id);\n this.pendingCallbacks.delete(id);\n\n this.notifyWatchers();\n }\n\n /**\n * Gets all registered items.\n *\n * @returns An array of 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 new Promise<E>((resolve, reject) => {\n void this.execute(id, resolve as (value: E) => void, reject);\n });\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.pendingCallbacks.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(\n new Map(this.items),\n new Map(this.initializationErrors),\n );\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 this.watchers.forEach(\n watcher => watcher(\n new Map(this.items),\n new Map(this.initializationErrors),\n ),\n );\n }\n\n /**\n * Gets or creates pending callbacks for a specific ID.\n *\n * @param id The ID of the item.\n * @returns The pending callbacks structure.\n */\n private getPendingCallbacks(id: RegistryId | null): PendingCallbacks<T> {\n let pending = this.pendingCallbacks.get(id);\n\n if (!pending) {\n pending = { success: [], error: [] };\n this.pendingCallbacks.set(id, pending);\n }\n\n return pending;\n }\n\n /**\n * Registers an item as the default (null ID) item if it's the first one.\n *\n * @param id The ID of the item being registered.\n * @param item The item instance.\n */\n private registerAsDefault(id: RegistryId | null, item: T): void {\n if (this.items.size === 1 && id !== null) {\n this.register(null, item);\n }\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 * Structure holding pending success and error callbacks for an item.\n */\ntype PendingCallbacks<T> = {\n success: Array<(item: T) => void>;\n error: Array<(error: Error) => void>;\n};\n\n/**\n * Callback type for watching registry changes.\n */\ntype RegistryWatcher<T> = (\n items: Map<RegistryId | null, T>,\n errors: Map<RegistryId | null, Error>,\n) => 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","export function isNil(value: any): value is null | undefined {\n return value === null || value === undefined;\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 // Try custom plugins before checking packages.\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 isNil,\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\n EditorsRegistry.the.resetErrors(editorId);\n\n try {\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 catch (error: any) {\n this.editorPromise = null;\n EditorsRegistry.the.error(editorId, error);\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\n if (!editor) {\n return;\n }\n\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', ({ editorId, data }) => {\n if (isNil(editorId) || editorId === this.attrs.editorId) {\n editor.setData(data);\n }\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","onSuccess","onError","item","error","resolve","reject","pending","callback","initializationErrors","promises","watcher","camelCase","str","_","c","m","debounce","delay","timeoutId","args","isPlainObject","value","proto","deepCamelCaseKeys","input","result","key","ClassHook","makeHook","constructor","instance","event","payload","selector","isEmptyObject","obj","isNil","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","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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A,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK;AAAM,iBAAO,MAAM,OAAO,8BAA8B;AAAA,QAC7D,KAAK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"}
|
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@ export async function loadEditorPlugins(plugins: EditorPlugin[]): Promise<Loaded
|
|
|
20
20
|
// Let's first try to load the plugin from the base package.
|
|
21
21
|
// Coverage is disabled due to Vitest issues with mocking dynamic imports.
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// Try custom plugins before checking packages.
|
|
24
24
|
const customPlugin = await CustomEditorPluginsRegistry.the.get(plugin);
|
|
25
25
|
|
|
26
26
|
if (customPlugin) {
|