{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/first.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/language.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/env.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/focustracker.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/keyboard.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/keystrokehandler.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/locale.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/index.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/eventinfo.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/fastdiff.js","webpack:///./node_modules/@ckeditor/ckeditor5-utils/src/isiterable.js"],"names":["first","iterable","iteratorItem","next","done","value","__webpack_require__","d","__webpack_exports__","RTL_LANGUAGE_CODES","getLanguageDirection","languageCode","includes","userAgent","navigator","toLowerCase","env","isMac","isGecko","isSafari","isAndroid","isBlink","features","isRegExpUnicodePropertySupported","indexOf","match","isSupported","search","RegExp","error","FocusTracker","Object","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_3__","this","set","_elements","Set","_nextEventLoopTimeout","element","_this","has","CKEditorError","listenTo","_focus","useCapture","_blur","add","focusedElement","stopListening","delete","clearTimeout","isFocused","_this2","setTimeout","mix","DomEmitterMixin","ObservableMixin","modifiersToGlyphsMac","ctrl","cmd","alt","shift","modifiersToGlyphsNonMac","keyCodes","generateKnownKeyCodes","keyCodeNames","fromEntries","entries","map","_ref","_ref2","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_slicedToArray_js__WEBPACK_IMPORTED_MODULE_3__","name","code","charAt","toUpperCase","slice","getCode","key","keyCode","altKey","ctrlKey","shiftKey","metaKey","parseKeystroke","keystroke","splitKeystrokeText","getEnvKeyCode","reduce","sum","getEnvKeystrokeText","keystrokeCode","modifiersToGlyphs","modifiers","_ref3","_ref4","glyph","isArrowKeyCode","arrowright","arrowleft","arrowup","arrowdown","getLocalizedArrowKeyCodeDirection","contentLanguageDirection","isLtrContent","endsWith","isForwardArrowKeyCode","localizedKeyCodeDirection","backspace","enter","space","esc","tab","letter","String","fromCharCode","split","trim","KeystrokeHandler","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_0__","_listener","create","emitter","evt","keyEvtData","fire","callback","options","arguments","length","undefined","priority","preventDefault","stopPropagation","stop","return","Locale","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_classCallCheck_js__WEBPACK_IMPORTED_MODULE_1__","uiLanguage","contentLanguage","uiLanguageDirection","t","message","values","_t","console","warn","toArray","string","hasPluralForm","plural","quantity","translatedString","_translate","interpolateString","replace","index","_env__WEBPACK_IMPORTED_MODULE_0__","_mix__WEBPACK_IMPORTED_MODULE_2__","_observablemixin__WEBPACK_IMPORTED_MODULE_4__","_ckeditorerror__WEBPACK_IMPORTED_MODULE_5__","_elementreplacer__WEBPACK_IMPORTED_MODULE_6__","_dom_createelement__WEBPACK_IMPORTED_MODULE_7__","_dom_global__WEBPACK_IMPORTED_MODULE_9__","_dom_getdatafromelement__WEBPACK_IMPORTED_MODULE_10__","_keyboard__WEBPACK_IMPORTED_MODULE_15__","_collection__WEBPACK_IMPORTED_MODULE_18__","_first__WEBPACK_IMPORTED_MODULE_19__","_focustracker__WEBPACK_IMPORTED_MODULE_20__","_keystrokehandler__WEBPACK_IMPORTED_MODULE_21__","_toarray__WEBPACK_IMPORTED_MODULE_22__","_tomap__WEBPACK_IMPORTED_MODULE_23__","EventInfo","source","path","spy","off","fastDiff","a","b","cmp","atomicChanges","Array","isArray","prototype","call","changeIndexes","findChangeBoundaryIndexes","changeIndexesToAtomicChanges","changeIndexesToChanges","arr1","arr2","firstIndex","findFirstDifferenceIndex","lastIndexOld","lastIndexNew","oldArrayReversed","cutAndReverse","newArrayReversed","lastIndex","i","Math","max","arr","howMany","reverse","newArray","result","push","type","newLength","fill","concat","isIterable","Symbol","iterator"],"mappings":"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","file":"js/chunk-6cb75c84.cfcaa915.js","sourcesContent":["/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module utils/first\n */\n\n/**\n * Returns first item of the given `iterable`.\n *\n * @param {Iterable.<*>} iterable\n * @returns {*}\n */\nexport default function first( iterable ) {\n\tconst iteratorItem = iterable.next();\n\n\tif ( iteratorItem.done ) {\n\t\treturn null;\n\t}\n\n\treturn iteratorItem.value;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module utils/language\n */\n\nconst RTL_LANGUAGE_CODES = [\n\t'ar', 'ara', // Arabic\n\t'fa', 'per', 'fas', // Persian\n\t'he', 'heb', // Hebrew\n\t'ku', 'kur', // Kurdish\n\t'ug', 'uig' // Uighur, Uyghur\n];\n\n/**\n * Helps determine whether a language text direction is LTR or RTL.\n *\n * @param {String} language The ISO 639-1 or ISO 639-2 language code.\n * @returns {'ltr'|'rtl'}\n */\nexport function getLanguageDirection( languageCode ) {\n\treturn RTL_LANGUAGE_CODES.includes( languageCode ) ? 'rtl' : 'ltr';\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* globals navigator:false */\n\n/**\n * @module utils/env\n */\n\nconst userAgent = navigator.userAgent.toLowerCase();\n\n/**\n * A namespace containing environment and browser information.\n *\n * @namespace\n */\nconst env = {\n\t/**\n\t * Indicates that the application is running on Macintosh.\n\t *\n\t * @static\n\t * @type {Boolean}\n\t */\n\tisMac: isMac( userAgent ),\n\n\t/**\n\t * Indicates that the application is running in Firefox (Gecko).\n\t *\n\t * @static\n\t * @type {Boolean}\n\t */\n\tisGecko: isGecko( userAgent ),\n\n\t/**\n\t * Indicates that the application is running in Safari.\n\t *\n\t * @static\n\t * @type {Boolean}\n\t */\n\tisSafari: isSafari( userAgent ),\n\n\t/**\n\t * Indicates that the application is running on Android mobile device.\n\t *\n\t * @static\n\t * @type {Boolean}\n\t */\n\tisAndroid: isAndroid( userAgent ),\n\n\t/**\n\t * Indicates that the application is running in a browser using the Blink engine.\n\t *\n\t * @static\n\t * @type {Boolean}\n\t */\n\tisBlink: isBlink( userAgent ),\n\n\t/**\n\t * Environment features information.\n\t *\n\t * @memberOf module:utils/env~env\n\t * @namespace\n\t */\n\tfeatures: {\n\t\t/**\n\t\t * Indicates that the environment supports ES2018 Unicode property escapes — like `\\p{P}` or `\\p{L}`.\n\t\t * More information about unicode properties might be found\n\t\t * [in Unicode Standard Annex #44](https://www.unicode.org/reports/tr44/#GC_Values_Table).\n\t\t *\n\t\t * @type {Boolean}\n\t\t */\n\t\tisRegExpUnicodePropertySupported: isRegExpUnicodePropertySupported()\n\t}\n};\n\nexport default env;\n\n/**\n * Checks if User Agent represented by the string is running on Macintosh.\n *\n * @param {String} userAgent **Lowercase** `navigator.userAgent` string.\n * @returns {Boolean} Whether User Agent is running on Macintosh or not.\n */\nexport function isMac( userAgent ) {\n\treturn userAgent.indexOf( 'macintosh' ) > -1;\n}\n\n/**\n * Checks if User Agent represented by the string is Firefox (Gecko).\n *\n * @param {String} userAgent **Lowercase** `navigator.userAgent` string.\n * @returns {Boolean} Whether User Agent is Firefox or not.\n */\nexport function isGecko( userAgent ) {\n\treturn !!userAgent.match( /gecko\\/\\d+/ );\n}\n\n/**\n * Checks if User Agent represented by the string is Safari.\n *\n * @param {String} userAgent **Lowercase** `navigator.userAgent` string.\n * @returns {Boolean} Whether User Agent is Safari or not.\n */\nexport function isSafari( userAgent ) {\n\treturn userAgent.indexOf( ' applewebkit/' ) > -1 && userAgent.indexOf( 'chrome' ) === -1;\n}\n\n/**\n * Checks if User Agent represented by the string is Android mobile device.\n *\n * @param {String} userAgent **Lowercase** `navigator.userAgent` string.\n * @returns {Boolean} Whether User Agent is Safari or not.\n */\nexport function isAndroid( userAgent ) {\n\treturn userAgent.indexOf( 'android' ) > -1;\n}\n\n/**\n * Checks if User Agent represented by the string is Blink engine.\n *\n * @param {String} userAgent **Lowercase** `navigator.userAgent` string.\n * @returns {Boolean} Whether User Agent is Blink engine or not.\n */\nexport function isBlink( userAgent ) {\n\t// The Edge browser before switching to the Blink engine used to report itself as Chrome (and \"Edge/\")\n\t// but after switching to the Blink it replaced \"Edge/\" with \"Edg/\".\n\treturn userAgent.indexOf( 'chrome/' ) > -1 && userAgent.indexOf( 'edge/' ) < 0;\n}\n\n/**\n * Checks if the current environment supports ES2018 Unicode properties like `\\p{P}` or `\\p{L}`.\n * More information about unicode properties might be found\n * [in Unicode Standard Annex #44](https://www.unicode.org/reports/tr44/#GC_Values_Table).\n *\n * @returns {Boolean}\n */\nexport function isRegExpUnicodePropertySupported() {\n\tlet isSupported = false;\n\n\t// Feature detection for Unicode properties. Added in ES2018. Currently Firefox does not support it.\n\t// See https://github.com/ckeditor/ckeditor5-mention/issues/44#issuecomment-487002174.\n\n\ttry {\n\t\t// Usage of regular expression literal cause error during build (ckeditor/ckeditor5-dev#534).\n\t\tisSupported = 'ć'.search( new RegExp( '[\\\\p{L}]', 'u' ) ) === 0;\n\t} catch ( error ) {\n\t\t// Firefox throws a SyntaxError when the group is unsupported.\n\t}\n\n\treturn isSupported;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* global setTimeout, clearTimeout */\n\n/**\n * @module utils/focustracker\n */\n\nimport DomEmitterMixin from './dom/emittermixin';\nimport ObservableMixin from './observablemixin';\nimport CKEditorError from './ckeditorerror';\nimport mix from './mix';\n\n/**\n * Allows observing a group of `HTMLElement`s whether at least one of them is focused.\n *\n * Used by the {@link module:core/editor/editor~Editor} in order to track whether the focus is still within the application,\n * or were used outside of its UI.\n *\n * **Note** `focus` and `blur` listeners use event capturing, so it is only needed to register wrapper `HTMLElement`\n * which contain other `focusable` elements. But note that this wrapper element has to be focusable too\n * (have e.g. `tabindex=\"-1\"`).\n *\n * Check out the {@glink framework/guides/deep-dive/ui/focus-tracking \"Deep dive into focus tracking\" guide} to learn more.\n *\n * @mixes module:utils/dom/emittermixin~EmitterMixin\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class FocusTracker {\n\tconstructor() {\n\t\t/**\n\t\t * True when one of the registered elements is focused.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Boolean} #isFocused\n\t\t */\n\t\tthis.set( 'isFocused', false );\n\n\t\t/**\n\t\t * The currently focused element.\n\t\t *\n\t\t * While {@link #isFocused `isFocused`} remains `true`, the focus can\n\t\t * move between different UI elements. This property tracks those\n\t\t * elements and tells which one is currently focused.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {HTMLElement|null} #focusedElement\n\t\t */\n\t\tthis.set( 'focusedElement', null );\n\n\t\t/**\n\t\t * List of registered elements.\n\t\t *\n\t\t * @private\n\t\t * @member {Set.}\n\t\t */\n\t\tthis._elements = new Set();\n\n\t\t/**\n\t\t * Event loop timeout.\n\t\t *\n\t\t * @private\n\t\t * @member {Number}\n\t\t */\n\t\tthis._nextEventLoopTimeout = null;\n\t}\n\n\t/**\n\t * Starts tracking the specified element.\n\t *\n\t * @param {HTMLElement} element\n\t */\n\tadd( element ) {\n\t\tif ( this._elements.has( element ) ) {\n\t\t\t/**\n\t\t\t * This element is already tracked by {@link module:utils/focustracker~FocusTracker}.\n\t\t\t *\n\t\t\t * @error focustracker-add-element-already-exist\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'focustracker-add-element-already-exist', this );\n\t\t}\n\n\t\tthis.listenTo( element, 'focus', () => this._focus( element ), { useCapture: true } );\n\t\tthis.listenTo( element, 'blur', () => this._blur(), { useCapture: true } );\n\t\tthis._elements.add( element );\n\t}\n\n\t/**\n\t * Stops tracking the specified element and stops listening on this element.\n\t *\n\t * @param {HTMLElement} element\n\t */\n\tremove( element ) {\n\t\tif ( element === this.focusedElement ) {\n\t\t\tthis._blur( element );\n\t\t}\n\n\t\tif ( this._elements.has( element ) ) {\n\t\t\tthis.stopListening( element );\n\t\t\tthis._elements.delete( element );\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the focus tracker by:\n\t * - Disabling all event listeners attached to tracked elements.\n\t * - Removing all tracked elements that were previously added.\n\t */\n\tdestroy() {\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Stores currently focused element and set {#isFocused} as `true`.\n\t *\n\t * @private\n\t * @param {HTMLElement} element Element which has been focused.\n\t */\n\t_focus( element ) {\n\t\tclearTimeout( this._nextEventLoopTimeout );\n\n\t\tthis.focusedElement = element;\n\t\tthis.isFocused = true;\n\t}\n\n\t/**\n\t * Clears currently focused element and set {@link #isFocused} as `false`.\n\t * This method uses `setTimeout` to change order of fires `blur` and `focus` events.\n\t *\n\t * @private\n\t * @fires blur\n\t */\n\t_blur() {\n\t\tclearTimeout( this._nextEventLoopTimeout );\n\n\t\tthis._nextEventLoopTimeout = setTimeout( () => {\n\t\t\tthis.focusedElement = null;\n\t\t\tthis.isFocused = false;\n\t\t}, 0 );\n\t}\n\n\t/**\n\t * @event focus\n\t */\n\n\t/**\n\t * @event blur\n\t */\n}\n\nmix( FocusTracker, DomEmitterMixin );\nmix( FocusTracker, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * A set of utilities related to keyboard support.\n *\n * @module utils/keyboard\n */\n\nimport CKEditorError from './ckeditorerror';\nimport env from './env';\n\nconst modifiersToGlyphsMac = {\n\tctrl: '⌃',\n\tcmd: '⌘',\n\talt: '⌥',\n\tshift: '⇧'\n};\n\nconst modifiersToGlyphsNonMac = {\n\tctrl: 'Ctrl+',\n\talt: 'Alt+',\n\tshift: 'Shift+'\n};\n\n/**\n * An object with `keyName => keyCode` pairs for a set of known keys.\n *\n * Contains:\n *\n * * `a-z`,\n * * `0-9`,\n * * `f1-f12`,\n * * `arrow(left|up|right|bottom)`,\n * * `backspace`, `delete`, `enter`, `esc`, `tab`,\n * * `ctrl`, `cmd`, `shift`, `alt`.\n */\nexport const keyCodes = generateKnownKeyCodes();\n\nconst keyCodeNames = Object.fromEntries(\n\tObject.entries( keyCodes ).map( ( [ name, code ] ) => [ code, name.charAt( 0 ).toUpperCase() + name.slice( 1 ) ] )\n);\n\n/**\n * Converts a key name or {@link module:utils/keyboard~KeystrokeInfo keystroke info} into a key code.\n *\n * Note: Key names are matched with {@link module:utils/keyboard~keyCodes} in a case-insensitive way.\n *\n * @param {String|module:utils/keyboard~KeystrokeInfo} A key name (see {@link module:utils/keyboard~keyCodes})\n * or a keystroke data object.\n * @returns {Number} Key or keystroke code.\n */\nexport function getCode( key ) {\n\tlet keyCode;\n\n\tif ( typeof key == 'string' ) {\n\t\tkeyCode = keyCodes[ key.toLowerCase() ];\n\n\t\tif ( !keyCode ) {\n\t\t\t/**\n\t\t\t * Unknown key name. Only key names included in the {@link module:utils/keyboard~keyCodes} can be used.\n\t\t\t *\n\t\t\t * @error keyboard-unknown-key\n\t\t\t * @param {String} key\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'keyboard-unknown-key', null, { key } );\n\t\t}\n\t} else {\n\t\tkeyCode = key.keyCode +\n\t\t\t( key.altKey ? keyCodes.alt : 0 ) +\n\t\t\t( key.ctrlKey ? keyCodes.ctrl : 0 ) +\n\t\t\t( key.shiftKey ? keyCodes.shift : 0 ) +\n\t\t\t( key.metaKey ? keyCodes.cmd : 0 );\n\t}\n\n\treturn keyCode;\n}\n\n/**\n * Parses the keystroke and returns a keystroke code that will match the code returned by\n * {@link module:utils/keyboard~getCode} for the corresponding {@link module:utils/keyboard~KeystrokeInfo keystroke info}.\n *\n * The keystroke can be passed in two formats:\n *\n * * as a single string – e.g. `ctrl + A`,\n * * as an array of {@link module:utils/keyboard~keyCodes known key names} and key codes – e.g.:\n * * `[ 'ctrl', 32 ]` (ctrl + space),\n * * `[ 'ctrl', 'a' ]` (ctrl + A).\n *\n * Note: Key names are matched with {@link module:utils/keyboard~keyCodes} in a case-insensitive way.\n *\n * Note: Only keystrokes with a single non-modifier key are supported (e.g. `ctrl+A` is OK, but `ctrl+A+B` is not).\n *\n * Note: On macOS, keystroke handling is translating the `Ctrl` key to the `Cmd` key and handling only that keystroke.\n * For example, a registered keystroke `Ctrl+A` will be translated to `Cmd+A` on macOS. To disable the translation of some keystroke,\n * use the forced modifier: `Ctrl!+A` (note the exclamation mark).\n *\n * @param {String|Array.} keystroke The keystroke definition.\n * @returns {Number} Keystroke code.\n */\nexport function parseKeystroke( keystroke ) {\n\tif ( typeof keystroke == 'string' ) {\n\t\tkeystroke = splitKeystrokeText( keystroke );\n\t}\n\n\treturn keystroke\n\t\t.map( key => ( typeof key == 'string' ) ? getEnvKeyCode( key ) : key )\n\t\t.reduce( ( key, sum ) => sum + key, 0 );\n}\n\n/**\n * Translates any keystroke string text like `\"Ctrl+A\"` to an\n * environment–specific keystroke, i.e. `\"⌘A\"` on macOS.\n *\n * @param {String} keystroke The keystroke text.\n * @returns {String} The keystroke text specific for the environment.\n */\nexport function getEnvKeystrokeText( keystroke ) {\n\tlet keystrokeCode = parseKeystroke( keystroke );\n\n\tconst modifiersToGlyphs = Object.entries( env.isMac ? modifiersToGlyphsMac : modifiersToGlyphsNonMac );\n\n\tconst modifiers = modifiersToGlyphs.reduce( ( modifiers, [ name, glyph ] ) => {\n\t\t// Modifier keys are stored as a bit mask so extract those from the keystroke code.\n\t\tif ( ( keystrokeCode & keyCodes[ name ] ) != 0 ) {\n\t\t\tkeystrokeCode &= ~keyCodes[ name ];\n\t\t\tmodifiers += glyph;\n\t\t}\n\n\t\treturn modifiers;\n\t}, '' );\n\n\treturn modifiers + ( keystrokeCode ? keyCodeNames[ keystrokeCode ] : '' );\n}\n\n/**\n * Returns `true` if the provided key code represents one of the arrow keys.\n *\n * @param {Number} keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.\n * @returns {Boolean}\n */\nexport function isArrowKeyCode( keyCode ) {\n\treturn keyCode == keyCodes.arrowright ||\n\t\tkeyCode == keyCodes.arrowleft ||\n\t\tkeyCode == keyCodes.arrowup ||\n\t\tkeyCode == keyCodes.arrowdown;\n}\n\n/**\n * Returns the direction in which the {@link module:engine/model/documentselection~DocumentSelection selection}\n * will move when the provided arrow key code is pressed considering the language direction of the editor content.\n *\n * For instance, in right–to–left (RTL) content languages, pressing the left arrow means moving the selection right (forward)\n * in the model structure. Similarly, pressing the right arrow moves the selection left (backward).\n *\n * @param {Number} keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.\n * @param {'ltr'|'rtl'} contentLanguageDirection The content language direction, corresponding to\n * {@link module:utils/locale~Locale#contentLanguageDirection}.\n * @returns {'left'|'up'|'right'|'down'} Localized arrow direction.\n */\nexport function getLocalizedArrowKeyCodeDirection( keyCode, contentLanguageDirection ) {\n\tconst isLtrContent = contentLanguageDirection === 'ltr';\n\n\tswitch ( keyCode ) {\n\t\tcase keyCodes.arrowleft:\n\t\t\treturn isLtrContent ? 'left' : 'right';\n\n\t\tcase keyCodes.arrowright:\n\t\t\treturn isLtrContent ? 'right' : 'left';\n\n\t\tcase keyCodes.arrowup:\n\t\t\treturn 'up';\n\n\t\tcase keyCodes.arrowdown:\n\t\t\treturn 'down';\n\t}\n}\n\n// Converts a key name to the key code with mapping based on the env.\n//\n// See: {@link module:utils/keyboard~getCode}.\n//\n// @param {String} key The key name (see {@link module:utils/keyboard~keyCodes}).\n// @returns {Number} Key code.\nfunction getEnvKeyCode( key ) {\n\t// Don't remap modifier key for forced modifiers.\n\tif ( key.endsWith( '!' ) ) {\n\t\treturn getCode( key.slice( 0, -1 ) );\n\t}\n\n\tconst code = getCode( key );\n\n\treturn env.isMac && code == keyCodes.ctrl ? keyCodes.cmd : code;\n}\n\n/**\n * Determines if the provided key code moves the {@link module:engine/model/documentselection~DocumentSelection selection}\n * forward or backward considering the language direction of the editor content.\n *\n * For instance, in right–to–left (RTL) languages, pressing the left arrow means moving forward\n * in the model structure. Similarly, pressing the right arrow moves the selection backward.\n *\n * @param {Number} keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.\n * @param {'ltr'|'rtl'} contentLanguageDirection The content language direction, corresponding to\n * {@link module:utils/locale~Locale#contentLanguageDirection}.\n * @returns {Boolean}\n */\nexport function isForwardArrowKeyCode( keyCode, contentLanguageDirection ) {\n\tconst localizedKeyCodeDirection = getLocalizedArrowKeyCodeDirection( keyCode, contentLanguageDirection );\n\n\treturn localizedKeyCodeDirection === 'down' || localizedKeyCodeDirection === 'right';\n}\n\nfunction generateKnownKeyCodes() {\n\tconst keyCodes = {\n\t\tarrowleft: 37,\n\t\tarrowup: 38,\n\t\tarrowright: 39,\n\t\tarrowdown: 40,\n\t\tbackspace: 8,\n\t\tdelete: 46,\n\t\tenter: 13,\n\t\tspace: 32,\n\t\tesc: 27,\n\t\ttab: 9,\n\n\t\t// The idea about these numbers is that they do not collide with any real key codes, so we can use them\n\t\t// like bit masks.\n\t\tctrl: 0x110000,\n\t\tshift: 0x220000,\n\t\talt: 0x440000,\n\t\tcmd: 0x880000\n\t};\n\n\t// a-z\n\tfor ( let code = 65; code <= 90; code++ ) {\n\t\tconst letter = String.fromCharCode( code );\n\n\t\tkeyCodes[ letter.toLowerCase() ] = code;\n\t}\n\n\t// 0-9\n\tfor ( let code = 48; code <= 57; code++ ) {\n\t\tkeyCodes[ code - 48 ] = code;\n\t}\n\n\t// F1-F12\n\tfor ( let code = 112; code <= 123; code++ ) {\n\t\tkeyCodes[ 'f' + ( code - 111 ) ] = code;\n\t}\n\n\treturn keyCodes;\n}\n\nfunction splitKeystrokeText( keystroke ) {\n\treturn keystroke.split( '+' ).map( key => key.trim() );\n}\n\n/**\n * Information about the keystroke.\n *\n * @interface module:utils/keyboard~KeystrokeInfo\n */\n\n/**\n * The [key code](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode).\n *\n * @member {Number} module:utils/keyboard~KeystrokeInfo#keyCode\n */\n\n/**\n * Whether the Alt modifier was pressed.\n *\n * @member {Boolean} module:utils/keyboard~KeystrokeInfo#altKey\n */\n\n/**\n * Whether the Ctrl modifier was pressed.\n *\n * @member {Boolean} module:utils/keyboard~KeystrokeInfo#ctrlKey\n */\n\n/**\n * Whether the Shift modifier was pressed.\n *\n * @member {Boolean} module:utils/keyboard~KeystrokeInfo#shiftKey\n */\n\n/**\n * Whether the Cmd modifier was pressed.\n *\n * @member {Boolean} module:utils/keyboard~KeystrokeInfo#metaKey\n */\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module utils/keystrokehandler\n */\n\nimport DomEmitterMixin from './dom/emittermixin';\nimport { getCode, parseKeystroke } from './keyboard';\n\n/**\n * Keystroke handler allows registering callbacks for given keystrokes.\n *\n * The most frequent use of this class is through the {@link module:core/editor/editor~Editor#keystrokes `editor.keystrokes`}\n * property. It allows listening to keystrokes executed in the editing view:\n *\n *\t\teditor.keystrokes.set( 'Ctrl+A', ( keyEvtData, cancel ) => {\n *\t\t\tconsole.log( 'Ctrl+A has been pressed' );\n *\t\t\tcancel();\n *\t\t} );\n *\n * However, this utility class can be used in various part of the UI. For instance, a certain {@link module:ui/view~View}\n * can use it like this:\n *\n *\t\tclass MyView extends View {\n *\t\t\tconstructor() {\n *\t\t\t\tthis.keystrokes = new KeystrokeHandler();\n *\n * \t\t\t\tthis.keystrokes.set( 'tab', handleTabKey );\n *\t\t\t}\n *\n *\t\t\trender() {\n *\t\t\t\tsuper.render();\n *\n *\t\t\t\tthis.keystrokes.listenTo( this.element );\n *\t\t\t}\n *\t\t}\n *\n * That keystroke handler will listen to `keydown` events fired in this view's main element.\n *\n */\nexport default class KeystrokeHandler {\n\t/**\n\t * Creates an instance of the keystroke handler.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Listener used to listen to events for easier keystroke handler destruction.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:utils/dom/emittermixin~Emitter}\n\t\t */\n\t\tthis._listener = Object.create( DomEmitterMixin );\n\t}\n\n\t/**\n\t * Starts listening for `keydown` events from a given emitter.\n\t *\n\t * @param {module:utils/emittermixin~Emitter} emitter\n\t */\n\tlistenTo( emitter ) {\n\t\t// The #_listener works here as a kind of dispatcher. It groups the events coming from the same\n\t\t// keystroke so the listeners can be attached to them with different priorities.\n\t\t//\n\t\t// E.g. all the keystrokes with the `keyCode` of 42 coming from the `emitter` are propagated\n\t\t// as a `_keydown:42` event by the `_listener`. If there's a callback created by the `set`\n\t\t// method for this 42 keystroke, it listens to the `_listener#_keydown:42` event only and interacts\n\t\t// only with other listeners of this particular event, thus making it possible to prioritize\n\t\t// the listeners and safely cancel execution, when needed. Instead of duplicating the Emitter logic,\n\t\t// the KeystrokeHandler re–uses it to do its job.\n\t\tthis._listener.listenTo( emitter, 'keydown', ( evt, keyEvtData ) => {\n\t\t\tthis._listener.fire( '_keydown:' + getCode( keyEvtData ), keyEvtData );\n\t\t} );\n\t}\n\n\t/**\n\t * Registers a handler for the specified keystroke.\n\t *\n\t * @param {String|Array.} keystroke Keystroke defined in a format accepted by\n\t * the {@link module:utils/keyboard~parseKeystroke} function.\n\t * @param {Function} callback A function called with the\n\t * {@link module:engine/view/observer/keyobserver~KeyEventData key event data} object and\n\t * a helper funcion to call both `preventDefault()` and `stopPropagation()` on the underlying event.\n\t * @param {Object} [options={}] Additional options.\n\t * @param {module:utils/priorities~PriorityString|Number} [options.priority='normal'] The priority of the keystroke\n\t * callback. The higher the priority value the sooner the callback will be executed. Keystrokes having the same priority\n\t * are called in the order they were added.\n\t */\n\tset( keystroke, callback, options = {} ) {\n\t\tconst keyCode = parseKeystroke( keystroke );\n\t\tconst priority = options.priority;\n\n\t\t// Execute the passed callback on KeystrokeHandler#_keydown.\n\t\t// TODO: https://github.com/ckeditor/ckeditor5-utils/issues/144\n\t\tthis._listener.listenTo( this._listener, '_keydown:' + keyCode, ( evt, keyEvtData ) => {\n\t\t\tcallback( keyEvtData, () => {\n\t\t\t\t// Stop the event in the DOM: no listener in the web page\n\t\t\t\t// will be triggered by this event.\n\t\t\t\tkeyEvtData.preventDefault();\n\t\t\t\tkeyEvtData.stopPropagation();\n\n\t\t\t\t// Stop the event in the KeystrokeHandler: no more callbacks\n\t\t\t\t// will be executed for this keystroke.\n\t\t\t\tevt.stop();\n\t\t\t} );\n\n\t\t\t// Mark this keystroke as handled by the callback. See: #press.\n\t\t\tevt.return = true;\n\t\t}, { priority } );\n\t}\n\n\t/**\n\t * Triggers a keystroke handler for a specified key combination, if such a keystroke was {@link #set defined}.\n\t *\n\t * @param {module:engine/view/observer/keyobserver~KeyEventData} keyEvtData Key event data.\n\t * @returns {Boolean} Whether the keystroke was handled.\n\t */\n\tpress( keyEvtData ) {\n\t\treturn !!this._listener.fire( '_keydown:' + getCode( keyEvtData ), keyEvtData );\n\t}\n\n\t/**\n\t * Destroys the keystroke handler.\n\t */\n\tdestroy() {\n\t\tthis._listener.stopListening();\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module utils/locale\n */\n\n/* globals console */\n\nimport toArray from './toarray';\nimport { _translate } from './translation-service';\nimport { getLanguageDirection } from './language';\n\n/**\n * Represents the localization services.\n */\nexport default class Locale {\n\t/**\n\t * Creates a new instance of the locale class. Learn more about\n\t * {@glink features/ui-language configuring the language of the editor}.\n\t *\n\t * @param {Object} [options] Locale configuration.\n\t * @param {String} [options.uiLanguage='en'] The editor UI language code in the\n\t * [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format. See {@link #uiLanguage}.\n\t * @param {String} [options.contentLanguage] The editor content language code in the\n\t * [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format. If not specified, the same as `options.language`.\n\t * See {@link #contentLanguage}.\n\t */\n\tconstructor( options = {} ) {\n\t\t/**\n\t\t * The editor UI language code in the [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format.\n\t\t *\n\t\t * If the {@link #contentLanguage content language} was not specified in the `Locale` constructor,\n\t\t * it also defines the language of the content.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.uiLanguage = options.uiLanguage || 'en';\n\n\t\t/**\n\t\t * The editor content language code in the [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format.\n\t\t *\n\t\t * Usually the same as the {@link #uiLanguage editor language}, it can be customized by passing an optional\n\t\t * argument to the `Locale` constructor.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.contentLanguage = options.contentLanguage || this.uiLanguage;\n\n\t\t/**\n\t\t * Text direction of the {@link #uiLanguage editor UI language}. Either `'ltr'` or `'rtl'`.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.uiLanguageDirection = getLanguageDirection( this.uiLanguage );\n\n\t\t/**\n\t\t * Text direction of the {@link #contentLanguage editor content language}.\n\t\t *\n\t\t * If the content language was passed directly to the `Locale` constructor, this property represents the\n\t\t * direction of that language.\n\t\t *\n\t\t * If the {@link #contentLanguage editor content language} was derived from the {@link #uiLanguage editor language},\n\t\t * the content language direction is the same as the {@link #uiLanguageDirection UI language direction}.\n\t\t *\n\t\t * The value is either `'ltr'` or `'rtl'`.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.contentLanguageDirection = getLanguageDirection( this.contentLanguage );\n\n\t\t/**\n\t\t * Translates the given message to the {@link #uiLanguage}. This method is also available in\n\t\t * {@link module:core/editor/editor~Editor#t `Editor`} and {@link module:ui/view~View#t `View`}.\n\t\t *\n\t\t * This method's context is statically bound to the `Locale` instance and **should always be called as a function**:\n\t\t *\n\t\t *\t\tconst t = locale.t;\n\t\t *\t\tt( 'Label' );\n\t\t *\n\t\t * The message can be either a string or an object implementing the {@link module:utils/translation-service~Message} interface.\n\t\t *\n\t\t * The message may contain placeholders (`%`) for value(s) that are passed as a `values` parameter.\n\t\t * For an array of values, the `%` will be changed to an element of that array at the given index.\n\t\t * For a single value passed as the second argument, only the `%0` placeholders will be changed to the provided value.\n\t\t *\n\t\t *\t\tt( 'Created file \"%0\" in %1ms.', [ fileName, timeTaken ] );\n\t\t * \t\tt( 'Created file \"%0\", fileName );\n\t\t *\n\t\t * The message supports plural forms. To specify the plural form, use the `plural` property. Singular or plural form\n\t\t * will be chosen depending on the first value from the passed `values`. The value of the `plural` property is used\n\t\t * as a default plural translation when the translation for the target language is missing.\n\t\t *\n\t\t *\t\tt( { string: 'Add a space', plural: 'Add %0 spaces' }, 1 ); // 'Add a space' for the English language.\n\t\t *\t\tt( { string: 'Add a space', plural: 'Add %0 spaces' }, 5 ); // 'Add 5 spaces' for the English language.\n\t\t *\t\tt( { string: '%1 a space', plural: '%1 %0 spaces' }, [ 2, 'Add' ] ); // 'Add 2 spaces' for the English language.\n\t\t *\n\t\t * \t\tt( { string: 'Add a space', plural: 'Add %0 spaces' }, 1 ); // 'Dodaj spację' for the Polish language.\n\t\t *\t\tt( { string: 'Add a space', plural: 'Add %0 spaces' }, 5 ); // 'Dodaj 5 spacji' for the Polish language.\n\t\t *\t\tt( { string: '%1 a space', plural: '%1 %0 spaces' }, [ 2, 'Add' ] ); // 'Dodaj 2 spacje' for the Polish language.\n\t\t *\n\t\t * * The message should provide an ID using the `id` property when the message strings are not unique and their\n\t\t * translations should be different.\n\t\t *\n\t\t *\t\ttranslate( 'en', { string: 'image', id: 'ADD_IMAGE' } );\n\t\t *\t\ttranslate( 'en', { string: 'image', id: 'AN_IMAGE' } );\n\t\t *\n\t\t * @method #t\n\t\t * @param {String|module:utils/translation-service~Message} message A message that will be localized (translated).\n\t\t * @param {String|Number|Array.} [values] A value or an array of values that will fill message placeholders.\n\t\t * For messages supporting plural forms the first value will determine the plural form.\n\t\t * @returns {String}\n\t\t */\n\t\tthis.t = ( message, values ) => this._t( message, values );\n\t}\n\n\t/**\n\t * The editor UI language code in the [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format.\n\t *\n\t * **Note**: This property was deprecated. Please use {@link #uiLanguage} and {@link #contentLanguage}\n\t * properties instead.\n\t *\n\t * @deprecated\n\t * @member {String}\n\t */\n\tget language() {\n\t\t/**\n\t\t * The {@link module:utils/locale~Locale#language `Locale#language`} property was deprecated and will\n\t\t * be removed in the near future. Please use the {@link #uiLanguage} and {@link #contentLanguage} properties instead.\n\t\t *\n\t\t * @error locale-deprecated-language-property\n\t\t */\n\t\tconsole.warn(\n\t\t\t'locale-deprecated-language-property: ' +\n\t\t\t'The Locale#language property has been deprecated and will be removed in the near future. ' +\n\t\t\t'Please use #uiLanguage and #contentLanguage properties instead.' );\n\n\t\treturn this.uiLanguage;\n\t}\n\n\t/**\n\t * An unbound version of the {@link #t} method.\n\t *\n\t * @private\n\t * @param {String|module:utils/translation-service~Message} message\n\t * @param {Number|String|Array.} [values]\n\t * @returns {String}\n\t */\n\t_t( message, values = [] ) {\n\t\tvalues = toArray( values );\n\n\t\tif ( typeof message === 'string' ) {\n\t\t\tmessage = { string: message };\n\t\t}\n\n\t\tconst hasPluralForm = !!message.plural;\n\t\tconst quantity = hasPluralForm ? values[ 0 ] : 1;\n\n\t\tconst translatedString = _translate( this.uiLanguage, message, quantity );\n\n\t\treturn interpolateString( translatedString, values );\n\t}\n}\n\n// Fills the `%0, %1, ...` string placeholders with values.\nfunction interpolateString( string, values ) {\n\treturn string.replace( /%(\\d+)/g, ( match, index ) => {\n\t\treturn ( index < values.length ) ? values[ index ] : match;\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module utils\n */\n\nexport { default as env } from './env';\nexport { default as diff } from './diff';\n\nexport { default as mix } from './mix';\nexport { default as EmitterMixin } from './emittermixin';\nexport { default as ObservableMixin } from './observablemixin';\n\nexport { default as CKEditorError, logError, logWarning } from './ckeditorerror';\n\nexport { default as ElementReplacer } from './elementreplacer';\n\nexport { default as createElement } from './dom/createelement';\nexport { default as DomEmitterMixin } from './dom/emittermixin';\nexport { default as global } from './dom/global';\nexport { default as getDataFromElement } from './dom/getdatafromelement';\nexport { default as Rect } from './dom/rect';\nexport { default as ResizeObserver } from './dom/resizeobserver';\nexport { default as setDataInElement } from './dom/setdatainelement';\nexport { default as toUnit } from './dom/tounit';\n\nexport * from './keyboard';\nexport * from './language';\nexport { default as Locale } from './locale';\nexport { default as Collection } from './collection';\nexport { default as first } from './first';\nexport { default as FocusTracker } from './focustracker';\nexport { default as KeystrokeHandler } from './keystrokehandler';\nexport { default as toArray } from './toarray';\nexport { default as toMap } from './tomap';\nexport { default as priorities } from './priorities';\n\nexport { default as uid } from './uid';\n\nexport { default as version } from './version';\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module utils/eventinfo\n */\n\nimport spy from './spy';\n\n/**\n * The event object passed to event callbacks. It is used to provide information about the event as well as a tool to\n * manipulate it.\n */\nexport default class EventInfo {\n\t/**\n\t * @param {Object} source The emitter.\n\t * @param {String} name The event name.\n\t */\n\tconstructor( source, name ) {\n\t\t/**\n\t\t * The object that fired the event.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Object}\n\t\t */\n\t\tthis.source = source;\n\n\t\t/**\n\t\t * The event name.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.name = name;\n\n\t\t/**\n\t\t * Path this event has followed. See {@link module:utils/emittermixin~EmitterMixin#delegate}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Array.}\n\t\t */\n\t\tthis.path = [];\n\n\t\t// The following methods are defined in the constructor because they must be re-created per instance.\n\n\t\t/**\n\t\t * Stops the event emitter to call further callbacks for this event interaction.\n\t\t *\n\t\t * @method #stop\n\t\t */\n\t\tthis.stop = spy();\n\n\t\t/**\n\t\t * Removes the current callback from future interactions of this event.\n\t\t *\n\t\t * @method #off\n\t\t */\n\t\tthis.off = spy();\n\n\t\t/**\n\t\t * The value which will be returned by {@link module:utils/emittermixin~EmitterMixin#fire}.\n\t\t *\n\t\t * It's `undefined` by default and can be changed by an event listener:\n\t\t *\n\t\t *\t\tdataController.fire( 'getSelectedContent', ( evt ) => {\n\t\t *\t\t\t// This listener will make `dataController.fire( 'getSelectedContent' )`\n\t\t *\t\t\t// always return an empty DocumentFragment.\n\t\t *\t\t\tevt.return = new DocumentFragment();\n\t\t *\n\t\t *\t\t\t// Make sure no other listeners are executed.\n\t\t *\t\t\tevt.stop();\n\t\t *\t\t} );\n\t\t *\n\t\t * @member #return\n\t\t */\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module utils/fastdiff\n */\n\n/**\n * Finds positions of the first and last change in the given string/array and generates a set of changes:\n *\n *\t\tfastDiff( '12a', '12xyza' );\n *\t\t// [ { index: 2, type: 'insert', values: [ 'x', 'y', 'z' ] } ]\n *\n *\t\tfastDiff( '12a', '12aa' );\n *\t\t// [ { index: 3, type: 'insert', values: [ 'a' ] } ]\n *\n *\t\tfastDiff( '12xyza', '12a' );\n *\t\t// [ { index: 2, type: 'delete', howMany: 3 } ]\n *\n *\t\tfastDiff( [ '1', '2', 'a', 'a' ], [ '1', '2', 'a' ] );\n *\t\t// [ { index: 3, type: 'delete', howMany: 1 } ]\n *\n *\t\tfastDiff( [ '1', '2', 'a', 'b', 'c', '3' ], [ '2', 'a', 'b' ] );\n *\t\t// [ { index: 0, type: 'insert', values: [ '2', 'a', 'b' ] }, { index: 3, type: 'delete', howMany: 6 } ]\n *\n * Passed arrays can contain any type of data, however to compare them correctly custom comparator function\n * should be passed as a third parameter:\n *\n *\t\tfastDiff( [ { value: 1 }, { value: 2 } ], [ { value: 1 }, { value: 3 } ], ( a, b ) => {\n *\t\t\treturn a.value === b.value;\n *\t\t} );\n *\t\t// [ { index: 1, type: 'insert', values: [ { value: 3 } ] }, { index: 2, type: 'delete', howMany: 1 } ]\n *\n * The resulted set of changes can be applied to the input in order to transform it into the output, for example:\n *\n *\t\tlet input = '12abc3';\n *\t\tconst output = '2ab';\n *\t\tconst changes = fastDiff( input, output );\n *\n *\t\tchanges.forEach( change => {\n *\t\t\tif ( change.type == 'insert' ) {\n *\t\t\t\tinput = input.substring( 0, change.index ) + change.values.join( '' ) + input.substring( change.index );\n *\t\t\t} else if ( change.type == 'delete' ) {\n *\t\t\t\tinput = input.substring( 0, change.index ) + input.substring( change.index + change.howMany );\n *\t\t\t}\n *\t\t} );\n *\n *\t\t// input equals output now\n *\n * or in case of arrays:\n *\n *\t\tlet input = [ '1', '2', 'a', 'b', 'c', '3' ];\n *\t\tconst output = [ '2', 'a', 'b' ];\n *\t\tconst changes = fastDiff( input, output );\n *\n *\t\tchanges.forEach( change => {\n *\t\t\tif ( change.type == 'insert' ) {\n *\t\t\t\tinput = input.slice( 0, change.index ).concat( change.values, input.slice( change.index ) );\n *\t\t\t} else if ( change.type == 'delete' ) {\n *\t\t\t\tinput = input.slice( 0, change.index ).concat( input.slice( change.index + change.howMany ) );\n *\t\t\t}\n *\t\t} );\n *\n *\t\t// input equals output now\n *\n * By passing `true` as the fourth parameter (`atomicChanges`) the output of this function will become compatible with\n * the {@link module:utils/diff~diff `diff()`} function:\n *\n *\t\tfastDiff( '12a', '12xyza' );\n *\t\t// [ 'equal', 'equal', 'insert', 'insert', 'insert', 'equal' ]\n *\n * The default output format of this function is compatible with the output format of\n * {@link module:utils/difftochanges~diffToChanges `diffToChanges()`}. The `diffToChanges()` input format is, in turn,\n * compatible with the output of {@link module:utils/diff~diff `diff()`}:\n *\n *\t\tconst a = '1234';\n *\t\tconst b = '12xyz34';\n *\n *\t\t// Both calls will return the same results (grouped changes format).\n *\t\tfastDiff( a, b );\n *\t\tdiffToChanges( diff( a, b ) );\n *\n *\t\t// Again, both calls will return the same results (atomic changes format).\n *\t\tfastDiff( a, b, null, true );\n *\t\tdiff( a, b );\n *\n *\n * @param {Array|String} a Input array or string.\n * @param {Array|String} b Input array or string.\n * @param {Function} [cmp] Optional function used to compare array values, by default `===` (strict equal operator) is used.\n * @param {Boolean} [atomicChanges=false] Whether an array of `inset|delete|equal` operations should\n * be returned instead of changes set. This makes this function compatible with {@link module:utils/diff~diff `diff()`}.\n * @returns {Array} Array of changes.\n */\nexport default function fastDiff( a, b, cmp, atomicChanges = false ) {\n\t// Set the comparator function.\n\tcmp = cmp || function( a, b ) {\n\t\treturn a === b;\n\t};\n\n\t// Convert the string (or any array-like object - eg. NodeList) to an array by using the slice() method because,\n\t// unlike Array.from(), it returns array of UTF-16 code units instead of the code points of a string.\n\t// One code point might be a surrogate pair of two code units. All text offsets are expected to be in code units.\n\t// See ckeditor/ckeditor5#3147.\n\t//\n\t// We need to make sure here that fastDiff() works identical to diff().\n\tif ( !Array.isArray( a ) ) {\n\t\ta = Array.prototype.slice.call( a );\n\t}\n\n\tif ( !Array.isArray( b ) ) {\n\t\tb = Array.prototype.slice.call( b );\n\t}\n\n\t// Find first and last change.\n\tconst changeIndexes = findChangeBoundaryIndexes( a, b, cmp );\n\n\t// Transform into changes array.\n\treturn atomicChanges ? changeIndexesToAtomicChanges( changeIndexes, b.length ) : changeIndexesToChanges( b, changeIndexes );\n}\n\n// Finds position of the first and last change in the given arrays. For example:\n//\n//\t\tconst indexes = findChangeBoundaryIndexes( [ '1', '2', '3', '4' ], [ '1', '3', '4', '2', '4' ] );\n//\t\tconsole.log( indexes ); // { firstIndex: 1, lastIndexOld: 3, lastIndexNew: 4 }\n//\n// The above indexes means that in the first array the modified part is `1[23]4` and in the second array it is `1[342]4`.\n// Based on such indexes, array with `insert`/`delete` operations which allows transforming first value into the second one\n// can be generated.\n//\n// @param {Array} arr1\n// @param {Array} arr2\n// @param {Function} cmp Comparator function.\n// @returns {Object}\n// @returns {Number} return.firstIndex Index of the first change in both values (always the same for both).\n// @returns {Number} result.lastIndexOld Index of the last common value in `arr1`.\n// @returns {Number} result.lastIndexNew Index of the last common value in `arr2`.\nfunction findChangeBoundaryIndexes( arr1, arr2, cmp ) {\n\t// Find the first difference between passed values.\n\tconst firstIndex = findFirstDifferenceIndex( arr1, arr2, cmp );\n\n\t// If arrays are equal return -1 indexes object.\n\tif ( firstIndex === -1 ) {\n\t\treturn { firstIndex: -1, lastIndexOld: -1, lastIndexNew: -1 };\n\t}\n\n\t// Remove the common part of each value and reverse them to make it simpler to find the last difference between them.\n\tconst oldArrayReversed = cutAndReverse( arr1, firstIndex );\n\tconst newArrayReversed = cutAndReverse( arr2, firstIndex );\n\n\t// Find the first difference between reversed values.\n\t// It should be treated as \"how many elements from the end the last difference occurred\".\n\t//\n\t// For example:\n\t//\n\t// \t\t\t\tinitial\t->\tafter cut\t-> reversed:\n\t// oldValue:\t'321ba'\t->\t'21ba'\t\t-> 'ab12'\n\t// newValue:\t'31xba'\t->\t'1xba'\t\t-> 'abx1'\n\t// lastIndex:\t\t\t\t\t\t\t-> 2\n\t//\n\t// So the last change occurred two characters from the end of the arrays.\n\tconst lastIndex = findFirstDifferenceIndex( oldArrayReversed, newArrayReversed, cmp );\n\n\t// Use `lastIndex` to calculate proper offset, starting from the beginning (`lastIndex` kind of starts from the end).\n\tconst lastIndexOld = arr1.length - lastIndex;\n\tconst lastIndexNew = arr2.length - lastIndex;\n\n\treturn { firstIndex, lastIndexOld, lastIndexNew };\n}\n\n// Returns a first index on which given arrays differ. If both arrays are the same, -1 is returned.\n//\n// @param {Array} arr1\n// @param {Array} arr2\n// @param {Function} cmp Comparator function.\n// @returns {Number}\nfunction findFirstDifferenceIndex( arr1, arr2, cmp ) {\n\tfor ( let i = 0; i < Math.max( arr1.length, arr2.length ); i++ ) {\n\t\tif ( arr1[ i ] === undefined || arr2[ i ] === undefined || !cmp( arr1[ i ], arr2[ i ] ) ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1; // Return -1 if arrays are equal.\n}\n\n// Returns a copy of the given array with `howMany` elements removed starting from the beginning and in reversed order.\n//\n// @param {Array} arr Array to be processed.\n// @param {Number} howMany How many elements from array beginning to remove.\n// @returns {Array} Shortened and reversed array.\nfunction cutAndReverse( arr, howMany ) {\n\treturn arr.slice( howMany ).reverse();\n}\n\n// Generates changes array based on change indexes from `findChangeBoundaryIndexes` function. This function will\n// generate array with 0 (no changes), 1 (deletion or insertion) or 2 records (insertion and deletion).\n//\n// @param {Array} newArray New array for which change indexes were calculated.\n// @param {Object} changeIndexes Change indexes object from `findChangeBoundaryIndexes` function.\n// @returns {Array.} Array of changes compatible with {@link module:utils/difftochanges~diffToChanges} format.\nfunction changeIndexesToChanges( newArray, changeIndexes ) {\n\tconst result = [];\n\tconst { firstIndex, lastIndexOld, lastIndexNew } = changeIndexes;\n\n\t// Order operations as 'insert', 'delete' array to keep compatibility with {@link module:utils/difftochanges~diffToChanges}\n\t// in most cases. However, 'diffToChanges' does not stick to any order so in some cases\n\t// (for example replacing '12345' with 'abcd') it will generate 'delete', 'insert' order.\n\tif ( lastIndexNew - firstIndex > 0 ) {\n\t\tresult.push( {\n\t\t\tindex: firstIndex,\n\t\t\ttype: 'insert',\n\t\t\tvalues: newArray.slice( firstIndex, lastIndexNew )\n\t\t} );\n\t}\n\n\tif ( lastIndexOld - firstIndex > 0 ) {\n\t\tresult.push( {\n\t\t\tindex: firstIndex + ( lastIndexNew - firstIndex ), // Increase index of what was inserted.\n\t\t\ttype: 'delete',\n\t\t\thowMany: lastIndexOld - firstIndex\n\t\t} );\n\t}\n\n\treturn result;\n}\n\n// Generates array with set `equal|insert|delete` operations based on change indexes from `findChangeBoundaryIndexes` function.\n//\n// @param {Object} changeIndexes Change indexes object from `findChangeBoundaryIndexes` function.\n// @param {Number} newLength Length of the new array on which `findChangeBoundaryIndexes` calculated change indexes.\n// @returns {Array.} Array of changes compatible with {@link module:utils/diff~diff} format.\nfunction changeIndexesToAtomicChanges( changeIndexes, newLength ) {\n\tconst { firstIndex, lastIndexOld, lastIndexNew } = changeIndexes;\n\n\t// No changes.\n\tif ( firstIndex === -1 ) {\n\t\treturn Array( newLength ).fill( 'equal' );\n\t}\n\n\tlet result = [];\n\tif ( firstIndex > 0 ) {\n\t\tresult = result.concat( Array( firstIndex ).fill( 'equal' ) );\n\t}\n\n\tif ( lastIndexNew - firstIndex > 0 ) {\n\t\tresult = result.concat( Array( lastIndexNew - firstIndex ).fill( 'insert' ) );\n\t}\n\n\tif ( lastIndexOld - firstIndex > 0 ) {\n\t\tresult = result.concat( Array( lastIndexOld - firstIndex ).fill( 'delete' ) );\n\t}\n\n\tif ( lastIndexNew < newLength ) {\n\t\tresult = result.concat( Array( newLength - lastIndexNew ).fill( 'equal' ) );\n\t}\n\n\treturn result;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module utils/isiterable\n */\n\n/**\n * Checks if value implements iterator interface.\n *\n * @param {*} value The value to check.\n * @returns {Boolean} True if value implements iterator interface.\n */\nexport default function isIterable( value ) {\n\treturn !!( value && value[ Symbol.iterator ] );\n}\n"],"sourceRoot":""}