Current section

Files

Jump to
ckeditor5_phoenix dist index.cjs.map
Raw

dist/index.cjs.map

{"version":3,"file":"index.cjs","sources":["../src/shared/debounce.ts","../src/shared/hook.ts","../src/shared/is-empty-object.ts","../src/shared/map-object-values.ts","../src/shared/parse-int-if-not-null.ts","../src/hooks/editor/editors-registry.ts","../src/hooks/editable.ts","../src/hooks/editor/custom-editor-plugins.ts","../src/hooks/editor/utils/is-single-editing-like-editor.ts","../src/hooks/editor/utils/load-editor-constructor.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/set-editor-editable-height.ts","../src/hooks/editor/editor.ts","../src/hooks/ui-part.ts","../src/hooks/index.ts"],"sourcesContent":["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","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 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(): void;\n\n /**\n * Called when the element has been removed from the DOM.\n * Perfect for cleanup tasks.\n */\n abstract destroyed(): void;\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/**\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 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 return instance.mounted?.();\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 destroyed(this: any) {\n this.el.instance.destroyed?.();\n },\n\n /**\n * The disconnected lifecycle callback that delegates to the hook instance.\n */\n disconnected(this: any) {\n this.el.instance.disconnected?.();\n },\n\n /**\n * The reconnected lifecycle callback that delegates to the hook instance.\n */\n reconnected(this: any) {\n this.el.instance.reconnected?.();\n },\n };\n}\n","export function isEmptyObject(obj: Record<string, unknown>): boolean {\n return Object.keys(obj).length === 0 && obj.constructor === Object;\n}\n","/**\n * Maps the values of an object using a provided mapper function.\n *\n * @param obj The object whose values will be mapped.\n * @param mapper A function that takes a value and its key, and returns a new value.\n * @template T The type of the original values in the object.\n * @template U The type of the new values in the object.\n * @returns A new object with the same keys as the original, but with values transformed by\n */\nexport function mapObjectValues<T, U>(\n obj: Record<string, T>,\n mapper: (value: T, key: string) => U,\n): Record<string, U> {\n const mappedEntries = Object\n .entries(obj)\n .map(([key, value]) => [key, mapper(value, key)] as const);\n\n return Object.fromEntries(mappedEntries);\n}\n","export function parseIntIfNotNull(value: string | null): number | null {\n if (value === null) {\n return null;\n }\n\n const parsed = Number.parseInt(value, 10);\n\n return Number.isNaN(parsed) ? null : parsed;\n}\n","import type { Editor } from 'ckeditor5';\n\nimport type { EditorId } from './typings';\n\n/**\n * Allows other hooks to communicate with specific editors.\n * It provides a way to register editors and execute callbacks on them when they are available.\n */\nexport class EditorsRegistry {\n static readonly the = new EditorsRegistry();\n\n /**\n * Map of registered editors.\n */\n private readonly editors = new Map<EditorId | null, Editor>();\n\n /**\n * Map of callbacks that are waiting for an editor to be registered.\n */\n private readonly callbacks = new Map<EditorId | null, EditorCallback<any>[]>();\n\n /**\n * Set of watchers that observe changes to the editors registry.\n */\n private readonly watchers = new Set<EditorsWatcher>();\n\n /**\n * Private constructor to enforce singleton pattern.\n */\n private constructor() {}\n\n /**\n * Executes a function on an editor.\n * If the editor is not yet registered, it will wait for it to be registered.\n *\n * @param editorId The ID of the editor.\n * @param fn The function to execute.\n * @returns A promise that resolves with the result of the function.\n */\n execute<T, E extends Editor = Editor>(editorId: EditorId | null, fn: (editor: E) => T): Promise<Awaited<T>> {\n const { callbacks, editors } = this;\n const editor = editors.get(editorId);\n\n if (editor) {\n return Promise.resolve(fn(editor as E));\n }\n\n return new Promise((resolve) => {\n const callback = async (editor: E) => resolve(await fn(editor));\n\n if (!this.callbacks.has(editorId)) {\n callbacks.set(editorId, []);\n }\n\n callbacks.set(editorId, [\n ...callbacks.get(editorId)!,\n callback,\n ]);\n });\n }\n\n /**\n * Registers an editor.\n *\n * @param editorId The ID of the editor.\n * @param editor The editor instance.\n */\n register(editorId: EditorId | null, editor: Editor): void {\n const { editors, callbacks } = this;\n const callbacksForEditor = callbacks.get(editorId);\n\n if (editors.has(editorId)) {\n throw new Error(`Editor with ID \"${editorId}\" is already registered.`);\n }\n\n editors.set(editorId, editor);\n\n if (callbacksForEditor) {\n callbacksForEditor.forEach(callback => callback(editor));\n callbacks.delete(editorId);\n }\n\n // Register the first editor as the default editor.\n // This is useful for editables that do not specify an editor ID.\n if (this.editors.size === 1) {\n this.register(null, editor);\n }\n\n this.notifyWatchers();\n }\n\n /**\n * Un-registers an editor.\n *\n * @param editorId The ID of the editor.\n */\n unregister(editorId: EditorId | null): void {\n const { editors, callbacks } = this;\n\n if (!editors.has(editorId)) {\n throw new Error(`Editor with ID \"${editorId}\" is not registered.`);\n }\n\n if (editorId && this.editors.get(null) === editors.get(editorId)) {\n this.unregister(null);\n }\n\n editors.delete(editorId);\n callbacks.delete(editorId);\n\n this.notifyWatchers();\n }\n\n /**\n * Gets all registered editors.\n */\n getEditors(): Editor[] {\n return Array.from(this.editors.values());\n }\n\n /**\n * Checks if an editor with the given ID is registered.\n *\n * @param editorId The ID of the editor.\n * @returns `true` if the editor is registered, `false` otherwise.\n */\n hasEditor(editorId: EditorId | null): boolean {\n return this.editors.has(editorId);\n }\n\n /**\n * Gets a promise that resolves with the editor instance for the given ID.\n * If the editor is not registered yet, it will wait for it to be registered.\n *\n * @param editorId The ID of the editor.\n * @returns A promise that resolves with the editor instance.\n */\n waitForEditor<E extends Editor>(editorId: EditorId | null): Promise<E> {\n return this.execute(editorId, editor => editor as E);\n }\n\n /**\n * Destroys all registered editors and clears the registry.\n * This will call the `destroy` method on each editor.\n */\n async destroyAllEditors() {\n const promises = (\n Array\n .from(this.editors.values())\n .map(editor => editor.destroy())\n );\n\n this.editors.clear();\n this.callbacks.clear();\n\n await Promise.all(promises);\n\n this.notifyWatchers();\n }\n\n /**\n * Registers a watcher that will be called whenever the editors registry changes.\n *\n * @param watcher The watcher function to register.\n * @returns A function to unregister the watcher.\n */\n watch(watcher: EditorsWatcher): () => void {\n this.watchers.add(watcher);\n\n // Call the watcher immediately with the current state\n watcher(new Map(this.editors));\n\n return this.unwatch.bind(this, watcher);\n }\n\n /**\n * Unregisters a watcher.\n *\n * @param watcher The watcher function to unregister.\n */\n unwatch(watcher: EditorsWatcher): void {\n this.watchers.delete(watcher);\n }\n\n /**\n * Notifies all watchers about changes to the editors registry.\n */\n private notifyWatchers(): void {\n const editorsCopy = new Map(this.editors);\n this.watchers.forEach(watcher => watcher(editorsCopy));\n }\n}\n\n/**\n * Callback type for editor operations.\n */\ntype EditorCallback<E extends Editor = Editor> = (editor: E) => void;\n\n/**\n * Callback type for watching editors registry changes.\n */\ntype EditorsWatcher = (editors: Map<EditorId | null, Editor>) => void;\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 mountedPromise: Promise<void> | 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.mountedPromise = EditorsRegistry.the.execute(editorId, (editor: MultiRootEditor) => {\n const { ui, editing, model } = editor;\n\n if (model.document.getRoot(rootName)) {\n return;\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 }\n\n /**\n * Destroys the editable component. Unmounts root from the editor.\n */\n override async destroyed() {\n const { editorId, 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 await this.mountedPromise;\n this.mountedPromise = null;\n\n // Unmount root from the editor.\n await EditorsRegistry.the.execute(editorId, (editor: MultiRootEditor) => {\n const root = editor.model.document.getRoot(rootName);\n\n if (root) {\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 { 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 { 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 { 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: Record<string, any> = 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 /* v8 ignore start */\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;\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 }\n catch (error) {\n console.error(`Failed to load premium package: ${error}`);\n }\n }\n\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 /* v8 ignore end */\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[];\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 { mapObjectValues } from 'src/shared';\n\nimport type { EditorCustomTranslationsDictionary } from '../typings';\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 height for the editor, if applicable.\n * This can be used to set a specific height for the editor instance.\n */\n editableHeight?: number;\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 { 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, custom_translations: customTranslations } = 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 config,\n license,\n customTranslations,\n };\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 } from 'ckeditor5';\n\nimport type { EditorId, EditorType } from './typings';\n\nimport {\n debounce,\n isEmptyObject,\n mapObjectValues,\n parseIntIfNotNull,\n} from '../../shared';\nimport { ClassHook, makeHook } from '../../shared/hook';\nimport { EditorsRegistry } from './editors-registry';\nimport {\n isSingleEditingLikeEditor,\n loadAllEditorTranslations,\n loadEditorConstructor,\n loadEditorPlugins,\n normalizeCustomTranslations,\n queryAllEditorEditables,\n readPresetOrThrow,\n setEditorEditableHeight,\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 name of the hook.\n */\n private editorPromise: Promise<Editor> | null = null;\n\n /**\n * Attributes for the editor instance.\n */\n private get attrs() {\n const value = {\n editorId: this.el.getAttribute('id')!,\n preset: readPresetOrThrow(this.el),\n editableHeight: parseIntIfNotNull(this.el.getAttribute('cke-editable-height')),\n events: {\n change: this.el.getAttribute('cke-change-event') !== null,\n blur: this.el.getAttribute('cke-blur-event') !== null,\n focus: this.el.getAttribute('cke-focus-event') !== null,\n },\n saveDebounceMs: parseIntIfNotNull(this.el.getAttribute('cke-save-debounce-ms')) ?? 400,\n language: {\n ui: this.el.getAttribute('cke-language') || 'en',\n content: this.el.getAttribute('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 this.editorPromise = this.createEditor();\n\n EditorsRegistry.the.register(this.attrs.editorId, await this.editorPromise);\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 (await this.editorPromise)?.destroy();\n this.editorPromise = null;\n\n EditorsRegistry.the.unregister(this.attrs.editorId);\n }\n\n /**\n * Creates the CKEditor instance.\n */\n private async createEditor() {\n const { preset, editorId, editableHeight, events, saveDebounceMs, language } = this.attrs;\n const { customTranslations, type, license, config: { plugins, ...config } } = preset;\n\n const Constructor = await loadEditorConstructor(type);\n const rootEditables = getInitialRootsContentElements(editorId, type);\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 const editor = await Constructor.create(\n rootEditables as any,\n {\n ...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\n if (events.change) {\n this.setupTypingContentPush(editorId, editor, saveDebounceMs);\n }\n\n if (events.blur) {\n this.setupEventPush(editorId, editor, 'blur');\n }\n\n if (events.focus) {\n this.setupEventPush(editorId, editor, 'focus');\n }\n\n // Handle incoming data from the server.\n this.handleEvent('ckeditor5:set-data', ({ data }) => {\n editor.setData(data);\n });\n\n if (isSingleEditingLikeEditor(type)) {\n const input = document.getElementById(`${editorId}_input`) as HTMLInputElement | null;\n\n if (input) {\n syncEditorToInput(input, editor, saveDebounceMs);\n }\n\n if (editableHeight) {\n setEditorEditableHeight(editor, editableHeight);\n }\n }\n\n return editor;\n };\n\n /**\n * Setups the content push event for the editor.\n */\n private setupTypingContentPush(editorId: EditorId, editor: Editor, saveDebounceMs: number) {\n const pushContentChange = () => {\n this.pushEvent(\n 'ckeditor5:change',\n {\n editorId,\n data: getEditorRootsValues(editor),\n },\n );\n };\n\n editor.model.document.on('change:data', debounce(saveDebounceMs, pushContentChange));\n pushContentChange();\n }\n\n /**\n * Setups the event push for the editor.\n */\n private setupEventPush(editorId: EditorId, editor: Editor, eventType: 'focus' | 'blur') {\n const pushEvent = () => {\n const { isFocused } = editor.ui.focusTracker;\n const currentType = isFocused ? 'focus' : 'blur';\n\n if (currentType !== eventType) {\n return;\n }\n\n this.pushEvent(\n `ckeditor5:${eventType}`,\n {\n editorId,\n data: getEditorRootsValues(editor),\n },\n );\n };\n\n editor.ui.focusTracker.on('change:isFocused', pushEvent);\n }\n}\n\n/**\n * Gets the values of the editor's roots.\n *\n * @param editor The CKEditor instance.\n * @returns An object mapping root names to their content.\n */\nfunction getEditorRootsValues(editor: Editor) {\n const roots = editor.model.document.getRootNames();\n\n return roots.reduce<Record<string, string>>((acc, rootName) => {\n acc[rootName] = editor.getData({ rootName });\n return acc;\n }, Object.create({}));\n}\n\n/**\n * Synchronizes the editor's content with a hidden input field.\n *\n * @param input The input element to synchronize with the editor.\n * @param editor The CKEditor instance.\n */\nfunction syncEditorToInput(input: HTMLInputElement, editor: Editor, saveDebounceMs: number) {\n const sync = () => {\n const newValue = editor.getData();\n\n input.value = newValue;\n input.dispatchEvent(new Event('input', { bubbles: true }));\n };\n\n editor.model.document.on('change:data', debounce(saveDebounceMs, sync));\n getParentFormElement(input)?.addEventListener('submit', sync);\n\n sync();\n}\n\n/**\n * Gets the parent form element of the given HTML element.\n *\n * @param element The HTML element to find the parent form for.\n * @returns The parent form element or null if not found.\n */\nfunction getParentFormElement(element: HTMLElement) {\n return element.closest('form') as HTMLFormElement | null;\n}\n\n/**\n * Gets the initial root elements for the editor based on its type.\n *\n * @param editorId The editor's ID.\n * @param type The type of the editor.\n * @returns The root element(s) for the editor.\n */\nfunction getInitialRootsContentElements(editorId: EditorId, type: EditorType) {\n // While the `decoupled` editor is a single editing-like editor, it has a different structure\n // and requires special handling to get the main editable.\n if (type === 'decoupled') {\n const { content } = queryDecoupledMainEditableOrThrow(editorId);\n\n return content;\n }\n\n if (isSingleEditingLikeEditor(type)) {\n return document.getElementById(`${editorId}_editor`)!;\n }\n\n const editables = queryAllEditorEditables(editorId);\n\n return mapObjectValues(editables, ({ content }) => content);\n}\n\n/**\n * Gets the initial data for the roots of the editor. If the editor is a single editing-like editor,\n * it retrieves the initial value from the element's attribute. Otherwise, it returns an object mapping\n * editable names to their initial values.\n *\n * @param editorId The editor's ID.\n * @param type The type of the editor.\n * @returns The initial values for the editor's roots.\n */\nfunction getInitialRootsValues(editorId: EditorId, type: EditorType) {\n // While the `decoupled` editor is a single editing-like editor, it has a different structure\n // and requires special handling to get the main editable.\n if (type === 'decoupled') {\n const { initialValue } = queryDecoupledMainEditableOrThrow(editorId);\n\n // If initial value is not set, then pick it from the editor element.\n if (initialValue) {\n return initialValue;\n }\n }\n\n // Let's check initial value assigned to the editor element.\n if (isSingleEditingLikeEditor(type)) {\n const initialValue = document.getElementById(editorId)?.getAttribute('cke-initial-value') || '';\n\n return initialValue;\n }\n\n const editables = queryAllEditorEditables(editorId);\n\n return mapObjectValues(editables, ({ initialValue }) => initialValue);\n}\n\n/**\n * Queries the main editable for a decoupled editor and throws an error if not found.\n *\n * @param editorId The ID of the editor to query.\n */\nfunction queryDecoupledMainEditableOrThrow(editorId: EditorId) {\n const mainEditable = queryAllEditorEditables(editorId)['main'];\n\n if (!mainEditable) {\n throw new Error(`No \"main\" editable found for editor with ID \"${editorId}\".`);\n }\n\n return mainEditable;\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5.\n */\nexport const EditorHook = makeHook(EditorHookImpl);\n","import { ClassHook, makeHook } from '../shared';\nimport { EditorsRegistry } from './editor/editors-registry';\n\n/**\n * UI Part hook for Phoenix LiveView. It allows you to create UI parts for multi-root editors.\n */\nclass UIPartHookImpl extends ClassHook {\n /**\n * The name of the hook.\n */\n private mountedPromise: Promise<void> | null = null;\n\n /**\n * Attributes for the editable instance.\n */\n private get attrs() {\n const value = {\n editorId: this.el.getAttribute('data-cke-editor-id') || null,\n name: this.el.getAttribute('data-cke-ui-part-name')!,\n };\n\n Object.defineProperty(this, 'attrs', {\n value,\n writable: false,\n configurable: false,\n enumerable: true,\n });\n\n return value;\n }\n\n /**\n * Mounts the editable component.\n */\n override async mounted() {\n const { editorId, name } = this.attrs;\n\n // If the editor is not registered yet, we will wait for it to be registered.\n this.mountedPromise = EditorsRegistry.the.execute(editorId, (editor) => {\n const { ui } = editor;\n\n const uiViewName = mapUIPartView(name);\n const uiPart = (ui.view as any)[uiViewName!];\n\n if (!uiPart) {\n console.error(`Unknown UI part name: \"${name}\". Supported names are \"toolbar\" and \"menubar\".`);\n return;\n }\n\n this.el.appendChild(uiPart.element);\n });\n }\n\n /**\n * Destroys the editable component. Unmounts root from the editor.\n */\n override async destroyed() {\n // Let's hide the element during destruction to prevent flickering.\n this.el.style.display = 'none';\n\n // Let's wait for the mounted promise to resolve before proceeding with destruction.\n await this.mountedPromise;\n this.mountedPromise = null;\n\n // Unmount all UI parts from the editor.\n this.el.innerHTML = '';\n }\n}\n\n/**\n * Maps the UI part name to the corresponding view in the editor.\n */\nfunction mapUIPartView(name: string): string | null {\n switch (name) {\n case 'toolbar':\n return 'toolbar';\n\n case 'menubar':\n return 'menuBarView';\n\n default:\n return null;\n }\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5 UI parts.\n */\nexport const UIPartHook = makeHook(UIPartHookImpl);\n","import { 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};\n"],"names":["debounce","delay","callback","timeoutId","args","ClassHook","makeHook","constructor","instance","event","payload","selector","isEmptyObject","obj","mapObjectValues","mapper","mappedEntries","key","value","parseIntIfNotNull","parsed","EditorsRegistry","editorId","fn","callbacks","editors","editor","resolve","callbacksForEditor","promises","watcher","editorsCopy","EditableHookImpl","editableId","rootName","initialValue","input","ui","editing","model","contentElement","editable","syncEditorRootToInput","root","EditableHook","sync","CustomEditorPluginsRegistry","name","reader","isSingleEditingLikeEditor","editorType","loadEditorConstructor","type","PKG","EditorConstructor","loadEditorPlugins","plugins","basePackage","premiumPackage","loaders","plugin","customPlugin","basePkgImport","error","premiumPkgImport","loadAllEditorTranslations","language","hasPremium","translations","loadEditorPkgTranslations","pkg","lang","pack","loadEditorTranslation","normalizeCustomTranslations","dictionary","queryAllEditorEditables","iterator","acc","element","content","EDITOR_TYPES","readPresetOrThrow","attributeValue","config","license","customTranslations","setEditorEditableHeight","height","writer","EditorHookImpl","preset","editableHeight","events","saveDebounceMs","Constructor","rootEditables","getInitialRootsContentElements","loadedPlugins","mixedTranslations","getInitialRootsValues","data","syncEditorToInput","pushContentChange","getEditorRootsValues","eventType","pushEvent","isFocused","newValue","getParentFormElement","queryDecoupledMainEditableOrThrow","editables","mainEditable","EditorHook","UIPartHookImpl","uiViewName","mapUIPartView","uiPart","UIPartHook","Hooks"],"mappings":"2hBAAO,SAASA,EACdC,EACAC,EACkC,CAClC,IAAIC,EAAkD,KAEtD,MAAO,IAAIC,IAA8B,CACnCD,GACF,aAAaA,CAAS,EAGxBA,EAAY,WAAW,IAAM,CAC3BD,EAAS,GAAGE,CAAI,CAClB,EAAGH,CAAK,CACV,CACF,CCLO,MAAeI,CAAU,CAK9B,GAKA,WAQA,UAaA,YAYA,WA+BF,CAOO,SAASC,EAASC,EAAkF,CACzG,MAAO,CAKL,SAAmB,CACjB,MAAMC,EAAW,IAAID,EAErB,YAAK,GAAG,SAAWC,EAEnBA,EAAS,GAAK,KAAK,GACnBA,EAAS,WAAa,KAAK,WAE3BA,EAAS,UAAY,CAACC,EAAOC,EAASR,IAAa,KAAK,YAAYO,EAAOC,EAASR,CAAQ,EAC5FM,EAAS,YAAc,CAACG,EAAUF,EAAOC,EAASR,IAAa,KAAK,cAAcS,EAAUF,EAAOC,EAASR,CAAQ,EACpHM,EAAS,YAAc,CAACC,EAAOP,IAAa,KAAK,cAAcO,EAAOP,CAAQ,EAEvEM,EAAS,UAAA,CAClB,EAKA,cAAwB,CACtB,KAAK,GAAG,SAAS,eAAA,CACnB,EAKA,WAAqB,CACnB,KAAK,GAAG,SAAS,YAAA,CACnB,EAKA,cAAwB,CACtB,KAAK,GAAG,SAAS,eAAA,CACnB,EAKA,aAAuB,CACrB,KAAK,GAAG,SAAS,cAAA,CACnB,CAAA,CAEJ,CC5IO,SAASI,EAAcC,EAAuC,CACnE,OAAO,OAAO,KAAKA,CAAG,EAAE,SAAW,GAAKA,EAAI,cAAgB,MAC9D,CCOO,SAASC,EACdD,EACAE,EACmB,CACnB,MAAMC,EAAgB,OACnB,QAAQH,CAAG,EACX,IAAI,CAAC,CAACI,EAAKC,CAAK,IAAM,CAACD,EAAKF,EAAOG,EAAOD,CAAG,CAAC,CAAU,EAE3D,OAAO,OAAO,YAAYD,CAAa,CACzC,CClBO,SAASG,EAAkBD,EAAqC,CACrE,GAAIA,IAAU,KACZ,OAAO,KAGT,MAAME,EAAS,OAAO,SAASF,EAAO,EAAE,EAExC,OAAO,OAAO,MAAME,CAAM,EAAI,KAAOA,CACvC,CCAO,MAAMC,CAAgB,CAC3B,OAAgB,IAAM,IAAIA,EAKT,YAAc,IAKd,cAAgB,IAKhB,aAAe,IAKxB,aAAc,CAAC,CAUvB,QAAsCC,EAA2BC,EAA2C,CAC1G,KAAM,CAAE,UAAAC,EAAW,QAAAC,CAAA,EAAY,KACzBC,EAASD,EAAQ,IAAIH,CAAQ,EAEnC,OAAII,EACK,QAAQ,QAAQH,EAAGG,CAAW,CAAC,EAGjC,IAAI,QAASC,GAAY,CAC9B,MAAMzB,EAAW,MAAOwB,GAAcC,EAAQ,MAAMJ,EAAGG,CAAM,CAAC,EAEzD,KAAK,UAAU,IAAIJ,CAAQ,GAC9BE,EAAU,IAAIF,EAAU,EAAE,EAG5BE,EAAU,IAAIF,EAAU,CACtB,GAAGE,EAAU,IAAIF,CAAQ,EACzBpB,CAAA,CACD,CACH,CAAC,CACH,CAQA,SAASoB,EAA2BI,EAAsB,CACxD,KAAM,CAAE,QAAAD,EAAS,UAAAD,CAAA,EAAc,KACzBI,EAAqBJ,EAAU,IAAIF,CAAQ,EAEjD,GAAIG,EAAQ,IAAIH,CAAQ,EACtB,MAAM,IAAI,MAAM,mBAAmBA,CAAQ,0BAA0B,EAGvEG,EAAQ,IAAIH,EAAUI,CAAM,EAExBE,IACFA,EAAmB,QAAQ1B,GAAYA,EAASwB,CAAM,CAAC,EACvDF,EAAU,OAAOF,CAAQ,GAKvB,KAAK,QAAQ,OAAS,GACxB,KAAK,SAAS,KAAMI,CAAM,EAG5B,KAAK,eAAA,CACP,CAOA,WAAWJ,EAAiC,CAC1C,KAAM,CAAE,QAAAG,EAAS,UAAAD,CAAA,EAAc,KAE/B,GAAI,CAACC,EAAQ,IAAIH,CAAQ,EACvB,MAAM,IAAI,MAAM,mBAAmBA,CAAQ,sBAAsB,EAG/DA,GAAY,KAAK,QAAQ,IAAI,IAAI,IAAMG,EAAQ,IAAIH,CAAQ,GAC7D,KAAK,WAAW,IAAI,EAGtBG,EAAQ,OAAOH,CAAQ,EACvBE,EAAU,OAAOF,CAAQ,EAEzB,KAAK,eAAA,CACP,CAKA,YAAuB,CACrB,OAAO,MAAM,KAAK,KAAK,QAAQ,QAAQ,CACzC,CAQA,UAAUA,EAAoC,CAC5C,OAAO,KAAK,QAAQ,IAAIA,CAAQ,CAClC,CASA,cAAgCA,EAAuC,CACrE,OAAO,KAAK,QAAQA,EAAUI,GAAUA,CAAW,CACrD,CAMA,MAAM,mBAAoB,CACxB,MAAMG,EACJ,MACG,KAAK,KAAK,QAAQ,QAAQ,EAC1B,IAAIH,GAAUA,EAAO,QAAA,CAAS,EAGnC,KAAK,QAAQ,MAAA,EACb,KAAK,UAAU,MAAA,EAEf,MAAM,QAAQ,IAAIG,CAAQ,EAE1B,KAAK,eAAA,CACP,CAQA,MAAMC,EAAqC,CACzC,YAAK,SAAS,IAAIA,CAAO,EAGzBA,EAAQ,IAAI,IAAI,KAAK,OAAO,CAAC,EAEtB,KAAK,QAAQ,KAAK,KAAMA,CAAO,CACxC,CAOA,QAAQA,EAA+B,CACrC,KAAK,SAAS,OAAOA,CAAO,CAC9B,CAKQ,gBAAuB,CAC7B,MAAMC,EAAc,IAAI,IAAI,KAAK,OAAO,EACxC,KAAK,SAAS,QAAQD,GAAWA,EAAQC,CAAW,CAAC,CACvD,CACF,CCvLA,MAAMC,UAAyB3B,CAAU,CAI/B,eAAuC,KAK/C,IAAY,OAAQ,CAClB,MAAMa,EAAQ,CACZ,WAAY,KAAK,GAAG,aAAa,IAAI,EACrC,SAAU,KAAK,GAAG,aAAa,oBAAoB,GAAK,KACxD,SAAU,KAAK,GAAG,aAAa,6BAA6B,EAC5D,aAAc,KAAK,GAAG,aAAa,iCAAiC,GAAK,EAAA,EAG3E,cAAO,eAAe,KAAM,QAAS,CACnC,MAAAA,EACA,SAAU,GACV,aAAc,GACd,WAAY,EAAA,CACb,EAEMA,CACT,CAKA,MAAe,SAAU,CACvB,KAAM,CAAE,WAAAe,EAAY,SAAAX,EAAU,SAAAY,EAAU,aAAAC,CAAA,EAAiB,KAAK,MACxDC,EAAQ,KAAK,GAAG,cAAgC,IAAIH,CAAU,QAAQ,EAG5E,KAAK,eAAiBZ,EAAgB,IAAI,QAAQC,EAAWI,GAA4B,CACvF,KAAM,CAAE,GAAAW,EAAI,QAAAC,EAAS,MAAAC,CAAA,EAAUb,EAE/B,GAAIa,EAAM,SAAS,QAAQL,CAAQ,EACjC,OAGFR,EAAO,QAAQQ,EAAU,CACvB,WAAY,GACZ,KAAMC,CAAA,CACP,EAED,MAAMK,EAAiB,KAAK,GAAG,cAAc,6BAA6B,EACpEC,EAAWJ,EAAG,KAAK,eAAeH,EAAUM,CAAe,EAEjEH,EAAG,YAAYI,CAAQ,EACvBH,EAAQ,KAAK,YAAA,EAETF,GACFM,EAAsBN,EAAOV,EAAQQ,CAAQ,CAEjD,CAAC,CACH,CAKA,MAAe,WAAY,CACzB,KAAM,CAAE,SAAAZ,EAAU,SAAAY,CAAA,EAAa,KAAK,MAGpC,KAAK,GAAG,MAAM,QAAU,OAGxB,MAAM,KAAK,eACX,KAAK,eAAiB,KAGtB,MAAMb,EAAgB,IAAI,QAAQC,EAAWI,GAA4B,CACvE,MAAMiB,EAAOjB,EAAO,MAAM,SAAS,QAAQQ,CAAQ,EAE/CS,IACFjB,EAAO,eAAeiB,CAAI,EAC1BjB,EAAO,WAAWQ,EAAU,EAAK,EAErC,CAAC,CACH,CACF,CAKO,MAAMU,EAAetC,EAAS0B,CAAgB,EAUrD,SAASU,EAAsBN,EAAyBV,EAAyBQ,EAAkB,CACjG,MAAMW,EAAO,IAAM,CACjBT,EAAM,MAAQV,EAAO,QAAQ,CAAE,SAAAQ,EAAU,CAC3C,EAEAR,EAAO,MAAM,SAAS,GAAG,cAAe1B,EAAS,IAAK6C,CAAI,CAAC,EAC3DA,EAAA,CACF,CCtGO,MAAMC,CAA4B,CACvC,OAAgB,IAAM,IAAIA,EAKT,YAAc,IAKvB,aAAc,CAAC,CASvB,SAASC,EAAcC,EAAkC,CACvD,GAAI,KAAK,QAAQ,IAAID,CAAI,EACvB,MAAM,IAAI,MAAM,qBAAqBA,CAAI,0BAA0B,EAGrE,YAAK,QAAQ,IAAIA,EAAMC,CAAM,EAEtB,KAAK,WAAW,KAAK,KAAMD,CAAI,CACxC,CAQA,WAAWA,EAAoB,CAC7B,GAAI,CAAC,KAAK,QAAQ,IAAIA,CAAI,EACxB,MAAM,IAAI,MAAM,qBAAqBA,CAAI,sBAAsB,EAGjE,KAAK,QAAQ,OAAOA,CAAI,CAC1B,CAMA,eAAsB,CACpB,KAAK,QAAQ,MAAA,CACf,CAQA,MAAM,IAAIA,EAAsD,CAG9D,OAFe,KAAK,QAAQ,IAAIA,CAAI,IAE7B,CACT,CAQA,IAAIA,EAAuB,CACzB,OAAO,KAAK,QAAQ,IAAIA,CAAI,CAC9B,CACF,CC3EO,SAASE,EAA0BC,EAAiC,CACzE,MAAO,CAAC,SAAU,UAAW,UAAW,WAAW,EAAE,SAASA,CAAU,CAC1E,CCFA,eAAsBC,EAAsBC,EAAkB,CAC5D,MAAMC,EAAM,KAAM,QAAO,WAAW,EAU9BC,EARY,CAChB,OAAQD,EAAI,aACZ,QAASA,EAAI,cACb,QAASA,EAAI,cACb,UAAWA,EAAI,gBACf,UAAWA,EAAI,eAAA,EAGmBD,CAAI,EAExC,GAAI,CAACE,EACH,MAAM,IAAI,MAAM,4BAA4BF,CAAI,EAAE,EAGpD,OAAOE,CACT,CCZA,eAAsBC,EAAkBC,EAAiD,CACvF,MAAMC,EAAmC,KAAM,QAAO,WAAW,EACjE,IAAIC,EAA6C,KAEjD,MAAMC,EAAUH,EAAQ,IAAI,MAAOI,GAAW,CAM5C,MAAMC,EAAe,MAAMf,EAA4B,IAAI,IAAIc,CAAM,EAErE,GAAIC,EACF,OAAOA,EAIT,KAAM,CAAE,CAACD,CAAM,EAAGE,GAAkBL,EAEpC,GAAIK,EACF,OAAOA,EAIT,GAAI,CAACJ,EACH,GAAI,CACFA,EAAiB,KAAM,QAAO,4BAA4B,CAC5D,OACOK,EAAO,CACZ,QAAQ,MAAM,mCAAmCA,CAAK,EAAE,CAC1D,CAGF,KAAM,CAAE,CAACH,CAAM,EAAGI,CAAA,EAAqBN,GAAkB,CAAA,EAEzD,GAAIM,EACF,OAAOA,EAIT,MAAM,IAAI,MAAM,WAAWJ,CAAM,0CAA0C,CAE7E,CAAC,EAED,MAAO,CACL,cAAe,MAAM,QAAQ,IAAID,CAAO,EACxC,WAAY,CAAC,CAACD,CAAA,CAElB,CCrDA,eAAsBO,EACpBC,EACAC,EACA,CACA,MAAMC,EAAe,CAACF,EAAS,GAAIA,EAAS,OAAO,EAUnD,OAT2B,MAAM,QAAQ,IACvC,CACEG,EAA0B,YAAaD,CAAY,EAEnDD,GAAcE,EAA0B,6BAA8BD,CAAY,CAAA,EAClF,OAAOE,GAAO,CAAC,CAACA,CAAG,CAAA,EAEpB,KAAKF,GAAgBA,EAAa,MAAM,CAG7C,CAWA,eAAeC,EACbC,EACAF,EACA,CAEA,OAAO,MAAM,QAAQ,IACnBA,EACG,OAAOG,GAAQA,IAAS,IAAI,EAC5B,IAAI,MAAOA,GAAS,CACnB,MAAMC,EAAO,MAAMC,EAAsBH,EAAKC,CAAI,EAGlD,OAAOC,GAAM,SAAWA,CAC1B,CAAC,EACA,OAAO,OAAO,CAAA,CAErB,CAaA,eAAeC,EAAsBH,EAAoBC,EAA4B,CACnF,GAAI,CAEF,GAAID,IAAQ,YAEV,OAAQC,EAAA,CACN,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,KAAM,OAAO,KAAM,QAAO,8BAA8B,EAC7D,IAAK,MAAO,OAAO,KAAM,QAAO,+BAA+B,EAC/D,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,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,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,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,UAAW,OAAO,KAAM,QAAO,mCAAmC,EACvE,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,QAAS,OAAO,KAAM,QAAO,iCAAiC,EACnE,QACE,eAAQ,KAAK,YAAYA,CAAI,sCAAsC,EAC5D,IAAA,KAMX,QAAQA,EAAA,CACN,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,MAAO,OAAO,KAAM,QAAO,gDAAgD,EAChF,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,QAAS,OAAO,KAAM,QAAO,kDAAkD,EACpF,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,QAAS,OAAO,KAAM,QAAO,kDAAkD,EACpF,IAAK,QAAS,OAAO,KAAM,QAAO,kDAAkD,EACpF,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,QAAS,OAAO,KAAM,QAAO,kDAAkD,EACpF,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,QAAS,OAAO,KAAM,QAAO,kDAAkD,EACpF,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EA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"}