OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openproject/app/assets/javascripts/vendor/ckeditor/ckeditor.js.map

1 lines
4.2 MiB

{"version":3,"sources":["webpack://OPEditor/webpack/universalModuleDefinition","webpack://OPEditor/webpack/bootstrap","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/ckeditorerror.js","webpack://OPEditor/./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js","webpack://OPEditor/./node_modules/markdown-it/lib/common/utils.js","webpack://OPEditor/./node_modules/lodash-es/_root.js","webpack://OPEditor/./node_modules/lodash-es/_nodeUtil.js","webpack://OPEditor/./node_modules/lodash-es/isBuffer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/version.js","webpack://OPEditor/./node_modules/lodash-es/_freeGlobal.js","webpack://OPEditor/(webpack)/buildin/global.js","webpack://OPEditor/(webpack)/buildin/harmony-module.js","webpack://OPEditor/./node_modules/uc.micro/categories/P/regex.js","webpack://OPEditor/./node_modules/markdown-it/lib/ruler.js","webpack://OPEditor/./node_modules/markdown-it/lib/token.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/theme/code.css?8959","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-heading/theme/heading.css?3817","webpack://OPEditor/./node_modules/markdown-it/lib/common/entities.js","webpack://OPEditor/./node_modules/mdurl/index.js","webpack://OPEditor/./node_modules/uc.micro/properties/Any/regex.js","webpack://OPEditor/./node_modules/uc.micro/categories/Cc/regex.js","webpack://OPEditor/./node_modules/uc.micro/categories/Z/regex.js","webpack://OPEditor/./node_modules/markdown-it/lib/common/html_re.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/strikethrough.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/emphasis.js","webpack://OPEditor/./node_modules/lodash-es/stubFalse.js","webpack://OPEditor/./node_modules/lodash-es/_cloneBuffer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/theme/placeholder.css?e043","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/theme/placeholder.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/globals/globals.css?0c98","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/globals/globals.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/editorui/editorui.css?9b58","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/editorui/editorui.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/dropdown.css?ab63","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/dropdown.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/icon/icon.css?dcba","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/icon/icon.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/tooltip/tooltip.css?a250","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/tooltip/tooltip.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/button.css?c37e","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/button.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/list/list.css?fc0e","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/list/list.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/switchbutton.css?7150","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/switchbutton.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/toolbardropdown.css?4d56","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/toolbardropdown.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/listdropdown.css?92e1","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/listdropdown.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/toolbar/toolbar.css?a52e","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/toolbar/toolbar.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-widget/theme/widget.css?1b9a","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-widget/theme/widget.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/balloonpanel.css?9810","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/balloonpanel.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/balloonrotator.css?270e","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/balloonrotator.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/fakepanel.css?e8ce","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/fakepanel.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadprogress.css?fc17","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadprogress.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadicon.css?0258","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadicon.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadloader.css?9840","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imageuploadloader.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/theme/code.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-block-quote/theme/blockquote.css?98c3","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-block-quote/theme/blockquote.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-heading/theme/heading.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/label/label.css?a80d","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/label/label.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/labeledinput/labeledinput.css?6a85","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/labeledinput/labeledinput.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/inputtext/inputtext.css?f229","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/components/inputtext/inputtext.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/textalternativeform.css?ec83","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/textalternativeform.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/image.css?4996","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/image.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imagecaption.css?2a2f","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imagecaption.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imagestyle.css?453e","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/imagestyle.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/theme/link.css?9ecb","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/theme/link.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/theme/linkform.css?806e","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/theme/linkform.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/theme/linkactions.css?72c0","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/theme/linkactions.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/tableediting.css?5c83","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/tableediting.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/inserttable.css?6096","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/inserttable.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/table.css?cbbb","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/table.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/theme/todolist.css?f6e7","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/theme/todolist.css","webpack://OPEditor/./node_modules/markdown-it/index.js","webpack://OPEditor/./node_modules/markdown-it/lib/index.js","webpack://OPEditor/./node_modules/mdurl/encode.js","webpack://OPEditor/./node_modules/mdurl/decode.js","webpack://OPEditor/./node_modules/mdurl/format.js","webpack://OPEditor/./node_modules/mdurl/parse.js","webpack://OPEditor/./node_modules/uc.micro/index.js","webpack://OPEditor/./node_modules/uc.micro/categories/Cf/regex.js","webpack://OPEditor/./node_modules/markdown-it/lib/helpers/index.js","webpack://OPEditor/./node_modules/markdown-it/lib/helpers/parse_link_label.js","webpack://OPEditor/./node_modules/markdown-it/lib/helpers/parse_link_destination.js","webpack://OPEditor/./node_modules/markdown-it/lib/helpers/parse_link_title.js","webpack://OPEditor/./node_modules/markdown-it/lib/renderer.js","webpack://OPEditor/./node_modules/markdown-it/lib/parser_core.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_core/normalize.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_core/block.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_core/inline.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_core/linkify.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_core/replacements.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_core/smartquotes.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_core/state_core.js","webpack://OPEditor/./node_modules/markdown-it/lib/parser_block.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/table.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/code.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/fence.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/blockquote.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/hr.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/list.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/reference.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/heading.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/lheading.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/html_block.js","webpack://OPEditor/./node_modules/markdown-it/lib/common/html_blocks.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/paragraph.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_block/state_block.js","webpack://OPEditor/./node_modules/markdown-it/lib/parser_inline.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/text.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/newline.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/escape.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/backticks.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/link.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/image.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/autolink.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/html_inline.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/entity.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/balance_pairs.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/text_collapse.js","webpack://OPEditor/./node_modules/markdown-it/lib/rules_inline/state_inline.js","webpack://OPEditor/./node_modules/linkify-it/index.js","webpack://OPEditor/./node_modules/linkify-it/lib/re.js","webpack://OPEditor/./node_modules/node-libs-browser/node_modules/punycode/punycode.js","webpack://OPEditor/(webpack)/buildin/module.js","webpack://OPEditor/./node_modules/markdown-it/lib/presets/default.js","webpack://OPEditor/./node_modules/markdown-it/lib/presets/zero.js","webpack://OPEditor/./node_modules/markdown-it/lib/presets/commonmark.js","webpack://OPEditor/./node_modules/markdown-it-task-lists/index.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/theme/mentionui.css?d67f","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/theme/mentionui.css","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/theme/mention.css?ab86","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/theme/mention.css","webpack://OPEditor/./node_modules/lodash-es/_Symbol.js","webpack://OPEditor/./node_modules/lodash-es/_getRawTag.js","webpack://OPEditor/./node_modules/lodash-es/_objectToString.js","webpack://OPEditor/./node_modules/lodash-es/_baseGetTag.js","webpack://OPEditor/./node_modules/lodash-es/_overArg.js","webpack://OPEditor/./node_modules/lodash-es/_getPrototype.js","webpack://OPEditor/./node_modules/lodash-es/isObjectLike.js","webpack://OPEditor/./node_modules/lodash-es/isPlainObject.js","webpack://OPEditor/./node_modules/lodash-es/_listCacheClear.js","webpack://OPEditor/./node_modules/lodash-es/eq.js","webpack://OPEditor/./node_modules/lodash-es/_assocIndexOf.js","webpack://OPEditor/./node_modules/lodash-es/_listCacheDelete.js","webpack://OPEditor/./node_modules/lodash-es/_listCacheGet.js","webpack://OPEditor/./node_modules/lodash-es/_listCacheHas.js","webpack://OPEditor/./node_modules/lodash-es/_listCacheSet.js","webpack://OPEditor/./node_modules/lodash-es/_ListCache.js","webpack://OPEditor/./node_modules/lodash-es/_stackClear.js","webpack://OPEditor/./node_modules/lodash-es/_stackDelete.js","webpack://OPEditor/./node_modules/lodash-es/_stackGet.js","webpack://OPEditor/./node_modules/lodash-es/_stackHas.js","webpack://OPEditor/./node_modules/lodash-es/isObject.js","webpack://OPEditor/./node_modules/lodash-es/isFunction.js","webpack://OPEditor/./node_modules/lodash-es/_isMasked.js","webpack://OPEditor/./node_modules/lodash-es/_coreJsData.js","webpack://OPEditor/./node_modules/lodash-es/_toSource.js","webpack://OPEditor/./node_modules/lodash-es/_baseIsNative.js","webpack://OPEditor/./node_modules/lodash-es/_getValue.js","webpack://OPEditor/./node_modules/lodash-es/_getNative.js","webpack://OPEditor/./node_modules/lodash-es/_Map.js","webpack://OPEditor/./node_modules/lodash-es/_nativeCreate.js","webpack://OPEditor/./node_modules/lodash-es/_hashClear.js","webpack://OPEditor/./node_modules/lodash-es/_hashDelete.js","webpack://OPEditor/./node_modules/lodash-es/_hashGet.js","webpack://OPEditor/./node_modules/lodash-es/_hashHas.js","webpack://OPEditor/./node_modules/lodash-es/_hashSet.js","webpack://OPEditor/./node_modules/lodash-es/_Hash.js","webpack://OPEditor/./node_modules/lodash-es/_mapCacheClear.js","webpack://OPEditor/./node_modules/lodash-es/_isKeyable.js","webpack://OPEditor/./node_modules/lodash-es/_getMapData.js","webpack://OPEditor/./node_modules/lodash-es/_mapCacheDelete.js","webpack://OPEditor/./node_modules/lodash-es/_mapCacheGet.js","webpack://OPEditor/./node_modules/lodash-es/_mapCacheHas.js","webpack://OPEditor/./node_modules/lodash-es/_mapCacheSet.js","webpack://OPEditor/./node_modules/lodash-es/_MapCache.js","webpack://OPEditor/./node_modules/lodash-es/_stackSet.js","webpack://OPEditor/./node_modules/lodash-es/_Stack.js","webpack://OPEditor/./node_modules/lodash-es/_arrayEach.js","webpack://OPEditor/./node_modules/lodash-es/_defineProperty.js","webpack://OPEditor/./node_modules/lodash-es/_baseAssignValue.js","webpack://OPEditor/./node_modules/lodash-es/_assignValue.js","webpack://OPEditor/./node_modules/lodash-es/_copyObject.js","webpack://OPEditor/./node_modules/lodash-es/_baseTimes.js","webpack://OPEditor/./node_modules/lodash-es/_baseIsArguments.js","webpack://OPEditor/./node_modules/lodash-es/isArguments.js","webpack://OPEditor/./node_modules/lodash-es/isArray.js","webpack://OPEditor/./node_modules/lodash-es/_isIndex.js","webpack://OPEditor/./node_modules/lodash-es/isLength.js","webpack://OPEditor/./node_modules/lodash-es/_baseIsTypedArray.js","webpack://OPEditor/./node_modules/lodash-es/_baseUnary.js","webpack://OPEditor/./node_modules/lodash-es/isTypedArray.js","webpack://OPEditor/./node_modules/lodash-es/_arrayLikeKeys.js","webpack://OPEditor/./node_modules/lodash-es/_isPrototype.js","webpack://OPEditor/./node_modules/lodash-es/_nativeKeys.js","webpack://OPEditor/./node_modules/lodash-es/_baseKeys.js","webpack://OPEditor/./node_modules/lodash-es/isArrayLike.js","webpack://OPEditor/./node_modules/lodash-es/keys.js","webpack://OPEditor/./node_modules/lodash-es/_baseAssign.js","webpack://OPEditor/./node_modules/lodash-es/_nativeKeysIn.js","webpack://OPEditor/./node_modules/lodash-es/_baseKeysIn.js","webpack://OPEditor/./node_modules/lodash-es/keysIn.js","webpack://OPEditor/./node_modules/lodash-es/_baseAssignIn.js","webpack://OPEditor/./node_modules/lodash-es/_copyArray.js","webpack://OPEditor/./node_modules/lodash-es/_arrayFilter.js","webpack://OPEditor/./node_modules/lodash-es/stubArray.js","webpack://OPEditor/./node_modules/lodash-es/_getSymbols.js","webpack://OPEditor/./node_modules/lodash-es/_copySymbols.js","webpack://OPEditor/./node_modules/lodash-es/_arrayPush.js","webpack://OPEditor/./node_modules/lodash-es/_getSymbolsIn.js","webpack://OPEditor/./node_modules/lodash-es/_copySymbolsIn.js","webpack://OPEditor/./node_modules/lodash-es/_baseGetAllKeys.js","webpack://OPEditor/./node_modules/lodash-es/_getAllKeys.js","webpack://OPEditor/./node_modules/lodash-es/_getAllKeysIn.js","webpack://OPEditor/./node_modules/lodash-es/_DataView.js","webpack://OPEditor/./node_modules/lodash-es/_Promise.js","webpack://OPEditor/./node_modules/lodash-es/_Set.js","webpack://OPEditor/./node_modules/lodash-es/_WeakMap.js","webpack://OPEditor/./node_modules/lodash-es/_getTag.js","webpack://OPEditor/./node_modules/lodash-es/_initCloneArray.js","webpack://OPEditor/./node_modules/lodash-es/_Uint8Array.js","webpack://OPEditor/./node_modules/lodash-es/_cloneArrayBuffer.js","webpack://OPEditor/./node_modules/lodash-es/_cloneDataView.js","webpack://OPEditor/./node_modules/lodash-es/_cloneRegExp.js","webpack://OPEditor/./node_modules/lodash-es/_cloneSymbol.js","webpack://OPEditor/./node_modules/lodash-es/_cloneTypedArray.js","webpack://OPEditor/./node_modules/lodash-es/_initCloneByTag.js","webpack://OPEditor/./node_modules/lodash-es/_baseCreate.js","webpack://OPEditor/./node_modules/lodash-es/_initCloneObject.js","webpack://OPEditor/./node_modules/lodash-es/_baseIsMap.js","webpack://OPEditor/./node_modules/lodash-es/isMap.js","webpack://OPEditor/./node_modules/lodash-es/_baseIsSet.js","webpack://OPEditor/./node_modules/lodash-es/isSet.js","webpack://OPEditor/./node_modules/lodash-es/_baseClone.js","webpack://OPEditor/./node_modules/lodash-es/cloneDeepWith.js","webpack://OPEditor/./node_modules/lodash-es/isElement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/config.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/spy.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/eventinfo.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/uid.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/priorities.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/emittermixin.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/mix.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/comparearrays.js","webpack://OPEditor/./node_modules/lodash-es/clone.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/node.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/text.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/textproxy.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/objecttomap.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/isiterable.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/matcher.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/element.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/containerelement.js","webpack://OPEditor/./node_modules/lodash-es/identity.js","webpack://OPEditor/./node_modules/lodash-es/_apply.js","webpack://OPEditor/./node_modules/lodash-es/_overRest.js","webpack://OPEditor/./node_modules/lodash-es/constant.js","webpack://OPEditor/./node_modules/lodash-es/_baseSetToString.js","webpack://OPEditor/./node_modules/lodash-es/_shortOut.js","webpack://OPEditor/./node_modules/lodash-es/_setToString.js","webpack://OPEditor/./node_modules/lodash-es/_baseRest.js","webpack://OPEditor/./node_modules/lodash-es/_isIterateeCall.js","webpack://OPEditor/./node_modules/lodash-es/_createAssigner.js","webpack://OPEditor/./node_modules/lodash-es/assignIn.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/observablemixin.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/editableelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/rooteditableelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/treewalker.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/position.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/range.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/count.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/selection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/documentselection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/collection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/document.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/attributeelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/emptyelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/env.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/keyboard.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/uielement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/documentfragment.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/downcastwriter.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/istext.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/filler.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/fastdiff.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/diff.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/insertat.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/remove.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/isnode.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/renderer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/global.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/indexof.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/getancestors.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/domconverter.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/getcommonancestor.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/iswindow.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/emittermixin.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/observer.js","webpack://OPEditor/./node_modules/lodash-es/_setCacheAdd.js","webpack://OPEditor/./node_modules/lodash-es/_setCacheHas.js","webpack://OPEditor/./node_modules/lodash-es/_SetCache.js","webpack://OPEditor/./node_modules/lodash-es/_arraySome.js","webpack://OPEditor/./node_modules/lodash-es/_cacheHas.js","webpack://OPEditor/./node_modules/lodash-es/_equalArrays.js","webpack://OPEditor/./node_modules/lodash-es/_mapToArray.js","webpack://OPEditor/./node_modules/lodash-es/_setToArray.js","webpack://OPEditor/./node_modules/lodash-es/_equalByTag.js","webpack://OPEditor/./node_modules/lodash-es/_equalObjects.js","webpack://OPEditor/./node_modules/lodash-es/_baseIsEqualDeep.js","webpack://OPEditor/./node_modules/lodash-es/_baseIsEqual.js","webpack://OPEditor/./node_modules/lodash-es/isEqualWith.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/mutationobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/domeventdata.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/domeventobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/keyobserver.js","webpack://OPEditor/./node_modules/lodash-es/now.js","webpack://OPEditor/./node_modules/lodash-es/isSymbol.js","webpack://OPEditor/./node_modules/lodash-es/toNumber.js","webpack://OPEditor/./node_modules/lodash-es/debounce.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/fakeselectionobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/selectionobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/focusobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/compositionobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/inputobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/isrange.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/getborderwidths.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/rect.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/scroll.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/view.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/tomap.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/node.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/text.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/textproxy.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/nodelist.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/element.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/treewalker.js","webpack://OPEditor/./node_modules/lodash-es/last.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/position.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/range.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/mapper.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/modelconsumable.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/downcastdispatcher.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/selection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/liverange.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/documentselection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/conversionhelpers.js","webpack://OPEditor/./node_modules/lodash-es/cloneDeep.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/downcasthelpers.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/upcasthelpers.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/controller/editingcontroller.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/plugincollection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/commandcollection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/translation-service.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/locale.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/viewconsumable.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/schema.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/upcastdispatcher.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/controller/datacontroller.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/conversion/conversion.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/batch.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/operation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/documentfragment.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/utils.js","webpack://OPEditor/./node_modules/lodash-es/isEqual.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/attributeoperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/detachoperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/moveoperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/insertoperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/markeroperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/renameoperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/rootattributeoperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/mergeoperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/splitoperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/rootelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/writer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/differ.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/history.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/unicode.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/document.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/markercollection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/liveposition.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/utils/insertcontent.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/utils/deletecontent.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/utils/modifyselection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/utils/getselectedcontent.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/utils/selection-post-fixer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/model.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/keystrokehandler.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/editingkeystrokehandler.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/editor/editor.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/editor/utils/dataapimixin.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/dataprocessor/basichtmlwriter.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/componentfactory.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/focustracker.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/editor/editorui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/placeholder.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-editor-decoupled/src/decouplededitorui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/normalizetoolbarconfig.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/enabletoolbarkeyboardfocus.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/viewcollection.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/template.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/view.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/editorui/editoruiview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/editableui/editableuiview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/editableui/inline/inlineeditableuiview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/focuscycler.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/toolbarseparatorview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/getresizeobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/dropdown/dropdownpanelview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/position.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/getpositionedancestor.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/dropdown/dropdownview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/icon/iconview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/tooltip/tooltipview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/button/buttonview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/icons/dropdown-arrow.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/dropdown/button/dropdownbuttonview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/list/listview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/list/listitemview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/list/listseparatorview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/button/switchbuttonview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/dropdown/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/three-vertical-dots.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/toolbarview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/bindings/preventdefault.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-editor-decoupled/src/decouplededitoruiview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-editor-decoupled/src/decouplededitor.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/editor/utils/securesourceelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/setdatainelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/getdatafromelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/plugin.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-widget/src/highlightstack.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-widget/theme/icons/drag-handle.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-widget/src/utils.js","webpack://OPEditor/./src/plugins/op-macro-toc-plugin.js","webpack://OPEditor/./src/plugins/op-macro-embedded-table/utils.js","webpack://OPEditor/./src/plugins/op-context/op-context.js","webpack://OPEditor/./src/plugins/op-macro-embedded-table/embedded-table-editing.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/mouseobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-widget/src/widget.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/tounit.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/icons/previous-arrow.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/theme/icons/next-arrow.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon.js","webpack://OPEditor/./src/icons/edit.svg","webpack://OPEditor/./src/helpers/create-toolbar-edit-button.js","webpack://OPEditor/./src/helpers/create-toolbar.js","webpack://OPEditor/./src/plugins/op-macro-embedded-table/embedded-table-toolbar.js","webpack://OPEditor/./src/plugins/op-macro-wp-button/utils.js","webpack://OPEditor/./src/plugins/op-macro-wp-button/op-macro-wp-button-editing.js","webpack://OPEditor/./src/plugins/op-macro-wp-button/op-macro-wp-button-toolbar.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/pendingactions.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-upload/src/filereader.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-upload/src/filerepository.js","webpack://OPEditor/./src/plugins/op-upload-resource-adapter.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-upload/src/ui/filedialogbuttonview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/image.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imageupload/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imageupload/imageuploadui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/theme/icons/image_placeholder.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imageupload/imageuploadprogress.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/notification/notification.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-clipboard/src/datatransfer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-clipboard/src/clipboardobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-clipboard/src/utils/viewtoplaintext.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-clipboard/src/clipboard.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-clipboard/src/utils/normalizeclipboarddata.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-clipboard/src/utils/plaintexttohtml.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/upcastwriter.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/src/command.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/image/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imageupload/imageuploadcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imageupload/imageuploadediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imageupload.js","webpack://OPEditor/./src/plugins/op-macro-child-pages/utils.js","webpack://OPEditor/./src/plugins/op-macro-child-pages/op-macro-child-pages-editing.js","webpack://OPEditor/./src/plugins/op-macro-child-pages/op-macro-child-pages-toolbar.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-enter/src/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-enter/src/entercommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-enter/src/enterobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-enter/src/enter.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-enter/src/shiftentercommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-enter/src/shiftenter.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/utils/changebuffer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/inputcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/utils/injectunsafekeystrokeshandling.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/utils/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/difftochanges.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/utils/injecttypingmutationshandling.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/input.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/deletecommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/deleteobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/delete.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/typing.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/nooperation.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/model/operation/transform.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-undo/src/basecommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-undo/src/undocommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-undo/src/redocommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-undo/src/undoediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-undo/theme/icons/undo.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-undo/theme/icons/redo.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-undo/src/undoui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-undo/src/undo.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-adapter-ckfinder/src/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-adapter-ckfinder/src/uploadadapter.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-autoformat/src/blockautoformatediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/utils/getlasttextline.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-autoformat/src/inlineautoformatediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-autoformat/src/autoformat.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/attributecommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/bold/boldediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/theme/icons/bold.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/bold/boldui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/code/codeediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/theme/icons/code.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/code/codeui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/strikethrough/strikethroughediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/theme/icons/strikethrough.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/strikethrough/strikethroughui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/italic/italicediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/theme/icons/italic.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/italic/italicui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/first.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-block-quote/src/blockquotecommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-block-quote/src/blockquoteediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/quote.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-block-quote/src/blockquoteui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paragraph/src/paragraphcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paragraph/src/paragraph.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-heading/src/headingcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-heading/src/headingediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/model.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-heading/src/headingui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-heading/src/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/image/imageloadobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/image/converters.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/image/imageinsertcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/image/imageediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagetextalternative/imagetextalternativecommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagetextalternative/imagetextalternativeediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/label/labelview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/labeledinput/labeledinputview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/inputtext/inputtextview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-ui/src/bindings/submithandler.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/check.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/cancel.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagetextalternative/ui/textalternativeformview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/low-vision.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/image/ui/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagetextalternative/imagetextalternativeui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagetextalternative.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagecaption/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagecaption/imagecaptionediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/imagestylecommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/converters.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/object-full-width.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/object-left.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/object-center.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/object-right.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/imagestyleediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/imagestyleui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-widget/src/widgettoolbarrepository.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/findlinkrange.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/linkcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/unlinkcommand.js","webpack://OPEditor/./node_modules/lodash-es/_baseSlice.js","webpack://OPEditor/./node_modules/lodash-es/_castSlice.js","webpack://OPEditor/./node_modules/lodash-es/_hasUnicode.js","webpack://OPEditor/./node_modules/lodash-es/_asciiToArray.js","webpack://OPEditor/./node_modules/lodash-es/_unicodeToArray.js","webpack://OPEditor/./node_modules/lodash-es/_stringToArray.js","webpack://OPEditor/./node_modules/lodash-es/_arrayMap.js","webpack://OPEditor/./node_modules/lodash-es/_baseToString.js","webpack://OPEditor/./node_modules/lodash-es/toString.js","webpack://OPEditor/./node_modules/lodash-es/_createCaseFirst.js","webpack://OPEditor/./node_modules/lodash-es/upperFirst.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/utils/automaticdecorators.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/utils/manualdecorator.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/utils/bindtwostepcarettoattribute.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/linkediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-engine/src/view/observer/clickobserver.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/ui/linkformview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/theme/icons/unlink.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-core/theme/icons/pencil.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/ui/linkactionsview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/theme/icons/link.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/linkui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/listcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/indentcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/converters.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/listediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/theme/icons/numberedlist.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/theme/icons/bulletedlist.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/listui.js","webpack://OPEditor/./src/icons/help.svg","webpack://OPEditor/./src/icons/code-block.svg","webpack://OPEditor/./src/plugins/code-block/widget.js","webpack://OPEditor/./src/plugins/code-block/click-observer.js","webpack://OPEditor/./src/plugins/code-block/code-block-editing.js","webpack://OPEditor/./src/plugins/code-block/converters.js","webpack://OPEditor/./src/plugins/code-block/code-block-toolbar.js","webpack://OPEditor/./src/icons/preview.svg","webpack://OPEditor/./src/helpers/button-disabler.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/converters/upcasttable.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/tablewalker.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/utils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/converters/downcast.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/inserttablecommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/insertrowcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/insertcolumncommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/splitcellcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/mergecellcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/removerowcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/removecolumncommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/setheaderrowcommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/commands/setheadercolumncommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/tableutils.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/converters/table-layout-post-fixer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/converters/table-cell-paragraph-post-fixer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/converters/table-cell-refresh-post-fixer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/tableediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/ui/inserttableview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/icons/table.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/icons/table-column.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/icons/table-row.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/theme/icons/table-merge-cell.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/tableui.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paste-from-office/src/filters/list.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paste-from-office/src/normalizers/googledocsnormalizer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paste-from-office/src/filters/removeboldwrapper.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paste-from-office/src/filters/space.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paste-from-office/src/filters/parse.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paste-from-office/src/filters/image.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paste-from-office/src/normalizers/mswordnormalizer.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/todolistcheckcommand.js","webpack://OPEditor/./node_modules/lodash-es/isString.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/todolistconverters.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-utils/src/dom/createelement.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/todolistediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/theme/icons/todolist.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/todolistui.js","webpack://OPEditor/./node_modules/turndown-plugin-gfm/lib/turndown-plugin-gfm.es.js","webpack://OPEditor/./node_modules/turndown/lib/turndown.es.js","webpack://OPEditor/./src/commonmark/utils/preprocessor.js","webpack://OPEditor/./src/commonmark/commonmarkdataprocessor.js","webpack://OPEditor/./src/commonmark/utils/paragraph-in-lists.js","webpack://OPEditor/./src/icons/source.svg","webpack://OPEditor/./src/icons/wysiwyg.svg","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/src/mentioncommand.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/src/mentionediting.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-typing/src/textwatcher.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/src/ui/mentionsview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/src/ui/domwrapperview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/src/ui/mentionlistitemview.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/src/mentionui.js","webpack://OPEditor/./src/op-plugins.js","webpack://OPEditor/./src/plugins/op-macro-embedded-table/embedded-table-plugin.js","webpack://OPEditor/./src/plugins/op-macro-wp-button/op-macro-wp-button-plugin.js","webpack://OPEditor/./src/plugins/op-macro-child-pages/op-macro-child-pages-plugin.js","webpack://OPEditor/./src/plugins/op-upload-plugin.js","webpack://OPEditor/./src/plugins/op-attachment-listener-plugin.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-essentials/src/essentials.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/bold.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/code.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/italic.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-basic-styles/src/strikethrough.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-block-quote/src/blockquote.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-heading/src/heading.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/image.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagecaption.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagestyle.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-image/src/imagetoolbar.js","webpack://OPEditor/./src/plugins/op-image-attachment-lookup/op-image-attachment-lookup-plugin.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-link/src/link.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/list.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-list/src/todolist.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-mention/src/mention.js","webpack://OPEditor/./src/mentions/mentions-caster.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice.js","webpack://OPEditor/./src/plugins/op-help-link-plugin/op-help-link-plugin.js","webpack://OPEditor/./src/plugins/code-block/code-block.js","webpack://OPEditor/./src/plugins/op-preview.plugin.js","webpack://OPEditor/./src/plugins/op-source-code.plugin.js","webpack://OPEditor/./src/commonmark/commonmark.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/table.js","webpack://OPEditor/./node_modules/@ckeditor/ckeditor5-table/src/tabletoolbar.js","webpack://OPEditor/./src/plugins/op-macro-list-plugin.js","webpack://OPEditor/./src/mentions/mentions-item-renderer.js","webpack://OPEditor/./src/op-ckeditor-config.js","webpack://OPEditor/./src/mentions/user-mentions.js","webpack://OPEditor/./src/mentions/work-package-mentions.js","webpack://OPEditor/./src/op-config-customizer.js","webpack://OPEditor/./src/op-ckeditor.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","DOCUMENTATION_URL","CKEditorError","Error","message","context","data","attachLinkToDocumentation","JSON","stringify","super","this","type","err","is","originalError","stack","matchedErrorName","match","memo","stylesInDom","isOldIE","Boolean","document","all","atob","getTarget","target","styleTarget","querySelector","HTMLIFrameElement","contentDocument","head","e","listToStyles","list","options","styles","newStyles","length","item","id","base","part","css","media","sourceMap","parts","push","addStylesToDom","domStyle","j","refs","addStyle","insertStyleElement","style","createElement","attributes","nonce","keys","forEach","setAttribute","insert","appendChild","textStore","replaceText","index","replacement","filter","join","applyToSingletonTag","remove","obj","styleSheet","cssText","cssNode","createTextNode","childNodes","removeChild","insertBefore","applyToTag","btoa","concat","unescape","encodeURIComponent","firstChild","singleton","singletonCounter","update","styleIndex","parentNode","removeStyleElement","newObj","newList","mayRemove","_i","_domStyle","_hasOwnProperty","has","isValidEntityCode","fromCodePoint","surrogate1","surrogate2","String","fromCharCode","UNESCAPE_MD_RE","UNESCAPE_ALL_RE","RegExp","source","DIGITAL_ENTITY_TEST_RE","entities","HTML_ESCAPE_TEST_RE","HTML_ESCAPE_REPLACE_RE","HTML_REPLACEMENTS","replaceUnsafeChar","ch","REGEXP_ESCAPE_RE","UNICODE_PUNCT_RE","lib","mdurl","ucmicro","assign","Array","slice","arguments","TypeError","isString","toString","_class","unescapeMd","str","indexOf","replace","unescapeAll","escaped","entity","code","charCodeAt","test","toLowerCase","parseInt","replaceEntityPattern","escapeHtml","arrayReplaceAt","src","pos","newElements","isSpace","isWhiteSpace","isMdAsciiPunct","isPunctChar","escapeRE","normalizeReference","trim","toUpperCase","freeSelf","self","Function","freeExports","nodeType","freeModule","freeProcess","process","nodeUtil","types","require","binding","Buffer","undefined","isBuffer","windowOrGlobal","global","CKEDITOR_VERSION","freeGlobal","g","originalModule","webpackPolyfill","children","Ruler","__rules__","__cache__","__find__","__compile__","chains","rule","enabled","alt","altName","chain","fn","at","opt","before","beforeName","ruleName","splice","after","afterName","enable","ignoreInvalid","isArray","result","idx","enableOnly","disable","getRules","chainName","Token","tag","nesting","attrs","map","level","content","markup","info","meta","block","hidden","attrIndex","len","attrPush","attrData","attrSet","attrGet","attrJoin","locals","encode","decode","format","parse","open_tag","close_tag","HTML_TAG_RE","HTML_OPEN_CLOSE_TAG_RE","postProcess","state","delimiters","startDelim","endDelim","token","loneMarkers","max","marker","end","tokens","pop","tokenize","silent","scanned","start","scanDelims","jump","open","can_open","close","can_close","curr","tokens_meta","isStrong","allocUnsafe","buffer","isDeep","constructor","copy","utils","helpers","Renderer","ParserCore","ParserBlock","ParserInline","LinkifyIt","punycode","config","zero","commonmark","BAD_PROTO_RE","GOOD_DATA_RE","validateLink","url","RECODE_HOSTNAME_FOR","normalizeLink","parsed","hostname","protocol","toASCII","er","normalizeLinkText","toUnicode","MarkdownIt","presetName","inline","core","renderer","linkify","configure","set","presets","components","rules","ruler","rules2","ruler2","missed","use","plugin","args","apply","env","State","render","parseInline","inlineMode","renderInline","encodeCache","string","exclude","keepEscaped","nextCode","cache","defaultChars","getEncodeCache","componentChars","decodeCache","getDecodeCache","seq","b1","b2","b3","b4","chr","slashes","auth","port","pathname","search","hash","Url","protocolPattern","portPattern","simplePathPattern","unwise","autoEscape","nonHostChars","hostEndingChars","hostnamePartPattern","hostnamePartStart","hostlessProtocol","slashedProtocol","slashesDenoteHost","lowerProto","hec","rest","split","simplePath","exec","proto","substr","atSign","hostEnd","lastIndexOf","host","parseHost","ipv6Hostname","hostparts","newpart","k","validParts","notHost","bit","unshift","qm","u","Any","Cc","Cf","P","Z","parseLinkLabel","parseLinkDestination","parseLinkTitle","disableNested","found","prevPos","labelEnd","posMax","oldPos","md","skipToken","ok","lines","default_rules","code_inline","slf","renderAttrs","code_block","fence","highlighted","tmpAttrs","tmpToken","langName","highlight","langPrefix","image","renderInlineAsText","renderToken","hardbreak","xhtmlOut","softbreak","breaks","text","html_block","html_inline","nextToken","needLf","_rules","Core","NEWLINES_RE","NULL_RE","tok","isLinkClose","currentToken","nodes","ln","lastPos","htmlLinkLevel","fullUrl","urlText","links","blockTokens","pretest","schema","lastIndex","RARE_RE","SCOPED_ABBR_TEST_RE","SCOPED_ABBR_RE","SCOPED_ABBR","tm","replaceFn","replace_scoped","inlineTokens","inside_autolink","replace_rare","blkIdx","typographer","QUOTE_TEST_RE","QUOTE_RE","APOSTROPHE","replaceAt","process_inlines","thisLevel","lastChar","nextChar","isLastPunctChar","isNextPunctChar","isLastWhiteSpace","isNextWhiteSpace","canOpen","canClose","isSingle","openQuote","closeQuote","OUTER","single","quotes","StateCore","startLine","endLine","line","hasEmptyLines","maxNesting","skipEmptyLines","sCount","blkIndent","tight","isEmpty","outTokens","lineMax","getLine","bMarks","eMarks","escapedSplit","escapes","backTicked","lastBackTick","substring","lineText","nextLine","columns","columnCount","aligns","tableLines","tbodyLines","tShift","last","getLines","params","mem","haveEndMarker","skipChars","skipSpaces","adjustTab","initial","lastLineEmpty","offset","oldBMarks","oldBSCount","oldIndent","oldParentType","oldSCount","oldTShift","spaceAfterMarker","terminate","terminatorRules","wasOutdented","oldLineMax","bsCount","parentType","cnt","skipBulletListMarker","skipOrderedListMarker","contentStart","indent","indentAfterMarker","isOrdered","itemLines","listLines","listTokIdx","markerCharCode","markerValue","oldListIndent","oldTight","posAfterMarker","prevEmptyEnd","isTerminatingParagraph","listIndent","Number","Math","min","markTightParagraphs","_endLine","destEndPos","destEndLineNo","href","label","res","title","references","tmp","skipSpacesBack","skipCharsBack","block_names","HTML_SEQUENCES","html","StateBlock","indent_found","ddIndent","from","begin","keepLastLF","lineIndent","first","queue","lineStart","_rules2","pending","pushPending","isTerminatorChar","pmax","ESCAPED","matchStart","matchEnd","labelStart","ref","parseReference","EMAIL_RE","AUTOLINK_RE","tail","linkMatch","emailMatch","lc","isLetter","DIGITAL_RE","NAMED_RE","processDelimiters","closerIdx","openerIdx","closer","opener","minOpenerIdx","newMinOpenerIdx","isOddMatch","lastJump","openersBottom","StateInline","pendingLevel","_prev_delimiters","token_meta","canSplitWord","count","left_flanking","right_flanking","isFunction","defaultOptions","fuzzyLink","fuzzyEmail","fuzzyIP","defaultSchemas","validate","re","http","src_auth","src_host_port_strict","src_path","no_http","src_domain","src_domain_root","src_port","src_host_terminator","mailto","src_email_name","src_host_strict","tlds_2ch_src_re","tlds_default","compile","__opts__","tlds","__tlds__","untpl","tpl","src_tlds","onCompile","__tlds_replaced__","src_xn","email_fuzzy","tpl_email_fuzzy","link_fuzzy","tpl_link_fuzzy","link_no_ip_fuzzy","tpl_link_no_ip_fuzzy","host_fuzzy_test","tpl_host_fuzzy_test","aliases","schemaError","val","__compiled__","__schemas__","compiled","link","isRegExp","createValidator","normalize","alias","slist","schema_test","src_ZPCc","schema_search","__index__","__text_cache__","resetScanCache","Match","shift","__last_index__","__schema__","raw","createMatch","schemas","reduce","acc","add","definition","ml","me","next","tld_pos","testSchemaAt","keepOld","sort","el","arr","reverse","opts","src_Any","src_Cc","src_Z","src_P","src_ZCc","src_pseudo_letter","src_ip4","src_host","tpl_host_fuzzy","tpl_host_no_ip_fuzzy","tpl_host_fuzzy_strict","tpl_host_port_fuzzy_strict","tpl_host_port_no_ip_fuzzy_strict","maxInt","tMin","tMax","skew","damp","initialBias","initialN","delimiter","regexPunycode","regexNonASCII","regexSeparators","errors","baseMinusTMin","floor","stringFromCharCode","error","RangeError","array","mapDomain","ucs2decode","extra","output","counter","ucs2encode","digitToBasic","digit","flag","adapt","delta","numPoints","firstTime","input","out","basic","oldi","w","baseMinusT","codePoint","inputLength","bias","handledCPCount","basicLength","q","currentValue","handledCPCountPlusOne","qMinusT","deprecate","paths","disableCheckboxes","useLabelWrapper","useLabelAfter","attr","parentToken","targetLevel","isTodoItem","isParagraph","isListItem","startsWithTodoMarkdown","todoify","TokenConstructor","checkbox","disabledAttr","makeCheckbox","ceil","random","for","afterLabel","beginLabel","endLabel","labelAfter","objectProto","nativeObjectToString","symToStringTag","isOwn","unmasked","nullTag","undefinedTag","func","transform","arg","getPrototypeOf","objectTag","funcProto","funcToString","objectCtorString","Ctor","__data__","size","other","ListCache","entries","clear","entry","asyncTag","funcTag","genTag","proxyTag","uid","maskSrcKey","IE_PROTO","reIsHostCtor","reIsNative","HASH_UNDEFINED","Hash","MapCache","LARGE_ARRAY_SIZE","pairs","Stack","iteratee","objValue","props","customizer","isNew","newValue","argsTag","propertyIsEnumerable","MAX_SAFE_INTEGER","reIsUint","typedArrayTags","nodeIsTypedArray","isTypedArray","inherited","isArr","isArg","isBuff","isType","skipIndexes","isProto","predicate","resIndex","nativeGetSymbols","getOwnPropertySymbols","symbol","values","keysFunc","symbolsFunc","dataViewCtorString","mapCtorString","promiseCtorString","setCtorString","weakMapCtorString","getTag","ArrayBuffer","resolve","ctorString","Uint8Array","arrayBuffer","byteLength","dataView","byteOffset","reFlags","regexp","symbolProto","symbolValueOf","valueOf","typedArray","symbolTag","objectCreate","nodeIsMap","isMap","nodeIsSet","isSet","CLONE_DEEP_FLAG","CLONE_FLAT_FLAG","CLONE_SYMBOLS_FLAG","cloneableTags","baseClone","bitmask","isFlat","isFull","isFunc","stacked","subValue","keysIn","configurations","defaultConfigurations","_config","_setObjectToTarget","_setToTarget","_getFromSource","isDefine","leaveDOMReferences","cloneConfig","configuration","spy","called","path","stop","off","uuid","priority","normal","highest","high","low","lowest","_listeningTo","_emitterId","event","callback","listenTo","wasFired","stopListening","emitter","emitterInfo","eventCallbacks","emitters","_getEmitterId","_setEmitterId","emitterId","callbacks","eventName","events","getEvents","childEventName","newEventNodes","childEvents","node","createEventNamespace","lists","getCallbacksListsForNamespace","callbackDefinition","added","removeCallback","eventOrInfo","eventInfo","getCallbacksForEvent","_events","callbackArgs","_delegations","destinations","passAllDestinations","fireDelegatedEvents","return","rethrowUnexpectedError","to","nameOrFunction","Map","delete","eventNode","callbacksLists","childCallbacksLists","fireArgs","delegatedInfo","fire","mix","baseClass","mixins","mixin","getOwnPropertyNames","sourceDescriptor","getOwnPropertyDescriptor","compareArrays","a","b","minLen","parent","getChildIndex","getChild","includeSelf","parentFirst","ancestors","ancestorsA","getAncestors","ancestorsB","thisPath","getPath","nodePath","isBefore","_removeChildren","_fireChange","json","_textData","otherNode","textNode","offsetInText","objectToMap","isIterable","iterator","Matcher","pattern","_patterns","classes","element","singleElement","isElementMatching","results","matchName","patterns","hasAttribute","attribute","getAttribute","matchAttributes","getClassNames","hasClass","matchClasses","hasStyle","getStyle","matchStyles","_attrs","parseAttributes","_children","_insertChild","_classes","Set","classString","parseClasses","_styles","parseInlineStyles","_customProperties","cutType","styleString","otherElement","className","matcher","deep","childrenClone","child","getChildren","_clone","cloned","getFillerOffset","items","childCount","_remove","howMany","stylesMap","stylesString","quoteType","propertyNameStart","propertyValueStart","propertyName","charAt","char","propertyValue","classesSet","classesString","classArray","lastChild","thisArg","nativeMax","otherArgs","HOT_COUNT","HOT_SPAN","nativeNow","Date","now","lastCalled","stamp","remaining","assigner","sources","guard","observablePropertiesSymbol","boundObservablesSymbol","boundPropertiesSymbol","ObservableMixin","initObservable","properties","configurable","oldValue","bindProperties","isStringArray","boundProperties","bindings","bindTo","toMany","bindToMany","_observable","_bindProperties","_to","_bindings","unbindProperties","boundObservables","toObservable","toProperty","toProperties","toPropertyBindings","boundObservable","methodName","originalMethod","on","evt","observable","parsedArgs","lastObservable","parseBindToArgs","bindingsKeys","numberOfBindings","updateBoundObservableProperty","toPropertyName","bindingsToObservable","updateBoundObservables","updateBindToBound","observables","observableAndAttributePairs","getBindingTargets","every","documentSymbol","getCustomProperty","_setCustomProperty","isFocused","selection","editableElement","rootNameSymbol","rootName","boundaries","startPosition","direction","position","_createAt","singleCharacters","shallow","ignoreElementEnd","_boundaryStartParent","_boundaryEndParent","skip","done","prevPosition","_next","_previous","clone","previousPosition","isAtEnd","_createAfter","_formatReturnValue","charactersCount","textLength","textProxy","isAtStart","_createBefore","startOffset","nextPosition","isEqual","endOffset","editable","shifted","treeWalker","otherPosition","compareWith","otherPath","itemOrPosition","getLastMatchingPosition","enlargeTrimSkip","isAfter","nodeAfterStart","nodeAfter","nodeBeforeEnd","nodeBefore","otherRange","loose","isCollapsed","containsStart","containsPosition","containsEnd","ranges","isIntersecting","commonRangeStart","commonRangeEnd","getCommonAncestor","startElement","endElement","getShiftedBy","_createFromParentsAndOffsets","offsetSize","_createFromPositionAndShift","_","selectable","placeOrOffset","_ranges","_lastRangeBackward","_isFake","_fakeSelectionLabel","setTo","range","rangeCount","anchor","firstRange","getFirstRange","lastRange","getLastRange","otherSelection","isFake","fakeSelectionLabel","focus","thisRange","isBackward","numOfRangesA","getRanges","rangeA","getTrimmed","rangeB","nextSibling","previousSibling","_setRanges","_setFakeOptions","fake","backward","_createIn","_createOn","newFocus","_addRange","newRanges","isLastBackward","_pushRange","storedRange","addedRange","intersectingRange","_selection","delegate","getFirstPosition","getLastPosition","getSelectedElement","isSimilar","setFocus","_items","_itemMap","_idProperty","idProperty","_bindToExternalToInternalMap","WeakMap","_bindToInternalToExternalMap","_skippedIndexesFromExternal","itemId","idOrIndex","itemOrId","subject","itemDoesNotExist","externalItem","ctx","find","_bindToCollection","externalCollection","as","Class","_setUpBindToBinding","using","callbackOrProperty","addItem","isExternalBoundToThis","externalItemBound","finalIndex","skipped","getIndex","roots","_postFixers","postFixer","destroy","writer","wasFixed","DEFAULT_PRIORITY","_priority","_id","_clonesGroup","nonUiChildrenCount","userAgent","navigator","isMac","isEdge","isGecko","isSafari","isAndroid","features","isRegExpUnicodePropertySupported","isSupported","macGlyphsToModifiers","modifiersToMacGlyphs","keyCodes","arrowleft","arrowup","arrowright","arrowdown","backspace","enter","space","esc","tab","ctrl","cmd","letter","generateKnownKeyCodes","getCode","keyCode","altKey","ctrlKey","shiftKey","parseKeystroke","keystroke","splitKeystrokeText","sum","domDocument","toDomElement","domElement","getAttributeKeys","injectUiElementHandling","view","domConverter","domSelection","domTarget","ownerDocument","defaultView","getSelection","domSelectionCollapsed","getRangeAt","collapsed","domParent","focusNode","domOffset","focusOffset","viewPosition","domPositionToView","jumpedOverAnyUiElement","nextViewPosition","newDomPosition","viewPositionToDom","collapse","extend","jumpOverUiElement","_cloneGroups","_setTo","_setFocus","attributeElement","_document","renderFunction","uiElement","_setAttribute","_removeAttribute","_addClass","_removeClass","_setStyle","_removeStyle","_removeCustomProperty","positionOrRange","_breakAttributes","_breakAttributesRange","newElement","sourceRange","targetPosition","move","positionOffset","positionParent","_removeFromClonedElementsGroup","mergeAttributes","mergeTextNodes","_appendChild","prev","newPosition","validateNodesToInsert","errorContext","validNodesToInsert","some","validNode","container","getParentContainer","insertionPosition","_addToClonedElementsGroup","endPosition","rangeOrItem","validateRangeContainer","breakStart","breakEnd","parentContainer","removed","mergePosition","walker","getWalker","current","rangeToRemove","parentElement","ancestor","countBefore","_wrapPosition","viewSelection","setSelection","_wrapRange","newRange","_unwrapChildren","newName","viewElement","getAttributes","groupName","wrapElement","wrapPositions","isText","isAttribute","isUI","_wrapAttributeElement","shouldABeOutsideB","newAttribute","_wrapChildren","offsetChange","unwrapElement","unwrapPositions","unwrapped","_unwrapAttributeElement","movePositionToTextNode","breakTextNode","fakePosition","createAttributeElement","POSITIVE_INFINITY","wrapRange","wrap","wrapper","toWrap","canBeJoined","getStyleNames","setStyle","addClass","toUnwrap","removeAttribute","removeClass","removeStyle","forceSplitText","rangeStart","rangeEnd","isContainerOrFragment","offsetAfter","clonedNode","nodesToMove","group","getIdentity","textToMove","_data","t1","t2","nodeBeforeLength","startContainer","endContainer","NBSP_FILLER","BR_FILLER","fillerBr","dataset","ckeFiller","INLINE_FILLER_LENGTH","INLINE_FILLER","inlineFiller","startsWithFiller","domNode","isInlineFiller","domText","getDataWithoutFiller","jumpOverInlineFiller","fastDiff","cmp","atomicChanges","changeIndexes","arr1","arr2","firstIndex","findFirstDifferenceIndex","lastIndexOld","lastIndexNew","oldArrayReversed","cutAndReverse","newArrayReversed","findChangeBoundaryIndexes","newLength","fill","changeIndexesToAtomicChanges","newArray","changeIndexesToChanges","aLength","bLength","_insert","_delete","es","fp","snake","y1","y2","dir","y","x","nodeToInsert","isNode","Document","Node","domDocuments","markedAttributes","markedChildren","markedTexts","_inlineFiller","_fakeSelectionContainer","mapViewToDom","inlineFillerPosition","_updateChildrenMappings","_isSelectionInInlineFiller","_removeInlineFiller","_getInlineFillerPosition","_needsInlineFillerAtSelection","_updateAttrs","_updateChildren","_updateText","fillerDomPosition","addInlineFiller","_updateSelection","_updateFocus","actualDomChildren","expectedDomChildren","viewChildrenToDom","withChildren","diff","_diffNodeLists","actions","_findReplaceActions","equal","action","insertIndex","deleteIndex","viewChild","_updateElementMappings","unbindDomElement","bindElements","firstPos","selectionPosition","domFillerNode","selectionParent","selectionOffset","findAncestor","isEditable","viewText","findCorrespondingDomText","newDomText","viewToDom","actualText","expectedText","filler","insertData","deleteData","domAttrKeys","viewAttrKeys","nodesToUnbind","_markDescendantTextToSync","domToView","domChildList","fakeSelectionContainer","childList","filterOutFakeSelectionContainer","actualDom","expectedDom","newActions","actualSlice","expectedSlice","areSimilar","viewNode","_removeDomSelection","_removeFakeSelection","domRoot","_updateFakeSelection","_updateDomSelection","top","left","width","textContent","createFakeSelectionContainer","bindFakeSelection","_fakeSelectionNeedsUpdate","domRange","createRange","removeAllRanges","selectNodeContents","addRange","_domSelectionNeedsUpdate","ELEMENT_NODE","childAtOffset","tagName","fixGeckoSelectionAfterBr","isDomSelectionCorrect","oldViewSelection","domSelectionToView","anchorNode","contains","doc","activeDomElement","activeElement","mapDomToView","domParentOrArray","nodeAfterFiller","fillerNode","node1","node2","actualDomChild","expectedDomChild","isBlockFiller","DOCUMENT_NODE","BR_FILLER_REF","blockFillerMode","preElements","blockElements","_blockFiller","_domToViewMapping","_viewToDomMapping","_fakeSelectionMapping","viewDocumentSelection","domFragment","viewFragment","textData","_processDataFromViewText","createDocumentFragment","bindDocumentFragments","createElementNS","fillerPositionOffset","childView","viewRange","domStart","domEnd","setStart","setEnd","viewParent","domBefore","domAfter","getParentUIElement","_processDataFromDomText","isComment","isDocumentFragment","viewName","keepOriginalCase","domChildrenToView","domChild","fakeSelectionToView","isDomSelectionBackward","viewRanges","domRangeToView","viewStart","viewEnd","findCorrespondingViewText","viewBefore","domElementOrDocumentFragment","isElement","documentFragmentOrElement","viewEditable","domEditable","scrollX","scrollY","scrollPositions","forEachDomNodeAncestor","scrollLeft","scrollTop","scrollTo","DOCUMENT_FRAGMENT_NODE","COMMENT_NODE","isEqualNode","includes","hasBlockParent","isNbspBlockFiller","anchorOffset","detach","_isDomSelectionPositionCorrect","prevNode","_getTouchingViewTextNode","_nodeEndsWithSpace","nextNode","_hasDomParentOfType","_getTouchingInlineDomNode","shouldLeftTrim","_checkShouldLeftTrimDomText","shouldRightTrim","_checkShouldRightTrimDomText","Text","getNext","topmostParent","createTreeWalker","NodeFilter","SHOW_TEXT","SHOW_ELEMENT","acceptNode","FILTER_ACCEPT","FILTER_SKIP","currentNode","touchingNode","lca","nodeA","nodeB","boundaryParent","parents","isWindow","stringifiedObject","proxy","_getProxyEmitter","attach","listeningEmitter","listenedToEmitterId","getNodeUID","_domNode","_domListeners","domListener","_createDomListener","useCapture","addEventListener","removeListener","domEvt","removeEventListener","Observer","isEnabled","SetCache","COMPARE_PARTIAL_FLAG","COMPARE_UNORDERED_FLAG","equalFunc","isPartial","arrLength","othLength","seen","arrValue","othValue","compared","othIndex","convert","objProps","objLength","skipCtor","objCtor","othCtor","objIsArr","othIsArr","objTag","othTag","objIsObj","othIsObj","isSameTag","objIsWrapped","othIsWrapped","objUnwrapped","othUnwrapped","baseIsEqual","characterData","characterDataOldValue","subtree","_renderer","_domElements","_mutationObserver","MutationObserver","_onMutations","takeRecords","observe","disconnect","domMutations","mutatedTexts","mutatedElements","mutation","_isBogusBrMutation","oldText","newText","viewMutations","mutatedText","markToSync","viewChildren","newViewChildren","sameNodes","oldChildren","newChildren","viewSelectionAnchor","viewSelectionFocus","child1","child2","forceRender","addedNode","removedNodes","addedNodes","domEvent","additionalData","preventDefault","stopPropagation","domEventType","onDomEvent","eventType","metaKey","NAN","reTrim","reIsBadHex","reIsBinary","reIsOctal","freeParseInt","isBinary","FUNC_ERROR_TEXT","nativeMin","wait","lastArgs","lastThis","maxWait","timerId","lastCallTime","lastInvokeTime","leading","maxing","trailing","invokeFunc","time","shouldInvoke","timeSinceLastCall","timerExpired","trailingEdge","setTimeout","timeWaiting","remainingWait","debounced","isInvoking","leadingEdge","clearTimeout","cancel","flush","_fireSelectionChangeDoneDebounced","_isArrowKeyCode","_handleSelectionMove","newSelection","oldSelection","mutationObserver","getObserver","_documents","WeakSet","_clearInfiniteLoopInterval","setInterval","_clearInfiniteLoop","_loopbackCounter","_handleSelectionChange","clearInterval","isReadOnly","newViewSelection","_renderTimeoutId","selectedEditable","isComposing","isRange","getBorderWidths","getComputedStyle","borderTopWidth","right","borderRightWidth","bottom","borderBottomWidth","borderLeftWidth","rectProperties","isSourceRange","_source","writable","copyRectProperties","getDomRangeRects","getBoundingClientRect","innerWidth","innerHeight","height","anotherRect","rect","getIntersection","getArea","visibleRect","isBody","commonAncestorContainer","parentRect","intersectionRect","prop","intersectRect","scrollBarWidth","scrollBarHeight","documentElement","clientWidth","clientHeight","borderWidths","offsetWidth","offsetHeight","rects","clientRects","getClientRects","elementOrRange","body","scrollViewportToShowTarget","viewportOffset","targetWindow","getWindow","currentWindow","currentFrame","firstAncestorToScroll","scrollAncestorsToShowRect","getParentElement","getRectRelativeToWindow","targetRect","scrollWindowToShowRect","frameElement","targetShiftedDownRect","moveBy","targetShiftedUpRect","viewportRect","excludeScrollbarsAndBorders","isAbove","isBelow","isLeftOf","isRightOf","getRect","parentWindow","firstRect","secondRect","relativeWindow","frame","frameRect","scrollAncestorsToShowTarget","domRoots","_initialDomRootAttributes","_observers","_ongoingChange","_postFixersInProgress","_renderingDisabled","_hasChangedSinceTheLastRendering","_writer","addObserver","_render","viewRoot","getRoot","_name","initialDomRootAttributes","updateContenteditableAttribute","change","observer","viewRangeToDom","isRenderingInProgress","callbackResult","_callPostFixers","disableObservers","enableObservers","toMap","getChildStartOffset","toJSON","_nodes","_insertNodes","getNodeIndex","maxOffset","getNodeStartOffset","totalOffset","nodeList","indexStart","getNode","offsetToIndex","relativePath","_removeNodes","fromJSON","stickiness","_visitedParent","prevVisitedParent","formatReturnValue","offsetInTextNode","newOffset","diffAt","leftParent","getParentPath","operation","_getTransformedByInsertOperation","_getTransformedByMoveOperation","_getTransformedBySplitOperation","_getTransformedByMergeOperation","_getTransformedByInsertion","_getTransformedByMove","sourcePosition","movedRange","_getCombined","splitPosition","moveTargetPosition","graveyardPosition","_getTransformedByDeletion","deletionPosition","deletePosition","transformed","insertPosition","combined","graveyard","getCommonPath","posParent","operations","getTransformedByOperation","containsRange","spread","newPos","moveRange","differenceSet","getDifference","difference","common","transformedCommon","newStart","newEnd","refIndex","_modelToViewMapping","_viewToModelMapping","_viewToModelLengthCallbacks","_markerNameToElements","_elementToMarkerNames","_unboundMarkerNames","viewContainer","modelPosition","_findPositionIn","viewBlock","findMappedViewAncestor","modelParent","modelOffset","_toModelOffset","modelElement","toModelElement","markerName","toViewElement","elements","names","nameToElements","elementToNames","markerNames","toModelPosition","modelRange","toViewPosition","mapper","isPhantom","boundElements","getElementsWithSameId","viewElementName","lengthCallback","viewOffset","getModelLength","expectedOffset","lastLength","_moveViewPositionToTextNode","_consumable","_textProxyRegistry","_normalizeConsumableType","_getSymbolForTextProxy","itemConsumables","startMap","endMap","_addSymbolForTextProxy","conversionApi","dispatcher","differ","markers","getMarkersToRemove","convertMarkerRemove","getChanges","convertInsert","convertRemove","convertAttribute","attributeKey","attributeOldValue","attributeNewValue","flushUnboundMarkerNames","markerRange","getRange","convertMarkerAdd","getMarkersToAdd","consumable","_createInsertConsumable","_testAndFire","_clearConversionApi","_createConsumableForRange","markersAtSelection","getMarkersAtPosition","_createSelectionConsumable","shouldMarkerChangeBeConverted","getItems","containsItem","anyNewRange","oldRange","_removeAllRanges","directChange","_popRange","attributeKeys","visited","startBlock","getParentBlock","isTopBlockInRange","isUnvisitedTopBlock","endBlock","isTouching","limitStartPosition","limitEndPosition","_checkRange","isUnvisitedBlock","model","isBlock","hasParentLimit","isLimit","parentBlock","findAncestorBlock","bindWithDocument","isDocumentOperation","_createFromRanges","boundariesChanged","contentChanged","doesOperationChangeRangeContent","toRange","storePrefix","hasOwnRange","isGravityOverridden","getSelectedBlocks","containsEntireContent","_updateMarkers","_updateAttributes","_getStoredAttributes","overrideGravity","restoreGravity","startsWith","_model","_attributePriority","_fixGraveyardRangesData","_hasChangedRange","_overriddenGravityRegister","liveRange","_fixGraveyardSelection","_validateSelectionRange","batch","changeParent","enqueueChange","storedAttributes","clearAttributesStoredInElement","_getDefaultRange","optionsOrPlaceOrOffset","overrideUid","_prepareRange","fromRange","selectionRange","clearAll","newAttributes","_getSurroundingAttributes","oldAttributes","_setAttributesTo","changed","newKey","oldKey","realKey","getAttrsIfCharacter","isObject","removedRangeStart","positionCandidate","getNearestSelectionRange","ConversionHelpers","dispatchers","_dispatchers","conversionHelper","normalizeToElementConfig","elementCreator","consume","insertElement","converterPriority","downcastElementToElement","modelValue","getFromAttributeCreator","oldViewElement","newViewElement","viewWriter","toViewRange","unwrap","downcastAttributeToElement","normalizeToAttributeConfig","attributeCreator","oldAttribute","changeAttribute","downcastAttributeToAttribute","isOpening","viewStartElement","viewEndElement","bindElementToMarker","insertUIElement","markerNameToElements","unbindElementFromMarkerName","createRangeOn","clearClonedElementsGroup","downcastMarkerToElement","highlightDescriptor","descriptor","prepareDescriptor","createViewElementFromHighlightDescriptor","rangeAfterWrap","highlightText","highlightElement","viewHighlightElement","removeHighlight","downcastMarkerToHighlight","viewElementType","modelData","viewElementDefinition","createContainerElement","createUIElement","createViewElementFromDefinition","modelAttributeValue","upcastElementToElement","normalizeModelAttributeConfig","converter","prepareToAttributeConverter","elementName","getViewElementNameFromConfig","upcastElementToAttribute","viewKey","normalized","normalizeViewAttributeKeyValueConfig","upcastAttributeToAttribute","oldModel","modelWriter","normalizeToMarkerConfig","upcastElementToMarker","matcherResult","viewItem","getModelElement","splitResult","splitToAllowedParent","modelCursor","convertChildren","createPositionAt","getSplitParts","createPositionBefore","createPositionAfter","cursorParent","prepareToElementConverter","viewConfig","viewAttributeKeyToCopy","defaultModelValue","modelKey","configToTest","onlyViewNameIsDefined","modelAttribute","checkAttribute","setAttributeOn","downcastDispatcher","_disableRendering","convertChanges","convertSelection","modelSelection","toModelRange","convertSelectionChange","createText","modelEnd","createRangeIn","unbindViewElement","brokenPosition","breakAttributes","editor","availablePlugins","_editor","_availablePlugins","_plugins","PluginConstructor","pluginName","errorMsg","plugins","removePlugins","that","loading","loaded","pluginConstructors","mapToAvailableConstructors","removePluginConstructors","missingPlugins","pluginNameOrConstructor","getPluginConstructor","getMissingPluginNames","console","Promise","reject","loadPlugin","then","initPlugins","requires","RequiredPluginConstructorOrName","RequiredPluginConstructor","requiredBy","_add","instantiatePlugin","catch","loadedPlugins","method","promise","PluginConstructorOrName","promises","pluginInstance","plugin1","plugin2","_commands","commandName","command","execute","commands","translate","language","translationKey","numberOfLanguages","CKEDITOR_TRANSLATIONS","hasTranslation","RTL_LANGUAGE_CODES","uiLanguage","contentLanguage","uiLanguageDirection","getLanguageDirection","contentLanguageDirection","_t","warn","translatedString","languageCode","ViewConsumable","_consumables","consumables","elementConsumables","revert","instance","consumablesFromElement","createFrom","_canConsumeName","_test","_consume","_revert","consumableName","_sourceDefinitions","_attributeProperties","decorate","SchemaContext","getDefinition","itemName","_clearCache","_compiledDefinitions","_compile","getDefinitions","def","isInline","_checkContextMatch","attributeName","allowAttributes","positionOrBaseElement","elementToMerge","checkMerge","checkChild","childDef","retValue","getAttributeProperties","selectionOrRangeOrPosition","rangeCommonAncestor","getMinimalFlatRanges","convertToMinimalFlatRanges","_getValidRangesForRange","backwardWalker","forwardWalker","forward","step","combineWalkers","removeDisallowedAttributeFromNode","positionsInRange","getPositions","compiledDefinitions","sourceRules","itemNames","compileBaseItemRule","compileAllowContentOf","compileAllowWhere","compileAllowAttributesOf","compileInheritPropertiesFrom","cleanUpAllowIn","cleanUpAllowAttributes","contextItemIndex","contextItem","getItem","allowIn","parentRule","mapContextItem","query","getNames","endsWith","sourceItemRules","itemRule","allowContentOf","allowWhere","allowAttributesOf","inheritTypesFrom","sourceItemRule","typeNames","copyTypes","copyProperty","inheritFrom","inheritAllFrom","makeInheritAllWork","allowContentOfItemName","getAllowedChildren","allowedItem","allowWhereItemName","allowedIn","allowAttributeOfItem","inheritAttributes","inheritPropertiesOfItem","existingItems","itemToCheck","ctxItem","_splitParts","_modelCursor","convertItem","_convertItem","_convertChildren","_splitToAllowedParent","_getSplitParts","contextDefinition","append","createContextTree","store","documentFragment","_removeEmptyElements","modelItem","markerElements","markerElement","currentPosition","extractMarkersFromModelFragment","nextModelCursor","allowedParent","findAllowedParent","treeWalkerValue","originalPart","splitPart","_registerSplitPair","anyRemoved","dataProcessor","processor","upcastDispatcher","_checkIfRootsExists","hasContent","ignoreWhitespaces","modelElementOrFragment","viewDocumentFragment","toView","toData","clearBindings","elementRange","intersection","_getMarkersRelativeToElement","version","initialData","main","modelRoot","newData","removeSelectionAttribute","toModel","viewElementOrFragment","rootNames","getRootNames","downcastDispatchers","upcastDispatchers","_helpers","_downcast","_createConversionHelpers","isDowncast","_upcast","elementToElement","_getAllUpcastDefinitions","attributeToElement","elementToAttribute","attributeToAttribute","upcastAlso","_getUpcastDefinition","upcastAlsoItem","Batch","op","baseVersion","Operation","__className","_normalizeNodes","_splitNodeAtPosition","_mergeNodesAtIndex","_move","_haveSameAttributes","mergedNode","offsetDiff","firstPart","secondPart","iteratorA","iteratorB","newTargetPosition","getMovedRangeStart","sourceElement","targetElement","sourceOffset","targetOffset","shouldReceiveAttributes","gyPosition","originalNodes","affectsData","_markers","oldName","mergedElement","getInsertionPosition","splitElement","_doc","_assertWriterUsedCorrectly","isSameTree","addOperation","applyOperation","rangeRootPosition","usingOperation","updateMarker","addMarker","itemOrRange","setAttributeOnRange","setAttributeOnItem","removeAttributesFromItem","_addOperationForAffectedMarkers","flat","applyRemoveOperation","_merge","_mergeDetached","createPositionFromPath","createSelection","merge","renameOperation","limitElement","firstSplitElement","firstCopyElement","elementOrString","shiftedRange","applyMarkerOperation","_set","markerOrName","currentMarker","_refresh","hasUsingOperationDefined","affectsDataDefined","currentRange","updatedRange","managedUsingOperations","keyOrObjectOrIterable","_setSelectionAttribute","keyOrIterableOfKeys","_removeSelectionAttribute","_overrideGravity","_restoreGravity","storeKey","_getStoreAttributeKey","_currentWriter","isAffected","elementBefore","elementAfter","affectedInLeftElement","affectedInRightElement","affectedAfterLeftElement","affectedBeforeRightElement","valueBefore","valueAfter","lastSplitPosition","previousValue","rootA","rootB","markerCollection","_markerCollection","_changesInElement","_elementSnapshots","_changedMarkers","_changeCount","_cachedChanges","_cachedChangesWithGraveyard","_isInInsertedElement","_markRemove","_markInsert","getMarkersIntersectingRange","bufferMarkerChange","_markAttribute","sourceParentInserted","targetParentInserted","graveyardParent","mergedIntoElement","buffered","includeChangesInGraveyard","diffSet","changes","snapshotChildren","elementChildren","_getChildrenSnapshot","_generateActionsFromChanges","_getInsertDiff","_getRemoveDiff","elementAttributes","snapshotAttributes","_getAttributesDiff","changeCount","prevDiff","thisDiff","isConsecutiveTextRemove","isConsecutiveTextAdd","isConsecutiveAttributeChange","_changesInGraveyardFilter","changeItem","_markChange","_removeAllNestedChanges","_makeSnapshot","_getChangesForElement","_handleChange","inc","nodesToHandle","old","incEnd","oldEnd","intersectionLength","howManyAfter","attributePart","diffs","snapshot","oldChildrenLength","oldChildrenHandled","repeat","posInGy","rangeInGy","History","_operations","_undoPairs","_undoneOperations","undoneOperation","undoingOperation","isInsideSurrogatePair","character","isLowSurrogateHalf","isInsideCombinedSymbol","graveyardName","history","_hasSelectionChangedFromTheLastChangeBlock","createRoot","bufferOperation","_hasDocumentChangedFromTheLastChangeBlock","refresh","hasDataChanges","reset","defaultRoot","_getDefaultRoot","validateTextNodePosition","rangeBoundary","oldMarker","hasChanged","_attachLiveRange","_managedUsingOperations","_affectsData","_destroyMarker","prefix","_detachLiveRange","_liveRange","stopDelegating","oldPosition","toPosition","canMergeWith","_filterAttributesOf","_affectedStart","_affectedEnd","parentContext","_handleNode","isFirst","isLast","removeDisallowedAttributes","nodeToSelect","_handleObject","_checkAndSplitToAllowedPosition","_mergeSiblingsOf","_handleDisallowedNode","_tryAutoparagraphing","handleNodes","livePos","fromPosition","_setAffectedBoundaries","mergeLeft","_canMergeLeft","mergeRight","_canMergeRight","mergePosLeft","mergePosRight","livePosition","paragraph","_getAllowedIn","tempPos","deleteContent","selRange","doNotResetEntireContent","getLimitElement","shouldEntireContentBeReplacedWithParagraph","insertParagraph","replaceEntireContentWithParagraph","startPos","endPos","leaveUnmerged","mergeBranches","startParent","endParent","leftPos","rightPos","rangeToCheck","checkCanBeMerged","parentToRemove","collapseSelectionAt","isTextAllowed","isParagraphAllowed","shouldAutoparagraph","validSelectionRange","doNotAutoparagraph","wordBoundaryCharacters","tryExtendingTo","unit","isForward","isAtWordBoundary","isAtNodeBoundary","boundaryChar","getCorrectWordBreakPosition","getCorrectPosition","getSearchRange","searchEnd","offsetToCheck","removeRangeContent","parentsToCheck","itemRange","parentToCheck","removeRange","injectSelectionPostFixer","registerPostFixer","correctedRange","tryFixingRange","fixedRanges","selectionStart","selectionEnd","selectionPostFixer","originalPosition","nearestSelectionRange","fixedPosition","tryFixingCollapsedRange","isTextAllowedOnStart","isTextAllowedOnEnd","startLimitElement","endLimitElement","startIsOnBlock","endIsOnBlock","checkSelectionOnNonLimitElements","fixedStart","fixedEnd","isStartInLimit","isEndInLimit","bothInSameParent","expandStart","isInObject","expandEnd","findOutermostLimitAncestor","tryFixingNonCollapsedRage","startingNode","isLimitNode","_pendingChanges","_validate","register","addChildCheck","childDefinition","_runPendingChanges","batchOrType","_execute","insertion","nodesToInsert","getSelectionRange","affectedRange","getAffectedRange","insertContent","setSelectionFocus","modifySelection","frag","commonPath","commonParent","getNodeByPath","flatSubtreeRange","appendText","leftExcessRange","getSelectedContent","rangeOrElement","intersectingMarker","ret","currentBatch","callbackReturnValue","_handleChangeBlock","_listener","keyEvtData","evtData","builtinPlugins","defaultConfig","languageConfig","locale","ui","once","editing","conversion","addAlias","keystrokes","extraPlugins","init","readyPromise","BasicHtmlWriter","fragment","implementation","createHTMLDocument","innerHTML","_domParser","DOMParser","_domConverter","_htmlWriter","getHtml","_toDom","parseFromString","_components","originalName","getNormalized","_elements","_nextEventLoopTimeout","_focus","_blur","focusedElement","componentFactory","focusTracker","_editableElementsMap","ckeditorInstance","editorUI","documentPlaceholders","enablePlaceholder","isDirectHost","updateDocumentPlaceholders","hidePlaceholder","placeholders","wasViewModified","updatePlaceholder","hostElement","getChildPlaceholderHostSubstitute","isEmptyish","selectionAnchor","needsPlaceholder","showPlaceholder","_toolbarConfig","editingView","editingRoot","setEditableElement","attachDomRoot","_initPlaceholder","_initToolbar","detachDomRoot","toolbar","fillFromConfig","origin","originKeystrokeHandler","originFocusTracker","beforeFocus","afterBlur","enableToolbarKeyboardFocus","placeholderText","isRendered","_parentElement","elementOrDocFragment","dest","evtName","xhtmlNs","_isRendered","_revertData","_renderNode","intoFragment","isApplying","revertData","_revertTemplateFromNode","isView","isTemplate","eventNameOrFunctionOrAttribute","TemplateToBinding","eventNameOrFunction","if","valueIfTrue","TemplateIfBinding","template","extendTemplate","extendObjectValueArray","eventListeners","childIndex","isInvalid","_renderText","_renderElement","_renderAttributes","_renderElementChildren","_setUpListeners","hasTemplateBinding","_bindToObservable","updater","getTextUpdater","attrName","attrValue","domAttrValue","attrNs","valueToBind","shouldExtend","getAttributeUpdater","_renderStyleAttribute","isFalsy","arrayValueReducer","setAttributeNS","styleName","styleValue","getStyleUpdater","isViewCollection","setParent","childRevertData","revertBindings","schemaItem","domEvtName","domSelector","activateDomEventListener","syncValueSchemaValue","templateBinding","activateAttributeListener","revertBinding","TemplateBinding","matches","getValue","getValueSchemaValue","removeAttributeNS","normalizePlainTextDefinition","normalizeTextDefinition","listeners","arrayify","normalizeListeners","normalizeAttributes","cur","ext","_viewCollections","_unboundChildren","createCollection","collection","_bindTemplate","registerChild","getViews","_renderBodyCollection","_bodyCollectionContainer","bodyElement","class","setTemplate","lang","_editableElement","_hasExternalElement","_editingView","_updateIsFocusedClasses","updateAfterRender","role","FocusCycler","keystrokeHandler","focusables","isFocusable","_getFocusableItem","viewIndex","focused","previous","collectionLength","display","RESIZE_CHECK_INTERVAL","_callback","_previousRects","_periodicCheckTimeout","_startPeriodicCheck","_stopPeriodicCheck","unobserve","periodicCheck","_checkElementRectsAndExecuteCallback","_hasRectChanged","contentRect","currentRect","previousRect","bindTemplate","selectstart","focusLast","getOptimalPosition","positions","limiter","fitInViewport","positionedElementAncestor","getPositionedAncestor","elementRect","bestPosition","limiterRect","getVisible","bestPositionRect","bestPositionName","maxLimiterIntersectArea","maxViewportIntersectArea","elementRectArea","positionName","positionRect","getPosition","limiterIntersectArea","viewportIntersectArea","limiterViewportIntersectRect","getIntersectionArea","setBestPosition","getBestPosition","getAbsoluteRectCoordinates","ancestorPosition","ancestorBorderWidths","moveTo","buttonView","panelView","isOpen","panelPosition","_getOptimalPosition","_panelPositions","closeDropdown","southEast","southWest","northEast","northWest","defaultPanelPositions","buttonRect","panelRect","viewBox","_updateXMLContent","_colorFillPaths","svg","fillColor","querySelectorAll","ariaLabelUid","tooltipView","_createTooltipView","labelView","_createLabelView","iconView","_getTooltipString","tabindex","isToggleable","mousedown","click","icon","tooltip","getEnvKeystrokeText","arrowView","_createArrowView","_focusCycler","focusPrevious","focusNext","focusFirst","toggleSwitchView","_createToggleView","clickOutsideHandler","activator","contextElements","contextElement","createDropdown","ButtonClass","dropdownView","closeDropdownOnBlur","closeDropdownOnExecute","focusDropdownContentsOnArrows","addDefaultBehavior","addToolbarToDropdown","buttons","toolbarView","addListToDropdown","listView","listItemView","itemsView","_behavior","shouldGroupWhenFull","StaticLayout","viewFocusables","viewItemsView","viewFocusTracker","viewLocale","ungroupedItems","groupedItems","groupedItemsDropdown","_createGroupedItemsDropdown","resizeObserver","cachedPadding","_updateFocusCycleableItems","_updateGrouping","_enableGroupingOnResize","wereItemsGrouped","_areItemsOverflowing","_groupLastItem","_ungroupFirstItem","lastChildRect","toolbarRect","computedStyle","paddingProperty","previousWidth","ResizeObserver","dropdown","sourceElementOrData","secureSourceElement","getData","HTMLTextAreaElement","setDataInElement","isHTMLElement","getInitialData","Plugin","HighlightStack","_stack","oldTop","_insertDescriptor","newTop","compareDescriptors","oldDescriptor","newDescriptor","_removeDescriptor","findIndex","shouldABeBeforeB","classesToString","WIDGET_CLASS_NAME","WIDGET_SELECTED_CLASS_NAME","isWidget","toWidget","setCustomProperty","labelOrCreator","setLabel","hasSelectionHandle","widgetElement","selectionHandle","addSelectionHandle","setHighlightHandling","normalizeToArray","getLabel","labelCreator","toWidgetEditable","findOptimalInsertionPosition","selectedElement","firstBlock","positionAfter","createTocViewElement","createTocDataElement","buttonName","withText","tocElement","I18n","placeholder","embeddedTableSymbol","isEmbeddedTableWidgetSelected","isEmbeddedTableWidget","getOPService","getPluginContext","services","getOPResource","getOPPath","pathName","pluginContext","button","macro_text","queryProps","opEmbeddedTableQuery","toEmbeddedTableWidget","createEmbeddedTableView","createEmbeddedTableDataElement","runInZone","externalQueryConfiguration","show","newQuery","selectAllKeystrokeCode","viewDocument","_previouslySelected","_clearPreviouslySelectedWidgets","lastMarked","isChild","_onMousedown","_onKeydown","_handleDelete","domEventData","isInsideNestedEditable","detail","_setSelectionOverElement","isLtrContent","wasHandled","isArrowKeyCode","isSelectAllKeyCode","_handleEnterKey","_selectAllNestedEditableContent","_selectAllContent","_handleArrowKeys","objectElement","_getObjectElementNextToSelection","previousNode","nodeToRemove","objectElement2","isBackwards","paragraphLimit","documentSelection","widgetParent","probe","widget","toUnit","toPx","defaultLimiterElement","isVisible","defaultPositions","positionOptions","southArrowNorth","southArrowNorthWest","southArrowNorthEast","northArrowSouth","northArrowSouthWest","northArrowSouthEast","optimalPosition","unpin","_pinWhenIsVisibleCallback","_startPinning","_stopPinning","hide","attachTo","getDomElement","limiterElement","scrollTarget","isWithinScrollTarget","isLimiterWithinScrollTarget","getNorthTop","balloonRect","arrowVerticalOffset","getSouthTop","arrowHorizontalOffset","northWestArrowSouth","northWestArrowSouthWest","northWestArrowSouthEast","northEastArrowSouth","northEastArrowSouthEast","northEastArrowSouthWest","southWestArrowNorth","southWestArrowNorthWest","southWestArrowNorthEast","southEastArrowNorth","southEastArrowNorthEast","southEastArrowNorthWest","positionLimiter","_viewToStack","_idToStack","_rotatorView","_createRotatorView","_fakePanelsView","_createFakePanelsView","hasView","stackId","_numberOfStacks","_visibleStack","singleViewMode","showStack","_showView","_singleViewMode","visibleView","_showNextStack","hideView","_getStackId","pin","_getBalloonPosition","updatePosition","visibleStack","stacks","nextIndex","isSingleViewMode","numberOfStacks","buttonNextView","buttonPrevView","_showPrevStack","number","balloonClassName","withArrow","showView","_createButtonView","balloonPanelView","_balloonPanelView","_addPanels","_removePanels","deregisterChild","numberOfPanels","createToolbarEditButton","createEditToolbar","config_namespace","isWidgetSelected","toolbarConfig","_balloon","_toolbar","_checkIsVisible","_isVisible","selectionCallback","balloon","getBalloonPositionData","repositionContextualBalloon","_hideToolbar","currentQuery","wpButtonMacroSymbol","isWpButtonMacroWidgetSelected","isWpButtonMacroWidget","createMacroViewElement","macros","configureWorkPackageButton","typename","macroLabel","toWpButtonMacroWidget","macroService","_actions","hasAny","FileReader","reader","_reader","onprogress","file","total","onload","onerror","onabort","readAsDataURL","abort","loaders","_updatePendingAction","_loadersMap","_pendingAction","uploaded","fileOrPromise","createUploadAdapter","loader","aggregatedUploaded","aggregatedTotal","uploadTotal","fileOrPromiseOrLoader","getLoader","_destroy","pendingActions","getMessage","uploadedPercent","filePromise","uploadAdapterCreator","_filePromiseWrapper","_createFilePromiseWrapper","_adapter","status","read","upload","uploadResponse","isFulfilled","rejecter","OpUploadResourceAdapter","resource","uploadAttachments","resourceContext","buildResponse","default","uploadUrl","_fileInputView","accept","multiple","files","createImageTypeRegExp","regExpSafeNames","fetchLocalImage","imageSrc","fetch","blob","mimeType","getImageMimeType","filename","File","createFileFromBlob","imageTypes","imageTypesRegExp","acceptedType","allowMultipleFiles","imagesToUpload","uploadStatusChange","modelImage","uploadId","fileRepository","viewFigure","_startAppearEffect","_showPlaceholder","_hidePlaceholder","progressBar","_createProgressBar","_showProgressBar","viewImg","_displayLocalImage","completeIcon","_showCompleteIcon","_removeUIElement","_hideProgressBar","_stopAppearEffect","_getUIElement","_createPlaceholder","imageFigure","uniqueProperty","alert","_showNotification","namespace","DataTransfer","nativeDataTransfer","kind","getAsFile","getFiles","_native","setData","handleInput","targetRanges","dropRange","dataTransfer","clipboardData","domDoc","clientX","clientY","caretRangeFromPoint","rangeParent","rangeOffset","getDropViewRange","smallPaddingElements","modelDocument","onCopyCut","_htmlDataProcessor","fullMatch","spaces","plainTextToHtml","scrollToTheSelection","dataController","modelFragment","viewToPlainText","childText","removeChildren","oldElement","insertChild","Command","_disableStack","forceDisabled","clearForceDisabled","forceDisable","getSelectedImageWidget","isImageWidget","isImage","insertImage","imageElement","insertAtSelection","isImageAllowed","getInsertImageParent","isImageAllowedInParent","checkSelectionOnObject","isInOtherImage","filesToUpload","uploadImage","createLoader","isHtmlIncluded","images","fetchableImages","isLocalImage","fetchableImage","isInGraveyard","getImagesFromChangeItem","_readAndUpload","notification","domFigure","originalDisplay","_ckHack","setAttributes","uploadStatus","_parseAndSetSrcsetAttributeOnImage","clean","showWarning","destroyLoader","maxWidth","srcsetAttribute","isNaN","childPagesMacroSymbol","isChildPagesMacroWidgetSelected","isChildPagesMacroWidget","page","includeParent","modelAttributeToView","setPlaceholderContent","placeholderContainer","toChildPagesMacroWidget","pageLabel","pageLabelContainer","placeholderContent","includeParentText","pageAttribute","configureChildPages","macroConf","getCopyOnEnterAttributes","allAttributes","copyOnEnter","isSelectionEmpty","attributesToCopy","splitBlock","setSelectionAttribute","isContainedWithinOneElement","enterBlock","splitPos","isSoft","insertBreak","softBreakAction","anchorPos","isInsideLimitElement","breakLineElement","createEmptyElement","ChangeBuffer","limit","isLocked","_changeCallback","_batch","_reset","_selectionChangeCallback","createBatch","ignoreLock","undoStepSize","_buffer","_batches","textInsertions","resultRange","isCollapsedRange","lock","unlock","injectUnsafeKeystrokesHandling","latestCompositionSelection","inputCommand","handleUnsafeKeystroke","isSelectionUnchanged","keyData","safeKeycodes","isSafeKeystroke","deleteSelectionContent","isFlatSelection","getSingleTextNodeChange","lastOperation","pushLast","isContinuationOf","expected","diffToChanges","compareChildNodes","oldChild","newChild","mutations","containerChildrenMutated","_handleContainerChildrenMutations","_handleTextMutation","_handleTextNodeInsertion","mutationsCommonAncestor","commonAncestor","getMutationsContainer","domMutationCommonAncestor","freshDomConverter","modelFromCurrentDom","currentModel","modelFromDomChildren","currentModelChildren","lastDomChild","lastCurrentChild","isSafeForTextMutation","diffResult","firstChangeAt","insertions","deletions","calculateChanges","modelSelectionRange","insertText","viewPos","modelPos","insertedText","lastChangeAt","handle","injectTypingMutationsHandling","_shouldEntireContentBeReplacedWithParagraph","sequence","_replaceEntireContentWithParagraph","limitElementFirstChild","fireViewDeleteEvent","originalEvent","hasWordModifier","inputType","selectionToRemove","deleteCommandParams","domSelectionAfterDeletion","transformations","setTransformation","OperationA","OperationB","transformationFunction","aGroup","noUpdateTransformation","getTransformation","transformSets","operationsA","operationsB","contextFactory","useRelations","forceWeakRemove","setOriginalOperations","originalOperations","nextTransformIndex","nextBaseVersionA","nextBaseVersionB","originalOperationsACount","originalOperationsBCount","opA","indexB","opB","newOpsA","getContext","newOpsB","updateRelation","newOpA","padWithNoOps","brokenOperationsACount","brokenOperationsBCount","updateBaseVersions","_history","_useRelations","_forceWeakRemove","_relations","takeFrom","originalOperation","_setRelation","affectedLeft","affectedRight","side","wasInLeftElement","wasStartBeforeMergedElement","wasEndBeforeMergedElement","wasInRightElement","aIsStrong","aWasUndone","_wasUndone","bWasUndone","abRelation","_getRelation","baRelation","originalOp","wasUndone","isUndoneOperation","origB","undoneB","getUndoneOperation","origA","relationsA","relation","_getComplementaryAttributeOperations","insertOperation","insertValue","_moveTargetIntoMovedRange","_makeMoveOperationsFromRanges","hasSameParentAs","moveOp","_breakRangeByMoveOperation","aNewRange","aToGraveyard","bToGraveyard","aIsWeak","removedRange","mergeInside","mergeSplittingElement","getReversed","aCompB","shouldSpread","rightRange","movesGraveyardElement","gyMoveSource","splitNodesMoveSource","gyMoveTarget","gyMove","splitNodesMoveTargetPath","splitNodesMoveTarget","splitNodesMove","extraRename","splitPath","additionalSplit","rangeToMove","gyElementMoved","newParentPosition","newTargetPath","howManyRemoved","aInGraveyard","bInGraveyard","newPositionPath","_createdBatches","docSelection","selectionRanges","transformSelectionRange","batchToUndo","undoingBatch","operationsToUndo","operationToUndo","nextBaseVersion","historyOperations","getOperations","reversedOperations","setOperationAsUndone","getTransformedByOperations","batchIndex","_undo","_restoreSelection","redoingBatch","_batchRegistry","_undoCommand","_redoCommand","isRedoBatch","isUndoBatch","addBatch","clearStack","undoneBatch","localizedUndoIcon","undo","redo","localizedRedoIcon","_addButton","Icon","TOKEN_COOKIE_NAME","TOKEN_LENGTH","tokenCharset","getCsrfToken","cookie","pair","decodeURIComponent","getCookie","randValues","crypto","getRandomValues","generateToken","_initRequest","_initListeners","_sendRequest","xhr","XMLHttpRequest","responseType","genericError","response","lengthComputable","FormData","send","callbackOrCommand","getLastTextLine","rangeText","testRegexpOrCallback","attributeOrCallback","regExp","testCallback","formatCallback","leftDel","rightDel","delStart","delEnd","rangesToFormat","validRanges","getValidRanges","testOutput","testOutputToRanges","rangesToRemove","arrays","getCallbackFunctionForInlineAutoformat","_getValueFromFirstAllowedNode","checkAttributeInSelection","forceValue","BOLD","setAttributeProperties","isFormatting","fontWeight","bold","CODE","STRIKETHROUGH","strikethrough","ITALIC","italic","iterable","iteratorItem","_getValue","_checkEnabled","blocks","blocksToQuote","findQuote","checkCanBeQuoted","_applyQuote","_removeQuote","getRangesOfBlockGroups","groupRange","positionBefore","quotesToMerge","quote","currentQuote","nextQuote","elementOrPosition","nextBlock","isBQAllowed","isBlockAllowedInBQ","checkCanBecomeParagraph","rename","paragraphLikeElements","isParagraphable","wrapInParagraph","_autoparagraphEmptyRoots","createContext","modelElements","heading","checkCanBecomeHeading","defaultModelElement","option","_addDefaultH1Conversion","enterCommand","localizedTitles","Paragraph","getLocalizedOptions","defaultTitle","dropdownTooltip","titles","itemDefinitions","headingCommand","paragraphCommand","commandValue","isOn","areEnabled","para","whichModel","_observedElements","_updateObservedElements","_fireEvents","modelToViewAttributeConverter","img","createImageViewElement","altText","toImageWidget","srcset","srcsetAttributeConverter","viewImage","conversionResult","viewFigureToModel","emptyElement","figure","InputView","inputUid","statusUid","inputView","_createInputView","statusView","_createStatusView","errorText","infoText","ariaDescribedById","select","readonly","setValue","submitHandler","labeledInput","_createLabeledInputView","saveButtonView","_createButton","check","cancelButtonView","_focusables","v","_createForm","_form","_showForm","_hideForm","_isInBalloon","focusEditable","getCaptionFromImage","imageModelElement","matchImageCaption","_insertMissingModelCaptionElement","captionModelToView","createCaptionForEditing","createEditableElement","captionElementCreator","_fixCaptionVisibility","_updateCaptionVisibility","lastCaption","_lastSelectedCaption","viewCaption","modelCaption","getParentCaption","showCaption","hideCaptionIfEmpty","viewModified","nodeFinder","imagesWithoutCaption","nestedItem","appendElement","captionElement","insertViewCaptionAndBind","caption","defaultStyle","isDefault","attributeValue","getStyleByName","defaultStyles","full","alignLeft","alignCenter","alignRight","defaultIcons","center","normalizeImageStyles","configuredStyles","_normalizeStyle","extendedStyle","modelToViewConverter","newStyle","oldStyle","modelToViewStyleAttribute","filteredStyles","viewFigureElement","modelImageElement","viewToModelStyleAttribute","translatedStyles","translateStyles","localizedDefaultStylesTitles","componentName","balloonToolbar","_toolbarDefinitions","_updateToolbarsVisibility","toolbarId","ariaLabel","getRelatedElement","maxRelatedElementDepth","deepestRelatedElement","deepestToolbarDefinition","relatedElement","relatedElementDepth","_isToolbarInBalloon","_isToolbarVisible","_showToolbar","toolbarDefinition","findLinkRange","_findBound","lookBack","lastNode","manualDecorators","manualDecorator","_getDecoratorStateFromModel","manualDecoratorIds","truthyManualDecorators","falsyManualDecorators","linkRange","decoratorName","linkCommand","rangesToUnlink","reHasUnicode","rsAstral","rsCombo","rsFitz","rsNonAstral","rsRegional","rsSurrPair","reOptMod","rsSeq","rsSymbol","reUnicode","INFINITY","symbolToString","baseToString","strSymbols","ATTRIBUTE_WHITESPACES","SAFE_URL","createLinkElement","linkElement","ensureSafeUrl","isSafeUrl","AutomaticDecorators","_definitions","ManualDecorator","TwoStepCaretHandler","_modelSelection","_overrideUid","_isNextGravityRestorationSkipped","_isGravityOverridden","isAtBoundary","_hasSelectionAttribute","isBetweenDifferentValues","_preventCaretMovement","isAtStartBoundary","isAtEndBoundary","_setSelectionAttributeFromTheNodeBefore","isStepAfterTheAttributeBoundary","_skipNextAutomaticGravityRestoration","overrideSelectionGravity","restoreSelectionGravity","isAttrBefore","isAttrAfter","HIGHLIGHT_CLASS","DECORATOR_AUTOMATIC","DECORATOR_MANUAL","EXTERNAL_LINKS_REGEXP","addTargetToExternalLinks","linkDecorators","decorators","localizedDecoratorsLabels","decorator","getLocalizedDecorators","retArray","normalizeDecorators","_enableAutomaticDecorators","_enableManualDecorators","twoStepCaretHandler","arrowRightPressed","arrowLeftPressed","contentDirection","isMovementHandled","handleForwardMovement","handleBackwardMovement","bindTwoStepCaretToAttribute","_setupLinkHighlight","automaticDecoratorDefinitions","automaticDecorators","rel","getDispatcher","manualDecoratorDefinitions","manualDecoratorName","highlightedLinks","urlInputView","_createUrlInput","_manualDecoratorSwitches","_createManualDecoratorSwitches","_createFormChildren","classList","accumulator","switchButton","switches","additionalButtonsView","previewButtonView","_createPreviewButton","unlinkButtonView","unlink","editButtonView","pencil","linkKeystroke","actionsView","_createActionsView","formView","_createFormView","_createToolbarLinkButton","_enableUserBalloonInteractions","unlinkCommand","_addFormView","_hideUI","getDecoratorSwitchesState","_closeFormView","_showUI","_getSelectedLinkElement","_areActionsVisible","_isUIVisible","_isUIInPanel","_areActionsInPanel","_getBalloonPositionData","_isFormInPanel","restoreManualDecoratorStates","_removeFormView","forceVisible","_addActionsView","_startUpdatingUI","prevSelectedLink","prevSelectionParent","getSelectionParent","selectedLink","targetLink","findLinkElementAncestor","startLink","endLink","isLinkElement","checkCanBecomeListItem","turnOff","currentIndent","newIndent","lowestIndent","_fixType","listType","listItem","startingItem","indentDirection","_indentBy","itemsToChange","lastItem","generateLiInUl","getListItemFillerOffset","createViewListItemElement","viewList","injectViewList","injectedItem","injectedList","refItem","getSiblingListItem","sameIndent","smallerIndent","prevItem","breakContainer","positionAfterUiElements","prevView","breakPosition","mergeViewLists","nextViewList","lastSubChild","modelChild","firstList","secondList","mergeContainers","itemIndent","createUIComponent","hasOnlyLists","modelViewInsertion","modelViewChangeType","listName","modelViewMergeAfterChangeType","modelViewSplitOnInsert","removeStart","removeEnd","previousList","mergePos","modelViewMergeAfter","viewItemPrev","viewItemNext","viewModelConverter","getIndent","listItemModel","convertedChild","findNextListItem","viewToModelListItemChildrenConverter","cleanList","isList","cleanListItem","foundList","firstNode","modelToViewPosition","topmostViewList","modelIndentPasteFixer","indentChange","hoistNestedLists","nextIndent","modelRemoveStartPosition","viewRemoveStartPosition","viewRemovedItem","prevModelItem","foo","prevIndent","prevViewList","itemToListHead","applied","_addListToFix","innerItem","listHead","_fixListIndents","_fixListTypes","maxIndent","fixBy","typesStack","modelChangePostFixer","registerViewToModelLength","getViewListItemLength","modelNode","modelLength","viewListPrev","modelViewChangeIndent","modelViewRemove","firstPosition","getCommandExecuter","outdent","registerChildCommand","codeBlockSymbol","isCodeBlockWidget","isCodeBlockWidgetSelected","createCodeBlockWidget","renderCodeBlockContent","toCodeBlockWidget","langElement","setTextNode","empty_text","codeBlock","modelCodeBlock","viewCodeBlockToModel","codeBlockContentToView","preElement","codeElement","langContent","contentElement","modelCodeBlockToView","editCodeBlock","languageClass","getToolbarItems","__currentlyDisabled","disableItems","except","jQuery","each","toDisable","enableItems","toEnable","parentName","updateNumericAttribute","defaultValue","createEmptyTableCell","tableCell","upcastTable","viewTable","rows","headingRows","headingColumns","tableMeta","headRows","bodyRows","firstTheadElement","tableChild","trs","tr","headingCols","scanRowForHeadingColumns","scanTable","table","row","upcastTableCell","viewTableCell","th","TableWalker","startRow","endRow","includeSpanned","column","_skipRows","_row","_column","_cellIndex","_spannedCells","_nextCellAtColumn","_isOverEndRow","cell","skipCurrentValue","outValue","_isSpanned","_getSpanned","_shouldSkipRow","_shouldSkipColumn","_formatOutValue","colspan","rowspan","_recordSpans","isSpanned","cellIndex","rowIsBelowStartRow","rowIsMarkedAsSkipped","columnToUpdate","_markSpannedCell","rowToUpdate","isTableWidget","getSelectedTableWidget","getTableWidgetAncestor","parentTable","downcastInsertTable","asWidget","figureElement","tableElement","tableWidget","toTableWidget","tableWalker","tableAttributes","viewRows","tableWalkerValue","tableSection","getOrCreateTableSection","getSectionName","tableRow","trElement","createTr","createViewTableCellElement","downcastInsertRow","getViewTable","downcastInsertCell","rowIndex","downcastTableHeadingRowsChange","oldRows","newRows","rowsToMove","isBetween","moveViewRowsToTableSection","renameViewTableCell","removeTableSectionIfEmpty","renameViewTableCellIfRequired","lower","upper","downcastTableHeadingColumnsChange","oldColumns","newColumns","lastColumnToCheck","desiredCellElementName","viewCell","renamedCell","getCellElementName","cellElementName","cellElement","isSingleParagraph","innerParagraph","paragraphInsertPosition","fakeParagraph","sectionName","viewTableSection","getExistingTableSectionElement","tableChildElement","createTableSection","viewTableRow","validParent","getInsertTableParent","tableUtils","createTable","order","tableParent","insertAt","insertRows","getCellLocation","insertColumns","isHorizontally","splitCellHorizontally","splitCellVertically","isHorizontal","cellToMerge","_getMergeableCell","isMergeNext","cellToExpand","cellToRemove","removedTableCellRow","mergeTableCells","spanAttribute","cellSpan","cellToMergeSpan","removedRowIndex","removeEmptyRow","horizontalCell","cellOnLeft","cellOnRight","leftCellColumn","rightCellColumn","leftCellSpan","getHorizontalCell","isMergeWithBodyCell","isMergeWithHeadCell","currentCellRowSpan","rowOfCellToMerge","tableMap","mergeColumn","cellToMergeData","getVerticalCell","span","currentRow","cellsToMove","rowspanToSet","targetRow","previousCell","cellToMove","getColumns","removedColumn","isInTable","_isInHeading","currentHeadingRows","selectionRow","headingRowsToSet","cellsToSplit","getOverlappingCells","splitHorizontally","newRowspan","spanToSet","columnIndex","tableCellPosition","selectionColumn","headingColumnsToSet","createEmptyRows","rowsToInsert","tableIterator","cellsToInsert","overlapsInsertedRow","columnsToInsert","tableColumns","createCells","skipRow","numberOfCells","newCellsSpan","updatedSpan","breakSpanEvenly","newCellsAttributes","splitCellColumn","cellsToUpdate","splitCellRow","cellColumn","isOnSameColumn","isInEvenlySplitRow","tableCellToInsert","cells","injectTableLayoutPostFixer","analyzedTables","isTableAttributeEntry","fixTableCellsRowspan","fixTableRowsSizes","tableLayoutPostFixer","cellsToTrim","maxRows","rowLimit","findCellsToTrim","rowsLengths","lengths","getRowsLengths","tableSize","maxColumns","isAttributeType","injectTableCellParagraphPostFixer","fixTable","fixTableRow","fixTableCellContent","checkTableCellChange","tableCellContentsPostFixer","textNodes","injectTableCellRefreshPostFixer","cellsToRefresh","checkRefresh","refreshItem","tableCellRefreshPostFixer","attributesCount","_handleTabOnSelectedTable","_getTabHandler","currentRowIndex","currentCellIndex","isFirstCellInRow","isLastCellInRow","isLastRow","cellToFocus","nextRow","previousRow","boxView","_highlightGridBoxes","mouseover","isContentLtr","insertTableView","bindIsOn","_prepareDropdown","addListOption","transformListItemLikeElementsIntoLists","itemLikeElements","itemLikeElementsMatcher","itemData","getListItemData","findAllItemLikeElements","currentList","itemLikeElement","previousItem","currentItem","isNewListNeeded","listStyle","listLikeItem","listStyleRegexp","listStyleTypeRegex","listStyleMatch","listStyleType","listStyleTypeMatch","detectListStyle","insertNewEmptyList","bulletMatcher","removeBulletElement","transformElementIntoListItem","googleDocsMatch","htmlString","removeBoldWrapper","unwrapParagraphInListItem","normalizeSafariSpaceSpans","parseHtml","domParser","normalizedHtml","normalizeSpacing","cleanContentAfterBody","htmlDocument","innerTextLength","normalizeSpacerunSpans","bodyString","bodyView","documentToView","stylesObject","styleTags","getElementsByTagName","sheet","cssRules","extractStyles","replaceImagesSourceWithBase64","rtfData","upcastWriter","shapesIds","imageElementsMatcher","imgs","shapes","shape","removeAllImgElementsRepresentingShapes","shapeElementsMatcher","prevSiblingName","findAllShapesIds","removeAllShapeElements","findAllImageElementsWithLocalSource","imageElements","imagesHexSources","newSrc","hexString","hex","replaceImagesFileSourceWithInlineRepresentation","regexPictureHeader","regexPicture","imageType","extractImageDataFromRtf","msWordMatch1","msWordMatch2","_selectedElements","_getSelectedItems","dataModelViewTextInsertion","dataViewModelCheckmarkInsertion","createCheckmarkElement","isChecked","onChange","contenteditable","xmlns","findLabel","onCheckedChange","addAttributeCheck","onCheckboxChecked","checkmarkElement","_handleCheckmarkChange","disabled","dataModelViewInsertion","oldCheckmarkElement","newCheckmarkElement","modelViewChangeChecked","mapModelToViewZeroOffsetPosition","localizedJumpOverCheckmarkKey","stopKeyEvent","jumpOverCheckmarkOnSideArrowKeyPress","listItemsToFix","previousSelectionRanges","highlightRegExp","highlightedCodeBlock","turndownService","addRule","nodeName","isHeadingRow","borderCells","alignMap","border","align","voidElements","isVoid","voidSelector","Rules","_keep","blankRule","blankReplacement","keepReplacement","defaultRule","defaultReplacement","findRule","filterValue","isPre","lineBreak","br","hLevel","headingStyle","blockquote","lastElementChild","bulletListMarker","indentedCodeBlock","codeBlockStyle","fencedCodeBlock","horizontalRule","hr","inlineLink","linkStyle","referenceLink","reference","linkReferenceStyle","emphasis","emDelimiter","strong","strongDelimiter","hasSiblings","isCodeBlock","leadingSpace","trailingSpace","keep","forNode","isBlank","Parser","JSDOM","_htmlParser","HTMLParser","canParse","canParseHTMLNatively","RootNode","getElementById","cloneNode","prevText","prevVoid","collapseWhitespace","isCode","hasVoid","flankingWhitespace","hasLeading","hasTrailing","isFlankedByWhitespace","sibling","isFlanked","nodeValue","leadingNewLinesRegExp","trailingNewLinesRegExp","TurndownService","defaults","outerHTML","destination","escape","replacementForNode","whitespace","string1","string2","newlines","maxNewlines","separator","turndown","canConvert","hasParentOfType","tagNames","originalSrcAttribute","_htmlDP","taskLists","createNodeIterator","removeParagraphsInLists","allowed_whitespace_nodes","allowed_raw_nodes","textNodesPreprocessor","FILTER_REJECT","linkPreprocessor","closest","checked","_content","mentionData","mention","mentionID","mentionText","_addMentionAttributes","_text","currentAttributes","attributesWithMention","_toMentionAttribute","createViewMentionElement","preventPartialMentionDowncast","wasChanged","nodeAfterInsertedTextNode","checkAndFix","insertedNode","nodeAfterInserted","removePartialMentionPostFixer","isBrokenMentionNode","extendAttributeOnMentionPostFixer","shouldNotTypeWithMentionAt","selectionMentionAttributePostFixer","baseMentionData","_uid","viewElementOrMention","dataMention","hasMatch","_startListening","_evaluateTextBeforeSelection","suffix","rangeBeforeSelection","textHasMatch","eventData","selected","indexToGet","_isItemVisibleInScrolledArea","offsetTop","VERTICAL_SPACING","_mentionsView","_createMentionView","_mentionsConfigurations","feeds","isHandledKey","selectNext","selectPrevious","executeSelected","_hideUIAndRemoveMarker","mentionDescription","feed","minimumCharacters","feedCallback","createFeedCallback","watcher","_setupTextWatcherForFeed","itemRenderer","mentionsView","_renderItem","mentionMarker","getStart","feedText","createRegExp","createTestCallback","hasMention","getFeedText","matchedTextLength","_getFeed","feedItem","markerMarker","_getBalloonPanelPositionData","selectFirst","removeMarker","_getItemRenderer","renderResult","preferredPosition","getBalloonPanelPositions","caret_se","caret_sw","caret_ne","caret_nw","numberOfCharacters","openAfterCharacters","mentionCharacters","feedItems","filteredItems","opMacroPlugins","opImageUploadPlugins","urls","removeDeletedImage","_addListAutoformats","_addBasicStylesAutoformats","_addHeadingAutoformats","_addBlockQuoteAutoformats","boldCallback","italicCallback","codeCallback","lookupDownloadLocationByName","replaceImageAttachmentsByName","replaceNamedAttachmentWithUrl","toMentionAttribute","userId","normalizers","isTransformedWithPasteFromOffice","activeNormalizer","normalizer","isActive","helpURL","previewing","unregisterPreview","showPreview","preview","$reference","$mainEditor","getEditableElement","$editable","$previewWrapper","siblings","previewService","getAndShowPreview","getOPPreviewContext","api","v3","previewMarkup","ajax","response_type","contentType","disablePreviewing","inSourceMode","labels","wysiwyg","hideSource","$sourceWrapper","showSource","widgetToolbarRepository","tableContentToolbarItems","tableToolbarItems","disabledPluginNames","dropdownItems","macroPlugin","isVertical","customItemRenderer","itemElement","OPMacroEmbeddedTable","OPMacroWpButton","OPWikiIncludePage","OPCodeBlock","OPChildPages","contentToolbar","queryText","_type","project_id","project","idFromLink","principals","OpenProject","urlRoot","getJSON","_embedded","user","displayText","scope","wp","to_s","configurationCustomizer","editorClass","openProject","canAddAttachments","disableAllMacros","disabledMacros","OPConstrainedEditor","OPClassicEditor","createCustomized"],"mappings":"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","file":"ckeditor.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"OPEditor\"] = factory();\n\telse\n\t\troot[\"OPEditor\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 159);\n","/**\n * @license Copyright (c) 2003-2019, 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/ckeditorerror\n */\n\n/**\n * URL to the documentation with error codes.\n */\nexport const DOCUMENTATION_URL =\n\t'https://ckeditor.com/docs/ckeditor5/latest/framework/guides/support/error-codes.html';\n\n/**\n * The CKEditor error class.\n *\n * You should throw `CKEditorError` when:\n *\n * * An unexpected situation occurred and the editor (most probably) will not work properly. Such exception will be handled\n * by the {@link module:watchdog/watchdog~Watchdog watchdog} (if it is integrated),\n * * If the editor is incorrectly integrated or the editor API is used in the wrong way. This way you will give\n * feedback to the developer as soon as possible. Keep in mind that for common integration issues which should not\n * stop editor initialization (like missing upload adapter, wrong name of a toolbar component) we use `console.warn()` with\n * {@link module:utils/ckeditorerror~attachLinkToDocumentation `attachLinkToDocumentation()`}\n * to improve developers experience and let them see the working editor as soon as possible.\n *\n *\t\t/**\n *\t\t * Error thrown when a plugin cannot be loaded due to JavaScript errors, lack of plugins with a given name, etc.\n *\t\t *\n *\t\t * @error plugin-load\n *\t\t * @param pluginName The name of the plugin that could not be loaded.\n *\t\t * @param moduleName The name of the module which tried to load this plugin.\n *\t\t * /\n *\t\tthrow new CKEditorError( 'plugin-load: It was not possible to load the \"{$pluginName}\" plugin in module \"{$moduleName}', {\n *\t\t\tpluginName: 'foo',\n *\t\t\tmoduleName: 'bar'\n *\t\t} );\n *\n * @extends Error\n */\nexport default class CKEditorError extends Error {\n\t/**\n\t * Creates an instance of the CKEditorError class.\n\t *\n\t * @param {String} message The error message in an `error-name: Error message.` format.\n\t * During the minification process the \"Error message\" part will be removed to limit the code size\n\t * and a link to this error documentation will be added to the `message`.\n\t * @param {Object|null} context A context of the error by which the {@link module:watchdog/watchdog~Watchdog watchdog}\n\t * is able to determine which editor crashed. It should be an editor instance or a property connected to it. It can be also\n\t * a `null` value if the editor should not be restarted in case of the error (e.g. during the editor initialization).\n\t * The error context should be checked using the `areConnectedThroughProperties( editor, context )` utility\n\t * to check if the object works as the context.\n\t * @param {Object} [data] Additional data describing the error. A stringified version of this object\n\t * will be appended to the error message, so the data are quickly visible in the console. The original\n\t * data object will also be later available under the {@link #data} property.\n\t */\n\tconstructor( message, context, data ) {\n\t\tmessage = attachLinkToDocumentation( message );\n\n\t\tif ( data ) {\n\t\t\tmessage += ' ' + JSON.stringify( data );\n\t\t}\n\n\t\tsuper( message );\n\n\t\t/**\n\t\t * @type {String}\n\t\t */\n\t\tthis.name = 'CKEditorError';\n\n\t\t/**\n\t\t * A context of the error by which the Watchdog is able to determine which editor crashed.\n\t\t *\n\t\t * @type {Object|null}\n\t\t */\n\t\tthis.context = context;\n\n\t\t/**\n\t\t * The additional error data passed to the constructor. Undefined if none was passed.\n\t\t *\n\t\t * @type {Object|undefined}\n\t\t */\n\t\tthis.data = data;\n\t}\n\n\t/**\n\t * Checks if the error is of the `CKEditorError` type.\n\t */\n\tis( type ) {\n\t\treturn type === 'CKEditorError';\n\t}\n\n\t/**\n\t * A utility that ensures the the thrown error is a {@link module:utils/ckeditorerror~CKEditorError} one.\n\t * It is uesful when combined with the {@link module:watchdog/watchdog~Watchdog} feature, which can restart the editor in case\n\t * of a {@link module:utils/ckeditorerror~CKEditorError} error.\n\t *\n\t * @param {Error} err An error.\n\t * @param {Object} context An object conected through properties with the editor instance. This context will be used\n\t * by the watchdog to verify which editor should be restarted.\n\t */\n\tstatic rethrowUnexpectedError( err, context ) {\n\t\tif ( err.is && err.is( 'CKEditorError' ) ) {\n\t\t\tthrow err;\n\t\t}\n\n\t\t/**\n\t\t * An unexpected error occurred inside the CKEditor 5 codebase. The `error.data.originalError` property\n\t\t * shows the original error properties.\n\t\t *\n\t\t * This error is only useful when the editor is initialized using the {@link module:watchdog/watchdog~Watchdog} feature.\n\t\t * In case of such error (or any {@link module:utils/ckeditorerror~CKEditorError} error) the wathcdog should restart the editor.\n\t\t *\n\t\t * @error unexpected-error\n\t\t */\n\t\tthrow new CKEditorError( 'unexpected-error', context, {\n\t\t\toriginalError: {\n\t\t\t\tmessage: err.message,\n\t\t\t\tstack: err.stack,\n\t\t\t\tname: err.name\n\t\t\t}\n\t\t} );\n\t}\n}\n\n/**\n * Attaches the link to the documentation at the end of the error message. Use whenever you log a warning or error on the\n * console. It is also used by {@link module:utils/ckeditorerror~CKEditorError}.\n *\n *\t\t /**\n *\t\t * There was a problem processing the configuration of the toolbar. The item with the given\n *\t\t * name does not exist so it was omitted when rendering the toolbar.\n *\t\t *\n *\t\t * @error toolbarview-item-unavailable\n *\t\t * @param {String} name The name of the component.\n *\t\t * /\n *\t\t console.warn( attachLinkToDocumentation(\n *\t\t \t'toolbarview-item-unavailable: The requested toolbar item is unavailable.' ), { name } );\n *\n * @param {String} message Message to be logged.\n * @returns {String}\n */\nexport function attachLinkToDocumentation( message ) {\n\tconst matchedErrorName = message.match( /^([^:]+):/ );\n\n\tif ( !matchedErrorName ) {\n\t\treturn message;\n\t}\n\n\treturn message + ` Read more: ${ DOCUMENTATION_URL }#error-${ matchedErrorName[ 1 ] }\\n`;\n}\n","\"use strict\";\n\nvar stylesInDom = {};\n\nvar isOldIE = function isOldIE() {\n var memo;\n return function memorize() {\n if (typeof memo === 'undefined') {\n // Test for IE <= 9 as proposed by Browserhacks\n // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805\n // Tests for existence of standard globals is to allow style-loader\n // to operate correctly into non-standard environments\n // @see https://github.com/webpack-contrib/style-loader/issues/177\n memo = Boolean(window && document && document.all && !window.atob);\n }\n\n return memo;\n };\n}();\n\nvar getTarget = function getTarget() {\n var memo = {};\n return function memorize(target) {\n if (typeof memo[target] === 'undefined') {\n var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself\n\n if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n try {\n // This will throw an exception if access to iframe is blocked\n // due to cross-origin restrictions\n styleTarget = styleTarget.contentDocument.head;\n } catch (e) {\n // istanbul ignore next\n styleTarget = null;\n }\n }\n\n memo[target] = styleTarget;\n }\n\n return memo[target];\n };\n}();\n\nfunction listToStyles(list, options) {\n var styles = [];\n var newStyles = {};\n\n for (var i = 0; i < list.length; i++) {\n var item = list[i];\n var id = options.base ? item[0] + options.base : item[0];\n var css = item[1];\n var media = item[2];\n var sourceMap = item[3];\n var part = {\n css: css,\n media: media,\n sourceMap: sourceMap\n };\n\n if (!newStyles[id]) {\n styles.push(newStyles[id] = {\n id: id,\n parts: [part]\n });\n } else {\n newStyles[id].parts.push(part);\n }\n }\n\n return styles;\n}\n\nfunction addStylesToDom(styles, options) {\n for (var i = 0; i < styles.length; i++) {\n var item = styles[i];\n var domStyle = stylesInDom[item.id];\n var j = 0;\n\n if (domStyle) {\n domStyle.refs++;\n\n for (; j < domStyle.parts.length; j++) {\n domStyle.parts[j](item.parts[j]);\n }\n\n for (; j < item.parts.length; j++) {\n domStyle.parts.push(addStyle(item.parts[j], options));\n }\n } else {\n var parts = [];\n\n for (; j < item.parts.length; j++) {\n parts.push(addStyle(item.parts[j], options));\n }\n\n stylesInDom[item.id] = {\n id: item.id,\n refs: 1,\n parts: parts\n };\n }\n }\n}\n\nfunction insertStyleElement(options) {\n var style = document.createElement('style');\n\n if (typeof options.attributes.nonce === 'undefined') {\n var nonce = typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null;\n\n if (nonce) {\n options.attributes.nonce = nonce;\n }\n }\n\n Object.keys(options.attributes).forEach(function (key) {\n style.setAttribute(key, options.attributes[key]);\n });\n\n if (typeof options.insert === 'function') {\n options.insert(style);\n } else {\n var target = getTarget(options.insert || 'head');\n\n if (!target) {\n throw new Error(\"Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.\");\n }\n\n target.appendChild(style);\n }\n\n return style;\n}\n\nfunction removeStyleElement(style) {\n // istanbul ignore if\n if (style.parentNode === null) {\n return false;\n }\n\n style.parentNode.removeChild(style);\n}\n/* istanbul ignore next */\n\n\nvar replaceText = function replaceText() {\n var textStore = [];\n return function replace(index, replacement) {\n textStore[index] = replacement;\n return textStore.filter(Boolean).join('\\n');\n };\n}();\n\nfunction applyToSingletonTag(style, index, remove, obj) {\n var css = remove ? '' : obj.css; // For old IE\n\n /* istanbul ignore if */\n\n if (style.styleSheet) {\n style.styleSheet.cssText = replaceText(index, css);\n } else {\n var cssNode = document.createTextNode(css);\n var childNodes = style.childNodes;\n\n if (childNodes[index]) {\n style.removeChild(childNodes[index]);\n }\n\n if (childNodes.length) {\n style.insertBefore(cssNode, childNodes[index]);\n } else {\n style.appendChild(cssNode);\n }\n }\n}\n\nfunction applyToTag(style, options, obj) {\n var css = obj.css;\n var media = obj.media;\n var sourceMap = obj.sourceMap;\n\n if (media) {\n style.setAttribute('media', media);\n }\n\n if (sourceMap && btoa) {\n css += \"\\n/*# sourceMappingURL=data:application/json;base64,\".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), \" */\");\n } // For old IE\n\n /* istanbul ignore if */\n\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n while (style.firstChild) {\n style.removeChild(style.firstChild);\n }\n\n style.appendChild(document.createTextNode(css));\n }\n}\n\nvar singleton = null;\nvar singletonCounter = 0;\n\nfunction addStyle(obj, options) {\n var style;\n var update;\n var remove;\n\n if (options.singleton) {\n var styleIndex = singletonCounter++;\n style = singleton || (singleton = insertStyleElement(options));\n update = applyToSingletonTag.bind(null, style, styleIndex, false);\n remove = applyToSingletonTag.bind(null, style, styleIndex, true);\n } else {\n style = insertStyleElement(options);\n update = applyToTag.bind(null, style, options);\n\n remove = function remove() {\n removeStyleElement(style);\n };\n }\n\n update(obj);\n return function updateStyle(newObj) {\n if (newObj) {\n if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) {\n return;\n }\n\n update(obj = newObj);\n } else {\n remove();\n }\n };\n}\n\nmodule.exports = function (list, options) {\n options = options || {};\n options.attributes = typeof options.attributes === 'object' ? options.attributes : {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of <style>\n // tags it will allow on a page\n\n if (!options.singleton && typeof options.singleton !== 'boolean') {\n options.singleton = isOldIE();\n }\n\n var styles = listToStyles(list, options);\n addStylesToDom(styles, options);\n return function update(newList) {\n var mayRemove = [];\n\n for (var i = 0; i < styles.length; i++) {\n var item = styles[i];\n var domStyle = stylesInDom[item.id];\n\n if (domStyle) {\n domStyle.refs--;\n mayRemove.push(domStyle);\n }\n }\n\n if (newList) {\n var newStyles = listToStyles(newList, options);\n addStylesToDom(newStyles, options);\n }\n\n for (var _i = 0; _i < mayRemove.length; _i++) {\n var _domStyle = mayRemove[_i];\n\n if (_domStyle.refs === 0) {\n for (var j = 0; j < _domStyle.parts.length; j++) {\n _domStyle.parts[j]();\n }\n\n delete stylesInDom[_domStyle.id];\n }\n }\n };\n};","// Utilities\n//\n'use strict';\n\n\nfunction _class(obj) { return Object.prototype.toString.call(obj); }\n\nfunction isString(obj) { return _class(obj) === '[object String]'; }\n\nvar _hasOwnProperty = Object.prototype.hasOwnProperty;\n\nfunction has(object, key) {\n return _hasOwnProperty.call(object, key);\n}\n\n// Merge objects\n//\nfunction assign(obj /*from1, from2, from3, ...*/) {\n var sources = Array.prototype.slice.call(arguments, 1);\n\n sources.forEach(function (source) {\n if (!source) { return; }\n\n if (typeof source !== 'object') {\n throw new TypeError(source + 'must be object');\n }\n\n Object.keys(source).forEach(function (key) {\n obj[key] = source[key];\n });\n });\n\n return obj;\n}\n\n// Remove element from array and put another array at those position.\n// Useful for some operations with tokens\nfunction arrayReplaceAt(src, pos, newElements) {\n return [].concat(src.slice(0, pos), newElements, src.slice(pos + 1));\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nfunction isValidEntityCode(c) {\n /*eslint no-bitwise:0*/\n // broken sequence\n if (c >= 0xD800 && c <= 0xDFFF) { return false; }\n // never used\n if (c >= 0xFDD0 && c <= 0xFDEF) { return false; }\n if ((c & 0xFFFF) === 0xFFFF || (c & 0xFFFF) === 0xFFFE) { return false; }\n // control codes\n if (c >= 0x00 && c <= 0x08) { return false; }\n if (c === 0x0B) { return false; }\n if (c >= 0x0E && c <= 0x1F) { return false; }\n if (c >= 0x7F && c <= 0x9F) { return false; }\n // out of range\n if (c > 0x10FFFF) { return false; }\n return true;\n}\n\nfunction fromCodePoint(c) {\n /*eslint no-bitwise:0*/\n if (c > 0xffff) {\n c -= 0x10000;\n var surrogate1 = 0xd800 + (c >> 10),\n surrogate2 = 0xdc00 + (c & 0x3ff);\n\n return String.fromCharCode(surrogate1, surrogate2);\n }\n return String.fromCharCode(c);\n}\n\n\nvar UNESCAPE_MD_RE = /\\\\([!\"#$%&'()*+,\\-.\\/:;<=>?@[\\\\\\]^_`{|}~])/g;\nvar ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;\nvar UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'gi');\n\nvar DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i;\n\nvar entities = require('./entities');\n\nfunction replaceEntityPattern(match, name) {\n var code = 0;\n\n if (has(entities, name)) {\n return entities[name];\n }\n\n if (name.charCodeAt(0) === 0x23/* # */ && DIGITAL_ENTITY_TEST_RE.test(name)) {\n code = name[1].toLowerCase() === 'x' ?\n parseInt(name.slice(2), 16) : parseInt(name.slice(1), 10);\n\n if (isValidEntityCode(code)) {\n return fromCodePoint(code);\n }\n }\n\n return match;\n}\n\n/*function replaceEntities(str) {\n if (str.indexOf('&') < 0) { return str; }\n\n return str.replace(ENTITY_RE, replaceEntityPattern);\n}*/\n\nfunction unescapeMd(str) {\n if (str.indexOf('\\\\') < 0) { return str; }\n return str.replace(UNESCAPE_MD_RE, '$1');\n}\n\nfunction unescapeAll(str) {\n if (str.indexOf('\\\\') < 0 && str.indexOf('&') < 0) { return str; }\n\n return str.replace(UNESCAPE_ALL_RE, function (match, escaped, entity) {\n if (escaped) { return escaped; }\n return replaceEntityPattern(match, entity);\n });\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nvar HTML_ESCAPE_TEST_RE = /[&<>\"]/;\nvar HTML_ESCAPE_REPLACE_RE = /[&<>\"]/g;\nvar HTML_REPLACEMENTS = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;'\n};\n\nfunction replaceUnsafeChar(ch) {\n return HTML_REPLACEMENTS[ch];\n}\n\nfunction escapeHtml(str) {\n if (HTML_ESCAPE_TEST_RE.test(str)) {\n return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar);\n }\n return str;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nvar REGEXP_ESCAPE_RE = /[.?*+^$[\\]\\\\(){}|-]/g;\n\nfunction escapeRE(str) {\n return str.replace(REGEXP_ESCAPE_RE, '\\\\$&');\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\nfunction isSpace(code) {\n switch (code) {\n case 0x09:\n case 0x20:\n return true;\n }\n return false;\n}\n\n// Zs (unicode class) || [\\t\\f\\v\\r\\n]\nfunction isWhiteSpace(code) {\n if (code >= 0x2000 && code <= 0x200A) { return true; }\n switch (code) {\n case 0x09: // \\t\n case 0x0A: // \\n\n case 0x0B: // \\v\n case 0x0C: // \\f\n case 0x0D: // \\r\n case 0x20:\n case 0xA0:\n case 0x1680:\n case 0x202F:\n case 0x205F:\n case 0x3000:\n return true;\n }\n return false;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\n/*eslint-disable max-len*/\nvar UNICODE_PUNCT_RE = require('uc.micro/categories/P/regex');\n\n// Currently without astral characters support.\nfunction isPunctChar(ch) {\n return UNICODE_PUNCT_RE.test(ch);\n}\n\n\n// Markdown ASCII punctuation characters.\n//\n// !, \", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \\, ], ^, _, `, {, |, }, or ~\n// http://spec.commonmark.org/0.15/#ascii-punctuation-character\n//\n// Don't confuse with unicode punctuation !!! It lacks some chars in ascii range.\n//\nfunction isMdAsciiPunct(ch) {\n switch (ch) {\n case 0x21/* ! */:\n case 0x22/* \" */:\n case 0x23/* # */:\n case 0x24/* $ */:\n case 0x25/* % */:\n case 0x26/* & */:\n case 0x27/* ' */:\n case 0x28/* ( */:\n case 0x29/* ) */:\n case 0x2A/* * */:\n case 0x2B/* + */:\n case 0x2C/* , */:\n case 0x2D/* - */:\n case 0x2E/* . */:\n case 0x2F/* / */:\n case 0x3A/* : */:\n case 0x3B/* ; */:\n case 0x3C/* < */:\n case 0x3D/* = */:\n case 0x3E/* > */:\n case 0x3F/* ? */:\n case 0x40/* @ */:\n case 0x5B/* [ */:\n case 0x5C/* \\ */:\n case 0x5D/* ] */:\n case 0x5E/* ^ */:\n case 0x5F/* _ */:\n case 0x60/* ` */:\n case 0x7B/* { */:\n case 0x7C/* | */:\n case 0x7D/* } */:\n case 0x7E/* ~ */:\n return true;\n default:\n return false;\n }\n}\n\n// Hepler to unify [reference labels].\n//\nfunction normalizeReference(str) {\n // Trim and collapse whitespace\n //\n str = str.trim().replace(/\\s+/g, ' ');\n\n // In node v10 'ẞ'.toLowerCase() === 'Ṿ', which is presumed to be a bug\n // fixed in v12 (couldn't find any details).\n //\n // So treat this one as a special case\n // (remove this when node v10 is no longer supported).\n //\n if ('ẞ'.toLowerCase() === 'Ṿ') {\n str = str.replace(/ẞ/g, 'ß');\n }\n\n // .toLowerCase().toUpperCase() should get rid of all differences\n // between letter variants.\n //\n // Simple .toLowerCase() doesn't normalize 125 code points correctly,\n // and .toUpperCase doesn't normalize 6 of them (list of exceptions:\n // İ, ϴ, ẞ, Ω, K, Å - those are already uppercased, but have differently\n // uppercased versions).\n //\n // Here's an example showing how it happens. Lets take greek letter omega:\n // uppercase U+0398 (Θ), U+03f4 (ϴ) and lowercase U+03b8 (θ), U+03d1 (ϑ)\n //\n // Unicode entries:\n // 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8;\n // 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398\n // 03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398\n // 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8;\n //\n // Case-insensitive comparison should treat all of them as equivalent.\n //\n // But .toLowerCase() doesn't change ϑ (it's already lowercase),\n // and .toUpperCase() doesn't change ϴ (already uppercase).\n //\n // Applying first lower then upper case normalizes any character:\n // '\\u0398\\u03f4\\u03b8\\u03d1'.toLowerCase().toUpperCase() === '\\u0398\\u0398\\u0398\\u0398'\n //\n // Note: this is equivalent to unicode case folding; unicode normalization\n // is a different step that is not required here.\n //\n // Final result should be uppercased, because it's later stored in an object\n // (this avoid a conflict with Object.prototype members,\n // most notably, `__proto__`)\n //\n return str.toLowerCase().toUpperCase();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\n// Re-export libraries commonly used in both markdown-it and its plugins,\n// so plugins won't have to depend on them explicitly, which reduces their\n// bundled size (e.g. a browser build).\n//\nexports.lib = {};\nexports.lib.mdurl = require('mdurl');\nexports.lib.ucmicro = require('uc.micro');\n\nexports.assign = assign;\nexports.isString = isString;\nexports.has = has;\nexports.unescapeMd = unescapeMd;\nexports.unescapeAll = unescapeAll;\nexports.isValidEntityCode = isValidEntityCode;\nexports.fromCodePoint = fromCodePoint;\n// exports.replaceEntities = replaceEntities;\nexports.escapeHtml = escapeHtml;\nexports.arrayReplaceAt = arrayReplaceAt;\nexports.isSpace = isSpace;\nexports.isWhiteSpace = isWhiteSpace;\nexports.isMdAsciiPunct = isMdAsciiPunct;\nexports.isPunctChar = isPunctChar;\nexports.escapeRE = escapeRE;\nexports.normalizeReference = normalizeReference;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nexport default root;\n","import freeGlobal from './_freeGlobal.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n try {\n // Use `util.types` for Node.js 10+.\n var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n if (types) {\n return types;\n }\n\n // Legacy `process.binding('util')` for Node.js < 10.\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n}());\n\nexport default nodeUtil;\n","import root from './_root.js';\nimport stubFalse from './stubFalse.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nexport default isBuffer;\n","/**\n * @license Copyright (c) 2003-2019, 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/version\n */\n\n/* globals window, global */\n\nimport { version } from 'ckeditor5/package.json';\nimport CKEditorError from './ckeditorerror';\n\nconst windowOrGlobal = typeof window === 'object' ? window : global;\n\nif ( windowOrGlobal.CKEDITOR_VERSION ) {\n\t/**\n\t * This error is thrown when due to a mistake in how CKEditor 5 was installed or initialized, some\n\t * of its modules were duplicated (evaluated and executed twice). Module duplication leads to inevitable runtime\n\t * errors.\n\t *\n\t * There are many situations in which some modules can be loaded twice. In the worst case scenario,\n\t * you may need to check your project for each of these issues and fix them all.\n\t *\n\t * # Trying to add a plugin to an existing build\n\t *\n\t * If you import an existing CKEditor 5 build and a plugin like this:\n\t *\n\t *\t\timport ClassicEditor from '@ckeditor/ckeditor5-build-classic';\n\t *\t\timport Highlight from '@ckeditor/ckeditor5-highlight/src/highlight';\n\t *\n\t * Then your project loads some CKEditor 5 packages twice. How does it happen?\n\t *\n\t * The build package contains a file which is already compiled with webpack. This means\n\t * that it contains all the necessary code from e.g. `@ckeditor/ckeditor5-engine` and `@ckeditor/ckeditor5-utils`.\n\t *\n\t * However, the `Highlight` plugin imports some of the modules from these packages, too. If you ask webpack to\n\t * build such a project, you will end up with the modules being included (and run) twice &mdash; first, because they are\n\t * included inside the build package, and second, because they are required by the `Highlight` plugin.\n\t *\n\t * Therefore, **you must never add plugins to an existing build** unless your plugin has no dependencies.\n\t *\n\t * Adding plugins to a build is done by taking the source version of this build (so, before it was built with webpack)\n\t * and adding plugins there. In this situation, webpack will know that it only needs to load each plugin once.\n\t *\n\t * Read more in the {@glink builds/guides/integration/installing-plugins \"Installing plugins\"} guide.\n\t *\n\t * # Confused an editor build with an editor implementation\n\t *\n\t * This scenario is very similar to the previous one, but has a different origin.\n\t *\n\t * Let's assume that you wanted to use CKEditor 5 from source, as explained in the\n\t * {@glink builds/guides/integration/advanced-setup#scenario-2-building-from-source \"Building from source\"} section\n\t * or in the {@glink framework/guides/quick-start \"Quick start\"} guide of CKEditor 5 Framework.\n\t *\n\t * The correct way to do so is to import an editor and plugins and run them together like this:\n\t *\n\t *\t\timport ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';\n\t *\t\timport Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';\n\t *\t\timport Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';\n\t *\t\timport Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';\n\t *\t\timport Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';\n\t *\n\t *\t\tClassicEditor\n\t *\t\t\t.create( document.querySelector( '#editor' ), {\n\t *\t\t\t\tplugins: [ Essentials, Paragraph, Bold, Italic ],\n\t *\t\t\t\ttoolbar: [ 'bold', 'italic' ]\n\t *\t\t\t} )\n\t *\t\t\t.then( editor => {\n\t *\t\t\t\tconsole.log( 'Editor was initialized', editor );\n\t *\t\t\t} )\n\t *\t\t\t.catch( error => {\n\t *\t\t\t\tconsole.error( error.stack );\n\t *\t\t\t} );\n\t *\n\t * However, you might have mistakenly imported a build instead of the source `ClassicEditor`. In this case\n\t * your imports will look like this:\n\t *\n\t *\t\timport ClassicEditor from '@ckeditor/ckeditor5-build-classic';\n\t *\t\timport Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';\n\t *\t\timport Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';\n\t *\t\timport Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';\n\t *\t\timport Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';\n\t *\n\t * This creates the same situation as in the previous section because you use a build together with source plugins.\n\t *\n\t * Remember: `@ckeditor/ckeditor5-build-*` packages contain editor builds and `@ckeditor/ckeditor5-editor-*` contain source editors.\n\t *\n\t * # Loading two or more builds on one page\n\t *\n\t * If you use CKEditor 5 builds, you might have loaded two (or more) `ckeditor.js` files on one web page.\n\t * Check your web page for duplicated `<script>` elements or make sure your page builder/bundler includes CKEditor only once.\n\t *\n\t * If you want to use two different types of editors at once, see the\n\t * {@glink builds/guides/integration/advanced-setup#scenario-3-using-two-different-editors \"Using two different editors\"}\n\t * section.\n\t *\n\t * # Using outdated packages\n\t *\n\t * Building CKEditor 5 from source requires using multiple npm packages. These packages have their dependencies\n\t * to other packages. If you use the latest version of, for example, `@ckeditor/ckeditor5-editor-classic` with\n\t * an outdated version of `@ckeditor/ckeditor5-image`, npm or yarn will need to install two different versions of\n\t * `@ckeditor/ckeditor5-core` because `@ckeditor/ckeditor5-editor-classic` and `@ckeditor/ckeditor5-image` may require\n\t * different versions of the core package.\n\t *\n\t * The solution to this issue is to update all packages to their latest version. We recommend\n\t * using tools like [`node-check-updates`](https://www.npmjs.com/package/npm-check-updates) which simplify this process.\n\t *\n\t * # Conflicting version of dependencies\n\t *\n\t * This is a special case of the previous scenario. If you use CKEditor 5 with some third-party plugins,\n\t * it may happen that even if you use the latest versions of the official packages and the latest version of\n\t * these third-party packages, there will be a conflict between some of their dependencies.\n\t *\n\t * Such a problem can be resolved by either downgrading CKEditor 5 packages (which we do not recommend) or\n\t * asking the author of the third-party package to upgrade its depdendencies (or forking their project and doing this yourself).\n\t *\n\t * # Packages were duplicated in `node_modules`\n\t *\n\t * In some situations, especially when calling `npm install` multiple times, it may happen\n\t * that npm will not correctly \"deduplicate\" packages.\n\t *\n\t * Normally, npm deduplicates all packages so, for example, `@ckeditor/ckeditor5-core` is installed only once in `node_modules/`.\n\t * However, it is known to fail to do so from time to time.\n\t *\n\t * We recommend checking if any of the steps listed below help:\n\t *\n\t * * `rm -rf node_modules && npm install` to make sure you have a clean `node_modules/` directory. This step\n\t * is known to help in most cases.\n\t * * If you use `yarn.lock` or `package-lock.json`, remove it before `npm install`.\n\t * * Check whether all CKEditor 5 packages are up to date and reinstall them\n\t * if you changed anything (`rm -rf node_modules && npm install`).\n\t *\n\t * If all packages are correct and compatible with each other, the steps above are known to help. If not, you may\n\t * try to check with `npm ls` how many times packages like `@ckeditor/ckeditor5-core`, `@ckeditor/ckeditor5-engine` and\n\t *`@ckeditor/ckeditor5-utils` are installed. If more than once, verify which package causes that.\n\t *\n\t * @error ckeditor-duplicated-modules\n\t */\n\tthrow new CKEditorError(\n\t\t'ckeditor-duplicated-modules: Some CKEditor 5 modules are duplicated.',\n\t\tnull\n\t);\n} else {\n\twindowOrGlobal.CKEDITOR_VERSION = version;\n}\n","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nexport default freeGlobal;\n","var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n","module.exports = function(originalModule) {\n\tif (!originalModule.webpackPolyfill) {\n\t\tvar module = Object.create(originalModule);\n\t\t// module.parent = undefined by default\n\t\tif (!module.children) module.children = [];\n\t\tObject.defineProperty(module, \"loaded\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.l;\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(module, \"id\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.i;\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(module, \"exports\", {\n\t\t\tenumerable: true\n\t\t});\n\t\tmodule.webpackPolyfill = 1;\n\t}\n\treturn module;\n};\n","module.exports=/[!-#%-\\*,-\\/:;\\?@\\[-\\]_\\{\\}\\xA1\\xA7\\xAB\\xB6\\xB7\\xBB\\xBF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u09FD\\u0A76\\u0AF0\\u0C84\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2308-\\u230B\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E4E\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA8FC\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65]|\\uD800[\\uDD00-\\uDD02\\uDF9F\\uDFD0]|\\uD801\\uDD6F|\\uD802[\\uDC57\\uDD1F\\uDD3F\\uDE50-\\uDE58\\uDE7F\\uDEF0-\\uDEF6\\uDF39-\\uDF3F\\uDF99-\\uDF9C]|\\uD803[\\uDF55-\\uDF59]|\\uD804[\\uDC47-\\uDC4D\\uDCBB\\uDCBC\\uDCBE-\\uDCC1\\uDD40-\\uDD43\\uDD74\\uDD75\\uDDC5-\\uDDC8\\uDDCD\\uDDDB\\uDDDD-\\uDDDF\\uDE38-\\uDE3D\\uDEA9]|\\uD805[\\uDC4B-\\uDC4F\\uDC5B\\uDC5D\\uDCC6\\uDDC1-\\uDDD7\\uDE41-\\uDE43\\uDE60-\\uDE6C\\uDF3C-\\uDF3E]|\\uD806[\\uDC3B\\uDE3F-\\uDE46\\uDE9A-\\uDE9C\\uDE9E-\\uDEA2]|\\uD807[\\uDC41-\\uDC45\\uDC70\\uDC71\\uDEF7\\uDEF8]|\\uD809[\\uDC70-\\uDC74]|\\uD81A[\\uDE6E\\uDE6F\\uDEF5\\uDF37-\\uDF3B\\uDF44]|\\uD81B[\\uDE97-\\uDE9A]|\\uD82F\\uDC9F|\\uD836[\\uDE87-\\uDE8B]|\\uD83A[\\uDD5E\\uDD5F]/","/**\n * class Ruler\n *\n * Helper class, used by [[MarkdownIt#core]], [[MarkdownIt#block]] and\n * [[MarkdownIt#inline]] to manage sequences of functions (rules):\n *\n * - keep rules in defined order\n * - assign the name to each rule\n * - enable/disable rules\n * - add/replace rules\n * - allow assign rules to additional named chains (in the same)\n * - cacheing lists of active rules\n *\n * You will not need use this class directly until write plugins. For simple\n * rules control use [[MarkdownIt.disable]], [[MarkdownIt.enable]] and\n * [[MarkdownIt.use]].\n **/\n'use strict';\n\n\n/**\n * new Ruler()\n **/\nfunction Ruler() {\n // List of added rules. Each element is:\n //\n // {\n // name: XXX,\n // enabled: Boolean,\n // fn: Function(),\n // alt: [ name2, name3 ]\n // }\n //\n this.__rules__ = [];\n\n // Cached rule chains.\n //\n // First level - chain name, '' for default.\n // Second level - diginal anchor for fast filtering by charcodes.\n //\n this.__cache__ = null;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Helper methods, should not be used directly\n\n\n// Find rule index by name\n//\nRuler.prototype.__find__ = function (name) {\n for (var i = 0; i < this.__rules__.length; i++) {\n if (this.__rules__[i].name === name) {\n return i;\n }\n }\n return -1;\n};\n\n\n// Build rules lookup cache\n//\nRuler.prototype.__compile__ = function () {\n var self = this;\n var chains = [ '' ];\n\n // collect unique names\n self.__rules__.forEach(function (rule) {\n if (!rule.enabled) { return; }\n\n rule.alt.forEach(function (altName) {\n if (chains.indexOf(altName) < 0) {\n chains.push(altName);\n }\n });\n });\n\n self.__cache__ = {};\n\n chains.forEach(function (chain) {\n self.__cache__[chain] = [];\n self.__rules__.forEach(function (rule) {\n if (!rule.enabled) { return; }\n\n if (chain && rule.alt.indexOf(chain) < 0) { return; }\n\n self.__cache__[chain].push(rule.fn);\n });\n });\n};\n\n\n/**\n * Ruler.at(name, fn [, options])\n * - name (String): rule name to replace.\n * - fn (Function): new rule function.\n * - options (Object): new rule options (not mandatory).\n *\n * Replace rule by name with new function & options. Throws error if name not\n * found.\n *\n * ##### Options:\n *\n * - __alt__ - array with names of \"alternate\" chains.\n *\n * ##### Example\n *\n * Replace existing typographer replacement rule with new one:\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.core.ruler.at('replacements', function replace(state) {\n * //...\n * });\n * ```\n **/\nRuler.prototype.at = function (name, fn, options) {\n var index = this.__find__(name);\n var opt = options || {};\n\n if (index === -1) { throw new Error('Parser rule not found: ' + name); }\n\n this.__rules__[index].fn = fn;\n this.__rules__[index].alt = opt.alt || [];\n this.__cache__ = null;\n};\n\n\n/**\n * Ruler.before(beforeName, ruleName, fn [, options])\n * - beforeName (String): new rule will be added before this one.\n * - ruleName (String): name of added rule.\n * - fn (Function): rule function.\n * - options (Object): rule options (not mandatory).\n *\n * Add new rule to chain before one with given name. See also\n * [[Ruler.after]], [[Ruler.push]].\n *\n * ##### Options:\n *\n * - __alt__ - array with names of \"alternate\" chains.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.block.ruler.before('paragraph', 'my_rule', function replace(state) {\n * //...\n * });\n * ```\n **/\nRuler.prototype.before = function (beforeName, ruleName, fn, options) {\n var index = this.__find__(beforeName);\n var opt = options || {};\n\n if (index === -1) { throw new Error('Parser rule not found: ' + beforeName); }\n\n this.__rules__.splice(index, 0, {\n name: ruleName,\n enabled: true,\n fn: fn,\n alt: opt.alt || []\n });\n\n this.__cache__ = null;\n};\n\n\n/**\n * Ruler.after(afterName, ruleName, fn [, options])\n * - afterName (String): new rule will be added after this one.\n * - ruleName (String): name of added rule.\n * - fn (Function): rule function.\n * - options (Object): rule options (not mandatory).\n *\n * Add new rule to chain after one with given name. See also\n * [[Ruler.before]], [[Ruler.push]].\n *\n * ##### Options:\n *\n * - __alt__ - array with names of \"alternate\" chains.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.inline.ruler.after('text', 'my_rule', function replace(state) {\n * //...\n * });\n * ```\n **/\nRuler.prototype.after = function (afterName, ruleName, fn, options) {\n var index = this.__find__(afterName);\n var opt = options || {};\n\n if (index === -1) { throw new Error('Parser rule not found: ' + afterName); }\n\n this.__rules__.splice(index + 1, 0, {\n name: ruleName,\n enabled: true,\n fn: fn,\n alt: opt.alt || []\n });\n\n this.__cache__ = null;\n};\n\n/**\n * Ruler.push(ruleName, fn [, options])\n * - ruleName (String): name of added rule.\n * - fn (Function): rule function.\n * - options (Object): rule options (not mandatory).\n *\n * Push new rule to the end of chain. See also\n * [[Ruler.before]], [[Ruler.after]].\n *\n * ##### Options:\n *\n * - __alt__ - array with names of \"alternate\" chains.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.core.ruler.push('my_rule', function replace(state) {\n * //...\n * });\n * ```\n **/\nRuler.prototype.push = function (ruleName, fn, options) {\n var opt = options || {};\n\n this.__rules__.push({\n name: ruleName,\n enabled: true,\n fn: fn,\n alt: opt.alt || []\n });\n\n this.__cache__ = null;\n};\n\n\n/**\n * Ruler.enable(list [, ignoreInvalid]) -> Array\n * - list (String|Array): list of rule names to enable.\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Enable rules with given names. If any rule name not found - throw Error.\n * Errors can be disabled by second param.\n *\n * Returns list of found rule names (if no exception happened).\n *\n * See also [[Ruler.disable]], [[Ruler.enableOnly]].\n **/\nRuler.prototype.enable = function (list, ignoreInvalid) {\n if (!Array.isArray(list)) { list = [ list ]; }\n\n var result = [];\n\n // Search by name and enable\n list.forEach(function (name) {\n var idx = this.__find__(name);\n\n if (idx < 0) {\n if (ignoreInvalid) { return; }\n throw new Error('Rules manager: invalid rule name ' + name);\n }\n this.__rules__[idx].enabled = true;\n result.push(name);\n }, this);\n\n this.__cache__ = null;\n return result;\n};\n\n\n/**\n * Ruler.enableOnly(list [, ignoreInvalid])\n * - list (String|Array): list of rule names to enable (whitelist).\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Enable rules with given names, and disable everything else. If any rule name\n * not found - throw Error. Errors can be disabled by second param.\n *\n * See also [[Ruler.disable]], [[Ruler.enable]].\n **/\nRuler.prototype.enableOnly = function (list, ignoreInvalid) {\n if (!Array.isArray(list)) { list = [ list ]; }\n\n this.__rules__.forEach(function (rule) { rule.enabled = false; });\n\n this.enable(list, ignoreInvalid);\n};\n\n\n/**\n * Ruler.disable(list [, ignoreInvalid]) -> Array\n * - list (String|Array): list of rule names to disable.\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Disable rules with given names. If any rule name not found - throw Error.\n * Errors can be disabled by second param.\n *\n * Returns list of found rule names (if no exception happened).\n *\n * See also [[Ruler.enable]], [[Ruler.enableOnly]].\n **/\nRuler.prototype.disable = function (list, ignoreInvalid) {\n if (!Array.isArray(list)) { list = [ list ]; }\n\n var result = [];\n\n // Search by name and disable\n list.forEach(function (name) {\n var idx = this.__find__(name);\n\n if (idx < 0) {\n if (ignoreInvalid) { return; }\n throw new Error('Rules manager: invalid rule name ' + name);\n }\n this.__rules__[idx].enabled = false;\n result.push(name);\n }, this);\n\n this.__cache__ = null;\n return result;\n};\n\n\n/**\n * Ruler.getRules(chainName) -> Array\n *\n * Return array of active functions (rules) for given chain name. It analyzes\n * rules configuration, compiles caches if not exists and returns result.\n *\n * Default chain name is `''` (empty string). It can't be skipped. That's\n * done intentionally, to keep signature monomorphic for high speed.\n **/\nRuler.prototype.getRules = function (chainName) {\n if (this.__cache__ === null) {\n this.__compile__();\n }\n\n // Chain can be empty, if rules disabled. But we still have to return Array.\n return this.__cache__[chainName] || [];\n};\n\nmodule.exports = Ruler;\n","// Token class\n\n'use strict';\n\n\n/**\n * class Token\n **/\n\n/**\n * new Token(type, tag, nesting)\n *\n * Create new token and fill passed properties.\n **/\nfunction Token(type, tag, nesting) {\n /**\n * Token#type -> String\n *\n * Type of the token (string, e.g. \"paragraph_open\")\n **/\n this.type = type;\n\n /**\n * Token#tag -> String\n *\n * html tag name, e.g. \"p\"\n **/\n this.tag = tag;\n\n /**\n * Token#attrs -> Array\n *\n * Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]`\n **/\n this.attrs = null;\n\n /**\n * Token#map -> Array\n *\n * Source map info. Format: `[ line_begin, line_end ]`\n **/\n this.map = null;\n\n /**\n * Token#nesting -> Number\n *\n * Level change (number in {-1, 0, 1} set), where:\n *\n * - `1` means the tag is opening\n * - `0` means the tag is self-closing\n * - `-1` means the tag is closing\n **/\n this.nesting = nesting;\n\n /**\n * Token#level -> Number\n *\n * nesting level, the same as `state.level`\n **/\n this.level = 0;\n\n /**\n * Token#children -> Array\n *\n * An array of child nodes (inline and img tokens)\n **/\n this.children = null;\n\n /**\n * Token#content -> String\n *\n * In a case of self-closing tag (code, html, fence, etc.),\n * it has contents of this tag.\n **/\n this.content = '';\n\n /**\n * Token#markup -> String\n *\n * '*' or '_' for emphasis, fence string for fence, etc.\n **/\n this.markup = '';\n\n /**\n * Token#info -> String\n *\n * fence infostring\n **/\n this.info = '';\n\n /**\n * Token#meta -> Object\n *\n * A place for plugins to store an arbitrary data\n **/\n this.meta = null;\n\n /**\n * Token#block -> Boolean\n *\n * True for block-level tokens, false for inline tokens.\n * Used in renderer to calculate line breaks\n **/\n this.block = false;\n\n /**\n * Token#hidden -> Boolean\n *\n * If it's true, ignore this element when rendering. Used for tight lists\n * to hide paragraphs.\n **/\n this.hidden = false;\n}\n\n\n/**\n * Token.attrIndex(name) -> Number\n *\n * Search attribute index by name.\n **/\nToken.prototype.attrIndex = function attrIndex(name) {\n var attrs, i, len;\n\n if (!this.attrs) { return -1; }\n\n attrs = this.attrs;\n\n for (i = 0, len = attrs.length; i < len; i++) {\n if (attrs[i][0] === name) { return i; }\n }\n return -1;\n};\n\n\n/**\n * Token.attrPush(attrData)\n *\n * Add `[ name, value ]` attribute to list. Init attrs if necessary\n **/\nToken.prototype.attrPush = function attrPush(attrData) {\n if (this.attrs) {\n this.attrs.push(attrData);\n } else {\n this.attrs = [ attrData ];\n }\n};\n\n\n/**\n * Token.attrSet(name, value)\n *\n * Set `name` attribute to `value`. Override old value if exists.\n **/\nToken.prototype.attrSet = function attrSet(name, value) {\n var idx = this.attrIndex(name),\n attrData = [ name, value ];\n\n if (idx < 0) {\n this.attrPush(attrData);\n } else {\n this.attrs[idx] = attrData;\n }\n};\n\n\n/**\n * Token.attrGet(name)\n *\n * Get the value of attribute `name`, or null if it does not exist.\n **/\nToken.prototype.attrGet = function attrGet(name) {\n var idx = this.attrIndex(name), value = null;\n if (idx >= 0) {\n value = this.attrs[idx][1];\n }\n return value;\n};\n\n\n/**\n * Token.attrJoin(name, value)\n *\n * Join value to existing attribute via space. Or create new attribute if not\n * exists. Useful to operate with token classes.\n **/\nToken.prototype.attrJoin = function attrJoin(name, value) {\n var idx = this.attrIndex(name);\n\n if (idx < 0) {\n this.attrPush([ name, value ]);\n } else {\n this.attrs[idx][1] = this.attrs[idx][1] + ' ' + value;\n }\n};\n\n\nmodule.exports = Token;\n","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./code.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./heading.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","// HTML5 entities map: { name -> utf16string }\n//\n'use strict';\n\n/*eslint quotes:0*/\nmodule.exports = require('entities/lib/maps/entities.json');\n","'use strict';\n\n\nmodule.exports.encode = require('./encode');\nmodule.exports.decode = require('./decode');\nmodule.exports.format = require('./format');\nmodule.exports.parse = require('./parse');\n","module.exports=/[\\0-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/","module.exports=/[\\0-\\x1F\\x7F-\\x9F]/","module.exports=/[ \\xA0\\u1680\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]/","// Regexps to match html elements\n\n'use strict';\n\nvar attr_name = '[a-zA-Z_:][a-zA-Z0-9:._-]*';\n\nvar unquoted = '[^\"\\'=<>`\\\\x00-\\\\x20]+';\nvar single_quoted = \"'[^']*'\";\nvar double_quoted = '\"[^\"]*\"';\n\nvar attr_value = '(?:' + unquoted + '|' + single_quoted + '|' + double_quoted + ')';\n\nvar attribute = '(?:\\\\s+' + attr_name + '(?:\\\\s*=\\\\s*' + attr_value + ')?)';\n\nvar open_tag = '<[A-Za-z][A-Za-z0-9\\\\-]*' + attribute + '*\\\\s*\\\\/?>';\n\nvar close_tag = '<\\\\/[A-Za-z][A-Za-z0-9\\\\-]*\\\\s*>';\nvar comment = '<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->';\nvar processing = '<[?].*?[?]>';\nvar declaration = '<![A-Z]+\\\\s+[^>]*>';\nvar cdata = '<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>';\n\nvar HTML_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + '|' + comment +\n '|' + processing + '|' + declaration + '|' + cdata + ')');\nvar HTML_OPEN_CLOSE_TAG_RE = new RegExp('^(?:' + open_tag + '|' + close_tag + ')');\n\nmodule.exports.HTML_TAG_RE = HTML_TAG_RE;\nmodule.exports.HTML_OPEN_CLOSE_TAG_RE = HTML_OPEN_CLOSE_TAG_RE;\n","// ~~strike through~~\n//\n'use strict';\n\n\n// Insert each marker as a separate text token, and add it to delimiter list\n//\nmodule.exports.tokenize = function strikethrough(state, silent) {\n var i, scanned, token, len, ch,\n start = state.pos,\n marker = state.src.charCodeAt(start);\n\n if (silent) { return false; }\n\n if (marker !== 0x7E/* ~ */) { return false; }\n\n scanned = state.scanDelims(state.pos, true);\n len = scanned.length;\n ch = String.fromCharCode(marker);\n\n if (len < 2) { return false; }\n\n if (len % 2) {\n token = state.push('text', '', 0);\n token.content = ch;\n len--;\n }\n\n for (i = 0; i < len; i += 2) {\n token = state.push('text', '', 0);\n token.content = ch + ch;\n\n state.delimiters.push({\n marker: marker,\n length: 0, // disable \"rule of 3\" length checks meant for emphasis\n jump: i,\n token: state.tokens.length - 1,\n end: -1,\n open: scanned.can_open,\n close: scanned.can_close\n });\n }\n\n state.pos += scanned.length;\n\n return true;\n};\n\n\nfunction postProcess(state, delimiters) {\n var i, j,\n startDelim,\n endDelim,\n token,\n loneMarkers = [],\n max = delimiters.length;\n\n for (i = 0; i < max; i++) {\n startDelim = delimiters[i];\n\n if (startDelim.marker !== 0x7E/* ~ */) {\n continue;\n }\n\n if (startDelim.end === -1) {\n continue;\n }\n\n endDelim = delimiters[startDelim.end];\n\n token = state.tokens[startDelim.token];\n token.type = 's_open';\n token.tag = 's';\n token.nesting = 1;\n token.markup = '~~';\n token.content = '';\n\n token = state.tokens[endDelim.token];\n token.type = 's_close';\n token.tag = 's';\n token.nesting = -1;\n token.markup = '~~';\n token.content = '';\n\n if (state.tokens[endDelim.token - 1].type === 'text' &&\n state.tokens[endDelim.token - 1].content === '~') {\n\n loneMarkers.push(endDelim.token - 1);\n }\n }\n\n // If a marker sequence has an odd number of characters, it's splitted\n // like this: `~~~~~` -> `~` + `~~` + `~~`, leaving one marker at the\n // start of the sequence.\n //\n // So, we have to move all those markers after subsequent s_close tags.\n //\n while (loneMarkers.length) {\n i = loneMarkers.pop();\n j = i + 1;\n\n while (j < state.tokens.length && state.tokens[j].type === 's_close') {\n j++;\n }\n\n j--;\n\n if (i !== j) {\n token = state.tokens[j];\n state.tokens[j] = state.tokens[i];\n state.tokens[i] = token;\n }\n }\n}\n\n\n// Walk through delimiter list and replace text tokens with tags\n//\nmodule.exports.postProcess = function strikethrough(state) {\n var curr,\n tokens_meta = state.tokens_meta,\n max = state.tokens_meta.length;\n\n postProcess(state, state.delimiters);\n\n for (curr = 0; curr < max; curr++) {\n if (tokens_meta[curr] && tokens_meta[curr].delimiters) {\n postProcess(state, tokens_meta[curr].delimiters);\n }\n }\n};\n","// Process *this* and _that_\n//\n'use strict';\n\n\n// Insert each marker as a separate text token, and add it to delimiter list\n//\nmodule.exports.tokenize = function emphasis(state, silent) {\n var i, scanned, token,\n start = state.pos,\n marker = state.src.charCodeAt(start);\n\n if (silent) { return false; }\n\n if (marker !== 0x5F /* _ */ && marker !== 0x2A /* * */) { return false; }\n\n scanned = state.scanDelims(state.pos, marker === 0x2A);\n\n for (i = 0; i < scanned.length; i++) {\n token = state.push('text', '', 0);\n token.content = String.fromCharCode(marker);\n\n state.delimiters.push({\n // Char code of the starting marker (number).\n //\n marker: marker,\n\n // Total length of these series of delimiters.\n //\n length: scanned.length,\n\n // An amount of characters before this one that's equivalent to\n // current one. In plain English: if this delimiter does not open\n // an emphasis, neither do previous `jump` characters.\n //\n // Used to skip sequences like \"*****\" in one step, for 1st asterisk\n // value will be 0, for 2nd it's 1 and so on.\n //\n jump: i,\n\n // A position of the token this delimiter corresponds to.\n //\n token: state.tokens.length - 1,\n\n // If this delimiter is matched as a valid opener, `end` will be\n // equal to its position, otherwise it's `-1`.\n //\n end: -1,\n\n // Boolean flags that determine if this delimiter could open or close\n // an emphasis.\n //\n open: scanned.can_open,\n close: scanned.can_close\n });\n }\n\n state.pos += scanned.length;\n\n return true;\n};\n\n\nfunction postProcess(state, delimiters) {\n var i,\n startDelim,\n endDelim,\n token,\n ch,\n isStrong,\n max = delimiters.length;\n\n for (i = max - 1; i >= 0; i--) {\n startDelim = delimiters[i];\n\n if (startDelim.marker !== 0x5F/* _ */ && startDelim.marker !== 0x2A/* * */) {\n continue;\n }\n\n // Process only opening markers\n if (startDelim.end === -1) {\n continue;\n }\n\n endDelim = delimiters[startDelim.end];\n\n // If the previous delimiter has the same marker and is adjacent to this one,\n // merge those into one strong delimiter.\n //\n // `<em><em>whatever</em></em>` -> `<strong>whatever</strong>`\n //\n isStrong = i > 0 &&\n delimiters[i - 1].end === startDelim.end + 1 &&\n delimiters[i - 1].token === startDelim.token - 1 &&\n delimiters[startDelim.end + 1].token === endDelim.token + 1 &&\n delimiters[i - 1].marker === startDelim.marker;\n\n ch = String.fromCharCode(startDelim.marker);\n\n token = state.tokens[startDelim.token];\n token.type = isStrong ? 'strong_open' : 'em_open';\n token.tag = isStrong ? 'strong' : 'em';\n token.nesting = 1;\n token.markup = isStrong ? ch + ch : ch;\n token.content = '';\n\n token = state.tokens[endDelim.token];\n token.type = isStrong ? 'strong_close' : 'em_close';\n token.tag = isStrong ? 'strong' : 'em';\n token.nesting = -1;\n token.markup = isStrong ? ch + ch : ch;\n token.content = '';\n\n if (isStrong) {\n state.tokens[delimiters[i - 1].token].content = '';\n state.tokens[delimiters[startDelim.end + 1].token].content = '';\n i--;\n }\n }\n}\n\n\n// Walk through delimiter list and replace text tokens with tags\n//\nmodule.exports.postProcess = function emphasis(state) {\n var curr,\n tokens_meta = state.tokens_meta,\n max = state.tokens_meta.length;\n\n postProcess(state, state.delimiters);\n\n for (curr = 0; curr < max; curr++) {\n if (tokens_meta[curr] && tokens_meta[curr].delimiters) {\n postProcess(state, tokens_meta[curr].delimiters);\n }\n }\n};\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nexport default stubFalse;\n","import root from './_root.js';\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;\n\n/**\n * Creates a clone of `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\nfunction cloneBuffer(buffer, isDeep) {\n if (isDeep) {\n return buffer.slice();\n }\n var length = buffer.length,\n result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n buffer.copy(result);\n return result;\n}\n\nexport default cloneBuffer;\n","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./placeholder.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-placeholder:before,.ck .ck-placeholder:before{content:attr(data-placeholder);pointer-events:none}.ck.ck-read-only .ck-placeholder:before{display:none}.ck.ck-placeholder:before,.ck .ck-placeholder:before{cursor:text;color:var(--ck-color-engine-placeholder-text)}\"","var content = require(\"!!../../../../postcss-loader/src/index.js??ref--5-1!./globals.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck-hidden{display:none!important}.ck.ck-reset,.ck.ck-reset_all,.ck.ck-reset_all *{box-sizing:border-box;width:auto;height:auto;position:static}:root{--ck-z-default:1;--ck-z-modal:calc(var(--ck-z-default) + 999);--ck-color-base-foreground:#fafafa;--ck-color-base-background:#fff;--ck-color-base-border:#c4c4c4;--ck-color-base-action:#61b045;--ck-color-base-focus:#6cb5f9;--ck-color-base-text:#333;--ck-color-base-active:#198cf0;--ck-color-base-active-focus:#0e7fe1;--ck-color-base-error:#db3700;--ck-color-focus-border:#47a4f5;--ck-color-focus-shadow:rgba(119,186,248,0.5);--ck-color-focus-disabled-shadow:rgba(119,186,248,0.3);--ck-color-focus-error-shadow:rgba(255,64,31,0.3);--ck-color-text:var(--ck-color-base-text);--ck-color-shadow-drop:rgba(0,0,0,0.15);--ck-color-shadow-drop-active:rgba(0,0,0,0.2);--ck-color-shadow-inner:rgba(0,0,0,0.1);--ck-color-button-default-background:transparent;--ck-color-button-default-hover-background:#e6e6e6;--ck-color-button-default-active-background:#d9d9d9;--ck-color-button-default-active-shadow:#bfbfbf;--ck-color-button-default-disabled-background:transparent;--ck-color-button-on-background:#dedede;--ck-color-button-on-hover-background:#c4c4c4;--ck-color-button-on-active-background:#bababa;--ck-color-button-on-active-shadow:#a1a1a1;--ck-color-button-on-disabled-background:#dedede;--ck-color-button-action-background:var(--ck-color-base-action);--ck-color-button-action-hover-background:#579e3d;--ck-color-button-action-active-background:#53973b;--ck-color-button-action-active-shadow:#498433;--ck-color-button-action-disabled-background:#7ec365;--ck-color-button-action-text:var(--ck-color-base-background);--ck-color-button-save:#008a00;--ck-color-button-cancel:#db3700;--ck-color-switch-button-off-background:#b0b0b0;--ck-color-switch-button-off-hover-background:#a3a3a3;--ck-color-switch-button-on-background:var(--ck-color-button-action-background);--ck-color-switch-button-on-hover-background:#579e3d;--ck-color-switch-button-inner-background:var(--ck-color-base-background);--ck-color-switch-button-inner-shadow:rgba(0,0,0,0.1);--ck-color-dropdown-panel-background:var(--ck-color-base-background);--ck-color-dropdown-panel-border:var(--ck-color-base-border);--ck-color-input-background:var(--ck-color-base-background);--ck-color-input-border:#c7c7c7;--ck-color-input-error-border:var(--ck-color-base-error);--ck-color-input-text:var(--ck-color-base-text);--ck-color-input-disabled-background:#f2f2f2;--ck-color-input-disabled-border:#c7c7c7;--ck-color-input-disabled-text:#5c5c5c;--ck-color-list-background:var(--ck-color-base-background);--ck-color-list-button-hover-background:var(--ck-color-button-default-hover-background);--ck-color-list-button-on-background:var(--ck-color-base-active);--ck-color-list-button-on-background-focus:var(--ck-color-base-active-focus);--ck-color-list-button-on-text:var(--ck-color-base-background);--ck-color-panel-background:var(--ck-color-base-background);--ck-color-panel-border:var(--ck-color-base-border);--ck-color-toolbar-background:var(--ck-color-base-foreground);--ck-color-toolbar-border:var(--ck-color-base-border);--ck-color-tooltip-background:var(--ck-color-base-text);--ck-color-tooltip-text:var(--ck-color-base-background);--ck-color-engine-placeholder-text:#707070;--ck-color-upload-bar-background:#6cb5f9;--ck-color-link-default:#0000f0;--ck-color-link-selected-background:rgba(31,177,255,0.1);--ck-disabled-opacity:.5;--ck-focus-outer-shadow-geometry:0 0 0 3px;--ck-focus-outer-shadow:var(--ck-focus-outer-shadow-geometry) var(--ck-color-focus-shadow);--ck-focus-disabled-outer-shadow:var(--ck-focus-outer-shadow-geometry) var(--ck-color-focus-disabled-shadow);--ck-focus-error-outer-shadow:var(--ck-focus-outer-shadow-geometry) var(--ck-color-focus-error-shadow);--ck-focus-ring:1px solid var(--ck-color-focus-border);--ck-font-size-base:13px;--ck-line-height-base:1.84615;--ck-font-face:Helvetica,Arial,Tahoma,Verdana,Sans-Serif;--ck-font-size-tiny:0.7em;--ck-font-size-small:0.75em;--ck-font-size-normal:1em;--ck-font-size-big:1.4em;--ck-font-size-large:1.8em;--ck-ui-component-min-height:2.3em}.ck.ck-reset,.ck.ck-reset_all,.ck.ck-reset_all *{margin:0;padding:0;border:0;background:transparent;text-decoration:none;vertical-align:middle;transition:none;word-wrap:break-word}.ck.ck-reset_all,.ck.ck-reset_all *{border-collapse:collapse;font:normal normal normal var(--ck-font-size-base)/var(--ck-line-height-base) var(--ck-font-face);color:var(--ck-color-text);text-align:left;white-space:nowrap;cursor:auto;float:none}.ck.ck-reset_all .ck-rtl *{text-align:right}.ck.ck-reset_all iframe{vertical-align:inherit}.ck.ck-reset_all textarea{white-space:pre-wrap}.ck.ck-reset_all input[type=password],.ck.ck-reset_all input[type=text],.ck.ck-reset_all textarea{cursor:text}.ck.ck-reset_all input[type=password][disabled],.ck.ck-reset_all input[type=text][disabled],.ck.ck-reset_all textarea[disabled]{cursor:default}.ck.ck-reset_all fieldset{padding:10px;border:2px groove #dfdee3}.ck.ck-reset_all button::-moz-focus-inner{padding:0;border:0}.ck[dir=rtl],.ck[dir=rtl] .ck{text-align:right}:root{--ck-border-radius:2px;--ck-inner-shadow:2px 2px 3px var(--ck-color-shadow-inner) inset;--ck-drop-shadow:0 1px 2px 1px var(--ck-color-shadow-drop);--ck-drop-shadow-active:0 3px 6px 1px var(--ck-color-shadow-drop-active);--ck-spacing-unit:0.6em;--ck-spacing-large:calc(var(--ck-spacing-unit)*1.5);--ck-spacing-standard:var(--ck-spacing-unit);--ck-spacing-medium:calc(var(--ck-spacing-unit)*0.8);--ck-spacing-small:calc(var(--ck-spacing-unit)*0.5);--ck-spacing-tiny:calc(var(--ck-spacing-unit)*0.3);--ck-spacing-extra-tiny:calc(var(--ck-spacing-unit)*0.16)}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./editorui.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-editor__editable:not(.ck-editor__nested-editable){border-radius:0}.ck-rounded-corners .ck.ck-editor__editable:not(.ck-editor__nested-editable),.ck.ck-editor__editable:not(.ck-editor__nested-editable).ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-editor__editable:not(.ck-editor__nested-editable).ck-focused{outline:none;border:var(--ck-focus-ring);box-shadow:var(--ck-inner-shadow),0 0}.ck.ck-editor__editable_inline{overflow:auto;padding:0 var(--ck-spacing-standard);border:1px solid transparent}.ck.ck-editor__editable_inline[dir=ltr]{text-align:left}.ck.ck-editor__editable_inline[dir=rtl]{text-align:right}.ck.ck-editor__editable_inline>:first-child{margin-top:var(--ck-spacing-large)}.ck.ck-editor__editable_inline>:last-child{margin-bottom:var(--ck-spacing-large)}.ck.ck-balloon-panel.ck-toolbar-container[class*=arrow_n]:after{border-bottom-color:var(--ck-color-base-foreground)}.ck.ck-balloon-panel.ck-toolbar-container[class*=arrow_s]:after{border-top-color:var(--ck-color-base-foreground)}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./dropdown.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-dropdown{display:inline-block;position:relative}.ck.ck-dropdown .ck-dropdown__arrow{pointer-events:none;z-index:var(--ck-z-default)}.ck.ck-dropdown .ck-button.ck-dropdown__button{width:100%}.ck.ck-dropdown .ck-button.ck-dropdown__button.ck-on .ck-tooltip{display:none}.ck.ck-dropdown .ck-dropdown__panel{-webkit-backface-visibility:hidden;display:none;z-index:var(--ck-z-modal);position:absolute}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel-visible{display:inline-block;will-change:transform}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_ne,.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_nw{bottom:100%}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se,.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw{transform:translate3d(0,100%,0)}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_ne,.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se{left:0}.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_nw,.ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw{right:0}:root{--ck-dropdown-arrow-size:calc(0.5*var(--ck-icon-size))}.ck.ck-dropdown{font-size:inherit}.ck.ck-dropdown .ck-dropdown__arrow{width:var(--ck-dropdown-arrow-size)}[dir=ltr] .ck.ck-dropdown .ck-dropdown__arrow{right:var(--ck-spacing-standard);margin-left:var(--ck-spacing-small)}[dir=rtl] .ck.ck-dropdown .ck-dropdown__arrow{left:var(--ck-spacing-standard);margin-right:var(--ck-spacing-small)}.ck.ck-dropdown.ck-disabled .ck-dropdown__arrow{opacity:var(--ck-disabled-opacity)}[dir=ltr] .ck.ck-dropdown .ck-button.ck-dropdown__button:not(.ck-button_with-text){padding-left:var(--ck-spacing-small)}[dir=rtl] .ck.ck-dropdown .ck-button.ck-dropdown__button:not(.ck-button_with-text){padding-right:var(--ck-spacing-small)}.ck.ck-dropdown .ck-button.ck-dropdown__button.ck-disabled .ck-button__label{opacity:var(--ck-disabled-opacity)}.ck.ck-dropdown .ck-button.ck-dropdown__button.ck-on{border-bottom-left-radius:0;border-bottom-right-radius:0}.ck.ck-dropdown .ck-button.ck-dropdown__button .ck-button__label{width:7em;overflow:hidden;text-overflow:ellipsis}.ck.ck-dropdown__panel{box-shadow:var(--ck-drop-shadow),0 0;border-radius:0}.ck-rounded-corners .ck.ck-dropdown__panel,.ck.ck-dropdown__panel.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:0}.ck.ck-dropdown__panel{background:var(--ck-color-dropdown-panel-background);border:1px solid var(--ck-color-dropdown-panel-border);bottom:0;min-width:100%}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./icon.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-icon{vertical-align:middle}:root{--ck-icon-size:calc(var(--ck-line-height-base)*var(--ck-font-size-normal))}.ck.ck-icon{width:var(--ck-icon-size);height:var(--ck-icon-size);font-size:.8333350694em;will-change:transform}.ck.ck-icon,.ck.ck-icon *{color:inherit;cursor:inherit}.ck.ck-icon :not([fill]){fill:currentColor}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./tooltip.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-tooltip,.ck.ck-tooltip .ck-tooltip__text:after{position:absolute;pointer-events:none;-webkit-backface-visibility:hidden}.ck-tooltip{visibility:hidden;opacity:0;display:none;z-index:var(--ck-z-modal)}.ck-tooltip .ck-tooltip__text{display:inline-block}.ck-tooltip .ck-tooltip__text:after{content:\\\"\\\";width:0;height:0}:root{--ck-tooltip-arrow-size:5px}.ck.ck-tooltip{left:50%;top:0}.ck.ck-tooltip.ck-tooltip_s{bottom:calc(-1*var(--ck-tooltip-arrow-size));transform:translateY(100%)}.ck.ck-tooltip.ck-tooltip_s .ck-tooltip__text:after{top:calc(-1*var(--ck-tooltip-arrow-size));transform:translateX(-50%);border-left-color:transparent;border-bottom-color:var(--ck-color-tooltip-background);border-right-color:transparent;border-top-color:transparent;border-left-width:var(--ck-tooltip-arrow-size);border-bottom-width:var(--ck-tooltip-arrow-size);border-right-width:var(--ck-tooltip-arrow-size);border-top-width:0}.ck.ck-tooltip.ck-tooltip_n{top:calc(-1*var(--ck-tooltip-arrow-size));transform:translateY(-100%)}.ck.ck-tooltip.ck-tooltip_n .ck-tooltip__text:after{bottom:calc(-1*var(--ck-tooltip-arrow-size));transform:translateX(-50%);border-left-color:transparent;border-bottom-color:transparent;border-right-color:transparent;border-top-color:var(--ck-color-tooltip-background);border-left-width:var(--ck-tooltip-arrow-size);border-bottom-width:0;border-right-width:var(--ck-tooltip-arrow-size);border-top-width:var(--ck-tooltip-arrow-size)}.ck.ck-tooltip .ck-tooltip__text{border-radius:0}.ck-rounded-corners .ck.ck-tooltip .ck-tooltip__text,.ck.ck-tooltip .ck-tooltip__text.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-tooltip .ck-tooltip__text{font-size:.9em;line-height:1.5;color:var(--ck-color-tooltip-text);padding:var(--ck-spacing-small) var(--ck-spacing-medium);background:var(--ck-color-tooltip-background);position:relative;left:-50%}.ck.ck-tooltip .ck-tooltip__text:after{border-style:solid;left:50%}.ck.ck-tooltip,.ck.ck-tooltip .ck-tooltip__text:after{transition:opacity .2s ease-in-out .2s}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./button.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-button,a.ck.ck-button{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.ck.ck-button .ck-tooltip,a.ck.ck-button .ck-tooltip{display:block}@media (hover:none){.ck.ck-button .ck-tooltip,a.ck.ck-button .ck-tooltip{display:none}}.ck.ck-button,a.ck.ck-button{position:relative;display:inline-flex;align-items:center;justify-content:left}.ck.ck-button.ck-button_with-text .ck-button__label,a.ck.ck-button.ck-button_with-text .ck-button__label{display:inline-block}.ck.ck-button:not(.ck-button_with-text),a.ck.ck-button:not(.ck-button_with-text){justify-content:center}.ck.ck-button:hover .ck-tooltip,a.ck.ck-button:hover .ck-tooltip{visibility:visible;opacity:1}.ck.ck-button .ck-button__label,.ck.ck-button:focus:not(:hover) .ck-tooltip,a.ck.ck-button .ck-button__label,a.ck.ck-button:focus:not(:hover) .ck-tooltip{display:none}.ck.ck-button,a.ck.ck-button{background:var(--ck-color-button-default-background)}.ck.ck-button:not(.ck-disabled):hover,a.ck.ck-button:not(.ck-disabled):hover{background:var(--ck-color-button-default-hover-background)}.ck.ck-button:not(.ck-disabled):active,a.ck.ck-button:not(.ck-disabled):active{background:var(--ck-color-button-default-active-background);box-shadow:inset 0 2px 2px var(--ck-color-button-default-active-shadow)}.ck.ck-button.ck-disabled,a.ck.ck-button.ck-disabled{background:var(--ck-color-button-default-disabled-background)}.ck.ck-button,a.ck.ck-button{border-radius:0}.ck-rounded-corners .ck.ck-button,.ck-rounded-corners a.ck.ck-button,.ck.ck-button.ck-rounded-corners,a.ck.ck-button.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-button,a.ck.ck-button{white-space:nowrap;cursor:default;vertical-align:middle;padding:var(--ck-spacing-tiny);text-align:center;min-width:var(--ck-ui-component-min-height);min-height:var(--ck-ui-component-min-height);line-height:1;font-size:inherit;border:1px solid transparent;transition:box-shadow .2s ease-in-out;-webkit-appearance:none}.ck.ck-button:active,.ck.ck-button:focus,a.ck.ck-button:active,a.ck.ck-button:focus{outline:none;border:var(--ck-focus-ring);box-shadow:var(--ck-focus-outer-shadow),0 0;border-color:transparent}.ck.ck-button.ck-disabled:active,.ck.ck-button.ck-disabled:focus,a.ck.ck-button.ck-disabled:active,a.ck.ck-button.ck-disabled:focus{box-shadow:var(--ck-focus-disabled-outer-shadow),0 0}.ck.ck-button.ck-disabled .ck-button__icon,a.ck.ck-button.ck-disabled .ck-button__icon{opacity:var(--ck-disabled-opacity)}.ck.ck-button.ck-disabled .ck-button__label,a.ck.ck-button.ck-disabled .ck-button__label{opacity:var(--ck-disabled-opacity)}.ck.ck-button.ck-button_with-text,a.ck.ck-button.ck-button_with-text{padding:var(--ck-spacing-tiny) var(--ck-spacing-standard)}[dir=ltr] .ck.ck-button.ck-button_with-text .ck-button__icon,[dir=ltr] a.ck.ck-button.ck-button_with-text .ck-button__icon{margin-left:calc(-1*var(--ck-spacing-small));margin-right:var(--ck-spacing-small)}[dir=rtl] .ck.ck-button.ck-button_with-text .ck-button__icon,[dir=rtl] a.ck.ck-button.ck-button_with-text .ck-button__icon{margin-right:calc(-1*var(--ck-spacing-small));margin-left:var(--ck-spacing-small)}.ck.ck-button.ck-on,a.ck.ck-button.ck-on{background:var(--ck-color-button-on-background)}.ck.ck-button.ck-on:not(.ck-disabled):hover,a.ck.ck-button.ck-on:not(.ck-disabled):hover{background:var(--ck-color-button-on-hover-background)}.ck.ck-button.ck-on:not(.ck-disabled):active,a.ck.ck-button.ck-on:not(.ck-disabled):active{background:var(--ck-color-button-on-active-background);box-shadow:inset 0 2px 2px var(--ck-color-button-on-active-shadow)}.ck.ck-button.ck-on.ck-disabled,a.ck.ck-button.ck-on.ck-disabled{background:var(--ck-color-button-on-disabled-background)}.ck.ck-button.ck-button-save,a.ck.ck-button.ck-button-save{color:var(--ck-color-button-save)}.ck.ck-button.ck-button-cancel,a.ck.ck-button.ck-button-cancel{color:var(--ck-color-button-cancel)}.ck.ck-button .ck-button__icon use,.ck.ck-button .ck-button__icon use *,a.ck.ck-button .ck-button__icon use,a.ck.ck-button .ck-button__icon use *{color:inherit}.ck.ck-button .ck-button__label,a.ck.ck-button .ck-button__label{font-size:inherit;font-weight:inherit;color:inherit;cursor:inherit;vertical-align:middle}[dir=ltr] .ck.ck-button .ck-button__label,[dir=ltr] a.ck.ck-button .ck-button__label{text-align:left}[dir=rtl] .ck.ck-button .ck-button__label,[dir=rtl] a.ck.ck-button .ck-button__label{text-align:right}.ck.ck-button-action,a.ck.ck-button-action{background:var(--ck-color-button-action-background)}.ck.ck-button-action:not(.ck-disabled):hover,a.ck.ck-button-action:not(.ck-disabled):hover{background:var(--ck-color-button-action-hover-background)}.ck.ck-button-action:not(.ck-disabled):active,a.ck.ck-button-action:not(.ck-disabled):active{background:var(--ck-color-button-action-active-background);box-shadow:inset 0 2px 2px var(--ck-color-button-action-active-shadow)}.ck.ck-button-action.ck-disabled,a.ck.ck-button-action.ck-disabled{background:var(--ck-color-button-action-disabled-background)}.ck.ck-button-action,a.ck.ck-button-action{color:var(--ck-color-button-action-text)}.ck.ck-button-bold,a.ck.ck-button-bold{font-weight:700}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./list.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-list{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-direction:column}.ck.ck-list .ck-list__item,.ck.ck-list .ck-list__separator{display:block}.ck.ck-list .ck-list__item>:focus{position:relative;z-index:var(--ck-z-default)}.ck.ck-list{border-radius:0}.ck-rounded-corners .ck.ck-list,.ck.ck-list.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-list{list-style-type:none;background:var(--ck-color-list-background)}.ck.ck-list__item{cursor:default;min-width:12em}.ck.ck-list__item .ck-button{min-height:unset;width:100%;text-align:left;border-radius:0;border:0;padding:calc(0.2*var(--ck-line-height-base)*var(--ck-font-size-base)) calc(0.4*var(--ck-line-height-base)*var(--ck-font-size-base))}.ck.ck-list__item .ck-button .ck-button__label{line-height:calc(1.2*var(--ck-line-height-base)*var(--ck-font-size-base))}.ck.ck-list__item .ck-button:active{box-shadow:none}.ck.ck-list__item .ck-button.ck-on{background:var(--ck-color-list-button-on-background);color:var(--ck-color-list-button-on-text)}.ck.ck-list__item .ck-button.ck-on:hover:not(ck-disabled){background:var(--ck-color-list-button-on-background-focus)}.ck.ck-list__item .ck-button.ck-on:active{box-shadow:none}.ck.ck-list__item .ck-button:hover:not(.ck-disabled){background:var(--ck-color-list-button-hover-background)}.ck.ck-list__item .ck-switchbutton.ck-on{background:var(--ck-color-list-background);color:inherit}.ck.ck-list__item .ck-switchbutton.ck-on:hover:not(ck-disabled){background:var(--ck-color-list-button-hover-background);color:inherit}.ck.ck-list__separator{height:1px;width:100%;background:var(--ck-color-base-border)}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./switchbutton.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-button.ck-switchbutton .ck-button__toggle,.ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner{display:block}:root{--ck-switch-button-toggle-width:2.6153846154em;--ck-switch-button-toggle-inner-size:1.0769230769em;--ck-switch-button-toggle-spacing:1px;--ck-switch-button-translation:1.3846153847em}[dir=ltr] .ck.ck-button.ck-switchbutton .ck-button__label{margin-right:calc(2*var(--ck-spacing-large))}[dir=rtl] .ck.ck-button.ck-switchbutton .ck-button__label{margin-left:calc(2*var(--ck-spacing-large))}.ck.ck-button.ck-switchbutton.ck-disabled .ck-button__toggle{opacity:var(--ck-disabled-opacity)}.ck.ck-button.ck-switchbutton .ck-button__toggle{border-radius:0}.ck-rounded-corners .ck.ck-button.ck-switchbutton .ck-button__toggle,.ck.ck-button.ck-switchbutton .ck-button__toggle.ck-rounded-corners{border-radius:var(--ck-border-radius)}[dir=ltr] .ck.ck-button.ck-switchbutton .ck-button__toggle{margin-left:auto}[dir=rtl] .ck.ck-button.ck-switchbutton .ck-button__toggle{margin-right:auto}.ck.ck-button.ck-switchbutton .ck-button__toggle{transition:background .4s ease;width:var(--ck-switch-button-toggle-width);background:var(--ck-color-switch-button-off-background)}.ck.ck-button.ck-switchbutton .ck-button__toggle:hover{background:var(--ck-color-switch-button-off-hover-background)}.ck.ck-button.ck-switchbutton .ck-button__toggle:hover .ck-button__toggle__inner{box-shadow:0 0 0 5px var(--ck-color-switch-button-inner-shadow)}.ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner{border-radius:0}.ck-rounded-corners .ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner,.ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner.ck-rounded-corners{border-radius:var(--ck-border-radius);border-radius:calc(0.5*var(--ck-border-radius))}.ck.ck-button.ck-switchbutton .ck-button__toggle .ck-button__toggle__inner{margin:var(--ck-switch-button-toggle-spacing);width:var(--ck-switch-button-toggle-inner-size);height:var(--ck-switch-button-toggle-inner-size);background:var(--ck-color-switch-button-inner-background);transition:all .3s ease}.ck.ck-button.ck-switchbutton.ck-on .ck-button__toggle{background:var(--ck-color-switch-button-on-background)}.ck.ck-button.ck-switchbutton.ck-on .ck-button__toggle:hover{background:var(--ck-color-switch-button-on-hover-background)}[dir=ltr] .ck.ck-button.ck-switchbutton.ck-on .ck-button__toggle .ck-button__toggle__inner{transform:translateX(var(--ck-switch-button-translation))}[dir=rtl] .ck.ck-button.ck-switchbutton.ck-on .ck-button__toggle .ck-button__toggle__inner{transform:translateX(calc(-1*var(--ck-switch-button-translation)))}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./toolbardropdown.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-toolbar-dropdown .ck.ck-toolbar .ck.ck-toolbar__items{flex-wrap:nowrap}.ck.ck-toolbar-dropdown .ck-dropdown__panel .ck-button:focus{z-index:calc(var(--ck-z-default) + 1)}.ck.ck-toolbar-dropdown .ck-toolbar{border:0}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./listdropdown.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-dropdown .ck-dropdown__panel .ck-list{border-radius:0}.ck-rounded-corners .ck.ck-dropdown .ck-dropdown__panel .ck-list,.ck.ck-dropdown .ck-dropdown__panel .ck-list.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:0}.ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:first-child .ck-button{border-radius:0}.ck-rounded-corners .ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:first-child .ck-button,.ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:first-child .ck-button.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:last-child .ck-button{border-radius:0}.ck-rounded-corners .ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:last-child .ck-button,.ck.ck-dropdown .ck-dropdown__panel .ck-list .ck-list__item:last-child .ck-button.ck-rounded-corners{border-radius:var(--ck-border-radius);border-top-left-radius:0;border-top-right-radius:0}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./toolbar.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-toolbar{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-flow:row nowrap;align-items:center}.ck.ck-toolbar>.ck-toolbar__items{display:flex;flex-flow:row wrap;align-items:center;flex-grow:1}.ck.ck-toolbar .ck.ck-toolbar__separator{display:inline-block}.ck.ck-toolbar .ck.ck-toolbar__separator:first-child,.ck.ck-toolbar .ck.ck-toolbar__separator:last-child{display:none}.ck.ck-toolbar.ck-toolbar_grouping>.ck-toolbar__items{flex-wrap:nowrap}.ck.ck-toolbar.ck-toolbar_vertical>.ck-toolbar__items{flex-direction:column}.ck.ck-toolbar.ck-toolbar_floating>.ck-toolbar__items{flex-wrap:nowrap}.ck.ck-toolbar>.ck.ck-toolbar__grouped-dropdown>.ck-dropdown__button .ck-dropdown__arrow{display:none}.ck.ck-toolbar{border-radius:0}.ck-rounded-corners .ck.ck-toolbar,.ck.ck-toolbar.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-toolbar{background:var(--ck-color-toolbar-background);padding:0 var(--ck-spacing-small);border:1px solid var(--ck-color-toolbar-border)}.ck.ck-toolbar>.ck-toolbar__items>*{margin-top:var(--ck-spacing-small);margin-bottom:var(--ck-spacing-small);margin-right:var(--ck-spacing-small)}.ck.ck-toolbar.ck-toolbar_vertical{padding:0}.ck.ck-toolbar.ck-toolbar_vertical>.ck-toolbar__items>.ck{width:100%;margin:0;border-radius:0;border:0}.ck.ck-toolbar>.ck-toolbar__items>*,.ck.ck-toolbar>.ck.ck-toolbar__grouped-dropdown{margin-top:var(--ck-spacing-small);margin-bottom:var(--ck-spacing-small)}.ck.ck-toolbar>.ck.ck-toolbar__grouped-dropdown>.ck.ck-button.ck-dropdown__button{padding-left:var(--ck-spacing-tiny)}.ck.ck-toolbar .ck.ck-toolbar__separator{align-self:stretch;width:1px;min-width:1px;margin-top:0;margin-bottom:0;background:var(--ck-color-toolbar-border)}.ck-toolbar-container .ck.ck-toolbar{border:0}.ck.ck-toolbar[dir=ltr]>.ck.ck-toolbar__grouped-dropdown,[dir=ltr] .ck.ck-toolbar>.ck.ck-toolbar__grouped-dropdown{padding-left:var(--ck-spacing-small)}.ck.ck-toolbar[dir=ltr]>.ck.ck-toolbar__items>:last-child,[dir=ltr] .ck.ck-toolbar>.ck.ck-toolbar__items>:last-child{margin-right:0}.ck.ck-toolbar[dir=ltr].ck-toolbar_grouping>.ck-toolbar__items,[dir=ltr] .ck.ck-toolbar.ck-toolbar_grouping>.ck-toolbar__items{margin-right:var(--ck-spacing-small)}.ck.ck-toolbar[dir=rtl]>.ck.ck-toolbar__grouped-dropdown,[dir=rtl] .ck.ck-toolbar>.ck.ck-toolbar__grouped-dropdown{padding-right:var(--ck-spacing-small)}.ck.ck-toolbar[dir=rtl]>.ck.ck-toolbar__items>*,[dir=rtl] .ck.ck-toolbar>.ck.ck-toolbar__items>*{margin-left:var(--ck-spacing-small);margin-right:0}.ck.ck-toolbar[dir=rtl]>.ck.ck-toolbar__items>:last-child,[dir=rtl] .ck.ck-toolbar>.ck.ck-toolbar__items>:last-child{margin-left:0}.ck.ck-toolbar[dir=rtl].ck-toolbar_grouping>.ck-toolbar__items,[dir=rtl] .ck.ck-toolbar.ck-toolbar_grouping>.ck-toolbar__items{margin-left:var(--ck-spacing-small)}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./widget.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-color-resizer:var(--ck-color-focus-border);--ck-resizer-size:10px;--ck-resizer-border-width:1px;--ck-resizer-border-radius:2px;--ck-resizer-offset:calc(var(--ck-resizer-size)/-2 - 2px);--ck-resizer-tooltip-offset:10px;--ck-color-resizer-tooltip-background:#262626;--ck-color-resizer-tooltip-text:#f2f2f2}.ck .ck-widget.ck-widget_with-selection-handle{position:relative}.ck .ck-widget.ck-widget_with-selection-handle:hover .ck-widget__selection-handle{visibility:visible}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle{position:absolute}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle .ck-icon{display:block}.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected .ck-widget__selection-handle{visibility:visible}.ck .ck-size-view{background:var(--ck-color-resizer-tooltip-background);color:var(--ck-color-resizer-tooltip-text);border:1px solid var(--ck-color-resizer-tooltip-text);border-radius:var(--ck-resizer-border-radius);font-size:var(--ck-font-size-tiny);display:block;padding:var(--ck-spacing-small)}.ck .ck-size-view.ck-orientation-bottom-left,.ck .ck-size-view.ck-orientation-bottom-right,.ck .ck-size-view.ck-orientation-top-left,.ck .ck-size-view.ck-orientation-top-right{position:absolute}.ck .ck-size-view.ck-orientation-top-left{top:var(--ck-resizer-tooltip-offset);left:var(--ck-resizer-tooltip-offset)}.ck .ck-size-view.ck-orientation-top-right{top:var(--ck-resizer-tooltip-offset);right:var(--ck-resizer-tooltip-offset)}.ck .ck-size-view.ck-orientation-bottom-right{bottom:var(--ck-resizer-tooltip-offset);right:var(--ck-resizer-tooltip-offset)}.ck .ck-size-view.ck-orientation-bottom-left{bottom:var(--ck-resizer-tooltip-offset);left:var(--ck-resizer-tooltip-offset)}:root{--ck-widget-outline-thickness:3px;--ck-widget-handler-icon-size:16px;--ck-widget-handler-animation-duration:200ms;--ck-widget-handler-animation-curve:ease;--ck-color-widget-blurred-border:#dedede;--ck-color-widget-hover-border:#ffc83d;--ck-color-widget-editable-focus-background:var(--ck-color-base-background);--ck-color-widget-drag-handler-icon-color:var(--ck-color-base-background)}.ck .ck-widget{outline-width:var(--ck-widget-outline-thickness);outline-style:solid;outline-color:transparent;transition:outline-color var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve)}.ck .ck-widget.ck-widget_selected,.ck .ck-widget.ck-widget_selected:hover{outline:var(--ck-widget-outline-thickness) solid var(--ck-color-focus-border)}.ck .ck-widget:hover{outline-color:var(--ck-color-widget-hover-border)}.ck .ck-editor__nested-editable{border:1px solid transparent}.ck .ck-editor__nested-editable.ck-editor__nested-editable_focused,.ck .ck-editor__nested-editable:focus{outline:none;border:var(--ck-focus-ring);box-shadow:var(--ck-inner-shadow),0 0;background-color:var(--ck-color-widget-editable-focus-background)}.ck-editor__editable>.ck-widget.ck-widget_with-selection-handle:first-child,.ck-editor__editable blockquote>.ck-widget.ck-widget_with-selection-handle:first-child{margin-top:calc(1em + var(--ck-widget-handler-icon-size))}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle{padding:4px;box-sizing:border-box;background-color:transparent;opacity:0;transition:background-color var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve),visibility var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve),opacity var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve);border-radius:var(--ck-border-radius) var(--ck-border-radius) 0 0;transform:translateY(-100%);left:calc(0px - var(--ck-widget-outline-thickness))}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle:hover .ck-icon .ck-icon__selected-indicator{opacity:1}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle .ck-icon{width:var(--ck-widget-handler-icon-size);height:var(--ck-widget-handler-icon-size);color:var(--ck-color-widget-drag-handler-icon-color)}.ck .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle .ck-icon .ck-icon__selected-indicator{opacity:0;transition:opacity .3s var(--ck-widget-handler-animation-curve)}.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected .ck-widget__selection-handle,.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected:hover .ck-widget__selection-handle{opacity:1;background-color:var(--ck-color-focus-border)}.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected .ck-widget__selection-handle .ck-icon .ck-icon__selected-indicator,.ck .ck-widget.ck-widget_with-selection-handle.ck-widget_selected:hover .ck-widget__selection-handle .ck-icon .ck-icon__selected-indicator{opacity:1}.ck .ck-widget.ck-widget_with-selection-handle:hover .ck-widget__selection-handle{opacity:1;background-color:var(--ck-color-widget-hover-border)}.ck[dir=rtl] .ck-widget.ck-widget_with-selection-handle .ck-widget__selection-handle{left:auto;right:calc(0px - var(--ck-widget-outline-thickness))}.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected,.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected:hover{outline-color:var(--ck-color-widget-blurred-border)}.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected .ck-widget__selection-handle,.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected .ck-widget__selection-handle:hover,.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected:hover .ck-widget__selection-handle,.ck-editor__editable.ck-blurred .ck-widget.ck-widget_selected:hover .ck-widget__selection-handle:hover{background:var(--ck-color-widget-blurred-border)}.ck-editor__editable.ck-read-only .ck-widget{--ck-widget-outline-thickness:0}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./balloonpanel.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-balloon-panel-arrow-z-index:calc(var(--ck-z-default) - 3)}.ck.ck-balloon-panel{display:none;position:absolute;z-index:var(--ck-z-modal)}.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:after,.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:before{content:\\\"\\\";position:absolute}.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:before{z-index:var(--ck-balloon-panel-arrow-z-index)}.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:after{z-index:calc(var(--ck-balloon-panel-arrow-z-index) + 1)}.ck.ck-balloon-panel[class*=arrow_n]:before{z-index:var(--ck-balloon-panel-arrow-z-index)}.ck.ck-balloon-panel[class*=arrow_n]:after{z-index:calc(var(--ck-balloon-panel-arrow-z-index) + 1)}.ck.ck-balloon-panel[class*=arrow_s]:before{z-index:var(--ck-balloon-panel-arrow-z-index)}.ck.ck-balloon-panel[class*=arrow_s]:after{z-index:calc(var(--ck-balloon-panel-arrow-z-index) + 1)}.ck.ck-balloon-panel.ck-balloon-panel_visible{display:block}:root{--ck-balloon-arrow-offset:2px;--ck-balloon-arrow-height:10px;--ck-balloon-arrow-half-width:8px}.ck.ck-balloon-panel{border-radius:0}.ck-rounded-corners .ck.ck-balloon-panel,.ck.ck-balloon-panel.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-balloon-panel{box-shadow:var(--ck-drop-shadow),0 0;min-height:15px;background:var(--ck-color-panel-background);border:1px solid var(--ck-color-panel-border)}.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:after,.ck.ck-balloon-panel.ck-balloon-panel_with-arrow:before{width:0;height:0;border-style:solid}.ck.ck-balloon-panel[class*=arrow_n]:after,.ck.ck-balloon-panel[class*=arrow_n]:before{border-left-width:var(--ck-balloon-arrow-half-width);border-bottom-width:var(--ck-balloon-arrow-height);border-right-width:var(--ck-balloon-arrow-half-width);border-top-width:0}.ck.ck-balloon-panel[class*=arrow_n]:before{border-bottom-color:var(--ck-color-panel-border)}.ck.ck-balloon-panel[class*=arrow_n]:after,.ck.ck-balloon-panel[class*=arrow_n]:before{border-left-color:transparent;border-right-color:transparent;border-top-color:transparent}.ck.ck-balloon-panel[class*=arrow_n]:after{border-bottom-color:var(--ck-color-panel-background);margin-top:var(--ck-balloon-arrow-offset)}.ck.ck-balloon-panel[class*=arrow_s]:after,.ck.ck-balloon-panel[class*=arrow_s]:before{border-left-width:var(--ck-balloon-arrow-half-width);border-bottom-width:0;border-right-width:var(--ck-balloon-arrow-half-width);border-top-width:var(--ck-balloon-arrow-height)}.ck.ck-balloon-panel[class*=arrow_s]:before{border-top-color:var(--ck-color-panel-border)}.ck.ck-balloon-panel[class*=arrow_s]:after,.ck.ck-balloon-panel[class*=arrow_s]:before{border-left-color:transparent;border-bottom-color:transparent;border-right-color:transparent}.ck.ck-balloon-panel[class*=arrow_s]:after{border-top-color:var(--ck-color-panel-background);margin-bottom:var(--ck-balloon-arrow-offset)}.ck.ck-balloon-panel.ck-balloon-panel_arrow_n:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_n:before{left:50%;margin-left:calc(-1*var(--ck-balloon-arrow-half-width));top:calc(-1*var(--ck-balloon-arrow-height))}.ck.ck-balloon-panel.ck-balloon-panel_arrow_nw:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_nw:before{left:calc(2*var(--ck-balloon-arrow-half-width));top:calc(-1*var(--ck-balloon-arrow-height))}.ck.ck-balloon-panel.ck-balloon-panel_arrow_ne:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_ne:before{right:calc(2*var(--ck-balloon-arrow-half-width));top:calc(-1*var(--ck-balloon-arrow-height))}.ck.ck-balloon-panel.ck-balloon-panel_arrow_s:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_s:before{left:50%;margin-left:calc(-1*var(--ck-balloon-arrow-half-width));bottom:calc(-1*var(--ck-balloon-arrow-height))}.ck.ck-balloon-panel.ck-balloon-panel_arrow_sw:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_sw:before{left:calc(2*var(--ck-balloon-arrow-half-width));bottom:calc(-1*var(--ck-balloon-arrow-height))}.ck.ck-balloon-panel.ck-balloon-panel_arrow_se:after,.ck.ck-balloon-panel.ck-balloon-panel_arrow_se:before{right:calc(2*var(--ck-balloon-arrow-half-width));bottom:calc(-1*var(--ck-balloon-arrow-height))}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./balloonrotator.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck .ck-balloon-rotator__navigation{display:flex;align-items:center;justify-content:center}.ck .ck-balloon-rotator__content .ck-toolbar{justify-content:center}.ck .ck-balloon-rotator__navigation{background:var(--ck-color-toolbar-background);border-bottom:1px solid var(--ck-color-toolbar-border);padding:0 var(--ck-spacing-small)}.ck .ck-balloon-rotator__navigation>*{margin-right:var(--ck-spacing-small);margin-top:var(--ck-spacing-small);margin-bottom:var(--ck-spacing-small)}.ck .ck-balloon-rotator__navigation .ck-balloon-rotator__counter{margin-right:var(--ck-spacing-standard);margin-left:var(--ck-spacing-small)}.ck .ck-balloon-rotator__content .ck.ck-annotation-wrapper{box-shadow:none}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./fakepanel.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck .ck-fake-panel{position:absolute;z-index:calc(var(--ck-z-modal) - 1)}.ck .ck-fake-panel div{position:absolute}.ck .ck-fake-panel div:first-child{z-index:2}.ck .ck-fake-panel div:nth-child(2){z-index:1}:root{--ck-balloon-fake-panel-offset-horizontal:6px;--ck-balloon-fake-panel-offset-vertical:6px}.ck .ck-fake-panel div{box-shadow:var(--ck-drop-shadow),0 0;min-height:15px;background:var(--ck-color-panel-background);border:1px solid var(--ck-color-panel-border);border-radius:var(--ck-border-radius);width:100%;height:100%}.ck .ck-fake-panel div:first-child{margin-left:var(--ck-balloon-fake-panel-offset-horizontal);margin-top:var(--ck-balloon-fake-panel-offset-vertical)}.ck .ck-fake-panel div:nth-child(2){margin-left:calc(var(--ck-balloon-fake-panel-offset-horizontal)*2);margin-top:calc(var(--ck-balloon-fake-panel-offset-vertical)*2)}.ck .ck-fake-panel div:nth-child(3){margin-left:calc(var(--ck-balloon-fake-panel-offset-horizontal)*3);margin-top:calc(var(--ck-balloon-fake-panel-offset-vertical)*3)}.ck .ck-balloon-panel_arrow_s+.ck-fake-panel,.ck .ck-balloon-panel_arrow_se+.ck-fake-panel,.ck .ck-balloon-panel_arrow_sw+.ck-fake-panel{--ck-balloon-fake-panel-offset-vertical:-6px}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./imageuploadprogress.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-editor__editable .image{position:relative}.ck.ck-editor__editable .image .ck-progress-bar{position:absolute;top:0;left:0}.ck.ck-editor__editable .image.ck-appear{animation:fadeIn .7s}.ck.ck-editor__editable .image .ck-progress-bar{height:2px;width:0;background:var(--ck-color-upload-bar-background);transition:width .1s}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./imageuploadicon.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck-image-upload-complete-icon{display:block;position:absolute;top:10px;right:10px;border-radius:50%}.ck-image-upload-complete-icon:after{content:\\\"\\\";position:absolute}:root{--ck-color-image-upload-icon:#fff;--ck-color-image-upload-icon-background:#008a00;--ck-image-upload-icon-size:20px;--ck-image-upload-icon-width:2px}.ck-image-upload-complete-icon{width:var(--ck-image-upload-icon-size);height:var(--ck-image-upload-icon-size);opacity:0;background:var(--ck-color-image-upload-icon-background);animation-name:ck-upload-complete-icon-show,ck-upload-complete-icon-hide;animation-fill-mode:forwards,forwards;animation-duration:.5s,.5s;font-size:var(--ck-image-upload-icon-size);animation-delay:0ms,3s}.ck-image-upload-complete-icon:after{left:25%;top:50%;opacity:0;height:0;width:0;transform:scaleX(-1) rotate(135deg);transform-origin:left top;border-top:var(--ck-image-upload-icon-width) solid var(--ck-color-image-upload-icon);border-right:var(--ck-image-upload-icon-width) solid var(--ck-color-image-upload-icon);animation-name:ck-upload-complete-icon-check;animation-duration:.5s;animation-delay:.5s;animation-fill-mode:forwards;box-sizing:border-box}@keyframes ck-upload-complete-icon-show{0%{opacity:0}to{opacity:1}}@keyframes ck-upload-complete-icon-hide{0%{opacity:1}to{opacity:0}}@keyframes ck-upload-complete-icon-check{0%{opacity:1;width:0;height:0}33%{width:.3em;height:0}to{opacity:1;width:.3em;height:.45em}}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./imageuploadloader.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck .ck-upload-placeholder-loader{position:absolute;display:flex;align-items:center;justify-content:center;top:0;left:0}.ck .ck-upload-placeholder-loader:before{content:\\\"\\\";position:relative}:root{--ck-color-upload-placeholder-loader:#b3b3b3;--ck-upload-placeholder-loader-size:32px}.ck .ck-image-upload-placeholder{width:100%;margin:0}.ck .ck-upload-placeholder-loader{width:100%;height:100%}.ck .ck-upload-placeholder-loader:before{width:var(--ck-upload-placeholder-loader-size);height:var(--ck-upload-placeholder-loader-size);border-radius:50%;border-top:3px solid var(--ck-color-upload-placeholder-loader);border-right:2px solid transparent;animation:ck-upload-placeholder-loader 1s linear infinite}@keyframes ck-upload-placeholder-loader{to{transform:rotate(1turn)}}\"","module.exports = \".ck-content code{background-color:hsla(0,0%,78%,.3);padding:.15em;border-radius:2px}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./blockquote.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck-content blockquote{overflow:hidden;padding-right:1.5em;padding-left:1.5em;margin-left:0;margin-right:0;font-style:italic;border-left:5px solid #ccc}.ck-content[dir=rtl] blockquote{border-left:0;border-right:5px solid #ccc}\"","module.exports = \".ck.ck-heading_heading1{font-size:20px}.ck.ck-heading_heading2{font-size:17px}.ck.ck-heading_heading3{font-size:14px}.ck[class*=ck-heading_heading]{font-weight:700}.ck.ck-dropdown.ck-heading-dropdown .ck-dropdown__button .ck-button__label{width:8em}.ck.ck-dropdown.ck-heading-dropdown .ck-dropdown__panel .ck-list__item{min-width:18em}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./label.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-label{display:block}.ck.ck-voice-label{display:none}.ck.ck-label{font-weight:700}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./labeledinput.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-labeled-input .ck-labeled-input__status{font-size:var(--ck-font-size-small);margin-top:var(--ck-spacing-small);white-space:normal}.ck.ck-labeled-input .ck-labeled-input__status_error{color:var(--ck-color-base-error)}\"","var content = require(\"!!../../../../../postcss-loader/src/index.js??ref--5-1!./inputtext.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-input-text-width:18em}.ck.ck-input-text{border-radius:0}.ck-rounded-corners .ck.ck-input-text,.ck.ck-input-text.ck-rounded-corners{border-radius:var(--ck-border-radius)}.ck.ck-input-text{box-shadow:var(--ck-inner-shadow),0 0;background:var(--ck-color-input-background);border:1px solid var(--ck-color-input-border);padding:var(--ck-spacing-extra-tiny) var(--ck-spacing-medium);min-width:var(--ck-input-text-width);min-height:var(--ck-ui-component-min-height);transition-property:box-shadow,border;transition:.2s ease-in-out}.ck.ck-input-text:focus{outline:none;border:var(--ck-focus-ring);box-shadow:var(--ck-focus-outer-shadow),var(--ck-inner-shadow)}.ck.ck-input-text[readonly]{border:1px solid var(--ck-color-input-disabled-border);background:var(--ck-color-input-disabled-background);color:var(--ck-color-input-disabled-text)}.ck.ck-input-text[readonly]:focus{box-shadow:var(--ck-focus-disabled-outer-shadow),var(--ck-inner-shadow)}.ck.ck-input-text.ck-error{border-color:var(--ck-color-input-error-border);animation:ck-text-input-shake .3s ease both}.ck.ck-input-text.ck-error:focus{box-shadow:var(--ck-focus-error-outer-shadow),var(--ck-inner-shadow)}@keyframes ck-text-input-shake{20%{transform:translateX(-2px)}40%{transform:translateX(2px)}60%{transform:translateX(-1px)}80%{transform:translateX(1px)}}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./textalternativeform.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-text-alternative-form{display:flex;flex-direction:row;flex-wrap:nowrap}.ck.ck-text-alternative-form .ck-labeled-input{display:inline-block}.ck.ck-text-alternative-form .ck-label{display:none}@media screen and (max-width:600px){.ck.ck-text-alternative-form{flex-wrap:wrap}.ck.ck-text-alternative-form .ck-labeled-input{flex-basis:100%}.ck.ck-text-alternative-form .ck-button{flex-basis:50%}}.ck.ck-text-alternative-form{padding:var(--ck-spacing-standard)}.ck.ck-text-alternative-form:focus{outline:none}[dir=ltr] .ck.ck-text-alternative-form>:not(:first-child),[dir=rtl] .ck.ck-text-alternative-form>:not(:last-child){margin-left:var(--ck-spacing-standard)}@media screen and (max-width:600px){.ck.ck-text-alternative-form{padding:0;width:calc(0.8*var(--ck-input-text-width))}.ck.ck-text-alternative-form .ck-labeled-input{margin:var(--ck-spacing-standard) var(--ck-spacing-standard) 0}.ck.ck-text-alternative-form .ck-labeled-input .ck-input-text{min-width:0;width:100%}.ck.ck-text-alternative-form .ck-button{padding:var(--ck-spacing-standard);margin-top:var(--ck-spacing-standard);border-radius:0;border:0;border-top:1px solid var(--ck-color-base-border)}[dir=ltr] .ck.ck-text-alternative-form .ck-button{margin-left:0}[dir=ltr] .ck.ck-text-alternative-form .ck-button:first-of-type{border-right:1px solid var(--ck-color-base-border)}[dir=rtl] .ck.ck-text-alternative-form .ck-button{margin-left:0}[dir=rtl] .ck.ck-text-alternative-form .ck-button:last-of-type{border-right:1px solid var(--ck-color-base-border)}}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./image.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck-content .image{display:table;clear:both;text-align:center;margin:1em auto}.ck-content .image>img{display:block;margin:0 auto;max-width:100%;min-width:50px}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./imagecaption.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck-content .image>figcaption{display:table-caption;caption-side:bottom;word-break:break-word;color:#333;background-color:#f7f7f7;padding:.6em;font-size:.75em;outline-offset:-1px}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./imagestyle.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-image-style-spacing:1.5em}.ck-content .image-style-align-center,.ck-content .image-style-align-left,.ck-content .image-style-align-right,.ck-content .image-style-side{max-width:50%}.ck-content .image-style-side{float:right;margin-left:var(--ck-image-style-spacing)}.ck-content .image-style-align-left{float:left;margin-right:var(--ck-image-style-spacing)}.ck-content .image-style-align-center{margin-left:auto;margin-right:auto}.ck-content .image-style-align-right{float:right;margin-left:var(--ck-image-style-spacing)}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./link.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck .ck-link_selected{background:var(--ck-color-link-selected-background)}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./linkform.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-link-form{display:flex}.ck.ck-link-form .ck-label{display:none}@media screen and (max-width:600px){.ck.ck-link-form{flex-wrap:wrap}.ck.ck-link-form .ck-labeled-input{flex-basis:100%}.ck.ck-link-form .ck-button{flex-basis:50%}}.ck.ck-link-form_layout-vertical{display:block}.ck.ck-link-form{padding:var(--ck-spacing-standard)}.ck.ck-link-form:focus{outline:none}[dir=ltr] .ck.ck-link-form>:not(:first-child),[dir=rtl] .ck.ck-link-form>:not(:last-child){margin-left:var(--ck-spacing-standard)}@media screen and (max-width:600px){.ck.ck-link-form{padding:0;width:calc(0.8*var(--ck-input-text-width))}.ck.ck-link-form .ck-labeled-input{margin:var(--ck-spacing-standard) var(--ck-spacing-standard) 0}.ck.ck-link-form .ck-labeled-input .ck-input-text{min-width:0;width:100%}.ck.ck-link-form .ck-button{padding:var(--ck-spacing-standard);margin-top:var(--ck-spacing-standard);border-radius:0;border:0;border-top:1px solid var(--ck-color-base-border)}[dir=ltr] .ck.ck-link-form .ck-button{margin-left:0}[dir=ltr] .ck.ck-link-form .ck-button:first-of-type{border-right:1px solid var(--ck-color-base-border)}[dir=rtl] .ck.ck-link-form .ck-button{margin-left:0}[dir=rtl] .ck.ck-link-form .ck-button:last-of-type{border-right:1px solid var(--ck-color-base-border)}}.ck.ck-link-form_layout-vertical{padding:0;min-width:var(--ck-input-text-width)}.ck.ck-link-form_layout-vertical .ck-labeled-input{margin:var(--ck-spacing-standard) var(--ck-spacing-standard) var(--ck-spacing-small)}.ck.ck-link-form_layout-vertical .ck-labeled-input .ck-input-text{min-width:0;width:100%}.ck.ck-link-form_layout-vertical .ck-button{padding:var(--ck-spacing-standard);margin:0;border-radius:0;border:0;border-top:1px solid var(--ck-color-base-border);width:50%}[dir=ltr] .ck.ck-link-form_layout-vertical .ck-button{margin-left:0}[dir=ltr] .ck.ck-link-form_layout-vertical .ck-button:first-of-type{border-right:1px solid var(--ck-color-base-border)}[dir=rtl] .ck.ck-link-form_layout-vertical .ck-button{margin-left:0}[dir=rtl] .ck.ck-link-form_layout-vertical .ck-button:last-of-type{border-right:1px solid var(--ck-color-base-border)}.ck.ck-link-form_layout-vertical .ck.ck-list{margin-left:0}.ck.ck-link-form_layout-vertical .ck.ck-list .ck-button.ck-switchbutton{border:0;width:100%}.ck.ck-link-form_layout-vertical .ck.ck-list .ck-button.ck-switchbutton:hover{background:none}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./linkactions.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck.ck-link-actions{display:flex;flex-direction:row;flex-wrap:nowrap}.ck.ck-link-actions .ck-link-actions__preview{display:inline-block}.ck.ck-link-actions .ck-link-actions__preview .ck-button__label{overflow:hidden}@media screen and (max-width:600px){.ck.ck-link-actions{flex-wrap:wrap}.ck.ck-link-actions .ck-link-actions__preview{flex-basis:100%}.ck.ck-link-actions .ck-button:not(.ck-link-actions__preview){flex-basis:50%}}.ck.ck-link-actions{padding:var(--ck-spacing-standard)}.ck.ck-link-actions .ck-button.ck-link-actions__preview{padding-left:0;padding-right:0}.ck.ck-link-actions .ck-button.ck-link-actions__preview,.ck.ck-link-actions .ck-button.ck-link-actions__preview:active,.ck.ck-link-actions .ck-button.ck-link-actions__preview:focus,.ck.ck-link-actions .ck-button.ck-link-actions__preview:hover{background:none}.ck.ck-link-actions .ck-button.ck-link-actions__preview:active{box-shadow:none}.ck.ck-link-actions .ck-button.ck-link-actions__preview:focus .ck-button__label{text-decoration:underline}.ck.ck-link-actions .ck-button.ck-link-actions__preview .ck-button__label{padding:0 var(--ck-spacing-medium);color:var(--ck-color-link-default);text-overflow:ellipsis;cursor:pointer;max-width:var(--ck-input-text-width);min-width:3em;text-align:center}.ck.ck-link-actions .ck-button.ck-link-actions__preview .ck-button__label:hover{text-decoration:underline}.ck.ck-link-actions:focus{outline:none}[dir=ltr] .ck.ck-link-actions .ck-button:not(:first-child),[dir=rtl] .ck.ck-link-actions .ck-button:not(:last-child){margin-left:var(--ck-spacing-standard)}@media screen and (max-width:600px){.ck.ck-link-actions{padding:0;width:calc(0.8*var(--ck-input-text-width))}.ck.ck-link-actions .ck-button.ck-link-actions__preview{margin:var(--ck-spacing-standard) var(--ck-spacing-standard) 0}.ck.ck-link-actions .ck-button.ck-link-actions__preview .ck-button__label{min-width:0;max-width:100%}.ck.ck-link-actions .ck-button:not(.ck-link-actions__preview){padding:var(--ck-spacing-standard);margin-top:var(--ck-spacing-standard);border-radius:0;border:0;border-top:1px solid var(--ck-color-base-border)}[dir=ltr] .ck.ck-link-actions .ck-button:not(.ck-link-actions__preview){margin-left:0}[dir=ltr] .ck.ck-link-actions .ck-button:not(.ck-link-actions__preview):first-of-type{border-right:1px solid var(--ck-color-base-border)}[dir=rtl] .ck.ck-link-actions .ck-button:not(.ck-link-actions__preview){margin-left:0}[dir=rtl] .ck.ck-link-actions .ck-button:not(.ck-link-actions__preview):last-of-type{border-right:1px solid var(--ck-color-base-border)}}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./tableediting.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-color-table-focused-cell-background:#f5fafe}.ck-widget.table td.ck-editor__nested-editable.ck-editor__nested-editable_focused,.ck-widget.table th.ck-editor__nested-editable.ck-editor__nested-editable_focused{background:var(--ck-color-table-focused-cell-background);border-style:none;outline:1px solid var(--ck-color-focus-border);outline-offset:-1px}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./inserttable.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-insert-table-dropdown-padding:10px;--ck-insert-table-dropdown-box-height:11px;--ck-insert-table-dropdown-box-width:12px;--ck-insert-table-dropdown-box-margin:1px;--ck-insert-table-dropdown-box-border-color:#bfbfbf;--ck-insert-table-dropdown-box-border-active-color:#53a0e4;--ck-insert-table-dropdown-box-active-background:#c7e5ff}.ck .ck-insert-table-dropdown__grid{display:flex;flex-direction:row;flex-wrap:wrap;width:calc(var(--ck-insert-table-dropdown-box-width)*10 + var(--ck-insert-table-dropdown-box-margin)*20 + var(--ck-insert-table-dropdown-padding)*2);padding:var(--ck-insert-table-dropdown-padding) var(--ck-insert-table-dropdown-padding) 0}.ck .ck-insert-table-dropdown__label{text-align:center}.ck .ck-insert-table-dropdown-grid-box{width:var(--ck-insert-table-dropdown-box-width);height:var(--ck-insert-table-dropdown-box-height);margin:var(--ck-insert-table-dropdown-box-margin);border:1px solid var(--ck-insert-table-dropdown-box-border-color);border-radius:1px}.ck .ck-insert-table-dropdown-grid-box.ck-on{border-color:var(--ck-insert-table-dropdown-box-border-active-color);background:var(--ck-insert-table-dropdown-box-active-background)}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./table.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \".ck-content .table{margin:1em auto;display:table}.ck-content .table table{border-collapse:collapse;border-spacing:0;border:1px double #b3b3b3}.ck-content .table table td,.ck-content .table table th{min-width:2em;padding:.4em;border-color:#d9d9d9}.ck-content .table table th{font-weight:700;background:#fafafa}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./todolist.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-todo-list-checkmark-size:16px}.ck-editor__editable .todo-list .todo-list__label>input{cursor:pointer}.ck-editor__editable .todo-list .todo-list__label>input:hover:before{box-shadow:0 0 0 5px rgba(0,0,0,.1)}.ck-content .todo-list{list-style:none}.ck-content .todo-list li{margin-bottom:5px}.ck-content .todo-list li .todo-list{margin-top:5px}.ck-content .todo-list .todo-list__label>input{-webkit-appearance:none;display:inline-block;position:relative;width:var(--ck-todo-list-checkmark-size);height:var(--ck-todo-list-checkmark-size);vertical-align:middle;border:0;left:-25px;margin-right:-15px;right:0;margin-left:0}.ck-content .todo-list .todo-list__label>input:before{display:block;position:absolute;box-sizing:border-box;content:\\\"\\\";width:100%;height:100%;border:1px solid #333;border-radius:2px;transition:box-shadow .25s ease-in-out,background .25s ease-in-out,border .25s ease-in-out}.ck-content .todo-list .todo-list__label>input:after{display:block;position:absolute;box-sizing:content-box;pointer-events:none;content:\\\"\\\";left:calc(var(--ck-todo-list-checkmark-size)/3);top:calc(var(--ck-todo-list-checkmark-size)/5.3);width:calc(var(--ck-todo-list-checkmark-size)/5.3);height:calc(var(--ck-todo-list-checkmark-size)/2.6);border-left:0 solid transparent;border-bottom:calc(var(--ck-todo-list-checkmark-size)/8) solid transparent;border-right:calc(var(--ck-todo-list-checkmark-size)/8) solid transparent;border-top:0 solid transparent;transform:rotate(45deg)}.ck-content .todo-list .todo-list__label>input[checked]:before{background:#26ab33;border-color:#26ab33}.ck-content .todo-list .todo-list__label>input[checked]:after{border-color:#fff}.ck-content .todo-list .todo-list__label .todo-list__label__description{vertical-align:middle}[dir=rtl] .todo-list .todo-list__label>input{left:0;margin-right:0;right:-25px;margin-left:-15px}\"","'use strict';\n\n\nmodule.exports = require('./lib/');\n","// Main parser class\n\n'use strict';\n\n\nvar utils = require('./common/utils');\nvar helpers = require('./helpers');\nvar Renderer = require('./renderer');\nvar ParserCore = require('./parser_core');\nvar ParserBlock = require('./parser_block');\nvar ParserInline = require('./parser_inline');\nvar LinkifyIt = require('linkify-it');\nvar mdurl = require('mdurl');\nvar punycode = require('punycode');\n\n\nvar config = {\n 'default': require('./presets/default'),\n zero: require('./presets/zero'),\n commonmark: require('./presets/commonmark')\n};\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// This validator can prohibit more than really needed to prevent XSS. It's a\n// tradeoff to keep code simple and to be secure by default.\n//\n// If you need different setup - override validator method as you wish. Or\n// replace it with dummy function and use external sanitizer.\n//\n\nvar BAD_PROTO_RE = /^(vbscript|javascript|file|data):/;\nvar GOOD_DATA_RE = /^data:image\\/(gif|png|jpeg|webp);/;\n\nfunction validateLink(url) {\n // url should be normalized at this point, and existing entities are decoded\n var str = url.trim().toLowerCase();\n\n return BAD_PROTO_RE.test(str) ? (GOOD_DATA_RE.test(str) ? true : false) : true;\n}\n\n////////////////////////////////////////////////////////////////////////////////\n\n\nvar RECODE_HOSTNAME_FOR = [ 'http:', 'https:', 'mailto:' ];\n\nfunction normalizeLink(url) {\n var parsed = mdurl.parse(url, true);\n\n if (parsed.hostname) {\n // Encode hostnames in urls like:\n // `http://host/`, `https://host/`, `mailto:user@host`, `//host/`\n //\n // We don't encode unknown schemas, because it's likely that we encode\n // something we shouldn't (e.g. `skype:name` treated as `skype:host`)\n //\n if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {\n try {\n parsed.hostname = punycode.toASCII(parsed.hostname);\n } catch (er) { /**/ }\n }\n }\n\n return mdurl.encode(mdurl.format(parsed));\n}\n\nfunction normalizeLinkText(url) {\n var parsed = mdurl.parse(url, true);\n\n if (parsed.hostname) {\n // Encode hostnames in urls like:\n // `http://host/`, `https://host/`, `mailto:user@host`, `//host/`\n //\n // We don't encode unknown schemas, because it's likely that we encode\n // something we shouldn't (e.g. `skype:name` treated as `skype:host`)\n //\n if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {\n try {\n parsed.hostname = punycode.toUnicode(parsed.hostname);\n } catch (er) { /**/ }\n }\n }\n\n return mdurl.decode(mdurl.format(parsed));\n}\n\n\n/**\n * class MarkdownIt\n *\n * Main parser/renderer class.\n *\n * ##### Usage\n *\n * ```javascript\n * // node.js, \"classic\" way:\n * var MarkdownIt = require('markdown-it'),\n * md = new MarkdownIt();\n * var result = md.render('# markdown-it rulezz!');\n *\n * // node.js, the same, but with sugar:\n * var md = require('markdown-it')();\n * var result = md.render('# markdown-it rulezz!');\n *\n * // browser without AMD, added to \"window\" on script load\n * // Note, there are no dash.\n * var md = window.markdownit();\n * var result = md.render('# markdown-it rulezz!');\n * ```\n *\n * Single line rendering, without paragraph wrap:\n *\n * ```javascript\n * var md = require('markdown-it')();\n * var result = md.renderInline('__markdown-it__ rulezz!');\n * ```\n **/\n\n/**\n * new MarkdownIt([presetName, options])\n * - presetName (String): optional, `commonmark` / `zero`\n * - options (Object)\n *\n * Creates parser instanse with given config. Can be called without `new`.\n *\n * ##### presetName\n *\n * MarkdownIt provides named presets as a convenience to quickly\n * enable/disable active syntax rules and options for common use cases.\n *\n * - [\"commonmark\"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.js) -\n * configures parser to strict [CommonMark](http://commonmark.org/) mode.\n * - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.js) -\n * similar to GFM, used when no preset name given. Enables all available rules,\n * but still without html, typographer & autolinker.\n * - [\"zero\"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js) -\n * all rules disabled. Useful to quickly setup your config via `.enable()`.\n * For example, when you need only `bold` and `italic` markup and nothing else.\n *\n * ##### options:\n *\n * - __html__ - `false`. Set `true` to enable HTML tags in source. Be careful!\n * That's not safe! You may need external sanitizer to protect output from XSS.\n * It's better to extend features via plugins, instead of enabling HTML.\n * - __xhtmlOut__ - `false`. Set `true` to add '/' when closing single tags\n * (`<br />`). This is needed only for full CommonMark compatibility. In real\n * world you will need HTML output.\n * - __breaks__ - `false`. Set `true` to convert `\\n` in paragraphs into `<br>`.\n * - __langPrefix__ - `language-`. CSS language class prefix for fenced blocks.\n * Can be useful for external highlighters.\n * - __linkify__ - `false`. Set `true` to autoconvert URL-like text to links.\n * - __typographer__ - `false`. Set `true` to enable [some language-neutral\n * replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) +\n * quotes beautification (smartquotes).\n * - __quotes__ - `“”‘’`, String or Array. Double + single quotes replacement\n * pairs, when typographer enabled and smartquotes on. For example, you can\n * use `'«»„“'` for Russian, `'„“‚‘'` for German, and\n * `['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›']` for French (including nbsp).\n * - __highlight__ - `null`. Highlighter function for fenced code blocks.\n * Highlighter `function (str, lang)` should return escaped HTML. It can also\n * return empty string if the source was not changed and should be escaped\n * externaly. If result starts with <pre... internal wrapper is skipped.\n *\n * ##### Example\n *\n * ```javascript\n * // commonmark mode\n * var md = require('markdown-it')('commonmark');\n *\n * // default mode\n * var md = require('markdown-it')();\n *\n * // enable everything\n * var md = require('markdown-it')({\n * html: true,\n * linkify: true,\n * typographer: true\n * });\n * ```\n *\n * ##### Syntax highlighting\n *\n * ```js\n * var hljs = require('highlight.js') // https://highlightjs.org/\n *\n * var md = require('markdown-it')({\n * highlight: function (str, lang) {\n * if (lang && hljs.getLanguage(lang)) {\n * try {\n * return hljs.highlight(lang, str, true).value;\n * } catch (__) {}\n * }\n *\n * return ''; // use external default escaping\n * }\n * });\n * ```\n *\n * Or with full wrapper override (if you need assign class to `<pre>`):\n *\n * ```javascript\n * var hljs = require('highlight.js') // https://highlightjs.org/\n *\n * // Actual default values\n * var md = require('markdown-it')({\n * highlight: function (str, lang) {\n * if (lang && hljs.getLanguage(lang)) {\n * try {\n * return '<pre class=\"hljs\"><code>' +\n * hljs.highlight(lang, str, true).value +\n * '</code></pre>';\n * } catch (__) {}\n * }\n *\n * return '<pre class=\"hljs\"><code>' + md.utils.escapeHtml(str) + '</code></pre>';\n * }\n * });\n * ```\n *\n **/\nfunction MarkdownIt(presetName, options) {\n if (!(this instanceof MarkdownIt)) {\n return new MarkdownIt(presetName, options);\n }\n\n if (!options) {\n if (!utils.isString(presetName)) {\n options = presetName || {};\n presetName = 'default';\n }\n }\n\n /**\n * MarkdownIt#inline -> ParserInline\n *\n * Instance of [[ParserInline]]. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n this.inline = new ParserInline();\n\n /**\n * MarkdownIt#block -> ParserBlock\n *\n * Instance of [[ParserBlock]]. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n this.block = new ParserBlock();\n\n /**\n * MarkdownIt#core -> Core\n *\n * Instance of [[Core]] chain executor. You may need it to add new rules when\n * writing plugins. For simple rules control use [[MarkdownIt.disable]] and\n * [[MarkdownIt.enable]].\n **/\n this.core = new ParserCore();\n\n /**\n * MarkdownIt#renderer -> Renderer\n *\n * Instance of [[Renderer]]. Use it to modify output look. Or to add rendering\n * rules for new token types, generated by plugins.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * function myToken(tokens, idx, options, env, self) {\n * //...\n * return result;\n * };\n *\n * md.renderer.rules['my_token'] = myToken\n * ```\n *\n * See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).\n **/\n this.renderer = new Renderer();\n\n /**\n * MarkdownIt#linkify -> LinkifyIt\n *\n * [linkify-it](https://github.com/markdown-it/linkify-it) instance.\n * Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.js)\n * rule.\n **/\n this.linkify = new LinkifyIt();\n\n /**\n * MarkdownIt#validateLink(url) -> Boolean\n *\n * Link validation function. CommonMark allows too much in links. By default\n * we disable `javascript:`, `vbscript:`, `file:` schemas, and almost all `data:...` schemas\n * except some embedded image types.\n *\n * You can change this behaviour:\n *\n * ```javascript\n * var md = require('markdown-it')();\n * // enable everything\n * md.validateLink = function () { return true; }\n * ```\n **/\n this.validateLink = validateLink;\n\n /**\n * MarkdownIt#normalizeLink(url) -> String\n *\n * Function used to encode link url to a machine-readable format,\n * which includes url-encoding, punycode, etc.\n **/\n this.normalizeLink = normalizeLink;\n\n /**\n * MarkdownIt#normalizeLinkText(url) -> String\n *\n * Function used to decode link url to a human-readable format`\n **/\n this.normalizeLinkText = normalizeLinkText;\n\n\n // Expose utils & helpers for easy acces from plugins\n\n /**\n * MarkdownIt#utils -> utils\n *\n * Assorted utility functions, useful to write plugins. See details\n * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js).\n **/\n this.utils = utils;\n\n /**\n * MarkdownIt#helpers -> helpers\n *\n * Link components parser functions, useful to write plugins. See details\n * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers).\n **/\n this.helpers = utils.assign({}, helpers);\n\n\n this.options = {};\n this.configure(presetName);\n\n if (options) { this.set(options); }\n}\n\n\n/** chainable\n * MarkdownIt.set(options)\n *\n * Set parser options (in the same format as in constructor). Probably, you\n * will never need it, but you can change options after constructor call.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')()\n * .set({ html: true, breaks: true })\n * .set({ typographer, true });\n * ```\n *\n * __Note:__ To achieve the best possible performance, don't modify a\n * `markdown-it` instance options on the fly. If you need multiple configurations\n * it's best to create multiple instances and initialize each with separate\n * config.\n **/\nMarkdownIt.prototype.set = function (options) {\n utils.assign(this.options, options);\n return this;\n};\n\n\n/** chainable, internal\n * MarkdownIt.configure(presets)\n *\n * Batch load of all options and compenent settings. This is internal method,\n * and you probably will not need it. But if you with - see available presets\n * and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)\n *\n * We strongly recommend to use presets instead of direct config loads. That\n * will give better compatibility with next versions.\n **/\nMarkdownIt.prototype.configure = function (presets) {\n var self = this, presetName;\n\n if (utils.isString(presets)) {\n presetName = presets;\n presets = config[presetName];\n if (!presets) { throw new Error('Wrong `markdown-it` preset \"' + presetName + '\", check name'); }\n }\n\n if (!presets) { throw new Error('Wrong `markdown-it` preset, can\\'t be empty'); }\n\n if (presets.options) { self.set(presets.options); }\n\n if (presets.components) {\n Object.keys(presets.components).forEach(function (name) {\n if (presets.components[name].rules) {\n self[name].ruler.enableOnly(presets.components[name].rules);\n }\n if (presets.components[name].rules2) {\n self[name].ruler2.enableOnly(presets.components[name].rules2);\n }\n });\n }\n return this;\n};\n\n\n/** chainable\n * MarkdownIt.enable(list, ignoreInvalid)\n * - list (String|Array): rule name or list of rule names to enable\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * Enable list or rules. It will automatically find appropriate components,\n * containing rules with given names. If rule not found, and `ignoreInvalid`\n * not set - throws exception.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')()\n * .enable(['sub', 'sup'])\n * .disable('smartquotes');\n * ```\n **/\nMarkdownIt.prototype.enable = function (list, ignoreInvalid) {\n var result = [];\n\n if (!Array.isArray(list)) { list = [ list ]; }\n\n [ 'core', 'block', 'inline' ].forEach(function (chain) {\n result = result.concat(this[chain].ruler.enable(list, true));\n }, this);\n\n result = result.concat(this.inline.ruler2.enable(list, true));\n\n var missed = list.filter(function (name) { return result.indexOf(name) < 0; });\n\n if (missed.length && !ignoreInvalid) {\n throw new Error('MarkdownIt. Failed to enable unknown rule(s): ' + missed);\n }\n\n return this;\n};\n\n\n/** chainable\n * MarkdownIt.disable(list, ignoreInvalid)\n * - list (String|Array): rule name or list of rule names to disable.\n * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.\n *\n * The same as [[MarkdownIt.enable]], but turn specified rules off.\n **/\nMarkdownIt.prototype.disable = function (list, ignoreInvalid) {\n var result = [];\n\n if (!Array.isArray(list)) { list = [ list ]; }\n\n [ 'core', 'block', 'inline' ].forEach(function (chain) {\n result = result.concat(this[chain].ruler.disable(list, true));\n }, this);\n\n result = result.concat(this.inline.ruler2.disable(list, true));\n\n var missed = list.filter(function (name) { return result.indexOf(name) < 0; });\n\n if (missed.length && !ignoreInvalid) {\n throw new Error('MarkdownIt. Failed to disable unknown rule(s): ' + missed);\n }\n return this;\n};\n\n\n/** chainable\n * MarkdownIt.use(plugin, params)\n *\n * Load specified plugin with given params into current parser instance.\n * It's just a sugar to call `plugin(md, params)` with curring.\n *\n * ##### Example\n *\n * ```javascript\n * var iterator = require('markdown-it-for-inline');\n * var md = require('markdown-it')()\n * .use(iterator, 'foo_replace', 'text', function (tokens, idx) {\n * tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar');\n * });\n * ```\n **/\nMarkdownIt.prototype.use = function (plugin /*, params, ... */) {\n var args = [ this ].concat(Array.prototype.slice.call(arguments, 1));\n plugin.apply(plugin, args);\n return this;\n};\n\n\n/** internal\n * MarkdownIt.parse(src, env) -> Array\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Parse input string and returns list of block tokens (special token type\n * \"inline\" will contain list of inline tokens). You should not call this\n * method directly, until you write custom renderer (for example, to produce\n * AST).\n *\n * `env` is used to pass data between \"distributed\" rules and return additional\n * metadata like reference info, needed for the renderer. It also can be used to\n * inject data in specific cases. Usually, you will be ok to pass `{}`,\n * and then pass updated object to renderer.\n **/\nMarkdownIt.prototype.parse = function (src, env) {\n if (typeof src !== 'string') {\n throw new Error('Input data should be a String');\n }\n\n var state = new this.core.State(src, this, env);\n\n this.core.process(state);\n\n return state.tokens;\n};\n\n\n/**\n * MarkdownIt.render(src [, env]) -> String\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Render markdown string into html. It does all magic for you :).\n *\n * `env` can be used to inject additional metadata (`{}` by default).\n * But you will not need it with high probability. See also comment\n * in [[MarkdownIt.parse]].\n **/\nMarkdownIt.prototype.render = function (src, env) {\n env = env || {};\n\n return this.renderer.render(this.parse(src, env), this.options, env);\n};\n\n\n/** internal\n * MarkdownIt.parseInline(src, env) -> Array\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * The same as [[MarkdownIt.parse]] but skip all block rules. It returns the\n * block tokens list with the single `inline` element, containing parsed inline\n * tokens in `children` property. Also updates `env` object.\n **/\nMarkdownIt.prototype.parseInline = function (src, env) {\n var state = new this.core.State(src, this, env);\n\n state.inlineMode = true;\n this.core.process(state);\n\n return state.tokens;\n};\n\n\n/**\n * MarkdownIt.renderInline(src [, env]) -> String\n * - src (String): source string\n * - env (Object): environment sandbox\n *\n * Similar to [[MarkdownIt.render]] but for single paragraph content. Result\n * will NOT be wrapped into `<p>` tags.\n **/\nMarkdownIt.prototype.renderInline = function (src, env) {\n env = env || {};\n\n return this.renderer.render(this.parseInline(src, env), this.options, env);\n};\n\n\nmodule.exports = MarkdownIt;\n","\n'use strict';\n\n\nvar encodeCache = {};\n\n\n// Create a lookup array where anything but characters in `chars` string\n// and alphanumeric chars is percent-encoded.\n//\nfunction getEncodeCache(exclude) {\n var i, ch, cache = encodeCache[exclude];\n if (cache) { return cache; }\n\n cache = encodeCache[exclude] = [];\n\n for (i = 0; i < 128; i++) {\n ch = String.fromCharCode(i);\n\n if (/^[0-9a-z]$/i.test(ch)) {\n // always allow unencoded alphanumeric characters\n cache.push(ch);\n } else {\n cache.push('%' + ('0' + i.toString(16).toUpperCase()).slice(-2));\n }\n }\n\n for (i = 0; i < exclude.length; i++) {\n cache[exclude.charCodeAt(i)] = exclude[i];\n }\n\n return cache;\n}\n\n\n// Encode unsafe characters with percent-encoding, skipping already\n// encoded sequences.\n//\n// - string - string to encode\n// - exclude - list of characters to ignore (in addition to a-zA-Z0-9)\n// - keepEscaped - don't encode '%' in a correct escape sequence (default: true)\n//\nfunction encode(string, exclude, keepEscaped) {\n var i, l, code, nextCode, cache,\n result = '';\n\n if (typeof exclude !== 'string') {\n // encode(string, keepEscaped)\n keepEscaped = exclude;\n exclude = encode.defaultChars;\n }\n\n if (typeof keepEscaped === 'undefined') {\n keepEscaped = true;\n }\n\n cache = getEncodeCache(exclude);\n\n for (i = 0, l = string.length; i < l; i++) {\n code = string.charCodeAt(i);\n\n if (keepEscaped && code === 0x25 /* % */ && i + 2 < l) {\n if (/^[0-9a-f]{2}$/i.test(string.slice(i + 1, i + 3))) {\n result += string.slice(i, i + 3);\n i += 2;\n continue;\n }\n }\n\n if (code < 128) {\n result += cache[code];\n continue;\n }\n\n if (code >= 0xD800 && code <= 0xDFFF) {\n if (code >= 0xD800 && code <= 0xDBFF && i + 1 < l) {\n nextCode = string.charCodeAt(i + 1);\n if (nextCode >= 0xDC00 && nextCode <= 0xDFFF) {\n result += encodeURIComponent(string[i] + string[i + 1]);\n i++;\n continue;\n }\n }\n result += '%EF%BF%BD';\n continue;\n }\n\n result += encodeURIComponent(string[i]);\n }\n\n return result;\n}\n\nencode.defaultChars = \";/?:@&=+$,-_.!~*'()#\";\nencode.componentChars = \"-_.!~*'()\";\n\n\nmodule.exports = encode;\n","\n'use strict';\n\n\n/* eslint-disable no-bitwise */\n\nvar decodeCache = {};\n\nfunction getDecodeCache(exclude) {\n var i, ch, cache = decodeCache[exclude];\n if (cache) { return cache; }\n\n cache = decodeCache[exclude] = [];\n\n for (i = 0; i < 128; i++) {\n ch = String.fromCharCode(i);\n cache.push(ch);\n }\n\n for (i = 0; i < exclude.length; i++) {\n ch = exclude.charCodeAt(i);\n cache[ch] = '%' + ('0' + ch.toString(16).toUpperCase()).slice(-2);\n }\n\n return cache;\n}\n\n\n// Decode percent-encoded string.\n//\nfunction decode(string, exclude) {\n var cache;\n\n if (typeof exclude !== 'string') {\n exclude = decode.defaultChars;\n }\n\n cache = getDecodeCache(exclude);\n\n return string.replace(/(%[a-f0-9]{2})+/gi, function(seq) {\n var i, l, b1, b2, b3, b4, chr,\n result = '';\n\n for (i = 0, l = seq.length; i < l; i += 3) {\n b1 = parseInt(seq.slice(i + 1, i + 3), 16);\n\n if (b1 < 0x80) {\n result += cache[b1];\n continue;\n }\n\n if ((b1 & 0xE0) === 0xC0 && (i + 3 < l)) {\n // 110xxxxx 10xxxxxx\n b2 = parseInt(seq.slice(i + 4, i + 6), 16);\n\n if ((b2 & 0xC0) === 0x80) {\n chr = ((b1 << 6) & 0x7C0) | (b2 & 0x3F);\n\n if (chr < 0x80) {\n result += '\\ufffd\\ufffd';\n } else {\n result += String.fromCharCode(chr);\n }\n\n i += 3;\n continue;\n }\n }\n\n if ((b1 & 0xF0) === 0xE0 && (i + 6 < l)) {\n // 1110xxxx 10xxxxxx 10xxxxxx\n b2 = parseInt(seq.slice(i + 4, i + 6), 16);\n b3 = parseInt(seq.slice(i + 7, i + 9), 16);\n\n if ((b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {\n chr = ((b1 << 12) & 0xF000) | ((b2 << 6) & 0xFC0) | (b3 & 0x3F);\n\n if (chr < 0x800 || (chr >= 0xD800 && chr <= 0xDFFF)) {\n result += '\\ufffd\\ufffd\\ufffd';\n } else {\n result += String.fromCharCode(chr);\n }\n\n i += 6;\n continue;\n }\n }\n\n if ((b1 & 0xF8) === 0xF0 && (i + 9 < l)) {\n // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx\n b2 = parseInt(seq.slice(i + 4, i + 6), 16);\n b3 = parseInt(seq.slice(i + 7, i + 9), 16);\n b4 = parseInt(seq.slice(i + 10, i + 12), 16);\n\n if ((b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80 && (b4 & 0xC0) === 0x80) {\n chr = ((b1 << 18) & 0x1C0000) | ((b2 << 12) & 0x3F000) | ((b3 << 6) & 0xFC0) | (b4 & 0x3F);\n\n if (chr < 0x10000 || chr > 0x10FFFF) {\n result += '\\ufffd\\ufffd\\ufffd\\ufffd';\n } else {\n chr -= 0x10000;\n result += String.fromCharCode(0xD800 + (chr >> 10), 0xDC00 + (chr & 0x3FF));\n }\n\n i += 9;\n continue;\n }\n }\n\n result += '\\ufffd';\n }\n\n return result;\n });\n}\n\n\ndecode.defaultChars = ';/?:@&=+$,#';\ndecode.componentChars = '';\n\n\nmodule.exports = decode;\n","\n'use strict';\n\n\nmodule.exports = function format(url) {\n var result = '';\n\n result += url.protocol || '';\n result += url.slashes ? '//' : '';\n result += url.auth ? url.auth + '@' : '';\n\n if (url.hostname && url.hostname.indexOf(':') !== -1) {\n // ipv6 address\n result += '[' + url.hostname + ']';\n } else {\n result += url.hostname || '';\n }\n\n result += url.port ? ':' + url.port : '';\n result += url.pathname || '';\n result += url.search || '';\n result += url.hash || '';\n\n return result;\n};\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n'use strict';\n\n//\n// Changes from joyent/node:\n//\n// 1. No leading slash in paths,\n// e.g. in `url.parse('http://foo?bar')` pathname is ``, not `/`\n//\n// 2. Backslashes are not replaced with slashes,\n// so `http:\\\\example.org\\` is treated like a relative path\n//\n// 3. Trailing colon is treated like a part of the path,\n// i.e. in `http://example.org:foo` pathname is `:foo`\n//\n// 4. Nothing is URL-encoded in the resulting object,\n// (in joyent/node some chars in auth and paths are encoded)\n//\n// 5. `url.parse()` does not have `parseQueryString` argument\n//\n// 6. Removed extraneous result properties: `host`, `path`, `query`, etc.,\n// which can be constructed using other parts of the url.\n//\n\n\nfunction Url() {\n this.protocol = null;\n this.slashes = null;\n this.auth = null;\n this.port = null;\n this.hostname = null;\n this.hash = null;\n this.search = null;\n this.pathname = null;\n}\n\n// Reference: RFC 3986, RFC 1808, RFC 2396\n\n// define these here so at least they only have to be\n// compiled once on the first module load.\nvar protocolPattern = /^([a-z0-9.+-]+:)/i,\n portPattern = /:[0-9]*$/,\n\n // Special case for a simple path URL\n simplePathPattern = /^(\\/\\/?(?!\\/)[^\\?\\s]*)(\\?[^\\s]*)?$/,\n\n // RFC 2396: characters reserved for delimiting URLs.\n // We actually just auto-escape these.\n delims = [ '<', '>', '\"', '`', ' ', '\\r', '\\n', '\\t' ],\n\n // RFC 2396: characters not allowed for various reasons.\n unwise = [ '{', '}', '|', '\\\\', '^', '`' ].concat(delims),\n\n // Allowed by RFCs, but cause of XSS attacks. Always escape these.\n autoEscape = [ '\\'' ].concat(unwise),\n // Characters that are never ever allowed in a hostname.\n // Note that any invalid chars are also handled, but these\n // are the ones that are *expected* to be seen, so we fast-path\n // them.\n nonHostChars = [ '%', '/', '?', ';', '#' ].concat(autoEscape),\n hostEndingChars = [ '/', '?', '#' ],\n hostnameMaxLen = 255,\n hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,\n hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,\n // protocols that can allow \"unsafe\" and \"unwise\" chars.\n /* eslint-disable no-script-url */\n // protocols that never have a hostname.\n hostlessProtocol = {\n 'javascript': true,\n 'javascript:': true\n },\n // protocols that always contain a // bit.\n slashedProtocol = {\n 'http': true,\n 'https': true,\n 'ftp': true,\n 'gopher': true,\n 'file': true,\n 'http:': true,\n 'https:': true,\n 'ftp:': true,\n 'gopher:': true,\n 'file:': true\n };\n /* eslint-enable no-script-url */\n\nfunction urlParse(url, slashesDenoteHost) {\n if (url && url instanceof Url) { return url; }\n\n var u = new Url();\n u.parse(url, slashesDenoteHost);\n return u;\n}\n\nUrl.prototype.parse = function(url, slashesDenoteHost) {\n var i, l, lowerProto, hec, slashes,\n rest = url;\n\n // trim before proceeding.\n // This is to support parse stuff like \" http://foo.com \\n\"\n rest = rest.trim();\n\n if (!slashesDenoteHost && url.split('#').length === 1) {\n // Try fast path regexp\n var simplePath = simplePathPattern.exec(rest);\n if (simplePath) {\n this.pathname = simplePath[1];\n if (simplePath[2]) {\n this.search = simplePath[2];\n }\n return this;\n }\n }\n\n var proto = protocolPattern.exec(rest);\n if (proto) {\n proto = proto[0];\n lowerProto = proto.toLowerCase();\n this.protocol = proto;\n rest = rest.substr(proto.length);\n }\n\n // figure out if it's got a host\n // user@server is *always* interpreted as a hostname, and url\n // resolution will treat //foo/bar as host=foo,path=bar because that's\n // how the browser resolves relative URLs.\n if (slashesDenoteHost || proto || rest.match(/^\\/\\/[^@\\/]+@[^@\\/]+/)) {\n slashes = rest.substr(0, 2) === '//';\n if (slashes && !(proto && hostlessProtocol[proto])) {\n rest = rest.substr(2);\n this.slashes = true;\n }\n }\n\n if (!hostlessProtocol[proto] &&\n (slashes || (proto && !slashedProtocol[proto]))) {\n\n // there's a hostname.\n // the first instance of /, ?, ;, or # ends the host.\n //\n // If there is an @ in the hostname, then non-host chars *are* allowed\n // to the left of the last @ sign, unless some host-ending character\n // comes *before* the @-sign.\n // URLs are obnoxious.\n //\n // ex:\n // http://a@b@c/ => user:a@b host:c\n // http://a@b?@c => user:a host:c path:/?@c\n\n // v0.12 TODO(isaacs): This is not quite how Chrome does things.\n // Review our test case against browsers more comprehensively.\n\n // find the first instance of any hostEndingChars\n var hostEnd = -1;\n for (i = 0; i < hostEndingChars.length; i++) {\n hec = rest.indexOf(hostEndingChars[i]);\n if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) {\n hostEnd = hec;\n }\n }\n\n // at this point, either we have an explicit point where the\n // auth portion cannot go past, or the last @ char is the decider.\n var auth, atSign;\n if (hostEnd === -1) {\n // atSign can be anywhere.\n atSign = rest.lastIndexOf('@');\n } else {\n // atSign must be in auth portion.\n // http://a@b/c@d => host:b auth:a path:/c@d\n atSign = rest.lastIndexOf('@', hostEnd);\n }\n\n // Now we have a portion which is definitely the auth.\n // Pull that off.\n if (atSign !== -1) {\n auth = rest.slice(0, atSign);\n rest = rest.slice(atSign + 1);\n this.auth = auth;\n }\n\n // the host is the remaining to the left of the first non-host char\n hostEnd = -1;\n for (i = 0; i < nonHostChars.length; i++) {\n hec = rest.indexOf(nonHostChars[i]);\n if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) {\n hostEnd = hec;\n }\n }\n // if we still have not hit it, then the entire thing is a host.\n if (hostEnd === -1) {\n hostEnd = rest.length;\n }\n\n if (rest[hostEnd - 1] === ':') { hostEnd--; }\n var host = rest.slice(0, hostEnd);\n rest = rest.slice(hostEnd);\n\n // pull out port.\n this.parseHost(host);\n\n // we've indicated that there is a hostname,\n // so even if it's empty, it has to be present.\n this.hostname = this.hostname || '';\n\n // if hostname begins with [ and ends with ]\n // assume that it's an IPv6 address.\n var ipv6Hostname = this.hostname[0] === '[' &&\n this.hostname[this.hostname.length - 1] === ']';\n\n // validate a little.\n if (!ipv6Hostname) {\n var hostparts = this.hostname.split(/\\./);\n for (i = 0, l = hostparts.length; i < l; i++) {\n var part = hostparts[i];\n if (!part) { continue; }\n if (!part.match(hostnamePartPattern)) {\n var newpart = '';\n for (var j = 0, k = part.length; j < k; j++) {\n if (part.charCodeAt(j) > 127) {\n // we replace non-ASCII char with a temporary placeholder\n // we need this to make sure size of hostname is not\n // broken by replacing non-ASCII by nothing\n newpart += 'x';\n } else {\n newpart += part[j];\n }\n }\n // we test again with ASCII char only\n if (!newpart.match(hostnamePartPattern)) {\n var validParts = hostparts.slice(0, i);\n var notHost = hostparts.slice(i + 1);\n var bit = part.match(hostnamePartStart);\n if (bit) {\n validParts.push(bit[1]);\n notHost.unshift(bit[2]);\n }\n if (notHost.length) {\n rest = notHost.join('.') + rest;\n }\n this.hostname = validParts.join('.');\n break;\n }\n }\n }\n }\n\n if (this.hostname.length > hostnameMaxLen) {\n this.hostname = '';\n }\n\n // strip [ and ] from the hostname\n // the host field still retains them, though\n if (ipv6Hostname) {\n this.hostname = this.hostname.substr(1, this.hostname.length - 2);\n }\n }\n\n // chop off from the tail first.\n var hash = rest.indexOf('#');\n if (hash !== -1) {\n // got a fragment string.\n this.hash = rest.substr(hash);\n rest = rest.slice(0, hash);\n }\n var qm = rest.indexOf('?');\n if (qm !== -1) {\n this.search = rest.substr(qm);\n rest = rest.slice(0, qm);\n }\n if (rest) { this.pathname = rest; }\n if (slashedProtocol[lowerProto] &&\n this.hostname && !this.pathname) {\n this.pathname = '';\n }\n\n return this;\n};\n\nUrl.prototype.parseHost = function(host) {\n var port = portPattern.exec(host);\n if (port) {\n port = port[0];\n if (port !== ':') {\n this.port = port.substr(1);\n }\n host = host.substr(0, host.length - port.length);\n }\n if (host) { this.hostname = host; }\n};\n\nmodule.exports = urlParse;\n","'use strict';\n\nexports.Any = require('./properties/Any/regex');\nexports.Cc = require('./categories/Cc/regex');\nexports.Cf = require('./categories/Cf/regex');\nexports.P = require('./categories/P/regex');\nexports.Z = require('./categories/Z/regex');\n","module.exports=/[\\xAD\\u0600-\\u0605\\u061C\\u06DD\\u070F\\u08E2\\u180E\\u200B-\\u200F\\u202A-\\u202E\\u2060-\\u2064\\u2066-\\u206F\\uFEFF\\uFFF9-\\uFFFB]|\\uD804[\\uDCBD\\uDCCD]|\\uD82F[\\uDCA0-\\uDCA3]|\\uD834[\\uDD73-\\uDD7A]|\\uDB40[\\uDC01\\uDC20-\\uDC7F]/","// Just a shortcut for bulk export\n'use strict';\n\n\nexports.parseLinkLabel = require('./parse_link_label');\nexports.parseLinkDestination = require('./parse_link_destination');\nexports.parseLinkTitle = require('./parse_link_title');\n","// Parse link label\n//\n// this function assumes that first character (\"[\") already matches;\n// returns the end of the label\n//\n'use strict';\n\nmodule.exports = function parseLinkLabel(state, start, disableNested) {\n var level, found, marker, prevPos,\n labelEnd = -1,\n max = state.posMax,\n oldPos = state.pos;\n\n state.pos = start + 1;\n level = 1;\n\n while (state.pos < max) {\n marker = state.src.charCodeAt(state.pos);\n if (marker === 0x5D /* ] */) {\n level--;\n if (level === 0) {\n found = true;\n break;\n }\n }\n\n prevPos = state.pos;\n state.md.inline.skipToken(state);\n if (marker === 0x5B /* [ */) {\n if (prevPos === state.pos - 1) {\n // increase level if we find text `[`, which is not a part of any token\n level++;\n } else if (disableNested) {\n state.pos = oldPos;\n return -1;\n }\n }\n }\n\n if (found) {\n labelEnd = state.pos;\n }\n\n // restore old state\n state.pos = oldPos;\n\n return labelEnd;\n};\n","// Parse link destination\n//\n'use strict';\n\n\nvar unescapeAll = require('../common/utils').unescapeAll;\n\n\nmodule.exports = function parseLinkDestination(str, pos, max) {\n var code, level,\n lines = 0,\n start = pos,\n result = {\n ok: false,\n pos: 0,\n lines: 0,\n str: ''\n };\n\n if (str.charCodeAt(pos) === 0x3C /* < */) {\n pos++;\n while (pos < max) {\n code = str.charCodeAt(pos);\n if (code === 0x0A /* \\n */) { return result; }\n if (code === 0x3E /* > */) {\n result.pos = pos + 1;\n result.str = unescapeAll(str.slice(start + 1, pos));\n result.ok = true;\n return result;\n }\n if (code === 0x5C /* \\ */ && pos + 1 < max) {\n pos += 2;\n continue;\n }\n\n pos++;\n }\n\n // no closing '>'\n return result;\n }\n\n // this should be ... } else { ... branch\n\n level = 0;\n while (pos < max) {\n code = str.charCodeAt(pos);\n\n if (code === 0x20) { break; }\n\n // ascii control characters\n if (code < 0x20 || code === 0x7F) { break; }\n\n if (code === 0x5C /* \\ */ && pos + 1 < max) {\n pos += 2;\n continue;\n }\n\n if (code === 0x28 /* ( */) {\n level++;\n }\n\n if (code === 0x29 /* ) */) {\n if (level === 0) { break; }\n level--;\n }\n\n pos++;\n }\n\n if (start === pos) { return result; }\n if (level !== 0) { return result; }\n\n result.str = unescapeAll(str.slice(start, pos));\n result.lines = lines;\n result.pos = pos;\n result.ok = true;\n return result;\n};\n","// Parse link title\n//\n'use strict';\n\n\nvar unescapeAll = require('../common/utils').unescapeAll;\n\n\nmodule.exports = function parseLinkTitle(str, pos, max) {\n var code,\n marker,\n lines = 0,\n start = pos,\n result = {\n ok: false,\n pos: 0,\n lines: 0,\n str: ''\n };\n\n if (pos >= max) { return result; }\n\n marker = str.charCodeAt(pos);\n\n if (marker !== 0x22 /* \" */ && marker !== 0x27 /* ' */ && marker !== 0x28 /* ( */) { return result; }\n\n pos++;\n\n // if opening marker is \"(\", switch it to closing marker \")\"\n if (marker === 0x28) { marker = 0x29; }\n\n while (pos < max) {\n code = str.charCodeAt(pos);\n if (code === marker) {\n result.pos = pos + 1;\n result.lines = lines;\n result.str = unescapeAll(str.slice(start + 1, pos));\n result.ok = true;\n return result;\n } else if (code === 0x0A) {\n lines++;\n } else if (code === 0x5C /* \\ */ && pos + 1 < max) {\n pos++;\n if (str.charCodeAt(pos) === 0x0A) {\n lines++;\n }\n }\n\n pos++;\n }\n\n return result;\n};\n","/**\n * class Renderer\n *\n * Generates HTML from parsed token stream. Each instance has independent\n * copy of rules. Those can be rewritten with ease. Also, you can add new\n * rules if you create plugin and adds new token types.\n **/\n'use strict';\n\n\nvar assign = require('./common/utils').assign;\nvar unescapeAll = require('./common/utils').unescapeAll;\nvar escapeHtml = require('./common/utils').escapeHtml;\n\n\n////////////////////////////////////////////////////////////////////////////////\n\nvar default_rules = {};\n\n\ndefault_rules.code_inline = function (tokens, idx, options, env, slf) {\n var token = tokens[idx];\n\n return '<code' + slf.renderAttrs(token) + '>' +\n escapeHtml(tokens[idx].content) +\n '</code>';\n};\n\n\ndefault_rules.code_block = function (tokens, idx, options, env, slf) {\n var token = tokens[idx];\n\n return '<pre' + slf.renderAttrs(token) + '><code>' +\n escapeHtml(tokens[idx].content) +\n '</code></pre>\\n';\n};\n\n\ndefault_rules.fence = function (tokens, idx, options, env, slf) {\n var token = tokens[idx],\n info = token.info ? unescapeAll(token.info).trim() : '',\n langName = '',\n highlighted, i, tmpAttrs, tmpToken;\n\n if (info) {\n langName = info.split(/\\s+/g)[0];\n }\n\n if (options.highlight) {\n highlighted = options.highlight(token.content, langName) || escapeHtml(token.content);\n } else {\n highlighted = escapeHtml(token.content);\n }\n\n if (highlighted.indexOf('<pre') === 0) {\n return highlighted + '\\n';\n }\n\n // If language exists, inject class gently, without modifying original token.\n // May be, one day we will add .clone() for token and simplify this part, but\n // now we prefer to keep things local.\n if (info) {\n i = token.attrIndex('class');\n tmpAttrs = token.attrs ? token.attrs.slice() : [];\n\n if (i < 0) {\n tmpAttrs.push([ 'class', options.langPrefix + langName ]);\n } else {\n tmpAttrs[i][1] += ' ' + options.langPrefix + langName;\n }\n\n // Fake token just to render attributes\n tmpToken = {\n attrs: tmpAttrs\n };\n\n return '<pre><code' + slf.renderAttrs(tmpToken) + '>'\n + highlighted\n + '</code></pre>\\n';\n }\n\n\n return '<pre><code' + slf.renderAttrs(token) + '>'\n + highlighted\n + '</code></pre>\\n';\n};\n\n\ndefault_rules.image = function (tokens, idx, options, env, slf) {\n var token = tokens[idx];\n\n // \"alt\" attr MUST be set, even if empty. Because it's mandatory and\n // should be placed on proper position for tests.\n //\n // Replace content with actual value\n\n token.attrs[token.attrIndex('alt')][1] =\n slf.renderInlineAsText(token.children, options, env);\n\n return slf.renderToken(tokens, idx, options);\n};\n\n\ndefault_rules.hardbreak = function (tokens, idx, options /*, env */) {\n return options.xhtmlOut ? '<br />\\n' : '<br>\\n';\n};\ndefault_rules.softbreak = function (tokens, idx, options /*, env */) {\n return options.breaks ? (options.xhtmlOut ? '<br />\\n' : '<br>\\n') : '\\n';\n};\n\n\ndefault_rules.text = function (tokens, idx /*, options, env */) {\n return escapeHtml(tokens[idx].content);\n};\n\n\ndefault_rules.html_block = function (tokens, idx /*, options, env */) {\n return tokens[idx].content;\n};\ndefault_rules.html_inline = function (tokens, idx /*, options, env */) {\n return tokens[idx].content;\n};\n\n\n/**\n * new Renderer()\n *\n * Creates new [[Renderer]] instance and fill [[Renderer#rules]] with defaults.\n **/\nfunction Renderer() {\n\n /**\n * Renderer#rules -> Object\n *\n * Contains render rules for tokens. Can be updated and extended.\n *\n * ##### Example\n *\n * ```javascript\n * var md = require('markdown-it')();\n *\n * md.renderer.rules.strong_open = function () { return '<b>'; };\n * md.renderer.rules.strong_close = function () { return '</b>'; };\n *\n * var result = md.renderInline(...);\n * ```\n *\n * Each rule is called as independent static function with fixed signature:\n *\n * ```javascript\n * function my_token_render(tokens, idx, options, env, renderer) {\n * // ...\n * return renderedHTML;\n * }\n * ```\n *\n * See [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js)\n * for more details and examples.\n **/\n this.rules = assign({}, default_rules);\n}\n\n\n/**\n * Renderer.renderAttrs(token) -> String\n *\n * Render token attributes to string.\n **/\nRenderer.prototype.renderAttrs = function renderAttrs(token) {\n var i, l, result;\n\n if (!token.attrs) { return ''; }\n\n result = '';\n\n for (i = 0, l = token.attrs.length; i < l; i++) {\n result += ' ' + escapeHtml(token.attrs[i][0]) + '=\"' + escapeHtml(token.attrs[i][1]) + '\"';\n }\n\n return result;\n};\n\n\n/**\n * Renderer.renderToken(tokens, idx, options) -> String\n * - tokens (Array): list of tokens\n * - idx (Numbed): token index to render\n * - options (Object): params of parser instance\n *\n * Default token renderer. Can be overriden by custom function\n * in [[Renderer#rules]].\n **/\nRenderer.prototype.renderToken = function renderToken(tokens, idx, options) {\n var nextToken,\n result = '',\n needLf = false,\n token = tokens[idx];\n\n // Tight list paragraphs\n if (token.hidden) {\n return '';\n }\n\n // Insert a newline between hidden paragraph and subsequent opening\n // block-level tag.\n //\n // For example, here we should insert a newline before blockquote:\n // - a\n // >\n //\n if (token.block && token.nesting !== -1 && idx && tokens[idx - 1].hidden) {\n result += '\\n';\n }\n\n // Add token name, e.g. `<img`\n result += (token.nesting === -1 ? '</' : '<') + token.tag;\n\n // Encode attributes, e.g. `<img src=\"foo\"`\n result += this.renderAttrs(token);\n\n // Add a slash for self-closing tags, e.g. `<img src=\"foo\" /`\n if (token.nesting === 0 && options.xhtmlOut) {\n result += ' /';\n }\n\n // Check if we need to add a newline after this tag\n if (token.block) {\n needLf = true;\n\n if (token.nesting === 1) {\n if (idx + 1 < tokens.length) {\n nextToken = tokens[idx + 1];\n\n if (nextToken.type === 'inline' || nextToken.hidden) {\n // Block-level tag containing an inline tag.\n //\n needLf = false;\n\n } else if (nextToken.nesting === -1 && nextToken.tag === token.tag) {\n // Opening tag + closing tag of the same type. E.g. `<li></li>`.\n //\n needLf = false;\n }\n }\n }\n }\n\n result += needLf ? '>\\n' : '>';\n\n return result;\n};\n\n\n/**\n * Renderer.renderInline(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to renter\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * The same as [[Renderer.render]], but for single token of `inline` type.\n **/\nRenderer.prototype.renderInline = function (tokens, options, env) {\n var type,\n result = '',\n rules = this.rules;\n\n for (var i = 0, len = tokens.length; i < len; i++) {\n type = tokens[i].type;\n\n if (typeof rules[type] !== 'undefined') {\n result += rules[type](tokens, i, options, env, this);\n } else {\n result += this.renderToken(tokens, i, options);\n }\n }\n\n return result;\n};\n\n\n/** internal\n * Renderer.renderInlineAsText(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to renter\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * Special kludge for image `alt` attributes to conform CommonMark spec.\n * Don't try to use it! Spec requires to show `alt` content with stripped markup,\n * instead of simple escaping.\n **/\nRenderer.prototype.renderInlineAsText = function (tokens, options, env) {\n var result = '';\n\n for (var i = 0, len = tokens.length; i < len; i++) {\n if (tokens[i].type === 'text') {\n result += tokens[i].content;\n } else if (tokens[i].type === 'image') {\n result += this.renderInlineAsText(tokens[i].children, options, env);\n }\n }\n\n return result;\n};\n\n\n/**\n * Renderer.render(tokens, options, env) -> String\n * - tokens (Array): list on block tokens to renter\n * - options (Object): params of parser instance\n * - env (Object): additional data from parsed input (references, for example)\n *\n * Takes token stream and generates HTML. Probably, you will never need to call\n * this method directly.\n **/\nRenderer.prototype.render = function (tokens, options, env) {\n var i, len, type,\n result = '',\n rules = this.rules;\n\n for (i = 0, len = tokens.length; i < len; i++) {\n type = tokens[i].type;\n\n if (type === 'inline') {\n result += this.renderInline(tokens[i].children, options, env);\n } else if (typeof rules[type] !== 'undefined') {\n result += rules[tokens[i].type](tokens, i, options, env, this);\n } else {\n result += this.renderToken(tokens, i, options, env);\n }\n }\n\n return result;\n};\n\nmodule.exports = Renderer;\n","/** internal\n * class Core\n *\n * Top-level rules executor. Glues block/inline parsers and does intermediate\n * transformations.\n **/\n'use strict';\n\n\nvar Ruler = require('./ruler');\n\n\nvar _rules = [\n [ 'normalize', require('./rules_core/normalize') ],\n [ 'block', require('./rules_core/block') ],\n [ 'inline', require('./rules_core/inline') ],\n [ 'linkify', require('./rules_core/linkify') ],\n [ 'replacements', require('./rules_core/replacements') ],\n [ 'smartquotes', require('./rules_core/smartquotes') ]\n];\n\n\n/**\n * new Core()\n **/\nfunction Core() {\n /**\n * Core#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of core rules.\n **/\n this.ruler = new Ruler();\n\n for (var i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1]);\n }\n}\n\n\n/**\n * Core.process(state)\n *\n * Executes core chain rules.\n **/\nCore.prototype.process = function (state) {\n var i, l, rules;\n\n rules = this.ruler.getRules('');\n\n for (i = 0, l = rules.length; i < l; i++) {\n rules[i](state);\n }\n};\n\nCore.prototype.State = require('./rules_core/state_core');\n\n\nmodule.exports = Core;\n","// Normalize input string\n\n'use strict';\n\n\n// https://spec.commonmark.org/0.29/#line-ending\nvar NEWLINES_RE = /\\r\\n?|\\n/g;\nvar NULL_RE = /\\0/g;\n\n\nmodule.exports = function normalize(state) {\n var str;\n\n // Normalize newlines\n str = state.src.replace(NEWLINES_RE, '\\n');\n\n // Replace NULL characters\n str = str.replace(NULL_RE, '\\uFFFD');\n\n state.src = str;\n};\n","'use strict';\n\n\nmodule.exports = function block(state) {\n var token;\n\n if (state.inlineMode) {\n token = new state.Token('inline', '', 0);\n token.content = state.src;\n token.map = [ 0, 1 ];\n token.children = [];\n state.tokens.push(token);\n } else {\n state.md.block.parse(state.src, state.md, state.env, state.tokens);\n }\n};\n","'use strict';\n\nmodule.exports = function inline(state) {\n var tokens = state.tokens, tok, i, l;\n\n // Parse inlines\n for (i = 0, l = tokens.length; i < l; i++) {\n tok = tokens[i];\n if (tok.type === 'inline') {\n state.md.inline.parse(tok.content, state.md, state.env, tok.children);\n }\n }\n};\n","// Replace link-like texts with link nodes.\n//\n// Currently restricted by `md.validateLink()` to http/https/ftp\n//\n'use strict';\n\n\nvar arrayReplaceAt = require('../common/utils').arrayReplaceAt;\n\n\nfunction isLinkOpen(str) {\n return /^<a[>\\s]/i.test(str);\n}\nfunction isLinkClose(str) {\n return /^<\\/a\\s*>/i.test(str);\n}\n\n\nmodule.exports = function linkify(state) {\n var i, j, l, tokens, token, currentToken, nodes, ln, text, pos, lastPos,\n level, htmlLinkLevel, url, fullUrl, urlText,\n blockTokens = state.tokens,\n links;\n\n if (!state.md.options.linkify) { return; }\n\n for (j = 0, l = blockTokens.length; j < l; j++) {\n if (blockTokens[j].type !== 'inline' ||\n !state.md.linkify.pretest(blockTokens[j].content)) {\n continue;\n }\n\n tokens = blockTokens[j].children;\n\n htmlLinkLevel = 0;\n\n // We scan from the end, to keep position when new tags added.\n // Use reversed logic in links start/end match\n for (i = tokens.length - 1; i >= 0; i--) {\n currentToken = tokens[i];\n\n // Skip content of markdown links\n if (currentToken.type === 'link_close') {\n i--;\n while (tokens[i].level !== currentToken.level && tokens[i].type !== 'link_open') {\n i--;\n }\n continue;\n }\n\n // Skip content of html tag links\n if (currentToken.type === 'html_inline') {\n if (isLinkOpen(currentToken.content) && htmlLinkLevel > 0) {\n htmlLinkLevel--;\n }\n if (isLinkClose(currentToken.content)) {\n htmlLinkLevel++;\n }\n }\n if (htmlLinkLevel > 0) { continue; }\n\n if (currentToken.type === 'text' && state.md.linkify.test(currentToken.content)) {\n\n text = currentToken.content;\n links = state.md.linkify.match(text);\n\n // Now split string to nodes\n nodes = [];\n level = currentToken.level;\n lastPos = 0;\n\n for (ln = 0; ln < links.length; ln++) {\n\n url = links[ln].url;\n fullUrl = state.md.normalizeLink(url);\n if (!state.md.validateLink(fullUrl)) { continue; }\n\n urlText = links[ln].text;\n\n // Linkifier might send raw hostnames like \"example.com\", where url\n // starts with domain name. So we prepend http:// in those cases,\n // and remove it afterwards.\n //\n if (!links[ln].schema) {\n urlText = state.md.normalizeLinkText('http://' + urlText).replace(/^http:\\/\\//, '');\n } else if (links[ln].schema === 'mailto:' && !/^mailto:/i.test(urlText)) {\n urlText = state.md.normalizeLinkText('mailto:' + urlText).replace(/^mailto:/, '');\n } else {\n urlText = state.md.normalizeLinkText(urlText);\n }\n\n pos = links[ln].index;\n\n if (pos > lastPos) {\n token = new state.Token('text', '', 0);\n token.content = text.slice(lastPos, pos);\n token.level = level;\n nodes.push(token);\n }\n\n token = new state.Token('link_open', 'a', 1);\n token.attrs = [ [ 'href', fullUrl ] ];\n token.level = level++;\n token.markup = 'linkify';\n token.info = 'auto';\n nodes.push(token);\n\n token = new state.Token('text', '', 0);\n token.content = urlText;\n token.level = level;\n nodes.push(token);\n\n token = new state.Token('link_close', 'a', -1);\n token.level = --level;\n token.markup = 'linkify';\n token.info = 'auto';\n nodes.push(token);\n\n lastPos = links[ln].lastIndex;\n }\n if (lastPos < text.length) {\n token = new state.Token('text', '', 0);\n token.content = text.slice(lastPos);\n token.level = level;\n nodes.push(token);\n }\n\n // replace current node\n blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);\n }\n }\n }\n};\n","// Simple typographic replacements\n//\n// (c) (C) → ©\n// (tm) (TM) → ™\n// (r) (R) → ®\n// +- → ±\n// (p) (P) -> §\n// ... → … (also ?.... → ?.., !.... → !..)\n// ???????? → ???, !!!!! → !!!, `,,` → `,`\n// -- → &ndash;, --- → &mdash;\n//\n'use strict';\n\n// TODO:\n// - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾\n// - miltiplication 2 x 4 -> 2 × 4\n\nvar RARE_RE = /\\+-|\\.\\.|\\?\\?\\?\\?|!!!!|,,|--/;\n\n// Workaround for phantomjs - need regex without /g flag,\n// or root check will fail every second time\nvar SCOPED_ABBR_TEST_RE = /\\((c|tm|r|p)\\)/i;\n\nvar SCOPED_ABBR_RE = /\\((c|tm|r|p)\\)/ig;\nvar SCOPED_ABBR = {\n c: '©',\n r: '®',\n p: '§',\n tm: '™'\n};\n\nfunction replaceFn(match, name) {\n return SCOPED_ABBR[name.toLowerCase()];\n}\n\nfunction replace_scoped(inlineTokens) {\n var i, token, inside_autolink = 0;\n\n for (i = inlineTokens.length - 1; i >= 0; i--) {\n token = inlineTokens[i];\n\n if (token.type === 'text' && !inside_autolink) {\n token.content = token.content.replace(SCOPED_ABBR_RE, replaceFn);\n }\n\n if (token.type === 'link_open' && token.info === 'auto') {\n inside_autolink--;\n }\n\n if (token.type === 'link_close' && token.info === 'auto') {\n inside_autolink++;\n }\n }\n}\n\nfunction replace_rare(inlineTokens) {\n var i, token, inside_autolink = 0;\n\n for (i = inlineTokens.length - 1; i >= 0; i--) {\n token = inlineTokens[i];\n\n if (token.type === 'text' && !inside_autolink) {\n if (RARE_RE.test(token.content)) {\n token.content = token.content\n .replace(/\\+-/g, '±')\n // .., ..., ....... -> …\n // but ?..... & !..... -> ?.. & !..\n .replace(/\\.{2,}/g, '…').replace(/([?!])…/g, '$1..')\n .replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',')\n // em-dash\n .replace(/(^|[^-])---([^-]|$)/mg, '$1\\u2014$2')\n // en-dash\n .replace(/(^|\\s)--(\\s|$)/mg, '$1\\u2013$2')\n .replace(/(^|[^-\\s])--([^-\\s]|$)/mg, '$1\\u2013$2');\n }\n }\n\n if (token.type === 'link_open' && token.info === 'auto') {\n inside_autolink--;\n }\n\n if (token.type === 'link_close' && token.info === 'auto') {\n inside_autolink++;\n }\n }\n}\n\n\nmodule.exports = function replace(state) {\n var blkIdx;\n\n if (!state.md.options.typographer) { return; }\n\n for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {\n\n if (state.tokens[blkIdx].type !== 'inline') { continue; }\n\n if (SCOPED_ABBR_TEST_RE.test(state.tokens[blkIdx].content)) {\n replace_scoped(state.tokens[blkIdx].children);\n }\n\n if (RARE_RE.test(state.tokens[blkIdx].content)) {\n replace_rare(state.tokens[blkIdx].children);\n }\n\n }\n};\n","// Convert straight quotation marks to typographic ones\n//\n'use strict';\n\n\nvar isWhiteSpace = require('../common/utils').isWhiteSpace;\nvar isPunctChar = require('../common/utils').isPunctChar;\nvar isMdAsciiPunct = require('../common/utils').isMdAsciiPunct;\n\nvar QUOTE_TEST_RE = /['\"]/;\nvar QUOTE_RE = /['\"]/g;\nvar APOSTROPHE = '\\u2019'; /* ’ */\n\n\nfunction replaceAt(str, index, ch) {\n return str.substr(0, index) + ch + str.substr(index + 1);\n}\n\nfunction process_inlines(tokens, state) {\n var i, token, text, t, pos, max, thisLevel, item, lastChar, nextChar,\n isLastPunctChar, isNextPunctChar, isLastWhiteSpace, isNextWhiteSpace,\n canOpen, canClose, j, isSingle, stack, openQuote, closeQuote;\n\n stack = [];\n\n for (i = 0; i < tokens.length; i++) {\n token = tokens[i];\n\n thisLevel = tokens[i].level;\n\n for (j = stack.length - 1; j >= 0; j--) {\n if (stack[j].level <= thisLevel) { break; }\n }\n stack.length = j + 1;\n\n if (token.type !== 'text') { continue; }\n\n text = token.content;\n pos = 0;\n max = text.length;\n\n /*eslint no-labels:0,block-scoped-var:0*/\n OUTER:\n while (pos < max) {\n QUOTE_RE.lastIndex = pos;\n t = QUOTE_RE.exec(text);\n if (!t) { break; }\n\n canOpen = canClose = true;\n pos = t.index + 1;\n isSingle = (t[0] === \"'\");\n\n // Find previous character,\n // default to space if it's the beginning of the line\n //\n lastChar = 0x20;\n\n if (t.index - 1 >= 0) {\n lastChar = text.charCodeAt(t.index - 1);\n } else {\n for (j = i - 1; j >= 0; j--) {\n if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break; // lastChar defaults to 0x20\n if (tokens[j].type !== 'text') continue;\n\n lastChar = tokens[j].content.charCodeAt(tokens[j].content.length - 1);\n break;\n }\n }\n\n // Find next character,\n // default to space if it's the end of the line\n //\n nextChar = 0x20;\n\n if (pos < max) {\n nextChar = text.charCodeAt(pos);\n } else {\n for (j = i + 1; j < tokens.length; j++) {\n if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break; // nextChar defaults to 0x20\n if (tokens[j].type !== 'text') continue;\n\n nextChar = tokens[j].content.charCodeAt(0);\n break;\n }\n }\n\n isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));\n isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));\n\n isLastWhiteSpace = isWhiteSpace(lastChar);\n isNextWhiteSpace = isWhiteSpace(nextChar);\n\n if (isNextWhiteSpace) {\n canOpen = false;\n } else if (isNextPunctChar) {\n if (!(isLastWhiteSpace || isLastPunctChar)) {\n canOpen = false;\n }\n }\n\n if (isLastWhiteSpace) {\n canClose = false;\n } else if (isLastPunctChar) {\n if (!(isNextWhiteSpace || isNextPunctChar)) {\n canClose = false;\n }\n }\n\n if (nextChar === 0x22 /* \" */ && t[0] === '\"') {\n if (lastChar >= 0x30 /* 0 */ && lastChar <= 0x39 /* 9 */) {\n // special case: 1\"\" - count first quote as an inch\n canClose = canOpen = false;\n }\n }\n\n if (canOpen && canClose) {\n // treat this as the middle of the word\n canOpen = false;\n canClose = isNextPunctChar;\n }\n\n if (!canOpen && !canClose) {\n // middle of word\n if (isSingle) {\n token.content = replaceAt(token.content, t.index, APOSTROPHE);\n }\n continue;\n }\n\n if (canClose) {\n // this could be a closing quote, rewind the stack to get a match\n for (j = stack.length - 1; j >= 0; j--) {\n item = stack[j];\n if (stack[j].level < thisLevel) { break; }\n if (item.single === isSingle && stack[j].level === thisLevel) {\n item = stack[j];\n\n if (isSingle) {\n openQuote = state.md.options.quotes[2];\n closeQuote = state.md.options.quotes[3];\n } else {\n openQuote = state.md.options.quotes[0];\n closeQuote = state.md.options.quotes[1];\n }\n\n // replace token.content *before* tokens[item.token].content,\n // because, if they are pointing at the same token, replaceAt\n // could mess up indices when quote length != 1\n token.content = replaceAt(token.content, t.index, closeQuote);\n tokens[item.token].content = replaceAt(\n tokens[item.token].content, item.pos, openQuote);\n\n pos += closeQuote.length - 1;\n if (item.token === i) { pos += openQuote.length - 1; }\n\n text = token.content;\n max = text.length;\n\n stack.length = j;\n continue OUTER;\n }\n }\n }\n\n if (canOpen) {\n stack.push({\n token: i,\n pos: t.index,\n single: isSingle,\n level: thisLevel\n });\n } else if (canClose && isSingle) {\n token.content = replaceAt(token.content, t.index, APOSTROPHE);\n }\n }\n }\n}\n\n\nmodule.exports = function smartquotes(state) {\n /*eslint max-depth:0*/\n var blkIdx;\n\n if (!state.md.options.typographer) { return; }\n\n for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {\n\n if (state.tokens[blkIdx].type !== 'inline' ||\n !QUOTE_TEST_RE.test(state.tokens[blkIdx].content)) {\n continue;\n }\n\n process_inlines(state.tokens[blkIdx].children, state);\n }\n};\n","// Core state object\n//\n'use strict';\n\nvar Token = require('../token');\n\n\nfunction StateCore(src, md, env) {\n this.src = src;\n this.env = env;\n this.tokens = [];\n this.inlineMode = false;\n this.md = md; // link to parser instance\n}\n\n// re-export Token class to use in core rules\nStateCore.prototype.Token = Token;\n\n\nmodule.exports = StateCore;\n","/** internal\n * class ParserBlock\n *\n * Block-level tokenizer.\n **/\n'use strict';\n\n\nvar Ruler = require('./ruler');\n\n\nvar _rules = [\n // First 2 params - rule name & source. Secondary array - list of rules,\n // which can be terminated by this one.\n [ 'table', require('./rules_block/table'), [ 'paragraph', 'reference' ] ],\n [ 'code', require('./rules_block/code') ],\n [ 'fence', require('./rules_block/fence'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],\n [ 'blockquote', require('./rules_block/blockquote'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],\n [ 'hr', require('./rules_block/hr'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],\n [ 'list', require('./rules_block/list'), [ 'paragraph', 'reference', 'blockquote' ] ],\n [ 'reference', require('./rules_block/reference') ],\n [ 'heading', require('./rules_block/heading'), [ 'paragraph', 'reference', 'blockquote' ] ],\n [ 'lheading', require('./rules_block/lheading') ],\n [ 'html_block', require('./rules_block/html_block'), [ 'paragraph', 'reference', 'blockquote' ] ],\n [ 'paragraph', require('./rules_block/paragraph') ]\n];\n\n\n/**\n * new ParserBlock()\n **/\nfunction ParserBlock() {\n /**\n * ParserBlock#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of block rules.\n **/\n this.ruler = new Ruler();\n\n for (var i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1], { alt: (_rules[i][2] || []).slice() });\n }\n}\n\n\n// Generate tokens for input range\n//\nParserBlock.prototype.tokenize = function (state, startLine, endLine) {\n var ok, i,\n rules = this.ruler.getRules(''),\n len = rules.length,\n line = startLine,\n hasEmptyLines = false,\n maxNesting = state.md.options.maxNesting;\n\n while (line < endLine) {\n state.line = line = state.skipEmptyLines(line);\n if (line >= endLine) { break; }\n\n // Termination condition for nested calls.\n // Nested calls currently used for blockquotes & lists\n if (state.sCount[line] < state.blkIndent) { break; }\n\n // If nesting level exceeded - skip tail to the end. That's not ordinary\n // situation and we should not care about content.\n if (state.level >= maxNesting) {\n state.line = endLine;\n break;\n }\n\n // Try all possible rules.\n // On success, rule should:\n //\n // - update `state.line`\n // - update `state.tokens`\n // - return true\n\n for (i = 0; i < len; i++) {\n ok = rules[i](state, line, endLine, false);\n if (ok) { break; }\n }\n\n // set state.tight if we had an empty line before current tag\n // i.e. latest empty line should not count\n state.tight = !hasEmptyLines;\n\n // paragraph might \"eat\" one newline after it in nested lists\n if (state.isEmpty(state.line - 1)) {\n hasEmptyLines = true;\n }\n\n line = state.line;\n\n if (line < endLine && state.isEmpty(line)) {\n hasEmptyLines = true;\n line++;\n state.line = line;\n }\n }\n};\n\n\n/**\n * ParserBlock.parse(str, md, env, outTokens)\n *\n * Process input string and push block tokens into `outTokens`\n **/\nParserBlock.prototype.parse = function (src, md, env, outTokens) {\n var state;\n\n if (!src) { return; }\n\n state = new this.State(src, md, env, outTokens);\n\n this.tokenize(state, state.line, state.lineMax);\n};\n\n\nParserBlock.prototype.State = require('./rules_block/state_block');\n\n\nmodule.exports = ParserBlock;\n","// GFM table, non-standard\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nfunction getLine(state, line) {\n var pos = state.bMarks[line] + state.blkIndent,\n max = state.eMarks[line];\n\n return state.src.substr(pos, max - pos);\n}\n\nfunction escapedSplit(str) {\n var result = [],\n pos = 0,\n max = str.length,\n ch,\n escapes = 0,\n lastPos = 0,\n backTicked = false,\n lastBackTick = 0;\n\n ch = str.charCodeAt(pos);\n\n while (pos < max) {\n if (ch === 0x60/* ` */) {\n if (backTicked) {\n // make \\` close code sequence, but not open it;\n // the reason is: `\\` is correct code block\n backTicked = false;\n lastBackTick = pos;\n } else if (escapes % 2 === 0) {\n backTicked = true;\n lastBackTick = pos;\n }\n } else if (ch === 0x7c/* | */ && (escapes % 2 === 0) && !backTicked) {\n result.push(str.substring(lastPos, pos));\n lastPos = pos + 1;\n }\n\n if (ch === 0x5c/* \\ */) {\n escapes++;\n } else {\n escapes = 0;\n }\n\n pos++;\n\n // If there was an un-closed backtick, go back to just after\n // the last backtick, but as if it was a normal character\n if (pos === max && backTicked) {\n backTicked = false;\n pos = lastBackTick + 1;\n }\n\n ch = str.charCodeAt(pos);\n }\n\n result.push(str.substring(lastPos));\n\n return result;\n}\n\n\nmodule.exports = function table(state, startLine, endLine, silent) {\n var ch, lineText, pos, i, nextLine, columns, columnCount, token,\n aligns, t, tableLines, tbodyLines;\n\n // should have at least two lines\n if (startLine + 2 > endLine) { return false; }\n\n nextLine = startLine + 1;\n\n if (state.sCount[nextLine] < state.blkIndent) { return false; }\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[nextLine] - state.blkIndent >= 4) { return false; }\n\n // first character of the second line should be '|', '-', ':',\n // and no other characters are allowed but spaces;\n // basically, this is the equivalent of /^[-:|][-:|\\s]*$/ regexp\n\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n if (pos >= state.eMarks[nextLine]) { return false; }\n\n ch = state.src.charCodeAt(pos++);\n if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */) { return false; }\n\n while (pos < state.eMarks[nextLine]) {\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */ && !isSpace(ch)) { return false; }\n\n pos++;\n }\n\n lineText = getLine(state, startLine + 1);\n\n columns = lineText.split('|');\n aligns = [];\n for (i = 0; i < columns.length; i++) {\n t = columns[i].trim();\n if (!t) {\n // allow empty columns before and after table, but not in between columns;\n // e.g. allow ` |---| `, disallow ` ---||--- `\n if (i === 0 || i === columns.length - 1) {\n continue;\n } else {\n return false;\n }\n }\n\n if (!/^:?-+:?$/.test(t)) { return false; }\n if (t.charCodeAt(t.length - 1) === 0x3A/* : */) {\n aligns.push(t.charCodeAt(0) === 0x3A/* : */ ? 'center' : 'right');\n } else if (t.charCodeAt(0) === 0x3A/* : */) {\n aligns.push('left');\n } else {\n aligns.push('');\n }\n }\n\n lineText = getLine(state, startLine).trim();\n if (lineText.indexOf('|') === -1) { return false; }\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n columns = escapedSplit(lineText.replace(/^\\||\\|$/g, ''));\n\n // header row will define an amount of columns in the entire table,\n // and align row shouldn't be smaller than that (the rest of the rows can)\n columnCount = columns.length;\n if (columnCount > aligns.length) { return false; }\n\n if (silent) { return true; }\n\n token = state.push('table_open', 'table', 1);\n token.map = tableLines = [ startLine, 0 ];\n\n token = state.push('thead_open', 'thead', 1);\n token.map = [ startLine, startLine + 1 ];\n\n token = state.push('tr_open', 'tr', 1);\n token.map = [ startLine, startLine + 1 ];\n\n for (i = 0; i < columns.length; i++) {\n token = state.push('th_open', 'th', 1);\n token.map = [ startLine, startLine + 1 ];\n if (aligns[i]) {\n token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];\n }\n\n token = state.push('inline', '', 0);\n token.content = columns[i].trim();\n token.map = [ startLine, startLine + 1 ];\n token.children = [];\n\n token = state.push('th_close', 'th', -1);\n }\n\n token = state.push('tr_close', 'tr', -1);\n token = state.push('thead_close', 'thead', -1);\n\n token = state.push('tbody_open', 'tbody', 1);\n token.map = tbodyLines = [ startLine + 2, 0 ];\n\n for (nextLine = startLine + 2; nextLine < endLine; nextLine++) {\n if (state.sCount[nextLine] < state.blkIndent) { break; }\n\n lineText = getLine(state, nextLine).trim();\n if (lineText.indexOf('|') === -1) { break; }\n if (state.sCount[nextLine] - state.blkIndent >= 4) { break; }\n columns = escapedSplit(lineText.replace(/^\\||\\|$/g, ''));\n\n token = state.push('tr_open', 'tr', 1);\n for (i = 0; i < columnCount; i++) {\n token = state.push('td_open', 'td', 1);\n if (aligns[i]) {\n token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];\n }\n\n token = state.push('inline', '', 0);\n token.content = columns[i] ? columns[i].trim() : '';\n token.children = [];\n\n token = state.push('td_close', 'td', -1);\n }\n token = state.push('tr_close', 'tr', -1);\n }\n token = state.push('tbody_close', 'tbody', -1);\n token = state.push('table_close', 'table', -1);\n\n tableLines[1] = tbodyLines[1] = nextLine;\n state.line = nextLine;\n return true;\n};\n","// Code block (4 spaces padded)\n\n'use strict';\n\n\nmodule.exports = function code(state, startLine, endLine/*, silent*/) {\n var nextLine, last, token;\n\n if (state.sCount[startLine] - state.blkIndent < 4) { return false; }\n\n last = nextLine = startLine + 1;\n\n while (nextLine < endLine) {\n if (state.isEmpty(nextLine)) {\n nextLine++;\n continue;\n }\n\n if (state.sCount[nextLine] - state.blkIndent >= 4) {\n nextLine++;\n last = nextLine;\n continue;\n }\n break;\n }\n\n state.line = last;\n\n token = state.push('code_block', 'code', 0);\n token.content = state.getLines(startLine, last, 4 + state.blkIndent, true);\n token.map = [ startLine, state.line ];\n\n return true;\n};\n","// fences (``` lang, ~~~ lang)\n\n'use strict';\n\n\nmodule.exports = function fence(state, startLine, endLine, silent) {\n var marker, len, params, nextLine, mem, token, markup,\n haveEndMarker = false,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n if (pos + 3 > max) { return false; }\n\n marker = state.src.charCodeAt(pos);\n\n if (marker !== 0x7E/* ~ */ && marker !== 0x60 /* ` */) {\n return false;\n }\n\n // scan marker length\n mem = pos;\n pos = state.skipChars(pos, marker);\n\n len = pos - mem;\n\n if (len < 3) { return false; }\n\n markup = state.src.slice(mem, pos);\n params = state.src.slice(pos, max);\n\n if (marker === 0x60 /* ` */) {\n if (params.indexOf(String.fromCharCode(marker)) >= 0) {\n return false;\n }\n }\n\n // Since start is found, we can report success here in validation mode\n if (silent) { return true; }\n\n // search end of block\n nextLine = startLine;\n\n for (;;) {\n nextLine++;\n if (nextLine >= endLine) {\n // unclosed block should be autoclosed by end of document.\n // also block seems to be autoclosed by end of parent\n break;\n }\n\n pos = mem = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos < max && state.sCount[nextLine] < state.blkIndent) {\n // non-empty line with negative indent should stop the list:\n // - ```\n // test\n break;\n }\n\n if (state.src.charCodeAt(pos) !== marker) { continue; }\n\n if (state.sCount[nextLine] - state.blkIndent >= 4) {\n // closing fence should be indented less than 4 spaces\n continue;\n }\n\n pos = state.skipChars(pos, marker);\n\n // closing code fence must be at least as long as the opening one\n if (pos - mem < len) { continue; }\n\n // make sure tail has spaces only\n pos = state.skipSpaces(pos);\n\n if (pos < max) { continue; }\n\n haveEndMarker = true;\n // found!\n break;\n }\n\n // If a fence has heading spaces, they should be removed from its inner block\n len = state.sCount[startLine];\n\n state.line = nextLine + (haveEndMarker ? 1 : 0);\n\n token = state.push('fence', 'code', 0);\n token.info = params;\n token.content = state.getLines(startLine + 1, nextLine, len, true);\n token.markup = markup;\n token.map = [ startLine, state.line ];\n\n return true;\n};\n","// Block quotes\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function blockquote(state, startLine, endLine, silent) {\n var adjustTab,\n ch,\n i,\n initial,\n l,\n lastLineEmpty,\n lines,\n nextLine,\n offset,\n oldBMarks,\n oldBSCount,\n oldIndent,\n oldParentType,\n oldSCount,\n oldTShift,\n spaceAfterMarker,\n terminate,\n terminatorRules,\n token,\n wasOutdented,\n oldLineMax = state.lineMax,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n // check the block quote marker\n if (state.src.charCodeAt(pos++) !== 0x3E/* > */) { return false; }\n\n // we know that it's going to be a valid blockquote,\n // so no point trying to find the end of it in silent mode\n if (silent) { return true; }\n\n // skip spaces after \">\" and re-calculate offset\n initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]);\n\n // skip one optional space after '>'\n if (state.src.charCodeAt(pos) === 0x20 /* space */) {\n // ' > test '\n // ^ -- position start of line here:\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n spaceAfterMarker = true;\n } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {\n spaceAfterMarker = true;\n\n if ((state.bsCount[startLine] + offset) % 4 === 3) {\n // ' >\\t test '\n // ^ -- position start of line here (tab has width===1)\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n } else {\n // ' >\\t test '\n // ^ -- position start of line here + shift bsCount slightly\n // to make extra space appear\n adjustTab = true;\n }\n } else {\n spaceAfterMarker = false;\n }\n\n oldBMarks = [ state.bMarks[startLine] ];\n state.bMarks[startLine] = pos;\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[startLine] + (adjustTab ? 1 : 0)) % 4;\n } else {\n offset++;\n }\n } else {\n break;\n }\n\n pos++;\n }\n\n oldBSCount = [ state.bsCount[startLine] ];\n state.bsCount[startLine] = state.sCount[startLine] + 1 + (spaceAfterMarker ? 1 : 0);\n\n lastLineEmpty = pos >= max;\n\n oldSCount = [ state.sCount[startLine] ];\n state.sCount[startLine] = offset - initial;\n\n oldTShift = [ state.tShift[startLine] ];\n state.tShift[startLine] = pos - state.bMarks[startLine];\n\n terminatorRules = state.md.block.ruler.getRules('blockquote');\n\n oldParentType = state.parentType;\n state.parentType = 'blockquote';\n wasOutdented = false;\n\n // Search the end of the block\n //\n // Block ends with either:\n // 1. an empty line outside:\n // ```\n // > test\n //\n // ```\n // 2. an empty line inside:\n // ```\n // >\n // test\n // ```\n // 3. another tag:\n // ```\n // > test\n // - - -\n // ```\n for (nextLine = startLine + 1; nextLine < endLine; nextLine++) {\n // check if it's outdented, i.e. it's inside list item and indented\n // less than said list item:\n //\n // ```\n // 1. anything\n // > current blockquote\n // 2. checking this line\n // ```\n if (state.sCount[nextLine] < state.blkIndent) wasOutdented = true;\n\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos >= max) {\n // Case 1: line is not inside the blockquote, and this line is empty.\n break;\n }\n\n if (state.src.charCodeAt(pos++) === 0x3E/* > */ && !wasOutdented) {\n // This line is inside the blockquote.\n\n // skip spaces after \">\" and re-calculate offset\n initial = offset = state.sCount[nextLine] + pos - (state.bMarks[nextLine] + state.tShift[nextLine]);\n\n // skip one optional space after '>'\n if (state.src.charCodeAt(pos) === 0x20 /* space */) {\n // ' > test '\n // ^ -- position start of line here:\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n spaceAfterMarker = true;\n } else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {\n spaceAfterMarker = true;\n\n if ((state.bsCount[nextLine] + offset) % 4 === 3) {\n // ' >\\t test '\n // ^ -- position start of line here (tab has width===1)\n pos++;\n initial++;\n offset++;\n adjustTab = false;\n } else {\n // ' >\\t test '\n // ^ -- position start of line here + shift bsCount slightly\n // to make extra space appear\n adjustTab = true;\n }\n } else {\n spaceAfterMarker = false;\n }\n\n oldBMarks.push(state.bMarks[nextLine]);\n state.bMarks[nextLine] = pos;\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[nextLine] + (adjustTab ? 1 : 0)) % 4;\n } else {\n offset++;\n }\n } else {\n break;\n }\n\n pos++;\n }\n\n lastLineEmpty = pos >= max;\n\n oldBSCount.push(state.bsCount[nextLine]);\n state.bsCount[nextLine] = state.sCount[nextLine] + 1 + (spaceAfterMarker ? 1 : 0);\n\n oldSCount.push(state.sCount[nextLine]);\n state.sCount[nextLine] = offset - initial;\n\n oldTShift.push(state.tShift[nextLine]);\n state.tShift[nextLine] = pos - state.bMarks[nextLine];\n continue;\n }\n\n // Case 2: line is not inside the blockquote, and the last line was empty.\n if (lastLineEmpty) { break; }\n\n // Case 3: another tag found.\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n\n if (terminate) {\n // Quirk to enforce \"hard termination mode\" for paragraphs;\n // normally if you call `tokenize(state, startLine, nextLine)`,\n // paragraphs will look below nextLine for paragraph continuation,\n // but if blockquote is terminated by another tag, they shouldn't\n state.lineMax = nextLine;\n\n if (state.blkIndent !== 0) {\n // state.blkIndent was non-zero, we now set it to zero,\n // so we need to re-calculate all offsets to appear as\n // if indent wasn't changed\n oldBMarks.push(state.bMarks[nextLine]);\n oldBSCount.push(state.bsCount[nextLine]);\n oldTShift.push(state.tShift[nextLine]);\n oldSCount.push(state.sCount[nextLine]);\n state.sCount[nextLine] -= state.blkIndent;\n }\n\n break;\n }\n\n oldBMarks.push(state.bMarks[nextLine]);\n oldBSCount.push(state.bsCount[nextLine]);\n oldTShift.push(state.tShift[nextLine]);\n oldSCount.push(state.sCount[nextLine]);\n\n // A negative indentation means that this is a paragraph continuation\n //\n state.sCount[nextLine] = -1;\n }\n\n oldIndent = state.blkIndent;\n state.blkIndent = 0;\n\n token = state.push('blockquote_open', 'blockquote', 1);\n token.markup = '>';\n token.map = lines = [ startLine, 0 ];\n\n state.md.block.tokenize(state, startLine, nextLine);\n\n token = state.push('blockquote_close', 'blockquote', -1);\n token.markup = '>';\n\n state.lineMax = oldLineMax;\n state.parentType = oldParentType;\n lines[1] = state.line;\n\n // Restore original tShift; this might not be necessary since the parser\n // has already been here, but just to make sure we can do that.\n for (i = 0; i < oldTShift.length; i++) {\n state.bMarks[i + startLine] = oldBMarks[i];\n state.tShift[i + startLine] = oldTShift[i];\n state.sCount[i + startLine] = oldSCount[i];\n state.bsCount[i + startLine] = oldBSCount[i];\n }\n state.blkIndent = oldIndent;\n\n return true;\n};\n","// Horizontal rule\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function hr(state, startLine, endLine, silent) {\n var marker, cnt, ch, token,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n marker = state.src.charCodeAt(pos++);\n\n // Check hr marker\n if (marker !== 0x2A/* * */ &&\n marker !== 0x2D/* - */ &&\n marker !== 0x5F/* _ */) {\n return false;\n }\n\n // markers can be mixed with spaces, but there should be at least 3 of them\n\n cnt = 1;\n while (pos < max) {\n ch = state.src.charCodeAt(pos++);\n if (ch !== marker && !isSpace(ch)) { return false; }\n if (ch === marker) { cnt++; }\n }\n\n if (cnt < 3) { return false; }\n\n if (silent) { return true; }\n\n state.line = startLine + 1;\n\n token = state.push('hr', 'hr', 0);\n token.map = [ startLine, state.line ];\n token.markup = Array(cnt + 1).join(String.fromCharCode(marker));\n\n return true;\n};\n","// Lists\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\n// Search `[-+*][\\n ]`, returns next pos after marker on success\n// or -1 on fail.\nfunction skipBulletListMarker(state, startLine) {\n var marker, pos, max, ch;\n\n pos = state.bMarks[startLine] + state.tShift[startLine];\n max = state.eMarks[startLine];\n\n marker = state.src.charCodeAt(pos++);\n // Check bullet\n if (marker !== 0x2A/* * */ &&\n marker !== 0x2D/* - */ &&\n marker !== 0x2B/* + */) {\n return -1;\n }\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n // \" -test \" - is not a list item\n return -1;\n }\n }\n\n return pos;\n}\n\n// Search `\\d+[.)][\\n ]`, returns next pos after marker on success\n// or -1 on fail.\nfunction skipOrderedListMarker(state, startLine) {\n var ch,\n start = state.bMarks[startLine] + state.tShift[startLine],\n pos = start,\n max = state.eMarks[startLine];\n\n // List marker should have at least 2 chars (digit + dot)\n if (pos + 1 >= max) { return -1; }\n\n ch = state.src.charCodeAt(pos++);\n\n if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) { return -1; }\n\n for (;;) {\n // EOL -> fail\n if (pos >= max) { return -1; }\n\n ch = state.src.charCodeAt(pos++);\n\n if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) {\n\n // List marker should have no more than 9 digits\n // (prevents integer overflow in browsers)\n if (pos - start >= 10) { return -1; }\n\n continue;\n }\n\n // found valid marker\n if (ch === 0x29/* ) */ || ch === 0x2e/* . */) {\n break;\n }\n\n return -1;\n }\n\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (!isSpace(ch)) {\n // \" 1.test \" - is not a list item\n return -1;\n }\n }\n return pos;\n}\n\nfunction markTightParagraphs(state, idx) {\n var i, l,\n level = state.level + 2;\n\n for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {\n if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {\n state.tokens[i + 2].hidden = true;\n state.tokens[i].hidden = true;\n i += 2;\n }\n }\n}\n\n\nmodule.exports = function list(state, startLine, endLine, silent) {\n var ch,\n contentStart,\n i,\n indent,\n indentAfterMarker,\n initial,\n isOrdered,\n itemLines,\n l,\n listLines,\n listTokIdx,\n markerCharCode,\n markerValue,\n max,\n nextLine,\n offset,\n oldListIndent,\n oldParentType,\n oldSCount,\n oldTShift,\n oldTight,\n pos,\n posAfterMarker,\n prevEmptyEnd,\n start,\n terminate,\n terminatorRules,\n token,\n isTerminatingParagraph = false,\n tight = true;\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n // Special case:\n // - item 1\n // - item 2\n // - item 3\n // - item 4\n // - this one is a paragraph continuation\n if (state.listIndent >= 0 &&\n state.sCount[startLine] - state.listIndent >= 4 &&\n state.sCount[startLine] < state.blkIndent) {\n return false;\n }\n\n // limit conditions when list can interrupt\n // a paragraph (validation mode only)\n if (silent && state.parentType === 'paragraph') {\n // Next list item should still terminate previous list item;\n //\n // This code can fail if plugins use blkIndent as well as lists,\n // but I hope the spec gets fixed long before that happens.\n //\n if (state.tShift[startLine] >= state.blkIndent) {\n isTerminatingParagraph = true;\n }\n }\n\n // Detect list type and position after marker\n if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {\n isOrdered = true;\n start = state.bMarks[startLine] + state.tShift[startLine];\n markerValue = Number(state.src.substr(start, posAfterMarker - start - 1));\n\n // If we're starting a new ordered list right after\n // a paragraph, it should start with 1.\n if (isTerminatingParagraph && markerValue !== 1) return false;\n\n } else if ((posAfterMarker = skipBulletListMarker(state, startLine)) >= 0) {\n isOrdered = false;\n\n } else {\n return false;\n }\n\n // If we're starting a new unordered list right after\n // a paragraph, first line should not be empty.\n if (isTerminatingParagraph) {\n if (state.skipSpaces(posAfterMarker) >= state.eMarks[startLine]) return false;\n }\n\n // We should terminate list on style change. Remember first one to compare.\n markerCharCode = state.src.charCodeAt(posAfterMarker - 1);\n\n // For validation mode we can terminate immediately\n if (silent) { return true; }\n\n // Start list\n listTokIdx = state.tokens.length;\n\n if (isOrdered) {\n token = state.push('ordered_list_open', 'ol', 1);\n if (markerValue !== 1) {\n token.attrs = [ [ 'start', markerValue ] ];\n }\n\n } else {\n token = state.push('bullet_list_open', 'ul', 1);\n }\n\n token.map = listLines = [ startLine, 0 ];\n token.markup = String.fromCharCode(markerCharCode);\n\n //\n // Iterate list items\n //\n\n nextLine = startLine;\n prevEmptyEnd = false;\n terminatorRules = state.md.block.ruler.getRules('list');\n\n oldParentType = state.parentType;\n state.parentType = 'list';\n\n while (nextLine < endLine) {\n pos = posAfterMarker;\n max = state.eMarks[nextLine];\n\n initial = offset = state.sCount[nextLine] + posAfterMarker - (state.bMarks[startLine] + state.tShift[startLine]);\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (ch === 0x09) {\n offset += 4 - (offset + state.bsCount[nextLine]) % 4;\n } else if (ch === 0x20) {\n offset++;\n } else {\n break;\n }\n\n pos++;\n }\n\n contentStart = pos;\n\n if (contentStart >= max) {\n // trimming space in \"- \\n 3\" case, indent is 1 here\n indentAfterMarker = 1;\n } else {\n indentAfterMarker = offset - initial;\n }\n\n // If we have more than 4 spaces, the indent is 1\n // (the rest is just indented code block)\n if (indentAfterMarker > 4) { indentAfterMarker = 1; }\n\n // \" - test\"\n // ^^^^^ - calculating total length of this thing\n indent = initial + indentAfterMarker;\n\n // Run subparser & write tokens\n token = state.push('list_item_open', 'li', 1);\n token.markup = String.fromCharCode(markerCharCode);\n token.map = itemLines = [ startLine, 0 ];\n\n // change current state, then restore it after parser subcall\n oldTight = state.tight;\n oldTShift = state.tShift[startLine];\n oldSCount = state.sCount[startLine];\n\n // - example list\n // ^ listIndent position will be here\n // ^ blkIndent position will be here\n //\n oldListIndent = state.listIndent;\n state.listIndent = state.blkIndent;\n state.blkIndent = indent;\n\n state.tight = true;\n state.tShift[startLine] = contentStart - state.bMarks[startLine];\n state.sCount[startLine] = offset;\n\n if (contentStart >= max && state.isEmpty(startLine + 1)) {\n // workaround for this case\n // (list item is empty, list terminates before \"foo\"):\n // ~~~~~~~~\n // -\n //\n // foo\n // ~~~~~~~~\n state.line = Math.min(state.line + 2, endLine);\n } else {\n state.md.block.tokenize(state, startLine, endLine, true);\n }\n\n // If any of list item is tight, mark list as tight\n if (!state.tight || prevEmptyEnd) {\n tight = false;\n }\n // Item become loose if finish with empty line,\n // but we should filter last element, because it means list finish\n prevEmptyEnd = (state.line - startLine) > 1 && state.isEmpty(state.line - 1);\n\n state.blkIndent = state.listIndent;\n state.listIndent = oldListIndent;\n state.tShift[startLine] = oldTShift;\n state.sCount[startLine] = oldSCount;\n state.tight = oldTight;\n\n token = state.push('list_item_close', 'li', -1);\n token.markup = String.fromCharCode(markerCharCode);\n\n nextLine = startLine = state.line;\n itemLines[1] = nextLine;\n contentStart = state.bMarks[startLine];\n\n if (nextLine >= endLine) { break; }\n\n //\n // Try to check if list is terminated or continued.\n //\n if (state.sCount[nextLine] < state.blkIndent) { break; }\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { break; }\n\n // fail if terminating block found\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n if (terminate) { break; }\n\n // fail if list has another type\n if (isOrdered) {\n posAfterMarker = skipOrderedListMarker(state, nextLine);\n if (posAfterMarker < 0) { break; }\n } else {\n posAfterMarker = skipBulletListMarker(state, nextLine);\n if (posAfterMarker < 0) { break; }\n }\n\n if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { break; }\n }\n\n // Finalize list\n if (isOrdered) {\n token = state.push('ordered_list_close', 'ol', -1);\n } else {\n token = state.push('bullet_list_close', 'ul', -1);\n }\n token.markup = String.fromCharCode(markerCharCode);\n\n listLines[1] = nextLine;\n state.line = nextLine;\n\n state.parentType = oldParentType;\n\n // mark paragraphs tight if needed\n if (tight) {\n markTightParagraphs(state, listTokIdx);\n }\n\n return true;\n};\n","'use strict';\n\n\nvar normalizeReference = require('../common/utils').normalizeReference;\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function reference(state, startLine, _endLine, silent) {\n var ch,\n destEndPos,\n destEndLineNo,\n endLine,\n href,\n i,\n l,\n label,\n labelEnd,\n oldParentType,\n res,\n start,\n str,\n terminate,\n terminatorRules,\n title,\n lines = 0,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine],\n nextLine = startLine + 1;\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n if (state.src.charCodeAt(pos) !== 0x5B/* [ */) { return false; }\n\n // Simple check to quickly interrupt scan on [link](url) at the start of line.\n // Can be useful on practice: https://github.com/markdown-it/markdown-it/issues/54\n while (++pos < max) {\n if (state.src.charCodeAt(pos) === 0x5D /* ] */ &&\n state.src.charCodeAt(pos - 1) !== 0x5C/* \\ */) {\n if (pos + 1 === max) { return false; }\n if (state.src.charCodeAt(pos + 1) !== 0x3A/* : */) { return false; }\n break;\n }\n }\n\n endLine = state.lineMax;\n\n // jump line-by-line until empty one or EOF\n terminatorRules = state.md.block.ruler.getRules('reference');\n\n oldParentType = state.parentType;\n state.parentType = 'reference';\n\n for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {\n // this would be a code block normally, but after paragraph\n // it's considered a lazy continuation regardless of what's there\n if (state.sCount[nextLine] - state.blkIndent > 3) { continue; }\n\n // quirk for blockquotes, this line should already be checked by that rule\n if (state.sCount[nextLine] < 0) { continue; }\n\n // Some tags can terminate paragraph without empty line.\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n if (terminate) { break; }\n }\n\n str = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n max = str.length;\n\n for (pos = 1; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n if (ch === 0x5B /* [ */) {\n return false;\n } else if (ch === 0x5D /* ] */) {\n labelEnd = pos;\n break;\n } else if (ch === 0x0A /* \\n */) {\n lines++;\n } else if (ch === 0x5C /* \\ */) {\n pos++;\n if (pos < max && str.charCodeAt(pos) === 0x0A) {\n lines++;\n }\n }\n }\n\n if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false; }\n\n // [label]: destination 'title'\n // ^^^ skip optional whitespace here\n for (pos = labelEnd + 2; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n if (ch === 0x0A) {\n lines++;\n } else if (isSpace(ch)) {\n /*eslint no-empty:0*/\n } else {\n break;\n }\n }\n\n // [label]: destination 'title'\n // ^^^^^^^^^^^ parse this\n res = state.md.helpers.parseLinkDestination(str, pos, max);\n if (!res.ok) { return false; }\n\n href = state.md.normalizeLink(res.str);\n if (!state.md.validateLink(href)) { return false; }\n\n pos = res.pos;\n lines += res.lines;\n\n // save cursor state, we could require to rollback later\n destEndPos = pos;\n destEndLineNo = lines;\n\n // [label]: destination 'title'\n // ^^^ skipping those spaces\n start = pos;\n for (; pos < max; pos++) {\n ch = str.charCodeAt(pos);\n if (ch === 0x0A) {\n lines++;\n } else if (isSpace(ch)) {\n /*eslint no-empty:0*/\n } else {\n break;\n }\n }\n\n // [label]: destination 'title'\n // ^^^^^^^ parse this\n res = state.md.helpers.parseLinkTitle(str, pos, max);\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos;\n lines += res.lines;\n } else {\n title = '';\n pos = destEndPos;\n lines = destEndLineNo;\n }\n\n // skip trailing spaces until the rest of the line\n while (pos < max) {\n ch = str.charCodeAt(pos);\n if (!isSpace(ch)) { break; }\n pos++;\n }\n\n if (pos < max && str.charCodeAt(pos) !== 0x0A) {\n if (title) {\n // garbage at the end of the line after title,\n // but it could still be a valid reference if we roll back\n title = '';\n pos = destEndPos;\n lines = destEndLineNo;\n while (pos < max) {\n ch = str.charCodeAt(pos);\n if (!isSpace(ch)) { break; }\n pos++;\n }\n }\n }\n\n if (pos < max && str.charCodeAt(pos) !== 0x0A) {\n // garbage at the end of the line\n return false;\n }\n\n label = normalizeReference(str.slice(1, labelEnd));\n if (!label) {\n // CommonMark 0.20 disallows empty labels\n return false;\n }\n\n // Reference can not terminate anything. This check is for safety only.\n /*istanbul ignore if*/\n if (silent) { return true; }\n\n if (typeof state.env.references === 'undefined') {\n state.env.references = {};\n }\n if (typeof state.env.references[label] === 'undefined') {\n state.env.references[label] = { title: title, href: href };\n }\n\n state.parentType = oldParentType;\n\n state.line = startLine + lines + 1;\n return true;\n};\n","// heading (#, ##, ...)\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function heading(state, startLine, endLine, silent) {\n var ch, level, tmp, token,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x23/* # */ || pos >= max) { return false; }\n\n // count heading level\n level = 1;\n ch = state.src.charCodeAt(++pos);\n while (ch === 0x23/* # */ && pos < max && level <= 6) {\n level++;\n ch = state.src.charCodeAt(++pos);\n }\n\n if (level > 6 || (pos < max && !isSpace(ch))) { return false; }\n\n if (silent) { return true; }\n\n // Let's cut tails like ' ### ' from the end of string\n\n max = state.skipSpacesBack(max, pos);\n tmp = state.skipCharsBack(max, 0x23, pos); // #\n if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1))) {\n max = tmp;\n }\n\n state.line = startLine + 1;\n\n token = state.push('heading_open', 'h' + String(level), 1);\n token.markup = '########'.slice(0, level);\n token.map = [ startLine, state.line ];\n\n token = state.push('inline', '', 0);\n token.content = state.src.slice(pos, max).trim();\n token.map = [ startLine, state.line ];\n token.children = [];\n\n token = state.push('heading_close', 'h' + String(level), -1);\n token.markup = '########'.slice(0, level);\n\n return true;\n};\n","// lheading (---, ===)\n\n'use strict';\n\n\nmodule.exports = function lheading(state, startLine, endLine/*, silent*/) {\n var content, terminate, i, l, token, pos, max, level, marker,\n nextLine = startLine + 1, oldParentType,\n terminatorRules = state.md.block.ruler.getRules('paragraph');\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n oldParentType = state.parentType;\n state.parentType = 'paragraph'; // use paragraph to match terminatorRules\n\n // jump line-by-line until empty one or EOF\n for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {\n // this would be a code block normally, but after paragraph\n // it's considered a lazy continuation regardless of what's there\n if (state.sCount[nextLine] - state.blkIndent > 3) { continue; }\n\n //\n // Check for underline in setext header\n //\n if (state.sCount[nextLine] >= state.blkIndent) {\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n\n if (pos < max) {\n marker = state.src.charCodeAt(pos);\n\n if (marker === 0x2D/* - */ || marker === 0x3D/* = */) {\n pos = state.skipChars(pos, marker);\n pos = state.skipSpaces(pos);\n\n if (pos >= max) {\n level = (marker === 0x3D/* = */ ? 1 : 2);\n break;\n }\n }\n }\n }\n\n // quirk for blockquotes, this line should already be checked by that rule\n if (state.sCount[nextLine] < 0) { continue; }\n\n // Some tags can terminate paragraph without empty line.\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n if (terminate) { break; }\n }\n\n if (!level) {\n // Didn't find valid underline\n return false;\n }\n\n content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n\n state.line = nextLine + 1;\n\n token = state.push('heading_open', 'h' + String(level), 1);\n token.markup = String.fromCharCode(marker);\n token.map = [ startLine, state.line ];\n\n token = state.push('inline', '', 0);\n token.content = content;\n token.map = [ startLine, state.line - 1 ];\n token.children = [];\n\n token = state.push('heading_close', 'h' + String(level), -1);\n token.markup = String.fromCharCode(marker);\n\n state.parentType = oldParentType;\n\n return true;\n};\n","// HTML block\n\n'use strict';\n\n\nvar block_names = require('../common/html_blocks');\nvar HTML_OPEN_CLOSE_TAG_RE = require('../common/html_re').HTML_OPEN_CLOSE_TAG_RE;\n\n// An array of opening and corresponding closing sequences for html tags,\n// last argument defines whether it can terminate a paragraph or not\n//\nvar HTML_SEQUENCES = [\n [ /^<(script|pre|style)(?=(\\s|>|$))/i, /<\\/(script|pre|style)>/i, true ],\n [ /^<!--/, /-->/, true ],\n [ /^<\\?/, /\\?>/, true ],\n [ /^<![A-Z]/, />/, true ],\n [ /^<!\\[CDATA\\[/, /\\]\\]>/, true ],\n [ new RegExp('^</?(' + block_names.join('|') + ')(?=(\\\\s|/?>|$))', 'i'), /^$/, true ],\n [ new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\\\s*$'), /^$/, false ]\n];\n\n\nmodule.exports = function html_block(state, startLine, endLine, silent) {\n var i, nextLine, token, lineText,\n pos = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // if it's indented more than 3 spaces, it should be a code block\n if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }\n\n if (!state.md.options.html) { return false; }\n\n if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }\n\n lineText = state.src.slice(pos, max);\n\n for (i = 0; i < HTML_SEQUENCES.length; i++) {\n if (HTML_SEQUENCES[i][0].test(lineText)) { break; }\n }\n\n if (i === HTML_SEQUENCES.length) { return false; }\n\n if (silent) {\n // true if this sequence can be a terminator, false otherwise\n return HTML_SEQUENCES[i][2];\n }\n\n nextLine = startLine + 1;\n\n // If we are here - we detected HTML block.\n // Let's roll down till block end.\n if (!HTML_SEQUENCES[i][1].test(lineText)) {\n for (; nextLine < endLine; nextLine++) {\n if (state.sCount[nextLine] < state.blkIndent) { break; }\n\n pos = state.bMarks[nextLine] + state.tShift[nextLine];\n max = state.eMarks[nextLine];\n lineText = state.src.slice(pos, max);\n\n if (HTML_SEQUENCES[i][1].test(lineText)) {\n if (lineText.length !== 0) { nextLine++; }\n break;\n }\n }\n }\n\n state.line = nextLine;\n\n token = state.push('html_block', '', 0);\n token.map = [ startLine, nextLine ];\n token.content = state.getLines(startLine, nextLine, state.blkIndent, true);\n\n return true;\n};\n","// List of valid html blocks names, accorting to commonmark spec\n// http://jgm.github.io/CommonMark/spec.html#html-blocks\n\n'use strict';\n\n\nmodule.exports = [\n 'address',\n 'article',\n 'aside',\n 'base',\n 'basefont',\n 'blockquote',\n 'body',\n 'caption',\n 'center',\n 'col',\n 'colgroup',\n 'dd',\n 'details',\n 'dialog',\n 'dir',\n 'div',\n 'dl',\n 'dt',\n 'fieldset',\n 'figcaption',\n 'figure',\n 'footer',\n 'form',\n 'frame',\n 'frameset',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'head',\n 'header',\n 'hr',\n 'html',\n 'iframe',\n 'legend',\n 'li',\n 'link',\n 'main',\n 'menu',\n 'menuitem',\n 'meta',\n 'nav',\n 'noframes',\n 'ol',\n 'optgroup',\n 'option',\n 'p',\n 'param',\n 'section',\n 'source',\n 'summary',\n 'table',\n 'tbody',\n 'td',\n 'tfoot',\n 'th',\n 'thead',\n 'title',\n 'tr',\n 'track',\n 'ul'\n];\n","// Paragraph\n\n'use strict';\n\n\nmodule.exports = function paragraph(state, startLine/*, endLine*/) {\n var content, terminate, i, l, token, oldParentType,\n nextLine = startLine + 1,\n terminatorRules = state.md.block.ruler.getRules('paragraph'),\n endLine = state.lineMax;\n\n oldParentType = state.parentType;\n state.parentType = 'paragraph';\n\n // jump line-by-line until empty one or EOF\n for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {\n // this would be a code block normally, but after paragraph\n // it's considered a lazy continuation regardless of what's there\n if (state.sCount[nextLine] - state.blkIndent > 3) { continue; }\n\n // quirk for blockquotes, this line should already be checked by that rule\n if (state.sCount[nextLine] < 0) { continue; }\n\n // Some tags can terminate paragraph without empty line.\n terminate = false;\n for (i = 0, l = terminatorRules.length; i < l; i++) {\n if (terminatorRules[i](state, nextLine, endLine, true)) {\n terminate = true;\n break;\n }\n }\n if (terminate) { break; }\n }\n\n content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();\n\n state.line = nextLine;\n\n token = state.push('paragraph_open', 'p', 1);\n token.map = [ startLine, state.line ];\n\n token = state.push('inline', '', 0);\n token.content = content;\n token.map = [ startLine, state.line ];\n token.children = [];\n\n token = state.push('paragraph_close', 'p', -1);\n\n state.parentType = oldParentType;\n\n return true;\n};\n","// Parser state class\n\n'use strict';\n\nvar Token = require('../token');\nvar isSpace = require('../common/utils').isSpace;\n\n\nfunction StateBlock(src, md, env, tokens) {\n var ch, s, start, pos, len, indent, offset, indent_found;\n\n this.src = src;\n\n // link to parser instance\n this.md = md;\n\n this.env = env;\n\n //\n // Internal state vartiables\n //\n\n this.tokens = tokens;\n\n this.bMarks = []; // line begin offsets for fast jumps\n this.eMarks = []; // line end offsets for fast jumps\n this.tShift = []; // offsets of the first non-space characters (tabs not expanded)\n this.sCount = []; // indents for each line (tabs expanded)\n\n // An amount of virtual spaces (tabs expanded) between beginning\n // of each line (bMarks) and real beginning of that line.\n //\n // It exists only as a hack because blockquotes override bMarks\n // losing information in the process.\n //\n // It's used only when expanding tabs, you can think about it as\n // an initial tab length, e.g. bsCount=21 applied to string `\\t123`\n // means first tab should be expanded to 4-21%4 === 3 spaces.\n //\n this.bsCount = [];\n\n // block parser variables\n this.blkIndent = 0; // required block content indent (for example, if we are\n // inside a list, it would be positioned after list marker)\n this.line = 0; // line index in src\n this.lineMax = 0; // lines count\n this.tight = false; // loose/tight mode for lists\n this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)\n this.listIndent = -1; // indent of the current list block (-1 if there isn't any)\n\n // can be 'blockquote', 'list', 'root', 'paragraph' or 'reference'\n // used in lists to determine if they interrupt a paragraph\n this.parentType = 'root';\n\n this.level = 0;\n\n // renderer\n this.result = '';\n\n // Create caches\n // Generate markers.\n s = this.src;\n indent_found = false;\n\n for (start = pos = indent = offset = 0, len = s.length; pos < len; pos++) {\n ch = s.charCodeAt(pos);\n\n if (!indent_found) {\n if (isSpace(ch)) {\n indent++;\n\n if (ch === 0x09) {\n offset += 4 - offset % 4;\n } else {\n offset++;\n }\n continue;\n } else {\n indent_found = true;\n }\n }\n\n if (ch === 0x0A || pos === len - 1) {\n if (ch !== 0x0A) { pos++; }\n this.bMarks.push(start);\n this.eMarks.push(pos);\n this.tShift.push(indent);\n this.sCount.push(offset);\n this.bsCount.push(0);\n\n indent_found = false;\n indent = 0;\n offset = 0;\n start = pos + 1;\n }\n }\n\n // Push fake entry to simplify cache bounds checks\n this.bMarks.push(s.length);\n this.eMarks.push(s.length);\n this.tShift.push(0);\n this.sCount.push(0);\n this.bsCount.push(0);\n\n this.lineMax = this.bMarks.length - 1; // don't count last fake line\n}\n\n// Push new token to \"stream\".\n//\nStateBlock.prototype.push = function (type, tag, nesting) {\n var token = new Token(type, tag, nesting);\n token.block = true;\n\n if (nesting < 0) this.level--; // closing tag\n token.level = this.level;\n if (nesting > 0) this.level++; // opening tag\n\n this.tokens.push(token);\n return token;\n};\n\nStateBlock.prototype.isEmpty = function isEmpty(line) {\n return this.bMarks[line] + this.tShift[line] >= this.eMarks[line];\n};\n\nStateBlock.prototype.skipEmptyLines = function skipEmptyLines(from) {\n for (var max = this.lineMax; from < max; from++) {\n if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) {\n break;\n }\n }\n return from;\n};\n\n// Skip spaces from given position.\nStateBlock.prototype.skipSpaces = function skipSpaces(pos) {\n var ch;\n\n for (var max = this.src.length; pos < max; pos++) {\n ch = this.src.charCodeAt(pos);\n if (!isSpace(ch)) { break; }\n }\n return pos;\n};\n\n// Skip spaces from given position in reverse.\nStateBlock.prototype.skipSpacesBack = function skipSpacesBack(pos, min) {\n if (pos <= min) { return pos; }\n\n while (pos > min) {\n if (!isSpace(this.src.charCodeAt(--pos))) { return pos + 1; }\n }\n return pos;\n};\n\n// Skip char codes from given position\nStateBlock.prototype.skipChars = function skipChars(pos, code) {\n for (var max = this.src.length; pos < max; pos++) {\n if (this.src.charCodeAt(pos) !== code) { break; }\n }\n return pos;\n};\n\n// Skip char codes reverse from given position - 1\nStateBlock.prototype.skipCharsBack = function skipCharsBack(pos, code, min) {\n if (pos <= min) { return pos; }\n\n while (pos > min) {\n if (code !== this.src.charCodeAt(--pos)) { return pos + 1; }\n }\n return pos;\n};\n\n// cut lines range from source.\nStateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF) {\n var i, lineIndent, ch, first, last, queue, lineStart,\n line = begin;\n\n if (begin >= end) {\n return '';\n }\n\n queue = new Array(end - begin);\n\n for (i = 0; line < end; line++, i++) {\n lineIndent = 0;\n lineStart = first = this.bMarks[line];\n\n if (line + 1 < end || keepLastLF) {\n // No need for bounds check because we have fake entry on tail.\n last = this.eMarks[line] + 1;\n } else {\n last = this.eMarks[line];\n }\n\n while (first < last && lineIndent < indent) {\n ch = this.src.charCodeAt(first);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n lineIndent += 4 - (lineIndent + this.bsCount[line]) % 4;\n } else {\n lineIndent++;\n }\n } else if (first - lineStart < this.tShift[line]) {\n // patched tShift masked characters to look like spaces (blockquotes, list markers)\n lineIndent++;\n } else {\n break;\n }\n\n first++;\n }\n\n if (lineIndent > indent) {\n // partially expanding tabs in code blocks, e.g '\\t\\tfoobar'\n // with indent=2 becomes ' \\tfoobar'\n queue[i] = new Array(lineIndent - indent + 1).join(' ') + this.src.slice(first, last);\n } else {\n queue[i] = this.src.slice(first, last);\n }\n }\n\n return queue.join('');\n};\n\n// re-export Token class to use in block rules\nStateBlock.prototype.Token = Token;\n\n\nmodule.exports = StateBlock;\n","/** internal\n * class ParserInline\n *\n * Tokenizes paragraph content.\n **/\n'use strict';\n\n\nvar Ruler = require('./ruler');\n\n\n////////////////////////////////////////////////////////////////////////////////\n// Parser rules\n\nvar _rules = [\n [ 'text', require('./rules_inline/text') ],\n [ 'newline', require('./rules_inline/newline') ],\n [ 'escape', require('./rules_inline/escape') ],\n [ 'backticks', require('./rules_inline/backticks') ],\n [ 'strikethrough', require('./rules_inline/strikethrough').tokenize ],\n [ 'emphasis', require('./rules_inline/emphasis').tokenize ],\n [ 'link', require('./rules_inline/link') ],\n [ 'image', require('./rules_inline/image') ],\n [ 'autolink', require('./rules_inline/autolink') ],\n [ 'html_inline', require('./rules_inline/html_inline') ],\n [ 'entity', require('./rules_inline/entity') ]\n];\n\nvar _rules2 = [\n [ 'balance_pairs', require('./rules_inline/balance_pairs') ],\n [ 'strikethrough', require('./rules_inline/strikethrough').postProcess ],\n [ 'emphasis', require('./rules_inline/emphasis').postProcess ],\n [ 'text_collapse', require('./rules_inline/text_collapse') ]\n];\n\n\n/**\n * new ParserInline()\n **/\nfunction ParserInline() {\n var i;\n\n /**\n * ParserInline#ruler -> Ruler\n *\n * [[Ruler]] instance. Keep configuration of inline rules.\n **/\n this.ruler = new Ruler();\n\n for (i = 0; i < _rules.length; i++) {\n this.ruler.push(_rules[i][0], _rules[i][1]);\n }\n\n /**\n * ParserInline#ruler2 -> Ruler\n *\n * [[Ruler]] instance. Second ruler used for post-processing\n * (e.g. in emphasis-like rules).\n **/\n this.ruler2 = new Ruler();\n\n for (i = 0; i < _rules2.length; i++) {\n this.ruler2.push(_rules2[i][0], _rules2[i][1]);\n }\n}\n\n\n// Skip single token by running all rules in validation mode;\n// returns `true` if any rule reported success\n//\nParserInline.prototype.skipToken = function (state) {\n var ok, i, pos = state.pos,\n rules = this.ruler.getRules(''),\n len = rules.length,\n maxNesting = state.md.options.maxNesting,\n cache = state.cache;\n\n\n if (typeof cache[pos] !== 'undefined') {\n state.pos = cache[pos];\n return;\n }\n\n if (state.level < maxNesting) {\n for (i = 0; i < len; i++) {\n // Increment state.level and decrement it later to limit recursion.\n // It's harmless to do here, because no tokens are created. But ideally,\n // we'd need a separate private state variable for this purpose.\n //\n state.level++;\n ok = rules[i](state, true);\n state.level--;\n\n if (ok) { break; }\n }\n } else {\n // Too much nesting, just skip until the end of the paragraph.\n //\n // NOTE: this will cause links to behave incorrectly in the following case,\n // when an amount of `[` is exactly equal to `maxNesting + 1`:\n //\n // [[[[[[[[[[[[[[[[[[[[[foo]()\n //\n // TODO: remove this workaround when CM standard will allow nested links\n // (we can replace it by preventing links from being parsed in\n // validation mode)\n //\n state.pos = state.posMax;\n }\n\n if (!ok) { state.pos++; }\n cache[pos] = state.pos;\n};\n\n\n// Generate tokens for input range\n//\nParserInline.prototype.tokenize = function (state) {\n var ok, i,\n rules = this.ruler.getRules(''),\n len = rules.length,\n end = state.posMax,\n maxNesting = state.md.options.maxNesting;\n\n while (state.pos < end) {\n // Try all possible rules.\n // On success, rule should:\n //\n // - update `state.pos`\n // - update `state.tokens`\n // - return true\n\n if (state.level < maxNesting) {\n for (i = 0; i < len; i++) {\n ok = rules[i](state, false);\n if (ok) { break; }\n }\n }\n\n if (ok) {\n if (state.pos >= end) { break; }\n continue;\n }\n\n state.pending += state.src[state.pos++];\n }\n\n if (state.pending) {\n state.pushPending();\n }\n};\n\n\n/**\n * ParserInline.parse(str, md, env, outTokens)\n *\n * Process input string and push inline tokens into `outTokens`\n **/\nParserInline.prototype.parse = function (str, md, env, outTokens) {\n var i, rules, len;\n var state = new this.State(str, md, env, outTokens);\n\n this.tokenize(state);\n\n rules = this.ruler2.getRules('');\n len = rules.length;\n\n for (i = 0; i < len; i++) {\n rules[i](state);\n }\n};\n\n\nParserInline.prototype.State = require('./rules_inline/state_inline');\n\n\nmodule.exports = ParserInline;\n","// Skip text characters for text token, place those to pending buffer\n// and increment current pos\n\n'use strict';\n\n\n// Rule to skip pure text\n// '{}$%@~+=:' reserved for extentions\n\n// !, \", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \\, ], ^, _, `, {, |, }, or ~\n\n// !!!! Don't confuse with \"Markdown ASCII Punctuation\" chars\n// http://spec.commonmark.org/0.15/#ascii-punctuation-character\nfunction isTerminatorChar(ch) {\n switch (ch) {\n case 0x0A/* \\n */:\n case 0x21/* ! */:\n case 0x23/* # */:\n case 0x24/* $ */:\n case 0x25/* % */:\n case 0x26/* & */:\n case 0x2A/* * */:\n case 0x2B/* + */:\n case 0x2D/* - */:\n case 0x3A/* : */:\n case 0x3C/* < */:\n case 0x3D/* = */:\n case 0x3E/* > */:\n case 0x40/* @ */:\n case 0x5B/* [ */:\n case 0x5C/* \\ */:\n case 0x5D/* ] */:\n case 0x5E/* ^ */:\n case 0x5F/* _ */:\n case 0x60/* ` */:\n case 0x7B/* { */:\n case 0x7D/* } */:\n case 0x7E/* ~ */:\n return true;\n default:\n return false;\n }\n}\n\nmodule.exports = function text(state, silent) {\n var pos = state.pos;\n\n while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) {\n pos++;\n }\n\n if (pos === state.pos) { return false; }\n\n if (!silent) { state.pending += state.src.slice(state.pos, pos); }\n\n state.pos = pos;\n\n return true;\n};\n\n// Alternative implementation, for memory.\n//\n// It costs 10% of performance, but allows extend terminators list, if place it\n// to `ParcerInline` property. Probably, will switch to it sometime, such\n// flexibility required.\n\n/*\nvar TERMINATOR_RE = /[\\n!#$%&*+\\-:<=>@[\\\\\\]^_`{}~]/;\n\nmodule.exports = function text(state, silent) {\n var pos = state.pos,\n idx = state.src.slice(pos).search(TERMINATOR_RE);\n\n // first char is terminator -> empty text\n if (idx === 0) { return false; }\n\n // no terminator -> text till end of string\n if (idx < 0) {\n if (!silent) { state.pending += state.src.slice(pos); }\n state.pos = state.src.length;\n return true;\n }\n\n if (!silent) { state.pending += state.src.slice(pos, pos + idx); }\n\n state.pos += idx;\n\n return true;\n};*/\n","// Proceess '\\n'\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function newline(state, silent) {\n var pmax, max, pos = state.pos;\n\n if (state.src.charCodeAt(pos) !== 0x0A/* \\n */) { return false; }\n\n pmax = state.pending.length - 1;\n max = state.posMax;\n\n // ' \\n' -> hardbreak\n // Lookup in pending chars is bad practice! Don't copy to other rules!\n // Pending string is stored in concat mode, indexed lookups will cause\n // convertion to flat mode.\n if (!silent) {\n if (pmax >= 0 && state.pending.charCodeAt(pmax) === 0x20) {\n if (pmax >= 1 && state.pending.charCodeAt(pmax - 1) === 0x20) {\n state.pending = state.pending.replace(/ +$/, '');\n state.push('hardbreak', 'br', 0);\n } else {\n state.pending = state.pending.slice(0, -1);\n state.push('softbreak', 'br', 0);\n }\n\n } else {\n state.push('softbreak', 'br', 0);\n }\n }\n\n pos++;\n\n // skip heading spaces for next line\n while (pos < max && isSpace(state.src.charCodeAt(pos))) { pos++; }\n\n state.pos = pos;\n return true;\n};\n","// Process escaped chars and hardbreaks\n\n'use strict';\n\nvar isSpace = require('../common/utils').isSpace;\n\nvar ESCAPED = [];\n\nfor (var i = 0; i < 256; i++) { ESCAPED.push(0); }\n\n'\\\\!\"#$%&\\'()*+,./:;<=>?@[]^_`{|}~-'\n .split('').forEach(function (ch) { ESCAPED[ch.charCodeAt(0)] = 1; });\n\n\nmodule.exports = function escape(state, silent) {\n var ch, pos = state.pos, max = state.posMax;\n\n if (state.src.charCodeAt(pos) !== 0x5C/* \\ */) { return false; }\n\n pos++;\n\n if (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (ch < 256 && ESCAPED[ch] !== 0) {\n if (!silent) { state.pending += state.src[pos]; }\n state.pos += 2;\n return true;\n }\n\n if (ch === 0x0A) {\n if (!silent) {\n state.push('hardbreak', 'br', 0);\n }\n\n pos++;\n // skip leading whitespaces from next line\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n if (!isSpace(ch)) { break; }\n pos++;\n }\n\n state.pos = pos;\n return true;\n }\n }\n\n if (!silent) { state.pending += '\\\\'; }\n state.pos++;\n return true;\n};\n","// Parse backticks\n\n'use strict';\n\nmodule.exports = function backtick(state, silent) {\n var start, max, marker, matchStart, matchEnd, token,\n pos = state.pos,\n ch = state.src.charCodeAt(pos);\n\n if (ch !== 0x60/* ` */) { return false; }\n\n start = pos;\n pos++;\n max = state.posMax;\n\n while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; }\n\n marker = state.src.slice(start, pos);\n\n matchStart = matchEnd = pos;\n\n while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) {\n matchEnd = matchStart + 1;\n\n while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; }\n\n if (matchEnd - matchStart === marker.length) {\n if (!silent) {\n token = state.push('code_inline', 'code', 0);\n token.markup = marker;\n token.content = state.src.slice(pos, matchStart)\n .replace(/\\n/g, ' ')\n .replace(/^ (.+) $/, '$1');\n }\n state.pos = matchEnd;\n return true;\n }\n }\n\n if (!silent) { state.pending += marker; }\n state.pos += marker.length;\n return true;\n};\n","// Process [link](<to> \"stuff\")\n\n'use strict';\n\nvar normalizeReference = require('../common/utils').normalizeReference;\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function link(state, silent) {\n var attrs,\n code,\n label,\n labelEnd,\n labelStart,\n pos,\n res,\n ref,\n title,\n token,\n href = '',\n oldPos = state.pos,\n max = state.posMax,\n start = state.pos,\n parseReference = true;\n\n if (state.src.charCodeAt(state.pos) !== 0x5B/* [ */) { return false; }\n\n labelStart = state.pos + 1;\n labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, true);\n\n // parser failed to find ']', so it's not a valid link\n if (labelEnd < 0) { return false; }\n\n pos = labelEnd + 1;\n if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {\n //\n // Inline link\n //\n\n // might have found a valid shortcut link, disable reference parsing\n parseReference = false;\n\n // [link]( <href> \"title\" )\n // ^^ skipping these spaces\n pos++;\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n if (pos >= max) { return false; }\n\n // [link]( <href> \"title\" )\n // ^^^^^^ parsing link destination\n start = pos;\n res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);\n if (res.ok) {\n href = state.md.normalizeLink(res.str);\n if (state.md.validateLink(href)) {\n pos = res.pos;\n } else {\n href = '';\n }\n }\n\n // [link]( <href> \"title\" )\n // ^^ skipping these spaces\n start = pos;\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n\n // [link]( <href> \"title\" )\n // ^^^^^^^ parsing link title\n res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos;\n\n // [link]( <href> \"title\" )\n // ^^ skipping these spaces\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n } else {\n title = '';\n }\n\n if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {\n // parsing a valid shortcut link failed, fallback to reference\n parseReference = true;\n }\n pos++;\n }\n\n if (parseReference) {\n //\n // Link reference\n //\n if (typeof state.env.references === 'undefined') { return false; }\n\n if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {\n start = pos + 1;\n pos = state.md.helpers.parseLinkLabel(state, pos);\n if (pos >= 0) {\n label = state.src.slice(start, pos++);\n } else {\n pos = labelEnd + 1;\n }\n } else {\n pos = labelEnd + 1;\n }\n\n // covers label === '' and label === undefined\n // (collapsed reference link and shortcut reference link respectively)\n if (!label) { label = state.src.slice(labelStart, labelEnd); }\n\n ref = state.env.references[normalizeReference(label)];\n if (!ref) {\n state.pos = oldPos;\n return false;\n }\n href = ref.href;\n title = ref.title;\n }\n\n //\n // We found the end of the link, and know for a fact it's a valid link;\n // so all that's left to do is to call tokenizer.\n //\n if (!silent) {\n state.pos = labelStart;\n state.posMax = labelEnd;\n\n token = state.push('link_open', 'a', 1);\n token.attrs = attrs = [ [ 'href', href ] ];\n if (title) {\n attrs.push([ 'title', title ]);\n }\n\n state.md.inline.tokenize(state);\n\n token = state.push('link_close', 'a', -1);\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n};\n","// Process ![image](<src> \"title\")\n\n'use strict';\n\nvar normalizeReference = require('../common/utils').normalizeReference;\nvar isSpace = require('../common/utils').isSpace;\n\n\nmodule.exports = function image(state, silent) {\n var attrs,\n code,\n content,\n label,\n labelEnd,\n labelStart,\n pos,\n ref,\n res,\n title,\n token,\n tokens,\n start,\n href = '',\n oldPos = state.pos,\n max = state.posMax;\n\n if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false; }\n if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false; }\n\n labelStart = state.pos + 2;\n labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false);\n\n // parser failed to find ']', so it's not a valid link\n if (labelEnd < 0) { return false; }\n\n pos = labelEnd + 1;\n if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {\n //\n // Inline link\n //\n\n // [link]( <href> \"title\" )\n // ^^ skipping these spaces\n pos++;\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n if (pos >= max) { return false; }\n\n // [link]( <href> \"title\" )\n // ^^^^^^ parsing link destination\n start = pos;\n res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);\n if (res.ok) {\n href = state.md.normalizeLink(res.str);\n if (state.md.validateLink(href)) {\n pos = res.pos;\n } else {\n href = '';\n }\n }\n\n // [link]( <href> \"title\" )\n // ^^ skipping these spaces\n start = pos;\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n\n // [link]( <href> \"title\" )\n // ^^^^^^^ parsing link title\n res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);\n if (pos < max && start !== pos && res.ok) {\n title = res.str;\n pos = res.pos;\n\n // [link]( <href> \"title\" )\n // ^^ skipping these spaces\n for (; pos < max; pos++) {\n code = state.src.charCodeAt(pos);\n if (!isSpace(code) && code !== 0x0A) { break; }\n }\n } else {\n title = '';\n }\n\n if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {\n state.pos = oldPos;\n return false;\n }\n pos++;\n } else {\n //\n // Link reference\n //\n if (typeof state.env.references === 'undefined') { return false; }\n\n if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {\n start = pos + 1;\n pos = state.md.helpers.parseLinkLabel(state, pos);\n if (pos >= 0) {\n label = state.src.slice(start, pos++);\n } else {\n pos = labelEnd + 1;\n }\n } else {\n pos = labelEnd + 1;\n }\n\n // covers label === '' and label === undefined\n // (collapsed reference link and shortcut reference link respectively)\n if (!label) { label = state.src.slice(labelStart, labelEnd); }\n\n ref = state.env.references[normalizeReference(label)];\n if (!ref) {\n state.pos = oldPos;\n return false;\n }\n href = ref.href;\n title = ref.title;\n }\n\n //\n // We found the end of the link, and know for a fact it's a valid link;\n // so all that's left to do is to call tokenizer.\n //\n if (!silent) {\n content = state.src.slice(labelStart, labelEnd);\n\n state.md.inline.parse(\n content,\n state.md,\n state.env,\n tokens = []\n );\n\n token = state.push('image', 'img', 0);\n token.attrs = attrs = [ [ 'src', href ], [ 'alt', '' ] ];\n token.children = tokens;\n token.content = content;\n\n if (title) {\n attrs.push([ 'title', title ]);\n }\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n};\n","// Process autolinks '<protocol:...>'\n\n'use strict';\n\n\n/*eslint max-len:0*/\nvar EMAIL_RE = /^<([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/;\nvar AUTOLINK_RE = /^<([a-zA-Z][a-zA-Z0-9+.\\-]{1,31}):([^<>\\x00-\\x20]*)>/;\n\n\nmodule.exports = function autolink(state, silent) {\n var tail, linkMatch, emailMatch, url, fullUrl, token,\n pos = state.pos;\n\n if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }\n\n tail = state.src.slice(pos);\n\n if (tail.indexOf('>') < 0) { return false; }\n\n if (AUTOLINK_RE.test(tail)) {\n linkMatch = tail.match(AUTOLINK_RE);\n\n url = linkMatch[0].slice(1, -1);\n fullUrl = state.md.normalizeLink(url);\n if (!state.md.validateLink(fullUrl)) { return false; }\n\n if (!silent) {\n token = state.push('link_open', 'a', 1);\n token.attrs = [ [ 'href', fullUrl ] ];\n token.markup = 'autolink';\n token.info = 'auto';\n\n token = state.push('text', '', 0);\n token.content = state.md.normalizeLinkText(url);\n\n token = state.push('link_close', 'a', -1);\n token.markup = 'autolink';\n token.info = 'auto';\n }\n\n state.pos += linkMatch[0].length;\n return true;\n }\n\n if (EMAIL_RE.test(tail)) {\n emailMatch = tail.match(EMAIL_RE);\n\n url = emailMatch[0].slice(1, -1);\n fullUrl = state.md.normalizeLink('mailto:' + url);\n if (!state.md.validateLink(fullUrl)) { return false; }\n\n if (!silent) {\n token = state.push('link_open', 'a', 1);\n token.attrs = [ [ 'href', fullUrl ] ];\n token.markup = 'autolink';\n token.info = 'auto';\n\n token = state.push('text', '', 0);\n token.content = state.md.normalizeLinkText(url);\n\n token = state.push('link_close', 'a', -1);\n token.markup = 'autolink';\n token.info = 'auto';\n }\n\n state.pos += emailMatch[0].length;\n return true;\n }\n\n return false;\n};\n","// Process html tags\n\n'use strict';\n\n\nvar HTML_TAG_RE = require('../common/html_re').HTML_TAG_RE;\n\n\nfunction isLetter(ch) {\n /*eslint no-bitwise:0*/\n var lc = ch | 0x20; // to lower case\n return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */);\n}\n\n\nmodule.exports = function html_inline(state, silent) {\n var ch, match, max, token,\n pos = state.pos;\n\n if (!state.md.options.html) { return false; }\n\n // Check start\n max = state.posMax;\n if (state.src.charCodeAt(pos) !== 0x3C/* < */ ||\n pos + 2 >= max) {\n return false;\n }\n\n // Quick fail on second char\n ch = state.src.charCodeAt(pos + 1);\n if (ch !== 0x21/* ! */ &&\n ch !== 0x3F/* ? */ &&\n ch !== 0x2F/* / */ &&\n !isLetter(ch)) {\n return false;\n }\n\n match = state.src.slice(pos).match(HTML_TAG_RE);\n if (!match) { return false; }\n\n if (!silent) {\n token = state.push('html_inline', '', 0);\n token.content = state.src.slice(pos, pos + match[0].length);\n }\n state.pos += match[0].length;\n return true;\n};\n","// Process html entity - &#123;, &#xAF;, &quot;, ...\n\n'use strict';\n\nvar entities = require('../common/entities');\nvar has = require('../common/utils').has;\nvar isValidEntityCode = require('../common/utils').isValidEntityCode;\nvar fromCodePoint = require('../common/utils').fromCodePoint;\n\n\nvar DIGITAL_RE = /^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i;\nvar NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;\n\n\nmodule.exports = function entity(state, silent) {\n var ch, code, match, pos = state.pos, max = state.posMax;\n\n if (state.src.charCodeAt(pos) !== 0x26/* & */) { return false; }\n\n if (pos + 1 < max) {\n ch = state.src.charCodeAt(pos + 1);\n\n if (ch === 0x23 /* # */) {\n match = state.src.slice(pos).match(DIGITAL_RE);\n if (match) {\n if (!silent) {\n code = match[1][0].toLowerCase() === 'x' ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10);\n state.pending += isValidEntityCode(code) ? fromCodePoint(code) : fromCodePoint(0xFFFD);\n }\n state.pos += match[0].length;\n return true;\n }\n } else {\n match = state.src.slice(pos).match(NAMED_RE);\n if (match) {\n if (has(entities, match[1])) {\n if (!silent) { state.pending += entities[match[1]]; }\n state.pos += match[0].length;\n return true;\n }\n }\n }\n }\n\n if (!silent) { state.pending += '&'; }\n state.pos++;\n return true;\n};\n","// For each opening emphasis-like marker find a matching closing one\n//\n'use strict';\n\n\nfunction processDelimiters(state, delimiters) {\n var closerIdx, openerIdx, closer, opener, minOpenerIdx, newMinOpenerIdx,\n isOddMatch, lastJump,\n openersBottom = {},\n max = delimiters.length;\n\n for (closerIdx = 0; closerIdx < max; closerIdx++) {\n closer = delimiters[closerIdx];\n\n // Length is only used for emphasis-specific \"rule of 3\",\n // if it's not defined (in strikethrough or 3rd party plugins),\n // we can default it to 0 to disable those checks.\n //\n closer.length = closer.length || 0;\n\n if (!closer.close) continue;\n\n // Previously calculated lower bounds (previous fails)\n // for each marker and each delimiter length modulo 3.\n if (!openersBottom.hasOwnProperty(closer.marker)) {\n openersBottom[closer.marker] = [ -1, -1, -1 ];\n }\n\n minOpenerIdx = openersBottom[closer.marker][closer.length % 3];\n newMinOpenerIdx = -1;\n\n openerIdx = closerIdx - closer.jump - 1;\n\n for (; openerIdx > minOpenerIdx; openerIdx -= opener.jump + 1) {\n opener = delimiters[openerIdx];\n\n if (opener.marker !== closer.marker) continue;\n\n if (newMinOpenerIdx === -1) newMinOpenerIdx = openerIdx;\n\n if (opener.open &&\n opener.end < 0 &&\n opener.level === closer.level) {\n\n isOddMatch = false;\n\n // from spec:\n //\n // If one of the delimiters can both open and close emphasis, then the\n // sum of the lengths of the delimiter runs containing the opening and\n // closing delimiters must not be a multiple of 3 unless both lengths\n // are multiples of 3.\n //\n if (opener.close || closer.open) {\n if ((opener.length + closer.length) % 3 === 0) {\n if (opener.length % 3 !== 0 || closer.length % 3 !== 0) {\n isOddMatch = true;\n }\n }\n }\n\n if (!isOddMatch) {\n // If previous delimiter cannot be an opener, we can safely skip\n // the entire sequence in future checks. This is required to make\n // sure algorithm has linear complexity (see *_*_*_*_*_... case).\n //\n lastJump = openerIdx > 0 && !delimiters[openerIdx - 1].open ?\n delimiters[openerIdx - 1].jump + 1 :\n 0;\n\n closer.jump = closerIdx - openerIdx + lastJump;\n closer.open = false;\n opener.end = closerIdx;\n opener.jump = lastJump;\n opener.close = false;\n newMinOpenerIdx = -1;\n break;\n }\n }\n }\n\n if (newMinOpenerIdx !== -1) {\n // If match for this delimiter run failed, we want to set lower bound for\n // future lookups. This is required to make sure algorithm has linear\n // complexity.\n //\n // See details here:\n // https://github.com/commonmark/cmark/issues/178#issuecomment-270417442\n //\n openersBottom[closer.marker][(closer.length || 0) % 3] = newMinOpenerIdx;\n }\n }\n}\n\n\nmodule.exports = function link_pairs(state) {\n var curr,\n tokens_meta = state.tokens_meta,\n max = state.tokens_meta.length;\n\n processDelimiters(state, state.delimiters);\n\n for (curr = 0; curr < max; curr++) {\n if (tokens_meta[curr] && tokens_meta[curr].delimiters) {\n processDelimiters(state, tokens_meta[curr].delimiters);\n }\n }\n};\n","// Clean up tokens after emphasis and strikethrough postprocessing:\n// merge adjacent text nodes into one and re-calculate all token levels\n//\n// This is necessary because initially emphasis delimiter markers (*, _, ~)\n// are treated as their own separate text tokens. Then emphasis rule either\n// leaves them as text (needed to merge with adjacent text) or turns them\n// into opening/closing tags (which messes up levels inside).\n//\n'use strict';\n\n\nmodule.exports = function text_collapse(state) {\n var curr, last,\n level = 0,\n tokens = state.tokens,\n max = state.tokens.length;\n\n for (curr = last = 0; curr < max; curr++) {\n // re-calculate levels after emphasis/strikethrough turns some text nodes\n // into opening/closing tags\n if (tokens[curr].nesting < 0) level--; // closing tag\n tokens[curr].level = level;\n if (tokens[curr].nesting > 0) level++; // opening tag\n\n if (tokens[curr].type === 'text' &&\n curr + 1 < max &&\n tokens[curr + 1].type === 'text') {\n\n // collapse two adjacent text nodes\n tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content;\n } else {\n if (curr !== last) { tokens[last] = tokens[curr]; }\n\n last++;\n }\n }\n\n if (curr !== last) {\n tokens.length = last;\n }\n};\n","// Inline parser state\n\n'use strict';\n\n\nvar Token = require('../token');\nvar isWhiteSpace = require('../common/utils').isWhiteSpace;\nvar isPunctChar = require('../common/utils').isPunctChar;\nvar isMdAsciiPunct = require('../common/utils').isMdAsciiPunct;\n\n\nfunction StateInline(src, md, env, outTokens) {\n this.src = src;\n this.env = env;\n this.md = md;\n this.tokens = outTokens;\n this.tokens_meta = Array(outTokens.length);\n\n this.pos = 0;\n this.posMax = this.src.length;\n this.level = 0;\n this.pending = '';\n this.pendingLevel = 0;\n\n // Stores { start: end } pairs. Useful for backtrack\n // optimization of pairs parse (emphasis, strikes).\n this.cache = {};\n\n // List of emphasis-like delimiters for current tag\n this.delimiters = [];\n\n // Stack of delimiter lists for upper level tags\n this._prev_delimiters = [];\n}\n\n\n// Flush pending text\n//\nStateInline.prototype.pushPending = function () {\n var token = new Token('text', '', 0);\n token.content = this.pending;\n token.level = this.pendingLevel;\n this.tokens.push(token);\n this.pending = '';\n return token;\n};\n\n\n// Push new token to \"stream\".\n// If pending text exists - flush it as text token\n//\nStateInline.prototype.push = function (type, tag, nesting) {\n if (this.pending) {\n this.pushPending();\n }\n\n var token = new Token(type, tag, nesting);\n var token_meta = null;\n\n if (nesting < 0) {\n // closing tag\n this.level--;\n this.delimiters = this._prev_delimiters.pop();\n }\n\n token.level = this.level;\n\n if (nesting > 0) {\n // opening tag\n this.level++;\n this._prev_delimiters.push(this.delimiters);\n this.delimiters = [];\n token_meta = { delimiters: this.delimiters };\n }\n\n this.pendingLevel = this.level;\n this.tokens.push(token);\n this.tokens_meta.push(token_meta);\n return token;\n};\n\n\n// Scan a sequence of emphasis-like markers, and determine whether\n// it can start an emphasis sequence or end an emphasis sequence.\n//\n// - start - position to scan from (it should point at a valid marker);\n// - canSplitWord - determine if these markers can be found inside a word\n//\nStateInline.prototype.scanDelims = function (start, canSplitWord) {\n var pos = start, lastChar, nextChar, count, can_open, can_close,\n isLastWhiteSpace, isLastPunctChar,\n isNextWhiteSpace, isNextPunctChar,\n left_flanking = true,\n right_flanking = true,\n max = this.posMax,\n marker = this.src.charCodeAt(start);\n\n // treat beginning of the line as a whitespace\n lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;\n\n while (pos < max && this.src.charCodeAt(pos) === marker) { pos++; }\n\n count = pos - start;\n\n // treat end of the line as a whitespace\n nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;\n\n isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));\n isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));\n\n isLastWhiteSpace = isWhiteSpace(lastChar);\n isNextWhiteSpace = isWhiteSpace(nextChar);\n\n if (isNextWhiteSpace) {\n left_flanking = false;\n } else if (isNextPunctChar) {\n if (!(isLastWhiteSpace || isLastPunctChar)) {\n left_flanking = false;\n }\n }\n\n if (isLastWhiteSpace) {\n right_flanking = false;\n } else if (isLastPunctChar) {\n if (!(isNextWhiteSpace || isNextPunctChar)) {\n right_flanking = false;\n }\n }\n\n if (!canSplitWord) {\n can_open = left_flanking && (!right_flanking || isLastPunctChar);\n can_close = right_flanking && (!left_flanking || isNextPunctChar);\n } else {\n can_open = left_flanking;\n can_close = right_flanking;\n }\n\n return {\n can_open: can_open,\n can_close: can_close,\n length: count\n };\n};\n\n\n// re-export Token class to use in block rules\nStateInline.prototype.Token = Token;\n\n\nmodule.exports = StateInline;\n","'use strict';\n\n\n////////////////////////////////////////////////////////////////////////////////\n// Helpers\n\n// Merge objects\n//\nfunction assign(obj /*from1, from2, from3, ...*/) {\n var sources = Array.prototype.slice.call(arguments, 1);\n\n sources.forEach(function (source) {\n if (!source) { return; }\n\n Object.keys(source).forEach(function (key) {\n obj[key] = source[key];\n });\n });\n\n return obj;\n}\n\nfunction _class(obj) { return Object.prototype.toString.call(obj); }\nfunction isString(obj) { return _class(obj) === '[object String]'; }\nfunction isObject(obj) { return _class(obj) === '[object Object]'; }\nfunction isRegExp(obj) { return _class(obj) === '[object RegExp]'; }\nfunction isFunction(obj) { return _class(obj) === '[object Function]'; }\n\n\nfunction escapeRE(str) { return str.replace(/[.?*+^$[\\]\\\\(){}|-]/g, '\\\\$&'); }\n\n////////////////////////////////////////////////////////////////////////////////\n\n\nvar defaultOptions = {\n fuzzyLink: true,\n fuzzyEmail: true,\n fuzzyIP: false\n};\n\n\nfunction isOptionsObj(obj) {\n return Object.keys(obj || {}).reduce(function (acc, k) {\n return acc || defaultOptions.hasOwnProperty(k);\n }, false);\n}\n\n\nvar defaultSchemas = {\n 'http:': {\n validate: function (text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.http) {\n // compile lazily, because \"host\"-containing variables can change on tlds update.\n self.re.http = new RegExp(\n '^\\\\/\\\\/' + self.re.src_auth + self.re.src_host_port_strict + self.re.src_path, 'i'\n );\n }\n if (self.re.http.test(tail)) {\n return tail.match(self.re.http)[0].length;\n }\n return 0;\n }\n },\n 'https:': 'http:',\n 'ftp:': 'http:',\n '//': {\n validate: function (text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.no_http) {\n // compile lazily, because \"host\"-containing variables can change on tlds update.\n self.re.no_http = new RegExp(\n '^' +\n self.re.src_auth +\n // Don't allow single-level domains, because of false positives like '//test'\n // with code comments\n '(?:localhost|(?:(?:' + self.re.src_domain + ')\\\\.)+' + self.re.src_domain_root + ')' +\n self.re.src_port +\n self.re.src_host_terminator +\n self.re.src_path,\n\n 'i'\n );\n }\n\n if (self.re.no_http.test(tail)) {\n // should not be `://` & `///`, that protects from errors in protocol name\n if (pos >= 3 && text[pos - 3] === ':') { return 0; }\n if (pos >= 3 && text[pos - 3] === '/') { return 0; }\n return tail.match(self.re.no_http)[0].length;\n }\n return 0;\n }\n },\n 'mailto:': {\n validate: function (text, pos, self) {\n var tail = text.slice(pos);\n\n if (!self.re.mailto) {\n self.re.mailto = new RegExp(\n '^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i'\n );\n }\n if (self.re.mailto.test(tail)) {\n return tail.match(self.re.mailto)[0].length;\n }\n return 0;\n }\n }\n};\n\n/*eslint-disable max-len*/\n\n// RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)\nvar tlds_2ch_src_re = 'a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]';\n\n// DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead\nvar tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');\n\n/*eslint-enable max-len*/\n\n////////////////////////////////////////////////////////////////////////////////\n\nfunction resetScanCache(self) {\n self.__index__ = -1;\n self.__text_cache__ = '';\n}\n\nfunction createValidator(re) {\n return function (text, pos) {\n var tail = text.slice(pos);\n\n if (re.test(tail)) {\n return tail.match(re)[0].length;\n }\n return 0;\n };\n}\n\nfunction createNormalizer() {\n return function (match, self) {\n self.normalize(match);\n };\n}\n\n// Schemas compiler. Build regexps.\n//\nfunction compile(self) {\n\n // Load & clone RE patterns.\n var re = self.re = require('./lib/re')(self.__opts__);\n\n // Define dynamic patterns\n var tlds = self.__tlds__.slice();\n\n self.onCompile();\n\n if (!self.__tlds_replaced__) {\n tlds.push(tlds_2ch_src_re);\n }\n tlds.push(re.src_xn);\n\n re.src_tlds = tlds.join('|');\n\n function untpl(tpl) { return tpl.replace('%TLDS%', re.src_tlds); }\n\n re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i');\n re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i');\n re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i');\n re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i');\n\n //\n // Compile each schema\n //\n\n var aliases = [];\n\n self.__compiled__ = {}; // Reset compiled data\n\n function schemaError(name, val) {\n throw new Error('(LinkifyIt) Invalid schema \"' + name + '\": ' + val);\n }\n\n Object.keys(self.__schemas__).forEach(function (name) {\n var val = self.__schemas__[name];\n\n // skip disabled methods\n if (val === null) { return; }\n\n var compiled = { validate: null, link: null };\n\n self.__compiled__[name] = compiled;\n\n if (isObject(val)) {\n if (isRegExp(val.validate)) {\n compiled.validate = createValidator(val.validate);\n } else if (isFunction(val.validate)) {\n compiled.validate = val.validate;\n } else {\n schemaError(name, val);\n }\n\n if (isFunction(val.normalize)) {\n compiled.normalize = val.normalize;\n } else if (!val.normalize) {\n compiled.normalize = createNormalizer();\n } else {\n schemaError(name, val);\n }\n\n return;\n }\n\n if (isString(val)) {\n aliases.push(name);\n return;\n }\n\n schemaError(name, val);\n });\n\n //\n // Compile postponed aliases\n //\n\n aliases.forEach(function (alias) {\n if (!self.__compiled__[self.__schemas__[alias]]) {\n // Silently fail on missed schemas to avoid errons on disable.\n // schemaError(alias, self.__schemas__[alias]);\n return;\n }\n\n self.__compiled__[alias].validate =\n self.__compiled__[self.__schemas__[alias]].validate;\n self.__compiled__[alias].normalize =\n self.__compiled__[self.__schemas__[alias]].normalize;\n });\n\n //\n // Fake record for guessed links\n //\n self.__compiled__[''] = { validate: null, normalize: createNormalizer() };\n\n //\n // Build schema condition\n //\n var slist = Object.keys(self.__compiled__)\n .filter(function (name) {\n // Filter disabled & fake schemas\n return name.length > 0 && self.__compiled__[name];\n })\n .map(escapeRE)\n .join('|');\n // (?!_) cause 1.5x slowdown\n self.re.schema_test = RegExp('(^|(?!_)(?:[><\\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'i');\n self.re.schema_search = RegExp('(^|(?!_)(?:[><\\uff5c]|' + re.src_ZPCc + '))(' + slist + ')', 'ig');\n\n self.re.pretest = RegExp(\n '(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@',\n 'i'\n );\n\n //\n // Cleanup\n //\n\n resetScanCache(self);\n}\n\n/**\n * class Match\n *\n * Match result. Single element of array, returned by [[LinkifyIt#match]]\n **/\nfunction Match(self, shift) {\n var start = self.__index__,\n end = self.__last_index__,\n text = self.__text_cache__.slice(start, end);\n\n /**\n * Match#schema -> String\n *\n * Prefix (protocol) for matched string.\n **/\n this.schema = self.__schema__.toLowerCase();\n /**\n * Match#index -> Number\n *\n * First position of matched string.\n **/\n this.index = start + shift;\n /**\n * Match#lastIndex -> Number\n *\n * Next position after matched string.\n **/\n this.lastIndex = end + shift;\n /**\n * Match#raw -> String\n *\n * Matched string.\n **/\n this.raw = text;\n /**\n * Match#text -> String\n *\n * Notmalized text of matched string.\n **/\n this.text = text;\n /**\n * Match#url -> String\n *\n * Normalized url of matched string.\n **/\n this.url = text;\n}\n\nfunction createMatch(self, shift) {\n var match = new Match(self, shift);\n\n self.__compiled__[match.schema].normalize(match, self);\n\n return match;\n}\n\n\n/**\n * class LinkifyIt\n **/\n\n/**\n * new LinkifyIt(schemas, options)\n * - schemas (Object): Optional. Additional schemas to validate (prefix/validator)\n * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }\n *\n * Creates new linkifier instance with optional additional schemas.\n * Can be called without `new` keyword for convenience.\n *\n * By default understands:\n *\n * - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links\n * - \"fuzzy\" links and emails (example.com, foo@bar.com).\n *\n * `schemas` is an object, where each key/value describes protocol/rule:\n *\n * - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:`\n * for example). `linkify-it` makes shure that prefix is not preceeded with\n * alphanumeric char and symbols. Only whitespaces and punctuation allowed.\n * - __value__ - rule to check tail after link prefix\n * - _String_ - just alias to existing rule\n * - _Object_\n * - _validate_ - validator function (should return matched length on success),\n * or `RegExp`.\n * - _normalize_ - optional function to normalize text & url of matched result\n * (for example, for @twitter mentions).\n *\n * `options`:\n *\n * - __fuzzyLink__ - recognige URL-s without `http(s):` prefix. Default `true`.\n * - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts\n * like version numbers. Default `false`.\n * - __fuzzyEmail__ - recognize emails without `mailto:` prefix.\n *\n **/\nfunction LinkifyIt(schemas, options) {\n if (!(this instanceof LinkifyIt)) {\n return new LinkifyIt(schemas, options);\n }\n\n if (!options) {\n if (isOptionsObj(schemas)) {\n options = schemas;\n schemas = {};\n }\n }\n\n this.__opts__ = assign({}, defaultOptions, options);\n\n // Cache last tested result. Used to skip repeating steps on next `match` call.\n this.__index__ = -1;\n this.__last_index__ = -1; // Next scan position\n this.__schema__ = '';\n this.__text_cache__ = '';\n\n this.__schemas__ = assign({}, defaultSchemas, schemas);\n this.__compiled__ = {};\n\n this.__tlds__ = tlds_default;\n this.__tlds_replaced__ = false;\n\n this.re = {};\n\n compile(this);\n}\n\n\n/** chainable\n * LinkifyIt#add(schema, definition)\n * - schema (String): rule name (fixed pattern prefix)\n * - definition (String|RegExp|Object): schema definition\n *\n * Add new rule definition. See constructor description for details.\n **/\nLinkifyIt.prototype.add = function add(schema, definition) {\n this.__schemas__[schema] = definition;\n compile(this);\n return this;\n};\n\n\n/** chainable\n * LinkifyIt#set(options)\n * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }\n *\n * Set recognition options for links without schema.\n **/\nLinkifyIt.prototype.set = function set(options) {\n this.__opts__ = assign(this.__opts__, options);\n return this;\n};\n\n\n/**\n * LinkifyIt#test(text) -> Boolean\n *\n * Searches linkifiable pattern and returns `true` on success or `false` on fail.\n **/\nLinkifyIt.prototype.test = function test(text) {\n // Reset scan cache\n this.__text_cache__ = text;\n this.__index__ = -1;\n\n if (!text.length) { return false; }\n\n var m, ml, me, len, shift, next, re, tld_pos, at_pos;\n\n // try to scan for link with schema - that's the most simple rule\n if (this.re.schema_test.test(text)) {\n re = this.re.schema_search;\n re.lastIndex = 0;\n while ((m = re.exec(text)) !== null) {\n len = this.testSchemaAt(text, m[2], re.lastIndex);\n if (len) {\n this.__schema__ = m[2];\n this.__index__ = m.index + m[1].length;\n this.__last_index__ = m.index + m[0].length + len;\n break;\n }\n }\n }\n\n if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {\n // guess schemaless links\n tld_pos = text.search(this.re.host_fuzzy_test);\n if (tld_pos >= 0) {\n // if tld is located after found link - no need to check fuzzy pattern\n if (this.__index__ < 0 || tld_pos < this.__index__) {\n if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {\n\n shift = ml.index + ml[1].length;\n\n if (this.__index__ < 0 || shift < this.__index__) {\n this.__schema__ = '';\n this.__index__ = shift;\n this.__last_index__ = ml.index + ml[0].length;\n }\n }\n }\n }\n }\n\n if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {\n // guess schemaless emails\n at_pos = text.indexOf('@');\n if (at_pos >= 0) {\n // We can't skip this check, because this cases are possible:\n // 192.168.1.1@gmail.com, my.in@example.com\n if ((me = text.match(this.re.email_fuzzy)) !== null) {\n\n shift = me.index + me[1].length;\n next = me.index + me[0].length;\n\n if (this.__index__ < 0 || shift < this.__index__ ||\n (shift === this.__index__ && next > this.__last_index__)) {\n this.__schema__ = 'mailto:';\n this.__index__ = shift;\n this.__last_index__ = next;\n }\n }\n }\n }\n\n return this.__index__ >= 0;\n};\n\n\n/**\n * LinkifyIt#pretest(text) -> Boolean\n *\n * Very quick check, that can give false positives. Returns true if link MAY BE\n * can exists. Can be used for speed optimization, when you need to check that\n * link NOT exists.\n **/\nLinkifyIt.prototype.pretest = function pretest(text) {\n return this.re.pretest.test(text);\n};\n\n\n/**\n * LinkifyIt#testSchemaAt(text, name, position) -> Number\n * - text (String): text to scan\n * - name (String): rule (schema) name\n * - position (Number): text offset to check from\n *\n * Similar to [[LinkifyIt#test]] but checks only specific protocol tail exactly\n * at given position. Returns length of found pattern (0 on fail).\n **/\nLinkifyIt.prototype.testSchemaAt = function testSchemaAt(text, schema, pos) {\n // If not supported schema check requested - terminate\n if (!this.__compiled__[schema.toLowerCase()]) {\n return 0;\n }\n return this.__compiled__[schema.toLowerCase()].validate(text, pos, this);\n};\n\n\n/**\n * LinkifyIt#match(text) -> Array|null\n *\n * Returns array of found link descriptions or `null` on fail. We strongly\n * recommend to use [[LinkifyIt#test]] first, for best speed.\n *\n * ##### Result match description\n *\n * - __schema__ - link schema, can be empty for fuzzy links, or `//` for\n * protocol-neutral links.\n * - __index__ - offset of matched text\n * - __lastIndex__ - index of next char after mathch end\n * - __raw__ - matched text\n * - __text__ - normalized text\n * - __url__ - link, generated from matched text\n **/\nLinkifyIt.prototype.match = function match(text) {\n var shift = 0, result = [];\n\n // Try to take previous element from cache, if .test() called before\n if (this.__index__ >= 0 && this.__text_cache__ === text) {\n result.push(createMatch(this, shift));\n shift = this.__last_index__;\n }\n\n // Cut head if cache was used\n var tail = shift ? text.slice(shift) : text;\n\n // Scan string until end reached\n while (this.test(tail)) {\n result.push(createMatch(this, shift));\n\n tail = tail.slice(this.__last_index__);\n shift += this.__last_index__;\n }\n\n if (result.length) {\n return result;\n }\n\n return null;\n};\n\n\n/** chainable\n * LinkifyIt#tlds(list [, keepOld]) -> this\n * - list (Array): list of tlds\n * - keepOld (Boolean): merge with current list if `true` (`false` by default)\n *\n * Load (or merge) new tlds list. Those are user for fuzzy links (without prefix)\n * to avoid false positives. By default this algorythm used:\n *\n * - hostname with any 2-letter root zones are ok.\n * - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф\n * are ok.\n * - encoded (`xn--...`) root zones are ok.\n *\n * If list is replaced, then exact match for 2-chars root zones will be checked.\n **/\nLinkifyIt.prototype.tlds = function tlds(list, keepOld) {\n list = Array.isArray(list) ? list : [ list ];\n\n if (!keepOld) {\n this.__tlds__ = list.slice();\n this.__tlds_replaced__ = true;\n compile(this);\n return this;\n }\n\n this.__tlds__ = this.__tlds__.concat(list)\n .sort()\n .filter(function (el, idx, arr) {\n return el !== arr[idx - 1];\n })\n .reverse();\n\n compile(this);\n return this;\n};\n\n/**\n * LinkifyIt#normalize(match)\n *\n * Default normalizer (if schema does not define it's own).\n **/\nLinkifyIt.prototype.normalize = function normalize(match) {\n\n // Do minimal possible changes by default. Need to collect feedback prior\n // to move forward https://github.com/markdown-it/linkify-it/issues/1\n\n if (!match.schema) { match.url = 'http://' + match.url; }\n\n if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {\n match.url = 'mailto:' + match.url;\n }\n};\n\n\n/**\n * LinkifyIt#onCompile()\n *\n * Override to modify basic RegExp-s.\n **/\nLinkifyIt.prototype.onCompile = function onCompile() {\n};\n\n\nmodule.exports = LinkifyIt;\n","'use strict';\n\n\nmodule.exports = function (opts) {\n var re = {};\n\n // Use direct extract instead of `regenerate` to reduse browserified size\n re.src_Any = require('uc.micro/properties/Any/regex').source;\n re.src_Cc = require('uc.micro/categories/Cc/regex').source;\n re.src_Z = require('uc.micro/categories/Z/regex').source;\n re.src_P = require('uc.micro/categories/P/regex').source;\n\n // \\p{\\Z\\P\\Cc\\CF} (white spaces + control + format + punctuation)\n re.src_ZPCc = [ re.src_Z, re.src_P, re.src_Cc ].join('|');\n\n // \\p{\\Z\\Cc} (white spaces + control)\n re.src_ZCc = [ re.src_Z, re.src_Cc ].join('|');\n\n // Experimental. List of chars, completely prohibited in links\n // because can separate it from other part of text\n var text_separators = '[><\\uff5c]';\n\n // All possible word characters (everything without punctuation, spaces & controls)\n // Defined via punctuation & spaces to save space\n // Should be something like \\p{\\L\\N\\S\\M} (\\w but without `_`)\n re.src_pseudo_letter = '(?:(?!' + text_separators + '|' + re.src_ZPCc + ')' + re.src_Any + ')';\n // The same as abothe but without [0-9]\n // var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')';\n\n ////////////////////////////////////////////////////////////////////////////////\n\n re.src_ip4 =\n\n '(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';\n\n // Prohibit any of \"@/[]()\" in user/pass to avoid wrong domain fetch.\n re.src_auth = '(?:(?:(?!' + re.src_ZCc + '|[@/\\\\[\\\\]()]).)+@)?';\n\n re.src_port =\n\n '(?::(?:6(?:[0-4]\\\\d{3}|5(?:[0-4]\\\\d{2}|5(?:[0-2]\\\\d|3[0-5])))|[1-5]?\\\\d{1,4}))?';\n\n re.src_host_terminator =\n\n '(?=$|' + text_separators + '|' + re.src_ZPCc + ')(?!-|_|:\\\\d|\\\\.-|\\\\.(?!$|' + re.src_ZPCc + '))';\n\n re.src_path =\n\n '(?:' +\n '[/?#]' +\n '(?:' +\n '(?!' + re.src_ZCc + '|' + text_separators + '|[()[\\\\]{}.,\"\\'?!\\\\-]).|' +\n '\\\\[(?:(?!' + re.src_ZCc + '|\\\\]).)*\\\\]|' +\n '\\\\((?:(?!' + re.src_ZCc + '|[)]).)*\\\\)|' +\n '\\\\{(?:(?!' + re.src_ZCc + '|[}]).)*\\\\}|' +\n '\\\\\"(?:(?!' + re.src_ZCc + '|[\"]).)+\\\\\"|' +\n \"\\\\'(?:(?!\" + re.src_ZCc + \"|[']).)+\\\\'|\" +\n \"\\\\'(?=\" + re.src_pseudo_letter + '|[-]).|' + // allow `I'm_king` if no pair found\n '\\\\.{2,4}[a-zA-Z0-9%/]|' + // github has ... in commit range links,\n // google has .... in links (issue #66)\n // Restrict to\n // - english\n // - percent-encoded\n // - parts of file path\n // until more examples found.\n '\\\\.(?!' + re.src_ZCc + '|[.]).|' +\n (opts && opts['---'] ?\n '\\\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate\n :\n '\\\\-+|'\n ) +\n '\\\\,(?!' + re.src_ZCc + ').|' + // allow `,,,` in paths\n '\\\\!(?!' + re.src_ZCc + '|[!]).|' +\n '\\\\?(?!' + re.src_ZCc + '|[?]).' +\n ')+' +\n '|\\\\/' +\n ')?';\n\n // Allow anything in markdown spec, forbid quote (\") at the first position\n // because emails enclosed in quotes are far more common\n re.src_email_name =\n\n '[\\\\-;:&=\\\\+\\\\$,\\\\.a-zA-Z0-9_][\\\\-;:&=\\\\+\\\\$,\\\\\"\\\\.a-zA-Z0-9_]*';\n\n re.src_xn =\n\n 'xn--[a-z0-9\\\\-]{1,59}';\n\n // More to read about domain names\n // http://serverfault.com/questions/638260/\n\n re.src_domain_root =\n\n // Allow letters & digits (http://test1)\n '(?:' +\n re.src_xn +\n '|' +\n re.src_pseudo_letter + '{1,63}' +\n ')';\n\n re.src_domain =\n\n '(?:' +\n re.src_xn +\n '|' +\n '(?:' + re.src_pseudo_letter + ')' +\n '|' +\n '(?:' + re.src_pseudo_letter + '(?:-|' + re.src_pseudo_letter + '){0,61}' + re.src_pseudo_letter + ')' +\n ')';\n\n re.src_host =\n\n '(?:' +\n // Don't need IP check, because digits are already allowed in normal domain names\n // src_ip4 +\n // '|' +\n '(?:(?:(?:' + re.src_domain + ')\\\\.)*' + re.src_domain/*_root*/ + ')' +\n ')';\n\n re.tpl_host_fuzzy =\n\n '(?:' +\n re.src_ip4 +\n '|' +\n '(?:(?:(?:' + re.src_domain + ')\\\\.)+(?:%TLDS%))' +\n ')';\n\n re.tpl_host_no_ip_fuzzy =\n\n '(?:(?:(?:' + re.src_domain + ')\\\\.)+(?:%TLDS%))';\n\n re.src_host_strict =\n\n re.src_host + re.src_host_terminator;\n\n re.tpl_host_fuzzy_strict =\n\n re.tpl_host_fuzzy + re.src_host_terminator;\n\n re.src_host_port_strict =\n\n re.src_host + re.src_port + re.src_host_terminator;\n\n re.tpl_host_port_fuzzy_strict =\n\n re.tpl_host_fuzzy + re.src_port + re.src_host_terminator;\n\n re.tpl_host_port_no_ip_fuzzy_strict =\n\n re.tpl_host_no_ip_fuzzy + re.src_port + re.src_host_terminator;\n\n\n ////////////////////////////////////////////////////////////////////////////////\n // Main rules\n\n // Rude test fuzzy links by host, for quick deny\n re.tpl_host_fuzzy_test =\n\n 'localhost|www\\\\.|\\\\.\\\\d{1,3}\\\\.|(?:\\\\.(?:%TLDS%)(?:' + re.src_ZPCc + '|>|$))';\n\n re.tpl_email_fuzzy =\n\n '(^|' + text_separators + '|\"|\\\\(|' + re.src_ZCc + ')' +\n '(' + re.src_email_name + '@' + re.tpl_host_fuzzy_strict + ')';\n\n re.tpl_link_fuzzy =\n // Fuzzy link can't be prepended with .:/\\- and non punctuation.\n // but can start with > (markdown blockquote)\n '(^|(?![.:/\\\\-_@])(?:[$+<=>^`|\\uff5c]|' + re.src_ZPCc + '))' +\n '((?![$+<=>^`|\\uff5c])' + re.tpl_host_port_fuzzy_strict + re.src_path + ')';\n\n re.tpl_link_no_ip_fuzzy =\n // Fuzzy link can't be prepended with .:/\\- and non punctuation.\n // but can start with > (markdown blockquote)\n '(^|(?![.:/\\\\-_@])(?:[$+<=>^`|\\uff5c]|' + re.src_ZPCc + '))' +\n '((?![$+<=>^`|\\uff5c])' + re.tpl_host_port_no_ip_fuzzy_strict + re.src_path + ')';\n\n return re;\n};\n","/*! https://mths.be/punycode v1.4.1 by @mathias */\n;(function(root) {\n\n\t/** Detect free variables */\n\tvar freeExports = typeof exports == 'object' && exports &&\n\t\t!exports.nodeType && exports;\n\tvar freeModule = typeof module == 'object' && module &&\n\t\t!module.nodeType && module;\n\tvar freeGlobal = typeof global == 'object' && global;\n\tif (\n\t\tfreeGlobal.global === freeGlobal ||\n\t\tfreeGlobal.window === freeGlobal ||\n\t\tfreeGlobal.self === freeGlobal\n\t) {\n\t\troot = freeGlobal;\n\t}\n\n\t/**\n\t * The `punycode` object.\n\t * @name punycode\n\t * @type Object\n\t */\n\tvar punycode,\n\n\t/** Highest positive signed 32-bit float value */\n\tmaxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1\n\n\t/** Bootstring parameters */\n\tbase = 36,\n\ttMin = 1,\n\ttMax = 26,\n\tskew = 38,\n\tdamp = 700,\n\tinitialBias = 72,\n\tinitialN = 128, // 0x80\n\tdelimiter = '-', // '\\x2D'\n\n\t/** Regular expressions */\n\tregexPunycode = /^xn--/,\n\tregexNonASCII = /[^\\x20-\\x7E]/, // unprintable ASCII chars + non-ASCII chars\n\tregexSeparators = /[\\x2E\\u3002\\uFF0E\\uFF61]/g, // RFC 3490 separators\n\n\t/** Error messages */\n\terrors = {\n\t\t'overflow': 'Overflow: input needs wider integers to process',\n\t\t'not-basic': 'Illegal input >= 0x80 (not a basic code point)',\n\t\t'invalid-input': 'Invalid input'\n\t},\n\n\t/** Convenience shortcuts */\n\tbaseMinusTMin = base - tMin,\n\tfloor = Math.floor,\n\tstringFromCharCode = String.fromCharCode,\n\n\t/** Temporary variable */\n\tkey;\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/**\n\t * A generic error utility function.\n\t * @private\n\t * @param {String} type The error type.\n\t * @returns {Error} Throws a `RangeError` with the applicable error message.\n\t */\n\tfunction error(type) {\n\t\tthrow new RangeError(errors[type]);\n\t}\n\n\t/**\n\t * A generic `Array#map` utility function.\n\t * @private\n\t * @param {Array} array The array to iterate over.\n\t * @param {Function} callback The function that gets called for every array\n\t * item.\n\t * @returns {Array} A new array of values returned by the callback function.\n\t */\n\tfunction map(array, fn) {\n\t\tvar length = array.length;\n\t\tvar result = [];\n\t\twhile (length--) {\n\t\t\tresult[length] = fn(array[length]);\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * A simple `Array#map`-like wrapper to work with domain name strings or email\n\t * addresses.\n\t * @private\n\t * @param {String} domain The domain name or email address.\n\t * @param {Function} callback The function that gets called for every\n\t * character.\n\t * @returns {Array} A new string of characters returned by the callback\n\t * function.\n\t */\n\tfunction mapDomain(string, fn) {\n\t\tvar parts = string.split('@');\n\t\tvar result = '';\n\t\tif (parts.length > 1) {\n\t\t\t// In email addresses, only the domain name should be punycoded. Leave\n\t\t\t// the local part (i.e. everything up to `@`) intact.\n\t\t\tresult = parts[0] + '@';\n\t\t\tstring = parts[1];\n\t\t}\n\t\t// Avoid `split(regex)` for IE8 compatibility. See #17.\n\t\tstring = string.replace(regexSeparators, '\\x2E');\n\t\tvar labels = string.split('.');\n\t\tvar encoded = map(labels, fn).join('.');\n\t\treturn result + encoded;\n\t}\n\n\t/**\n\t * Creates an array containing the numeric code points of each Unicode\n\t * character in the string. While JavaScript uses UCS-2 internally,\n\t * this function will convert a pair of surrogate halves (each of which\n\t * UCS-2 exposes as separate characters) into a single code point,\n\t * matching UTF-16.\n\t * @see `punycode.ucs2.encode`\n\t * @see <https://mathiasbynens.be/notes/javascript-encoding>\n\t * @memberOf punycode.ucs2\n\t * @name decode\n\t * @param {String} string The Unicode input string (UCS-2).\n\t * @returns {Array} The new array of code points.\n\t */\n\tfunction ucs2decode(string) {\n\t\tvar output = [],\n\t\t counter = 0,\n\t\t length = string.length,\n\t\t value,\n\t\t extra;\n\t\twhile (counter < length) {\n\t\t\tvalue = string.charCodeAt(counter++);\n\t\t\tif (value >= 0xD800 && value <= 0xDBFF && counter < length) {\n\t\t\t\t// high surrogate, and there is a next character\n\t\t\t\textra = string.charCodeAt(counter++);\n\t\t\t\tif ((extra & 0xFC00) == 0xDC00) { // low surrogate\n\t\t\t\t\toutput.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);\n\t\t\t\t} else {\n\t\t\t\t\t// unmatched surrogate; only append this code unit, in case the next\n\t\t\t\t\t// code unit is the high surrogate of a surrogate pair\n\t\t\t\t\toutput.push(value);\n\t\t\t\t\tcounter--;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\toutput.push(value);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Creates a string based on an array of numeric code points.\n\t * @see `punycode.ucs2.decode`\n\t * @memberOf punycode.ucs2\n\t * @name encode\n\t * @param {Array} codePoints The array of numeric code points.\n\t * @returns {String} The new Unicode string (UCS-2).\n\t */\n\tfunction ucs2encode(array) {\n\t\treturn map(array, function(value) {\n\t\t\tvar output = '';\n\t\t\tif (value > 0xFFFF) {\n\t\t\t\tvalue -= 0x10000;\n\t\t\t\toutput += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);\n\t\t\t\tvalue = 0xDC00 | value & 0x3FF;\n\t\t\t}\n\t\t\toutput += stringFromCharCode(value);\n\t\t\treturn output;\n\t\t}).join('');\n\t}\n\n\t/**\n\t * Converts a basic code point into a digit/integer.\n\t * @see `digitToBasic()`\n\t * @private\n\t * @param {Number} codePoint The basic numeric code point value.\n\t * @returns {Number} The numeric value of a basic code point (for use in\n\t * representing integers) in the range `0` to `base - 1`, or `base` if\n\t * the code point does not represent a value.\n\t */\n\tfunction basicToDigit(codePoint) {\n\t\tif (codePoint - 48 < 10) {\n\t\t\treturn codePoint - 22;\n\t\t}\n\t\tif (codePoint - 65 < 26) {\n\t\t\treturn codePoint - 65;\n\t\t}\n\t\tif (codePoint - 97 < 26) {\n\t\t\treturn codePoint - 97;\n\t\t}\n\t\treturn base;\n\t}\n\n\t/**\n\t * Converts a digit/integer into a basic code point.\n\t * @see `basicToDigit()`\n\t * @private\n\t * @param {Number} digit The numeric value of a basic code point.\n\t * @returns {Number} The basic code point whose value (when used for\n\t * representing integers) is `digit`, which needs to be in the range\n\t * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is\n\t * used; else, the lowercase form is used. The behavior is undefined\n\t * if `flag` is non-zero and `digit` has no uppercase form.\n\t */\n\tfunction digitToBasic(digit, flag) {\n\t\t// 0..25 map to ASCII a..z or A..Z\n\t\t// 26..35 map to ASCII 0..9\n\t\treturn digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);\n\t}\n\n\t/**\n\t * Bias adaptation function as per section 3.4 of RFC 3492.\n\t * https://tools.ietf.org/html/rfc3492#section-3.4\n\t * @private\n\t */\n\tfunction adapt(delta, numPoints, firstTime) {\n\t\tvar k = 0;\n\t\tdelta = firstTime ? floor(delta / damp) : delta >> 1;\n\t\tdelta += floor(delta / numPoints);\n\t\tfor (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {\n\t\t\tdelta = floor(delta / baseMinusTMin);\n\t\t}\n\t\treturn floor(k + (baseMinusTMin + 1) * delta / (delta + skew));\n\t}\n\n\t/**\n\t * Converts a Punycode string of ASCII-only symbols to a string of Unicode\n\t * symbols.\n\t * @memberOf punycode\n\t * @param {String} input The Punycode string of ASCII-only symbols.\n\t * @returns {String} The resulting string of Unicode symbols.\n\t */\n\tfunction decode(input) {\n\t\t// Don't use UCS-2\n\t\tvar output = [],\n\t\t inputLength = input.length,\n\t\t out,\n\t\t i = 0,\n\t\t n = initialN,\n\t\t bias = initialBias,\n\t\t basic,\n\t\t j,\n\t\t index,\n\t\t oldi,\n\t\t w,\n\t\t k,\n\t\t digit,\n\t\t t,\n\t\t /** Cached calculation results */\n\t\t baseMinusT;\n\n\t\t// Handle the basic code points: let `basic` be the number of input code\n\t\t// points before the last delimiter, or `0` if there is none, then copy\n\t\t// the first basic code points to the output.\n\n\t\tbasic = input.lastIndexOf(delimiter);\n\t\tif (basic < 0) {\n\t\t\tbasic = 0;\n\t\t}\n\n\t\tfor (j = 0; j < basic; ++j) {\n\t\t\t// if it's not a basic code point\n\t\t\tif (input.charCodeAt(j) >= 0x80) {\n\t\t\t\terror('not-basic');\n\t\t\t}\n\t\t\toutput.push(input.charCodeAt(j));\n\t\t}\n\n\t\t// Main decoding loop: start just after the last delimiter if any basic code\n\t\t// points were copied; start at the beginning otherwise.\n\n\t\tfor (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {\n\n\t\t\t// `index` is the index of the next character to be consumed.\n\t\t\t// Decode a generalized variable-length integer into `delta`,\n\t\t\t// which gets added to `i`. The overflow checking is easier\n\t\t\t// if we increase `i` as we go, then subtract off its starting\n\t\t\t// value at the end to obtain `delta`.\n\t\t\tfor (oldi = i, w = 1, k = base; /* no condition */; k += base) {\n\n\t\t\t\tif (index >= inputLength) {\n\t\t\t\t\terror('invalid-input');\n\t\t\t\t}\n\n\t\t\t\tdigit = basicToDigit(input.charCodeAt(index++));\n\n\t\t\t\tif (digit >= base || digit > floor((maxInt - i) / w)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\ti += digit * w;\n\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\n\t\t\t\tif (digit < t) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tbaseMinusT = base - t;\n\t\t\t\tif (w > floor(maxInt / baseMinusT)) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tw *= baseMinusT;\n\n\t\t\t}\n\n\t\t\tout = output.length + 1;\n\t\t\tbias = adapt(i - oldi, out, oldi == 0);\n\n\t\t\t// `i` was supposed to wrap around from `out` to `0`,\n\t\t\t// incrementing `n` each time, so we'll fix that now:\n\t\t\tif (floor(i / out) > maxInt - n) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tn += floor(i / out);\n\t\t\ti %= out;\n\n\t\t\t// Insert `n` at position `i` of the output\n\t\t\toutput.splice(i++, 0, n);\n\n\t\t}\n\n\t\treturn ucs2encode(output);\n\t}\n\n\t/**\n\t * Converts a string of Unicode symbols (e.g. a domain name label) to a\n\t * Punycode string of ASCII-only symbols.\n\t * @memberOf punycode\n\t * @param {String} input The string of Unicode symbols.\n\t * @returns {String} The resulting Punycode string of ASCII-only symbols.\n\t */\n\tfunction encode(input) {\n\t\tvar n,\n\t\t delta,\n\t\t handledCPCount,\n\t\t basicLength,\n\t\t bias,\n\t\t j,\n\t\t m,\n\t\t q,\n\t\t k,\n\t\t t,\n\t\t currentValue,\n\t\t output = [],\n\t\t /** `inputLength` will hold the number of code points in `input`. */\n\t\t inputLength,\n\t\t /** Cached calculation results */\n\t\t handledCPCountPlusOne,\n\t\t baseMinusT,\n\t\t qMinusT;\n\n\t\t// Convert the input in UCS-2 to Unicode\n\t\tinput = ucs2decode(input);\n\n\t\t// Cache the length\n\t\tinputLength = input.length;\n\n\t\t// Initialize the state\n\t\tn = initialN;\n\t\tdelta = 0;\n\t\tbias = initialBias;\n\n\t\t// Handle the basic code points\n\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\tcurrentValue = input[j];\n\t\t\tif (currentValue < 0x80) {\n\t\t\t\toutput.push(stringFromCharCode(currentValue));\n\t\t\t}\n\t\t}\n\n\t\thandledCPCount = basicLength = output.length;\n\n\t\t// `handledCPCount` is the number of code points that have been handled;\n\t\t// `basicLength` is the number of basic code points.\n\n\t\t// Finish the basic string - if it is not empty - with a delimiter\n\t\tif (basicLength) {\n\t\t\toutput.push(delimiter);\n\t\t}\n\n\t\t// Main encoding loop:\n\t\twhile (handledCPCount < inputLength) {\n\n\t\t\t// All non-basic code points < n have been handled already. Find the next\n\t\t\t// larger one:\n\t\t\tfor (m = maxInt, j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\t\t\t\tif (currentValue >= n && currentValue < m) {\n\t\t\t\t\tm = currentValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,\n\t\t\t// but guard against overflow\n\t\t\thandledCPCountPlusOne = handledCPCount + 1;\n\t\t\tif (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {\n\t\t\t\terror('overflow');\n\t\t\t}\n\n\t\t\tdelta += (m - n) * handledCPCountPlusOne;\n\t\t\tn = m;\n\n\t\t\tfor (j = 0; j < inputLength; ++j) {\n\t\t\t\tcurrentValue = input[j];\n\n\t\t\t\tif (currentValue < n && ++delta > maxInt) {\n\t\t\t\t\terror('overflow');\n\t\t\t\t}\n\n\t\t\t\tif (currentValue == n) {\n\t\t\t\t\t// Represent delta as a generalized variable-length integer\n\t\t\t\t\tfor (q = delta, k = base; /* no condition */; k += base) {\n\t\t\t\t\t\tt = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);\n\t\t\t\t\t\tif (q < t) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tqMinusT = q - t;\n\t\t\t\t\t\tbaseMinusT = base - t;\n\t\t\t\t\t\toutput.push(\n\t\t\t\t\t\t\tstringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))\n\t\t\t\t\t\t);\n\t\t\t\t\t\tq = floor(qMinusT / baseMinusT);\n\t\t\t\t\t}\n\n\t\t\t\t\toutput.push(stringFromCharCode(digitToBasic(q, 0)));\n\t\t\t\t\tbias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);\n\t\t\t\t\tdelta = 0;\n\t\t\t\t\t++handledCPCount;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t++delta;\n\t\t\t++n;\n\n\t\t}\n\t\treturn output.join('');\n\t}\n\n\t/**\n\t * Converts a Punycode string representing a domain name or an email address\n\t * to Unicode. Only the Punycoded parts of the input will be converted, i.e.\n\t * it doesn't matter if you call it on a string that has already been\n\t * converted to Unicode.\n\t * @memberOf punycode\n\t * @param {String} input The Punycoded domain name or email address to\n\t * convert to Unicode.\n\t * @returns {String} The Unicode representation of the given Punycode\n\t * string.\n\t */\n\tfunction toUnicode(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexPunycode.test(string)\n\t\t\t\t? decode(string.slice(4).toLowerCase())\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/**\n\t * Converts a Unicode string representing a domain name or an email address to\n\t * Punycode. Only the non-ASCII parts of the domain name will be converted,\n\t * i.e. it doesn't matter if you call it with a domain that's already in\n\t * ASCII.\n\t * @memberOf punycode\n\t * @param {String} input The domain name or email address to convert, as a\n\t * Unicode string.\n\t * @returns {String} The Punycode representation of the given domain name or\n\t * email address.\n\t */\n\tfunction toASCII(input) {\n\t\treturn mapDomain(input, function(string) {\n\t\t\treturn regexNonASCII.test(string)\n\t\t\t\t? 'xn--' + encode(string)\n\t\t\t\t: string;\n\t\t});\n\t}\n\n\t/*--------------------------------------------------------------------------*/\n\n\t/** Define the public API */\n\tpunycode = {\n\t\t/**\n\t\t * A string representing the current Punycode.js version number.\n\t\t * @memberOf punycode\n\t\t * @type String\n\t\t */\n\t\t'version': '1.4.1',\n\t\t/**\n\t\t * An object of methods to convert from JavaScript's internal character\n\t\t * representation (UCS-2) to Unicode code points, and back.\n\t\t * @see <https://mathiasbynens.be/notes/javascript-encoding>\n\t\t * @memberOf punycode\n\t\t * @type Object\n\t\t */\n\t\t'ucs2': {\n\t\t\t'decode': ucs2decode,\n\t\t\t'encode': ucs2encode\n\t\t},\n\t\t'decode': decode,\n\t\t'encode': encode,\n\t\t'toASCII': toASCII,\n\t\t'toUnicode': toUnicode\n\t};\n\n\t/** Expose `punycode` */\n\t// Some AMD build optimizers, like r.js, check for specific condition patterns\n\t// like the following:\n\tif (\n\t\ttypeof define == 'function' &&\n\t\ttypeof define.amd == 'object' &&\n\t\tdefine.amd\n\t) {\n\t\tdefine('punycode', function() {\n\t\t\treturn punycode;\n\t\t});\n\t} else if (freeExports && freeModule) {\n\t\tif (module.exports == freeExports) {\n\t\t\t// in Node.js, io.js, or RingoJS v0.8.0+\n\t\t\tfreeModule.exports = punycode;\n\t\t} else {\n\t\t\t// in Narwhal or RingoJS v0.7.0-\n\t\t\tfor (key in punycode) {\n\t\t\t\tpunycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// in Rhino or a web browser\n\t\troot.punycode = punycode;\n\t}\n\n}(this));\n","module.exports = function(module) {\n\tif (!module.webpackPolyfill) {\n\t\tmodule.deprecate = function() {};\n\t\tmodule.paths = [];\n\t\t// module.parent = undefined by default\n\t\tif (!module.children) module.children = [];\n\t\tObject.defineProperty(module, \"loaded\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.l;\n\t\t\t}\n\t\t});\n\t\tObject.defineProperty(module, \"id\", {\n\t\t\tenumerable: true,\n\t\t\tget: function() {\n\t\t\t\treturn module.i;\n\t\t\t}\n\t\t});\n\t\tmodule.webpackPolyfill = 1;\n\t}\n\treturn module;\n};\n","// markdown-it default options\n\n'use strict';\n\n\nmodule.exports = {\n options: {\n html: false, // Enable HTML tags in source\n xhtmlOut: false, // Use '/' to close single tags (<br />)\n breaks: false, // Convert '\\n' in paragraphs into <br>\n langPrefix: 'language-', // CSS language prefix for fenced blocks\n linkify: false, // autoconvert URL-like texts to links\n\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: '\\u201c\\u201d\\u2018\\u2019', /* “”‘’ */\n\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with <pre... internal wrapper is skipped.\n //\n // function (/*str, lang*/) { return ''; }\n //\n highlight: null,\n\n maxNesting: 100 // Internal protection, recursion limit\n },\n\n components: {\n\n core: {},\n block: {},\n inline: {}\n }\n};\n","// \"Zero\" preset, with nothing enabled. Useful for manual configuring of simple\n// modes. For example, to parse bold/italic only.\n\n'use strict';\n\n\nmodule.exports = {\n options: {\n html: false, // Enable HTML tags in source\n xhtmlOut: false, // Use '/' to close single tags (<br />)\n breaks: false, // Convert '\\n' in paragraphs into <br>\n langPrefix: 'language-', // CSS language prefix for fenced blocks\n linkify: false, // autoconvert URL-like texts to links\n\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: '\\u201c\\u201d\\u2018\\u2019', /* “”‘’ */\n\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with <pre... internal wrapper is skipped.\n //\n // function (/*str, lang*/) { return ''; }\n //\n highlight: null,\n\n maxNesting: 20 // Internal protection, recursion limit\n },\n\n components: {\n\n core: {\n rules: [\n 'normalize',\n 'block',\n 'inline'\n ]\n },\n\n block: {\n rules: [\n 'paragraph'\n ]\n },\n\n inline: {\n rules: [\n 'text'\n ],\n rules2: [\n 'balance_pairs',\n 'text_collapse'\n ]\n }\n }\n};\n","// Commonmark default options\n\n'use strict';\n\n\nmodule.exports = {\n options: {\n html: true, // Enable HTML tags in source\n xhtmlOut: true, // Use '/' to close single tags (<br />)\n breaks: false, // Convert '\\n' in paragraphs into <br>\n langPrefix: 'language-', // CSS language prefix for fenced blocks\n linkify: false, // autoconvert URL-like texts to links\n\n // Enable some language-neutral replacements + quotes beautification\n typographer: false,\n\n // Double + single quotes replacement pairs, when typographer enabled,\n // and smartquotes on. Could be either a String or an Array.\n //\n // For example, you can use '«»„“' for Russian, '„“‚‘' for German,\n // and ['«\\xA0', '\\xA0»', '‹\\xA0', '\\xA0›'] for French (including nbsp).\n quotes: '\\u201c\\u201d\\u2018\\u2019', /* “”‘’ */\n\n // Highlighter function. Should return escaped HTML,\n // or '' if the source string is not changed and should be escaped externaly.\n // If result starts with <pre... internal wrapper is skipped.\n //\n // function (/*str, lang*/) { return ''; }\n //\n highlight: null,\n\n maxNesting: 20 // Internal protection, recursion limit\n },\n\n components: {\n\n core: {\n rules: [\n 'normalize',\n 'block',\n 'inline'\n ]\n },\n\n block: {\n rules: [\n 'blockquote',\n 'code',\n 'fence',\n 'heading',\n 'hr',\n 'html_block',\n 'lheading',\n 'list',\n 'reference',\n 'paragraph'\n ]\n },\n\n inline: {\n rules: [\n 'autolink',\n 'backticks',\n 'emphasis',\n 'entity',\n 'escape',\n 'html_inline',\n 'image',\n 'link',\n 'newline',\n 'text'\n ],\n rules2: [\n 'balance_pairs',\n 'emphasis',\n 'text_collapse'\n ]\n }\n }\n};\n","// Markdown-it plugin to render GitHub-style task lists; see\n//\n// https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments\n// https://github.com/blog/1825-task-lists-in-all-markdown-documents\n\nvar disableCheckboxes = true;\nvar useLabelWrapper = false;\nvar useLabelAfter = false;\n\nmodule.exports = function(md, options) {\n\tif (options) {\n\t\tdisableCheckboxes = !options.enabled;\n\t\tuseLabelWrapper = !!options.label;\n\t\tuseLabelAfter = !!options.labelAfter;\n\t}\n\n\tmd.core.ruler.after('inline', 'github-task-lists', function(state) {\n\t\tvar tokens = state.tokens;\n\t\tfor (var i = 2; i < tokens.length; i++) {\n\t\t\tif (isTodoItem(tokens, i)) {\n\t\t\t\ttodoify(tokens[i], state.Token);\n\t\t\t\tattrSet(tokens[i-2], 'class', 'task-list-item' + (!disableCheckboxes ? ' enabled' : ''));\n\t\t\t\tattrSet(tokens[parentToken(tokens, i-2)], 'class', 'contains-task-list');\n\t\t\t}\n\t\t}\n\t});\n};\n\nfunction attrSet(token, name, value) {\n\tvar index = token.attrIndex(name);\n\tvar attr = [name, value];\n\n\tif (index < 0) {\n\t\ttoken.attrPush(attr);\n\t} else {\n\t\ttoken.attrs[index] = attr;\n\t}\n}\n\nfunction parentToken(tokens, index) {\n\tvar targetLevel = tokens[index].level - 1;\n\tfor (var i = index - 1; i >= 0; i--) {\n\t\tif (tokens[i].level === targetLevel) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n\nfunction isTodoItem(tokens, index) {\n\treturn isInline(tokens[index]) &&\n\t isParagraph(tokens[index - 1]) &&\n\t isListItem(tokens[index - 2]) &&\n\t startsWithTodoMarkdown(tokens[index]);\n}\n\nfunction todoify(token, TokenConstructor) {\n\ttoken.children.unshift(makeCheckbox(token, TokenConstructor));\n\ttoken.children[1].content = token.children[1].content.slice(3);\n\ttoken.content = token.content.slice(3);\n\n\tif (useLabelWrapper) {\n\t\tif (useLabelAfter) {\n\t\t\ttoken.children.pop();\n\n\t\t\t// Use large random number as id property of the checkbox.\n\t\t\tvar id = 'task-item-' + Math.ceil(Math.random() * (10000 * 1000) - 1000);\n\t\t\ttoken.children[0].content = token.children[0].content.slice(0, -1) + ' id=\"' + id + '\">';\n\t\t\ttoken.children.push(afterLabel(token.content, id, TokenConstructor));\n\t\t} else {\n\t\t\ttoken.children.unshift(beginLabel(TokenConstructor));\n\t\t\ttoken.children.push(endLabel(TokenConstructor));\n\t\t}\n\t}\n}\n\nfunction makeCheckbox(token, TokenConstructor) {\n\tvar checkbox = new TokenConstructor('html_inline', '', 0);\n\tvar disabledAttr = disableCheckboxes ? ' disabled=\"\" ' : '';\n\tif (token.content.indexOf('[ ] ') === 0) {\n\t\tcheckbox.content = '<input class=\"task-list-item-checkbox\"' + disabledAttr + 'type=\"checkbox\">';\n\t} else if (token.content.indexOf('[x] ') === 0 || token.content.indexOf('[X] ') === 0) {\n\t\tcheckbox.content = '<input class=\"task-list-item-checkbox\" checked=\"\"' + disabledAttr + 'type=\"checkbox\">';\n\t}\n\treturn checkbox;\n}\n\n// these next two functions are kind of hacky; probably should really be a\n// true block-level token with .tag=='label'\nfunction beginLabel(TokenConstructor) {\n\tvar token = new TokenConstructor('html_inline', '', 0);\n\ttoken.content = '<label>';\n\treturn token;\n}\n\nfunction endLabel(TokenConstructor) {\n\tvar token = new TokenConstructor('html_inline', '', 0);\n\ttoken.content = '</label>';\n\treturn token;\n}\n\nfunction afterLabel(content, id, TokenConstructor) {\n\tvar token = new TokenConstructor('html_inline', '', 0);\n\ttoken.content = '<label class=\"task-list-item-label\" for=\"' + id + '\">' + content + '</label>';\n\ttoken.attrs = [{for: id}];\n\treturn token;\n}\n\nfunction isInline(token) { return token.type === 'inline'; }\nfunction isParagraph(token) { return token.type === 'paragraph_open'; }\nfunction isListItem(token) { return token.type === 'list_item_open'; }\n\nfunction startsWithTodoMarkdown(token) {\n\t// leading whitespace in a list item is already trimmed off by markdown-it\n\treturn token.content.indexOf('[ ] ') === 0 || token.content.indexOf('[x] ') === 0 || token.content.indexOf('[X] ') === 0;\n}\n","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./mentionui.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-mention-list-max-height:300px}.ck.ck-mentions{max-height:var(--ck-mention-list-max-height);overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain}.ck.ck-mentions>.ck-list__item{overflow:hidden;flex-shrink:0}\"","var content = require(\"!!../../../postcss-loader/src/index.js??ref--5-1!./mention.css\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {\"injectType\":\"singletonStyleTag\"}\n\noptions.insert = \"head\";\noptions.singleton = true;\n\nvar update = require(\"!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","module.exports = \":root{--ck-color-mention-background:rgba(153,0,48,0.1);--ck-color-mention-text:#990030}.ck-content .mention{background:var(--ck-color-mention-background);color:var(--ck-color-mention-text)}\"","import root from './_root.js';\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nexport default Symbol;\n","import Symbol from './_Symbol.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nexport default getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nexport default objectToString;\n","import Symbol from './_Symbol.js';\nimport getRawTag from './_getRawTag.js';\nimport objectToString from './_objectToString.js';\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nexport default baseGetTag;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nexport default overArg;\n","import overArg from './_overArg.js';\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nexport default getPrototype;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nexport default isObjectLike;\n","import baseGetTag from './_baseGetTag.js';\nimport getPrototype from './_getPrototype.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to infer the `Object` constructor. */\nvar objectCtorString = funcToString.call(Object);\n\n/**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\nfunction isPlainObject(value) {\n if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n funcToString.call(Ctor) == objectCtorString;\n}\n\nexport default isPlainObject;\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n}\n\nexport default listCacheClear;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nexport default eq;\n","import eq from './eq.js';\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n}\n\nexport default assocIndexOf;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n}\n\nexport default listCacheDelete;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n}\n\nexport default listCacheGet;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n}\n\nexport default listCacheHas;\n","import assocIndexOf from './_assocIndexOf.js';\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n}\n\nexport default listCacheSet;\n","import listCacheClear from './_listCacheClear.js';\nimport listCacheDelete from './_listCacheDelete.js';\nimport listCacheGet from './_listCacheGet.js';\nimport listCacheHas from './_listCacheHas.js';\nimport listCacheSet from './_listCacheSet.js';\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nexport default ListCache;\n","import ListCache from './_ListCache.js';\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n}\n\nexport default stackClear;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n}\n\nexport default stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n return this.__data__.get(key);\n}\n\nexport default stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n return this.__data__.has(key);\n}\n\nexport default stackHas;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nexport default isObject;\n","import baseGetTag from './_baseGetTag.js';\nimport isObject from './isObject.js';\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nexport default isFunction;\n","import coreJsData from './_coreJsData.js';\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nexport default isMasked;\n","import root from './_root.js';\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nexport default coreJsData;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nexport default toSource;\n","import isFunction from './isFunction.js';\nimport isMasked from './_isMasked.js';\nimport isObject from './isObject.js';\nimport toSource from './_toSource.js';\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nexport default baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nexport default getValue;\n","import baseIsNative from './_baseIsNative.js';\nimport getValue from './_getValue.js';\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nexport default getNative;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nexport default Map;\n","import getNative from './_getNative.js';\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nexport default nativeCreate;\n","import nativeCreate from './_nativeCreate.js';\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n}\n\nexport default hashClear;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default hashDelete;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nexport default hashGet;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n}\n\nexport default hashHas;\n","import nativeCreate from './_nativeCreate.js';\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n}\n\nexport default hashSet;\n","import hashClear from './_hashClear.js';\nimport hashDelete from './_hashDelete.js';\nimport hashGet from './_hashGet.js';\nimport hashHas from './_hashHas.js';\nimport hashSet from './_hashSet.js';\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nexport default Hash;\n","import Hash from './_Hash.js';\nimport ListCache from './_ListCache.js';\nimport Map from './_Map.js';\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n}\n\nexport default mapCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n}\n\nexport default isKeyable;\n","import isKeyable from './_isKeyable.js';\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n}\n\nexport default getMapData;\n","import getMapData from './_getMapData.js';\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n}\n\nexport default mapCacheDelete;\n","import getMapData from './_getMapData.js';\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n return getMapData(this, key).get(key);\n}\n\nexport default mapCacheGet;\n","import getMapData from './_getMapData.js';\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n return getMapData(this, key).has(key);\n}\n\nexport default mapCacheHas;\n","import getMapData from './_getMapData.js';\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n}\n\nexport default mapCacheSet;\n","import mapCacheClear from './_mapCacheClear.js';\nimport mapCacheDelete from './_mapCacheDelete.js';\nimport mapCacheGet from './_mapCacheGet.js';\nimport mapCacheHas from './_mapCacheHas.js';\nimport mapCacheSet from './_mapCacheSet.js';\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nexport default MapCache;\n","import ListCache from './_ListCache.js';\nimport Map from './_Map.js';\nimport MapCache from './_MapCache.js';\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n}\n\nexport default stackSet;\n","import ListCache from './_ListCache.js';\nimport stackClear from './_stackClear.js';\nimport stackDelete from './_stackDelete.js';\nimport stackGet from './_stackGet.js';\nimport stackHas from './_stackHas.js';\nimport stackSet from './_stackSet.js';\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nexport default Stack;\n","/**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n}\n\nexport default arrayEach;\n","import getNative from './_getNative.js';\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nexport default defineProperty;\n","import defineProperty from './_defineProperty.js';\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n}\n\nexport default baseAssignValue;\n","import baseAssignValue from './_baseAssignValue.js';\nimport eq from './eq.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nexport default assignValue;\n","import assignValue from './_assignValue.js';\nimport baseAssignValue from './_baseAssignValue.js';\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n}\n\nexport default copyObject;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nexport default baseTimes;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nexport default baseIsArguments;\n","import baseIsArguments from './_baseIsArguments.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n};\n\nexport default isArguments;\n","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nexport default isArray;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n var type = typeof value;\n length = length == null ? MAX_SAFE_INTEGER : length;\n\n return !!length &&\n (type == 'number' ||\n (type != 'symbol' && reIsUint.test(value))) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nexport default isIndex;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nexport default isLength;\n","import baseGetTag from './_baseGetTag.js';\nimport isLength from './isLength.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nexport default baseIsTypedArray;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nexport default baseUnary;\n","import baseIsTypedArray from './_baseIsTypedArray.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nexport default isTypedArray;\n","import baseTimes from './_baseTimes.js';\nimport isArguments from './isArguments.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isIndex from './_isIndex.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default arrayLikeKeys;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nexport default isPrototype;\n","import overArg from './_overArg.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nexport default nativeKeys;\n","import isPrototype from './_isPrototype.js';\nimport nativeKeys from './_nativeKeys.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default baseKeys;\n","import isFunction from './isFunction.js';\nimport isLength from './isLength.js';\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\nexport default isArrayLike;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeys from './_baseKeys.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nexport default keys;\n","import copyObject from './_copyObject.js';\nimport keys from './keys.js';\n\n/**\n * The base implementation of `_.assign` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssign(object, source) {\n return object && copyObject(source, keys(source), object);\n}\n\nexport default baseAssign;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default nativeKeysIn;\n","import isObject from './isObject.js';\nimport isPrototype from './_isPrototype.js';\nimport nativeKeysIn from './_nativeKeysIn.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n}\n\nexport default baseKeysIn;\n","import arrayLikeKeys from './_arrayLikeKeys.js';\nimport baseKeysIn from './_baseKeysIn.js';\nimport isArrayLike from './isArrayLike.js';\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nexport default keysIn;\n","import copyObject from './_copyObject.js';\nimport keysIn from './keysIn.js';\n\n/**\n * The base implementation of `_.assignIn` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssignIn(object, source) {\n return object && copyObject(source, keysIn(source), object);\n}\n\nexport default baseAssignIn;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n}\n\nexport default copyArray;\n","/**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction arrayFilter(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result[resIndex++] = value;\n }\n }\n return result;\n}\n\nexport default arrayFilter;\n","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n return [];\n}\n\nexport default stubArray;\n","import arrayFilter from './_arrayFilter.js';\nimport stubArray from './stubArray.js';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n if (object == null) {\n return [];\n }\n object = Object(object);\n return arrayFilter(nativeGetSymbols(object), function(symbol) {\n return propertyIsEnumerable.call(object, symbol);\n });\n};\n\nexport default getSymbols;\n","import copyObject from './_copyObject.js';\nimport getSymbols from './_getSymbols.js';\n\n/**\n * Copies own symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbols(source, object) {\n return copyObject(source, getSymbols(source), object);\n}\n\nexport default copySymbols;\n","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n}\n\nexport default arrayPush;\n","import arrayPush from './_arrayPush.js';\nimport getPrototype from './_getPrototype.js';\nimport getSymbols from './_getSymbols.js';\nimport stubArray from './stubArray.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own and inherited enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {\n var result = [];\n while (object) {\n arrayPush(result, getSymbols(object));\n object = getPrototype(object);\n }\n return result;\n};\n\nexport default getSymbolsIn;\n","import copyObject from './_copyObject.js';\nimport getSymbolsIn from './_getSymbolsIn.js';\n\n/**\n * Copies own and inherited symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbolsIn(source, object) {\n return copyObject(source, getSymbolsIn(source), object);\n}\n\nexport default copySymbolsIn;\n","import arrayPush from './_arrayPush.js';\nimport isArray from './isArray.js';\n\n/**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction baseGetAllKeys(object, keysFunc, symbolsFunc) {\n var result = keysFunc(object);\n return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n}\n\nexport default baseGetAllKeys;\n","import baseGetAllKeys from './_baseGetAllKeys.js';\nimport getSymbols from './_getSymbols.js';\nimport keys from './keys.js';\n\n/**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeys(object) {\n return baseGetAllKeys(object, keys, getSymbols);\n}\n\nexport default getAllKeys;\n","import baseGetAllKeys from './_baseGetAllKeys.js';\nimport getSymbolsIn from './_getSymbolsIn.js';\nimport keysIn from './keysIn.js';\n\n/**\n * Creates an array of own and inherited enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeysIn(object) {\n return baseGetAllKeys(object, keysIn, getSymbolsIn);\n}\n\nexport default getAllKeysIn;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView');\n\nexport default DataView;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Promise = getNative(root, 'Promise');\n\nexport default Promise;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar Set = getNative(root, 'Set');\n\nexport default Set;\n","import getNative from './_getNative.js';\nimport root from './_root.js';\n\n/* Built-in method references that are verified to be native. */\nvar WeakMap = getNative(root, 'WeakMap');\n\nexport default WeakMap;\n","import DataView from './_DataView.js';\nimport Map from './_Map.js';\nimport Promise from './_Promise.js';\nimport Set from './_Set.js';\nimport WeakMap from './_WeakMap.js';\nimport baseGetTag from './_baseGetTag.js';\nimport toSource from './_toSource.js';\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]',\n objectTag = '[object Object]',\n promiseTag = '[object Promise]',\n setTag = '[object Set]',\n weakMapTag = '[object WeakMap]';\n\nvar dataViewTag = '[object DataView]';\n\n/** Used to detect maps, sets, and weakmaps. */\nvar dataViewCtorString = toSource(DataView),\n mapCtorString = toSource(Map),\n promiseCtorString = toSource(Promise),\n setCtorString = toSource(Set),\n weakMapCtorString = toSource(WeakMap);\n\n/**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nvar getTag = baseGetTag;\n\n// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\nif ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n (Map && getTag(new Map) != mapTag) ||\n (Promise && getTag(Promise.resolve()) != promiseTag) ||\n (Set && getTag(new Set) != setTag) ||\n (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n getTag = function(value) {\n var result = baseGetTag(value),\n Ctor = result == objectTag ? value.constructor : undefined,\n ctorString = Ctor ? toSource(Ctor) : '';\n\n if (ctorString) {\n switch (ctorString) {\n case dataViewCtorString: return dataViewTag;\n case mapCtorString: return mapTag;\n case promiseCtorString: return promiseTag;\n case setCtorString: return setTag;\n case weakMapCtorString: return weakMapTag;\n }\n }\n return result;\n };\n}\n\nexport default getTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Initializes an array clone.\n *\n * @private\n * @param {Array} array The array to clone.\n * @returns {Array} Returns the initialized clone.\n */\nfunction initCloneArray(array) {\n var length = array.length,\n result = new array.constructor(length);\n\n // Add properties assigned by `RegExp#exec`.\n if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n result.index = array.index;\n result.input = array.input;\n }\n return result;\n}\n\nexport default initCloneArray;\n","import root from './_root.js';\n\n/** Built-in value references. */\nvar Uint8Array = root.Uint8Array;\n\nexport default Uint8Array;\n","import Uint8Array from './_Uint8Array.js';\n\n/**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction cloneArrayBuffer(arrayBuffer) {\n var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n return result;\n}\n\nexport default cloneArrayBuffer;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\n\n/**\n * Creates a clone of `dataView`.\n *\n * @private\n * @param {Object} dataView The data view to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned data view.\n */\nfunction cloneDataView(dataView, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n}\n\nexport default cloneDataView;\n","/** Used to match `RegExp` flags from their coerced string values. */\nvar reFlags = /\\w*$/;\n\n/**\n * Creates a clone of `regexp`.\n *\n * @private\n * @param {Object} regexp The regexp to clone.\n * @returns {Object} Returns the cloned regexp.\n */\nfunction cloneRegExp(regexp) {\n var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));\n result.lastIndex = regexp.lastIndex;\n return result;\n}\n\nexport default cloneRegExp;\n","import Symbol from './_Symbol.js';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * Creates a clone of the `symbol` object.\n *\n * @private\n * @param {Object} symbol The symbol object to clone.\n * @returns {Object} Returns the cloned symbol object.\n */\nfunction cloneSymbol(symbol) {\n return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};\n}\n\nexport default cloneSymbol;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\n\n/**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\nfunction cloneTypedArray(typedArray, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n}\n\nexport default cloneTypedArray;\n","import cloneArrayBuffer from './_cloneArrayBuffer.js';\nimport cloneDataView from './_cloneDataView.js';\nimport cloneRegExp from './_cloneRegExp.js';\nimport cloneSymbol from './_cloneSymbol.js';\nimport cloneTypedArray from './_cloneTypedArray.js';\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/**\n * Initializes an object clone based on its `toStringTag`.\n *\n * **Note:** This function only supports cloning values with tags of\n * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.\n *\n * @private\n * @param {Object} object The object to clone.\n * @param {string} tag The `toStringTag` of the object to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneByTag(object, tag, isDeep) {\n var Ctor = object.constructor;\n switch (tag) {\n case arrayBufferTag:\n return cloneArrayBuffer(object);\n\n case boolTag:\n case dateTag:\n return new Ctor(+object);\n\n case dataViewTag:\n return cloneDataView(object, isDeep);\n\n case float32Tag: case float64Tag:\n case int8Tag: case int16Tag: case int32Tag:\n case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n return cloneTypedArray(object, isDeep);\n\n case mapTag:\n return new Ctor;\n\n case numberTag:\n case stringTag:\n return new Ctor(object);\n\n case regexpTag:\n return cloneRegExp(object);\n\n case setTag:\n return new Ctor;\n\n case symbolTag:\n return cloneSymbol(object);\n }\n}\n\nexport default initCloneByTag;\n","import isObject from './isObject.js';\n\n/** Built-in value references. */\nvar objectCreate = Object.create;\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n function object() {}\n return function(proto) {\n if (!isObject(proto)) {\n return {};\n }\n if (objectCreate) {\n return objectCreate(proto);\n }\n object.prototype = proto;\n var result = new object;\n object.prototype = undefined;\n return result;\n };\n}());\n\nexport default baseCreate;\n","import baseCreate from './_baseCreate.js';\nimport getPrototype from './_getPrototype.js';\nimport isPrototype from './_isPrototype.js';\n\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n return (typeof object.constructor == 'function' && !isPrototype(object))\n ? baseCreate(getPrototype(object))\n : {};\n}\n\nexport default initCloneObject;\n","import getTag from './_getTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]';\n\n/**\n * The base implementation of `_.isMap` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n */\nfunction baseIsMap(value) {\n return isObjectLike(value) && getTag(value) == mapTag;\n}\n\nexport default baseIsMap;\n","import baseIsMap from './_baseIsMap.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsMap = nodeUtil && nodeUtil.isMap;\n\n/**\n * Checks if `value` is classified as a `Map` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n * @example\n *\n * _.isMap(new Map);\n * // => true\n *\n * _.isMap(new WeakMap);\n * // => false\n */\nvar isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;\n\nexport default isMap;\n","import getTag from './_getTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar setTag = '[object Set]';\n\n/**\n * The base implementation of `_.isSet` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n */\nfunction baseIsSet(value) {\n return isObjectLike(value) && getTag(value) == setTag;\n}\n\nexport default baseIsSet;\n","import baseIsSet from './_baseIsSet.js';\nimport baseUnary from './_baseUnary.js';\nimport nodeUtil from './_nodeUtil.js';\n\n/* Node.js helper references. */\nvar nodeIsSet = nodeUtil && nodeUtil.isSet;\n\n/**\n * Checks if `value` is classified as a `Set` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n * @example\n *\n * _.isSet(new Set);\n * // => true\n *\n * _.isSet(new WeakSet);\n * // => false\n */\nvar isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;\n\nexport default isSet;\n","import Stack from './_Stack.js';\nimport arrayEach from './_arrayEach.js';\nimport assignValue from './_assignValue.js';\nimport baseAssign from './_baseAssign.js';\nimport baseAssignIn from './_baseAssignIn.js';\nimport cloneBuffer from './_cloneBuffer.js';\nimport copyArray from './_copyArray.js';\nimport copySymbols from './_copySymbols.js';\nimport copySymbolsIn from './_copySymbolsIn.js';\nimport getAllKeys from './_getAllKeys.js';\nimport getAllKeysIn from './_getAllKeysIn.js';\nimport getTag from './_getTag.js';\nimport initCloneArray from './_initCloneArray.js';\nimport initCloneByTag from './_initCloneByTag.js';\nimport initCloneObject from './_initCloneObject.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isMap from './isMap.js';\nimport isObject from './isObject.js';\nimport isSet from './isSet.js';\nimport keys from './keys.js';\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n CLONE_FLAT_FLAG = 2,\n CLONE_SYMBOLS_FLAG = 4;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values supported by `_.clone`. */\nvar cloneableTags = {};\ncloneableTags[argsTag] = cloneableTags[arrayTag] =\ncloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =\ncloneableTags[boolTag] = cloneableTags[dateTag] =\ncloneableTags[float32Tag] = cloneableTags[float64Tag] =\ncloneableTags[int8Tag] = cloneableTags[int16Tag] =\ncloneableTags[int32Tag] = cloneableTags[mapTag] =\ncloneableTags[numberTag] = cloneableTags[objectTag] =\ncloneableTags[regexpTag] = cloneableTags[setTag] =\ncloneableTags[stringTag] = cloneableTags[symbolTag] =\ncloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\ncloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\ncloneableTags[errorTag] = cloneableTags[funcTag] =\ncloneableTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.clone` and `_.cloneDeep` which tracks\n * traversed objects.\n *\n * @private\n * @param {*} value The value to clone.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Deep clone\n * 2 - Flatten inherited properties\n * 4 - Clone symbols\n * @param {Function} [customizer] The function to customize cloning.\n * @param {string} [key] The key of `value`.\n * @param {Object} [object] The parent object of `value`.\n * @param {Object} [stack] Tracks traversed objects and their clone counterparts.\n * @returns {*} Returns the cloned value.\n */\nfunction baseClone(value, bitmask, customizer, key, object, stack) {\n var result,\n isDeep = bitmask & CLONE_DEEP_FLAG,\n isFlat = bitmask & CLONE_FLAT_FLAG,\n isFull = bitmask & CLONE_SYMBOLS_FLAG;\n\n if (customizer) {\n result = object ? customizer(value, key, object, stack) : customizer(value);\n }\n if (result !== undefined) {\n return result;\n }\n if (!isObject(value)) {\n return value;\n }\n var isArr = isArray(value);\n if (isArr) {\n result = initCloneArray(value);\n if (!isDeep) {\n return copyArray(value, result);\n }\n } else {\n var tag = getTag(value),\n isFunc = tag == funcTag || tag == genTag;\n\n if (isBuffer(value)) {\n return cloneBuffer(value, isDeep);\n }\n if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n result = (isFlat || isFunc) ? {} : initCloneObject(value);\n if (!isDeep) {\n return isFlat\n ? copySymbolsIn(value, baseAssignIn(result, value))\n : copySymbols(value, baseAssign(result, value));\n }\n } else {\n if (!cloneableTags[tag]) {\n return object ? value : {};\n }\n result = initCloneByTag(value, tag, isDeep);\n }\n }\n // Check for circular references and return its corresponding clone.\n stack || (stack = new Stack);\n var stacked = stack.get(value);\n if (stacked) {\n return stacked;\n }\n stack.set(value, result);\n\n if (isSet(value)) {\n value.forEach(function(subValue) {\n result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));\n });\n } else if (isMap(value)) {\n value.forEach(function(subValue, key) {\n result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));\n });\n }\n\n var keysFunc = isFull\n ? (isFlat ? getAllKeysIn : getAllKeys)\n : (isFlat ? keysIn : keys);\n\n var props = isArr ? undefined : keysFunc(value);\n arrayEach(props || value, function(subValue, key) {\n if (props) {\n key = subValue;\n subValue = value[key];\n }\n // Recursively populate clone (susceptible to call stack limits).\n assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));\n });\n return result;\n}\n\nexport default baseClone;\n","import baseClone from './_baseClone.js';\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n CLONE_SYMBOLS_FLAG = 4;\n\n/**\n * This method is like `_.cloneWith` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @param {Function} [customizer] The function to customize cloning.\n * @returns {*} Returns the deep cloned value.\n * @see _.cloneWith\n * @example\n *\n * function customizer(value) {\n * if (_.isElement(value)) {\n * return value.cloneNode(true);\n * }\n * }\n *\n * var el = _.cloneDeepWith(document.body, customizer);\n *\n * console.log(el === document.body);\n * // => false\n * console.log(el.nodeName);\n * // => 'BODY'\n * console.log(el.childNodes.length);\n * // => 20\n */\nfunction cloneDeepWith(value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);\n}\n\nexport default cloneDeepWith;\n","import isObjectLike from './isObjectLike.js';\nimport isPlainObject from './isPlainObject.js';\n\n/**\n * Checks if `value` is likely a DOM element.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.\n * @example\n *\n * _.isElement(document.body);\n * // => true\n *\n * _.isElement('<body>');\n * // => false\n */\nfunction isElement(value) {\n return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);\n}\n\nexport default isElement;\n","/**\n * @license Copyright (c) 2003-2019, 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/config\n */\n\nimport { isPlainObject, isElement, cloneDeepWith } from 'lodash-es';\n\n/**\n * Handles a configuration dictionary.\n */\nexport default class Config {\n\t/**\n\t * Creates an instance of the {@link ~Config} class.\n\t *\n\t * @param {Object} [configurations] The initial configurations to be set. Usually, provided by the user.\n\t * @param {Object} [defaultConfigurations] The default configurations. Usually, provided by the system.\n\t */\n\tconstructor( configurations, defaultConfigurations ) {\n\t\t/**\n\t\t * Store for the whole configuration.\n\t\t *\n\t\t * @private\n\t\t * @member {Object}\n\t\t */\n\t\tthis._config = {};\n\n\t\t// Set default configuration.\n\t\tif ( defaultConfigurations ) {\n\t\t\tthis.define( defaultConfigurations );\n\t\t}\n\n\t\t// Set initial configuration.\n\t\tif ( configurations ) {\n\t\t\tthis._setObjectToTarget( this._config, configurations );\n\t\t}\n\t}\n\n\t/**\n\t * Set configuration values.\n\t *\n\t * It accepts both a name/value pair or an object, which properties and values will be used to set\n\t * configurations.\n\t *\n\t * It also accepts setting a \"deep configuration\" by using dots in the name. For example, `'resize.width'` sets\n\t * the value for the `width` configuration in the `resize` subset.\n\t *\n\t *\t\tconfig.set( 'width', 500 );\n\t *\t\tconfig.set( 'toolbar.collapsed', true );\n\t *\n\t *\t\t// Equivalent to:\n\t *\t\tconfig.set( {\n\t *\t\t\twidth: 500\n\t *\t\t\ttoolbar: {\n\t *\t\t\t\tcollapsed: true\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * Passing an object as the value will amend the configuration, not replace it.\n\t *\n\t *\t\tconfig.set( 'toolbar', {\n\t *\t\t\tcollapsed: true,\n\t *\t\t} );\n\t *\n\t *\t\tconfig.set( 'toolbar', {\n\t *\t\t\tcolor: 'red',\n\t *\t\t} );\n\t *\n\t *\t\tconfig.get( 'toolbar.collapsed' ); // true\n\t *\t\tconfig.get( 'toolbar.color' ); // 'red'\n\t *\n\t * @param {String|Object} name The configuration name or an object from which take properties as\n\t * configuration entries. Configuration names are case-sensitive.\n\t * @param {*} value The configuration value. Used if a name is passed.\n\t */\n\tset( name, value ) {\n\t\tthis._setToTarget( this._config, name, value );\n\t}\n\n\t/**\n\t * Does exactly the same as {@link #set} with one exception – passed configuration extends\n\t * existing one, but does not overwrite already defined values.\n\t *\n\t * This method is supposed to be called by plugin developers to setup plugin's configurations. It would be\n\t * rarely used for other needs.\n\t *\n\t * @param {String|Object} name The configuration name or an object from which take properties as\n\t * configuration entries. Configuration names are case-sensitive.\n\t * @param {*} value The configuration value. Used if a name is passed.\n\t */\n\tdefine( name, value ) {\n\t\tconst isDefine = true;\n\n\t\tthis._setToTarget( this._config, name, value, isDefine );\n\t}\n\n\t/**\n\t * Gets the value for a configuration entry.\n\t *\n\t *\t\tconfig.get( 'name' );\n\t *\n\t * Deep configurations can be retrieved by separating each part with a dot.\n\t *\n\t *\t\tconfig.get( 'toolbar.collapsed' );\n\t *\n\t * @param {String} name The configuration name. Configuration names are case-sensitive.\n\t * @returns {*} The configuration value or `undefined` if the configuration entry was not found.\n\t */\n\tget( name ) {\n\t\treturn this._getFromSource( this._config, name );\n\t}\n\n\t/**\n\t * Saves passed configuration to the specified target (nested object).\n\t *\n\t * @private\n\t * @param {Object} target Nested config object.\n\t * @param {String|Object} name The configuration name or an object from which take properties as\n\t * configuration entries. Configuration names are case-sensitive.\n\t * @param {*} value The configuration value. Used if a name is passed.\n\t * @param {Boolean} [isDefine=false] Define if passed configuration should overwrite existing one.\n\t */\n\t_setToTarget( target, name, value, isDefine = false ) {\n\t\t// In case of an object, iterate through it and call `_setToTarget` again for each property.\n\t\tif ( isPlainObject( name ) ) {\n\t\t\tthis._setObjectToTarget( target, name, isDefine );\n\n\t\t\treturn;\n\t\t}\n\n\t\t// The configuration name should be split into parts if it has dots. E.g. `resize.width` -> [`resize`, `width`].\n\t\tconst parts = name.split( '.' );\n\n\t\t// Take the name of the configuration out of the parts. E.g. `resize.width` -> `width`.\n\t\tname = parts.pop();\n\n\t\t// Iterate over parts to check if currently stored configuration has proper structure.\n\t\tfor ( const part of parts ) {\n\t\t\t// If there is no object for specified part then create one.\n\t\t\tif ( !isPlainObject( target[ part ] ) ) {\n\t\t\t\ttarget[ part ] = {};\n\t\t\t}\n\n\t\t\t// Nested object becomes a target.\n\t\t\ttarget = target[ part ];\n\t\t}\n\n\t\t// In case of value is an object.\n\t\tif ( isPlainObject( value ) ) {\n\t\t\t// We take care of proper config structure.\n\t\t\tif ( !isPlainObject( target[ name ] ) ) {\n\t\t\t\ttarget[ name ] = {};\n\t\t\t}\n\n\t\t\ttarget = target[ name ];\n\n\t\t\t// And iterate through this object calling `_setToTarget` again for each property.\n\t\t\tthis._setObjectToTarget( target, value, isDefine );\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Do nothing if we are defining configuration for non empty name.\n\t\tif ( isDefine && typeof target[ name ] != 'undefined' ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttarget[ name ] = value;\n\t}\n\n\t/**\n\t * Get specified configuration from specified source (nested object).\n\t *\n\t * @private\n\t * @param {Object} source level of nested object.\n\t * @param {String} name The configuration name. Configuration names are case-sensitive.\n\t * @returns {*} The configuration value or `undefined` if the configuration entry was not found.\n\t */\n\t_getFromSource( source, name ) {\n\t\t// The configuration name should be split into parts if it has dots. E.g. `resize.width` -> [`resize`, `width`].\n\t\tconst parts = name.split( '.' );\n\n\t\t// Take the name of the configuration out of the parts. E.g. `resize.width` -> `width`.\n\t\tname = parts.pop();\n\n\t\t// Iterate over parts to check if currently stored configuration has proper structure.\n\t\tfor ( const part of parts ) {\n\t\t\tif ( !isPlainObject( source[ part ] ) ) {\n\t\t\t\tsource = null;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Nested object becomes a source.\n\t\t\tsource = source[ part ];\n\t\t}\n\n\t\t// Always returns undefined for non existing configuration.\n\t\treturn source ? cloneConfig( source[ name ] ) : undefined;\n\t}\n\n\t/**\n\t * Iterates through passed object and calls {@link #_setToTarget} method with object key and value for each property.\n\t *\n\t * @private\n\t * @param {Object} target Nested config object.\n\t * @param {Object} configuration Configuration data set\n\t * @param {Boolean} [isDefine] Defines if passed configuration is default configuration or not.\n\t */\n\t_setObjectToTarget( target, configuration, isDefine ) {\n\t\tObject.keys( configuration ).forEach( key => {\n\t\t\tthis._setToTarget( target, key, configuration[ key ], isDefine );\n\t\t} );\n\t}\n}\n\n// Clones configuration object or value.\n// @param {*} source Source configuration\n// @returns {*} Cloned configuration value.\nfunction cloneConfig( source ) {\n\treturn cloneDeepWith( source, leaveDOMReferences );\n}\n\n// A customizer function for cloneDeepWith.\n// It will leave references to DOM Elements instead of cloning them.\n//\n// @param {*} value\n// @returns {Element|undefined}\nfunction leaveDOMReferences( value ) {\n\treturn isElement( value ) ? value : undefined;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/spy\n */\n\n/**\n * Creates a spy function (ala Sinon.js) that can be used to inspect call to it.\n *\n * The following are the present features:\n *\n * * spy.called: property set to `true` if the function has been called at least once.\n *\n * @returns {Function} The spy function.\n */\nfunction spy() {\n\treturn function spy() {\n\t\tspy.called = true;\n\t};\n}\n\nexport default spy;\n","/**\n * @license Copyright (c) 2003-2019, 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.<Object>}\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-2019, 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/uid\n */\n\n/**\n * Returns a unique id. This id consist of an 'e' character and a randomly generated string of 32 aphanumeric characters.\n * Each character in uid string represents a hexadecimal digit (base 16).\n *\n * @returns {String} A hexadecimal number representing the id.\n */\nexport default function uid() {\n\tlet uuid = 'e'; // Make sure that id does not start with number.\n\n\tfor ( let i = 0; i < 8; i++ ) {\n\t\tuuid += Math.floor( ( 1 + Math.random() ) * 0x10000 ).toString( 16 ).substring( 1 );\n\t}\n\n\treturn uuid;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/priorities\n */\n\n/**\n * String representing a priority value.\n *\n * @typedef {'highest'|'high'|'normal'|'low'|'lowest'} module:utils/priorities~PriorityString\n */\n\n/**\n * Provides group of constants to use instead of hardcoding numeric priority values.\n *\n * @namespace\n */\nconst priorities = {\n\t/**\n\t * Converts a string with priority name to it's numeric value. If `Number` is given, it just returns it.\n\t *\n\t * @static\n\t * @param {module:utils/priorities~PriorityString|Number} priority Priority to convert.\n\t * @returns {Number} Converted priority.\n\t */\n\tget( priority ) {\n\t\tif ( typeof priority != 'number' ) {\n\t\t\treturn this[ priority ] || this.normal;\n\t\t} else {\n\t\t\treturn priority;\n\t\t}\n\t},\n\n\thighest: 100000,\n\thigh: 1000,\n\tnormal: 0,\n\tlow: -1000,\n\tlowest: -100000\n};\n\nexport default priorities;\n","/**\n * @license Copyright (c) 2003-2019, 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/emittermixin\n */\n\nimport EventInfo from './eventinfo';\nimport uid from './uid';\nimport priorities from './priorities';\n\n// To check if component is loaded more than once.\nimport './version';\nimport CKEditorError from './ckeditorerror';\n\nconst _listeningTo = Symbol( 'listeningTo' );\nconst _emitterId = Symbol( 'emitterId' );\n\n/**\n * Mixin that injects the {@link ~Emitter events API} into its host.\n *\n * @mixin EmitterMixin\n * @implements module:utils/emittermixin~Emitter\n */\nconst EmitterMixin = {\n\t/**\n\t * @inheritDoc\n\t */\n\ton( event, callback, options = {} ) {\n\t\tthis.listenTo( this, event, callback, options );\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tonce( event, callback, options ) {\n\t\tlet wasFired = false;\n\n\t\tconst onceCallback = function( event, ...args ) {\n\t\t\t// Ensure the callback is called only once even if the callback itself leads to re-firing the event\n\t\t\t// (which would call the callback again).\n\t\t\tif ( !wasFired ) {\n\t\t\t\twasFired = true;\n\n\t\t\t\t// Go off() at the first call.\n\t\t\t\tevent.off();\n\n\t\t\t\t// Go with the original callback.\n\t\t\t\tcallback.call( this, event, ...args );\n\t\t\t}\n\t\t};\n\n\t\t// Make a similar on() call, simply replacing the callback.\n\t\tthis.listenTo( this, event, onceCallback, options );\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\toff( event, callback ) {\n\t\tthis.stopListening( this, event, callback );\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tlistenTo( emitter, event, callback, options = {} ) {\n\t\tlet emitterInfo, eventCallbacks;\n\n\t\t// _listeningTo contains a list of emitters that this object is listening to.\n\t\t// This list has the following format:\n\t\t//\n\t\t// _listeningTo: {\n\t\t// emitterId: {\n\t\t// emitter: emitter,\n\t\t// callbacks: {\n\t\t// event1: [ callback1, callback2, ... ]\n\t\t// ....\n\t\t// }\n\t\t// },\n\t\t// ...\n\t\t// }\n\n\t\tif ( !this[ _listeningTo ] ) {\n\t\t\tthis[ _listeningTo ] = {};\n\t\t}\n\n\t\tconst emitters = this[ _listeningTo ];\n\n\t\tif ( !_getEmitterId( emitter ) ) {\n\t\t\t_setEmitterId( emitter );\n\t\t}\n\n\t\tconst emitterId = _getEmitterId( emitter );\n\n\t\tif ( !( emitterInfo = emitters[ emitterId ] ) ) {\n\t\t\temitterInfo = emitters[ emitterId ] = {\n\t\t\t\temitter,\n\t\t\t\tcallbacks: {}\n\t\t\t};\n\t\t}\n\n\t\tif ( !( eventCallbacks = emitterInfo.callbacks[ event ] ) ) {\n\t\t\teventCallbacks = emitterInfo.callbacks[ event ] = [];\n\t\t}\n\n\t\teventCallbacks.push( callback );\n\n\t\t// Finally register the callback to the event.\n\t\tcreateEventNamespace( emitter, event );\n\t\tconst lists = getCallbacksListsForNamespace( emitter, event );\n\t\tconst priority = priorities.get( options.priority );\n\n\t\tconst callbackDefinition = {\n\t\t\tcallback,\n\t\t\tpriority\n\t\t};\n\n\t\t// Add the callback to all callbacks list.\n\t\tfor ( const callbacks of lists ) {\n\t\t\t// Add the callback to the list in the right priority position.\n\t\t\tlet added = false;\n\n\t\t\tfor ( let i = 0; i < callbacks.length; i++ ) {\n\t\t\t\tif ( callbacks[ i ].priority < priority ) {\n\t\t\t\t\tcallbacks.splice( i, 0, callbackDefinition );\n\t\t\t\t\tadded = true;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add at the end, if right place was not found.\n\t\t\tif ( !added ) {\n\t\t\t\tcallbacks.push( callbackDefinition );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstopListening( emitter, event, callback ) {\n\t\tconst emitters = this[ _listeningTo ];\n\t\tlet emitterId = emitter && _getEmitterId( emitter );\n\t\tconst emitterInfo = emitters && emitterId && emitters[ emitterId ];\n\t\tconst eventCallbacks = emitterInfo && event && emitterInfo.callbacks[ event ];\n\n\t\t// Stop if nothing has been listened.\n\t\tif ( !emitters || ( emitter && !emitterInfo ) || ( event && !eventCallbacks ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// All params provided. off() that single callback.\n\t\tif ( callback ) {\n\t\t\tremoveCallback( emitter, event, callback );\n\t\t}\n\t\t// Only `emitter` and `event` provided. off() all callbacks for that event.\n\t\telse if ( eventCallbacks ) {\n\t\t\twhile ( ( callback = eventCallbacks.pop() ) ) {\n\t\t\t\tremoveCallback( emitter, event, callback );\n\t\t\t}\n\n\t\t\tdelete emitterInfo.callbacks[ event ];\n\t\t}\n\t\t// Only `emitter` provided. off() all events for that emitter.\n\t\telse if ( emitterInfo ) {\n\t\t\tfor ( event in emitterInfo.callbacks ) {\n\t\t\t\tthis.stopListening( emitter, event );\n\t\t\t}\n\t\t\tdelete emitters[ emitterId ];\n\t\t}\n\t\t// No params provided. off() all emitters.\n\t\telse {\n\t\t\tfor ( emitterId in emitters ) {\n\t\t\t\tthis.stopListening( emitters[ emitterId ].emitter );\n\t\t\t}\n\t\t\tdelete this[ _listeningTo ];\n\t\t}\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tfire( eventOrInfo, ...args ) {\n\t\ttry {\n\t\t\tconst eventInfo = eventOrInfo instanceof EventInfo ? eventOrInfo : new EventInfo( this, eventOrInfo );\n\t\t\tconst event = eventInfo.name;\n\t\t\tlet callbacks = getCallbacksForEvent( this, event );\n\n\t\t\t// Record that the event passed this emitter on its path.\n\t\t\teventInfo.path.push( this );\n\n\t\t\t// Handle event listener callbacks first.\n\t\t\tif ( callbacks ) {\n\t\t\t\t// Arguments passed to each callback.\n\t\t\t\tconst callbackArgs = [ eventInfo, ...args ];\n\n\t\t\t\t// Copying callbacks array is the easiest and most secure way of preventing infinite loops, when event callbacks\n\t\t\t\t// are added while processing other callbacks. Previous solution involved adding counters (unique ids) but\n\t\t\t\t// failed if callbacks were added to the queue before currently processed callback.\n\t\t\t\t// If this proves to be too inefficient, another method is to change `.on()` so callbacks are stored if same\n\t\t\t\t// event is currently processed. Then, `.fire()` at the end, would have to add all stored events.\n\t\t\t\tcallbacks = Array.from( callbacks );\n\n\t\t\t\tfor ( let i = 0; i < callbacks.length; i++ ) {\n\t\t\t\t\tcallbacks[ i ].callback.apply( this, callbackArgs );\n\n\t\t\t\t\t// Remove the callback from future requests if off() has been called.\n\t\t\t\t\tif ( eventInfo.off.called ) {\n\t\t\t\t\t\t// Remove the called mark for the next calls.\n\t\t\t\t\t\tdelete eventInfo.off.called;\n\n\t\t\t\t\t\tremoveCallback( this, event, callbacks[ i ].callback );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Do not execute next callbacks if stop() was called.\n\t\t\t\t\tif ( eventInfo.stop.called ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Delegate event to other emitters if needed.\n\t\t\tif ( this._delegations ) {\n\t\t\t\tconst destinations = this._delegations.get( event );\n\t\t\t\tconst passAllDestinations = this._delegations.get( '*' );\n\n\t\t\t\tif ( destinations ) {\n\t\t\t\t\tfireDelegatedEvents( destinations, eventInfo, args );\n\t\t\t\t}\n\n\t\t\t\tif ( passAllDestinations ) {\n\t\t\t\t\tfireDelegatedEvents( passAllDestinations, eventInfo, args );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn eventInfo.return;\n\t\t} catch ( err ) {\n\t\t\tCKEditorError.rethrowUnexpectedError( err, this );\n\t\t}\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdelegate( ...events ) {\n\t\treturn {\n\t\t\tto: ( emitter, nameOrFunction ) => {\n\t\t\t\tif ( !this._delegations ) {\n\t\t\t\t\tthis._delegations = new Map();\n\t\t\t\t}\n\n\t\t\t\t// Originally there was a for..of loop which unfortunately caused an error in Babel that didn't allow\n\t\t\t\t// build an application. See: https://github.com/ckeditor/ckeditor5-react/issues/40.\n\t\t\t\tevents.forEach( eventName => {\n\t\t\t\t\tconst destinations = this._delegations.get( eventName );\n\n\t\t\t\t\tif ( !destinations ) {\n\t\t\t\t\t\tthis._delegations.set( eventName, new Map( [ [ emitter, nameOrFunction ] ] ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdestinations.set( emitter, nameOrFunction );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t};\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstopDelegating( event, emitter ) {\n\t\tif ( !this._delegations ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !event ) {\n\t\t\tthis._delegations.clear();\n\t\t} else if ( !emitter ) {\n\t\t\tthis._delegations.delete( event );\n\t\t} else {\n\t\t\tconst destinations = this._delegations.get( event );\n\n\t\t\tif ( destinations ) {\n\t\t\t\tdestinations.delete( emitter );\n\t\t\t}\n\t\t}\n\t}\n};\n\nexport default EmitterMixin;\n\n/**\n * Emitter/listener interface.\n *\n * Can be easily implemented by a class by mixing the {@link module:utils/emittermixin~EmitterMixin} mixin.\n *\n * @interface Emitter\n */\n\n/**\n * Registers a callback function to be executed when an event is fired.\n *\n * Shorthand for {@link #listenTo `this.listenTo( this, event, callback, options )`} (it makes the emitter\n * listen on itself).\n *\n * @method #on\n * @param {String} event The name of the event.\n * @param {Function} callback The function to be called on event.\n * @param {Object} [options={}] Additional options.\n * @param {module:utils/priorities~PriorityString|Number} [options.priority='normal'] The priority of this event callback. The higher\n * the priority value the sooner the callback will be fired. Events having the same priority are called in the\n * order they were added.\n */\n\n/**\n * Registers a callback function to be executed on the next time the event is fired only. This is similar to\n * calling {@link #on} followed by {@link #off} in the callback.\n *\n * @method #once\n * @param {String} event The name of the event.\n * @param {Function} callback The function to be called on event.\n * @param {Object} [options={}] Additional options.\n * @param {module:utils/priorities~PriorityString|Number} [options.priority='normal'] The priority of this event callback. The higher\n * the priority value the sooner the callback will be fired. Events having the same priority are called in the\n * order they were added.\n */\n\n/**\n * Stops executing the callback on the given event.\n * Shorthand for {@link #stopListening `this.stopListening( this, event, callback )`}.\n *\n * @method #off\n * @param {String} event The name of the event.\n * @param {Function} callback The function to stop being called.\n */\n\n/**\n * Registers a callback function to be executed when an event is fired in a specific (emitter) object.\n *\n * Events can be grouped in namespaces using `:`.\n * When namespaced event is fired, it additionally fires all callbacks for that namespace.\n *\n *\t\t// myEmitter.on( ... ) is a shorthand for myEmitter.listenTo( myEmitter, ... ).\n *\t\tmyEmitter.on( 'myGroup', genericCallback );\n *\t\tmyEmitter.on( 'myGroup:myEvent', specificCallback );\n *\n *\t\t// genericCallback is fired.\n *\t\tmyEmitter.fire( 'myGroup' );\n *\t\t// both genericCallback and specificCallback are fired.\n *\t\tmyEmitter.fire( 'myGroup:myEvent' );\n *\t\t// genericCallback is fired even though there are no callbacks for \"foo\".\n *\t\tmyEmitter.fire( 'myGroup:foo' );\n *\n * An event callback can {@link module:utils/eventinfo~EventInfo#stop stop the event} and\n * set the {@link module:utils/eventinfo~EventInfo#return return value} of the {@link #fire} method.\n *\n * @method #listenTo\n * @param {module:utils/emittermixin~Emitter} emitter The object that fires the event.\n * @param {String} event The name of the event.\n * @param {Function} callback The function to be called on event.\n * @param {Object} [options={}] Additional options.\n * @param {module:utils/priorities~PriorityString|Number} [options.priority='normal'] The priority of this event callback. The higher\n * the priority value the sooner the callback will be fired. Events having the same priority are called in the\n * order they were added.\n */\n\n/**\n * Stops listening for events. It can be used at different levels:\n *\n * * To stop listening to a specific callback.\n * * To stop listening to a specific event.\n * * To stop listening to all events fired by a specific object.\n * * To stop listening to all events fired by all objects.\n *\n * @method #stopListening\n * @param {module:utils/emittermixin~Emitter} [emitter] The object to stop listening to. If omitted, stops it for all objects.\n * @param {String} [event] (Requires the `emitter`) The name of the event to stop listening to. If omitted, stops it\n * for all events from `emitter`.\n * @param {Function} [callback] (Requires the `event`) The function to be removed from the call list for the given\n * `event`.\n */\n\n/**\n * Fires an event, executing all callbacks registered for it.\n *\n * The first parameter passed to callbacks is an {@link module:utils/eventinfo~EventInfo} object,\n * followed by the optional `args` provided in the `fire()` method call.\n *\n * @method #fire\n * @param {String|module:utils/eventinfo~EventInfo} eventOrInfo The name of the event or `EventInfo` object if event is delegated.\n * @param {...*} [args] Additional arguments to be passed to the callbacks.\n * @returns {*} By default the method returns `undefined`. However, the return value can be changed by listeners\n * through modification of the {@link module:utils/eventinfo~EventInfo#return `evt.return`}'s property (the event info\n * is the first param of every callback).\n */\n\n/**\n * Delegates selected events to another {@link module:utils/emittermixin~Emitter}. For instance:\n *\n *\t\temitterA.delegate( 'eventX' ).to( emitterB );\n *\t\temitterA.delegate( 'eventX', 'eventY' ).to( emitterC );\n *\n * then `eventX` is delegated (fired by) `emitterB` and `emitterC` along with `data`:\n *\n *\t\temitterA.fire( 'eventX', data );\n *\n * and `eventY` is delegated (fired by) `emitterC` along with `data`:\n *\n *\t\temitterA.fire( 'eventY', data );\n *\n * @method #delegate\n * @param {...String} events Event names that will be delegated to another emitter.\n * @returns {module:utils/emittermixin~EmitterMixinDelegateChain}\n */\n\n/**\n * Stops delegating events. It can be used at different levels:\n *\n * * To stop delegating all events.\n * * To stop delegating a specific event to all emitters.\n * * To stop delegating a specific event to a specific emitter.\n *\n * @method #stopDelegating\n * @param {String} [event] The name of the event to stop delegating. If omitted, stops it all delegations.\n * @param {module:utils/emittermixin~Emitter} [emitter] (requires `event`) The object to stop delegating a particular event to.\n * If omitted, stops delegation of `event` to all emitters.\n */\n\n/**\n * Checks if `listeningEmitter` listens to an emitter with given `listenedToEmitterId` and if so, returns that emitter.\n * If not, returns `null`.\n *\n * @protected\n * @param {module:utils/emittermixin~Emitter} listeningEmitter An emitter that listens.\n * @param {String} listenedToEmitterId Unique emitter id of emitter listened to.\n * @returns {module:utils/emittermixin~Emitter|null}\n */\nexport function _getEmitterListenedTo( listeningEmitter, listenedToEmitterId ) {\n\tif ( listeningEmitter[ _listeningTo ] && listeningEmitter[ _listeningTo ][ listenedToEmitterId ] ) {\n\t\treturn listeningEmitter[ _listeningTo ][ listenedToEmitterId ].emitter;\n\t}\n\n\treturn null;\n}\n\n/**\n * Sets emitter's unique id.\n *\n * **Note:** `_emitterId` can be set only once.\n *\n * @protected\n * @param {module:utils/emittermixin~Emitter} emitter An emitter for which id will be set.\n * @param {String} [id] Unique id to set. If not passed, random unique id will be set.\n */\nexport function _setEmitterId( emitter, id ) {\n\tif ( !emitter[ _emitterId ] ) {\n\t\temitter[ _emitterId ] = id || uid();\n\t}\n}\n\n/**\n * Returns emitter's unique id.\n *\n * @protected\n * @param {module:utils/emittermixin~Emitter} emitter An emitter which id will be returned.\n */\nexport function _getEmitterId( emitter ) {\n\treturn emitter[ _emitterId ];\n}\n\n// Gets the internal `_events` property of the given object.\n// `_events` property store all lists with callbacks for registered event names.\n// If there were no events registered on the object, empty `_events` object is created.\nfunction getEvents( source ) {\n\tif ( !source._events ) {\n\t\tObject.defineProperty( source, '_events', {\n\t\t\tvalue: {}\n\t\t} );\n\t}\n\n\treturn source._events;\n}\n\n// Creates event node for generic-specific events relation architecture.\nfunction makeEventNode() {\n\treturn {\n\t\tcallbacks: [],\n\t\tchildEvents: []\n\t};\n}\n\n// Creates an architecture for generic-specific events relation.\n// If needed, creates all events for given eventName, i.e. if the first registered event\n// is foo:bar:abc, it will create foo:bar:abc, foo:bar and foo event and tie them together.\n// It also copies callbacks from more generic events to more specific events when\n// specific events are created.\nfunction createEventNamespace( source, eventName ) {\n\tconst events = getEvents( source );\n\n\t// First, check if the event we want to add to the structure already exists.\n\tif ( events[ eventName ] ) {\n\t\t// If it exists, we don't have to do anything.\n\t\treturn;\n\t}\n\n\t// In other case, we have to create the structure for the event.\n\t// Note, that we might need to create intermediate events too.\n\t// I.e. if foo:bar:abc is being registered and we only have foo in the structure,\n\t// we need to also register foo:bar.\n\n\t// Currently processed event name.\n\tlet name = eventName;\n\t// Name of the event that is a child event for currently processed event.\n\tlet childEventName = null;\n\n\t// Array containing all newly created specific events.\n\tconst newEventNodes = [];\n\n\t// While loop can't check for ':' index because we have to handle generic events too.\n\t// In each loop, we truncate event name, going from the most specific name to the generic one.\n\t// I.e. foo:bar:abc -> foo:bar -> foo.\n\twhile ( name !== '' ) {\n\t\tif ( events[ name ] ) {\n\t\t\t// If the currently processed event name is already registered, we can be sure\n\t\t\t// that it already has all the structure created, so we can break the loop here\n\t\t\t// as no more events need to be registered.\n\t\t\tbreak;\n\t\t}\n\n\t\t// If this event is not yet registered, create a new object for it.\n\t\tevents[ name ] = makeEventNode();\n\t\t// Add it to the array with newly created events.\n\t\tnewEventNodes.push( events[ name ] );\n\n\t\t// Add previously processed event name as a child of this event.\n\t\tif ( childEventName ) {\n\t\t\tevents[ name ].childEvents.push( childEventName );\n\t\t}\n\n\t\tchildEventName = name;\n\t\t// If `.lastIndexOf()` returns -1, `.substr()` will return '' which will break the loop.\n\t\tname = name.substr( 0, name.lastIndexOf( ':' ) );\n\t}\n\n\tif ( name !== '' ) {\n\t\t// If name is not empty, we found an already registered event that was a parent of the\n\t\t// event we wanted to register.\n\n\t\t// Copy that event's callbacks to newly registered events.\n\t\tfor ( const node of newEventNodes ) {\n\t\t\tnode.callbacks = events[ name ].callbacks.slice();\n\t\t}\n\n\t\t// Add last newly created event to the already registered event.\n\t\tevents[ name ].childEvents.push( childEventName );\n\t}\n}\n\n// Gets an array containing callbacks list for a given event and it's more specific events.\n// I.e. if given event is foo:bar and there is also foo:bar:abc event registered, this will\n// return callback list of foo:bar and foo:bar:abc (but not foo).\nfunction getCallbacksListsForNamespace( source, eventName ) {\n\tconst eventNode = getEvents( source )[ eventName ];\n\n\tif ( !eventNode ) {\n\t\treturn [];\n\t}\n\n\tlet callbacksLists = [ eventNode.callbacks ];\n\n\tfor ( let i = 0; i < eventNode.childEvents.length; i++ ) {\n\t\tconst childCallbacksLists = getCallbacksListsForNamespace( source, eventNode.childEvents[ i ] );\n\n\t\tcallbacksLists = callbacksLists.concat( childCallbacksLists );\n\t}\n\n\treturn callbacksLists;\n}\n\n// Get the list of callbacks for a given event, but only if there any callbacks have been registered.\n// If there are no callbacks registered for given event, it checks if this is a specific event and looks\n// for callbacks for it's more generic version.\nfunction getCallbacksForEvent( source, eventName ) {\n\tlet event;\n\n\tif ( !source._events || !( event = source._events[ eventName ] ) || !event.callbacks.length ) {\n\t\t// There are no callbacks registered for specified eventName.\n\t\t// But this could be a specific-type event that is in a namespace.\n\t\tif ( eventName.indexOf( ':' ) > -1 ) {\n\t\t\t// If the eventName is specific, try to find callback lists for more generic event.\n\t\t\treturn getCallbacksForEvent( source, eventName.substr( 0, eventName.lastIndexOf( ':' ) ) );\n\t\t} else {\n\t\t\t// If this is a top-level generic event, return null;\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn event.callbacks;\n}\n\n// Fires delegated events for given map of destinations.\n//\n// @private\n// * @param {Map.<utils.Emitter>} destinations A map containing\n// `[ {@link module:utils/emittermixin~Emitter}, \"event name\" ]` pair destinations.\n// * @param {utils.EventInfo} eventInfo The original event info object.\n// * @param {Array.<*>} fireArgs Arguments the original event was fired with.\nfunction fireDelegatedEvents( destinations, eventInfo, fireArgs ) {\n\tfor ( let [ emitter, name ] of destinations ) {\n\t\tif ( !name ) {\n\t\t\tname = eventInfo.name;\n\t\t} else if ( typeof name == 'function' ) {\n\t\t\tname = name( eventInfo.name );\n\t\t}\n\n\t\tconst delegatedInfo = new EventInfo( eventInfo.source, name );\n\n\t\tdelegatedInfo.path = [ ...eventInfo.path ];\n\n\t\temitter.fire( delegatedInfo, ...fireArgs );\n\t}\n}\n\n// Removes callback from emitter for given event.\n//\n// @param {module:utils/emittermixin~Emitter} emitter\n// @param {String} event\n// @param {Function} callback\nfunction removeCallback( emitter, event, callback ) {\n\tconst lists = getCallbacksListsForNamespace( emitter, event );\n\n\tfor ( const callbacks of lists ) {\n\t\tfor ( let i = 0; i < callbacks.length; i++ ) {\n\t\t\tif ( callbacks[ i ].callback == callback ) {\n\t\t\t\t// Remove the callback from the list (fixing the next index).\n\t\t\t\tcallbacks.splice( i, 1 );\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * The return value of {@link ~EmitterMixin#delegate}.\n *\n * @interface module:utils/emittermixin~EmitterMixinDelegateChain\n */\n\n/**\n * Selects destination for {@link module:utils/emittermixin~EmitterMixin#delegate} events.\n *\n * @method #to\n * @param {module:utils/emittermixin~Emitter} emitter An `EmitterMixin` instance which is the destination for delegated events.\n * @param {String|Function} [nameOrFunction] A custom event name or function which converts the original name string.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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/mix\n */\n\n/**\n * Copies enumerable properties and symbols from the objects given as 2nd+ parameters to the\n * prototype of first object (a constructor).\n *\n *\t\tclass Editor {\n *\t\t\t...\n *\t\t}\n *\n *\t\tconst SomeMixin = {\n *\t\t\ta() {\n *\t\t\t\treturn 'a';\n *\t\t\t}\n *\t\t};\n *\n *\t\tmix( Editor, SomeMixin, ... );\n *\n *\t\tnew Editor().a(); // -> 'a'\n *\n * Note: Properties which already exist in the base class will not be overriden.\n *\n * @param {Function} [baseClass] Class which prototype will be extended.\n * @param {Object} [...mixins] Objects from which to get properties.\n */\nexport default function mix( baseClass, ...mixins ) {\n\tmixins.forEach( mixin => {\n\t\tObject.getOwnPropertyNames( mixin ).concat( Object.getOwnPropertySymbols( mixin ) )\n\t\t\t.forEach( key => {\n\t\t\t\tif ( key in baseClass.prototype ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst sourceDescriptor = Object.getOwnPropertyDescriptor( mixin, key );\n\t\t\t\tsourceDescriptor.enumerable = false;\n\n\t\t\t\tObject.defineProperty( baseClass.prototype, key, sourceDescriptor );\n\t\t\t} );\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/comparearrays\n */\n\n/**\n * Compares how given arrays relate to each other. One array can be: same as another array, prefix of another array\n * or completely different. If arrays are different, first index at which they differ is returned. Otherwise,\n * a flag specifying the relation is returned. Flags are negative numbers, so whenever a number >= 0 is returned\n * it means that arrays differ.\n *\n *\t\tcompareArrays( [ 0, 2 ], [ 0, 2 ] );\t\t// 'same'\n *\t\tcompareArrays( [ 0, 2 ], [ 0, 2, 1 ] );\t\t// 'prefix'\n *\t\tcompareArrays( [ 0, 2 ], [ 0 ] );\t\t\t// 'extension'\n *\t\tcompareArrays( [ 0, 2 ], [ 1, 2 ] );\t\t// 0\n *\t\tcompareArrays( [ 0, 2 ], [ 0, 1 ] );\t\t// 1\n *\n * @param {Array} a Array that is compared.\n * @param {Array} b Array to compare with.\n * @returns {module:utils/comparearrays~ArrayRelation} How array `a` is related to `b`.\n */\nexport default function compareArrays( a, b ) {\n\tconst minLen = Math.min( a.length, b.length );\n\n\tfor ( let i = 0; i < minLen; i++ ) {\n\t\tif ( a[ i ] != b[ i ] ) {\n\t\t\t// The arrays are different.\n\t\t\treturn i;\n\t\t}\n\t}\n\n\t// Both arrays were same at all points.\n\tif ( a.length == b.length ) {\n\t\t// If their length is also same, they are the same.\n\t\treturn 'same';\n\t} else if ( a.length < b.length ) {\n\t\t// Compared array is shorter so it is a prefix of the other array.\n\t\treturn 'prefix';\n\t} else {\n\t\t// Compared array is longer so it is an extension of the other array.\n\t\treturn 'extension';\n\t}\n}\n\n/**\n * @typedef {'extension'|'same'|'prefix'} module:utils/comparearrays~ArrayRelation\n */\n","import baseClone from './_baseClone.js';\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_SYMBOLS_FLAG = 4;\n\n/**\n * Creates a shallow clone of `value`.\n *\n * **Note:** This method is loosely based on the\n * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)\n * and supports cloning arrays, array buffers, booleans, date objects, maps,\n * numbers, `Object` objects, regexes, sets, strings, symbols, and typed\n * arrays. The own enumerable properties of `arguments` objects are cloned\n * as plain objects. An empty object is returned for uncloneable values such\n * as error objects, functions, DOM nodes, and WeakMaps.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to clone.\n * @returns {*} Returns the cloned value.\n * @see _.cloneDeep\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var shallow = _.clone(objects);\n * console.log(shallow[0] === objects[0]);\n * // => true\n */\nfunction clone(value) {\n return baseClone(value, CLONE_SYMBOLS_FLAG);\n}\n\nexport default clone;\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/node\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';\nimport { clone } from 'lodash-es';\n\n// To check if component is loaded more than once.\nimport '@ckeditor/ckeditor5-utils/src/version';\n\n/**\n * Abstract tree view node class.\n *\n * This is an abstract class. Its constructor should not be used directly.\n * Use the {@link module:engine/view/element~Element} class to create view elements\n * or {@link module:engine/view/text~Text} class to create view text nodes.\n *\n * @abstract\n */\nexport default class Node {\n\t/**\n\t * Creates a tree view node.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Parent element. Null by default. Set by {@link module:engine/view/element~Element#_insertChild}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment|null}\n\t\t */\n\t\tthis.parent = null;\n\t}\n\n\t/**\n\t * Index of the node in the parent element or null if the node has no parent.\n\t *\n\t * Accessing this property throws an error if this node's parent element does not contain it.\n\t * This means that view tree got broken.\n\t *\n\t * @readonly\n\t * @type {Number|null}\n\t */\n\tget index() {\n\t\tlet pos;\n\n\t\tif ( !this.parent ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// No parent or child doesn't exist in parent's children.\n\t\tif ( ( pos = this.parent.getChildIndex( this ) ) == -1 ) {\n\t\t\t/**\n\t\t\t * The node's parent does not contain this node. It means that the document tree is corrupted.\n\t\t\t *\n\t\t\t * @error view-node-not-found-in-parent\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-node-not-found-in-parent: The node\\'s parent does not contain this node.', this );\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t/**\n\t * Node's next sibling, or `null` if it is the last child.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/node~Node|null}\n\t */\n\tget nextSibling() {\n\t\tconst index = this.index;\n\n\t\treturn ( index !== null && this.parent.getChild( index + 1 ) ) || null;\n\t}\n\n\t/**\n\t * Node's previous sibling, or `null` if it is the first child.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/node~Node|null}\n\t */\n\tget previousSibling() {\n\t\tconst index = this.index;\n\n\t\treturn ( index !== null && this.parent.getChild( index - 1 ) ) || null;\n\t}\n\n\t/**\n\t * Top-most ancestor of the node. If the node has no parent it is the root itself.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\tlet root = this; // eslint-disable-line consistent-this\n\n\t\twhile ( root.parent ) {\n\t\t\troot = root.parent;\n\t\t}\n\n\t\treturn root;\n\t}\n\n\t/**\n\t * {@link module:engine/view/document~Document View document} that owns this node, or `null` if the node is inside\n\t * {@link module:engine/view/documentfragment~DocumentFragment document fragment}.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/document~Document|null}\n\t */\n\tget document() {\n\t\t// Parent might be Node, null or DocumentFragment.\n\t\tif ( this.parent instanceof Node ) {\n\t\t\treturn this.parent.document;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Gets a path to the node. The path is an array containing indices of consecutive ancestors of this node,\n\t * beginning from {@link module:engine/view/node~Node#root root}, down to this node's index.\n\t *\n\t *\t\tconst abc = downcastWriter.createText( 'abc' );\n\t *\t\tconst foo = downcastWriter.createText( 'foo' );\n\t *\t\tconst h1 = downcastWriter.createElement( 'h1', null, downcastWriter.createText( 'header' ) );\n\t *\t\tconst p = downcastWriter.createElement( 'p', null, [ abc, foo ] );\n\t *\t\tconst div = downcastWriter.createElement( 'div', null, [ h1, p ] );\n\t *\t\tfoo.getPath(); // Returns [ 1, 3 ]. `foo` is in `p` which is in `div`. `p` starts at offset 1, while `foo` at 3.\n\t *\t\th1.getPath(); // Returns [ 0 ].\n\t *\t\tdiv.getPath(); // Returns [].\n\t *\n\t * @returns {Array.<Number>} The path.\n\t */\n\tgetPath() {\n\t\tconst path = [];\n\t\tlet node = this; // eslint-disable-line consistent-this\n\n\t\twhile ( node.parent ) {\n\t\t\tpath.unshift( node.index );\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\treturn path;\n\t}\n\n\t/**\n\t * Returns ancestors array of this node.\n\t *\n\t * @param {Object} options Options object.\n\t * @param {Boolean} [options.includeSelf=false] When set to `true` this node will be also included in parent's array.\n\t * @param {Boolean} [options.parentFirst=false] When set to `true`, array will be sorted from node's parent to root element,\n\t * otherwise root element will be the first item in the array.\n\t * @returns {Array} Array with ancestors.\n\t */\n\tgetAncestors( options = { includeSelf: false, parentFirst: false } ) {\n\t\tconst ancestors = [];\n\t\tlet parent = options.includeSelf ? this : this.parent;\n\n\t\twhile ( parent ) {\n\t\t\tancestors[ options.parentFirst ? 'push' : 'unshift' ]( parent );\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn ancestors;\n\t}\n\n\t/**\n\t * Returns a {@link module:engine/view/element~Element} or {@link module:engine/view/documentfragment~DocumentFragment}\n\t * which is a common ancestor of both nodes.\n\t *\n\t * @param {module:engine/view/node~Node} node The second node.\n\t * @param {Object} options Options object.\n\t * @param {Boolean} [options.includeSelf=false] When set to `true` both nodes will be considered \"ancestors\" too.\n\t * Which means that if e.g. node A is inside B, then their common ancestor will be B.\n\t * @returns {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment|null}\n\t */\n\tgetCommonAncestor( node, options = {} ) {\n\t\tconst ancestorsA = this.getAncestors( options );\n\t\tconst ancestorsB = node.getAncestors( options );\n\n\t\tlet i = 0;\n\n\t\twhile ( ancestorsA[ i ] == ancestorsB[ i ] && ancestorsA[ i ] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i === 0 ? null : ancestorsA[ i - 1 ];\n\t}\n\n\t/**\n\t * Returns whether this node is before given node. `false` is returned if nodes are in different trees (for example,\n\t * in different {@link module:engine/view/documentfragment~DocumentFragment}s).\n\t *\n\t * @param {module:engine/view/node~Node} node Node to compare with.\n\t * @returns {Boolean}\n\t */\n\tisBefore( node ) {\n\t\t// Given node is not before this node if they are same.\n\t\tif ( this == node ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Return `false` if it is impossible to compare nodes.\n\t\tif ( this.root !== node.root ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst thisPath = this.getPath();\n\t\tconst nodePath = node.getPath();\n\n\t\tconst result = compareArrays( thisPath, nodePath );\n\n\t\tswitch ( result ) {\n\t\t\tcase 'prefix':\n\t\t\t\treturn true;\n\n\t\t\tcase 'extension':\n\t\t\t\treturn false;\n\n\t\t\tdefault:\n\t\t\t\treturn thisPath[ result ] < nodePath[ result ];\n\t\t}\n\t}\n\n\t/**\n\t * Returns whether this node is after given node. `false` is returned if nodes are in different trees (for example,\n\t * in different {@link module:engine/view/documentfragment~DocumentFragment}s).\n\t *\n\t * @param {module:engine/view/node~Node} node Node to compare with.\n\t * @returns {Boolean}\n\t */\n\tisAfter( node ) {\n\t\t// Given node is not before this node if they are same.\n\t\tif ( this == node ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Return `false` if it is impossible to compare nodes.\n\t\tif ( this.root !== node.root ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// In other cases, just check if the `node` is before, and return the opposite.\n\t\treturn !this.isBefore( node );\n\t}\n\n\t/**\n\t * Removes node from parent.\n\t *\n\t * @protected\n\t */\n\t_remove() {\n\t\tthis.parent._removeChildren( this.index );\n\t}\n\n\t/**\n\t * @protected\n\t * @param {module:engine/view/document~ChangeType} type Type of the change.\n\t * @param {module:engine/view/node~Node} node Changed node.\n\t * @fires change\n\t */\n\t_fireChange( type, node ) {\n\t\tthis.fire( 'change:' + type, node );\n\n\t\tif ( this.parent ) {\n\t\t\tthis.parent._fireChange( type, node );\n\t\t}\n\t}\n\n\t/**\n\t * Custom toJSON method to solve child-parent circular dependencies.\n\t *\n\t * @returns {Object} Clone of this object with the parent property removed.\n\t */\n\ttoJSON() {\n\t\tconst json = clone( this );\n\n\t\t// Due to circular references we need to remove parent reference.\n\t\tdelete json.parent;\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t * This method is useful when processing view objects that are of unknown type. For example, a function\n\t * may return a {@link module:engine/view/documentfragment~DocumentFragment} or a {@link module:engine/view/node~Node}\n\t * that can be either a text node or an element. This method can be used to check what kind of object is returned.\n\t *\n\t *\t\tsomeObject.is( 'element' ); // -> true if this is an element\n\t *\t\tsomeObject.is( 'node' ); // -> true if this is a node (a text node or an element)\n\t *\t\tsomeObject.is( 'documentFragment' ); // -> true if this is a document fragment\n\t *\n\t * Since this method is also available on a range of model objects, you can prefix the type of the object with\n\t * `model:` or `view:` to check, for example, if this is the model's or view's element:\n\t *\n\t *\t\tviewElement.is( 'view:element' ); // -> true\n\t *\t\tviewElement.is( 'model:element' ); // -> false\n\t *\n\t * By using this method it is also possible to check a name of an element:\n\t *\n\t *\t\timgElement.is( 'img' ); // -> true\n\t *\t\timgElement.is( 'element', 'img' ); // -> same as above\n\t *\t\timgElement.is( 'view:element', 'img' ); // -> same as above, but more precise\n\t *\n\t * The list of view objects which implement the `is()` method:\n\t *\n\t * * {@link module:engine/view/attributeelement~AttributeElement#is `AttributeElement#is()`}\n\t * * {@link module:engine/view/containerelement~ContainerElement#is `ContainerElement#is()`}\n\t * * {@link module:engine/view/documentfragment~DocumentFragment#is `DocumentFragment#is()`}\n\t * * {@link module:engine/view/documentselection~DocumentSelection#is `DocumentSelection#is()`}\n\t * * {@link module:engine/view/editableelement~EditableElement#is `EditableElement#is()`}\n\t * * {@link module:engine/view/element~Element#is `Element#is()`}\n\t * * {@link module:engine/view/emptyelement~EmptyElement#is `EmptyElement#is()`}\n\t * * {@link module:engine/view/node~Node#is `Node#is()`}\n\t * * {@link module:engine/view/position~Position#is `Position#is()`}\n\t * * {@link module:engine/view/range~Range#is `Range#is()`}\n\t * * {@link module:engine/view/rooteditableelement~RootEditableElement#is `RootEditableElement#is()`}\n\t * * {@link module:engine/view/selection~Selection#is `Selection#is()`}\n\t * * {@link module:engine/view/text~Text#is `Text#is()`}\n\t * * {@link module:engine/view/textproxy~TextProxy#is `TextProxy#is()`}\n\t * * {@link module:engine/view/uielement~UIElement#is `UIElement#is()`}\n\t *\n\t * @method #is\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'node' || type == 'view:node';\n\t}\n\n\t/**\n\t * Clones this node.\n\t *\n\t * @protected\n\t * @method #_clone\n\t * @returns {module:engine/view/node~Node} Clone of this node.\n\t */\n\n\t/**\n\t * Checks if provided node is similar to this node.\n\t *\n\t * @method #isSimilar\n\t * @returns {Boolean} True if nodes are similar.\n\t */\n}\n\n/**\n * Fired when list of {@link module:engine/view/element~Element elements} children changes.\n *\n * Change event is bubbled – it is fired on all ancestors.\n *\n * @event change:children\n * @param {module:engine/view/node~Node} changedNode\n */\n\n/**\n * Fired when list of {@link module:engine/view/element~Element elements} attributes changes.\n *\n * Change event is bubbled – it is fired on all ancestors.\n *\n * @event change:attributes\n * @param {module:engine/view/node~Node} changedNode\n */\n\n/**\n * Fired when {@link module:engine/view/text~Text text nodes} data changes.\n *\n * Change event is bubbled – it is fired on all ancestors.\n *\n * @event change:text\n * @param {module:engine/view/node~Node} changedNode\n */\n\n/**\n * @event change\n */\n\nmix( Node, EmitterMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/text\n */\n\nimport Node from './node';\n\n/**\n * Tree view text node.\n *\n * The constructor of this class shouldn't be used directly. To create new Text instances\n * use the {@link module:engine/view/downcastwriter~DowncastWriter#createText `DowncastWriter#createText()`}\n * method when working on data downcasted from the model or the\n * {@link module:engine/view/upcastwriter~UpcastWriter#createText `UpcastWriter#createText()`}\n * method when working on non-semantic views.\n *\n * @extends module:engine/view/node~Node\n */\nexport default class Text extends Node {\n\t/**\n\t * Creates a tree view text node.\n\t *\n\t * @protected\n\t * @param {String} data The text's data.\n\t */\n\tconstructor( data ) {\n\t\tsuper();\n\n\t\t/**\n\t\t * The text content.\n\t\t *\n\t\t * Setting the data fires the {@link module:engine/view/node~Node#event:change:text change event}.\n\t\t *\n\t\t * @protected\n\t\t * @member {String} module:engine/view/text~Text#_textData\n\t\t */\n\t\tthis._textData = data;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\ttext.is( 'text' ); // -> true\n\t *\t\ttext.is( 'node' ); // -> true\n\t *\t\ttext.is( 'view:text' ); // -> true\n\t *\t\ttext.is( 'view:node' ); // -> true\n\t *\n\t *\t\ttext.is( 'model:text' ); // -> false\n\t *\t\ttext.is( 'element' ); // -> false\n\t *\t\ttext.is( 'range' ); // -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'text' || type == 'view:text' || super.is( type );\n\t}\n\n\t/**\n\t * The text content.\n\t *\n\t * @readonly\n\t * @type {String}\n\t */\n\tget data() {\n\t\treturn this._textData;\n\t}\n\n\t/**\n\t * This getter is required when using the addition assignment operator on protected property:\n\t *\n\t *\t\tconst foo = downcastWriter.createText( 'foo' );\n\t *\t\tconst bar = downcastWriter.createText( 'bar' );\n\t *\n\t *\t\tfoo._data += bar.data; // executes: `foo._data = foo._data + bar.data`\n\t *\t\tconsole.log( foo.data ); // prints: 'foobar'\n\t *\n\t * If the protected getter didn't exist, `foo._data` will return `undefined` and result of the merge will be invalid.\n\t *\n\t * @protected\n\t * @type {String}\n\t */\n\tget _data() {\n\t\treturn this.data;\n\t}\n\n\t/**\n\t * Sets data and fires the {@link module:engine/view/node~Node#event:change:text change event}.\n\t *\n\t * @protected\n\t * @fires change:text\n\t * @param {String} data New data for the text node.\n\t */\n\tset _data( data ) {\n\t\tthis._fireChange( 'text', this );\n\n\t\tthis._textData = data;\n\t}\n\n\t/**\n\t * Checks if this text node is similar to other text node.\n\t * Both nodes should have the same data to be considered as similar.\n\t *\n\t * @param {module:engine/view/text~Text} otherNode Node to check if it is same as this node.\n\t * @returns {Boolean}\n\t */\n\tisSimilar( otherNode ) {\n\t\tif ( !( otherNode instanceof Text ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this === otherNode || this.data === otherNode.data;\n\t}\n\n\t/**\n\t * Clones this node.\n\t *\n\t * @protected\n\t * @returns {module:engine/view/text~Text} Text node that is a clone of this node.\n\t */\n\t_clone() {\n\t\treturn new Text( this.data );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/textproxy\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * TextProxy is a wrapper for substring of {@link module:engine/view/text~Text}. Instance of this class is created by\n * {@link module:engine/view/treewalker~TreeWalker} when only a part of {@link module:engine/view/text~Text} needs to be returned.\n *\n * `TextProxy` has an API similar to {@link module:engine/view/text~Text Text} and allows to do most of the common tasks performed\n * on view nodes.\n *\n * **Note:** Some `TextProxy` instances may represent whole text node, not just a part of it.\n * See {@link module:engine/view/textproxy~TextProxy#isPartial}.\n *\n * **Note:** `TextProxy` is a readonly interface.\n *\n * **Note:** `TextProxy` instances are created on the fly basing on the current state of parent {@link module:engine/view/text~Text}.\n * Because of this it is highly unrecommended to store references to `TextProxy instances because they might get\n * invalidated due to operations on Document. Also TextProxy is not a {@link module:engine/view/node~Node} so it can not be\n * inserted as a child of {@link module:engine/view/element~Element}.\n *\n * `TextProxy` instances are created by {@link module:engine/view/treewalker~TreeWalker view tree walker}. You should not need to create\n * an instance of this class by your own.\n */\nexport default class TextProxy {\n\t/**\n\t * Creates a text proxy.\n\t *\n\t * @protected\n\t * @param {module:engine/view/text~Text} textNode Text node which part is represented by this text proxy.\n\t * @param {Number} offsetInText Offset in {@link module:engine/view/textproxy~TextProxy#textNode text node}\n\t * from which the text proxy starts.\n\t * @param {Number} length Text proxy length, that is how many text node's characters, starting from `offsetInText` it represents.\n\t * @constructor\n\t */\n\tconstructor( textNode, offsetInText, length ) {\n\t\t/**\n\t\t * Reference to the {@link module:engine/view/text~Text} element which TextProxy is a substring.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/text~Text} module:engine/view/textproxy~TextProxy#textNode\n\t\t */\n\t\tthis.textNode = textNode;\n\n\t\tif ( offsetInText < 0 || offsetInText > textNode.data.length ) {\n\t\t\t/**\n\t\t\t * Given offsetInText value is incorrect.\n\t\t\t *\n\t\t\t * @error view-textproxy-wrong-offsetintext\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-textproxy-wrong-offsetintext: Given offsetInText value is incorrect.', this );\n\t\t}\n\n\t\tif ( length < 0 || offsetInText + length > textNode.data.length ) {\n\t\t\t/**\n\t\t\t * Given length value is incorrect.\n\t\t\t *\n\t\t\t * @error view-textproxy-wrong-length\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-textproxy-wrong-length: Given length value is incorrect.', this );\n\t\t}\n\n\t\t/**\n\t\t * Text data represented by this text proxy.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} module:engine/view/textproxy~TextProxy#data\n\t\t */\n\t\tthis.data = textNode.data.substring( offsetInText, offsetInText + length );\n\n\t\t/**\n\t\t * Offset in the `textNode` where this `TextProxy` instance starts.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} module:engine/view/textproxy~TextProxy#offsetInText\n\t\t */\n\t\tthis.offsetInText = offsetInText;\n\t}\n\n\t/**\n\t * Offset size of this node.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget offsetSize() {\n\t\treturn this.data.length;\n\t}\n\n\t/**\n\t * Flag indicating whether `TextProxy` instance covers only part of the original {@link module:engine/view/text~Text text node}\n\t * (`true`) or the whole text node (`false`).\n\t *\n\t * This is `false` when text proxy starts at the very beginning of {@link module:engine/view/textproxy~TextProxy#textNode textNode}\n\t * ({@link module:engine/view/textproxy~TextProxy#offsetInText offsetInText} equals `0`) and text proxy sizes is equal to\n\t * text node size.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isPartial() {\n\t\treturn this.data.length !== this.textNode.data.length;\n\t}\n\n\t/**\n\t * Parent of this text proxy, which is same as parent of text node represented by this text proxy.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment|null}\n\t */\n\tget parent() {\n\t\treturn this.textNode.parent;\n\t}\n\n\t/**\n\t * Root of this text proxy, which is same as root of text node represented by this text proxy.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this.textNode.root;\n\t}\n\n\t/**\n\t * {@link module:engine/view/document~Document View document} that owns this text proxy, or `null` if the text proxy is inside\n\t * {@link module:engine/view/documentfragment~DocumentFragment document fragment}.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/document~Document|null}\n\t */\n\tget document() {\n\t\treturn this.textNode.document;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\ttextProxy.is( 'textProxy' ); // -> true\n\t *\t\ttextProxy.is( 'view:textProxy' ); // -> true\n\t *\n\t *\t\ttextProxy.is( 'model:textProxy' ); // -> false\n\t *\t\ttextProxy.is( 'element' ); // -> false\n\t *\t\ttextProxy.is( 'range' ); // -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'textProxy' || type == 'view:textProxy';\n\t}\n\n\t/**\n\t * Returns ancestors array of this text proxy.\n\t *\n\t * @param {Object} options Options object.\n\t * @param {Boolean} [options.includeSelf=false] When set to `true` {#textNode} will be also included in parent's array.\n\t * @param {Boolean} [options.parentFirst=false] When set to `true`, array will be sorted from text proxy parent to\n\t * root element, otherwise root element will be the first item in the array.\n\t * @returns {Array} Array with ancestors.\n\t */\n\tgetAncestors( options = { includeSelf: false, parentFirst: false } ) {\n\t\tconst ancestors = [];\n\t\tlet parent = options.includeSelf ? this.textNode : this.parent;\n\n\t\twhile ( parent !== null ) {\n\t\t\tancestors[ options.parentFirst ? 'push' : 'unshift' ]( parent );\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn ancestors;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/objecttomap\n */\n\n/**\n * Transforms object to map.\n *\n *\t\tconst map = objectToMap( { 'foo': 1, 'bar': 2 } );\n *\t\tmap.get( 'foo' ); // 1\n *\n * @param {Object} obj Object to transform.\n * @returns {Map} Map created from object.\n */\nexport default function objectToMap( obj ) {\n\tconst map = new Map();\n\n\tfor ( const key in obj ) {\n\t\tmap.set( key, obj[ key ] );\n\t}\n\n\treturn map;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/matcher\n */\n\n/**\n * View matcher class.\n * Instance of this class can be used to find {@link module:engine/view/element~Element elements} that match given pattern.\n */\nexport default class Matcher {\n\t/**\n\t * Creates new instance of Matcher.\n\t *\n\t * @param {String|RegExp|Object} [pattern] Match patterns. See {@link module:engine/view/matcher~Matcher#add add method} for\n\t * more information.\n\t */\n\tconstructor( ...pattern ) {\n\t\t/**\n\t\t * @private\n\t\t * @type {Array<String|RegExp|Object>}\n\t\t */\n\t\tthis._patterns = [];\n\n\t\tthis.add( ...pattern );\n\t}\n\n\t/**\n\t * Adds pattern or patterns to matcher instance.\n\t *\n\t *\t\t// String.\n\t *\t\tmatcher.add( 'div' );\n\t *\n\t *\t\t// Regular expression.\n\t *\t\tmatcher.add( /^\\w/ );\n\t *\n\t *\t\t// Single class.\n\t *\t\tmatcher.add( {\n\t *\t\t\tclasses: 'foobar'\n\t *\t\t} );\n\t *\n\t * See {@link module:engine/view/matcher~MatcherPattern} for more examples.\n\t *\n\t * Multiple patterns can be added in one call:\n\t *\n\t * \t\tmatcher.add( 'div', { classes: 'foobar' } );\n\t *\n\t * @param {Object|String|RegExp|Function} pattern Object describing pattern details. If string or regular expression\n\t * is provided it will be used to match element's name. Pattern can be also provided in a form\n\t * of a function - then this function will be called with each {@link module:engine/view/element~Element element} as a parameter.\n\t * Function's return value will be stored under `match` key of the object returned from\n\t * {@link module:engine/view/matcher~Matcher#match match} or {@link module:engine/view/matcher~Matcher#matchAll matchAll} methods.\n\t * @param {String|RegExp} [pattern.name] Name or regular expression to match element's name.\n\t * @param {Object} [pattern.attributes] Object with key-value pairs representing attributes to match. Each object key\n\t * represents attribute name. Value under that key can be either:\n\t * * `true` - then attribute is just required (can be empty),\n\t * * a string - then attribute has to be equal, or\n\t * * a regular expression - then attribute has to match the expression.\n\t * @param {String|RegExp|Array} [pattern.classes] Class name or array of class names to match. Each name can be\n\t * provided in a form of string or regular expression.\n\t * @param {Object} [pattern.styles] Object with key-value pairs representing styles to match. Each object key\n\t * represents style name. Value under that key can be either a string or a regular expression and it will be used\n\t * to match style value.\n\t */\n\tadd( ...pattern ) {\n\t\tfor ( let item of pattern ) {\n\t\t\t// String or RegExp pattern is used as element's name.\n\t\t\tif ( typeof item == 'string' || item instanceof RegExp ) {\n\t\t\t\titem = { name: item };\n\t\t\t}\n\n\t\t\t// Single class name/RegExp can be provided.\n\t\t\tif ( item.classes && ( typeof item.classes == 'string' || item.classes instanceof RegExp ) ) {\n\t\t\t\titem.classes = [ item.classes ];\n\t\t\t}\n\n\t\t\tthis._patterns.push( item );\n\t\t}\n\t}\n\n\t/**\n\t * Matches elements for currently stored patterns. Returns match information about first found\n\t * {@link module:engine/view/element~Element element}, otherwise returns `null`.\n\t *\n\t * Example of returned object:\n\t *\n\t *\t\t{\n\t *\t\t\telement: <instance of found element>,\n\t *\t\t\tpattern: <pattern used to match found element>,\n\t *\t\t\tmatch: {\n\t *\t\t\t\tname: true,\n\t *\t\t\t\tattributes: [ 'title', 'href' ],\n\t *\t\t\t\tclasses: [ 'foo' ],\n\t *\t\t\t\tstyles: [ 'color', 'position' ]\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t * @see module:engine/view/matcher~Matcher#add\n\t * @see module:engine/view/matcher~Matcher#matchAll\n\t * @param {...module:engine/view/element~Element} element View element to match against stored patterns.\n\t * @returns {Object|null} result\n\t * @returns {module:engine/view/element~Element} result.element Matched view element.\n\t * @returns {Object|String|RegExp|Function} result.pattern Pattern that was used to find matched element.\n\t * @returns {Object} result.match Object representing matched element parts.\n\t * @returns {Boolean} [result.match.name] True if name of the element was matched.\n\t * @returns {Array} [result.match.attributes] Array with matched attribute names.\n\t * @returns {Array} [result.match.classes] Array with matched class names.\n\t * @returns {Array} [result.match.styles] Array with matched style names.\n\t */\n\tmatch( ...element ) {\n\t\tfor ( const singleElement of element ) {\n\t\t\tfor ( const pattern of this._patterns ) {\n\t\t\t\tconst match = isElementMatching( singleElement, pattern );\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\telement: singleElement,\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tmatch\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Matches elements for currently stored patterns. Returns array of match information with all found\n\t * {@link module:engine/view/element~Element elements}. If no element is found - returns `null`.\n\t *\n\t * @see module:engine/view/matcher~Matcher#add\n\t * @see module:engine/view/matcher~Matcher#match\n\t * @param {...module:engine/view/element~Element} element View element to match against stored patterns.\n\t * @returns {Array.<Object>|null} Array with match information about found elements or `null`. For more information\n\t * see {@link module:engine/view/matcher~Matcher#match match method} description.\n\t */\n\tmatchAll( ...element ) {\n\t\tconst results = [];\n\n\t\tfor ( const singleElement of element ) {\n\t\t\tfor ( const pattern of this._patterns ) {\n\t\t\t\tconst match = isElementMatching( singleElement, pattern );\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tresults.push( {\n\t\t\t\t\t\telement: singleElement,\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tmatch\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn results.length > 0 ? results : null;\n\t}\n\n\t/**\n\t * Returns the name of the element to match if there is exactly one pattern added to the matcher instance\n\t * and it matches element name defined by `string` (not `RegExp`). Otherwise, returns `null`.\n\t *\n\t * @returns {String|null} Element name trying to match.\n\t */\n\tgetElementName() {\n\t\tif ( this._patterns.length !== 1 ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst pattern = this._patterns[ 0 ];\n\t\tconst name = pattern.name;\n\n\t\treturn ( typeof pattern != 'function' && name && !( name instanceof RegExp ) ) ? name : null;\n\t}\n}\n\n// Returns match information if {@link module:engine/view/element~Element element} is matching provided pattern.\n// If element cannot be matched to provided pattern - returns `null`.\n//\n// @param {module:engine/view/element~Element} element\n// @param {Object|String|RegExp|Function} pattern\n// @returns {Object|null} Returns object with match information or null if element is not matching.\nfunction isElementMatching( element, pattern ) {\n\t// If pattern is provided as function - return result of that function;\n\tif ( typeof pattern == 'function' ) {\n\t\treturn pattern( element );\n\t}\n\n\tconst match = {};\n\t// Check element's name.\n\tif ( pattern.name ) {\n\t\tmatch.name = matchName( pattern.name, element.name );\n\n\t\tif ( !match.name ) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t// Check element's attributes.\n\tif ( pattern.attributes ) {\n\t\tmatch.attributes = matchAttributes( pattern.attributes, element );\n\n\t\tif ( !match.attributes ) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t// Check element's classes.\n\tif ( pattern.classes ) {\n\t\tmatch.classes = matchClasses( pattern.classes, element );\n\n\t\tif ( !match.classes ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// Check element's styles.\n\tif ( pattern.styles ) {\n\t\tmatch.styles = matchStyles( pattern.styles, element );\n\n\t\tif ( !match.styles ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn match;\n}\n\n// Checks if name can be matched by provided pattern.\n//\n// @param {String|RegExp} pattern\n// @param {String} name\n// @returns {Boolean} Returns `true` if name can be matched, `false` otherwise.\nfunction matchName( pattern, name ) {\n\t// If pattern is provided as RegExp - test against this regexp.\n\tif ( pattern instanceof RegExp ) {\n\t\treturn pattern.test( name );\n\t}\n\n\treturn pattern === name;\n}\n\n// Checks if attributes of provided element can be matched against provided patterns.\n//\n// @param {Object} patterns Object with information about attributes to match. Each key of the object will be\n// used as attribute name. Value of each key can be a string or regular expression to match against attribute value.\n// @param {module:engine/view/element~Element} element Element which attributes will be tested.\n// @returns {Array|null} Returns array with matched attribute names or `null` if no attributes were matched.\nfunction matchAttributes( patterns, element ) {\n\tconst match = [];\n\n\tfor ( const name in patterns ) {\n\t\tconst pattern = patterns[ name ];\n\n\t\tif ( element.hasAttribute( name ) ) {\n\t\t\tconst attribute = element.getAttribute( name );\n\n\t\t\tif ( pattern === true ) {\n\t\t\t\tmatch.push( name );\n\t\t\t} else if ( pattern instanceof RegExp ) {\n\t\t\t\tif ( pattern.test( attribute ) ) {\n\t\t\t\t\tmatch.push( name );\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t} else if ( attribute === pattern ) {\n\t\t\t\tmatch.push( name );\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn match;\n}\n\n// Checks if classes of provided element can be matched against provided patterns.\n//\n// @param {Array.<String|RegExp>} patterns Array of strings or regular expressions to match against element's classes.\n// @param {module:engine/view/element~Element} element Element which classes will be tested.\n// @returns {Array|null} Returns array with matched class names or `null` if no classes were matched.\nfunction matchClasses( patterns, element ) {\n\tconst match = [];\n\n\tfor ( const pattern of patterns ) {\n\t\tif ( pattern instanceof RegExp ) {\n\t\t\tconst classes = element.getClassNames();\n\n\t\t\tfor ( const name of classes ) {\n\t\t\t\tif ( pattern.test( name ) ) {\n\t\t\t\t\tmatch.push( name );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( match.length === 0 ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} else if ( element.hasClass( pattern ) ) {\n\t\t\tmatch.push( pattern );\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn match;\n}\n\n// Checks if styles of provided element can be matched against provided patterns.\n//\n// @param {Object} patterns Object with information about styles to match. Each key of the object will be\n// used as style name. Value of each key can be a string or regular expression to match against style value.\n// @param {module:engine/view/element~Element} element Element which styles will be tested.\n// @returns {Array|null} Returns array with matched style names or `null` if no styles were matched.\nfunction matchStyles( patterns, element ) {\n\tconst match = [];\n\n\tfor ( const name in patterns ) {\n\t\tconst pattern = patterns[ name ];\n\n\t\tif ( element.hasStyle( name ) ) {\n\t\t\tconst style = element.getStyle( name );\n\n\t\t\tif ( pattern instanceof RegExp ) {\n\t\t\t\tif ( pattern.test( style ) ) {\n\t\t\t\t\tmatch.push( name );\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t} else if ( style === pattern ) {\n\t\t\t\tmatch.push( name );\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn match;\n}\n\n/**\n * An entity that is a valid pattern recognized by a matcher. `MatcherPattern` is used by {@link ~Matcher} to recognize\n * if a view element fits in a group of view elements described by the pattern.\n *\n * `MatcherPattern` can be given as a `String`, a `RegExp`, an `Object` or a `Function`.\n *\n * If `MatcherPattern` is given as a `String` or `RegExp`, it will match any view element that has a matching name:\n *\n *\t\t// Match any element with name equal to 'div'.\n *\t\tconst pattern = 'div';\n *\n *\t\t// Match any element which name starts on 'p'.\n *\t\tconst pattern = /^p/;\n *\n * If `MatcherPattern` is given as an `Object`, all the object's properties will be matched with view element properties.\n *\n *\t\t// Match view element's name.\n *\t\tconst pattern = { name: /^p/ };\n *\n *\t\t// Match view element which has matching attributes.\n *\t\tconst pattern = {\n *\t\t\tattributes: {\n *\t\t\t\ttitle: 'foobar',\t// Attribute title should equal 'foobar'.\n *\t\t\t\tfoo: /^\\w+/,\t\t// Attribute foo should match /^\\w+/ regexp.\n *\t\t\t\tbar: true\t\t\t// Attribute bar should be set (can be empty).\n *\t\t\t}\n *\t\t};\n *\n *\t\t// Match view element which has given class.\n *\t\tconst pattern = {\n *\t\t\tclasses: 'foobar'\n *\t\t};\n *\n *\t\t// Match view element class using regular expression.\n *\t\tconst pattern = {\n *\t\t\tclasses: /foo.../\n *\t\t};\n *\n *\t\t// Multiple classes to match.\n *\t\tconst pattern = {\n *\t\t\tclasses: [ 'baz', 'bar', /foo.../ ]\n *\t\t};\n *\n *\t\t// Match view element which has given styles.\n *\t\tconst pattern = {\n *\t\t\tstyles: {\n *\t\t\t\tposition: 'absolute',\n *\t\t\t\tcolor: /^\\w*blue$/\n *\t\t\t}\n *\t\t};\n *\n *\t\t// Pattern with multiple properties.\n *\t\tconst pattern = {\n *\t\t\tname: 'span',\n *\t\t\tstyles: {\n *\t\t\t\t'font-weight': 'bold'\n *\t\t\t},\n *\t\t\tclasses: 'highlighted'\n *\t\t};\n *\n * If `MatcherPattern` is given as a `Function`, the function takes a view element as a first and only parameter and\n * the function should decide whether that element matches. If so, it should return what part of the view element has been matched.\n * Otherwise, the function should return `null`. The returned result will be included in `match` property of the object\n * returned by {@link ~Matcher#match} call.\n *\n *\t\t// Match an empty <div> element.\n *\t\tconst pattern = element => {\n *\t\t\tif ( element.name == 'div' && element.childCount > 0 ) {\n *\t\t\t\t// Return which part of the element was matched.\n *\t\t\t\treturn { name: true };\n *\t\t\t}\n *\n *\t\t\treturn null;\n *\t\t};\n *\n *\t\t// Match a <p> element with big font (\"heading-like\" element).\n *\t\tconst pattern = element => {\n *\t\t\tif ( element.name == 'p' ) {\n *\t\t\t\tconst fontSize = element.getStyle( 'font-size' );\n *\t\t\t\tconst size = fontSize.match( /(\\d+)/px );\n *\n *\t\t\t\tif ( size && Number( size[ 1 ] ) > 26 ) {\n *\t\t\t\t\treturn { name: true, attribute: [ 'font-size' ] };\n *\t\t\t\t}\n *\t\t\t}\n *\n *\t\t\treturn null;\n *\t\t};\n *\n * `MatcherPattern` is defined in a way that it is a superset of {@link module:engine/view/elementdefinition~ElementDefinition},\n * that is, every `ElementDefinition` also can be used as a `MatcherPattern`.\n *\n * @typedef {String|RegExp|Object|Function} module:engine/view/matcher~MatcherPattern\n *\n * @property {String|RegExp} [name] View element name to match.\n * @property {String|RegExp|Array.<String|RegExp>} [classes] View element's class name(s) to match.\n * @property {Object} [styles] Object with key-value pairs representing styles to match.\n * Each object key represents style name. Value can be given as `String` or `RegExp`.\n * @property {Object} [attributes] Object with key-value pairs representing attributes to match.\n * Each object key represents attribute name. Value can be given as `String` or `RegExp`.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/element\n */\n\nimport Node from './node';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport objectToMap from '@ckeditor/ckeditor5-utils/src/objecttomap';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\nimport Matcher from './matcher';\nimport { isPlainObject } from 'lodash-es';\n\n/**\n * View element.\n *\n * The editing engine does not define a fixed semantics of its elements (it is \"DTD-free\").\n * This is why the type of the {@link module:engine/view/element~Element} need to\n * be defined by the feature developer. When creating an element you should use one of the following methods:\n *\n * * {@link module:engine/view/downcastwriter~DowncastWriter#createContainerElement `downcastWriter#createContainerElement()`}\n * in order to create a {@link module:engine/view/containerelement~ContainerElement},\n * * {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement `downcastWriter#createAttributeElement()`}\n * in order to create a {@link module:engine/view/attributeelement~AttributeElement},\n * * {@link module:engine/view/downcastwriter~DowncastWriter#createEmptyElement `downcastWriter#createEmptyElement()`}\n * in order to create a {@link module:engine/view/emptyelement~EmptyElement}.\n * * {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement `downcastWriter#createUIElement()`}\n * in order to create a {@link module:engine/view/uielement~UIElement}.\n * * {@link module:engine/view/downcastwriter~DowncastWriter#createEditableElement `downcastWriter#createEditableElement()`}\n * in order to create a {@link module:engine/view/editableelement~EditableElement}.\n *\n * Note that for view elements which are not created from the model, like elements from mutations, paste or\n * {@link module:engine/controller/datacontroller~DataController#set data.set} it is not possible to define the type of the element.\n * In such cases the {@link module:engine/view/upcastwriter~UpcastWriter#createElement `UpcastWriter#createElement()`} method\n * should be used to create generic view elements.\n *\n * @extends module:engine/view/node~Node\n */\nexport default class Element extends Node {\n\t/**\n\t * Creates a view element.\n\t *\n\t * Attributes can be passed in various formats:\n\t *\n\t *\t\tnew Element( 'div', { class: 'editor', contentEditable: 'true' } ); // object\n\t *\t\tnew Element( 'div', [ [ 'class', 'editor' ], [ 'contentEditable', 'true' ] ] ); // map-like iterator\n\t *\t\tnew Element( 'div', mapOfAttributes ); // map\n\t *\n\t * @protected\n\t * @param {String} name Node name.\n\t * @param {Object|Iterable} [attrs] Collection of attributes.\n\t * @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]\n\t * A list of nodes to be inserted into created element.\n\t */\n\tconstructor( name, attrs, children ) {\n\t\tsuper();\n\n\t\t/**\n\t\t * Name of the element.\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 * Map of attributes, where attributes names are keys and attributes values are values.\n\t\t *\n\t\t * @protected\n\t\t * @member {Map} #_attrs\n\t\t */\n\t\tthis._attrs = parseAttributes( attrs );\n\n\t\t/**\n\t\t * Array of child nodes.\n\t\t *\n\t\t * @protected\n\t\t * @member {Array.<module:engine/view/node~Node>}\n\t\t */\n\t\tthis._children = [];\n\n\t\tif ( children ) {\n\t\t\tthis._insertChild( 0, children );\n\t\t}\n\n\t\t/**\n\t\t * Set of classes associated with element instance.\n\t\t *\n\t\t * @protected\n\t\t * @member {Set}\n\t\t */\n\t\tthis._classes = new Set();\n\n\t\tif ( this._attrs.has( 'class' ) ) {\n\t\t\t// Remove class attribute and handle it by class set.\n\t\t\tconst classString = this._attrs.get( 'class' );\n\t\t\tparseClasses( this._classes, classString );\n\t\t\tthis._attrs.delete( 'class' );\n\t\t}\n\n\t\t/**\n\t\t * Map of styles.\n\t\t *\n\t\t * @protected\n\t\t * @member {Map} module:engine/view/element~Element#_styles\n\t\t */\n\t\tthis._styles = new Map();\n\n\t\tif ( this._attrs.has( 'style' ) ) {\n\t\t\t// Remove style attribute and handle it by styles map.\n\t\t\tparseInlineStyles( this._styles, this._attrs.get( 'style' ) );\n\t\t\tthis._attrs.delete( 'style' );\n\t\t}\n\n\t\t/**\n\t\t * Map of custom properties.\n\t\t * Custom properties can be added to element instance, will be cloned but not rendered into DOM.\n\t\t *\n\t\t * @protected\n\t\t * @member {Map}\n\t\t */\n\t\tthis._customProperties = new Map();\n\t}\n\n\t/**\n\t * Number of element's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget childCount() {\n\t\treturn this._children.length;\n\t}\n\n\t/**\n\t * Is `true` if there are no nodes inside this element, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isEmpty() {\n\t\treturn this._children.length === 0;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\telement.is( 'element' ); // -> true\n\t *\t\telement.is( 'node' ); // -> true\n\t *\t\telement.is( 'view:element' ); // -> true\n\t *\t\telement.is( 'view:node' ); // -> true\n\t *\n\t *\t\telement.is( 'model:element' ); // -> false\n\t *\t\telement.is( 'documentSelection' ); // -> false\n\t *\n\t * Assuming that the object being checked is an element, you can also check its\n\t * {@link module:engine/view/element~Element#name name}:\n\t *\n\t *\t\telement.is( 'img' ); // -> true if this is an <img> element\n\t *\t\telement.is( 'element', 'img' ); // -> same as above\n\t *\t\ttext.is( 'img' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tconst cutType = type.replace( /^view:/, '' );\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'element' || cutType == this.name || super.is( type );\n\t\t} else {\n\t\t\treturn cutType == 'element' && name == this.name;\n\t\t}\n\t}\n\n\t/**\n\t * Gets child at the given index.\n\t *\n\t * @param {Number} index Index of child.\n\t * @returns {module:engine/view/node~Node} Child node.\n\t */\n\tgetChild( index ) {\n\t\treturn this._children[ index ];\n\t}\n\n\t/**\n\t * Gets index of the given child node. Returns `-1` if child node is not found.\n\t *\n\t * @param {module:engine/view/node~Node} node Child node.\n\t * @returns {Number} Index of the child node.\n\t */\n\tgetChildIndex( node ) {\n\t\treturn this._children.indexOf( node );\n\t}\n\n\t/**\n\t * Gets child nodes iterator.\n\t *\n\t * @returns {Iterable.<module:engine/view/node~Node>} Child nodes iterator.\n\t */\n\tgetChildren() {\n\t\treturn this._children[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Returns an iterator that contains the keys for attributes. Order of inserting attributes is not preserved.\n\t *\n\t * @returns {Iterable.<String>} Keys for attributes.\n\t */\n\t* getAttributeKeys() {\n\t\tif ( this._classes.size > 0 ) {\n\t\t\tyield 'class';\n\t\t}\n\n\t\tif ( this._styles.size > 0 ) {\n\t\t\tyield 'style';\n\t\t}\n\n\t\tyield* this._attrs.keys();\n\t}\n\n\t/**\n\t * Returns iterator that iterates over this element's attributes.\n\t *\n\t * Attributes are returned as arrays containing two items. First one is attribute key and second is attribute value.\n\t * This format is accepted by native `Map` object and also can be passed in `Node` constructor.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\t* getAttributes() {\n\t\tyield* this._attrs.entries();\n\n\t\tif ( this._classes.size > 0 ) {\n\t\t\tyield [ 'class', this.getAttribute( 'class' ) ];\n\t\t}\n\n\t\tif ( this._styles.size > 0 ) {\n\t\t\tyield [ 'style', this.getAttribute( 'style' ) ];\n\t\t}\n\t}\n\n\t/**\n\t * Gets attribute by key. If attribute is not present - returns undefined.\n\t *\n\t * @param {String} key Attribute key.\n\t * @returns {String|undefined} Attribute value.\n\t */\n\tgetAttribute( key ) {\n\t\tif ( key == 'class' ) {\n\t\t\tif ( this._classes.size > 0 ) {\n\t\t\t\treturn [ ...this._classes ].join( ' ' );\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ( key == 'style' ) {\n\t\t\tif ( this._styles.size > 0 ) {\n\t\t\t\tlet styleString = '';\n\n\t\t\t\tfor ( const [ property, value ] of this._styles ) {\n\t\t\t\t\tstyleString += `${ property }:${ value };`;\n\t\t\t\t}\n\n\t\t\t\treturn styleString;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn this._attrs.get( key );\n\t}\n\n\t/**\n\t * Returns a boolean indicating whether an attribute with the specified key exists in the element.\n\t *\n\t * @param {String} key Attribute key.\n\t * @returns {Boolean} `true` if attribute with the specified key exists in the element, false otherwise.\n\t */\n\thasAttribute( key ) {\n\t\tif ( key == 'class' ) {\n\t\t\treturn this._classes.size > 0;\n\t\t}\n\n\t\tif ( key == 'style' ) {\n\t\t\treturn this._styles.size > 0;\n\t\t}\n\n\t\treturn this._attrs.has( key );\n\t}\n\n\t/**\n\t * Checks if this element is similar to other element.\n\t * Both elements should have the same name and attributes to be considered as similar. Two similar elements\n\t * can contain different set of children nodes.\n\t *\n\t * @param {module:engine/view/element~Element} otherElement\n\t * @returns {Boolean}\n\t */\n\tisSimilar( otherElement ) {\n\t\tif ( !( otherElement instanceof Element ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If exactly the same Element is provided - return true immediately.\n\t\tif ( this === otherElement ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check element name.\n\t\tif ( this.name != otherElement.name ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check number of attributes, classes and styles.\n\t\tif ( this._attrs.size !== otherElement._attrs.size || this._classes.size !== otherElement._classes.size ||\n\t\t\tthis._styles.size !== otherElement._styles.size ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if attributes are the same.\n\t\tfor ( const [ key, value ] of this._attrs ) {\n\t\t\tif ( !otherElement._attrs.has( key ) || otherElement._attrs.get( key ) !== value ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Check if classes are the same.\n\t\tfor ( const className of this._classes ) {\n\t\t\tif ( !otherElement._classes.has( className ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Check if styles are the same.\n\t\tfor ( const [ property, value ] of this._styles ) {\n\t\t\tif ( !otherElement._styles.has( property ) || otherElement._styles.get( property ) !== value ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns true if class is present.\n\t * If more then one class is provided - returns true only when all classes are present.\n\t *\n\t *\t\telement.hasClass( 'foo' ); // Returns true if 'foo' class is present.\n\t *\t\telement.hasClass( 'foo', 'bar' ); // Returns true if 'foo' and 'bar' classes are both present.\n\t *\n\t * @param {...String} className\n\t */\n\thasClass( ...className ) {\n\t\tfor ( const name of className ) {\n\t\t\tif ( !this._classes.has( name ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns iterator that contains all class names.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\tgetClassNames() {\n\t\treturn this._classes.keys();\n\t}\n\n\t/**\n\t * Returns style value for given property.\n\t * Undefined is returned if style does not exist.\n\t *\n\t * @param {String} property\n\t * @returns {String|undefined}\n\t */\n\tgetStyle( property ) {\n\t\treturn this._styles.get( property );\n\t}\n\n\t/**\n\t * Returns iterator that contains all style names.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\tgetStyleNames() {\n\t\treturn this._styles.keys();\n\t}\n\n\t/**\n\t * Returns true if style keys are present.\n\t * If more then one style property is provided - returns true only when all properties are present.\n\t *\n\t *\t\telement.hasStyle( 'color' ); // Returns true if 'border-top' style is present.\n\t *\t\telement.hasStyle( 'color', 'border-top' ); // Returns true if 'color' and 'border-top' styles are both present.\n\t *\n\t * @param {...String} property\n\t */\n\thasStyle( ...property ) {\n\t\tfor ( const name of property ) {\n\t\t\tif ( !this._styles.has( name ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns ancestor element that match specified pattern.\n\t * Provided patterns should be compatible with {@link module:engine/view/matcher~Matcher Matcher} as it is used internally.\n\t *\n\t * @see module:engine/view/matcher~Matcher\n\t * @param {Object|String|RegExp|Function} patterns Patterns used to match correct ancestor.\n\t * See {@link module:engine/view/matcher~Matcher}.\n\t * @returns {module:engine/view/element~Element|null} Found element or `null` if no matching ancestor was found.\n\t */\n\tfindAncestor( ...patterns ) {\n\t\tconst matcher = new Matcher( ...patterns );\n\t\tlet parent = this.parent;\n\n\t\twhile ( parent ) {\n\t\t\tif ( matcher.match( parent ) ) {\n\t\t\t\treturn parent;\n\t\t\t}\n\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Returns the custom property value for the given key.\n\t *\n\t * @param {String|Symbol} key\n\t * @returns {*}\n\t */\n\tgetCustomProperty( key ) {\n\t\treturn this._customProperties.get( key );\n\t}\n\n\t/**\n\t * Returns an iterator which iterates over this element's custom properties.\n\t * Iterator provides `[ key, value ]` pairs for each stored property.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\t* getCustomProperties() {\n\t\tyield* this._customProperties.entries();\n\t}\n\n\t/**\n\t * Returns identity string based on element's name, styles, classes and other attributes.\n\t * Two elements that {@link #isSimilar are similar} will have same identity string.\n\t * It has the following format:\n\t *\n\t *\t\t'name class=\"class1,class2\" style=\"style1:value1;style2:value2\" attr1=\"val1\" attr2=\"val2\"'\n \t *\n\t * For example:\n\t *\n\t *\t\tconst element = writer.createContainerElement( 'foo', {\n\t *\t\t\tbanana: '10',\n\t *\t\t\tapple: '20',\n\t *\t\t\tstyle: 'color: red; border-color: white;',\n\t *\t\t\tclass: 'baz'\n\t *\t\t} );\n\t *\n\t *\t\t// returns 'foo class=\"baz\" style=\"border-color:white;color:red\" apple=\"20\" banana=\"10\"'\n\t *\t\telement.getIdentity();\n\t *\n\t * NOTE: Classes, styles and other attributes are sorted alphabetically.\n\t *\n\t * @returns {String}\n\t */\n\tgetIdentity() {\n\t\tconst classes = Array.from( this._classes ).sort().join( ',' );\n\t\tconst styles = Array.from( this._styles ).map( i => `${ i[ 0 ] }:${ i[ 1 ] }` ).sort().join( ';' );\n\t\tconst attributes = Array.from( this._attrs ).map( i => `${ i[ 0 ] }=\"${ i[ 1 ] }\"` ).sort().join( ' ' );\n\n\t\treturn this.name +\n\t\t\t( classes == '' ? '' : ` class=\"${ classes }\"` ) +\n\t\t\t( styles == '' ? '' : ` style=\"${ styles }\"` ) +\n\t\t\t( attributes == '' ? '' : ` ${ attributes }` );\n\t}\n\n\t/**\n\t * Clones provided element.\n\t *\n\t * @protected\n\t * @param {Boolean} [deep=false] If set to `true` clones element and all its children recursively. When set to `false`,\n\t * element will be cloned without any children.\n\t * @returns {module:engine/view/element~Element} Clone of this element.\n\t */\n\t_clone( deep = false ) {\n\t\tconst childrenClone = [];\n\n\t\tif ( deep ) {\n\t\t\tfor ( const child of this.getChildren() ) {\n\t\t\t\tchildrenClone.push( child._clone( deep ) );\n\t\t\t}\n\t\t}\n\n\t\t// ContainerElement and AttributeElement should be also cloned properly.\n\t\tconst cloned = new this.constructor( this.name, this._attrs, childrenClone );\n\n\t\t// Classes and styles are cloned separately - this solution is faster than adding them back to attributes and\n\t\t// parse once again in constructor.\n\t\tcloned._classes = new Set( this._classes );\n\t\tcloned._styles = new Map( this._styles );\n\n\t\t// Clone custom properties.\n\t\tcloned._customProperties = new Map( this._customProperties );\n\n\t\t// Clone filler offset method.\n\t\t// We can't define this method in a prototype because it's behavior which\n\t\t// is changed by e.g. toWidget() function from ckeditor5-widget. Perhaps this should be one of custom props.\n\t\tcloned.getFillerOffset = this.getFillerOffset;\n\n\t\treturn cloned;\n\t}\n\n\t/**\n\t * {@link module:engine/view/element~Element#_insertChild Insert} a child node or a list of child nodes at the end of this node\n\t * and sets the parent of these nodes to this element.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#insert\n\t * @protected\n\t * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.\n\t * @fires module:engine/view/node~Node#change\n\t * @returns {Number} Number of appended nodes.\n\t */\n\t_appendChild( items ) {\n\t\treturn this._insertChild( this.childCount, items );\n\t}\n\n\t/**\n\t * Inserts a child node or a list of child nodes on the given index and sets the parent of these nodes to\n\t * this element.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#insert\n\t * @protected\n\t * @param {Number} index Position where nodes should be inserted.\n\t * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.\n\t * @fires module:engine/view/node~Node#change\n\t * @returns {Number} Number of inserted nodes.\n\t */\n\t_insertChild( index, items ) {\n\t\tthis._fireChange( 'children', this );\n\t\tlet count = 0;\n\n\t\tconst nodes = normalize( items );\n\n\t\tfor ( const node of nodes ) {\n\t\t\t// If node that is being added to this element is already inside another element, first remove it from the old parent.\n\t\t\tif ( node.parent !== null ) {\n\t\t\t\tnode._remove();\n\t\t\t}\n\n\t\t\tnode.parent = this;\n\n\t\t\tthis._children.splice( index, 0, node );\n\t\t\tindex++;\n\t\t\tcount++;\n\t\t}\n\n\t\treturn count;\n\t}\n\n\t/**\n\t * Removes number of child nodes starting at the given index and set the parent of these nodes to `null`.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#remove\n\t * @protected\n\t * @param {Number} index Number of the first node to remove.\n\t * @param {Number} [howMany=1] Number of nodes to remove.\n\t * @fires module:engine/view/node~Node#change\n\t * @returns {Array.<module:engine/view/node~Node>} The array of removed nodes.\n\t */\n\t_removeChildren( index, howMany = 1 ) {\n\t\tthis._fireChange( 'children', this );\n\n\t\tfor ( let i = index; i < index + howMany; i++ ) {\n\t\t\tthis._children[ i ].parent = null;\n\t\t}\n\n\t\treturn this._children.splice( index, howMany );\n\t}\n\n\t/**\n\t * Adds or overwrite attribute with a specified key and value.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#setAttribute\n\t * @protected\n\t * @param {String} key Attribute key.\n\t * @param {String} value Attribute value.\n\t * @fires module:engine/view/node~Node#change\n\t */\n\t_setAttribute( key, value ) {\n\t\tvalue = String( value );\n\n\t\tthis._fireChange( 'attributes', this );\n\n\t\tif ( key == 'class' ) {\n\t\t\tparseClasses( this._classes, value );\n\t\t} else if ( key == 'style' ) {\n\t\t\tparseInlineStyles( this._styles, value );\n\t\t} else {\n\t\t\tthis._attrs.set( key, value );\n\t\t}\n\t}\n\n\t/**\n\t * Removes attribute from the element.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#removeAttribute\n\t * @protected\n\t * @param {String} key Attribute key.\n\t * @returns {Boolean} Returns true if an attribute existed and has been removed.\n\t * @fires module:engine/view/node~Node#change\n\t */\n\t_removeAttribute( key ) {\n\t\tthis._fireChange( 'attributes', this );\n\n\t\t// Remove class attribute.\n\t\tif ( key == 'class' ) {\n\t\t\tif ( this._classes.size > 0 ) {\n\t\t\t\tthis._classes.clear();\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\t// Remove style attribute.\n\t\tif ( key == 'style' ) {\n\t\t\tif ( this._styles.size > 0 ) {\n\t\t\t\tthis._styles.clear();\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\t// Remove other attributes.\n\t\treturn this._attrs.delete( key );\n\t}\n\n\t/**\n\t * Adds specified class.\n\t *\n\t *\t\telement._addClass( 'foo' ); // Adds 'foo' class.\n\t *\t\telement._addClass( [ 'foo', 'bar' ] ); // Adds 'foo' and 'bar' classes.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#addClass\n\t * @protected\n\t * @param {Array.<String>|String} className\n\t * @fires module:engine/view/node~Node#change\n\t */\n\t_addClass( className ) {\n\t\tthis._fireChange( 'attributes', this );\n\n\t\tclassName = Array.isArray( className ) ? className : [ className ];\n\t\tclassName.forEach( name => this._classes.add( name ) );\n\t}\n\n\t/**\n\t * Removes specified class.\n\t *\n\t *\t\telement._removeClass( 'foo' ); // Removes 'foo' class.\n\t *\t\telement._removeClass( [ 'foo', 'bar' ] ); // Removes both 'foo' and 'bar' classes.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#removeClass\n\t * @protected\n\t * @param {Array.<String>|String} className\n\t * @fires module:engine/view/node~Node#change\n\t */\n\t_removeClass( className ) {\n\t\tthis._fireChange( 'attributes', this );\n\n\t\tclassName = Array.isArray( className ) ? className : [ className ];\n\t\tclassName.forEach( name => this._classes.delete( name ) );\n\t}\n\n\t/**\n\t * Adds style to the element.\n\t *\n\t *\t\telement._setStyle( 'color', 'red' );\n\t *\t\telement._setStyle( {\n\t *\t\t\tcolor: 'red',\n\t *\t\t\tposition: 'fixed'\n\t *\t\t} );\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#setStyle\n\t * @protected\n\t * @param {String|Object} property Property name or object with key - value pairs.\n\t * @param {String} [value] Value to set. This parameter is ignored if object is provided as the first parameter.\n\t * @fires module:engine/view/node~Node#change\n\t */\n\t_setStyle( property, value ) {\n\t\tthis._fireChange( 'attributes', this );\n\n\t\tif ( isPlainObject( property ) ) {\n\t\t\tconst keys = Object.keys( property );\n\n\t\t\tfor ( const key of keys ) {\n\t\t\t\tthis._styles.set( key, property[ key ] );\n\t\t\t}\n\t\t} else {\n\t\t\tthis._styles.set( property, value );\n\t\t}\n\t}\n\n\t/**\n\t * Removes specified style.\n\t *\n\t *\t\telement._removeStyle( 'color' ); // Removes 'color' style.\n\t *\t\telement._removeStyle( [ 'color', 'border-top' ] ); // Removes both 'color' and 'border-top' styles.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#removeStyle\n\t * @protected\n\t * @param {Array.<String>|String} property\n\t * @fires module:engine/view/node~Node#change\n\t */\n\t_removeStyle( property ) {\n\t\tthis._fireChange( 'attributes', this );\n\n\t\tproperty = Array.isArray( property ) ? property : [ property ];\n\t\tproperty.forEach( name => this._styles.delete( name ) );\n\t}\n\n\t/**\n\t * Sets a custom property. Unlike attributes, custom properties are not rendered to the DOM,\n\t * so they can be used to add special data to elements.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#setCustomProperty\n\t * @protected\n\t * @param {String|Symbol} key\n\t * @param {*} value\n\t */\n\t_setCustomProperty( key, value ) {\n\t\tthis._customProperties.set( key, value );\n\t}\n\n\t/**\n\t * Removes the custom property stored under the given key.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#removeCustomProperty\n\t * @protected\n\t * @param {String|Symbol} key\n\t * @returns {Boolean} Returns true if property was removed.\n\t */\n\t_removeCustomProperty( key ) {\n\t\treturn this._customProperties.delete( key );\n\t}\n\n\t/**\n\t * Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.\n\t *\n\t * @abstract\n\t * @method module:engine/view/element~Element#getFillerOffset\n\t */\n}\n\n// Parses attributes provided to the element constructor before they are applied to an element. If attributes are passed\n// as an object (instead of `Map`), the object is transformed to the map. Attributes with `null` value are removed.\n// Attributes with non-`String` value are converted to `String`.\n//\n// @param {Object|Map} attrs Attributes to parse.\n// @returns {Map} Parsed attributes.\nfunction parseAttributes( attrs ) {\n\tif ( isPlainObject( attrs ) ) {\n\t\tattrs = objectToMap( attrs );\n\t} else {\n\t\tattrs = new Map( attrs );\n\t}\n\n\tfor ( const [ key, value ] of attrs ) {\n\t\tif ( value === null ) {\n\t\t\tattrs.delete( key );\n\t\t} else if ( typeof value != 'string' ) {\n\t\t\tattrs.set( key, String( value ) );\n\t\t}\n\t}\n\n\treturn attrs;\n}\n\n// Parses inline styles and puts property - value pairs into styles map.\n// Styles map is cleared before insertion.\n//\n// @param {Map.<String, String>} stylesMap Map to insert parsed properties and values.\n// @param {String} stylesString Styles to parse.\nfunction parseInlineStyles( stylesMap, stylesString ) {\n\t// `null` if no quote was found in input string or last found quote was a closing quote. See below.\n\tlet quoteType = null;\n\tlet propertyNameStart = 0;\n\tlet propertyValueStart = 0;\n\tlet propertyName = null;\n\n\tstylesMap.clear();\n\n\t// Do not set anything if input string is empty.\n\tif ( stylesString === '' ) {\n\t\treturn;\n\t}\n\n\t// Fix inline styles that do not end with `;` so they are compatible with algorithm below.\n\tif ( stylesString.charAt( stylesString.length - 1 ) != ';' ) {\n\t\tstylesString = stylesString + ';';\n\t}\n\n\t// Seek the whole string for \"special characters\".\n\tfor ( let i = 0; i < stylesString.length; i++ ) {\n\t\tconst char = stylesString.charAt( i );\n\n\t\tif ( quoteType === null ) {\n\t\t\t// No quote found yet or last found quote was a closing quote.\n\t\t\tswitch ( char ) {\n\t\t\t\tcase ':':\n\t\t\t\t\t// Most of time colon means that property name just ended.\n\t\t\t\t\t// Sometimes however `:` is found inside property value (for example in background image url).\n\t\t\t\t\tif ( !propertyName ) {\n\t\t\t\t\t\t// Treat this as end of property only if property name is not already saved.\n\t\t\t\t\t\t// Save property name.\n\t\t\t\t\t\tpropertyName = stylesString.substr( propertyNameStart, i - propertyNameStart );\n\t\t\t\t\t\t// Save this point as the start of property value.\n\t\t\t\t\t\tpropertyValueStart = i + 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase '\"':\n\t\t\t\tcase '\\'':\n\t\t\t\t\t// Opening quote found (this is an opening quote, because `quoteType` is `null`).\n\t\t\t\t\tquoteType = char;\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ';': {\n\t\t\t\t\t// Property value just ended.\n\t\t\t\t\t// Use previously stored property value start to obtain property value.\n\t\t\t\t\tconst propertyValue = stylesString.substr( propertyValueStart, i - propertyValueStart );\n\n\t\t\t\t\tif ( propertyName ) {\n\t\t\t\t\t\t// Save parsed part.\n\t\t\t\t\t\tstylesMap.set( propertyName.trim(), propertyValue.trim() );\n\t\t\t\t\t}\n\n\t\t\t\t\tpropertyName = null;\n\n\t\t\t\t\t// Save this point as property name start. Property name starts immediately after previous property value ends.\n\t\t\t\t\tpropertyNameStart = i + 1;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( char === quoteType ) {\n\t\t\t// If a quote char is found and it is a closing quote, mark this fact by `null`-ing `quoteType`.\n\t\t\tquoteType = null;\n\t\t}\n\t}\n}\n\n// Parses class attribute and puts all classes into classes set.\n// Classes set s cleared before insertion.\n//\n// @param {Set.<String>} classesSet Set to insert parsed classes.\n// @param {String} classesString String with classes to parse.\nfunction parseClasses( classesSet, classesString ) {\n\tconst classArray = classesString.split( /\\s+/ );\n\tclassesSet.clear();\n\tclassArray.forEach( name => classesSet.add( name ) );\n}\n\n// Converts strings to Text and non-iterables to arrays.\n//\n// @param {String|module:engine/view/item~Item|Iterable.<String|module:engine/view/item~Item>}\n// @returns {Iterable.<module:engine/view/node~Node>}\nfunction normalize( nodes ) {\n\t// Separate condition because string is iterable.\n\tif ( typeof nodes == 'string' ) {\n\t\treturn [ new Text( nodes ) ];\n\t}\n\n\tif ( !isIterable( nodes ) ) {\n\t\tnodes = [ nodes ];\n\t}\n\n\t// Array.from to enable .map() on non-arrays.\n\treturn Array.from( nodes )\n\t\t.map( node => {\n\t\t\tif ( typeof node == 'string' ) {\n\t\t\t\treturn new Text( node );\n\t\t\t}\n\n\t\t\tif ( node instanceof TextProxy ) {\n\t\t\t\treturn new Text( node.data );\n\t\t\t}\n\n\t\t\treturn node;\n\t\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/containerelement\n */\n\nimport Element from './element';\n\n/**\n * Containers are elements which define document structure. They define boundaries for\n * {@link module:engine/view/attributeelement~AttributeElement attributes}. They are mostly used for block elements like `<p>` or `<div>`.\n *\n * Editing engine does not define a fixed HTML DTD. This is why a feature developer needs to choose between various\n * types (container element, {@link module:engine/view/attributeelement~AttributeElement attribute element},\n * {@link module:engine/view/emptyelement~EmptyElement empty element}, etc) when developing a feature.\n *\n * The container element should be your default choice when writing a converter, unless:\n *\n * * this element represents a model text attribute (then use {@link module:engine/view/attributeelement~AttributeElement}),\n * * this is an empty element like `<img>` (then use {@link module:engine/view/emptyelement~EmptyElement}),\n * * this is a root element,\n * * this is a nested editable element (then use {@link module:engine/view/editableelement~EditableElement}).\n *\n * To create a new container element instance use the\n * {@link module:engine/view/downcastwriter~DowncastWriter#createContainerElement `DowncastWriter#createContainerElement()`}\n * method.\n *\n * @extends module:engine/view/element~Element\n */\nexport default class ContainerElement extends Element {\n\t/**\n\t * Creates a container element.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#createContainerElement\n\t * @see module:engine/view/element~Element\n\t * @protected\n\t */\n\tconstructor( name, attrs, children ) {\n\t\tsuper( name, attrs, children );\n\n\t\t/**\n\t\t * Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.\n\t\t *\n\t\t * @method #getFillerOffset\n\t\t * @returns {Number|null} Block filler offset or `null` if block filler is not needed.\n\t\t */\n\t\tthis.getFillerOffset = getFillerOffset;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tcontainerElement.is( 'containerElement' ); // -> true\n\t *\t\tcontainerElement.is( 'element' ); // -> true\n\t *\t\tcontainerElement.is( 'node' ); // -> true\n\t *\t\tcontainerElement.is( 'view:containerElement' ); // -> true\n\t *\t\tcontainerElement.is( 'view:element' ); // -> true\n\t *\t\tcontainerElement.is( 'view:node' ); // -> true\n\t *\n\t *\t\tcontainerElement.is( 'model:element' ); // -> false\n\t *\t\tcontainerElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is a container element, you can also check its\n\t * {@link module:engine/view/containerelement~ContainerElement#name name}:\n\t *\n\t *\t\tcontainerElement.is( 'div' ); // -> true if this is a div container element\n\t *\t\tcontainerElement.is( 'contaienrElement', 'div' ); // -> same as above\n\t *\t\ttext.is( 'div' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tconst cutType = type && type.replace( /^view:/, '' );\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'containerElement' || super.is( type );\n\t\t} else {\n\t\t\treturn ( cutType == 'containerElement' && name == this.name ) || super.is( type, name );\n\t\t}\n\t}\n}\n\n/**\n * Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.\n *\n * @returns {Number|null} Block filler offset or `null` if block filler is not needed.\n */\nexport function getFillerOffset() {\n\tconst children = [ ...this.getChildren() ];\n\tconst lastChild = children[ this.childCount - 1 ];\n\n\t// Block filler is required after a `<br>` if it's the last element in its container. See #1422.\n\tif ( lastChild && lastChild.is( 'element', 'br' ) ) {\n\t\treturn this.childCount;\n\t}\n\n\tfor ( const child of children ) {\n\t\t// If there's any non-UI element – don't render the bogus.\n\t\tif ( !child.is( 'uiElement' ) ) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t// If there are only UI elements – render the bogus at the end of the element.\n\treturn this.childCount;\n}\n","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nexport default identity;\n","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nexport default apply;\n","import apply from './_apply.js';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nexport default overRest;\n","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nexport default constant;\n","import constant from './constant.js';\nimport defineProperty from './_defineProperty.js';\nimport identity from './identity.js';\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nexport default baseSetToString;\n","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nexport default shortOut;\n","import baseSetToString from './_baseSetToString.js';\nimport shortOut from './_shortOut.js';\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nexport default setToString;\n","import identity from './identity.js';\nimport overRest from './_overRest.js';\nimport setToString from './_setToString.js';\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nexport default baseRest;\n","import eq from './eq.js';\nimport isArrayLike from './isArrayLike.js';\nimport isIndex from './_isIndex.js';\nimport isObject from './isObject.js';\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nexport default isIterateeCall;\n","import baseRest from './_baseRest.js';\nimport isIterateeCall from './_isIterateeCall.js';\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\nexport default createAssigner;\n","import copyObject from './_copyObject.js';\nimport createAssigner from './_createAssigner.js';\nimport keysIn from './keysIn.js';\n\n/**\n * This method is like `_.assign` except that it iterates over own and\n * inherited source properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extend\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assign\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assignIn({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }\n */\nvar assignIn = createAssigner(function(object, source) {\n copyObject(source, keysIn(source), object);\n});\n\nexport default assignIn;\n","/**\n * @license Copyright (c) 2003-2019, 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/observablemixin\n */\n\nimport EmitterMixin from './emittermixin';\nimport CKEditorError from './ckeditorerror';\nimport { extend, isObject } from 'lodash-es';\n\nconst observablePropertiesSymbol = Symbol( 'observableProperties' );\nconst boundObservablesSymbol = Symbol( 'boundObservables' );\nconst boundPropertiesSymbol = Symbol( 'boundProperties' );\n\n/**\n * Mixin that injects the \"observable properties\" and data binding functionality described in the\n * {@link ~Observable} interface.\n *\n * Read more about the concept of observables in the:\n * * {@glink framework/guides/architecture/core-editor-architecture#event-system-and-observables \"Event system and observables\"}\n * section of the {@glink framework/guides/architecture/core-editor-architecture \"Core editor architecture\"} guide,\n * * {@glink framework/guides/deep-dive/observables \"Observables\" deep dive} guide.\n *\n * @mixin ObservableMixin\n * @mixes module:utils/emittermixin~EmitterMixin\n * @implements module:utils/observablemixin~Observable\n */\nconst ObservableMixin = {\n\t/**\n\t * @inheritDoc\n\t */\n\tset( name, value ) {\n\t\t// If the first parameter is an Object, iterate over its properties.\n\t\tif ( isObject( name ) ) {\n\t\t\tObject.keys( name ).forEach( property => {\n\t\t\t\tthis.set( property, name[ property ] );\n\t\t\t}, this );\n\n\t\t\treturn;\n\t\t}\n\n\t\tinitObservable( this );\n\n\t\tconst properties = this[ observablePropertiesSymbol ];\n\n\t\tif ( ( name in this ) && !properties.has( name ) ) {\n\t\t\t/**\n\t\t\t * Cannot override an existing property.\n\t\t\t *\n\t\t\t * This error is thrown when trying to {@link ~Observable#set set} an property with\n\t\t\t * a name of an already existing property. For example:\n\t\t\t *\n\t\t\t *\t\tlet observable = new Model();\n\t\t\t *\t\tobservable.property = 1;\n\t\t\t *\t\tobservable.set( 'property', 2 );\t\t\t// throws\n\t\t\t *\n\t\t\t *\t\tobservable.set( 'property', 1 );\n\t\t\t *\t\tobservable.set( 'property', 2 );\t\t\t// ok, because this is an existing property.\n\t\t\t *\n\t\t\t * @error observable-set-cannot-override\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'observable-set-cannot-override: Cannot override an existing property.', this );\n\t\t}\n\n\t\tObject.defineProperty( this, name, {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\n\t\t\tget() {\n\t\t\t\treturn properties.get( name );\n\t\t\t},\n\n\t\t\tset( value ) {\n\t\t\t\tconst oldValue = properties.get( name );\n\n\t\t\t\t// Fire `set` event before the new value will be set to make it possible\n\t\t\t\t// to override observable property without affecting `change` event.\n\t\t\t\t// See https://github.com/ckeditor/ckeditor5-utils/issues/171.\n\t\t\t\tlet newValue = this.fire( 'set:' + name, name, value, oldValue );\n\n\t\t\t\tif ( newValue === undefined ) {\n\t\t\t\t\tnewValue = value;\n\t\t\t\t}\n\n\t\t\t\t// Allow undefined as an initial value like A.define( 'x', undefined ) (#132).\n\t\t\t\t// Note: When properties map has no such own property, then its value is undefined.\n\t\t\t\tif ( oldValue !== newValue || !properties.has( name ) ) {\n\t\t\t\t\tproperties.set( name, newValue );\n\t\t\t\t\tthis.fire( 'change:' + name, name, newValue, oldValue );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\tthis[ name ] = value;\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tbind( ...bindProperties ) {\n\t\tif ( !bindProperties.length || !isStringArray( bindProperties ) ) {\n\t\t\t/**\n\t\t\t * All properties must be strings.\n\t\t\t *\n\t\t\t * @error observable-bind-wrong-properties\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'observable-bind-wrong-properties: All properties must be strings.', this );\n\t\t}\n\n\t\tif ( ( new Set( bindProperties ) ).size !== bindProperties.length ) {\n\t\t\t/**\n\t\t\t * Properties must be unique.\n\t\t\t *\n\t\t\t * @error observable-bind-duplicate-properties\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'observable-bind-duplicate-properties: Properties must be unique.', this );\n\t\t}\n\n\t\tinitObservable( this );\n\n\t\tconst boundProperties = this[ boundPropertiesSymbol ];\n\n\t\tbindProperties.forEach( propertyName => {\n\t\t\tif ( boundProperties.has( propertyName ) ) {\n\t\t\t\t/**\n\t\t\t\t * Cannot bind the same property more that once.\n\t\t\t\t *\n\t\t\t\t * @error observable-bind-rebind\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'observable-bind-rebind: Cannot bind the same property more that once.', this );\n\t\t\t}\n\t\t} );\n\n\t\tconst bindings = new Map();\n\n\t\t// @typedef {Object} Binding\n\t\t// @property {Array} property Property which is bound.\n\t\t// @property {Array} to Array of observable–property components of the binding (`{ observable: ..., property: .. }`).\n\t\t// @property {Array} callback A function which processes `to` components.\n\t\tbindProperties.forEach( a => {\n\t\t\tconst binding = { property: a, to: [] };\n\n\t\t\tboundProperties.set( a, binding );\n\t\t\tbindings.set( a, binding );\n\t\t} );\n\n\t\t// @typedef {Object} BindChain\n\t\t// @property {Function} to See {@link ~ObservableMixin#_bindTo}.\n\t\t// @property {Function} toMany See {@link ~ObservableMixin#_bindToMany}.\n\t\t// @property {module:utils/observablemixin~Observable} _observable The observable which initializes the binding.\n\t\t// @property {Array} _bindProperties Array of `_observable` properties to be bound.\n\t\t// @property {Array} _to Array of `to()` observable–properties (`{ observable: toObservable, properties: ...toProperties }`).\n\t\t// @property {Map} _bindings Stores bindings to be kept in\n\t\t// {@link ~ObservableMixin#_boundProperties}/{@link ~ObservableMixin#_boundObservables}\n\t\t// initiated in this binding chain.\n\t\treturn {\n\t\t\tto: bindTo,\n\t\t\ttoMany: bindToMany,\n\n\t\t\t_observable: this,\n\t\t\t_bindProperties: bindProperties,\n\t\t\t_to: [],\n\t\t\t_bindings: bindings\n\t\t};\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tunbind( ...unbindProperties ) {\n\t\t// Nothing to do here if not inited yet.\n\t\tif ( !( observablePropertiesSymbol in this ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst boundProperties = this[ boundPropertiesSymbol ];\n\t\tconst boundObservables = this[ boundObservablesSymbol ];\n\n\t\tif ( unbindProperties.length ) {\n\t\t\tif ( !isStringArray( unbindProperties ) ) {\n\t\t\t\t/**\n\t\t\t\t * Properties must be strings.\n\t\t\t\t *\n\t\t\t\t * @error observable-unbind-wrong-properties\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'observable-unbind-wrong-properties: Properties must be strings.', this );\n\t\t\t}\n\n\t\t\tunbindProperties.forEach( propertyName => {\n\t\t\t\tconst binding = boundProperties.get( propertyName );\n\n\t\t\t\t// Nothing to do if the binding is not defined\n\t\t\t\tif ( !binding ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet toObservable, toProperty, toProperties, toPropertyBindings;\n\n\t\t\t\tbinding.to.forEach( to => {\n\t\t\t\t\t// TODO: ES6 destructuring.\n\t\t\t\t\ttoObservable = to[ 0 ];\n\t\t\t\t\ttoProperty = to[ 1 ];\n\t\t\t\t\ttoProperties = boundObservables.get( toObservable );\n\t\t\t\t\ttoPropertyBindings = toProperties[ toProperty ];\n\n\t\t\t\t\ttoPropertyBindings.delete( binding );\n\n\t\t\t\t\tif ( !toPropertyBindings.size ) {\n\t\t\t\t\t\tdelete toProperties[ toProperty ];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !Object.keys( toProperties ).length ) {\n\t\t\t\t\t\tboundObservables.delete( toObservable );\n\t\t\t\t\t\tthis.stopListening( toObservable, 'change' );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tboundProperties.delete( propertyName );\n\t\t\t} );\n\t\t} else {\n\t\t\tboundObservables.forEach( ( bindings, boundObservable ) => {\n\t\t\t\tthis.stopListening( boundObservable, 'change' );\n\t\t\t} );\n\n\t\t\tboundObservables.clear();\n\t\t\tboundProperties.clear();\n\t\t}\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdecorate( methodName ) {\n\t\tconst originalMethod = this[ methodName ];\n\n\t\tif ( !originalMethod ) {\n\t\t\t/**\n\t\t\t * Cannot decorate an undefined method.\n\t\t\t *\n\t\t\t * @error observablemixin-cannot-decorate-undefined\n\t\t\t * @param {Object} object The object which method should be decorated.\n\t\t\t * @param {String} methodName Name of the method which does not exist.\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'observablemixin-cannot-decorate-undefined: Cannot decorate an undefined method.',\n\t\t\t\tthis,\n\t\t\t\t{ object: this, methodName }\n\t\t\t);\n\t\t}\n\n\t\tthis.on( methodName, ( evt, args ) => {\n\t\t\tevt.return = originalMethod.apply( this, args );\n\t\t} );\n\n\t\tthis[ methodName ] = function( ...args ) {\n\t\t\treturn this.fire( methodName, args );\n\t\t};\n\t}\n};\n\nextend( ObservableMixin, EmitterMixin );\n\nexport default ObservableMixin;\n\n// Init symbol properties needed to for the observable mechanism to work.\n//\n// @private\n// @param {module:utils/observablemixin~ObservableMixin} observable\nfunction initObservable( observable ) {\n\t// Do nothing if already inited.\n\tif ( observablePropertiesSymbol in observable ) {\n\t\treturn;\n\t}\n\n\t// The internal hash containing the observable's state.\n\t//\n\t// @private\n\t// @type {Map}\n\tObject.defineProperty( observable, observablePropertiesSymbol, {\n\t\tvalue: new Map()\n\t} );\n\n\t// Map containing bindings to external observables. It shares the binding objects\n\t// (`{ observable: A, property: 'a', to: ... }`) with {@link module:utils/observablemixin~ObservableMixin#_boundProperties} and\n\t// it is used to observe external observables to update own properties accordingly.\n\t// See {@link module:utils/observablemixin~ObservableMixin#bind}.\n\t//\n\t//\t\tA.bind( 'a', 'b', 'c' ).to( B, 'x', 'y', 'x' );\n\t//\t\tconsole.log( A._boundObservables );\n\t//\n\t//\t\t\tMap( {\n\t//\t\t\t\tB: {\n\t//\t\t\t\t\tx: Set( [\n\t//\t\t\t\t\t\t{ observable: A, property: 'a', to: [ [ B, 'x' ] ] },\n\t//\t\t\t\t\t\t{ observable: A, property: 'c', to: [ [ B, 'x' ] ] }\n\t//\t\t\t\t\t] ),\n\t//\t\t\t\t\ty: Set( [\n\t//\t\t\t\t\t\t{ observable: A, property: 'b', to: [ [ B, 'y' ] ] },\n\t//\t\t\t\t\t] )\n\t//\t\t\t\t}\n\t//\t\t\t} )\n\t//\n\t//\t\tA.bind( 'd' ).to( B, 'z' ).to( C, 'w' ).as( callback );\n\t//\t\tconsole.log( A._boundObservables );\n\t//\n\t//\t\t\tMap( {\n\t//\t\t\t\tB: {\n\t//\t\t\t\t\tx: Set( [\n\t//\t\t\t\t\t\t{ observable: A, property: 'a', to: [ [ B, 'x' ] ] },\n\t//\t\t\t\t\t\t{ observable: A, property: 'c', to: [ [ B, 'x' ] ] }\n\t//\t\t\t\t\t] ),\n\t//\t\t\t\t\ty: Set( [\n\t//\t\t\t\t\t\t{ observable: A, property: 'b', to: [ [ B, 'y' ] ] },\n\t//\t\t\t\t\t] ),\n\t//\t\t\t\t\tz: Set( [\n\t//\t\t\t\t\t\t{ observable: A, property: 'd', to: [ [ B, 'z' ], [ C, 'w' ] ], callback: callback }\n\t//\t\t\t\t\t] )\n\t//\t\t\t\t},\n\t//\t\t\t\tC: {\n\t//\t\t\t\t\tw: Set( [\n\t//\t\t\t\t\t\t{ observable: A, property: 'd', to: [ [ B, 'z' ], [ C, 'w' ] ], callback: callback }\n\t//\t\t\t\t\t] )\n\t//\t\t\t\t}\n\t//\t\t\t} )\n\t//\n\t// @private\n\t// @type {Map}\n\tObject.defineProperty( observable, boundObservablesSymbol, {\n\t\tvalue: new Map()\n\t} );\n\n\t// Object that stores which properties of this observable are bound and how. It shares\n\t// the binding objects (`{ observable: A, property: 'a', to: ... }`) with\n\t// {@link module:utils/observablemixin~ObservableMixin#_boundObservables}. This data structure is\n\t// a reverse of {@link module:utils/observablemixin~ObservableMixin#_boundObservables} and it is helpful for\n\t// {@link module:utils/observablemixin~ObservableMixin#unbind}.\n\t//\n\t// See {@link module:utils/observablemixin~ObservableMixin#bind}.\n\t//\n\t//\t\tA.bind( 'a', 'b', 'c' ).to( B, 'x', 'y', 'x' );\n\t//\t\tconsole.log( A._boundProperties );\n\t//\n\t//\t\t\tMap( {\n\t//\t\t\t\ta: { observable: A, property: 'a', to: [ [ B, 'x' ] ] },\n\t//\t\t\t\tb: { observable: A, property: 'b', to: [ [ B, 'y' ] ] },\n\t//\t\t\t\tc: { observable: A, property: 'c', to: [ [ B, 'x' ] ] }\n\t//\t\t\t} )\n\t//\n\t//\t\tA.bind( 'd' ).to( B, 'z' ).to( C, 'w' ).as( callback );\n\t//\t\tconsole.log( A._boundProperties );\n\t//\n\t//\t\t\tMap( {\n\t//\t\t\t\ta: { observable: A, property: 'a', to: [ [ B, 'x' ] ] },\n\t//\t\t\t\tb: { observable: A, property: 'b', to: [ [ B, 'y' ] ] },\n\t//\t\t\t\tc: { observable: A, property: 'c', to: [ [ B, 'x' ] ] },\n\t//\t\t\t\td: { observable: A, property: 'd', to: [ [ B, 'z' ], [ C, 'w' ] ], callback: callback }\n\t//\t\t\t} )\n\t//\n\t// @private\n\t// @type {Map}\n\tObject.defineProperty( observable, boundPropertiesSymbol, {\n\t\tvalue: new Map()\n\t} );\n}\n\n// A chaining for {@link module:utils/observablemixin~ObservableMixin#bind} providing `.to()` interface.\n//\n// @private\n// @param {...[Observable|String|Function]} args Arguments of the `.to( args )` binding.\nfunction bindTo( ...args ) {\n\tconst parsedArgs = parseBindToArgs( ...args );\n\tconst bindingsKeys = Array.from( this._bindings.keys() );\n\tconst numberOfBindings = bindingsKeys.length;\n\n\t// Eliminate A.bind( 'x' ).to( B, C )\n\tif ( !parsedArgs.callback && parsedArgs.to.length > 1 ) {\n\t\t/**\n\t\t * Binding multiple observables only possible with callback.\n\t\t *\n\t\t * @error observable-bind-no-callback\n\t\t */\n\t\tthrow new CKEditorError(\n\t\t\t'observable-bind-to-no-callback: Binding multiple observables only possible with callback.',\n\t\t\tthis\n\t\t);\n\t}\n\n\t// Eliminate A.bind( 'x', 'y' ).to( B, callback )\n\tif ( numberOfBindings > 1 && parsedArgs.callback ) {\n\t\t/**\n\t\t * Cannot bind multiple properties and use a callback in one binding.\n\t\t *\n\t\t * @error observable-bind-to-extra-callback\n\t\t */\n\t\tthrow new CKEditorError(\n\t\t\t'observable-bind-to-extra-callback: Cannot bind multiple properties and use a callback in one binding.',\n\t\t\tthis\n\t\t);\n\t}\n\n\tparsedArgs.to.forEach( to => {\n\t\t// Eliminate A.bind( 'x', 'y' ).to( B, 'a' )\n\t\tif ( to.properties.length && to.properties.length !== numberOfBindings ) {\n\t\t\t/**\n\t\t\t * The number of properties must match.\n\t\t\t *\n\t\t\t * @error observable-bind-to-properties-length\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'observable-bind-to-properties-length: The number of properties must match.', this );\n\t\t}\n\n\t\t// When no to.properties specified, observing source properties instead i.e.\n\t\t// A.bind( 'x', 'y' ).to( B ) -> Observe B.x and B.y\n\t\tif ( !to.properties.length ) {\n\t\t\tto.properties = this._bindProperties;\n\t\t}\n\t} );\n\n\tthis._to = parsedArgs.to;\n\n\t// Fill {@link BindChain#_bindings} with callback. When the callback is set there's only one binding.\n\tif ( parsedArgs.callback ) {\n\t\tthis._bindings.get( bindingsKeys[ 0 ] ).callback = parsedArgs.callback;\n\t}\n\n\tattachBindToListeners( this._observable, this._to );\n\n\t// Update observable._boundProperties and observable._boundObservables.\n\tupdateBindToBound( this );\n\n\t// Set initial values of bound properties.\n\tthis._bindProperties.forEach( propertyName => {\n\t\tupdateBoundObservableProperty( this._observable, propertyName );\n\t} );\n}\n\n// Binds to an attribute in a set of iterable observables.\n//\n// @private\n// @param {Array.<Observable>} observables\n// @param {String} attribute\n// @param {Function} callback\nfunction bindToMany( observables, attribute, callback ) {\n\tif ( this._bindings.size > 1 ) {\n\t\t/**\n\t\t * Binding one attribute to many observables only possible with one attribute.\n\t\t *\n\t\t * @error observable-bind-to-many-not-one-binding\n\t\t */\n\t\tthrow new CKEditorError( 'observable-bind-to-many-not-one-binding: Cannot bind multiple properties with toMany().', this );\n\t}\n\n\tthis.to(\n\t\t// Bind to #attribute of each observable...\n\t\t...getBindingTargets( observables, attribute ),\n\t\t// ...using given callback to parse attribute values.\n\t\tcallback\n\t);\n}\n\n// Returns an array of binding components for\n// {@link Observable#bind} from a set of iterable observables.\n//\n// @param {Array.<Observable>} observables\n// @param {String} attribute\n// @returns {Array.<String|Observable>}\nfunction getBindingTargets( observables, attribute ) {\n\tconst observableAndAttributePairs = observables.map( observable => [ observable, attribute ] );\n\n\t// Merge pairs to one-dimension array of observables and attributes.\n\treturn Array.prototype.concat.apply( [], observableAndAttributePairs );\n}\n\n// Check if all entries of the array are of `String` type.\n//\n// @private\n// @param {Array} arr An array to be checked.\n// @returns {Boolean}\nfunction isStringArray( arr ) {\n\treturn arr.every( a => typeof a == 'string' );\n}\n\n// Parses and validates {@link Observable#bind}`.to( args )` arguments and returns\n// an object with a parsed structure. For example\n//\n//\t\tA.bind( 'x' ).to( B, 'a', C, 'b', call );\n//\n// becomes\n//\n//\t\t{\n//\t\t\tto: [\n//\t\t\t\t{ observable: B, properties: [ 'a' ] },\n//\t\t\t\t{ observable: C, properties: [ 'b' ] },\n//\t\t\t],\n//\t\t\tcallback: call\n// \t\t}\n//\n// @private\n// @param {...*} args Arguments of {@link Observable#bind}`.to( args )`.\n// @returns {Object}\nfunction parseBindToArgs( ...args ) {\n\t// Eliminate A.bind( 'x' ).to()\n\tif ( !args.length ) {\n\t\t/**\n\t\t * Invalid argument syntax in `to()`.\n\t\t *\n\t\t * @error observable-bind-to-parse-error\n\t\t */\n\t\tthrow new CKEditorError( 'observable-bind-to-parse-error: Invalid argument syntax in `to()`.', null );\n\t}\n\n\tconst parsed = { to: [] };\n\tlet lastObservable;\n\n\tif ( typeof args[ args.length - 1 ] == 'function' ) {\n\t\tparsed.callback = args.pop();\n\t}\n\n\targs.forEach( a => {\n\t\tif ( typeof a == 'string' ) {\n\t\t\tlastObservable.properties.push( a );\n\t\t} else if ( typeof a == 'object' ) {\n\t\t\tlastObservable = { observable: a, properties: [] };\n\t\t\tparsed.to.push( lastObservable );\n\t\t} else {\n\t\t\tthrow new CKEditorError( 'observable-bind-to-parse-error: Invalid argument syntax in `to()`.', null );\n\t\t}\n\t} );\n\n\treturn parsed;\n}\n\n// Synchronizes {@link module:utils/observablemixin#_boundObservables} with {@link Binding}.\n//\n// @private\n// @param {Binding} binding A binding to store in {@link Observable#_boundObservables}.\n// @param {Observable} toObservable A observable, which is a new component of `binding`.\n// @param {String} toPropertyName A name of `toObservable`'s property, a new component of the `binding`.\nfunction updateBoundObservables( observable, binding, toObservable, toPropertyName ) {\n\tconst boundObservables = observable[ boundObservablesSymbol ];\n\tconst bindingsToObservable = boundObservables.get( toObservable );\n\tconst bindings = bindingsToObservable || {};\n\n\tif ( !bindings[ toPropertyName ] ) {\n\t\tbindings[ toPropertyName ] = new Set();\n\t}\n\n\t// Pass the binding to a corresponding Set in `observable._boundObservables`.\n\tbindings[ toPropertyName ].add( binding );\n\n\tif ( !bindingsToObservable ) {\n\t\tboundObservables.set( toObservable, bindings );\n\t}\n}\n\n// Synchronizes {@link Observable#_boundProperties} and {@link Observable#_boundObservables}\n// with {@link BindChain}.\n//\n// Assuming the following binding being created\n//\n// \t\tA.bind( 'a', 'b' ).to( B, 'x', 'y' );\n//\n// the following bindings were initialized by {@link Observable#bind} in {@link BindChain#_bindings}:\n//\n// \t\t{\n// \t\t\ta: { observable: A, property: 'a', to: [] },\n// \t\t\tb: { observable: A, property: 'b', to: [] },\n// \t\t}\n//\n// Iterate over all bindings in this chain and fill their `to` properties with\n// corresponding to( ... ) arguments (components of the binding), so\n//\n// \t\t{\n// \t\t\ta: { observable: A, property: 'a', to: [ B, 'x' ] },\n// \t\t\tb: { observable: A, property: 'b', to: [ B, 'y' ] },\n// \t\t}\n//\n// Then update the structure of {@link Observable#_boundObservables} with updated\n// binding, so it becomes:\n//\n// \t\tMap( {\n// \t\t\tB: {\n// \t\t\t\tx: Set( [\n// \t\t\t\t\t{ observable: A, property: 'a', to: [ [ B, 'x' ] ] }\n// \t\t\t\t] ),\n// \t\t\t\ty: Set( [\n// \t\t\t\t\t{ observable: A, property: 'b', to: [ [ B, 'y' ] ] },\n// \t\t\t\t] )\n//\t\t\t}\n// \t\t} )\n//\n// @private\n// @param {BindChain} chain The binding initialized by {@link Observable#bind}.\nfunction updateBindToBound( chain ) {\n\tlet toProperty;\n\n\tchain._bindings.forEach( ( binding, propertyName ) => {\n\t\t// Note: For a binding without a callback, this will run only once\n\t\t// like in A.bind( 'x', 'y' ).to( B, 'a', 'b' )\n\t\t// TODO: ES6 destructuring.\n\t\tchain._to.forEach( to => {\n\t\t\ttoProperty = to.properties[ binding.callback ? 0 : chain._bindProperties.indexOf( propertyName ) ];\n\n\t\t\tbinding.to.push( [ to.observable, toProperty ] );\n\t\t\tupdateBoundObservables( chain._observable, binding, to.observable, toProperty );\n\t\t} );\n\t} );\n}\n\n// Updates an property of a {@link Observable} with a value\n// determined by an entry in {@link Observable#_boundProperties}.\n//\n// @private\n// @param {Observable} observable A observable which property is to be updated.\n// @param {String} propertyName An property to be updated.\nfunction updateBoundObservableProperty( observable, propertyName ) {\n\tconst boundProperties = observable[ boundPropertiesSymbol ];\n\tconst binding = boundProperties.get( propertyName );\n\tlet propertyValue;\n\n\t// When a binding with callback is created like\n\t//\n\t// \t\tA.bind( 'a' ).to( B, 'b', C, 'c', callback );\n\t//\n\t// collect B.b and C.c, then pass them to callback to set A.a.\n\tif ( binding.callback ) {\n\t\tpropertyValue = binding.callback.apply( observable, binding.to.map( to => to[ 0 ][ to[ 1 ] ] ) );\n\t} else {\n\t\tpropertyValue = binding.to[ 0 ];\n\t\tpropertyValue = propertyValue[ 0 ][ propertyValue[ 1 ] ];\n\t}\n\n\tif ( observable.hasOwnProperty( propertyName ) ) {\n\t\tobservable[ propertyName ] = propertyValue;\n\t} else {\n\t\tobservable.set( propertyName, propertyValue );\n\t}\n}\n\n// Starts listening to changes in {@link BindChain._to} observables to update\n// {@link BindChain._observable} {@link BindChain._bindProperties}. Also sets the\n// initial state of {@link BindChain._observable}.\n//\n// @private\n// @param {BindChain} chain The chain initialized by {@link Observable#bind}.\nfunction attachBindToListeners( observable, toBindings ) {\n\ttoBindings.forEach( to => {\n\t\tconst boundObservables = observable[ boundObservablesSymbol ];\n\t\tlet bindings;\n\n\t\t// If there's already a chain between the observables (`observable` listens to\n\t\t// `to.observable`), there's no need to create another `change` event listener.\n\t\tif ( !boundObservables.get( to.observable ) ) {\n\t\t\tobservable.listenTo( to.observable, 'change', ( evt, propertyName ) => {\n\t\t\t\tbindings = boundObservables.get( to.observable )[ propertyName ];\n\n\t\t\t\t// Note: to.observable will fire for any property change, react\n\t\t\t\t// to changes of properties which are bound only.\n\t\t\t\tif ( bindings ) {\n\t\t\t\t\tbindings.forEach( binding => {\n\t\t\t\t\t\tupdateBoundObservableProperty( observable, binding.property );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t} );\n}\n\n/**\n * Interface which adds \"observable properties\" and data binding functionality.\n *\n * Can be easily implemented by a class by mixing the {@link module:utils/observablemixin~ObservableMixin} mixin.\n *\n * Read more about the usage of this interface in the:\n * * {@glink framework/guides/architecture/core-editor-architecture#event-system-and-observables \"Event system and observables\"}\n * section of the {@glink framework/guides/architecture/core-editor-architecture \"Core editor architecture\"} guide,\n * * {@glink framework/guides/deep-dive/observables \"Observables\" deep dive} guide.\n *\n * @interface Observable\n * @extends module:utils/emittermixin~Emitter\n */\n\n/**\n * Fired when a property changed value.\n *\n *\t\tobservable.set( 'prop', 1 );\n *\n *\t\tobservable.on( 'change:prop', ( evt, propertyName, newValue, oldValue ) => {\n *\t\t\tconsole.log( `${ propertyName } has changed from ${ oldValue } to ${ newValue }` );\n *\t\t} );\n *\n *\t\tobservable.prop = 2; // -> 'prop has changed from 1 to 2'\n *\n * @event change:{property}\n * @param {String} name The property name.\n * @param {*} value The new property value.\n * @param {*} oldValue The previous property value.\n */\n\n/**\n * Fired when a property value is going to be set but is not set yet (before the `change` event is fired).\n *\n * You can control the final value of the property by using\n * the {@link module:utils/eventinfo~EventInfo#return event's `return` property}.\n *\n *\t\tobservable.set( 'prop', 1 );\n *\n *\t\tobservable.on( 'set:prop', ( evt, propertyName, newValue, oldValue ) => {\n *\t\t\tconsole.log( `Value is going to be changed from ${ oldValue } to ${ newValue }` );\n *\t\t\tconsole.log( `Current property value is ${ observable[ propertyName ] }` );\n *\n *\t\t\t// Let's override the value.\n *\t\t\tevt.return = 3;\n *\t\t} );\n *\n *\t\tobservable.on( 'change:prop', ( evt, propertyName, newValue, oldValue ) => {\n *\t\t\tconsole.log( `Value has changed from ${ oldValue } to ${ newValue }` );\n *\t\t} );\n *\n *\t\tobservable.prop = 2; // -> 'Value is going to be changed from 1 to 2'\n *\t\t // -> 'Current property value is 1'\n *\t\t // -> 'Value has changed from 1 to 3'\n *\n * **Note:** Event is fired even when the new value is the same as the old value.\n *\n * @event set:{property}\n * @param {String} name The property name.\n * @param {*} value The new property value.\n * @param {*} oldValue The previous property value.\n */\n\n/**\n * Creates and sets the value of an observable property of this object. Such an property becomes a part\n * of the state and is be observable.\n *\n * It accepts also a single object literal containing key/value pairs with properties to be set.\n *\n * This method throws the `observable-set-cannot-override` error if the observable instance already\n * have a property with the given property name. This prevents from mistakenly overriding existing\n * properties and methods, but means that `foo.set( 'bar', 1 )` may be slightly slower than `foo.bar = 1`.\n *\n * @method #set\n * @param {String|Object} name The property's name or object with `name=>value` pairs.\n * @param {*} [value] The property's value (if `name` was passed in the first parameter).\n */\n\n/**\n * Binds {@link #set observable properties} to other objects implementing the\n * {@link module:utils/observablemixin~Observable} interface.\n *\n * Read more in the {@glink framework/guides/deep-dive/observables#property-bindings dedicated guide}\n * covering the topic of property bindings with some additional examples.\n *\n * Consider two objects: a `button` and an associated `command` (both `Observable`).\n *\n * A simple property binding could be as follows:\n *\n *\t\tbutton.bind( 'isEnabled' ).to( command, 'isEnabled' );\n *\n * or even shorter:\n *\n *\t\tbutton.bind( 'isEnabled' ).to( command );\n *\n * which works in the following way:\n *\n * * `button.isEnabled` **instantly equals** `command.isEnabled`,\n * * whenever `command.isEnabled` changes, `button.isEnabled` will immediately reflect its value.\n *\n * **Note**: To release the binding, use {@link module:utils/observablemixin~Observable#unbind}.\n *\n * You can also \"rename\" the property in the binding by specifying the new name in the `to()` chain:\n *\n *\t\tbutton.bind( 'isEnabled' ).to( command, 'isWorking' );\n *\n * It is possible to bind more than one property at a time to shorten the code:\n *\n *\t\tbutton.bind( 'isEnabled', 'value' ).to( command );\n *\n * which corresponds to:\n *\n *\t\tbutton.bind( 'isEnabled' ).to( command );\n *\t\tbutton.bind( 'value' ).to( command );\n *\n * The binding can include more than one observable, combining multiple data sources in a custom callback:\n *\n *\t\tbutton.bind( 'isEnabled' ).to( command, 'isEnabled', ui, 'isVisible',\n *\t\t\t( isCommandEnabled, isUIVisible ) => isCommandEnabled && isUIVisible );\n *\n * It is also possible to bind to the same property in an array of observables.\n * To bind a `button` to multiple commands (also `Observables`) so that each and every one of them\n * must be enabled for the button to become enabled, use the following code:\n *\n *\t\tbutton.bind( 'isEnabled' ).toMany( [ commandA, commandB, commandC ], 'isEnabled',\n *\t\t\t( isAEnabled, isBEnabled, isCEnabled ) => isAEnabled && isBEnabled && isCEnabled );\n *\n * @method #bind\n * @param {...String} bindProperties Observable properties that will be bound to other observable(s).\n * @returns {Object} The bind chain with the `to()` and `toMany()` methods.\n */\n\n/**\n * Removes the binding created with {@link #bind}.\n *\n *\t\t// Removes the binding for the 'a' property.\n *\t\tA.unbind( 'a' );\n *\n *\t\t// Removes bindings for all properties.\n *\t\tA.unbind();\n *\n * @method #unbind\n * @param {...String} [unbindProperties] Observable properties to be unbound. All the bindings will\n * be released if no properties are provided.\n */\n\n/**\n * Turns the given methods of this object into event-based ones. This means that the new method will fire an event\n * (named after the method) and the original action will be plugged as a listener to that event.\n *\n * Read more in the {@glink framework/guides/deep-dive/observables#decorating-object-methods dedicated guide}\n * covering the topic of decorating methods with some additional examples.\n *\n * Decorating the method does not change its behavior (it only adds an event),\n * but it allows to modify it later on by listening to the method's event.\n *\n * For example, to cancel the method execution the event can be {@link module:utils/eventinfo~EventInfo#stop stopped}:\n *\n *\t\tclass Foo {\n *\t\t\tconstructor() {\n *\t\t\t\tthis.decorate( 'method' );\n *\t\t\t}\n *\n *\t\t\tmethod() {\n *\t\t\t\tconsole.log( 'called!' );\n *\t\t\t}\n *\t\t}\n *\n *\t\tconst foo = new Foo();\n *\t\tfoo.on( 'method', ( evt ) => {\n *\t\t\tevt.stop();\n *\t\t}, { priority: 'high' } );\n *\n *\t\tfoo.method(); // Nothing is logged.\n *\n *\n * **Note**: The high {@link module:utils/priorities~PriorityString priority} listener\n * has been used to execute this particular callback before the one which calls the original method\n * (which uses the \"normal\" priority).\n *\n * It is also possible to change the returned value:\n *\n *\t\tfoo.on( 'method', ( evt ) => {\n *\t\t\tevt.return = 'Foo!';\n *\t\t} );\n *\n *\t\tfoo.method(); // -> 'Foo'\n *\n * Finally, it is possible to access and modify the arguments the method is called with:\n *\n *\t\tmethod( a, b ) {\n *\t\t\tconsole.log( `${ a }, ${ b }` );\n *\t\t}\n *\n *\t\t// ...\n *\n *\t\tfoo.on( 'method', ( evt, args ) => {\n *\t\t\targs[ 0 ] = 3;\n *\n *\t\t\tconsole.log( args[ 1 ] ); // -> 2\n *\t\t}, { priority: 'high' } );\n *\n *\t\tfoo.method( 1, 2 ); // -> '3, 2'\n *\n * @method #decorate\n * @param {String} methodName Name of the method to decorate.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/editableelement\n */\n\nimport ContainerElement from './containerelement';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\n\nconst documentSymbol = Symbol( 'document' );\n\n/**\n * Editable element which can be a {@link module:engine/view/rooteditableelement~RootEditableElement root}\n * or nested editable area in the editor.\n *\n * Editable is automatically read-only when its {@link module:engine/view/document~Document Document} is read-only.\n *\n * The constructor of this class shouldn't be used directly. To create new `EditableElement` use the\n * {@link module:engine/view/downcastwriter~DowncastWriter#createEditableElement `downcastWriter#createEditableElement()`} method.\n *\n * @extends module:engine/view/containerelement~ContainerElement\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class EditableElement extends ContainerElement {\n\t/**\n\t * Creates an editable element.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#createEditableElement\n\t * @protected\n\t */\n\tconstructor( name, attrs, children ) {\n\t\tsuper( name, attrs, children );\n\n\t\t/**\n\t\t * Whether the editable is in read-write or read-only mode.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} module:engine/view/editableelement~EditableElement#isReadOnly\n\t\t */\n\t\tthis.set( 'isReadOnly', false );\n\n\t\t/**\n\t\t * Whether the editable is focused.\n\t\t *\n\t\t * This property updates when {@link module:engine/view/document~Document#isFocused document.isFocused} or view\n\t\t * selection is changed.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Boolean} module:engine/view/editableelement~EditableElement#isFocused\n\t\t */\n\t\tthis.set( 'isFocused', false );\n\n\t\t/**\n\t\t * The {@link module:engine/view/document~Document} which is an owner of this root.\n\t\t * Can only by set once.\n\t\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-editableelement-document-already-set`\n\t\t * when document is already set.\n\t\t *\n\t\t * @member {module:engine/view/document~Document} #document\n\t\t */\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\teditableElement.is( 'editableElement' ); // -> true\n\t *\t\teditableElement.is( 'element' ); // -> true\n\t *\t\teditableElement.is( 'node' ); // -> true\n\t *\t\teditableElement.is( 'view:editableElement' ); // -> true\n\t *\t\teditableElement.is( 'view:element' ); // -> true\n\t *\t\teditableElement.is( 'view:node' ); // -> true\n\t *\n\t *\t\teditableElement.is( 'model:element' ); // -> false\n\t *\t\teditableElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is an editbale element, you can also check its\n\t * {@link module:engine/view/editableelement~EditableElement#name name}:\n\t *\n\t *\t\teditableElement.is( 'div' ); // -> true if this is a div element\n\t *\t\teditableElement.is( 'editableElement', 'div' ); // -> same as above\n\t *\t\ttext.is( 'div' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tconst cutType = type && type.replace( /^view:/, '' );\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'editableElement' || super.is( type );\n\t\t} else {\n\t\t\treturn ( cutType == 'editableElement' && name == this.name ) || super.is( type, name );\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Returns document associated with the editable.\n\t *\n\t * @readonly\n\t * @returns {module:engine/view/document~Document}\n\t */\n\tget document() {\n\t\treturn this.getCustomProperty( documentSymbol );\n\t}\n\n\t/**\n\t * Sets document of this editable element.\n\t *\n\t * @protected\n\t * @param {module:engine/view/document~Document} document\n\t */\n\tset _document( document ) {\n\t\tif ( this.getCustomProperty( documentSymbol ) ) {\n\t\t\t/**\n\t\t\t * View document is already set. It can only be set once.\n\t\t\t *\n\t\t\t * @error view-editableelement-document-already-set\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-editableelement-document-already-set: View document is already set.', this );\n\t\t}\n\n\t\tthis._setCustomProperty( documentSymbol, document );\n\n\t\tthis.bind( 'isReadOnly' ).to( document );\n\n\t\tthis.bind( 'isFocused' ).to(\n\t\t\tdocument,\n\t\t\t'isFocused',\n\t\t\tisFocused => isFocused && document.selection.editableElement == this\n\t\t);\n\n\t\t// Update focus state based on selection changes.\n\t\tthis.listenTo( document.selection, 'change', () => {\n\t\t\tthis.isFocused = document.isFocused && document.selection.editableElement == this;\n\t\t} );\n\t}\n}\n\nmix( EditableElement, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/rooteditableelement\n */\n\nimport EditableElement from './editableelement';\n\nconst rootNameSymbol = Symbol( 'rootName' );\n\n/**\n * Class representing a single root in the data view. A root can be either {@link ~RootEditableElement#isReadOnly editable or read-only},\n * but in both cases it is called \"an editable\". Roots can contain other {@link module:engine/view/editableelement~EditableElement\n * editable elements} making them \"nested editables\".\n *\n * @extends module:engine/view/editableelement~EditableElement\n */\nexport default class RootEditableElement extends EditableElement {\n\t/**\n\t * Creates root editable element.\n\t *\n\t * @param {String} name Node name.\n\t */\n\tconstructor( name ) {\n\t\tsuper( name );\n\n\t\t/**\n\t\t * Name of this root inside {@link module:engine/view/document~Document} that is an owner of this root. If no\n\t\t * other name is set, `main` name is used.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.rootName = 'main';\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\trootEditableElement.is( 'rootEditableElement' ); // -> true\n\t *\t\trootEditableElement.is( 'editableElement' ); // -> true\n\t *\t\trootEditableElement.is( 'element' ); // -> true\n\t *\t\trootEditableElement.is( 'node' ); // -> true\n\t *\t\trootEditableElement.is( 'view:rootEditableElement' ); // -> true\n\t *\t\trootEditableElement.is( 'view:editableElement' ); // -> true\n\t *\t\trootEditableElement.is( 'view:element' ); // -> true\n\t *\t\trootEditableElement.is( 'view:node' ); // -> true\n\t *\n\t *\t\trootEditableElement.is( 'model:element' ); // -> false\n\t *\t\trootEditableElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is a root editbale element, you can also check its\n\t * {@link module:engine/view/rooteditableelement~RootEditableElement#name name}:\n\t *\n\t *\t\trootEditableElement.is( 'div' ); // -> true if this is a div root editable element\n\t *\t\trootEditableElement.is( 'rootEditableElement', 'div' ); // -> same as above\n\t *\t\ttext.is( 'div' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tconst cutType = type.replace( /^view:/, '' );\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'rootElement' || super.is( type );\n\t\t} else {\n\t\t\treturn ( cutType == 'rootElement' && name == this.name ) || super.is( type, name );\n\t\t}\n\t}\n\n\tget rootName() {\n\t\treturn this.getCustomProperty( rootNameSymbol );\n\t}\n\n\tset rootName( rootName ) {\n\t\tthis._setCustomProperty( rootNameSymbol, rootName );\n\t}\n\n\t/**\n\t * Overrides old element name and sets new one.\n\t * This is needed because view roots are created before they are attached to the DOM.\n\t * The name of the root element is temporary at this stage. It has to be changed when the\n\t * view root element is attached to the DOM element.\n\t *\n\t * @protected\n\t * @param {String} name The new name of element.\n\t */\n\tset _name( name ) {\n\t\tthis.name = name;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/treewalker\n */\n\nimport Element from './element';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport Position from './position';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Position iterator class. It allows to iterate forward and backward over the document.\n */\nexport default class TreeWalker {\n\t/**\n\t * Creates a range iterator. All parameters are optional, but you have to specify either `boundaries` or `startPosition`.\n\t *\n\t * @constructor\n\t * @param {Object} options Object with configuration.\n\t * @param {module:engine/view/range~Range} [options.boundaries=null] Range to define boundaries of the iterator.\n\t * @param {module:engine/view/position~Position} [options.startPosition] Starting position.\n\t * @param {'forward'|'backward'} [options.direction='forward'] Walking direction.\n\t * @param {Boolean} [options.singleCharacters=false] Flag indicating whether all characters from\n\t * {@link module:engine/view/text~Text} should be returned as one {@link module:engine/view/text~Text} (`false`) ore one by one as\n\t * {@link module:engine/view/textproxy~TextProxy} (`true`).\n\t * @param {Boolean} [options.shallow=false] Flag indicating whether iterator should enter elements or not. If the\n\t * iterator is shallow child nodes of any iterated node will not be returned along with `elementEnd` tag.\n\t * @param {Boolean} [options.ignoreElementEnd=false] Flag indicating whether iterator should ignore `elementEnd`\n\t * tags. If the option is true walker will not return a parent node of start position. If this option is `true`\n\t * each {@link module:engine/view/element~Element} will be returned once, while if the option is `false` they might be returned\n\t * twice: for `'elementStart'` and `'elementEnd'`.\n\t */\n\tconstructor( options = {} ) {\n\t\tif ( !options.boundaries && !options.startPosition ) {\n\t\t\t/**\n\t\t\t * Neither boundaries nor starting position have been defined.\n\t\t\t *\n\t\t\t * @error view-tree-walker-no-start-position\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'view-tree-walker-no-start-position: Neither boundaries nor starting position have been defined.',\n\t\t\t\tnull\n\t\t\t);\n\t\t}\n\n\t\tif ( options.direction && options.direction != 'forward' && options.direction != 'backward' ) {\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'view-tree-walker-unknown-direction: Only `backward` and `forward` direction allowed.',\n\t\t\t\toptions.startPosition,\n\t\t\t\t{ direction: options.direction }\n\t\t\t);\n\t\t}\n\n\t\t/**\n\t\t * Iterator boundaries.\n\t\t *\n\t\t * When the iterator is walking `'forward'` on the end of boundary or is walking `'backward'`\n\t\t * on the start of boundary, then `{ done: true }` is returned.\n\t\t *\n\t\t * If boundaries are not defined they are set before first and after last child of the root node.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/range~Range} module:engine/view/treewalker~TreeWalker#boundaries\n\t\t */\n\t\tthis.boundaries = options.boundaries || null;\n\n\t\t/**\n\t\t * Iterator position. If start position is not defined then position depends on {@link #direction}. If direction is\n\t\t * `'forward'` position starts form the beginning, when direction is `'backward'` position starts from the end.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/position~Position} module:engine/view/treewalker~TreeWalker#position\n\t\t */\n\t\tif ( options.startPosition ) {\n\t\t\tthis.position = Position._createAt( options.startPosition );\n\t\t} else {\n\t\t\tthis.position = Position._createAt( options.boundaries[ options.direction == 'backward' ? 'end' : 'start' ] );\n\t\t}\n\n\t\t/**\n\t\t * Walking direction. Defaults `'forward'`.\n\t\t *\n\t\t * @readonly\n\t\t * @member {'backward'|'forward'} module:engine/view/treewalker~TreeWalker#direction\n\t\t */\n\t\tthis.direction = options.direction || 'forward';\n\n\t\t/**\n\t\t * Flag indicating whether all characters from {@link module:engine/view/text~Text} should be returned as one\n\t\t * {@link module:engine/view/text~Text} or one by one as {@link module:engine/view/textproxy~TextProxy}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} module:engine/view/treewalker~TreeWalker#singleCharacters\n\t\t */\n\t\tthis.singleCharacters = !!options.singleCharacters;\n\n\t\t/**\n\t\t * Flag indicating whether iterator should enter elements or not. If the iterator is shallow child nodes of any\n\t\t * iterated node will not be returned along with `elementEnd` tag.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} module:engine/view/treewalker~TreeWalker#shallow\n\t\t */\n\t\tthis.shallow = !!options.shallow;\n\n\t\t/**\n\t\t * Flag indicating whether iterator should ignore `elementEnd` tags. If set to `true`, walker will not\n\t\t * return a parent node of the start position. Each {@link module:engine/view/element~Element} will be returned once.\n\t\t * When set to `false` each element might be returned twice: for `'elementStart'` and `'elementEnd'`.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} module:engine/view/treewalker~TreeWalker#ignoreElementEnd\n\t\t */\n\t\tthis.ignoreElementEnd = !!options.ignoreElementEnd;\n\n\t\t/**\n\t\t * Start boundary parent.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/view/node~Node} module:engine/view/treewalker~TreeWalker#_boundaryStartParent\n\t\t */\n\t\tthis._boundaryStartParent = this.boundaries ? this.boundaries.start.parent : null;\n\n\t\t/**\n\t\t * End boundary parent.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/view/node~Node} module:engine/view/treewalker~TreeWalker#_boundaryEndParent\n\t\t */\n\t\tthis._boundaryEndParent = this.boundaries ? this.boundaries.end.parent : null;\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * @returns {Iterable.<module:engine/view/treewalker~TreeWalkerValue>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Moves {@link #position} in the {@link #direction} skipping values as long as the callback function returns `true`.\n\t *\n\t * For example:\n\t *\n\t * \t\twalker.skip( value => value.type == 'text' ); // <p>{}foo</p> -> <p>foo[]</p>\n\t * \t\twalker.skip( value => true ); // Move the position to the end: <p>{}foo</p> -> <p>foo</p>[]\n\t * \t\twalker.skip( value => false ); // Do not move the position.\n\t *\n\t * @param {Function} skip Callback function. Gets {@link module:engine/view/treewalker~TreeWalkerValue} and should\n\t * return `true` if the value should be skipped or `false` if not.\n\t */\n\tskip( skip ) {\n\t\tlet done, value, prevPosition;\n\n\t\tdo {\n\t\t\tprevPosition = this.position;\n\n\t\t\t( { done, value } = this.next() );\n\t\t} while ( !done && skip( value ) );\n\n\t\tif ( !done ) {\n\t\t\tthis.position = prevPosition;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the next tree walker's value.\n\t *\n\t * @returns {module:engine/view/treewalker~TreeWalkerValue} Object implementing iterator interface, returning\n\t * information about taken step.\n\t */\n\tnext() {\n\t\tif ( this.direction == 'forward' ) {\n\t\t\treturn this._next();\n\t\t} else {\n\t\t\treturn this._previous();\n\t\t}\n\t}\n\n\t/**\n\t * Makes a step forward in view. Moves the {@link #position} to the next position and returns the encountered value.\n\t *\n\t * @private\n\t * @returns {Object}\n\t * @returns {Boolean} return.done `true` if iterator is done, `false` otherwise.\n\t * @returns {module:engine/view/treewalker~TreeWalkerValue} return.value Information about taken step.\n\t */\n\t_next() {\n\t\tlet position = this.position.clone();\n\t\tconst previousPosition = this.position;\n\t\tconst parent = position.parent;\n\n\t\t// We are at the end of the root.\n\t\tif ( parent.parent === null && position.offset === parent.childCount ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\t// We reached the walker boundary.\n\t\tif ( parent === this._boundaryEndParent && position.offset == this.boundaries.end.offset ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\t// Get node just after current position.\n\t\tlet node;\n\n\t\t// Text is a specific parent because it contains string instead of child nodes.\n\t\tif ( parent instanceof Text ) {\n\t\t\tif ( position.isAtEnd ) {\n\t\t\t\t// Prevent returning \"elementEnd\" for Text node. Skip that value and return the next walker step.\n\t\t\t\tthis.position = Position._createAfter( parent );\n\n\t\t\t\treturn this._next();\n\t\t\t}\n\n\t\t\tnode = parent.data[ position.offset ];\n\t\t} else {\n\t\t\tnode = parent.getChild( position.offset );\n\t\t}\n\n\t\tif ( node instanceof Element ) {\n\t\t\tif ( !this.shallow ) {\n\t\t\t\tposition = new Position( node, 0 );\n\t\t\t} else {\n\t\t\t\tposition.offset++;\n\t\t\t}\n\n\t\t\tthis.position = position;\n\n\t\t\treturn this._formatReturnValue( 'elementStart', node, previousPosition, position, 1 );\n\t\t} else if ( node instanceof Text ) {\n\t\t\tif ( this.singleCharacters ) {\n\t\t\t\tposition = new Position( node, 0 );\n\t\t\t\tthis.position = position;\n\n\t\t\t\treturn this._next();\n\t\t\t} else {\n\t\t\t\tlet charactersCount = node.data.length;\n\t\t\t\tlet item;\n\n\t\t\t\t// If text stick out of walker range, we need to cut it and wrap in TextProxy.\n\t\t\t\tif ( node == this._boundaryEndParent ) {\n\t\t\t\t\tcharactersCount = this.boundaries.end.offset;\n\t\t\t\t\titem = new TextProxy( node, 0, charactersCount );\n\t\t\t\t\tposition = Position._createAfter( item );\n\t\t\t\t} else {\n\t\t\t\t\titem = new TextProxy( node, 0, node.data.length );\n\t\t\t\t\t// If not just keep moving forward.\n\t\t\t\t\tposition.offset++;\n\t\t\t\t}\n\n\t\t\t\tthis.position = position;\n\n\t\t\t\treturn this._formatReturnValue( 'text', item, previousPosition, position, charactersCount );\n\t\t\t}\n\t\t} else if ( typeof node == 'string' ) {\n\t\t\tlet textLength;\n\n\t\t\tif ( this.singleCharacters ) {\n\t\t\t\ttextLength = 1;\n\t\t\t} else {\n\t\t\t\t// Check if text stick out of walker range.\n\t\t\t\tconst endOffset = parent === this._boundaryEndParent ? this.boundaries.end.offset : parent.data.length;\n\n\t\t\t\ttextLength = endOffset - position.offset;\n\t\t\t}\n\n\t\t\tconst textProxy = new TextProxy( parent, position.offset, textLength );\n\n\t\t\tposition.offset += textLength;\n\t\t\tthis.position = position;\n\n\t\t\treturn this._formatReturnValue( 'text', textProxy, previousPosition, position, textLength );\n\t\t} else {\n\t\t\t// `node` is not set, we reached the end of current `parent`.\n\t\t\tposition = Position._createAfter( parent );\n\t\t\tthis.position = position;\n\n\t\t\tif ( this.ignoreElementEnd ) {\n\t\t\t\treturn this._next();\n\t\t\t} else {\n\t\t\t\treturn this._formatReturnValue( 'elementEnd', parent, previousPosition, position );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Makes a step backward in view. Moves the {@link #position} to the previous position and returns the encountered value.\n\t *\n\t * @private\n\t * @returns {Object}\n\t * @returns {Boolean} return.done True if iterator is done.\n\t * @returns {module:engine/view/treewalker~TreeWalkerValue} return.value Information about taken step.\n\t */\n\t_previous() {\n\t\tlet position = this.position.clone();\n\t\tconst previousPosition = this.position;\n\t\tconst parent = position.parent;\n\n\t\t// We are at the beginning of the root.\n\t\tif ( parent.parent === null && position.offset === 0 ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\t// We reached the walker boundary.\n\t\tif ( parent == this._boundaryStartParent && position.offset == this.boundaries.start.offset ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\t// Get node just before current position.\n\t\tlet node;\n\n\t\t// Text {@link module:engine/view/text~Text} element is a specific parent because contains string instead of child nodes.\n\t\tif ( parent instanceof Text ) {\n\t\t\tif ( position.isAtStart ) {\n\t\t\t\t// Prevent returning \"elementStart\" for Text node. Skip that value and return the next walker step.\n\t\t\t\tthis.position = Position._createBefore( parent );\n\n\t\t\t\treturn this._previous();\n\t\t\t}\n\n\t\t\tnode = parent.data[ position.offset - 1 ];\n\t\t} else {\n\t\t\tnode = parent.getChild( position.offset - 1 );\n\t\t}\n\n\t\tif ( node instanceof Element ) {\n\t\t\tif ( !this.shallow ) {\n\t\t\t\tposition = new Position( node, node.childCount );\n\t\t\t\tthis.position = position;\n\n\t\t\t\tif ( this.ignoreElementEnd ) {\n\t\t\t\t\treturn this._previous();\n\t\t\t\t} else {\n\t\t\t\t\treturn this._formatReturnValue( 'elementEnd', node, previousPosition, position );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tposition.offset--;\n\t\t\t\tthis.position = position;\n\n\t\t\t\treturn this._formatReturnValue( 'elementStart', node, previousPosition, position, 1 );\n\t\t\t}\n\t\t} else if ( node instanceof Text ) {\n\t\t\tif ( this.singleCharacters ) {\n\t\t\t\tposition = new Position( node, node.data.length );\n\t\t\t\tthis.position = position;\n\n\t\t\t\treturn this._previous();\n\t\t\t} else {\n\t\t\t\tlet charactersCount = node.data.length;\n\t\t\t\tlet item;\n\n\t\t\t\t// If text stick out of walker range, we need to cut it and wrap in TextProxy.\n\t\t\t\tif ( node == this._boundaryStartParent ) {\n\t\t\t\t\tconst offset = this.boundaries.start.offset;\n\n\t\t\t\t\titem = new TextProxy( node, offset, node.data.length - offset );\n\t\t\t\t\tcharactersCount = item.data.length;\n\t\t\t\t\tposition = Position._createBefore( item );\n\t\t\t\t} else {\n\t\t\t\t\titem = new TextProxy( node, 0, node.data.length );\n\t\t\t\t\t// If not just keep moving backward.\n\t\t\t\t\tposition.offset--;\n\t\t\t\t}\n\n\t\t\t\tthis.position = position;\n\n\t\t\t\treturn this._formatReturnValue( 'text', item, previousPosition, position, charactersCount );\n\t\t\t}\n\t\t} else if ( typeof node == 'string' ) {\n\t\t\tlet textLength;\n\n\t\t\tif ( !this.singleCharacters ) {\n\t\t\t\t// Check if text stick out of walker range.\n\t\t\t\tconst startOffset = parent === this._boundaryStartParent ? this.boundaries.start.offset : 0;\n\n\t\t\t\ttextLength = position.offset - startOffset;\n\t\t\t} else {\n\t\t\t\ttextLength = 1;\n\t\t\t}\n\n\t\t\tposition.offset -= textLength;\n\n\t\t\tconst textProxy = new TextProxy( parent, position.offset, textLength );\n\n\t\t\tthis.position = position;\n\n\t\t\treturn this._formatReturnValue( 'text', textProxy, previousPosition, position, textLength );\n\t\t} else {\n\t\t\t// `node` is not set, we reached the beginning of current `parent`.\n\t\t\tposition = Position._createBefore( parent );\n\t\t\tthis.position = position;\n\n\t\t\treturn this._formatReturnValue( 'elementStart', parent, previousPosition, position, 1 );\n\t\t}\n\t}\n\n\t/**\n\t * Format returned data and adjust `previousPosition` and `nextPosition` if reach the bound of the {@link module:engine/view/text~Text}.\n\t *\n\t * @private\n\t * @param {module:engine/view/treewalker~TreeWalkerValueType} type Type of step.\n\t * @param {module:engine/view/item~Item} item Item between old and new position.\n\t * @param {module:engine/view/position~Position} previousPosition Previous position of iterator.\n\t * @param {module:engine/view/position~Position} nextPosition Next position of iterator.\n\t * @param {Number} [length] Length of the item.\n\t * @returns {module:engine/view/treewalker~TreeWalkerValue}\n\t */\n\t_formatReturnValue( type, item, previousPosition, nextPosition, length ) {\n\t\t// Text is a specific parent, because contains string instead of children.\n\t\t// Walker doesn't enter to the Text except situations when walker is iterating over every single character,\n\t\t// or the bound starts/ends inside the Text. So when the position is at the beginning or at the end of the Text\n\t\t// we move it just before or just after Text.\n\t\tif ( item instanceof TextProxy ) {\n\t\t\t// Position is at the end of Text.\n\t\t\tif ( item.offsetInText + item.data.length == item.textNode.data.length ) {\n\t\t\t\tif ( this.direction == 'forward' && !( this.boundaries && this.boundaries.end.isEqual( this.position ) ) ) {\n\t\t\t\t\tnextPosition = Position._createAfter( item.textNode );\n\t\t\t\t\t// When we change nextPosition of returned value we need also update walker current position.\n\t\t\t\t\tthis.position = nextPosition;\n\t\t\t\t} else {\n\t\t\t\t\tpreviousPosition = Position._createAfter( item.textNode );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Position is at the begining ot the text.\n\t\t\tif ( item.offsetInText === 0 ) {\n\t\t\t\tif ( this.direction == 'backward' && !( this.boundaries && this.boundaries.start.isEqual( this.position ) ) ) {\n\t\t\t\t\tnextPosition = Position._createBefore( item.textNode );\n\t\t\t\t\t// When we change nextPosition of returned value we need also update walker current position.\n\t\t\t\t\tthis.position = nextPosition;\n\t\t\t\t} else {\n\t\t\t\t\tpreviousPosition = Position._createBefore( item.textNode );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdone: false,\n\t\t\tvalue: {\n\t\t\t\ttype,\n\t\t\t\titem,\n\t\t\t\tpreviousPosition,\n\t\t\t\tnextPosition,\n\t\t\t\tlength\n\t\t\t}\n\t\t};\n\t}\n}\n\n/**\n * Type of the step made by {@link module:engine/view/treewalker~TreeWalker}.\n * Possible values: `'elementStart'` if walker is at the beginning of a node, `'elementEnd'` if walker is at the end\n * of node, or `'text'` if walker traversed over single and multiple characters.\n * For {@link module:engine/view/text~Text} `elementStart` and `elementEnd` is not returned.\n *\n * @typedef {String} module:engine/view/treewalker~TreeWalkerValueType\n */\n\n/**\n * Object returned by {@link module:engine/view/treewalker~TreeWalker} when traversing tree view.\n *\n * @typedef {Object} module:engine/view/treewalker~TreeWalkerValue\n * @property {module:engine/view/treewalker~TreeWalkerValueType} type\n * @property {module:engine/view/item~Item} item Item between the old and the new positions\n * of the tree walker.\n * @property {module:engine/view/position~Position} previousPosition Previous position of the iterator.\n * * Forward iteration: For `'elementEnd'` it is the last position inside the element. For all other types it is the\n * position before the item.\n * * Backward iteration: For `'elementStart'` it is the first position inside the element. For all other types it is\n * the position after item.\n * * If the position is at the beginning or at the end of the {@link module:engine/view/text~Text} it is always moved from the\n * inside of the text to its parent just before or just after that text.\n * @property {module:engine/view/position~Position} nextPosition Next position of the iterator.\n * * Forward iteration: For `'elementStart'` it is the first position inside the element. For all other types it is\n * the position after the item.\n * * Backward iteration: For `'elementEnd'` it is last position inside element. For all other types it is the position\n * before the item.\n * * If the position is at the beginning or at the end of the {@link module:engine/view/text~Text} it is always moved from the\n * inside of the text to its parent just before or just after that text.\n * @property {Number} [length] Length of the item. For `'elementStart'` it is `1`. For `'text'` it is\n * the length of that text. For `'elementEnd'` it is `undefined`.\n */\n\n/**\n * Tree walking directions.\n *\n * @typedef {'forward'|'backward'} module:engine/view/treewalker~TreeWalkerDirection\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/position\n */\n\nimport TreeWalker from './treewalker';\n\nimport compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport EditableElement from './editableelement';\n\n// To check if component is loaded more than once.\nimport '@ckeditor/ckeditor5-utils/src/version';\n\n/**\n * Position in the view tree. Position is represented by its parent node and an offset in this parent.\n *\n * In order to create a new position instance use the `createPosition*()` factory methods available in:\n *\n * * {@link module:engine/view/view~View}\n * * {@link module:engine/view/downcastwriter~DowncastWriter}\n * * {@link module:engine/view/upcastwriter~UpcastWriter}\n */\nexport default class Position {\n\t/**\n\t * Creates a position.\n\t *\n\t * @param {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment} parent Position parent.\n\t * @param {Number} offset Position offset.\n\t */\n\tconstructor( parent, offset ) {\n\t\t/**\n\t\t * Position parent.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment}\n\t\t * module:engine/view/position~Position#parent\n\t\t */\n\t\tthis.parent = parent;\n\n\t\t/**\n\t\t * Position offset.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} module:engine/view/position~Position#offset\n\t\t */\n\t\tthis.offset = offset;\n\t}\n\n\t/**\n\t * Node directly after the position. Equals `null` when there is no node after position or position is located\n\t * inside text node.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/node~Node|null}\n\t */\n\tget nodeAfter() {\n\t\tif ( this.parent.is( 'text' ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.parent.getChild( this.offset ) || null;\n\t}\n\n\t/**\n\t * Node directly before the position. Equals `null` when there is no node before position or position is located\n\t * inside text node.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/node~Node|null}\n\t */\n\tget nodeBefore() {\n\t\tif ( this.parent.is( 'text' ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.parent.getChild( this.offset - 1 ) || null;\n\t}\n\n\t/**\n\t * Is `true` if position is at the beginning of its {@link module:engine/view/position~Position#parent parent}, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isAtStart() {\n\t\treturn this.offset === 0;\n\t}\n\n\t/**\n\t * Is `true` if position is at the end of its {@link module:engine/view/position~Position#parent parent}, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isAtEnd() {\n\t\tconst endOffset = this.parent.is( 'text' ) ? this.parent.data.length : this.parent.childCount;\n\n\t\treturn this.offset === endOffset;\n\t}\n\n\t/**\n\t * Position's root, that is the root of the position's parent element.\n\t *\n\t * @readonly\n\t * @type {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this.parent.root;\n\t}\n\n\t/**\n\t * {@link module:engine/view/editableelement~EditableElement EditableElement} instance that contains this position, or `null` if\n\t * position is not inside an editable element.\n\t *\n\t * @type {module:engine/view/editableelement~EditableElement|null}\n\t */\n\tget editableElement() {\n\t\tlet editable = this.parent;\n\n\t\twhile ( !( editable instanceof EditableElement ) ) {\n\t\t\tif ( editable.parent ) {\n\t\t\t\teditable = editable.parent;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\treturn editable;\n\t}\n\n\t/**\n\t * Returns a new instance of Position with offset incremented by `shift` value.\n\t *\n\t * @param {Number} shift How position offset should get changed. Accepts negative values.\n\t * @returns {module:engine/view/position~Position} Shifted position.\n\t */\n\tgetShiftedBy( shift ) {\n\t\tconst shifted = Position._createAt( this );\n\n\t\tconst offset = shifted.offset + shift;\n\t\tshifted.offset = offset < 0 ? 0 : offset;\n\n\t\treturn shifted;\n\t}\n\n\t/**\n\t * Gets the farthest position which matches the callback using\n\t * {@link module:engine/view/treewalker~TreeWalker TreeWalker}.\n\t *\n\t * For example:\n\t *\n\t * \t\tgetLastMatchingPosition( value => value.type == 'text' ); // <p>{}foo</p> -> <p>foo[]</p>\n\t * \t\tgetLastMatchingPosition( value => value.type == 'text', { direction: 'backward' } ); // <p>foo[]</p> -> <p>{}foo</p>\n\t * \t\tgetLastMatchingPosition( value => false ); // Do not move the position.\n\t *\n\t * @param {Function} skip Callback function. Gets {@link module:engine/view/treewalker~TreeWalkerValue} and should\n\t * return `true` if the value should be skipped or `false` if not.\n\t * @param {Object} options Object with configuration options. See {@link module:engine/view/treewalker~TreeWalker}.\n\t *\n\t * @returns {module:engine/view/position~Position} The position after the last item which matches the `skip` callback test.\n\t */\n\tgetLastMatchingPosition( skip, options = {} ) {\n\t\toptions.startPosition = this;\n\n\t\tconst treeWalker = new TreeWalker( options );\n\t\ttreeWalker.skip( skip );\n\n\t\treturn treeWalker.position;\n\t}\n\n\t/**\n\t * Returns ancestors array of this position, that is this position's parent and it's ancestors.\n\t *\n\t * @returns {Array} Array with ancestors.\n\t */\n\tgetAncestors() {\n\t\tif ( this.parent.is( 'documentFragment' ) ) {\n\t\t\treturn [ this.parent ];\n\t\t} else {\n\t\t\treturn this.parent.getAncestors( { includeSelf: true } );\n\t\t}\n\t}\n\n\t/**\n\t * Returns a {@link module:engine/view/node~Node} or {@link module:engine/view/documentfragment~DocumentFragment}\n\t * which is a common ancestor of both positions.\n\t *\n\t * @param {module:engine/view/position~Position} position\n\t * @returns {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment|null}\n\t */\n\tgetCommonAncestor( position ) {\n\t\tconst ancestorsA = this.getAncestors();\n\t\tconst ancestorsB = position.getAncestors();\n\n\t\tlet i = 0;\n\n\t\twhile ( ancestorsA[ i ] == ancestorsB[ i ] && ancestorsA[ i ] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i === 0 ? null : ancestorsA[ i - 1 ];\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tposition.is( 'position' ); // -> true\n\t *\t\tposition.is( 'view:position' ); // -> true\n\t *\n\t *\t\tposition.is( 'model:position' ); // -> false\n\t *\t\tposition.is( 'element' ); // -> false\n\t *\t\tposition.is( 'range' ); // -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'position' || type == 'view:position';\n\t}\n\n\t/**\n\t * Checks whether this position equals given position.\n\t *\n\t * @param {module:engine/view/position~Position} otherPosition Position to compare with.\n\t * @returns {Boolean} True if positions are same.\n\t */\n\tisEqual( otherPosition ) {\n\t\treturn ( this.parent == otherPosition.parent && this.offset == otherPosition.offset );\n\t}\n\n\t/**\n\t * Checks whether this position is located before given position. When method returns `false` it does not mean that\n\t * this position is after give one. Two positions may be located inside separate roots and in that situation this\n\t * method will still return `false`.\n\t *\n\t * @see module:engine/view/position~Position#isAfter\n\t * @see module:engine/view/position~Position#compareWith\n\t * @param {module:engine/view/position~Position} otherPosition Position to compare with.\n\t * @returns {Boolean} Returns `true` if this position is before given position.\n\t */\n\tisBefore( otherPosition ) {\n\t\treturn this.compareWith( otherPosition ) == 'before';\n\t}\n\n\t/**\n\t * Checks whether this position is located after given position. When method returns `false` it does not mean that\n\t * this position is before give one. Two positions may be located inside separate roots and in that situation this\n\t * method will still return `false`.\n\t *\n\t * @see module:engine/view/position~Position#isBefore\n\t * @see module:engine/view/position~Position#compareWith\n\t * @param {module:engine/view/position~Position} otherPosition Position to compare with.\n\t * @returns {Boolean} Returns `true` if this position is after given position.\n\t */\n\tisAfter( otherPosition ) {\n\t\treturn this.compareWith( otherPosition ) == 'after';\n\t}\n\n\t/**\n\t * Checks whether this position is before, after or in same position that other position. Two positions may be also\n\t * different when they are located in separate roots.\n\t *\n\t * @param {module:engine/view/position~Position} otherPosition Position to compare with.\n\t * @returns {module:engine/view/position~PositionRelation}\n\t */\n\tcompareWith( otherPosition ) {\n\t\tif ( this.root !== otherPosition.root ) {\n\t\t\treturn 'different';\n\t\t}\n\n\t\tif ( this.isEqual( otherPosition ) ) {\n\t\t\treturn 'same';\n\t\t}\n\n\t\t// Get path from root to position's parent element.\n\t\tconst thisPath = this.parent.is( 'node' ) ? this.parent.getPath() : [];\n\t\tconst otherPath = otherPosition.parent.is( 'node' ) ? otherPosition.parent.getPath() : [];\n\n\t\t// Add the positions' offsets to the parents offsets.\n\t\tthisPath.push( this.offset );\n\t\totherPath.push( otherPosition.offset );\n\n\t\t// Compare both path arrays to find common ancestor.\n\t\tconst result = compareArrays( thisPath, otherPath );\n\n\t\tswitch ( result ) {\n\t\t\tcase 'prefix':\n\t\t\t\treturn 'before';\n\n\t\t\tcase 'extension':\n\t\t\t\treturn 'after';\n\n\t\t\tdefault:\n\t\t\t\treturn thisPath[ result ] < otherPath[ result ] ? 'before' : 'after';\n\t\t}\n\t}\n\n\t/**\n\t * Creates a {@link module:engine/view/treewalker~TreeWalker TreeWalker} instance with this positions as a start position.\n\t *\n\t * @param {Object} options Object with configuration options. See {@link module:engine/view/treewalker~TreeWalker}\n\t * @param {module:engine/view/range~Range} [options.boundaries=null] Range to define boundaries of the iterator.\n\t * @param {Boolean} [options.singleCharacters=false]\n\t * @param {Boolean} [options.shallow=false]\n\t * @param {Boolean} [options.ignoreElementEnd=false]\n\t */\n\tgetWalker( options = {} ) {\n\t\toptions.startPosition = this;\n\n\t\treturn new TreeWalker( options );\n\t}\n\n\tclone() {\n\t\treturn new Position( this.parent, this.offset );\n\t}\n\n\t/**\n\t * Creates position at the given location. The location can be specified as:\n\t *\n\t * * a {@link module:engine/view/position~Position position},\n\t * * parent element and offset (offset defaults to `0`),\n\t * * parent element and `'end'` (sets position at the end of that element),\n\t * * {@link module:engine/view/item~Item view item} and `'before'` or `'after'` (sets position before or after given view item).\n\t *\n\t * This method is a shortcut to other constructors such as:\n\t *\n\t * * {@link module:engine/view/position~Position._createBefore},\n\t * * {@link module:engine/view/position~Position._createAfter}.\n\t *\n\t * @protected\n\t * @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/view/item~Item view item}.\n\t */\n\tstatic _createAt( itemOrPosition, offset ) {\n\t\tif ( itemOrPosition instanceof Position ) {\n\t\t\treturn new this( itemOrPosition.parent, itemOrPosition.offset );\n\t\t} else {\n\t\t\tconst node = itemOrPosition;\n\n\t\t\tif ( offset == 'end' ) {\n\t\t\t\toffset = node.is( 'text' ) ? node.data.length : node.childCount;\n\t\t\t} else if ( offset == 'before' ) {\n\t\t\t\treturn this._createBefore( node );\n\t\t\t} else if ( offset == 'after' ) {\n\t\t\t\treturn this._createAfter( node );\n\t\t\t} else if ( offset !== 0 && !offset ) {\n\t\t\t\t/**\n\t\t\t\t * {@link module:engine/view/view~View#createPositionAt `View#createPositionAt()`}\n\t\t\t\t * requires the offset to be specified when the first parameter is a view item.\n\t\t\t\t *\n\t\t\t\t * @error view-createPositionAt-offset-required\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'view-createPositionAt-offset-required: ' +\n\t\t\t\t\t'View#createPositionAt() requires the offset when the first parameter is a view item.',\n\t\t\t\t\tnode\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn new Position( node, offset );\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new position after given view item.\n\t *\n\t * @protected\n\t * @param {module:engine/view/item~Item} item View item after which the position should be located.\n\t * @returns {module:engine/view/position~Position}\n\t */\n\tstatic _createAfter( item ) {\n\t\t// TextProxy is not a instance of Node so we need do handle it in specific way.\n\t\tif ( item.is( 'textProxy' ) ) {\n\t\t\treturn new Position( item.textNode, item.offsetInText + item.data.length );\n\t\t}\n\n\t\tif ( !item.parent ) {\n\t\t\t/**\n\t\t\t * You can not make a position after a root.\n\t\t\t *\n\t\t\t * @error view-position-after-root\n\t\t\t * @param {module:engine/view/node~Node} root\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-position-after-root: You can not make position after root.', item, { root: item } );\n\t\t}\n\n\t\treturn new Position( item.parent, item.index + 1 );\n\t}\n\n\t/**\n\t * Creates a new position before given view item.\n\t *\n\t * @protected\n\t * @param {module:engine/view/item~Item} item View item before which the position should be located.\n\t * @returns {module:engine/view/position~Position}\n\t */\n\tstatic _createBefore( item ) {\n\t\t// TextProxy is not a instance of Node so we need do handle it in specific way.\n\t\tif ( item.is( 'textProxy' ) ) {\n\t\t\treturn new Position( item.textNode, item.offsetInText );\n\t\t}\n\n\t\tif ( !item.parent ) {\n\t\t\t/**\n\t\t\t * You cannot make a position before a root.\n\t\t\t *\n\t\t\t * @error view-position-before-root\n\t\t\t * @param {module:engine/view/node~Node} root\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-position-before-root: You can not make position before root.', item, { root: item } );\n\t\t}\n\n\t\treturn new Position( item.parent, item.index );\n\t}\n}\n\n/**\n * A flag indicating whether this position is `'before'` or `'after'` or `'same'` as given position.\n * If positions are in different roots `'different'` flag is returned.\n *\n * @typedef {String} module:engine/view/position~PositionRelation\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/range\n */\n\nimport Position from './position';\nimport TreeWalker from './treewalker';\n\n/**\n * Range in the view tree. A range is represented by its start and end {@link module:engine/view/position~Position positions}.\n *\n * In order to create a new position instance use the `createPosition*()` factory methods available in:\n *\n * * {@link module:engine/view/view~View}\n * * {@link module:engine/view/downcastwriter~DowncastWriter}\n * * {@link module:engine/view/upcastwriter~UpcastWriter}\n */\nexport default class Range {\n\t/**\n\t * Creates a range spanning from `start` position to `end` position.\n\t *\n\t * **Note:** Constructor creates it's own {@link module:engine/view/position~Position} instances basing on passed values.\n\t *\n\t * @param {module:engine/view/position~Position} start Start position.\n\t * @param {module:engine/view/position~Position} [end] End position. If not set, range will be collapsed at the `start` position.\n\t */\n\tconstructor( start, end = null ) {\n\t\t/**\n\t\t * Start position.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/position~Position}\n\t\t */\n\t\tthis.start = start.clone();\n\n\t\t/**\n\t\t * End position.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/position~Position}\n\t\t */\n\t\tthis.end = end ? end.clone() : start.clone();\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Iterates over all {@link module:engine/view/item~Item view items} that are in this range and returns\n\t * them together with additional information like length or {@link module:engine/view/position~Position positions},\n\t * grouped as {@link module:engine/view/treewalker~TreeWalkerValue}.\n\t *\n\t * This iterator uses {@link module:engine/view/treewalker~TreeWalker TreeWalker} with `boundaries` set to this range and\n\t * `ignoreElementEnd` option\n\t * set to `true`.\n\t *\n\t * @returns {Iterable.<module:engine/view/treewalker~TreeWalkerValue>}\n\t */\n\t* [ Symbol.iterator ]() {\n\t\tyield* new TreeWalker( { boundaries: this, ignoreElementEnd: true } );\n\t}\n\n\t/**\n\t * Returns whether the range is collapsed, that is it start and end positions are equal.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isCollapsed() {\n\t\treturn this.start.isEqual( this.end );\n\t}\n\n\t/**\n\t * Returns whether this range is flat, that is if {@link module:engine/view/range~Range#start start} position and\n\t * {@link module:engine/view/range~Range#end end} position are in the same {@link module:engine/view/position~Position#parent parent}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isFlat() {\n\t\treturn this.start.parent === this.end.parent;\n\t}\n\n\t/**\n\t * Range root element.\n\t *\n\t * @type {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this.start.root;\n\t}\n\n\t/**\n\t * Creates a maximal range that has the same content as this range but is expanded in both ways (at the beginning\n\t * and at the end).\n\t *\n\t * For example:\n\t *\n\t *\t\t<p>Foo</p><p><b>{Bar}</b></p> -> <p>Foo</p>[<p><b>Bar</b>]</p>\n\t *\t\t<p><b>foo</b>{bar}<span></span></p> -> <p><b>foo[</b>bar<span></span>]</p>\n\t *\n\t * Note that in the sample above:\n\t *\n\t * - `<p>` have type of {@link module:engine/view/containerelement~ContainerElement},\n\t * - `<b>` have type of {@link module:engine/view/attributeelement~AttributeElement},\n\t * - `<span>` have type of {@link module:engine/view/uielement~UIElement}.\n\t *\n\t * @returns {module:engine/view/range~Range} Enlarged range.\n\t */\n\tgetEnlarged() {\n\t\tlet start = this.start.getLastMatchingPosition( enlargeTrimSkip, { direction: 'backward' } );\n\t\tlet end = this.end.getLastMatchingPosition( enlargeTrimSkip );\n\n\t\t// Fix positions, in case if they are in Text node.\n\t\tif ( start.parent.is( 'text' ) && start.isAtStart ) {\n\t\t\tstart = Position._createBefore( start.parent );\n\t\t}\n\n\t\tif ( end.parent.is( 'text' ) && end.isAtEnd ) {\n\t\t\tend = Position._createAfter( end.parent );\n\t\t}\n\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Creates a minimum range that has the same content as this range but is trimmed in both ways (at the beginning\n\t * and at the end).\n\t *\n\t * For example:\n\t *\n\t *\t\t<p>Foo</p>[<p><b>Bar</b>]</p> -> <p>Foo</p><p><b>{Bar}</b></p>\n\t *\t\t<p><b>foo[</b>bar<span></span>]</p> -> <p><b>foo</b>{bar}<span></span></p>\n\t *\n\t * Note that in the sample above:\n\t *\n\t * - `<p>` have type of {@link module:engine/view/containerelement~ContainerElement},\n\t * - `<b>` have type of {@link module:engine/view/attributeelement~AttributeElement},\n\t * - `<span>` have type of {@link module:engine/view/uielement~UIElement}.\n\t *\n\t * @returns {module:engine/view/range~Range} Shrink range.\n\t */\n\tgetTrimmed() {\n\t\tlet start = this.start.getLastMatchingPosition( enlargeTrimSkip );\n\n\t\tif ( start.isAfter( this.end ) || start.isEqual( this.end ) ) {\n\t\t\treturn new Range( start, start );\n\t\t}\n\n\t\tlet end = this.end.getLastMatchingPosition( enlargeTrimSkip, { direction: 'backward' } );\n\t\tconst nodeAfterStart = start.nodeAfter;\n\t\tconst nodeBeforeEnd = end.nodeBefore;\n\n\t\t// Because TreeWalker prefers positions next to text node, we need to move them manually into these text nodes.\n\t\tif ( nodeAfterStart && nodeAfterStart.is( 'text' ) ) {\n\t\t\tstart = new Position( nodeAfterStart, 0 );\n\t\t}\n\n\t\tif ( nodeBeforeEnd && nodeBeforeEnd.is( 'text' ) ) {\n\t\t\tend = new Position( nodeBeforeEnd, nodeBeforeEnd.data.length );\n\t\t}\n\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Two ranges are equal if their start and end positions are equal.\n\t *\n\t * @param {module:engine/view/range~Range} otherRange Range to compare with.\n\t * @returns {Boolean} `true` if ranges are equal, `false` otherwise\n\t */\n\tisEqual( otherRange ) {\n\t\treturn this == otherRange || ( this.start.isEqual( otherRange.start ) && this.end.isEqual( otherRange.end ) );\n\t}\n\n\t/**\n\t * Checks whether this range contains given {@link module:engine/view/position~Position position}.\n\t *\n\t * @param {module:engine/view/position~Position} position Position to check.\n\t * @returns {Boolean} `true` if given {@link module:engine/view/position~Position position} is contained in this range,\n\t * `false` otherwise.\n\t */\n\tcontainsPosition( position ) {\n\t\treturn position.isAfter( this.start ) && position.isBefore( this.end );\n\t}\n\n\t/**\n\t * Checks whether this range contains given {@link module:engine/view/range~Range range}.\n\t *\n\t * @param {module:engine/view/range~Range} otherRange Range to check.\n\t * @param {Boolean} [loose=false] Whether the check is loose or strict. If the check is strict (`false`), compared range cannot\n\t * start or end at the same position as this range boundaries. If the check is loose (`true`), compared range can start, end or\n\t * even be equal to this range. Note that collapsed ranges are always compared in strict mode.\n\t * @returns {Boolean} `true` if given {@link module:engine/view/range~Range range} boundaries are contained by this range, `false`\n\t * otherwise.\n\t */\n\tcontainsRange( otherRange, loose = false ) {\n\t\tif ( otherRange.isCollapsed ) {\n\t\t\tloose = false;\n\t\t}\n\n\t\tconst containsStart = this.containsPosition( otherRange.start ) || ( loose && this.start.isEqual( otherRange.start ) );\n\t\tconst containsEnd = this.containsPosition( otherRange.end ) || ( loose && this.end.isEqual( otherRange.end ) );\n\n\t\treturn containsStart && containsEnd;\n\t}\n\n\t/**\n\t * Computes which part(s) of this {@link module:engine/view/range~Range range} is not a part of given\n\t * {@link module:engine/view/range~Range range}.\n\t * Returned array contains zero, one or two {@link module:engine/view/range~Range ranges}.\n\t *\n\t * Examples:\n\t *\n\t *\t\tlet foo = downcastWriter.createText( 'foo' );\n\t *\t\tlet img = downcastWriter.createContainerElement( 'img' );\n\t *\t\tlet bar = downcastWriter.createText( 'bar' );\n\t *\t\tlet p = downcastWriter.createContainerElement( 'p', null, [ foo, img, bar ] );\n\t *\n\t *\t\tlet range = view.createRange( view.createPositionAt( foo, 2 ), view.createPositionAt( bar, 1 ); // \"o\", img, \"b\" are in range.\n\t *\t\tlet otherRange = view.createRange( // \"oo\", img, \"ba\" are in range.\n\t *\t\t\tview.createPositionAt( foo, 1 ),\n\t *\t\t\tview.createPositionAt( bar, 2 )\n\t *\t\t);\n\t *\t\tlet transformed = range.getDifference( otherRange );\n\t *\t\t// transformed array has no ranges because `otherRange` contains `range`\n\t *\n\t *\t\totherRange = view.createRange( view.createPositionAt( foo, 1 ), view.createPositionAt( p, 2 ); // \"oo\", img are in range.\n\t *\t\ttransformed = range.getDifference( otherRange );\n\t *\t\t// transformed array has one range: from ( p, 2 ) to ( bar, 1 )\n\t *\n\t *\t\totherRange = view.createRange( view.createPositionAt( p, 1 ), view.createPositionAt( p, 2 ) ); // img is in range.\n\t *\t\ttransformed = range.getDifference( otherRange );\n\t *\t\t// transformed array has two ranges: from ( foo, 1 ) to ( p, 1 ) and from ( p, 2 ) to ( bar, 1 )\n\t *\n\t * @param {module:engine/view/range~Range} otherRange Range to differentiate against.\n\t * @returns {Array.<module:engine/view/range~Range>} The difference between ranges.\n\t */\n\tgetDifference( otherRange ) {\n\t\tconst ranges = [];\n\n\t\tif ( this.isIntersecting( otherRange ) ) {\n\t\t\t// Ranges intersect.\n\n\t\t\tif ( this.containsPosition( otherRange.start ) ) {\n\t\t\t\t// Given range start is inside this range. This means that we have to\n\t\t\t\t// add shrunken range - from the start to the middle of this range.\n\t\t\t\tranges.push( new Range( this.start, otherRange.start ) );\n\t\t\t}\n\n\t\t\tif ( this.containsPosition( otherRange.end ) ) {\n\t\t\t\t// Given range end is inside this range. This means that we have to\n\t\t\t\t// add shrunken range - from the middle of this range to the end.\n\t\t\t\tranges.push( new Range( otherRange.end, this.end ) );\n\t\t\t}\n\t\t} else {\n\t\t\t// Ranges do not intersect, return the original range.\n\t\t\tranges.push( this.clone() );\n\t\t}\n\n\t\treturn ranges;\n\t}\n\n\t/**\n\t * Returns an intersection of this {@link module:engine/view/range~Range range} and given {@link module:engine/view/range~Range range}.\n\t * Intersection is a common part of both of those ranges. If ranges has no common part, returns `null`.\n\t *\n\t * Examples:\n\t *\n\t *\t\tlet foo = downcastWriter.createText( 'foo' );\n\t *\t\tlet img = downcastWriter.createContainerElement( 'img' );\n\t *\t\tlet bar = downcastWriter.createText( 'bar' );\n\t *\t\tlet p = downcastWriter.createContainerElement( 'p', null, [ foo, img, bar ] );\n\t *\n\t *\t\tlet range = view.createRange( view.createPositionAt( foo, 2 ), view.createPositionAt( bar, 1 ); // \"o\", img, \"b\" are in range.\n\t *\t\tlet otherRange = view.createRange( view.createPositionAt( foo, 1 ), view.createPositionAt( p, 2 ); // \"oo\", img are in range.\n\t *\t\tlet transformed = range.getIntersection( otherRange ); // range from ( foo, 1 ) to ( p, 2 ).\n\t *\n\t *\t\totherRange = view.createRange( view.createPositionAt( bar, 1 ), view.createPositionAt( bar, 3 ); \"ar\" is in range.\n\t *\t\ttransformed = range.getIntersection( otherRange ); // null - no common part.\n\t *\n\t * @param {module:engine/view/range~Range} otherRange Range to check for intersection.\n\t * @returns {module:engine/view/range~Range|null} A common part of given ranges or `null` if ranges have no common part.\n\t */\n\tgetIntersection( otherRange ) {\n\t\tif ( this.isIntersecting( otherRange ) ) {\n\t\t\t// Ranges intersect, so a common range will be returned.\n\t\t\t// At most, it will be same as this range.\n\t\t\tlet commonRangeStart = this.start;\n\t\t\tlet commonRangeEnd = this.end;\n\n\t\t\tif ( this.containsPosition( otherRange.start ) ) {\n\t\t\t\t// Given range start is inside this range. This means thaNt we have to\n\t\t\t\t// shrink common range to the given range start.\n\t\t\t\tcommonRangeStart = otherRange.start;\n\t\t\t}\n\n\t\t\tif ( this.containsPosition( otherRange.end ) ) {\n\t\t\t\t// Given range end is inside this range. This means that we have to\n\t\t\t\t// shrink common range to the given range end.\n\t\t\t\tcommonRangeEnd = otherRange.end;\n\t\t\t}\n\n\t\t\treturn new Range( commonRangeStart, commonRangeEnd );\n\t\t}\n\n\t\t// Ranges do not intersect, so they do not have common part.\n\t\treturn null;\n\t}\n\n\t/**\n\t * Creates a {@link module:engine/view/treewalker~TreeWalker TreeWalker} instance with this range as a boundary.\n\t *\n\t * @param {Object} options Object with configuration options. See {@link module:engine/view/treewalker~TreeWalker}.\n\t * @param {module:engine/view/position~Position} [options.startPosition]\n\t * @param {Boolean} [options.singleCharacters=false]\n\t * @param {Boolean} [options.shallow=false]\n\t * @param {Boolean} [options.ignoreElementEnd=false]\n\t * @returns {module:engine/view/treewalker~TreeWalker}\n\t */\n\tgetWalker( options = {} ) {\n\t\toptions.boundaries = this;\n\n\t\treturn new TreeWalker( options );\n\t}\n\n\t/**\n\t * Returns a {@link module:engine/view/node~Node} or {@link module:engine/view/documentfragment~DocumentFragment}\n\t * which is a common ancestor of range's both ends (in which the entire range is contained).\n\t *\n\t * @returns {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment|null}\n\t */\n\tgetCommonAncestor() {\n\t\treturn this.start.getCommonAncestor( this.end );\n\t}\n\n\t/**\n\t * Clones this range.\n\t *\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tclone() {\n\t\treturn new Range( this.start, this.end );\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all {@link module:engine/view/item~Item view items} that are in this range and returns\n\t * them.\n\t *\n\t * This method uses {@link module:engine/view/treewalker~TreeWalker} with `boundaries` set to this range and `ignoreElementEnd` option\n\t * set to `true`. However it returns only {@link module:engine/view/item~Item items},\n\t * not {@link module:engine/view/treewalker~TreeWalkerValue}.\n\t *\n\t * You may specify additional options for the tree walker. See {@link module:engine/view/treewalker~TreeWalker} for\n\t * a full list of available options.\n\t *\n\t * @param {Object} options Object with configuration options. See {@link module:engine/view/treewalker~TreeWalker}.\n\t * @returns {Iterable.<module:engine/view/item~Item>}\n\t */\n\t* getItems( options = {} ) {\n\t\toptions.boundaries = this;\n\t\toptions.ignoreElementEnd = true;\n\n\t\tconst treeWalker = new TreeWalker( options );\n\n\t\tfor ( const value of treeWalker ) {\n\t\t\tyield value.item;\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all {@link module:engine/view/position~Position positions} that are boundaries or\n\t * contained in this range.\n\t *\n\t * This method uses {@link module:engine/view/treewalker~TreeWalker} with `boundaries` set to this range. However it returns only\n\t * {@link module:engine/view/position~Position positions}, not {@link module:engine/view/treewalker~TreeWalkerValue}.\n\t *\n\t * You may specify additional options for the tree walker. See {@link module:engine/view/treewalker~TreeWalker} for\n\t * a full list of available options.\n\t *\n\t * @param {Object} options Object with configuration options. See {@link module:engine/view/treewalker~TreeWalker}.\n\t * @returns {Iterable.<module:engine/view/position~Position>}\n\t */\n\t* getPositions( options = {} ) {\n\t\toptions.boundaries = this;\n\n\t\tconst treeWalker = new TreeWalker( options );\n\n\t\tyield treeWalker.position;\n\n\t\tfor ( const value of treeWalker ) {\n\t\t\tyield value.nextPosition;\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\trange.is( 'range' ); // -> true\n\t *\t\trange.is( 'view:range' ); // -> true\n\t *\n\t *\t\trange.is( 'model:range' ); // -> false\n\t *\t\trange.is( 'element' ); // -> false\n\t *\t\trange.is( 'selection' ); // -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'range' || type == 'view:range';\n\t}\n\n\t/**\n\t * Checks and returns whether this range intersects with the given range.\n\t *\n\t * @param {module:engine/view/range~Range} otherRange Range to compare with.\n\t * @returns {Boolean} True if ranges intersect.\n\t */\n\tisIntersecting( otherRange ) {\n\t\treturn this.start.isBefore( otherRange.end ) && this.end.isAfter( otherRange.start );\n\t}\n\n\t/**\n\t * Creates a range from the given parents and offsets.\n\t *\n\t * @protected\n\t * @param {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment} startElement Start position\n\t * parent element.\n\t * @param {Number} startOffset Start position offset.\n\t * @param {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment} endElement End position\n\t * parent element.\n\t * @param {Number} endOffset End position offset.\n\t * @returns {module:engine/view/range~Range} Created range.\n\t */\n\tstatic _createFromParentsAndOffsets( startElement, startOffset, endElement, endOffset ) {\n\t\treturn new this(\n\t\t\tnew Position( startElement, startOffset ),\n\t\t\tnew Position( endElement, endOffset )\n\t\t);\n\t}\n\n\t/**\n\t * Creates a new range, spreading from specified {@link module:engine/view/position~Position position} to a position moved by\n\t * given `shift`. If `shift` is a negative value, shifted position is treated as the beginning of the range.\n\t *\n\t * @protected\n\t * @param {module:engine/view/position~Position} position Beginning of the range.\n\t * @param {Number} shift How long the range should be.\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tstatic _createFromPositionAndShift( position, shift ) {\n\t\tconst start = position;\n\t\tconst end = position.getShiftedBy( shift );\n\n\t\treturn shift > 0 ? new this( start, end ) : new this( end, start );\n\t}\n\n\t/**\n\t * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of\n\t * that element and ends after the last child of that element.\n\t *\n\t * @protected\n\t * @param {module:engine/view/element~Element} element Element which is a parent for the range.\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tstatic _createIn( element ) {\n\t\treturn this._createFromParentsAndOffsets( element, 0, element, element.childCount );\n\t}\n\n\t/**\n\t * Creates a range that starts before given {@link module:engine/view/item~Item view item} and ends after it.\n\t *\n\t * @protected\n\t * @param {module:engine/view/item~Item} item\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tstatic _createOn( item ) {\n\t\tconst size = item.is( 'textProxy' ) ? item.offsetSize : 1;\n\n\t\treturn this._createFromPositionAndShift( Position._createBefore( item ), size );\n\t}\n}\n\n// Function used by getEnlarged and getTrimmed methods.\nfunction enlargeTrimSkip( value ) {\n\tif ( value.item.is( 'attributeElement' ) || value.item.is( 'uiElement' ) ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/count\n */\n\n/**\n * Returns the number of items return by the iterator.\n *\n *\t\tcount( [ 1, 2, 3, 4, 5 ] ); // 5;\n *\n * @param {Iterable.<*>} iterator Any iterator.\n * @returns {Number} Number of items returned by that iterator.\n */\nexport default function count( iterator ) {\n\tlet count = 0;\n\n\tfor ( const _ of iterator ) { // eslint-disable-line no-unused-vars\n\t\tcount++;\n\t}\n\n\treturn count;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/selection\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport Range from './range';\nimport Position from './position';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport Node from './node';\nimport Element from './element';\nimport count from '@ckeditor/ckeditor5-utils/src/count';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\nimport DocumentSelection from './documentselection';\n\n/**\n * Class representing an arbirtary selection in the view.\n * See also {@link module:engine/view/documentselection~DocumentSelection}.\n *\n * New selection instances can be created via the constructor or one these methods:\n *\n * * {@link module:engine/view/view~View#createSelection `View#createSelection()`},\n * * {@link module:engine/view/upcastwriter~UpcastWriter#createSelection `UpcastWriter#createSelection()`}.\n *\n * A selection can consist of {@link module:engine/view/range~Range ranges} that can be set by using\n * the {@link module:engine/view/selection~Selection#setTo `Selection#setTo()`} method.\n */\nexport default class Selection {\n\t/**\n\t * Creates new selection instance.\n\t *\n\t * **Note**: The selection constructor is available as a factory method:\n\t *\n\t * * {@link module:engine/view/view~View#createSelection `View#createSelection()`},\n\t * * {@link module:engine/view/upcastwriter~UpcastWriter#createSelection `UpcastWriter#createSelection()`}.\n\t *\n\t * \t\t// Creates empty selection without ranges.\n\t *\t\tconst selection = writer.createSelection();\n\t *\n\t *\t\t// Creates selection at the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tconst selection = writer.createSelection( range );\n\t *\n\t *\t\t// Creates selection at the given ranges\n\t * \t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];\n\t *\t\tconst selection = writer.createSelection( ranges );\n\t *\n\t *\t\t// Creates selection from the other selection.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tconst selection = writer.createSelection( otherSelection );\n\t *\n\t *\t\t// Creates selection from the document selection.\n\t *\t\tconst selection = writer.createSelection( editor.editing.view.document.selection );\n\t *\n\t * \t\t// Creates selection at the given position.\n\t *\t\tconst position = writer.createPositionFromPath( root, path );\n\t *\t\tconst selection = writer.createSelection( position );\n\t *\n\t *\t\t// Creates collapsed selection at the position of given item and offset.\n\t *\t\tconst paragraph = writer.createContainerElement( 'paragraph' );\n\t *\t\tconst selection = writer.createSelection( paragraph, offset );\n\t *\n\t *\t\t// Creates a range inside an {@link module:engine/view/element~Element element} which starts before the\n\t *\t\t// first child of that element and ends after the last child of that element.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'in' );\n\t *\n\t *\t\t// Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends\n\t *\t\t// just after the item.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'on' );\n\t *\n\t * `Selection`'s constructor allow passing additional options (`backward`, `fake` and `label`) as the last argument.\n\t *\n\t *\t\t// Creates backward selection.\n\t *\t\tconst selection = writer.createSelection( range, { backward: true } );\n\t *\n\t * Fake selection does not render as browser native selection over selected elements and is hidden to the user.\n\t * This way, no native selection UI artifacts are displayed to the user and selection over elements can be\n\t * represented in other way, for example by applying proper CSS class.\n\t *\n\t * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM\n\t * (and be properly handled by screen readers).\n\t *\n\t *\t\t// Creates fake selection with label.\n\t *\t\tconst selection = writer.createSelection( range, { fake: true, label: 'foo' } );\n\t *\n\t * @param {module:engine/view/selection~Selectable} [selectable=null]\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Offset or place when selectable is an `Item`.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`.\n\t * @param {String} [options.label] Label for the fake selection.\n\t */\n\tconstructor( selectable = null, placeOrOffset, options ) {\n\t\t/**\n\t\t * Stores all ranges that are selected.\n\t\t *\n\t\t * @protected\n\t\t * @member {Array.<module:engine/view/range~Range>}\n\t\t */\n\t\tthis._ranges = [];\n\n\t\t/**\n\t\t * Specifies whether the last added range was added as a backward or forward range.\n\t\t *\n\t\t * @protected\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis._lastRangeBackward = false;\n\n\t\t/**\n\t\t * Specifies whether selection instance is fake.\n\t\t *\n\t\t * @private\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis._isFake = false;\n\n\t\t/**\n\t\t * Fake selection's label.\n\t\t *\n\t\t * @private\n\t\t * @member {String}\n\t\t */\n\t\tthis._fakeSelectionLabel = '';\n\n\t\tthis.setTo( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Returns true if selection instance is marked as `fake`.\n\t *\n\t * @see #setTo\n\t * @returns {Boolean}\n\t */\n\tget isFake() {\n\t\treturn this._isFake;\n\t}\n\n\t/**\n\t * Returns fake selection label.\n\t *\n\t * @see #setTo\n\t * @returns {String}\n\t */\n\tget fakeSelectionLabel() {\n\t\treturn this._fakeSelectionLabel;\n\t}\n\n\t/**\n\t * Selection anchor. Anchor may be described as a position where the selection starts. Together with\n\t * {@link #focus focus} they define the direction of selection, which is important\n\t * when expanding/shrinking selection. Anchor is always the start or end of the most recent added range.\n\t * It may be a bit unintuitive when there are multiple ranges in selection.\n\t *\n\t * @see #focus\n\t * @type {module:engine/view/position~Position}\n\t */\n\tget anchor() {\n\t\tif ( !this._ranges.length ) {\n\t\t\treturn null;\n\t\t}\n\t\tconst range = this._ranges[ this._ranges.length - 1 ];\n\t\tconst anchor = this._lastRangeBackward ? range.end : range.start;\n\n\t\treturn anchor.clone();\n\t}\n\n\t/**\n\t * Selection focus. Focus is a position where the selection ends.\n\t *\n\t * @see #anchor\n\t * @type {module:engine/view/position~Position}\n\t */\n\tget focus() {\n\t\tif ( !this._ranges.length ) {\n\t\t\treturn null;\n\t\t}\n\t\tconst range = this._ranges[ this._ranges.length - 1 ];\n\t\tconst focus = this._lastRangeBackward ? range.start : range.end;\n\n\t\treturn focus.clone();\n\t}\n\n\t/**\n\t * Returns whether the selection is collapsed. Selection is collapsed when there is exactly one range which is\n\t * collapsed.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isCollapsed() {\n\t\treturn this.rangeCount === 1 && this._ranges[ 0 ].isCollapsed;\n\t}\n\n\t/**\n\t * Returns number of ranges in selection.\n\t *\n\t * @type {Number}\n\t */\n\tget rangeCount() {\n\t\treturn this._ranges.length;\n\t}\n\n\t/**\n\t * Specifies whether the {@link #focus} precedes {@link #anchor}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isBackward() {\n\t\treturn !this.isCollapsed && this._lastRangeBackward;\n\t}\n\n\t/**\n\t * {@link module:engine/view/editableelement~EditableElement EditableElement} instance that contains this selection, or `null`\n\t * if the selection is not inside an editable element.\n\t *\n\t * @type {module:engine/view/editableelement~EditableElement|null}\n\t */\n\tget editableElement() {\n\t\tif ( this.anchor ) {\n\t\t\treturn this.anchor.editableElement;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Returns an iterable that contains copies of all ranges added to the selection.\n\t *\n\t * @returns {Iterable.<module:engine/view/range~Range>}\n\t */\n\t* getRanges() {\n\t\tfor ( const range of this._ranges ) {\n\t\t\tyield range.clone();\n\t\t}\n\t}\n\n\t/**\n\t * Returns copy of the first range in the selection. First range is the one which\n\t * {@link module:engine/view/range~Range#start start} position {@link module:engine/view/position~Position#isBefore is before} start\n\t * position of all other ranges (not to confuse with the first range added to the selection).\n\t * Returns `null` if no ranges are added to selection.\n\t *\n\t * @returns {module:engine/view/range~Range|null}\n\t */\n\tgetFirstRange() {\n\t\tlet first = null;\n\n\t\tfor ( const range of this._ranges ) {\n\t\t\tif ( !first || range.start.isBefore( first.start ) ) {\n\t\t\t\tfirst = range;\n\t\t\t}\n\t\t}\n\n\t\treturn first ? first.clone() : null;\n\t}\n\n\t/**\n\t * Returns copy of the last range in the selection. Last range is the one which {@link module:engine/view/range~Range#end end}\n\t * position {@link module:engine/view/position~Position#isAfter is after} end position of all other ranges (not to confuse\n\t * with the last range added to the selection). Returns `null` if no ranges are added to selection.\n\t *\n\t * @returns {module:engine/view/range~Range|null}\n\t */\n\tgetLastRange() {\n\t\tlet last = null;\n\n\t\tfor ( const range of this._ranges ) {\n\t\t\tif ( !last || range.end.isAfter( last.end ) ) {\n\t\t\t\tlast = range;\n\t\t\t}\n\t\t}\n\n\t\treturn last ? last.clone() : null;\n\t}\n\n\t/**\n\t * Returns copy of the first position in the selection. First position is the position that\n\t * {@link module:engine/view/position~Position#isBefore is before} any other position in the selection ranges.\n\t * Returns `null` if no ranges are added to selection.\n\t *\n\t * @returns {module:engine/view/position~Position|null}\n\t */\n\tgetFirstPosition() {\n\t\tconst firstRange = this.getFirstRange();\n\n\t\treturn firstRange ? firstRange.start.clone() : null;\n\t}\n\n\t/**\n\t * Returns copy of the last position in the selection. Last position is the position that\n\t * {@link module:engine/view/position~Position#isAfter is after} any other position in the selection ranges.\n\t * Returns `null` if no ranges are added to selection.\n\t *\n\t * @returns {module:engine/view/position~Position|null}\n\t */\n\tgetLastPosition() {\n\t\tconst lastRange = this.getLastRange();\n\n\t\treturn lastRange ? lastRange.end.clone() : null;\n\t}\n\n\t/**\n\t * Checks whether, this selection is equal to given selection. Selections are equal if they have same directions,\n\t * same number of ranges and all ranges from one selection equal to a range from other selection.\n\t *\n\t * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection} otherSelection\n\t * Selection to compare with.\n\t * @returns {Boolean} `true` if selections are equal, `false` otherwise.\n\t */\n\tisEqual( otherSelection ) {\n\t\tif ( this.isFake != otherSelection.isFake ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.isFake && this.fakeSelectionLabel != otherSelection.fakeSelectionLabel ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.rangeCount != otherSelection.rangeCount ) {\n\t\t\treturn false;\n\t\t} else if ( this.rangeCount === 0 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( !this.anchor.isEqual( otherSelection.anchor ) || !this.focus.isEqual( otherSelection.focus ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor ( const thisRange of this._ranges ) {\n\t\t\tlet found = false;\n\n\t\t\tfor ( const otherRange of otherSelection._ranges ) {\n\t\t\t\tif ( thisRange.isEqual( otherRange ) ) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !found ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks whether this selection is similar to given selection. Selections are similar if they have same directions, same\n\t * number of ranges, and all {@link module:engine/view/range~Range#getTrimmed trimmed} ranges from one selection are\n\t * equal to any trimmed range from other selection.\n\t *\n\t * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection} otherSelection\n\t * Selection to compare with.\n\t * @returns {Boolean} `true` if selections are similar, `false` otherwise.\n\t */\n\tisSimilar( otherSelection ) {\n\t\tif ( this.isBackward != otherSelection.isBackward ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst numOfRangesA = count( this.getRanges() );\n\t\tconst numOfRangesB = count( otherSelection.getRanges() );\n\n\t\t// If selections have different number of ranges, they cannot be similar.\n\t\tif ( numOfRangesA != numOfRangesB ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If both selections have no ranges, they are similar.\n\t\tif ( numOfRangesA == 0 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check if each range in one selection has a similar range in other selection.\n\t\tfor ( let rangeA of this.getRanges() ) {\n\t\t\trangeA = rangeA.getTrimmed();\n\n\t\t\tlet found = false;\n\n\t\t\tfor ( let rangeB of otherSelection.getRanges() ) {\n\t\t\t\trangeB = rangeB.getTrimmed();\n\n\t\t\t\tif ( rangeA.start.isEqual( rangeB.start ) && rangeA.end.isEqual( rangeB.end ) ) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// For `rangeA`, neither range in `otherSelection` was similar. So selections are not similar.\n\t\t\tif ( !found ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// There were no ranges that weren't matched. Selections are similar.\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns the selected element. {@link module:engine/view/element~Element Element} is considered as selected if there is only\n\t * one range in the selection, and that range contains exactly one element.\n\t * Returns `null` if there is no selected element.\n\t *\n\t * @returns {module:engine/view/element~Element|null}\n\t */\n\tgetSelectedElement() {\n\t\tif ( this.rangeCount !== 1 ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst range = this.getFirstRange();\n\n\t\tlet nodeAfterStart = range.start.nodeAfter;\n\t\tlet nodeBeforeEnd = range.end.nodeBefore;\n\n\t\t// Handle the situation when selection position is at the beginning / at the end of a text node.\n\t\t// In such situation `.nodeAfter` and `.nodeBefore` are `null` but the selection still might be spanning\n\t\t// over one element.\n\t\t//\n\t\t// <p>Foo{<span class=\"widget\"></span>}bar</p> vs <p>Foo[<span class=\"widget\"></span>]bar</p>\n\t\t//\n\t\t// These are basically the same selections, only the difference is if the selection position is at\n\t\t// at the end/at the beginning of a text node or just before/just after the text node.\n\t\t//\n\t\tif ( range.start.parent.is( 'text' ) && range.start.isAtEnd && range.start.parent.nextSibling ) {\n\t\t\tnodeAfterStart = range.start.parent.nextSibling;\n\t\t}\n\n\t\tif ( range.end.parent.is( 'text' ) && range.end.isAtStart && range.end.parent.previousSibling ) {\n\t\t\tnodeBeforeEnd = range.end.parent.previousSibling;\n\t\t}\n\n\t\treturn ( nodeAfterStart instanceof Element && nodeAfterStart == nodeBeforeEnd ) ? nodeAfterStart : null;\n\t}\n\n\t/**\n\t * Sets this selection's ranges and direction to the specified location based on the given\n\t * {@link module:engine/view/selection~Selectable selectable}.\n\t *\n\t *\t\t// Sets selection to the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tselection.setTo( range );\n\t *\n\t *\t\t// Sets selection to given ranges.\n\t * \t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];\n\t *\t\tselection.setTo( range );\n\t *\n\t *\t\t// Sets selection to the other selection.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tselection.setTo( otherSelection );\n\t *\n\t *\t \t// Sets selection to contents of DocumentSelection.\n\t *\t\tselection.setTo( editor.editing.view.document.selection );\n\t *\n\t * \t\t// Sets collapsed selection at the given position.\n\t *\t\tconst position = writer.createPositionAt( root, path );\n\t *\t\tselection.setTo( position );\n\t *\n\t * \t\t// Sets collapsed selection at the position of given item and offset.\n\t *\t\tselection.setTo( paragraph, offset );\n\t *\n\t * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of\n\t * that element and ends after the last child of that element.\n\t *\n\t *\t\tselection.setTo( paragraph, 'in' );\n\t *\n\t * Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends just after the item.\n\t *\n\t *\t\tselection.setTo( paragraph, 'on' );\n\t *\n\t * \t\t// Clears selection. Removes all ranges.\n\t *\t\tselection.setTo( null );\n\t *\n\t * `Selection#setTo()` method allow passing additional options (`backward`, `fake` and `label`) as the last argument.\n\t *\n\t *\t\t// Sets selection as backward.\n\t *\t\tselection.setTo( range, { backward: true } );\n\t *\n\t * Fake selection does not render as browser native selection over selected elements and is hidden to the user.\n\t * This way, no native selection UI artifacts are displayed to the user and selection over elements can be\n\t * represented in other way, for example by applying proper CSS class.\n\t *\n\t * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM\n\t * (and be properly handled by screen readers).\n\t *\n\t *\t\t// Creates fake selection with label.\n\t *\t\tselection.setTo( range, { fake: true, label: 'foo' } );\n\t *\n\t * @fires change\n\t * @param {module:engine/view/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`.\n\t * @param {String} [options.label] Label for the fake selection.\n\t */\n\tsetTo( selectable, placeOrOffset, options ) {\n\t\tif ( selectable === null ) {\n\t\t\tthis._setRanges( [] );\n\t\t\tthis._setFakeOptions( placeOrOffset );\n\t\t} else if ( selectable instanceof Selection || selectable instanceof DocumentSelection ) {\n\t\t\tthis._setRanges( selectable.getRanges(), selectable.isBackward );\n\t\t\tthis._setFakeOptions( { fake: selectable.isFake, label: selectable.fakeSelectionLabel } );\n\t\t} else if ( selectable instanceof Range ) {\n\t\t\tthis._setRanges( [ selectable ], placeOrOffset && placeOrOffset.backward );\n\t\t\tthis._setFakeOptions( placeOrOffset );\n\t\t} else if ( selectable instanceof Position ) {\n\t\t\tthis._setRanges( [ new Range( selectable ) ] );\n\t\t\tthis._setFakeOptions( placeOrOffset );\n\t\t} else if ( selectable instanceof Node ) {\n\t\t\tconst backward = !!options && !!options.backward;\n\t\t\tlet range;\n\n\t\t\tif ( placeOrOffset === undefined ) {\n\t\t\t\t/**\n\t\t\t\t * selection.setTo requires the second parameter when the first parameter is a node.\n\t\t\t\t *\n\t\t\t\t * @error view-selection-setTo-required-second-parameter\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'view-selection-setTo-required-second-parameter: ' +\n\t\t\t\t\t'selection.setTo requires the second parameter when the first parameter is a node.',\n\t\t\t\t\tthis\n\t\t\t\t);\n\t\t\t} else if ( placeOrOffset == 'in' ) {\n\t\t\t\trange = Range._createIn( selectable );\n\t\t\t} else if ( placeOrOffset == 'on' ) {\n\t\t\t\trange = Range._createOn( selectable );\n\t\t\t} else {\n\t\t\t\trange = new Range( Position._createAt( selectable, placeOrOffset ) );\n\t\t\t}\n\n\t\t\tthis._setRanges( [ range ], backward );\n\t\t\tthis._setFakeOptions( options );\n\t\t} else if ( isIterable( selectable ) ) {\n\t\t\t// We assume that the selectable is an iterable of ranges.\n\t\t\t// Array.from() is used to prevent setting ranges to the old iterable\n\t\t\tthis._setRanges( selectable, placeOrOffset && placeOrOffset.backward );\n\t\t\tthis._setFakeOptions( placeOrOffset );\n\t\t} else {\n\t\t\t/**\n\t\t\t * Cannot set selection to given place.\n\t\t\t *\n\t\t\t * @error view-selection-setTo-not-selectable\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-selection-setTo-not-selectable: Cannot set selection to given place.', this );\n\t\t}\n\n\t\tthis.fire( 'change' );\n\t}\n\n\t/**\n\t * Moves {@link #focus} to the specified location.\n\t *\n\t * The location can be specified in the same form as {@link module:engine/view/view~View#createPositionAt view.createPositionAt()}\n\t * parameters.\n\t *\n\t * @fires change\n\t * @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/view/item~Item view item}.\n\t */\n\tsetFocus( itemOrPosition, offset ) {\n\t\tif ( this.anchor === null ) {\n\t\t\t/**\n\t\t\t * Cannot set selection focus if there are no ranges in selection.\n\t\t\t *\n\t\t\t * @error view-selection-setFocus-no-ranges\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'view-selection-setFocus-no-ranges: Cannot set selection focus if there are no ranges in selection.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tconst newFocus = Position._createAt( itemOrPosition, offset );\n\n\t\tif ( newFocus.compareWith( this.focus ) == 'same' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst anchor = this.anchor;\n\n\t\tthis._ranges.pop();\n\n\t\tif ( newFocus.compareWith( anchor ) == 'before' ) {\n\t\t\tthis._addRange( new Range( newFocus, anchor ), true );\n\t\t} else {\n\t\t\tthis._addRange( new Range( anchor, newFocus ) );\n\t\t}\n\n\t\tthis.fire( 'change' );\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tselection.is( 'selection' ); // -> true\n\t *\t\tselection.is( 'view:selection' ); // -> true\n\t *\n\t *\t\tselection.is( 'model:selection' ); // -> false\n\t *\t\tselection.is( 'element' ); // -> false\n\t *\t\tselection.is( 'range' ); // -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'selection' || type == 'view:selection';\n\t}\n\n\t/**\n\t * Replaces all ranges that were added to the selection with given array of ranges. Last range of the array\n\t * is treated like the last added range and is used to set {@link #anchor anchor} and {@link #focus focus}.\n\t * Accepts a flag describing in which way the selection is made.\n\t *\n\t * @private\n\t * @param {Iterable.<module:engine/view/range~Range>} newRanges Iterable object of ranges to set.\n\t * @param {Boolean} [isLastBackward=false] Flag describing if last added range was selected forward - from start to end\n\t * (`false`) or backward - from end to start (`true`). Defaults to `false`.\n\t */\n\t_setRanges( newRanges, isLastBackward = false ) {\n\t\t// New ranges should be copied to prevent removing them by setting them to `[]` first.\n\t\t// Only applies to situations when selection is set to the same selection or same selection's ranges.\n\t\tnewRanges = Array.from( newRanges );\n\n\t\tthis._ranges = [];\n\n\t\tfor ( const range of newRanges ) {\n\t\t\tthis._addRange( range );\n\t\t}\n\n\t\tthis._lastRangeBackward = !!isLastBackward;\n\t}\n\n\t/**\n\t * Sets this selection instance to be marked as `fake`. A fake selection does not render as browser native selection\n\t * over selected elements and is hidden to the user. This way, no native selection UI artifacts are displayed to\n\t * the user and selection over elements can be represented in other way, for example by applying proper CSS class.\n\t *\n\t * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM (and be\n\t * properly handled by screen readers).\n\t *\n\t * @private\n\t * @param {Object} [options] Options.\n\t * @param {Boolean} [options.fake] If set to true selection will be marked as `fake`.\n\t * @param {String} [options.label=''] Fake selection label.\n\t */\n\t_setFakeOptions( options = {} ) {\n\t\tthis._isFake = !!options.fake;\n\t\tthis._fakeSelectionLabel = options.fake ? options.label || '' : '';\n\t}\n\n\t/**\n\t * Adds a range to the selection. Added range is copied. This means that passed range is not saved in the\n\t * selection instance and you can safely operate on it.\n\t *\n\t * Accepts a flag describing in which way the selection is made - passed range might be selected from\n\t * {@link module:engine/view/range~Range#start start} to {@link module:engine/view/range~Range#end end}\n\t * or from {@link module:engine/view/range~Range#end end} to {@link module:engine/view/range~Range#start start}.\n\t * The flag is used to set {@link #anchor anchor} and {@link #focus focus} properties.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-selection-range-intersects` if added range intersects\n\t * with ranges already stored in Selection instance.\n\t *\n\t * @private\n\t * @fires change\n\t * @param {module:engine/view/range~Range} range\n\t * @param {Boolean} [isBackward]\n\t */\n\t_addRange( range, isBackward = false ) {\n\t\tif ( !( range instanceof Range ) ) {\n\t\t\t/**\n\t\t\t * Selection range set to an object that is not an instance of {@link module:engine/view/range~Range}.\n\t\t\t *\n\t\t\t * @error view-selection-add-range-not-range\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'view-selection-add-range-not-range: ' +\n\t\t\t\t'Selection range set to an object that is not an instance of view.Range',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tthis._pushRange( range );\n\t\tthis._lastRangeBackward = !!isBackward;\n\t}\n\n\t/**\n\t * Adds range to selection - creates copy of given range so it can be safely used and modified.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-selection-range-intersects` if added range intersects\n\t * with ranges already stored in selection instance.\n\t *\n\t * @private\n\t * @param {module:engine/view/range~Range} range\n\t */\n\t_pushRange( range ) {\n\t\tfor ( const storedRange of this._ranges ) {\n\t\t\tif ( range.isIntersecting( storedRange ) ) {\n\t\t\t\t/**\n\t\t\t\t * Trying to add a range that intersects with another range from selection.\n\t\t\t\t *\n\t\t\t\t * @error view-selection-range-intersects\n\t\t\t\t * @param {module:engine/view/range~Range} addedRange Range that was added to the selection.\n\t\t\t\t * @param {module:engine/view/range~Range} intersectingRange Range from selection that intersects with `addedRange`.\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'view-selection-range-intersects: Trying to add a range that intersects with another range from selection.',\n\t\t\t\t\tthis,\n\t\t\t\t\t{ addedRange: range, intersectingRange: storedRange }\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._ranges.push( new Range( range.start, range.end ) );\n\t}\n\n\t/**\n\t * Fired whenever selection ranges are changed through {@link ~Selection Selection API}.\n\t *\n\t * @event change\n\t */\n}\n\nmix( Selection, EmitterMixin );\n\n/**\n * An entity that is used to set selection.\n *\n * See also {@link module:engine/view/selection~Selection#setTo}\n *\n * @typedef {\n * module:engine/view/selection~Selection|\n * module:engine/view/documentselection~DocumentSelection|\n * module:engine/view/position~Position|\n * Iterable.<module:engine/view/range~Range>|\n * module:engine/view/range~Range|\n * module:engine/view/item~Item|\n * null\n * } module:engine/view/selection~Selectable\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/documentselection\n */\n\nimport Selection from './selection';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\n\n/**\n * Class representing the document selection in the view.\n *\n * Its instance is available in {@link module:engine/view/document~Document#selection `Document#selection`}.\n *\n * It is similar to {@link module:engine/view/selection~Selection} but\n * it has a read-only API and can be modified only by the writer available in\n * the {@link module:engine/view/view~View#change `View#change()`} block\n * (so via {@link module:engine/view/downcastwriter~DowncastWriter#setSelection `DowncastWriter#setSelection()`}).\n */\nexport default class DocumentSelection {\n\t/**\n\t * Creates new DocumentSelection instance.\n\t *\n\t * \t\t// Creates empty selection without ranges.\n\t *\t\tconst selection = new DocumentSelection();\n\t *\n\t *\t\t// Creates selection at the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tconst selection = new DocumentSelection( range );\n\t *\n\t *\t\t// Creates selection at the given ranges\n\t * \t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( start2, end2 ) ];\n\t *\t\tconst selection = new DocumentSelection( ranges );\n\t *\n\t *\t\t// Creates selection from the other selection.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tconst selection = new DocumentSelection( otherSelection );\n\t *\n\t * \t\t// Creates selection at the given position.\n\t *\t\tconst position = writer.createPositionAt( root, offset );\n\t *\t\tconst selection = new DocumentSelection( position );\n\t *\n\t *\t\t// Creates collapsed selection at the position of given item and offset.\n\t *\t\tconst paragraph = writer.createContainerElement( 'paragraph' );\n\t *\t\tconst selection = new DocumentSelection( paragraph, offset );\n\t *\n\t *\t\t// Creates a range inside an {@link module:engine/view/element~Element element} which starts before the\n\t *\t\t// first child of that element and ends after the last child of that element.\n\t *\t\tconst selection = new DocumentSelection( paragraph, 'in' );\n\t *\n\t *\t\t// Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends\n\t *\t\t// just after the item.\n\t *\t\tconst selection = new DocumentSelection( paragraph, 'on' );\n\t *\n\t * `Selection`'s constructor allow passing additional options (`backward`, `fake` and `label`) as the last argument.\n\t *\n\t *\t\t// Creates backward selection.\n\t *\t\tconst selection = new DocumentSelection( range, { backward: true } );\n\t *\n\t * Fake selection does not render as browser native selection over selected elements and is hidden to the user.\n\t * This way, no native selection UI artifacts are displayed to the user and selection over elements can be\n\t * represented in other way, for example by applying proper CSS class.\n\t *\n\t * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM\n\t * (and be properly handled by screen readers).\n\t *\n\t *\t\t// Creates fake selection with label.\n\t *\t\tconst selection = new DocumentSelection( range, { fake: true, label: 'foo' } );\n\t *\n\t * @param {module:engine/view/selection~Selectable} [selectable=null]\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Offset or place when selectable is an `Item`.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`.\n\t * @param {String} [options.label] Label for the fake selection.\n\t */\n\tconstructor( selectable = null, placeOrOffset, options ) {\n\t\t/**\n\t\t * Selection is used internally (`DocumentSelection` is a proxy to that selection).\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/view/selection~Selection}\n\t\t */\n\t\tthis._selection = new Selection();\n\n\t\t// Delegate change event to be fired on DocumentSelection instance.\n\t\tthis._selection.delegate( 'change' ).to( this );\n\n\t\t// Set selection data.\n\t\tthis._selection.setTo( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Returns true if selection instance is marked as `fake`.\n\t *\n\t * @see #_setTo\n\t * @returns {Boolean}\n\t */\n\tget isFake() {\n\t\treturn this._selection.isFake;\n\t}\n\n\t/**\n\t * Returns fake selection label.\n\t *\n\t * @see #_setTo\n\t * @returns {String}\n\t */\n\tget fakeSelectionLabel() {\n\t\treturn this._selection.fakeSelectionLabel;\n\t}\n\n\t/**\n\t * Selection anchor. Anchor may be described as a position where the selection starts. Together with\n\t * {@link #focus focus} they define the direction of selection, which is important\n\t * when expanding/shrinking selection. Anchor is always the start or end of the most recent added range.\n\t * It may be a bit unintuitive when there are multiple ranges in selection.\n\t *\n\t * @see #focus\n\t * @type {module:engine/view/position~Position}\n\t */\n\tget anchor() {\n\t\treturn this._selection.anchor;\n\t}\n\n\t/**\n\t * Selection focus. Focus is a position where the selection ends.\n\t *\n\t * @see #anchor\n\t * @type {module:engine/view/position~Position}\n\t */\n\tget focus() {\n\t\treturn this._selection.focus;\n\t}\n\n\t/**\n\t * Returns whether the selection is collapsed. Selection is collapsed when there is exactly one range which is\n\t * collapsed.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isCollapsed() {\n\t\treturn this._selection.isCollapsed;\n\t}\n\n\t/**\n\t * Returns number of ranges in selection.\n\t *\n\t * @type {Number}\n\t */\n\tget rangeCount() {\n\t\treturn this._selection.rangeCount;\n\t}\n\n\t/**\n\t * Specifies whether the {@link #focus} precedes {@link #anchor}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isBackward() {\n\t\treturn this._selection.isBackward;\n\t}\n\n\t/**\n\t * {@link module:engine/view/editableelement~EditableElement EditableElement} instance that contains this selection, or `null`\n\t * if the selection is not inside an editable element.\n\t *\n\t * @type {module:engine/view/editableelement~EditableElement|null}\n\t */\n\tget editableElement() {\n\t\treturn this._selection.editableElement;\n\t}\n\n\t/**\n\t * Used for the compatibility with the {@link module:engine/view/selection~Selection#isEqual} method.\n\t *\n\t * @protected\n\t */\n\tget _ranges() {\n\t\treturn this._selection._ranges;\n\t}\n\n\t/**\n\t * Returns an iterable that contains copies of all ranges added to the selection.\n\t *\n\t * @returns {Iterable.<module:engine/view/range~Range>}\n\t */\n\t* getRanges() {\n\t\tyield* this._selection.getRanges();\n\t}\n\n\t/**\n\t * Returns copy of the first range in the selection. First range is the one which\n\t * {@link module:engine/view/range~Range#start start} position {@link module:engine/view/position~Position#isBefore is before} start\n\t * position of all other ranges (not to confuse with the first range added to the selection).\n\t * Returns `null` if no ranges are added to selection.\n\t *\n\t * @returns {module:engine/view/range~Range|null}\n\t */\n\tgetFirstRange() {\n\t\treturn this._selection.getFirstRange();\n\t}\n\n\t/**\n\t * Returns copy of the last range in the selection. Last range is the one which {@link module:engine/view/range~Range#end end}\n\t * position {@link module:engine/view/position~Position#isAfter is after} end position of all other ranges (not to confuse\n\t * with the last range added to the selection). Returns `null` if no ranges are added to selection.\n\t *\n\t * @returns {module:engine/view/range~Range|null}\n\t */\n\tgetLastRange() {\n\t\treturn this._selection.getLastRange();\n\t}\n\n\t/**\n\t * Returns copy of the first position in the selection. First position is the position that\n\t * {@link module:engine/view/position~Position#isBefore is before} any other position in the selection ranges.\n\t * Returns `null` if no ranges are added to selection.\n\t *\n\t * @returns {module:engine/view/position~Position|null}\n\t */\n\tgetFirstPosition() {\n\t\treturn this._selection.getFirstPosition();\n\t}\n\n\t/**\n\t * Returns copy of the last position in the selection. Last position is the position that\n\t * {@link module:engine/view/position~Position#isAfter is after} any other position in the selection ranges.\n\t * Returns `null` if no ranges are added to selection.\n\t *\n\t * @returns {module:engine/view/position~Position|null}\n\t */\n\tgetLastPosition() {\n\t\treturn this._selection.getLastPosition();\n\t}\n\n\t/**\n\t * Returns the selected element. {@link module:engine/view/element~Element Element} is considered as selected if there is only\n\t * one range in the selection, and that range contains exactly one element.\n\t * Returns `null` if there is no selected element.\n\t *\n\t * @returns {module:engine/view/element~Element|null}\n\t */\n\tgetSelectedElement() {\n\t\treturn this._selection.getSelectedElement();\n\t}\n\n\t/**\n\t * Checks whether, this selection is equal to given selection. Selections are equal if they have same directions,\n\t * same number of ranges and all ranges from one selection equal to a range from other selection.\n\t *\n\t * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection} otherSelection\n\t * Selection to compare with.\n\t * @returns {Boolean} `true` if selections are equal, `false` otherwise.\n\t */\n\tisEqual( otherSelection ) {\n\t\treturn this._selection.isEqual( otherSelection );\n\t}\n\n\t/**\n\t * Checks whether this selection is similar to given selection. Selections are similar if they have same directions, same\n\t * number of ranges, and all {@link module:engine/view/range~Range#getTrimmed trimmed} ranges from one selection are\n\t * equal to any trimmed range from other selection.\n\t *\n\t * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection} otherSelection\n\t * Selection to compare with.\n\t * @returns {Boolean} `true` if selections are similar, `false` otherwise.\n\t */\n\tisSimilar( otherSelection ) {\n\t\treturn this._selection.isSimilar( otherSelection );\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tdocSelection.is( 'selection' ); // -> true\n\t *\t\tdocSelection.is( 'documentSelection' ); // -> true\n\t *\t\tdocSelection.is( 'view:selection' ); // -> true\n\t *\t\tdocSelection.is( 'view:documentSelection' ); // -> true\n\t *\n\t *\t\tdocSelection.is( 'model:documentSelection' ); // -> false\n\t *\t\tdocSelection.is( 'element' ); // -> false\n\t *\t\tdocSelection.is( 'node' ); // -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'selection' ||\n\t\t\ttype == 'documentSelection' ||\n\t\t\ttype == 'view:selection' ||\n\t\t\ttype == 'view:documentSelection';\n\t}\n\n\t/**\n\t * Sets this selection's ranges and direction to the specified location based on the given\n\t * {@link module:engine/view/selection~Selectable selectable}.\n\t *\n\t *\t\t// Sets selection to the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tdocumentSelection._setTo( range );\n\t *\n\t *\t\t// Sets selection to given ranges.\n\t * \t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( start2, end2 ) ];\n\t *\t\tdocumentSelection._setTo( range );\n\t *\n\t *\t\t// Sets selection to the other selection.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tdocumentSelection._setTo( otherSelection );\n\t *\n\t * \t\t// Sets collapsed selection at the given position.\n\t *\t\tconst position = writer.createPositionAt( root, offset );\n\t *\t\tdocumentSelection._setTo( position );\n\t *\n\t * \t\t// Sets collapsed selection at the position of given item and offset.\n\t *\t\tdocumentSelection._setTo( paragraph, offset );\n\t *\n\t * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of\n\t * that element and ends after the last child of that element.\n\t *\n\t *\t\tdocumentSelection._setTo( paragraph, 'in' );\n\t *\n\t * Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends just after the item.\n\t *\n\t *\t\tdocumentSelection._setTo( paragraph, 'on' );\n\t *\n\t * \t\t// Clears selection. Removes all ranges.\n\t *\t\tdocumentSelection._setTo( null );\n\t *\n\t * `Selection#_setTo()` method allow passing additional options (`backward`, `fake` and `label`) as the last argument.\n\t *\n\t *\t\t// Sets selection as backward.\n\t *\t\tdocumentSelection._setTo( range, { backward: true } );\n\t *\n\t * Fake selection does not render as browser native selection over selected elements and is hidden to the user.\n\t * This way, no native selection UI artifacts are displayed to the user and selection over elements can be\n\t * represented in other way, for example by applying proper CSS class.\n\t *\n\t * Additionally fake's selection label can be provided. It will be used to des cribe fake selection in DOM\n\t * (and be properly handled by screen readers).\n\t *\n\t *\t\t// Creates fake selection with label.\n\t *\t\tdocumentSelection._setTo( range, { fake: true, label: 'foo' } );\n\t *\n\t * @protected\n\t * @fires change\n\t * @param {module:engine/view/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`.\n\t * @param {String} [options.label] Label for the fake selection.\n\t */\n\t_setTo( selectable, placeOrOffset, options ) {\n\t\tthis._selection.setTo( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Moves {@link #focus} to the specified location.\n\t *\n\t * The location can be specified in the same form as {@link module:engine/view/view~View#createPositionAt view.createPositionAt()}\n\t * parameters.\n\t *\n\t * @protected\n\t * @fires change\n\t * @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/view/item~Item view item}.\n\t */\n\t_setFocus( itemOrPosition, offset ) {\n\t\tthis._selection.setFocus( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Fired whenever selection ranges are changed through {@link ~DocumentSelection Selection API}.\n\t *\n\t * @event change\n\t */\n}\n\nmix( DocumentSelection, EmitterMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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/collection\n */\n\nimport EmitterMixin from './emittermixin';\nimport CKEditorError from './ckeditorerror';\nimport uid from './uid';\nimport mix from './mix';\n\n/**\n * Collections are ordered sets of objects. Items in the collection can be retrieved by their indexes\n * in the collection (like in an array) or by their ids.\n *\n * If an object without an `id` property is being added to the collection, the `id` property will be generated\n * automatically. Note that the automatically generated id is unique only within this single collection instance.\n *\n * By default an item in the collection is identified by its `id` property. The name of the identifier can be\n * configured through the constructor of the collection.\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class Collection {\n\t/**\n\t * Creates a new Collection instance.\n\t *\n\t * @param {Object} [options={}] The options object.\n\t * @param {String} [options.idProperty='id'] The name of the property which is considered to identify an item.\n\t */\n\tconstructor( options = {} ) {\n\t\t/**\n\t\t * The internal list of items in the collection.\n\t\t *\n\t\t * @private\n\t\t * @member {Object[]}\n\t\t */\n\t\tthis._items = [];\n\n\t\t/**\n\t\t * The internal map of items in the collection.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._itemMap = new Map();\n\n\t\t/**\n\t\t * The name of the property which is considered to identify an item.\n\t\t *\n\t\t * @private\n\t\t * @member {String}\n\t\t */\n\t\tthis._idProperty = options.idProperty || 'id';\n\n\t\t/**\n\t\t * A helper mapping external items of a bound collection ({@link #bindTo})\n\t\t * and actual items of this collection. It provides information\n\t\t * necessary to properly remove items bound to another collection.\n\t\t *\n\t\t * See {@link #_bindToInternalToExternalMap}.\n\t\t *\n\t\t * @protected\n\t\t * @member {WeakMap}\n\t\t */\n\t\tthis._bindToExternalToInternalMap = new WeakMap();\n\n\t\t/**\n\t\t * A helper mapping items of this collection to external items of a bound collection\n\t\t * ({@link #bindTo}). It provides information necessary to manage the bindings, e.g.\n\t\t * to avoid loops in two–way bindings.\n\t\t *\n\t\t * See {@link #_bindToExternalToInternalMap}.\n\t\t *\n\t\t * @protected\n\t\t * @member {WeakMap}\n\t\t */\n\t\tthis._bindToInternalToExternalMap = new WeakMap();\n\n\t\t/**\n\t\t * Stores indexes of skipped items from bound external collection.\n\t\t *\n\t\t * @private\n\t\t * @member {Array}\n\t\t */\n\t\tthis._skippedIndexesFromExternal = [];\n\n\t\t/**\n\t\t * A collection instance this collection is bound to as a result\n\t\t * of calling {@link #bindTo} method.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:utils/collection~Collection} #_bindToCollection\n\t\t */\n\t}\n\n\t/**\n\t * The number of items available in the collection.\n\t *\n\t * @member {Number} #length\n\t */\n\tget length() {\n\t\treturn this._items.length;\n\t}\n\n\t/**\n\t * Returns the first item from the collection or null when collection is empty.\n\t *\n\t * @returns {Object|null} The first item or `null` if collection is empty.\n\t */\n\tget first() {\n\t\treturn this._items[ 0 ] || null;\n\t}\n\n\t/**\n\t * Returns the last item from the collection or null when collection is empty.\n\t *\n\t * @returns {Object|null} The last item or `null` if collection is empty.\n\t */\n\tget last() {\n\t\treturn this._items[ this.length - 1 ] || null;\n\t}\n\n\t/**\n\t * Adds an item into the collection.\n\t *\n\t * If the item does not have an id, then it will be automatically generated and set on the item.\n\t *\n\t * @chainable\n\t * @param {Object} item\n\t * @param {Number} [index] The position of the item in the collection. The item\n\t * is pushed to the collection when `index` not specified.\n\t * @fires add\n\t */\n\tadd( item, index ) {\n\t\tlet itemId;\n\t\tconst idProperty = this._idProperty;\n\n\t\tif ( ( idProperty in item ) ) {\n\t\t\titemId = item[ idProperty ];\n\n\t\t\tif ( typeof itemId != 'string' ) {\n\t\t\t\t/**\n\t\t\t\t * This item's id should be a string.\n\t\t\t\t *\n\t\t\t\t * @error collection-add-invalid-id\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'collection-add-invalid-id', this );\n\t\t\t}\n\n\t\t\tif ( this.get( itemId ) ) {\n\t\t\t\t/**\n\t\t\t\t * This item already exists in the collection.\n\t\t\t\t *\n\t\t\t\t * @error collection-add-item-already-exists\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'collection-add-item-already-exists', this );\n\t\t\t}\n\t\t} else {\n\t\t\titem[ idProperty ] = itemId = uid();\n\t\t}\n\n\t\t// TODO: Use ES6 default function argument.\n\t\tif ( index === undefined ) {\n\t\t\tindex = this._items.length;\n\t\t} else if ( index > this._items.length || index < 0 ) {\n\t\t\t/**\n\t\t\t * The index number has invalid value.\n\t\t\t *\n\t\t\t * @error collection-add-item-bad-index\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'collection-add-item-invalid-index', this );\n\t\t}\n\n\t\tthis._items.splice( index, 0, item );\n\n\t\tthis._itemMap.set( itemId, item );\n\n\t\tthis.fire( 'add', item, index );\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets item by its id or index.\n\t *\n\t * @param {String|Number} idOrIndex The item id or index in the collection.\n\t * @returns {Object|null} The requested item or `null` if such item does not exist.\n\t */\n\tget( idOrIndex ) {\n\t\tlet item;\n\n\t\tif ( typeof idOrIndex == 'string' ) {\n\t\t\titem = this._itemMap.get( idOrIndex );\n\t\t} else if ( typeof idOrIndex == 'number' ) {\n\t\t\titem = this._items[ idOrIndex ];\n\t\t} else {\n\t\t\t/**\n\t\t\t * Index or id must be given.\n\t\t\t *\n\t\t\t * @error collection-get-invalid-arg\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'collection-get-invalid-arg: Index or id must be given.', this );\n\t\t}\n\n\t\treturn item || null;\n\t}\n\n\t/**\n\t * Returns a boolean indicating whether the collection contains an item.\n\t *\n\t * @param {Object|String} itemOrId The item or its id in the collection.\n\t * @returns {Boolean} `true` if the collection contains the item, `false` otherwise.\n\t */\n\thas( itemOrId ) {\n\t\tif ( typeof itemOrId == 'string' ) {\n\t\t\treturn this._itemMap.has( itemOrId );\n\t\t} else { // Object\n\t\t\tconst idProperty = this._idProperty;\n\t\t\tconst id = itemOrId[ idProperty ];\n\n\t\t\treturn this._itemMap.has( id );\n\t\t}\n\t}\n\n\t/**\n\t * Gets index of item in the collection.\n\t * When item is not defined in the collection then index will be equal -1.\n\t *\n\t * @param {Object|String} itemOrId The item or its id in the collection.\n\t * @returns {Number} Index of given item.\n\t */\n\tgetIndex( itemOrId ) {\n\t\tlet item;\n\n\t\tif ( typeof itemOrId == 'string' ) {\n\t\t\titem = this._itemMap.get( itemOrId );\n\t\t} else {\n\t\t\titem = itemOrId;\n\t\t}\n\n\t\treturn this._items.indexOf( item );\n\t}\n\n\t/**\n\t * Removes an item from the collection.\n\t *\n\t * @param {Object|Number|String} subject The item to remove, its id or index in the collection.\n\t * @returns {Object} The removed item.\n\t * @fires remove\n\t */\n\tremove( subject ) {\n\t\tlet index, id, item;\n\t\tlet itemDoesNotExist = false;\n\t\tconst idProperty = this._idProperty;\n\n\t\tif ( typeof subject == 'string' ) {\n\t\t\tid = subject;\n\t\t\titem = this._itemMap.get( id );\n\t\t\titemDoesNotExist = !item;\n\n\t\t\tif ( item ) {\n\t\t\t\tindex = this._items.indexOf( item );\n\t\t\t}\n\t\t} else if ( typeof subject == 'number' ) {\n\t\t\tindex = subject;\n\t\t\titem = this._items[ index ];\n\t\t\titemDoesNotExist = !item;\n\n\t\t\tif ( item ) {\n\t\t\t\tid = item[ idProperty ];\n\t\t\t}\n\t\t} else {\n\t\t\titem = subject;\n\t\t\tid = item[ idProperty ];\n\t\t\tindex = this._items.indexOf( item );\n\t\t\titemDoesNotExist = ( index == -1 || !this._itemMap.get( id ) );\n\t\t}\n\n\t\tif ( itemDoesNotExist ) {\n\t\t\t/**\n\t\t\t * Item not found.\n\t\t\t *\n\t\t\t * @error collection-remove-404\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'collection-remove-404: Item not found.', this );\n\t\t}\n\n\t\tthis._items.splice( index, 1 );\n\t\tthis._itemMap.delete( id );\n\n\t\tconst externalItem = this._bindToInternalToExternalMap.get( item );\n\t\tthis._bindToInternalToExternalMap.delete( item );\n\t\tthis._bindToExternalToInternalMap.delete( externalItem );\n\n\t\tthis.fire( 'remove', item, index );\n\n\t\treturn item;\n\t}\n\n\t/**\n\t * Executes the callback for each item in the collection and composes an array or values returned by this callback.\n\t *\n\t * @param {Function} callback\n\t * @param {Object} callback.item\n\t * @param {Number} callback.index\n\t * @param {Object} ctx Context in which the `callback` will be called.\n\t * @returns {Array} The result of mapping.\n\t */\n\tmap( callback, ctx ) {\n\t\treturn this._items.map( callback, ctx );\n\t}\n\n\t/**\n\t * Finds the first item in the collection for which the `callback` returns a true value.\n\t *\n\t * @param {Function} callback\n\t * @param {Object} callback.item\n\t * @param {Number} callback.index\n\t * @param {Object} ctx Context in which the `callback` will be called.\n\t * @returns {Object} The item for which `callback` returned a true value.\n\t */\n\tfind( callback, ctx ) {\n\t\treturn this._items.find( callback, ctx );\n\t}\n\n\t/**\n\t * Returns an array with items for which the `callback` returned a true value.\n\t *\n\t * @param {Function} callback\n\t * @param {Object} callback.item\n\t * @param {Number} callback.index\n\t * @param {Object} ctx Context in which the `callback` will be called.\n\t * @returns {Object[]} The array with matching items.\n\t */\n\tfilter( callback, ctx ) {\n\t\treturn this._items.filter( callback, ctx );\n\t}\n\n\t/**\n\t * Removes all items from the collection and destroys the binding created using\n\t * {@link #bindTo}.\n\t */\n\tclear() {\n\t\tif ( this._bindToCollection ) {\n\t\t\tthis.stopListening( this._bindToCollection );\n\t\t\tthis._bindToCollection = null;\n\t\t}\n\n\t\twhile ( this.length ) {\n\t\t\tthis.remove( 0 );\n\t\t}\n\t}\n\n\t/**\n\t * Binds and synchronizes the collection with another one.\n\t *\n\t * The binding can be a simple factory:\n\t *\n\t *\t\tclass FactoryClass {\n\t *\t\t\tconstructor( data ) {\n\t *\t\t\t\tthis.label = data.label;\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t *\t\tconst source = new Collection( { idProperty: 'label' } );\n\t *\t\tconst target = new Collection();\n\t *\n\t *\t\ttarget.bindTo( source ).as( FactoryClass );\n\t *\n\t *\t\tsource.add( { label: 'foo' } );\n\t *\t\tsource.add( { label: 'bar' } );\n\t *\n\t *\t\tconsole.log( target.length ); // 2\n\t *\t\tconsole.log( target.get( 1 ).label ); // 'bar'\n\t *\n\t *\t\tsource.remove( 0 );\n\t *\t\tconsole.log( target.length ); // 1\n\t *\t\tconsole.log( target.get( 0 ).label ); // 'bar'\n\t *\n\t * or the factory driven by a custom callback:\n\t *\n\t *\t\tclass FooClass {\n\t *\t\t\tconstructor( data ) {\n\t *\t\t\t\tthis.label = data.label;\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t *\t\tclass BarClass {\n\t *\t\t\tconstructor( data ) {\n\t *\t\t\t\tthis.label = data.label;\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t *\t\tconst source = new Collection( { idProperty: 'label' } );\n\t *\t\tconst target = new Collection();\n\t *\n\t *\t\ttarget.bindTo( source ).using( ( item ) => {\n\t *\t\t\tif ( item.label == 'foo' ) {\n\t *\t\t\t\treturn new FooClass( item );\n\t *\t\t\t} else {\n\t *\t\t\t\treturn new BarClass( item );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\tsource.add( { label: 'foo' } );\n\t *\t\tsource.add( { label: 'bar' } );\n\t *\n\t *\t\tconsole.log( target.length ); // 2\n\t *\t\tconsole.log( target.get( 0 ) instanceof FooClass ); // true\n\t *\t\tconsole.log( target.get( 1 ) instanceof BarClass ); // true\n\t *\n\t * or the factory out of property name:\n\t *\n\t *\t\tconst source = new Collection( { idProperty: 'label' } );\n\t *\t\tconst target = new Collection();\n\t *\n\t *\t\ttarget.bindTo( source ).using( 'label' );\n\t *\n\t *\t\tsource.add( { label: { value: 'foo' } } );\n\t *\t\tsource.add( { label: { value: 'bar' } } );\n\t *\n\t *\t\tconsole.log( target.length ); // 2\n\t *\t\tconsole.log( target.get( 0 ).value ); // 'foo'\n\t *\t\tconsole.log( target.get( 1 ).value ); // 'bar'\n\t *\n\t * It's possible to skip specified items by returning falsy value:\n\t *\n\t *\t\tconst source = new Collection();\n\t *\t\tconst target = new Collection();\n\t *\n\t *\t\ttarget.bindTo( source ).using( item => {\n\t *\t\t\tif ( item.hidden ) {\n\t *\t\t\t\treturn null;\n\t *\t\t\t}\n\t *\n\t *\t\t\treturn item;\n\t *\t\t} );\n\t *\n\t *\t\tsource.add( { hidden: true } );\n\t *\t\tsource.add( { hidden: false } );\n\t *\n\t *\t\tconsole.log( source.length ); // 2\n\t *\t\tconsole.log( target.length ); // 1\n\t *\n\t * **Note**: {@link #clear} can be used to break the binding.\n\t *\n\t * @param {module:utils/collection~Collection} externalCollection A collection to be bound.\n\t * @returns {Object}\n\t * @returns {module:utils/collection~CollectionBindToChain} The binding chain object.\n\t */\n\tbindTo( externalCollection ) {\n\t\tif ( this._bindToCollection ) {\n\t\t\t/**\n\t\t\t * The collection cannot be bound more than once.\n\t\t\t *\n\t\t\t * @error collection-bind-to-rebind\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'collection-bind-to-rebind: The collection cannot be bound more than once.', this );\n\t\t}\n\n\t\tthis._bindToCollection = externalCollection;\n\n\t\treturn {\n\t\t\tas: Class => {\n\t\t\t\tthis._setUpBindToBinding( item => new Class( item ) );\n\t\t\t},\n\n\t\t\tusing: callbackOrProperty => {\n\t\t\t\tif ( typeof callbackOrProperty == 'function' ) {\n\t\t\t\t\tthis._setUpBindToBinding( item => callbackOrProperty( item ) );\n\t\t\t\t} else {\n\t\t\t\t\tthis._setUpBindToBinding( item => item[ callbackOrProperty ] );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Finalizes and activates a binding initiated by {#bindTo}.\n\t *\n\t * @protected\n\t * @param {Function} factory A function which produces collection items.\n\t */\n\t_setUpBindToBinding( factory ) {\n\t\tconst externalCollection = this._bindToCollection;\n\n\t\t// Adds the item to the collection once a change has been done to the external collection.\n\t\t//\n\t\t// @private\n\t\tconst addItem = ( evt, externalItem, index ) => {\n\t\t\tconst isExternalBoundToThis = externalCollection._bindToCollection == this;\n\t\t\tconst externalItemBound = externalCollection._bindToInternalToExternalMap.get( externalItem );\n\n\t\t\t// If an external collection is bound to this collection, which makes it a 2–way binding,\n\t\t\t// and the particular external collection item is already bound, don't add it here.\n\t\t\t// The external item has been created **out of this collection's item** and (re)adding it will\n\t\t\t// cause a loop.\n\t\t\tif ( isExternalBoundToThis && externalItemBound ) {\n\t\t\t\tthis._bindToExternalToInternalMap.set( externalItem, externalItemBound );\n\t\t\t\tthis._bindToInternalToExternalMap.set( externalItemBound, externalItem );\n\t\t\t} else {\n\t\t\t\tconst item = factory( externalItem );\n\n\t\t\t\t// When there is no item we need to remember skipped index first and then we can skip this item.\n\t\t\t\tif ( !item ) {\n\t\t\t\t\tthis._skippedIndexesFromExternal.push( index );\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Lets try to put item at the same index as index in external collection\n\t\t\t\t// but when there are a skipped items in one or both collections we need to recalculate this index.\n\t\t\t\tlet finalIndex = index;\n\n\t\t\t\t// When we try to insert item after some skipped items from external collection we need\n\t\t\t\t// to include this skipped items and decrease index.\n\t\t\t\t//\n\t\t\t\t// For the following example:\n\t\t\t\t// external -> [ 'A', 'B - skipped for internal', 'C - skipped for internal' ]\n\t\t\t\t// internal -> [ A ]\n\t\t\t\t//\n\t\t\t\t// Another item is been added at the end of external collection:\n\t\t\t\t// external.add( 'D' )\n\t\t\t\t// external -> [ 'A', 'B - skipped for internal', 'C - skipped for internal', 'D' ]\n\t\t\t\t//\n\t\t\t\t// We can't just add 'D' to internal at the same index as index in external because\n\t\t\t\t// this will produce empty indexes what is invalid:\n\t\t\t\t// internal -> [ 'A', empty, empty, 'D' ]\n\t\t\t\t//\n\t\t\t\t// So we need to include skipped items and decrease index\n\t\t\t\t// internal -> [ 'A', 'D' ]\n\t\t\t\tfor ( const skipped of this._skippedIndexesFromExternal ) {\n\t\t\t\t\tif ( index > skipped ) {\n\t\t\t\t\t\tfinalIndex--;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// We need to take into consideration that external collection could skip some items from\n\t\t\t\t// internal collection.\n\t\t\t\t//\n\t\t\t\t// For the following example:\n\t\t\t\t// internal -> [ 'A', 'B - skipped for external', 'C - skipped for external' ]\n\t\t\t\t// external -> [ A ]\n\t\t\t\t//\n\t\t\t\t// Another item is been added at the end of external collection:\n\t\t\t\t// external.add( 'D' )\n\t\t\t\t// external -> [ 'A', 'D' ]\n\t\t\t\t//\n\t\t\t\t// We need to include skipped items and place new item after them:\n\t\t\t\t// internal -> [ 'A', 'B - skipped for external', 'C - skipped for external', 'D' ]\n\t\t\t\tfor ( const skipped of externalCollection._skippedIndexesFromExternal ) {\n\t\t\t\t\tif ( finalIndex >= skipped ) {\n\t\t\t\t\t\tfinalIndex++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis._bindToExternalToInternalMap.set( externalItem, item );\n\t\t\t\tthis._bindToInternalToExternalMap.set( item, externalItem );\n\t\t\t\tthis.add( item, finalIndex );\n\n\t\t\t\t// After adding new element to internal collection we need update indexes\n\t\t\t\t// of skipped items in external collection.\n\t\t\t\tfor ( let i = 0; i < externalCollection._skippedIndexesFromExternal.length; i++ ) {\n\t\t\t\t\tif ( finalIndex <= externalCollection._skippedIndexesFromExternal[ i ] ) {\n\t\t\t\t\t\texternalCollection._skippedIndexesFromExternal[ i ]++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Load the initial content of the collection.\n\t\tfor ( const externalItem of externalCollection ) {\n\t\t\taddItem( null, externalItem, externalCollection.getIndex( externalItem ) );\n\t\t}\n\n\t\t// Synchronize the with collection as new items are added.\n\t\tthis.listenTo( externalCollection, 'add', addItem );\n\n\t\t// Synchronize the with collection as new items are removed.\n\t\tthis.listenTo( externalCollection, 'remove', ( evt, externalItem, index ) => {\n\t\t\tconst item = this._bindToExternalToInternalMap.get( externalItem );\n\n\t\t\tif ( item ) {\n\t\t\t\tthis.remove( item );\n\t\t\t}\n\n\t\t\t// After removing element from external collection we need update/remove indexes\n\t\t\t// of skipped items in internal collection.\n\t\t\tthis._skippedIndexesFromExternal = this._skippedIndexesFromExternal.reduce( ( result, skipped ) => {\n\t\t\t\tif ( index < skipped ) {\n\t\t\t\t\tresult.push( skipped - 1 );\n\t\t\t\t}\n\n\t\t\t\tif ( index > skipped ) {\n\t\t\t\t\tresult.push( skipped );\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t}, [] );\n\t\t} );\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this._items[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Fired when an item is added to the collection.\n\t *\n\t * @event add\n\t * @param {Object} item The added item.\n\t */\n\n\t/**\n\t * Fired when an item is removed from the collection.\n\t *\n\t * @event remove\n\t * @param {Object} item The removed item.\n\t * @param {Number} index Index from which item was removed.\n\t */\n}\n\nmix( Collection, EmitterMixin );\n\n/**\n * An object returned by the {@link module:utils/collection~Collection#bindTo `bindTo()`} method\n * providing functions that specify the type of the binding.\n *\n * See the {@link module:utils/collection~Collection#bindTo `bindTo()`} documentation for examples.\n *\n * @interface module:utils/collection~CollectionBindToChain\n */\n\n/**\n * Creates a callback or a property binding.\n *\n * @method #using\n * @param {Function|String} callbackOrProperty When the function is passed, it should return\n * the collection items. When the string is provided, the property value is used to create the bound collection items.\n */\n\n/**\n * Creates the class factory binding in which items of the source collection are passed to\n * the constructor of the specified class.\n *\n * @method #as\n * @param {Function} Class The class constructor used to create instances in the factory.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/document\n */\n\nimport DocumentSelection from './documentselection';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\n\n/**\n * Document class creates an abstract layer over the content editable area, contains a tree of view elements and\n * {@link module:engine/view/documentselection~DocumentSelection view selection} associated with this document.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class Document {\n\t/**\n\t * Creates a Document instance.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Selection done on this document.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/documentselection~DocumentSelection} module:engine/view/document~Document#selection\n\t\t */\n\t\tthis.selection = new DocumentSelection();\n\n\t\t/**\n\t\t * Roots of the view tree. Collection of the {@link module:engine/view/element~Element view elements}.\n\t\t *\n\t\t * View roots are created as a result of binding between {@link module:engine/view/document~Document#roots} and\n\t\t * {@link module:engine/model/document~Document#roots} and this is handled by\n\t\t * {@link module:engine/controller/editingcontroller~EditingController}, so to create view root we need to create\n\t\t * model root using {@link module:engine/model/document~Document#createRoot}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/collection~Collection} module:engine/view/document~Document#roots\n\t\t */\n\t\tthis.roots = new Collection( { idProperty: 'rootName' } );\n\n\t\t/**\n\t\t * Defines whether document is in read-only mode.\n\t\t *\n\t\t * When document is read-ony then all roots are read-only as well and caret placed inside this root is hidden.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isReadOnly\n\t\t */\n\t\tthis.set( 'isReadOnly', false );\n\n\t\t/**\n\t\t * True if document is focused.\n\t\t *\n\t\t * This property is updated by the {@link module:engine/view/observer/focusobserver~FocusObserver}.\n\t\t * If the {@link module:engine/view/observer/focusobserver~FocusObserver} is disabled this property will not change.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Boolean} module:engine/view/document~Document#isFocused\n\t\t */\n\t\tthis.set( 'isFocused', false );\n\n\t\t/**\n\t\t * True if composition is in progress inside the document.\n\t\t *\n\t\t * This property is updated by the {@link module:engine/view/observer/compositionobserver~CompositionObserver}.\n\t\t * If the {@link module:engine/view/observer/compositionobserver~CompositionObserver} is disabled this property will not change.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Boolean} module:engine/view/document~Document#isComposing\n\t\t */\n\t\tthis.set( 'isComposing', false );\n\n\t\t/**\n\t\t * Post-fixer callbacks registered to the view document.\n\t\t *\n\t\t * @private\n\t\t * @member {Set}\n\t\t */\n\t\tthis._postFixers = new Set();\n\t}\n\n\t/**\n\t * Gets a {@link module:engine/view/document~Document#roots view root element} with the specified name. If the name is not\n\t * specific \"main\" root is returned.\n\t *\n\t * @param {String} [name='main'] Name of the root.\n\t * @returns {module:engine/view/rooteditableelement~RootEditableElement|null} The view root element with the specified name\n\t * or null when there is no root of given name.\n\t */\n\tgetRoot( name = 'main' ) {\n\t\treturn this.roots.get( name );\n\t}\n\n\t/**\n\t * Allows registering post-fixer callbacks. A post-fixers mechanism allows to update the view tree just before it is rendered\n\t * to the DOM.\n\t *\n\t * Post-fixers are executed right after all changes from the outermost change block were applied but\n\t * before the {@link module:engine/view/view~View#event:render render event} is fired. If a post-fixer callback made\n\t * a change, it should return `true`. When this happens, all post-fixers are fired again to check if something else should\n\t * not be fixed in the new document tree state.\n\t *\n\t * View post-fixers are useful when you want to apply some fixes whenever the view structure changes. Keep in mind that\n\t * changes executed in a view post-fixer should not break model-view mapping.\n\t *\n\t * The types of changes which should be safe:\n\t *\n\t * * adding or removing attribute from elements,\n\t * * changes inside of {@link module:engine/view/uielement~UIElement UI elements},\n\t * * {@link module:engine/model/differ~Differ#refreshItem marking some of the model elements to be re-converted}.\n\t *\n\t * Try to avoid changes which touch view structure:\n\t *\n\t * * you should not add or remove nor wrap or unwrap any view elements,\n\t * * you should not change the editor data model in a view post-fixer.\n\t *\n\t * As a parameter, a post-fixer callback receives a {@link module:engine/view/downcastwriter~DowncastWriter downcast writer}.\n\t *\n\t * Typically, a post-fixer will look like this:\n\t *\n\t *\t\teditor.editing.view.document.registerPostFixer( writer => {\n\t *\t\t\tif ( checkSomeCondition() ) {\n\t *\t\t\t\twriter.doSomething();\n\t *\n\t *\t\t\t\t// Let other post-fixers know that something changed.\n\t *\t\t\t\treturn true;\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * Note that nothing happens right after you register a post-fixer (e.g. execute such a code in the console).\n\t * That is because adding a post-fixer does not execute it.\n\t * The post-fixer will be executed as soon as any change in the document needs to cause its rendering.\n\t * If you want to re-render the editor's view after registering the post-fixer then you should do it manually by calling\n\t * {@link module:engine/view/view~View#forceRender `view.forceRender()`}.\n\t *\n\t * If you need to register a callback which is executed when DOM elements are already updated,\n\t * use {@link module:engine/view/view~View#event:render render event}.\n\t *\n\t * @param {Function} postFixer\n\t */\n\tregisterPostFixer( postFixer ) {\n\t\tthis._postFixers.add( postFixer );\n\t}\n\n\t/**\n\t * Destroys this instance. Makes sure that all observers are destroyed and listeners removed.\n\t */\n\tdestroy() {\n\t\tthis.roots.map( root => root.destroy() );\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Performs post-fixer loops. Executes post-fixer callbacks as long as none of them has done any changes to the model.\n\t *\n\t * @protected\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n\t */\n\t_callPostFixers( writer ) {\n\t\tlet wasFixed = false;\n\n\t\tdo {\n\t\t\tfor ( const callback of this._postFixers ) {\n\t\t\t\twasFixed = callback( writer );\n\n\t\t\t\tif ( wasFixed ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( wasFixed );\n\t}\n\n\t/**\n\t * Event fired whenever document content layout changes. It is fired whenever content is\n\t * {@link module:engine/view/view~View#event:render rendered}, but should be also fired by observers in case of\n\t * other actions which may change layout, for instance when image loads.\n\t *\n\t * @event layoutChanged\n\t */\n}\n\nmix( Document, ObservableMixin );\n\n/**\n * Enum representing type of the change.\n *\n * Possible values:\n *\n * * `children` - for child list changes,\n * * `attributes` - for element attributes changes,\n * * `text` - for text nodes changes.\n *\n * @typedef {String} module:engine/view/document~ChangeType\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/attributeelement\n */\n\nimport Element from './element';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n// Default attribute priority.\nconst DEFAULT_PRIORITY = 10;\n\n/**\n * Attribute elements are used to represent formatting elements in the view (think – `<b>`, `<span style=\"font-size: 2em\">`, etc.).\n * Most often they are created when downcasting model text attributes.\n *\n * Editing engine does not define a fixed HTML DTD. This is why a feature developer needs to choose between various\n * types (container element, {@link module:engine/view/attributeelement~AttributeElement attribute element},\n * {@link module:engine/view/emptyelement~EmptyElement empty element}, etc) when developing a feature.\n *\n * To create a new attribute element instance use the\n * {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement `DowncastWriter#createAttributeElement()`} method.\n *\n * @extends module:engine/view/element~Element\n */\nexport default class AttributeElement extends Element {\n\t/**\n\t * Creates an attribute element.\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#createAttributeElement\n\t * @see module:engine/view/element~Element\n\t * @protected\n\t */\n\tconstructor( name, attrs, children ) {\n\t\tsuper( name, attrs, children );\n\n\t\t/**\n\t\t * Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.\n\t\t *\n\t\t * @method #getFillerOffset\n\t\t * @returns {Number|null} Block filler offset or `null` if block filler is not needed.\n\t\t */\n\t\tthis.getFillerOffset = getFillerOffset;\n\n\t\t/**\n\t\t * Element priority. Decides in what order elements are wrapped by {@link module:engine/view/downcastwriter~DowncastWriter}.\n\t\t *\n\t\t * @protected\n\t\t * @member {Number}\n\t\t */\n\t\tthis._priority = DEFAULT_PRIORITY;\n\n\t\t/**\n\t\t * Element identifier. If set, it is used by {@link module:engine/view/element~Element#isSimilar},\n\t\t * and then two elements are considered similar if, and only if they have the same `_id`.\n\t\t *\n\t\t * @protected\n\t\t * @member {String|Number}\n\t\t */\n\t\tthis._id = null;\n\n\t\t/**\n\t\t * Keeps all the attribute elements that have the same {@link module:engine/view/attributeelement~AttributeElement#id ids}\n\t\t * and still exist in the view tree.\n\t\t *\n\t\t * This property is managed by {@link module:engine/view/downcastwriter~DowncastWriter}.\n\t\t *\n\t\t * @protected\n\t\t * @member {Set.<module:engine/view/attributeelement~AttributeElement>|null}\n\t\t */\n\t\tthis._clonesGroup = null;\n\t}\n\n\t/**\n\t * Element priority. Decides in what order elements are wrapped by {@link module:engine/view/downcastwriter~DowncastWriter}.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget priority() {\n\t\treturn this._priority;\n\t}\n\n\t/**\n\t * Element identifier. If set, it is used by {@link module:engine/view/element~Element#isSimilar},\n\t * and then two elements are considered similar if, and only if they have the same `id`.\n\t *\n\t * @readonly\n\t * @type {String|Number}\n\t */\n\tget id() {\n\t\treturn this._id;\n\t}\n\n\t/**\n\t * Returns all {@link module:engine/view/attributeelement~AttributeElement attribute elements} that has the\n\t * same {@link module:engine/view/attributeelement~AttributeElement#id id} and are in the view tree (were not removed).\n\t *\n\t * Note: If this element has been removed from the tree, returned set will not include it.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError attribute-element-get-elements-with-same-id-no-id}\n\t * if this element has no `id`.\n\t *\n\t * @returns {Set.<module:engine/view/attributeelement~AttributeElement>} Set containing all the attribute elements\n\t * with the same `id` that were added and not removed from the view tree.\n\t */\n\tgetElementsWithSameId() {\n\t\tif ( this.id === null ) {\n\t\t\t/**\n\t\t\t * Cannot get elements with the same id for an attribute element without id.\n\t\t\t *\n\t\t\t * @error attribute-element-get-elements-with-same-id-no-id\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'attribute-element-get-elements-with-same-id-no-id: ' +\n\t\t\t\t'Cannot get elements with the same id for an attribute element without id.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\treturn new Set( this._clonesGroup );\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tattributeElement.is( 'attributeElement' ); // -> true\n\t *\t\tattributeElement.is( 'element' ); // -> true\n\t *\t\tattributeElement.is( 'node' ); // -> true\n\t *\t\tattributeElement.is( 'view:attributeElement' ); // -> true\n\t *\t\tattributeElement.is( 'view:element' ); // -> true\n\t *\t\tattributeElement.is( 'view:node' ); // -> true\n\t *\n\t *\t\tattributeElement.is( 'model:element' ); // -> false\n\t *\t\tattributeElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is an attribute element, you can also check its\n\t * {@link module:engine/view/attributeelement~AttributeElement#name name}:\n\t *\n\t *\t\tattributeElement.is( 'b' ); // -> true if this is a bold element\n\t *\t\tattributeElement.is( 'attributeElement', 'b' ); // -> same as above\n\t *\t\ttext.is( 'b' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tconst cutType = type && type.replace( /^view:/, '' );\n\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'attributeElement' || super.is( type );\n\t\t} else {\n\t\t\treturn ( cutType == 'attributeElement' && name == this.name ) || super.is( type, name );\n\t\t}\n\t}\n\n\t/**\n\t * Checks if this element is similar to other element.\n\t *\n\t * If none of elements has set {@link module:engine/view/attributeelement~AttributeElement#id}, then both elements\n\t * should have the same name, attributes and priority to be considered as similar. Two similar elements can contain\n\t * different set of children nodes.\n\t *\n\t * If at least one element has {@link module:engine/view/attributeelement~AttributeElement#id} set, then both\n\t * elements have to have the same {@link module:engine/view/attributeelement~AttributeElement#id} value to be\n\t * considered similar.\n\t *\n\t * Similarity is important for {@link module:engine/view/downcastwriter~DowncastWriter}. For example:\n\t *\n\t * * two following similar elements can be merged together into one, longer element,\n\t * * {@link module:engine/view/downcastwriter~DowncastWriter#unwrap} checks similarity of passed element and processed element to\n\t * decide whether processed element should be unwrapped,\n\t * * etc.\n\t *\n\t * @param {module:engine/view/element~Element} otherElement\n\t * @returns {Boolean}\n\t */\n\tisSimilar( otherElement ) {\n\t\t// If any element has an `id` set, just compare the ids.\n\t\tif ( this.id !== null || otherElement.id !== null ) {\n\t\t\treturn this.id === otherElement.id;\n\t\t}\n\n\t\treturn super.isSimilar( otherElement ) && this.priority == otherElement.priority;\n\t}\n\n\t/**\n\t * Clones provided element with priority.\n\t *\n\t * @protected\n\t * @param {Boolean} deep If set to `true` clones element and all its children recursively. When set to `false`,\n\t * element will be cloned without any children.\n\t * @returns {module:engine/view/attributeelement~AttributeElement} Clone of this element.\n\t */\n\t_clone( deep ) {\n\t\tconst cloned = super._clone( deep );\n\n\t\t// Clone priority too.\n\t\tcloned._priority = this._priority;\n\n\t\t// And id too.\n\t\tcloned._id = this._id;\n\n\t\treturn cloned;\n\t}\n}\n\n/**\n * Default attribute priority.\n *\n * @member {Number} module:engine/view/attributeelement~AttributeElement.DEFAULT_PRIORITY\n */\nAttributeElement.DEFAULT_PRIORITY = DEFAULT_PRIORITY;\n\n// Returns block {@link module:engine/view/filler~Filler filler} offset or `null` if block filler is not needed.\n//\n// @returns {Number|null} Block filler offset or `null` if block filler is not needed.\nfunction getFillerOffset() {\n\t// <b>foo</b> does not need filler.\n\tif ( nonUiChildrenCount( this ) ) {\n\t\treturn null;\n\t}\n\n\tlet element = this.parent;\n\n\t// <p><b></b></p> needs filler -> <p><b><br></b></p>\n\twhile ( element && element.is( 'attributeElement' ) ) {\n\t\tif ( nonUiChildrenCount( element ) > 1 ) {\n\t\t\treturn null;\n\t\t}\n\n\t\telement = element.parent;\n\t}\n\n\tif ( !element || nonUiChildrenCount( element ) > 1 ) {\n\t\treturn null;\n\t}\n\n\t// Render block filler at the end of element (after all ui elements).\n\treturn this.childCount;\n}\n\n// Returns total count of children that are not {@link module:engine/view/uielement~UIElement UIElements}.\n//\n// @param {module:engine/view/element~Element} element\n// @returns {Number}\nfunction nonUiChildrenCount( element ) {\n\treturn Array.from( element.getChildren() ).filter( element => !element.is( 'uiElement' ) ).length;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/emptyelement\n */\n\nimport Element from './element';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport Node from './node';\n\n/**\n * Empty element class. It is used to represent elements that cannot contain any child nodes (for example `<img>` elements).\n *\n * To create a new empty element use the\n * {@link module:engine/view/downcastwriter~DowncastWriter#createEmptyElement `downcastWriter#createEmptyElement()`} method.\n *\n * @extends module:engine/view/element~Element\n */\nexport default class EmptyElement extends Element {\n\t/**\n\t * Creates new instance of EmptyElement.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-emptyelement-cannot-add` when third parameter is passed,\n\t * to inform that usage of EmptyElement is incorrect (adding child nodes to EmptyElement is forbidden).\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#createEmptyElement\n\t * @protected\n\t * @param {String} name Node name.\n\t * @param {Object|Iterable} [attributes] Collection of attributes.\n\t */\n\tconstructor( name, attributes, children ) {\n\t\tsuper( name, attributes, children );\n\n\t\t/**\n\t\t * Returns `null` because filler is not needed for EmptyElements.\n\t\t *\n\t\t * @method #getFillerOffset\n\t\t * @returns {null} Always returns null.\n\t\t */\n\t\tthis.getFillerOffset = getFillerOffset;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\temptyElement.is( 'emptyElement' ); // -> true\n\t *\t\temptyElement.is( 'element' ); // -> true\n\t *\t\temptyElement.is( 'node' ); // -> true\n\t *\t\temptyElement.is( 'view:emptyElement' ); // -> true\n\t *\t\temptyElement.is( 'view:element' ); // -> true\n\t *\t\temptyElement.is( 'view:node' ); // -> true\n\t *\n\t *\t\temptyElement.is( 'model:element' ); // -> false\n\t *\t\temptyElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is an empty element, you can also check its\n\t * {@link module:engine/view/emptyelement~EmptyElement#name name}:\n\t *\n\t *\t\temptyElement.is( 'img' ); // -> true if this is a img element\n\t *\t\temptyElement.is( 'emptyElement', 'img' ); // -> same as above\n\t *\t\ttext.is( 'img' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tconst cutType = type.replace( /^view:/, '' );\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'emptyElement' || super.is( type );\n\t\t} else {\n\t\t\treturn ( cutType == 'emptyElement' && name == this.name ) || super.is( type, name );\n\t\t}\n\t}\n\n\t/**\n\t * Overrides {@link module:engine/view/element~Element#_insertChild} method.\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-emptyelement-cannot-add` to prevent\n\t * adding any child nodes to EmptyElement.\n\t *\n\t * @protected\n\t */\n\t_insertChild( index, nodes ) {\n\t\tif ( nodes && ( nodes instanceof Node || Array.from( nodes ).length > 0 ) ) {\n\t\t\t/**\n\t\t\t * Cannot add children to {@link module:engine/view/emptyelement~EmptyElement}.\n\t\t\t *\n\t\t\t * @error view-emptyelement-cannot-add\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'view-emptyelement-cannot-add: Cannot add child nodes to EmptyElement instance.',\n\t\t\t\t[ this, nodes ]\n\t\t\t);\n\t\t}\n\t}\n}\n\n// Returns `null` because block filler is not needed for EmptyElements.\n//\n// @returns {null}\nfunction getFillerOffset() {\n\treturn null;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 Microsoft Edge.\n\t *\n\t * @static\n\t * @type {Boolean}\n\t */\n\tisEdge: isEdge( 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 * 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 Microsoft Edge.\n *\n * @param {String} userAgent **Lowercase** `navigator.userAgent` string.\n * @returns {Boolean} Whether User Agent is Edge or not.\n */\nexport function isEdge( userAgent ) {\n\treturn !!userAgent.match( /edge\\/(\\d+.?\\d*)/ );\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 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 and Edge do 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-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Set of utils related to keyboard support.\n *\n * @module utils/keyboard\n */\n\nimport CKEditorError from './ckeditorerror';\nimport env from './env';\n\nconst macGlyphsToModifiers = {\n\t'⌘': 'ctrl',\n\t'⇧': 'shift',\n\t'⌥': 'alt'\n};\n\nconst modifiersToMacGlyphs = {\n\t'ctrl': '⌘',\n\t'shift': '⇧',\n\t'alt': '⌥'\n};\n\n/**\n * 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\n/**\n * Converts a key name or a {@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} 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 contained by the {@link module:utils/keyboard~keyCodes} can be used.\n\t\t\t *\n\t\t\t * @errror keyboard-unknown-key\n\t\t\t * @param {String} key\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'keyboard-unknown-key: Unknown key name.',\n\t\t\t\tnull, { key }\n\t\t\t);\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}\n\n\treturn keyCode;\n}\n\n/**\n * Parses keystroke and returns a keystroke code that will match the code returned by\n * link {@link module:utils/keyboard.getCode} for a 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 * @param {String|Array.<Number|String>} keystroke 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' ) ? getCode( key ) : key )\n\t\t.reduce( ( key, sum ) => sum + key, 0 );\n}\n\n/**\n * It translates any keystroke string text like `\"CTRL+A\"` to an\n * environment–specific keystroke, i.e. `\"⌘A\"` on Mac OSX.\n *\n * @param {String} keystroke Keystroke text.\n * @returns {String} Keystroke text specific for the environment.\n */\nexport function getEnvKeystrokeText( keystroke ) {\n\tif ( !env.isMac ) {\n\t\treturn keystroke;\n\t}\n\n\treturn splitKeystrokeText( keystroke )\n\t\t// Replace modifiers (e.g. \"ctrl\") with Mac glyphs (e.g. \"⌘\") first.\n\t\t.map( key => modifiersToMacGlyphs[ key.toLowerCase() ] || key )\n\n\t\t// Decide whether to put \"+\" between keys in the keystroke or not.\n\t\t.reduce( ( value, key ) => {\n\t\t\tif ( value.slice( -1 ) in macGlyphsToModifiers ) {\n\t\t\t\treturn value + key;\n\t\t\t} else {\n\t\t\t\treturn value + '+' + key;\n\t\t\t}\n\t\t} );\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\t// Has the same code as ctrl, because their behaviour should be unified across the editor.\n\t\t// See http://ckeditor.github.io/editor-recommendations/general-policies#ctrl-vs-cmd\n\t\tcmd: 0x110000,\n\t\tshift: 0x220000,\n\t\talt: 0x440000\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( /\\s*\\+\\s*/ );\n}\n\n/**\n * Information about a 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 <kbd>Alt</kbd> modifier was pressed.\n *\n * @member {Bolean} module:utils/keyboard~KeystrokeInfo#altKey\n */\n\n/**\n * Whether the <kbd>Ctrl</kbd> or <kbd>Cmd</kbd> modifier was pressed.\n *\n * @member {Bolean} module:utils/keyboard~KeystrokeInfo#ctrlKey\n */\n\n/**\n * Whether the <kbd>Shift</kbd> modifier was pressed.\n *\n * @member {Bolean} module:utils/keyboard~KeystrokeInfo#shiftKey\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/uielement\n */\n\nimport Element from './element';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport Node from './node';\nimport { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';\n\n/**\n * UI element class. It should be used to represent editing UI which needs to be injected into the editing view\n * If possible, you should keep your UI outside the editing view. However, if that is not possible,\n * UI elements can be used.\n *\n * How a UI element is rendered is in your control (you pass a callback to\n * {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement `downcastWriter#createUIElement()`}).\n * The editor will ignore your UI element – the selection cannot be placed in it, it is skipped (invisible) when\n * the user modifies the selection by using arrow keys and the editor does not listen to any mutations which\n * happen inside your UI elements.\n *\n * The limitation is that you cannot convert a model element to a UI element. UI elements need to be\n * created for {@link module:engine/model/markercollection~Marker markers} or as additinal elements\n * inside normal {@link module:engine/view/containerelement~ContainerElement container elements}.\n *\n * To create a new UI element use the\n * {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement `downcastWriter#createUIElement()`} method.\n *\n * @extends module:engine/view/element~Element\n */\nexport default class UIElement extends Element {\n\t/**\n\t * Creates new instance of UIElement.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-uielement-cannot-add` when third parameter is passed,\n\t * to inform that usage of UIElement is incorrect (adding child nodes to UIElement is forbidden).\n\t *\n\t * @see module:engine/view/downcastwriter~DowncastWriter#createUIElement\n\t * @protected\n\t * @param {String} name Node name.\n\t * @param {Object|Iterable} [attributes] Collection of attributes.\n\t */\n\tconstructor( name, attributes, children ) {\n\t\tsuper( name, attributes, children );\n\n\t\t/**\n\t\t * Returns `null` because filler is not needed for UIElements.\n\t\t *\n\t\t * @method #getFillerOffset\n\t\t * @returns {null} Always returns null.\n\t\t */\n\t\tthis.getFillerOffset = getFillerOffset;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tuiElement.is( 'uiElement' ); // -> true\n\t *\t\tuiElement.is( 'element' ); // -> true\n\t *\t\tuiElement.is( 'node' ); // -> true\n\t *\t\tuiElement.is( 'view:uiElement' ); // -> true\n\t *\t\tuiElement.is( 'view:element' ); // -> true\n\t *\t\tuiElement.is( 'view:node' ); // -> true\n\t *\n\t *\t\tuiElement.is( 'model:element' ); // -> false\n\t *\t\tuiElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is an ui element, you can also check its\n\t * {@link module:engine/view/uielement~UIElement#name name}:\n\t *\n\t *\t\tuiElement.is( 'span' ); // -> true if this is a span ui element\n\t *\t\tuiElement.is( 'uiElement', 'span' ); // -> same as above\n\t *\t\ttext.is( 'span' ); -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tconst cutType = type.replace( /^view:/, '' );\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'uiElement' || super.is( type );\n\t\t} else {\n\t\t\treturn ( cutType == 'uiElement' && name == this.name ) || super.is( type, name );\n\t\t}\n\t}\n\n\t/**\n\t * Overrides {@link module:engine/view/element~Element#_insertChild} method.\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-uielement-cannot-add` to prevent adding any child nodes\n\t * to UIElement.\n\t *\n\t * @protected\n\t */\n\t_insertChild( index, nodes ) {\n\t\tif ( nodes && ( nodes instanceof Node || Array.from( nodes ).length > 0 ) ) {\n\t\t\t/**\n\t\t\t * Cannot add children to {@link module:engine/view/uielement~UIElement}.\n\t\t\t *\n\t\t\t * @error view-uielement-cannot-add\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-uielement-cannot-add: Cannot add child nodes to UIElement instance.', this );\n\t\t}\n\t}\n\n\t/**\n\t * Renders this {@link module:engine/view/uielement~UIElement} to DOM. This method is called by\n\t * {@link module:engine/view/domconverter~DomConverter}.\n\t * Do not use inheritance to create custom rendering method, replace `render()` method instead:\n\t *\n\t *\t\tconst myUIElement = downcastWriter.createUIElement( 'span' );\n\t *\t\tmyUIElement.render = function( domDocument ) {\n\t *\t\t\tconst domElement = this.toDomElement( domDocument );\n\t *\t\t\tdomElement.innerHTML = '<b>this is ui element</b>';\n\t *\n\t *\t\t\treturn domElement;\n\t *\t\t};\n\t *\n\t * @param {Document} domDocument\n\t * @returns {HTMLElement}\n\t */\n\trender( domDocument ) {\n\t\treturn this.toDomElement( domDocument );\n\t}\n\n\t/**\n\t * Creates DOM element based on this view UIElement.\n\t * Note that each time this method is called new DOM element is created.\n\t *\n\t * @param {Document} domDocument\n\t * @returns {HTMLElement}\n\t */\n\ttoDomElement( domDocument ) {\n\t\tconst domElement = domDocument.createElement( this.name );\n\n\t\tfor ( const key of this.getAttributeKeys() ) {\n\t\t\tdomElement.setAttribute( key, this.getAttribute( key ) );\n\t\t}\n\n\t\treturn domElement;\n\t}\n}\n\n/**\n * This function injects UI element handling to the given {@link module:engine/view/document~Document document}.\n *\n * A callback is added to {@link module:engine/view/document~Document#event:keydown document keydown event}.\n * The callback handles the situation when right arrow key is pressed and selection is collapsed before a UI element.\n * Without this handler, it would be impossible to \"jump over\" UI element using right arrow key.\n *\n * @param {module:engine/view/view~View} view View controller to which the quirks handling will be injected.\n */\nexport function injectUiElementHandling( view ) {\n\tview.document.on( 'keydown', ( evt, data ) => jumpOverUiElement( evt, data, view.domConverter ) );\n}\n\n// Returns `null` because block filler is not needed for UIElements.\n//\n// @returns {null}\nfunction getFillerOffset() {\n\treturn null;\n}\n\n// Selection cannot be placed in a `UIElement`. Whenever it is placed there, it is moved before it. This\n// causes a situation when it is impossible to jump over `UIElement` using right arrow key, because the selection\n// ends up in ui element (in DOM) and is moved back to the left. This handler fixes this situation.\nfunction jumpOverUiElement( evt, data, domConverter ) {\n\tif ( data.keyCode == keyCodes.arrowright ) {\n\t\tconst domSelection = data.domTarget.ownerDocument.defaultView.getSelection();\n\t\tconst domSelectionCollapsed = domSelection.rangeCount == 1 && domSelection.getRangeAt( 0 ).collapsed;\n\n\t\t// Jump over UI element if selection is collapsed or shift key is pressed. These are the cases when selection would extend.\n\t\tif ( domSelectionCollapsed || data.shiftKey ) {\n\t\t\tconst domParent = domSelection.focusNode;\n\t\t\tconst domOffset = domSelection.focusOffset;\n\n\t\t\tconst viewPosition = domConverter.domPositionToView( domParent, domOffset );\n\n\t\t\t// In case if dom element is not converted to view or is not mapped or something. Happens for example in some tests.\n\t\t\tif ( viewPosition === null ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Skip all following ui elements.\n\t\t\tlet jumpedOverAnyUiElement = false;\n\n\t\t\tconst nextViewPosition = viewPosition.getLastMatchingPosition( value => {\n\t\t\t\tif ( value.item.is( 'uiElement' ) ) {\n\t\t\t\t\t// Remember that there was at least one ui element.\n\t\t\t\t\tjumpedOverAnyUiElement = true;\n\t\t\t\t}\n\n\t\t\t\t// Jump over ui elements, jump over empty attribute elements, move up from inside of attribute element.\n\t\t\t\tif ( value.item.is( 'uiElement' ) || value.item.is( 'attributeElement' ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t// Don't jump over text or don't get out of container element.\n\t\t\t\treturn false;\n\t\t\t} );\n\n\t\t\t// If anything has been skipped, fix position.\n\t\t\t// This `if` could be possibly omitted but maybe it is better not to mess with DOM selection if not needed.\n\t\t\tif ( jumpedOverAnyUiElement ) {\n\t\t\t\tconst newDomPosition = domConverter.viewPositionToDom( nextViewPosition );\n\n\t\t\t\tif ( domSelectionCollapsed ) {\n\t\t\t\t\t// Selection was collapsed, so collapse it at further position.\n\t\t\t\t\tdomSelection.collapse( newDomPosition.parent, newDomPosition.offset );\n\t\t\t\t} else {\n\t\t\t\t\t// Selection was not collapse, so extend it instead of collapsing.\n\t\t\t\t\tdomSelection.extend( newDomPosition.parent, newDomPosition.offset );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/documentfragment\n */\n\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\n\n/**\n * Document fragment.\n *\n * To create a new document fragment instance use the\n * {@link module:engine/view/upcastwriter~UpcastWriter#createDocumentFragment `UpcastWriter#createDocumentFragment()`}\n * method.\n */\nexport default class DocumentFragment {\n\t/**\n\t * Creates new DocumentFragment instance.\n\t *\n\t * @protected\n\t * @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]\n\t * A list of nodes to be inserted into the created document fragment.\n\t */\n\tconstructor( children ) {\n\t\t/**\n\t\t * Array of child nodes.\n\t\t *\n\t\t * @protected\n\t\t * @member {Array.<module:engine/view/element~Element>} module:engine/view/documentfragment~DocumentFragment#_children\n\t\t */\n\t\tthis._children = [];\n\n\t\tif ( children ) {\n\t\t\tthis._insertChild( 0, children );\n\t\t}\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Iterates over nodes added to this document fragment.\n\t *\n\t * @returns {Iterable.<module:engine/view/node~Node>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this._children[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Number of child nodes in this document fragment.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget childCount() {\n\t\treturn this._children.length;\n\t}\n\n\t/**\n\t * Is `true` if there are no nodes inside this document fragment, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isEmpty() {\n\t\treturn this.childCount === 0;\n\t}\n\n\t/**\n\t * Artificial root of `DocumentFragment`. Returns itself. Added for compatibility reasons.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Artificial parent of `DocumentFragment`. Returns `null`. Added for compatibility reasons.\n\t *\n\t * @readonly\n\t * @type {null}\n\t */\n\tget parent() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tdocFrag.is( 'documentFragment' ); // -> true\n\t *\t\tdocFrag.is( 'view:documentFragment' ); // -> true\n\t *\n\t *\t\tdocFrag.is( 'model:documentFragment' ); // -> false\n\t *\t\tdocFrag.is( 'element' ); // -> false\n\t *\t\tdocFrag.is( 'node' ); // -> false\n\t *\n\t * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'documentFragment' || type == 'view:documentFragment';\n\t}\n\n\t/**\n\t * {@link module:engine/view/documentfragment~DocumentFragment#_insertChild Insert} a child node or a list of child nodes at the end\n\t * and sets the parent of these nodes to this fragment.\n\t *\n\t * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.\n\t * @returns {Number} Number of appended nodes.\n\t */\n\t_appendChild( items ) {\n\t\treturn this._insertChild( this.childCount, items );\n\t}\n\n\t/**\n\t * Gets child at the given index.\n\t *\n\t * @param {Number} index Index of child.\n\t * @returns {module:engine/view/node~Node} Child node.\n\t */\n\tgetChild( index ) {\n\t\treturn this._children[ index ];\n\t}\n\n\t/**\n\t * Gets index of the given child node. Returns `-1` if child node is not found.\n\t *\n\t * @param {module:engine/view/node~Node} node Child node.\n\t * @returns {Number} Index of the child node.\n\t */\n\tgetChildIndex( node ) {\n\t\treturn this._children.indexOf( node );\n\t}\n\n\t/**\n\t * Gets child nodes iterator.\n\t *\n\t * @returns {Iterable.<module:engine/view/node~Node>} Child nodes iterator.\n\t */\n\tgetChildren() {\n\t\treturn this._children[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Inserts a child node or a list of child nodes on the given index and sets the parent of these nodes to\n\t * this fragment.\n\t *\n\t * @param {Number} index Position where nodes should be inserted.\n\t * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.\n\t * @returns {Number} Number of inserted nodes.\n\t */\n\t_insertChild( index, items ) {\n\t\tthis._fireChange( 'children', this );\n\t\tlet count = 0;\n\n\t\tconst nodes = normalize( items );\n\n\t\tfor ( const node of nodes ) {\n\t\t\t// If node that is being added to this element is already inside another element, first remove it from the old parent.\n\t\t\tif ( node.parent !== null ) {\n\t\t\t\tnode._remove();\n\t\t\t}\n\n\t\t\tnode.parent = this;\n\n\t\t\tthis._children.splice( index, 0, node );\n\t\t\tindex++;\n\t\t\tcount++;\n\t\t}\n\n\t\treturn count;\n\t}\n\n\t/**\n\t * Removes number of child nodes starting at the given index and set the parent of these nodes to `null`.\n\t *\n\t * @param {Number} index Number of the first node to remove.\n\t * @param {Number} [howMany=1] Number of nodes to remove.\n\t * @returns {Array.<module:engine/view/node~Node>} The array of removed nodes.\n\t */\n\t_removeChildren( index, howMany = 1 ) {\n\t\tthis._fireChange( 'children', this );\n\n\t\tfor ( let i = index; i < index + howMany; i++ ) {\n\t\t\tthis._children[ i ].parent = null;\n\t\t}\n\n\t\treturn this._children.splice( index, howMany );\n\t}\n\n\t/**\n\t * Fires `change` event with given type of the change.\n\t *\n\t * @private\n\t * @param {module:engine/view/document~ChangeType} type Type of the change.\n\t * @param {module:engine/view/node~Node} node Changed node.\n\t * @fires module:engine/view/node~Node#change\n\t */\n\t_fireChange( type, node ) {\n\t\tthis.fire( 'change:' + type, node );\n\t}\n}\n\nmix( DocumentFragment, EmitterMixin );\n\n// Converts strings to Text and non-iterables to arrays.\n//\n// @param {String|module:engine/view/item~Item|Iterable.<String|module:engine/view/item~Item>}\n// @returns {Iterable.<module:engine/view/node~Node>}\nfunction normalize( nodes ) {\n\t// Separate condition because string is iterable.\n\tif ( typeof nodes == 'string' ) {\n\t\treturn [ new Text( nodes ) ];\n\t}\n\n\tif ( !isIterable( nodes ) ) {\n\t\tnodes = [ nodes ];\n\t}\n\n\t// Array.from to enable .map() on non-arrays.\n\treturn Array.from( nodes )\n\t\t.map( node => {\n\t\t\tif ( typeof node == 'string' ) {\n\t\t\t\treturn new Text( node );\n\t\t\t}\n\n\t\t\tif ( node instanceof TextProxy ) {\n\t\t\t\treturn new Text( node.data );\n\t\t\t}\n\n\t\t\treturn node;\n\t\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 module:engine/view/downcastwriter\n */\n\nimport Position from './position';\nimport Range from './range';\nimport Selection from './selection';\nimport ContainerElement from './containerelement';\nimport AttributeElement from './attributeelement';\nimport EmptyElement from './emptyelement';\nimport UIElement from './uielement';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport DocumentFragment from './documentfragment';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\nimport Text from './text';\nimport EditableElement from './editableelement';\nimport { isPlainObject } from 'lodash-es';\n\n/**\n * View downcast writer.\n *\n * It provides a set of methods used to manipulate view nodes.\n *\n * Do not create an instance of this writer manually. To modify a view structure, use\n * the {@link module:engine/view/view~View#change `View#change()`} block.\n *\n * The `DowncastWriter` is designed to work with semantic views which are the views that were/are being downcasted from the model.\n * To work with ordinary views (e.g. parsed from a pasted content) use the\n * {@link module:engine/view/upcastwriter~UpcastWriter upcast writer}.\n *\n * Read more about changing the view in the {@glink framework/guides/architecture/editing-engine#changing-the-view Changing the view}\n * section of the {@glink framework/guides/architecture/editing-engine Editing engine architecture} guide.\n */\nexport default class DowncastWriter {\n\tconstructor( document ) {\n\t\t/**\n\t\t * @readonly\n\t\t * @type {module:engine/view/document~Document}\n\t\t */\n\t\tthis.document = document;\n\n\t\t/**\n\t\t * Holds references to the attribute groups that share the same {@link module:engine/view/attributeelement~AttributeElement#id id}.\n\t\t * The keys are `id`s, the values are `Set`s holding {@link module:engine/view/attributeelement~AttributeElement}s.\n\t\t *\n\t\t * @private\n\t\t * @type {Map.<String,Set>}\n\t\t */\n\t\tthis._cloneGroups = new Map();\n\t}\n\n\t/**\n\t * Sets {@link module:engine/view/documentselection~DocumentSelection selection's} ranges and direction to the\n\t * specified location based on the given {@link module:engine/view/selection~Selectable selectable}.\n\t *\n\t * Usage:\n\t *\n\t *\t\t// Sets selection to the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\twriter.setSelection( range );\n\t *\n\t *\t\t// Sets backward selection to the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\twriter.setSelection( range );\n\t *\n\t *\t\t// Sets selection to given ranges.\n\t * \t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( start2, end2 ) ];\n\t *\t\twriter.setSelection( range );\n\t *\n\t *\t\t// Sets selection to the other selection.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\twriter.setSelection( otherSelection );\n\t *\n\t * \t\t// Sets collapsed selection at the given position.\n\t *\t\tconst position = writer.createPositionFromPath( root, path );\n\t *\t\twriter.setSelection( position );\n\t *\n\t * \t\t// Sets collapsed selection at the position of given item and offset.\n\t *\t\tconst paragraph = writer.createContainerElement( 'p' );\n\t *\t\twriter.setSelection( paragraph, offset );\n\t *\n\t * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of\n \t * that element and ends after the last child of that element.\n\t *\n\t * \t\twriter.setSelection( paragraph, 'in' );\n\t *\n\t * Creates a range on the {@link module:engine/view/item~Item item} which starts before the item and ends just after the item.\n\t *\n\t *\t\twriter.setSelection( paragraph, 'on' );\n\t *\n\t * \t\t// Removes all ranges.\n\t *\t\twriter.setSelection( null );\n\t *\n\t * `DowncastWriter#setSelection()` allow passing additional options (`backward`, `fake` and `label`) as the last argument.\n\t *\n\t *\t\t// Sets selection as backward.\n\t *\t\twriter.setSelection( range, { backward: true } );\n\t *\n\t *\t\t// Sets selection as fake.\n\t *\t\t// Fake selection does not render as browser native selection over selected elements and is hidden to the user.\n\t * \t\t// This way, no native selection UI artifacts are displayed to the user and selection over elements can be\n\t * \t\t// represented in other way, for example by applying proper CSS class.\n\t *\t\twriter.setSelection( range, { fake: true } );\n\t *\n\t * \t\t// Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM\n\t * \t\t// (and be properly handled by screen readers).\n\t *\t\twriter.setSelection( range, { fake: true, label: 'foo' } );\n\t *\n\t * @param {module:engine/view/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`.\n\t * @param {String} [options.label] Label for the fake selection.\n\t */\n\tsetSelection( selectable, placeOrOffset, options ) {\n\t\tthis.document.selection._setTo( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Moves {@link module:engine/view/documentselection~DocumentSelection#focus selection's focus} to the specified location.\n\t *\n\t * The location can be specified in the same form as {@link module:engine/view/view~View#createPositionAt view.createPositionAt()}\n\t * parameters.\n\t *\n\t * @param {module:engine/view/item~Item|module:engine/view/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/view/item~Item view item}.\n\t */\n\tsetSelectionFocus( itemOrPosition, offset ) {\n\t\tthis.document.selection._setFocus( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Creates a new {@link module:engine/view/text~Text text node}.\n\t *\n\t *\t\twriter.createText( 'foo' );\n\t *\n\t * @param {String} data The text's data.\n\t * @returns {module:engine/view/text~Text} The created text node.\n\t */\n\tcreateText( data ) {\n\t\treturn new Text( data );\n\t}\n\n\t/**\n\t * Creates new {@link module:engine/view/attributeelement~AttributeElement}.\n\t *\n\t *\t\twriter.createAttributeElement( 'strong' );\n\t *\t\twriter.createAttributeElement( 'a', { href: 'foo.bar' } );\n\t *\n\t *\t\t// Make `<a>` element contain other attributes element so the `<a>` element is not broken.\n\t *\t\twriter.createAttributeElement( 'a', { href: 'foo.bar' }, { priority: 5 } );\n\t *\n\t *\t\t// Set `id` of a marker element so it is not joined or merged with \"normal\" elements.\n\t *\t\twriter.createAttributeElement( 'span', { class: 'my-marker' }, { id: 'marker:my' } );\n\t *\n\t * @param {String} name Name of the element.\n\t * @param {Object} [attributes] Element's attributes.\n\t * @param {Object} [options] Element's options.\n\t * @param {Number} [options.priority] Element's {@link module:engine/view/attributeelement~AttributeElement#priority priority}.\n\t * @param {Number|String} [options.id] Element's {@link module:engine/view/attributeelement~AttributeElement#id id}.\n\t * @returns {module:engine/view/attributeelement~AttributeElement} Created element.\n\t */\n\tcreateAttributeElement( name, attributes, options = {} ) {\n\t\tconst attributeElement = new AttributeElement( name, attributes );\n\n\t\tif ( options.priority ) {\n\t\t\tattributeElement._priority = options.priority;\n\t\t}\n\n\t\tif ( options.id ) {\n\t\t\tattributeElement._id = options.id;\n\t\t}\n\n\t\treturn attributeElement;\n\t}\n\n\t/**\n\t * Creates new {@link module:engine/view/containerelement~ContainerElement}.\n\t *\n\t *\t\twriter.createContainerElement( 'p' );\n\t *\n\t *\t\t// Create element with custom attributes.\n\t *\t\twriter.createContainerElement( 'div', { id: 'foo-bar', 'data-baz': '123' } );\n\t *\n\t *\t\t// Create element with custom styles.\n\t *\t\twriter.createContainerElement( 'p', { style: 'font-weight: bold; padding-bottom: 10px' } );\n\t *\n\t *\t\t// Create element with custom classes.\n\t *\t\twriter.createContainerElement( 'p', { class: 'foo bar baz' } );\n\t *\n\t * @param {String} name Name of the element.\n\t * @param {Object} [attributes] Elements attributes.\n\t * @returns {module:engine/view/containerelement~ContainerElement} Created element.\n\t */\n\tcreateContainerElement( name, attributes ) {\n\t\treturn new ContainerElement( name, attributes );\n\t}\n\n\t/**\n\t * Creates new {@link module:engine/view/editableelement~EditableElement}.\n\t *\n\t *\t\twriter.createEditableElement( 'div' );\n\t *\t\twriter.createEditableElement( 'div', { id: 'foo-1234' } );\n\t *\n\t * @param {String} name Name of the element.\n\t * @param {Object} [attributes] Elements attributes.\n\t * @returns {module:engine/view/editableelement~EditableElement} Created element.\n\t */\n\tcreateEditableElement( name, attributes ) {\n\t\tconst editableElement = new EditableElement( name, attributes );\n\t\teditableElement._document = this.document;\n\n\t\treturn editableElement;\n\t}\n\n\t/**\n\t * Creates new {@link module:engine/view/emptyelement~EmptyElement}.\n\t *\n\t *\t\twriter.createEmptyElement( 'img' );\n\t *\t\twriter.createEmptyElement( 'img', { id: 'foo-1234' } );\n\t *\n\t * @param {String} name Name of the element.\n\t * @param {Object} [attributes] Elements attributes.\n\t * @returns {module:engine/view/emptyelement~EmptyElement} Created element.\n\t */\n\tcreateEmptyElement( name, attributes ) {\n\t\treturn new EmptyElement( name, attributes );\n\t}\n\n\t/**\n\t * Creates new {@link module:engine/view/uielement~UIElement}.\n\t *\n\t *\t\twriter.createUIElement( 'span' );\n\t *\t\twriter.createUIElement( 'span', { id: 'foo-1234' } );\n\t *\n\t * Custom render function can be provided as third parameter:\n\t *\n\t *\t\twriter.createUIElement( 'span', null, function( domDocument ) {\n\t *\t\t\tconst domElement = this.toDomElement( domDocument );\n\t *\t\t\tdomElement.innerHTML = '<b>this is ui element</b>';\n\t *\n\t *\t\t\treturn domElement;\n\t *\t\t} );\n\t *\n\t * @param {String} name Name of the element.\n\t * @param {Object} [attributes] Elements attributes.\n\t * @param {Function} [renderFunction] Custom render function.\n\t * @returns {module:engine/view/uielement~UIElement} Created element.\n\t */\n\tcreateUIElement( name, attributes, renderFunction ) {\n\t\tconst uiElement = new UIElement( name, attributes );\n\n\t\tif ( renderFunction ) {\n\t\t\tuiElement.render = renderFunction;\n\t\t}\n\n\t\treturn uiElement;\n\t}\n\n\t/**\n\t * Adds or overwrite element's attribute with a specified key and value.\n\t *\n\t *\t\twriter.setAttribute( 'href', 'http://ckeditor.com', linkElement );\n\t *\n\t * @param {String} key Attribute key.\n\t * @param {String} value Attribute value.\n\t * @param {module:engine/view/element~Element} element\n\t */\n\tsetAttribute( key, value, element ) {\n\t\telement._setAttribute( key, value );\n\t}\n\n\t/**\n\t * Removes attribute from the element.\n\t *\n\t *\t\twriter.removeAttribute( 'href', linkElement );\n\t *\n\t * @param {String} key Attribute key.\n\t * @param {module:engine/view/element~Element} element\n\t */\n\tremoveAttribute( key, element ) {\n\t\telement._removeAttribute( key );\n\t}\n\n\t/**\n\t * Adds specified class to the element.\n\t *\n\t *\t\twriter.addClass( 'foo', linkElement );\n\t *\t\twriter.addClass( [ 'foo', 'bar' ], linkElement );\n\t *\n\t * @param {Array.<String>|String} className\n\t * @param {module:engine/view/element~Element} element\n\t */\n\taddClass( className, element ) {\n\t\telement._addClass( className );\n\t}\n\n\t/**\n\t * Removes specified class from the element.\n\t *\n\t *\t\twriter.removeClass( 'foo', linkElement );\n\t *\t\twriter.removeClass( [ 'foo', 'bar' ], linkElement );\n\t *\n\t * @param {Array.<String>|String} className\n\t * @param {module:engine/view/element~Element} element\n\t */\n\tremoveClass( className, element ) {\n\t\telement._removeClass( className );\n\t}\n\n\t/**\n\t * Adds style to the element.\n\t *\n\t *\t\twriter.setStyle( 'color', 'red', element );\n\t *\t\twriter.setStyle( {\n\t *\t\t\tcolor: 'red',\n\t *\t\t\tposition: 'fixed'\n\t *\t\t}, element );\n\t *\n\t * @param {String|Object} property Property name or object with key - value pairs.\n\t * @param {String} [value] Value to set. This parameter is ignored if object is provided as the first parameter.\n\t * @param {module:engine/view/element~Element} element Element to set styles on.\n\t */\n\tsetStyle( property, value, element ) {\n\t\tif ( isPlainObject( property ) && element === undefined ) {\n\t\t\telement = value;\n\t\t}\n\n\t\telement._setStyle( property, value );\n\t}\n\n\t/**\n\t * Removes specified style from the element.\n\t *\n\t *\t\twriter.removeStyle( 'color', element ); // Removes 'color' style.\n\t *\t\twriter.removeStyle( [ 'color', 'border-top' ], element ); // Removes both 'color' and 'border-top' styles.\n\t *\n\t * @param {Array.<String>|String} property\n\t * @param {module:engine/view/element~Element} element\n\t */\n\tremoveStyle( property, element ) {\n\t\telement._removeStyle( property );\n\t}\n\n\t/**\n\t * Sets a custom property on element. Unlike attributes, custom properties are not rendered to the DOM,\n\t * so they can be used to add special data to elements.\n\t *\n\t * @param {String|Symbol} key\n\t * @param {*} value\n\t * @param {module:engine/view/element~Element} element\n\t */\n\tsetCustomProperty( key, value, element ) {\n\t\telement._setCustomProperty( key, value );\n\t}\n\n\t/**\n\t * Removes a custom property stored under the given key.\n\t *\n\t * @param {String|Symbol} key\n\t * @param {module:engine/view/element~Element} element\n\t * @returns {Boolean} Returns true if property was removed.\n\t */\n\tremoveCustomProperty( key, element ) {\n\t\treturn element._removeCustomProperty( key );\n\t}\n\n\t/**\n\t * Breaks attribute nodes at provided position or at boundaries of provided range. It breaks attribute elements inside\n\t * up to a container element.\n\t *\n\t * In following examples `<p>` is a container, `<b>` and `<u>` are attribute nodes:\n\t *\n\t *\t\t<p>foo<b><u>bar{}</u></b></p> -> <p>foo<b><u>bar</u></b>[]</p>\n\t *\t\t<p>foo<b><u>{}bar</u></b></p> -> <p>foo{}<b><u>bar</u></b></p>\n\t *\t\t<p>foo<b><u>b{}ar</u></b></p> -> <p>foo<b><u>b</u></b>[]<b><u>ar</u></b></p>\n\t *\t\t<p><b>fo{o</b><u>ba}r</u></p> -> <p><b>fo</b><b>o</b><u>ba</u><u>r</u></b></p>\n\t *\n\t * **Note:** {@link module:engine/view/documentfragment~DocumentFragment DocumentFragment} is treated like a container.\n\t *\n\t * **Note:** Difference between {@link module:engine/view/downcastwriter~DowncastWriter#breakAttributes breakAttributes} and\n\t * {@link module:engine/view/downcastwriter~DowncastWriter#breakContainer breakContainer} is that `breakAttributes` breaks all\n\t * {@link module:engine/view/attributeelement~AttributeElement attribute elements} that are ancestors of given `position`,\n\t * up to the first encountered {@link module:engine/view/containerelement~ContainerElement container element}.\n\t * `breakContainer` assumes that given `position` is directly in container element and breaks that container element.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-invalid-range-container`\n\t * when {@link module:engine/view/range~Range#start start}\n\t * and {@link module:engine/view/range~Range#end end} positions of a passed range are not placed inside same parent container.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-cannot-break-empty-element`\n\t * when trying to break attributes\n\t * inside {@link module:engine/view/emptyelement~EmptyElement EmptyElement}.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-cannot-break-ui-element`\n\t * when trying to break attributes\n\t * inside {@link module:engine/view/uielement~UIElement UIElement}.\n\t *\n\t * @see module:engine/view/attributeelement~AttributeElement\n\t * @see module:engine/view/containerelement~ContainerElement\n\t * @see module:engine/view/downcastwriter~DowncastWriter#breakContainer\n\t * @param {module:engine/view/position~Position|module:engine/view/range~Range} positionOrRange Position where\n\t * to break attribute elements.\n\t * @returns {module:engine/view/position~Position|module:engine/view/range~Range} New position or range, after breaking the attribute\n\t * elements.\n\t */\n\tbreakAttributes( positionOrRange ) {\n\t\tif ( positionOrRange instanceof Position ) {\n\t\t\treturn this._breakAttributes( positionOrRange );\n\t\t} else {\n\t\t\treturn this._breakAttributesRange( positionOrRange );\n\t\t}\n\t}\n\n\t/**\n\t * Breaks {@link module:engine/view/containerelement~ContainerElement container view element} into two, at the given position. Position\n\t * has to be directly inside container element and cannot be in root. Does not break if position is at the beginning\n\t * or at the end of it's parent element.\n\t *\n\t *\t\t<p>foo^bar</p> -> <p>foo</p><p>bar</p>\n\t *\t\t<div><p>foo</p>^<p>bar</p></div> -> <div><p>foo</p></div><div><p>bar</p></div>\n\t *\t\t<p>^foobar</p> -> ^<p>foobar</p>\n\t *\t\t<p>foobar^</p> -> <p>foobar</p>^\n\t *\n\t * **Note:** Difference between {@link module:engine/view/downcastwriter~DowncastWriter#breakAttributes breakAttributes} and\n\t * {@link module:engine/view/downcastwriter~DowncastWriter#breakContainer breakContainer} is that `breakAttributes` breaks all\n\t * {@link module:engine/view/attributeelement~AttributeElement attribute elements} that are ancestors of given `position`,\n\t * up to the first encountered {@link module:engine/view/containerelement~ContainerElement container element}.\n\t * `breakContainer` assumes that given `position` is directly in container element and breaks that container element.\n\t *\n\t * @see module:engine/view/attributeelement~AttributeElement\n\t * @see module:engine/view/containerelement~ContainerElement\n\t * @see module:engine/view/downcastwriter~DowncastWriter#breakAttributes\n\t * @param {module:engine/view/position~Position} position Position where to break element.\n\t * @returns {module:engine/view/position~Position} Position between broken elements. If element has not been broken,\n\t * the returned position is placed either before it or after it.\n\t */\n\tbreakContainer( position ) {\n\t\tconst element = position.parent;\n\n\t\tif ( !( element.is( 'containerElement' ) ) ) {\n\t\t\t/**\n\t\t\t * Trying to break an element which is not a container element.\n\t\t\t *\n\t\t\t * @error view-writer-break-non-container-element\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'view-writer-break-non-container-element: Trying to break an element which is not a container element.',\n\t\t\t\tthis.document\n\t\t\t);\n\t\t}\n\n\t\tif ( !element.parent ) {\n\t\t\t/**\n\t\t\t * Trying to break root element.\n\t\t\t *\n\t\t\t * @error view-writer-break-root\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-writer-break-root: Trying to break root element.', this.document );\n\t\t}\n\n\t\tif ( position.isAtStart ) {\n\t\t\treturn Position._createBefore( element );\n\t\t} else if ( !position.isAtEnd ) {\n\t\t\tconst newElement = element._clone( false );\n\n\t\t\tthis.insert( Position._createAfter( element ), newElement );\n\n\t\t\tconst sourceRange = new Range( position, Position._createAt( element, 'end' ) );\n\t\t\tconst targetPosition = new Position( newElement, 0 );\n\n\t\t\tthis.move( sourceRange, targetPosition );\n\t\t}\n\n\t\treturn Position._createAfter( element );\n\t}\n\n\t/**\n\t * Merges {@link module:engine/view/attributeelement~AttributeElement attribute elements}. It also merges text nodes if needed.\n\t * Only {@link module:engine/view/attributeelement~AttributeElement#isSimilar similar} attribute elements can be merged.\n\t *\n\t * In following examples `<p>` is a container and `<b>` is an attribute element:\n\t *\n\t *\t\t<p>foo[]bar</p> -> <p>foo{}bar</p>\n\t *\t\t<p><b>foo</b>[]<b>bar</b></p> -> <p><b>foo{}bar</b></p>\n\t *\t\t<p><b foo=\"bar\">a</b>[]<b foo=\"baz\">b</b></p> -> <p><b foo=\"bar\">a</b>[]<b foo=\"baz\">b</b></p>\n\t *\n\t * It will also take care about empty attributes when merging:\n\t *\n\t *\t\t<p><b>[]</b></p> -> <p>[]</p>\n\t *\t\t<p><b>foo</b><i>[]</i><b>bar</b></p> -> <p><b>foo{}bar</b></p>\n\t *\n\t * **Note:** Difference between {@link module:engine/view/downcastwriter~DowncastWriter#mergeAttributes mergeAttributes} and\n\t * {@link module:engine/view/downcastwriter~DowncastWriter#mergeContainers mergeContainers} is that `mergeAttributes` merges two\n\t * {@link module:engine/view/attributeelement~AttributeElement attribute elements} or {@link module:engine/view/text~Text text nodes}\n\t * while `mergeContainer` merges two {@link module:engine/view/containerelement~ContainerElement container elements}.\n\t *\n\t * @see module:engine/view/attributeelement~AttributeElement\n\t * @see module:engine/view/containerelement~ContainerElement\n\t * @see module:engine/view/downcastwriter~DowncastWriter#mergeContainers\n\t * @param {module:engine/view/position~Position} position Merge position.\n\t * @returns {module:engine/view/position~Position} Position after merge.\n\t */\n\tmergeAttributes( position ) {\n\t\tconst positionOffset = position.offset;\n\t\tconst positionParent = position.parent;\n\n\t\t// When inside text node - nothing to merge.\n\t\tif ( positionParent.is( 'text' ) ) {\n\t\t\treturn position;\n\t\t}\n\n\t\t// When inside empty attribute - remove it.\n\t\tif ( positionParent.is( 'attributeElement' ) && positionParent.childCount === 0 ) {\n\t\t\tconst parent = positionParent.parent;\n\t\t\tconst offset = positionParent.index;\n\n\t\t\tpositionParent._remove();\n\t\t\tthis._removeFromClonedElementsGroup( positionParent );\n\n\t\t\treturn this.mergeAttributes( new Position( parent, offset ) );\n\t\t}\n\n\t\tconst nodeBefore = positionParent.getChild( positionOffset - 1 );\n\t\tconst nodeAfter = positionParent.getChild( positionOffset );\n\n\t\t// Position should be placed between two nodes.\n\t\tif ( !nodeBefore || !nodeAfter ) {\n\t\t\treturn position;\n\t\t}\n\n\t\t// When position is between two text nodes.\n\t\tif ( nodeBefore.is( 'text' ) && nodeAfter.is( 'text' ) ) {\n\t\t\treturn mergeTextNodes( nodeBefore, nodeAfter );\n\t\t}\n\t\t// When position is between two same attribute elements.\n\t\telse if ( nodeBefore.is( 'attributeElement' ) && nodeAfter.is( 'attributeElement' ) && nodeBefore.isSimilar( nodeAfter ) ) {\n\t\t\t// Move all children nodes from node placed after selection and remove that node.\n\t\t\tconst count = nodeBefore.childCount;\n\t\t\tnodeBefore._appendChild( nodeAfter.getChildren() );\n\n\t\t\tnodeAfter._remove();\n\t\t\tthis._removeFromClonedElementsGroup( nodeAfter );\n\n\t\t\t// New position is located inside the first node, before new nodes.\n\t\t\t// Call this method recursively to merge again if needed.\n\t\t\treturn this.mergeAttributes( new Position( nodeBefore, count ) );\n\t\t}\n\n\t\treturn position;\n\t}\n\n\t/**\n\t * Merges two {@link module:engine/view/containerelement~ContainerElement container elements} that are before and after given position.\n\t * Precisely, the element after the position is removed and it's contents are moved to element before the position.\n\t *\n\t *\t\t<p>foo</p>^<p>bar</p> -> <p>foo^bar</p>\n\t *\t\t<div>foo</div>^<p>bar</p> -> <div>foo^bar</div>\n\t *\n\t * **Note:** Difference between {@link module:engine/view/downcastwriter~DowncastWriter#mergeAttributes mergeAttributes} and\n\t * {@link module:engine/view/downcastwriter~DowncastWriter#mergeContainers mergeContainers} is that `mergeAttributes` merges two\n\t * {@link module:engine/view/attributeelement~AttributeElement attribute elements} or {@link module:engine/view/text~Text text nodes}\n\t * while `mergeContainer` merges two {@link module:engine/view/containerelement~ContainerElement container elements}.\n\t *\n\t * @see module:engine/view/attributeelement~AttributeElement\n\t * @see module:engine/view/containerelement~ContainerElement\n\t * @see module:engine/view/downcastwriter~DowncastWriter#mergeAttributes\n\t * @param {module:engine/view/position~Position} position Merge position.\n\t * @returns {module:engine/view/position~Position} Position after merge.\n\t */\n\tmergeContainers( position ) {\n\t\tconst prev = position.nodeBefore;\n\t\tconst next = position.nodeAfter;\n\n\t\tif ( !prev || !next || !prev.is( 'containerElement' ) || !next.is( 'containerElement' ) ) {\n\t\t\t/**\n\t\t\t * Element before and after given position cannot be merged.\n\t\t\t *\n\t\t\t * @error view-writer-merge-containers-invalid-position\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-writer-merge-containers-invalid-position: ' +\n\t\t\t\t'Element before and after given position cannot be merged.', this.document );\n\t\t}\n\n\t\tconst lastChild = prev.getChild( prev.childCount - 1 );\n\t\tconst newPosition = lastChild instanceof Text ? Position._createAt( lastChild, 'end' ) : Position._createAt( prev, 'end' );\n\n\t\tthis.move( Range._createIn( next ), Position._createAt( prev, 'end' ) );\n\t\tthis.remove( Range._createOn( next ) );\n\n\t\treturn newPosition;\n\t}\n\n\t/**\n\t * Insert node or nodes at specified position. Takes care about breaking attributes before insertion\n\t * and merging them afterwards.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-insert-invalid-node` when nodes to insert\n\t * contains instances that are not {@link module:engine/view/text~Text Texts},\n\t * {@link module:engine/view/attributeelement~AttributeElement AttributeElements},\n\t * {@link module:engine/view/containerelement~ContainerElement ContainerElements},\n\t * {@link module:engine/view/emptyelement~EmptyElement EmptyElements} or\n\t * {@link module:engine/view/uielement~UIElement UIElements}.\n\t *\n\t * @param {module:engine/view/position~Position} position Insertion position.\n\t * @param {module:engine/view/text~Text|module:engine/view/attributeelement~AttributeElement|\n\t * module:engine/view/containerelement~ContainerElement|module:engine/view/emptyelement~EmptyElement|\n\t * module:engine/view/uielement~UIElement|Iterable.<module:engine/view/text~Text|\n\t * module:engine/view/attributeelement~AttributeElement|module:engine/view/containerelement~ContainerElement|\n\t * module:engine/view/emptyelement~EmptyElement|module:engine/view/uielement~UIElement>} nodes Node or nodes to insert.\n\t * @returns {module:engine/view/range~Range} Range around inserted nodes.\n\t */\n\tinsert( position, nodes ) {\n\t\tnodes = isIterable( nodes ) ? [ ...nodes ] : [ nodes ];\n\n\t\t// Check if nodes to insert are instances of AttributeElements, ContainerElements, EmptyElements, UIElements or Text.\n\t\tvalidateNodesToInsert( nodes, this.document );\n\n\t\tconst container = getParentContainer( position );\n\n\t\tif ( !container ) {\n\t\t\t/**\n\t\t\t * Position's parent container cannot be found.\n\t\t\t *\n\t\t\t * @error view-writer-invalid-position-container\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-writer-invalid-position-container', this.document );\n\t\t}\n\n\t\tconst insertionPosition = this._breakAttributes( position, true );\n\t\tconst length = container._insertChild( insertionPosition.offset, nodes );\n\n\t\tfor ( const node of nodes ) {\n\t\t\tthis._addToClonedElementsGroup( node );\n\t\t}\n\n\t\tconst endPosition = insertionPosition.getShiftedBy( length );\n\t\tconst start = this.mergeAttributes( insertionPosition );\n\n\t\t// When no nodes were inserted - return collapsed range.\n\t\tif ( length === 0 ) {\n\t\t\treturn new Range( start, start );\n\t\t} else {\n\t\t\t// If start position was merged - move end position.\n\t\t\tif ( !start.isEqual( insertionPosition ) ) {\n\t\t\t\tendPosition.offset--;\n\t\t\t}\n\n\t\t\tconst end = this.mergeAttributes( endPosition );\n\n\t\t\treturn new Range( start, end );\n\t\t}\n\t}\n\n\t/**\n\t * Removes provided range from the container.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-invalid-range-container` when\n\t * {@link module:engine/view/range~Range#start start} and {@link module:engine/view/range~Range#end end} positions are not placed inside\n\t * same parent container.\n\t *\n\t * @param {module:engine/view/range~Range|module:engine/view/item~Item} rangeOrItem Range to remove from container\n\t * or an {@link module:engine/view/item~Item item} to remove. If range is provided, after removing, it will be updated\n\t * to a collapsed range showing the new position.\n\t * @returns {module:engine/view/documentfragment~DocumentFragment} Document fragment containing removed nodes.\n\t */\n\tremove( rangeOrItem ) {\n\t\tconst range = rangeOrItem instanceof Range ? rangeOrItem : Range._createOn( rangeOrItem );\n\n\t\tvalidateRangeContainer( range, this.document );\n\n\t\t// If range is collapsed - nothing to remove.\n\t\tif ( range.isCollapsed ) {\n\t\t\treturn new DocumentFragment();\n\t\t}\n\n\t\t// Break attributes at range start and end.\n\t\tconst { start: breakStart, end: breakEnd } = this._breakAttributesRange( range, true );\n\t\tconst parentContainer = breakStart.parent;\n\n\t\tconst count = breakEnd.offset - breakStart.offset;\n\n\t\t// Remove nodes in range.\n\t\tconst removed = parentContainer._removeChildren( breakStart.offset, count );\n\n\t\tfor ( const node of removed ) {\n\t\t\tthis._removeFromClonedElementsGroup( node );\n\t\t}\n\n\t\t// Merge after removing.\n\t\tconst mergePosition = this.mergeAttributes( breakStart );\n\t\trange.start = mergePosition;\n\t\trange.end = mergePosition.clone();\n\n\t\t// Return removed nodes.\n\t\treturn new DocumentFragment( removed );\n\t}\n\n\t/**\n\t * Removes matching elements from given range.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-invalid-range-container` when\n\t * {@link module:engine/view/range~Range#start start} and {@link module:engine/view/range~Range#end end} positions are not placed inside\n\t * same parent container.\n\t *\n\t * @param {module:engine/view/range~Range} range Range to clear.\n\t * @param {module:engine/view/element~Element} element Element to remove.\n\t */\n\tclear( range, element ) {\n\t\tvalidateRangeContainer( range, this.document );\n\n\t\t// Create walker on given range.\n\t\t// We walk backward because when we remove element during walk it modifies range end position.\n\t\tconst walker = range.getWalker( {\n\t\t\tdirection: 'backward',\n\t\t\tignoreElementEnd: true\n\t\t} );\n\n\t\t// Let's walk.\n\t\tfor ( const current of walker ) {\n\t\t\tconst item = current.item;\n\t\t\tlet rangeToRemove;\n\n\t\t\t// When current item matches to the given element.\n\t\t\tif ( item.is( 'element' ) && element.isSimilar( item ) ) {\n\t\t\t\t// Create range on this element.\n\t\t\t\trangeToRemove = Range._createOn( item );\n\t\t\t\t// When range starts inside Text or TextProxy element.\n\t\t\t} else if ( !current.nextPosition.isAfter( range.start ) && item.is( 'textProxy' ) ) {\n\t\t\t\t// We need to check if parent of this text matches to given element.\n\t\t\t\tconst parentElement = item.getAncestors().find( ancestor => {\n\t\t\t\t\treturn ancestor.is( 'element' ) && element.isSimilar( ancestor );\n\t\t\t\t} );\n\n\t\t\t\t// If it is then create range inside this element.\n\t\t\t\tif ( parentElement ) {\n\t\t\t\t\trangeToRemove = Range._createIn( parentElement );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we have found element to remove.\n\t\t\tif ( rangeToRemove ) {\n\t\t\t\t// We need to check if element range stick out of the given range and truncate if it is.\n\t\t\t\tif ( rangeToRemove.end.isAfter( range.end ) ) {\n\t\t\t\t\trangeToRemove.end = range.end;\n\t\t\t\t}\n\n\t\t\t\tif ( rangeToRemove.start.isBefore( range.start ) ) {\n\t\t\t\t\trangeToRemove.start = range.start;\n\t\t\t\t}\n\n\t\t\t\t// At the end we remove range with found element.\n\t\t\t\tthis.remove( rangeToRemove );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Moves nodes from provided range to target position.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-invalid-range-container` when\n\t * {@link module:engine/view/range~Range#start start} and {@link module:engine/view/range~Range#end end} positions are not placed inside\n\t * same parent container.\n\t *\n\t * @param {module:engine/view/range~Range} sourceRange Range containing nodes to move.\n\t * @param {module:engine/view/position~Position} targetPosition Position to insert.\n\t * @returns {module:engine/view/range~Range} Range in target container. Inserted nodes are placed between\n\t * {@link module:engine/view/range~Range#start start} and {@link module:engine/view/range~Range#end end} positions.\n\t */\n\tmove( sourceRange, targetPosition ) {\n\t\tlet nodes;\n\n\t\tif ( targetPosition.isAfter( sourceRange.end ) ) {\n\t\t\ttargetPosition = this._breakAttributes( targetPosition, true );\n\n\t\t\tconst parent = targetPosition.parent;\n\t\t\tconst countBefore = parent.childCount;\n\n\t\t\tsourceRange = this._breakAttributesRange( sourceRange, true );\n\n\t\t\tnodes = this.remove( sourceRange );\n\n\t\t\ttargetPosition.offset += ( parent.childCount - countBefore );\n\t\t} else {\n\t\t\tnodes = this.remove( sourceRange );\n\t\t}\n\n\t\treturn this.insert( targetPosition, nodes );\n\t}\n\n\t/**\n\t * Wraps elements within range with provided {@link module:engine/view/attributeelement~AttributeElement AttributeElement}.\n\t * If a collapsed range is provided, it will be wrapped only if it is equal to view selection.\n\t *\n\t * If a collapsed range was passed and is same as selection, the selection\n\t * will be moved to the inside of the wrapped attribute element.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError} `view-writer-invalid-range-container`\n\t * when {@link module:engine/view/range~Range#start}\n\t * and {@link module:engine/view/range~Range#end} positions are not placed inside same parent container.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError} `view-writer-wrap-invalid-attribute` when passed attribute element is not\n\t * an instance of {@link module:engine/view/attributeelement~AttributeElement AttributeElement}.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError} `view-writer-wrap-nonselection-collapsed-range` when passed range\n\t * is collapsed and different than view selection.\n\t *\n\t * @param {module:engine/view/range~Range} range Range to wrap.\n\t * @param {module:engine/view/attributeelement~AttributeElement} attribute Attribute element to use as wrapper.\n\t * @returns {module:engine/view/range~Range} range Range after wrapping, spanning over wrapping attribute element.\n\t*/\n\twrap( range, attribute ) {\n\t\tif ( !( attribute instanceof AttributeElement ) ) {\n\t\t\tthrow new CKEditorError( 'view-writer-wrap-invalid-attribute', this.document );\n\t\t}\n\n\t\tvalidateRangeContainer( range, this.document );\n\n\t\tif ( !range.isCollapsed ) {\n\t\t\t// Non-collapsed range. Wrap it with the attribute element.\n\t\t\treturn this._wrapRange( range, attribute );\n\t\t} else {\n\t\t\t// Collapsed range. Wrap position.\n\t\t\tlet position = range.start;\n\n\t\t\tif ( position.parent.is( 'element' ) && !_hasNonUiChildren( position.parent ) ) {\n\t\t\t\tposition = position.getLastMatchingPosition( value => value.item.is( 'uiElement' ) );\n\t\t\t}\n\n\t\t\tposition = this._wrapPosition( position, attribute );\n\t\t\tconst viewSelection = this.document.selection;\n\n\t\t\t// If wrapping position is equal to view selection, move view selection inside wrapping attribute element.\n\t\t\tif ( viewSelection.isCollapsed && viewSelection.getFirstPosition().isEqual( range.start ) ) {\n\t\t\t\tthis.setSelection( position );\n\t\t\t}\n\n\t\t\treturn new Range( position );\n\t\t}\n\t}\n\n\t/**\n\t * Unwraps nodes within provided range from attribute element.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-invalid-range-container` when\n\t * {@link module:engine/view/range~Range#start start} and {@link module:engine/view/range~Range#end end} positions are not placed inside\n\t * same parent container.\n\t *\n\t * @param {module:engine/view/range~Range} range\n\t * @param {module:engine/view/attributeelement~AttributeElement} attribute\n\t */\n\tunwrap( range, attribute ) {\n\t\tif ( !( attribute instanceof AttributeElement ) ) {\n\t\t\t/**\n\t\t\t * Attribute element need to be instance of attribute element.\n\t\t\t *\n\t\t\t * @error view-writer-unwrap-invalid-attribute\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-writer-unwrap-invalid-attribute', this.document );\n\t\t}\n\n\t\tvalidateRangeContainer( range, this.document );\n\n\t\t// If range is collapsed - nothing to unwrap.\n\t\tif ( range.isCollapsed ) {\n\t\t\treturn range;\n\t\t}\n\n\t\t// Break attributes at range start and end.\n\t\tconst { start: breakStart, end: breakEnd } = this._breakAttributesRange( range, true );\n\t\tconst parentContainer = breakStart.parent;\n\n\t\t// Unwrap children located between break points.\n\t\tconst newRange = this._unwrapChildren( parentContainer, breakStart.offset, breakEnd.offset, attribute );\n\n\t\t// Merge attributes at the both ends and return a new range.\n\t\tconst start = this.mergeAttributes( newRange.start );\n\n\t\t// If start position was merged - move end position back.\n\t\tif ( !start.isEqual( newRange.start ) ) {\n\t\t\tnewRange.end.offset--;\n\t\t}\n\n\t\tconst end = this.mergeAttributes( newRange.end );\n\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Renames element by creating a copy of renamed element but with changed name and then moving contents of the\n\t * old element to the new one. Keep in mind that this will invalidate all {@link module:engine/view/position~Position positions} which\n\t * has renamed element as {@link module:engine/view/position~Position#parent a parent}.\n\t *\n\t * New element has to be created because `Element#tagName` property in DOM is readonly.\n\t *\n\t * Since this function creates a new element and removes the given one, the new element is returned to keep reference.\n\t *\n\t * @param {String} newName New name for element.\n\t * @param {module:engine/view/containerelement~ContainerElement} viewElement Element to be renamed.\n\t */\n\trename( newName, viewElement ) {\n\t\tconst newElement = new ContainerElement( newName, viewElement.getAttributes() );\n\n\t\tthis.insert( Position._createAfter( viewElement ), newElement );\n\t\tthis.move( Range._createIn( viewElement ), Position._createAt( newElement, 0 ) );\n\t\tthis.remove( Range._createOn( viewElement ) );\n\n\t\treturn newElement;\n\t}\n\n\t/**\n\t * Cleans up memory by removing obsolete cloned elements group from the writer.\n\t *\n\t * Should be used whenever all {@link module:engine/view/attributeelement~AttributeElement attribute elements}\n\t * with the same {@link module:engine/view/attributeelement~AttributeElement#id id} are going to be removed from the view and\n\t * the group will no longer be needed.\n\t *\n\t * Cloned elements group are not removed automatically in case if the group is still needed after all its elements\n\t * were removed from the view.\n\t *\n\t * Keep in mind that group names are equal to the `id` property of the attribute element.\n\t *\n\t * @param {String} groupName Name of the group to clear.\n\t */\n\tclearClonedElementsGroup( groupName ) {\n\t\tthis._cloneGroups.delete( groupName );\n\t}\n\n\t/**\n\t * Creates position at the given location. The location can be specified as:\n\t *\n\t * * a {@link module:engine/view/position~Position position},\n\t * * parent element and offset (offset defaults to `0`),\n\t * * parent element and `'end'` (sets position at the end of that element),\n\t * * {@link module:engine/view/item~Item view item} and `'before'` or `'after'` (sets position before or after given view item).\n\t *\n\t * This method is a shortcut to other constructors such as:\n\t *\n\t * * {@link #createPositionBefore},\n\t * * {@link #createPositionAfter},\n\t *\n\t * @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/view/item~Item view item}.\n\t */\n\tcreatePositionAt( itemOrPosition, offset ) {\n\t\treturn Position._createAt( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Creates a new position after given view item.\n\t *\n\t * @param {module:engine/view/item~Item} item View item after which the position should be located.\n\t * @returns {module:engine/view/position~Position}\n\t */\n\tcreatePositionAfter( item ) {\n\t\treturn Position._createAfter( item );\n\t}\n\n\t/**\n\t * Creates a new position before given view item.\n\t *\n\t * @param {module:engine/view/item~Item} item View item before which the position should be located.\n\t * @returns {module:engine/view/position~Position}\n\t */\n\tcreatePositionBefore( item ) {\n\t\treturn Position._createBefore( item );\n\t}\n\n\t/**\n\t * Creates a range spanning from `start` position to `end` position.\n\t *\n\t * **Note:** This factory method creates it's own {@link module:engine/view/position~Position} instances basing on passed values.\n\t *\n\t * @param {module:engine/view/position~Position} start Start position.\n\t * @param {module:engine/view/position~Position} [end] End position. If not set, range will be collapsed at `start` position.\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRange( start, end ) {\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Creates a range that starts before given {@link module:engine/view/item~Item view item} and ends after it.\n\t *\n\t * @param {module:engine/view/item~Item} item\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRangeOn( item ) {\n\t\treturn Range._createOn( item );\n\t}\n\n\t/**\n\t * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of\n\t * that element and ends after the last child of that element.\n\t *\n\t * @param {module:engine/view/element~Element} element Element which is a parent for the range.\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRangeIn( element ) {\n\t\treturn Range._createIn( element );\n\t}\n\n\t/**\n\t Creates new {@link module:engine/view/selection~Selection} instance.\n\t *\n\t * \t\t// Creates empty selection without ranges.\n\t *\t\tconst selection = writer.createSelection();\n\t *\n\t *\t\t// Creates selection at the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tconst selection = writer.createSelection( range );\n\t *\n\t *\t\t// Creates selection at the given ranges\n\t * \t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];\n\t *\t\tconst selection = writer.createSelection( ranges );\n\t *\n\t *\t\t// Creates selection from the other selection.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tconst selection = writer.createSelection( otherSelection );\n\t *\n\t *\t\t// Creates selection from the document selection.\n\t *\t\tconst selection = writer.createSelection( editor.editing.view.document.selection );\n\t *\n\t * \t\t// Creates selection at the given position.\n\t *\t\tconst position = writer.createPositionFromPath( root, path );\n\t *\t\tconst selection = writer.createSelection( position );\n\t *\n\t *\t\t// Creates collapsed selection at the position of given item and offset.\n\t *\t\tconst paragraph = writer.createContainerElement( 'p' );\n\t *\t\tconst selection = writer.createSelection( paragraph, offset );\n\t *\n\t *\t\t// Creates a range inside an {@link module:engine/view/element~Element element} which starts before the\n\t *\t\t// first child of that element and ends after the last child of that element.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'in' );\n\t *\n\t *\t\t// Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends\n\t *\t\t// just after the item.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'on' );\n\t *\n\t * `Selection`'s constructor allow passing additional options (`backward`, `fake` and `label`) as the last argument.\n\t *\n\t *\t\t// Creates backward selection.\n\t *\t\tconst selection = writer.createSelection( range, { backward: true } );\n\t *\n\t * Fake selection does not render as browser native selection over selected elements and is hidden to the user.\n\t * This way, no native selection UI artifacts are displayed to the user and selection over elements can be\n\t * represented in other way, for example by applying proper CSS class.\n\t *\n\t * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM\n\t * (and be properly handled by screen readers).\n\t *\n\t *\t\t// Creates fake selection with label.\n\t *\t\tconst selection = writer.createSelection( range, { fake: true, label: 'foo' } );\n\t *\n\t * @param {module:engine/view/selection~Selectable} [selectable=null]\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Offset or place when selectable is an `Item`.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`.\n\t * @param {String} [options.label] Label for the fake selection.\n\t * @returns {module:engine/view/selection~Selection}\n\t */\n\tcreateSelection( selectable, placeOrOffset, options ) {\n\t\treturn new Selection( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Wraps children with provided `wrapElement`. Only children contained in `parent` element between\n\t * `startOffset` and `endOffset` will be wrapped.\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} parent\n\t * @param {Number} startOffset\n\t * @param {Number} endOffset\n\t * @param {module:engine/view/element~Element} wrapElement\n\t */\n\t_wrapChildren( parent, startOffset, endOffset, wrapElement ) {\n\t\tlet i = startOffset;\n\t\tconst wrapPositions = [];\n\n\t\twhile ( i < endOffset ) {\n\t\t\tconst child = parent.getChild( i );\n\t\t\tconst isText = child.is( 'text' );\n\t\t\tconst isAttribute = child.is( 'attributeElement' );\n\t\t\tconst isEmpty = child.is( 'emptyElement' );\n\t\t\tconst isUI = child.is( 'uiElement' );\n\n\t\t\t//\n\t\t\t// (In all examples, assume that `wrapElement` is `<span class=\"foo\">` element.)\n\t\t\t//\n\t\t\t// Check if `wrapElement` can be joined with the wrapped element. One of requirements is having same name.\n\t\t\t// If possible, join elements.\n\t\t\t//\n\t\t\t// <p><span class=\"bar\">abc</span></p> --> <p><span class=\"foo bar\">abc</span></p>\n\t\t\t//\n\t\t\tif ( isAttribute && this._wrapAttributeElement( wrapElement, child ) ) {\n\t\t\t\twrapPositions.push( new Position( parent, i ) );\n\t\t\t}\n\t\t\t//\n\t\t\t// Wrap the child if it is not an attribute element or if it is an attribute element that should be inside\n\t\t\t// `wrapElement` (due to priority).\n\t\t\t//\n\t\t\t// <p>abc</p> --> <p><span class=\"foo\">abc</span></p>\n\t\t\t// <p><strong>abc</strong></p> --> <p><span class=\"foo\"><strong>abc</strong></span></p>\n\t\t\t//\n\t\t\telse if ( isText || isEmpty || isUI || ( isAttribute && shouldABeOutsideB( wrapElement, child ) ) ) {\n\t\t\t\t// Clone attribute.\n\t\t\t\tconst newAttribute = wrapElement._clone();\n\n\t\t\t\t// Wrap current node with new attribute.\n\t\t\t\tchild._remove();\n\t\t\t\tnewAttribute._appendChild( child );\n\n\t\t\t\tparent._insertChild( i, newAttribute );\n\t\t\t\tthis._addToClonedElementsGroup( newAttribute );\n\n\t\t\t\twrapPositions.push( new Position( parent, i ) );\n\t\t\t}\n\t\t\t//\n\t\t\t// If other nested attribute is found and it wasn't wrapped (see above), continue wrapping inside it.\n\t\t\t//\n\t\t\t// <p><a href=\"foo.html\">abc</a></p> --> <p><a href=\"foo.html\"><span class=\"foo\">abc</span></a></p>\n\t\t\t//\n\t\t\telse if ( isAttribute ) {\n\t\t\t\tthis._wrapChildren( child, 0, child.childCount, wrapElement );\n\t\t\t}\n\n\t\t\ti++;\n\t\t}\n\n\t\t// Merge at each wrap.\n\t\tlet offsetChange = 0;\n\n\t\tfor ( const position of wrapPositions ) {\n\t\t\tposition.offset -= offsetChange;\n\n\t\t\t// Do not merge with elements outside selected children.\n\t\t\tif ( position.offset == startOffset ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst newPosition = this.mergeAttributes( position );\n\n\t\t\t// If nodes were merged - other merge offsets will change.\n\t\t\tif ( !newPosition.isEqual( position ) ) {\n\t\t\t\toffsetChange++;\n\t\t\t\tendOffset--;\n\t\t\t}\n\t\t}\n\n\t\treturn Range._createFromParentsAndOffsets( parent, startOffset, parent, endOffset );\n\t}\n\n\t/**\n\t * Unwraps children from provided `unwrapElement`. Only children contained in `parent` element between\n\t * `startOffset` and `endOffset` will be unwrapped.\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} parent\n\t * @param {Number} startOffset\n\t * @param {Number} endOffset\n\t * @param {module:engine/view/element~Element} unwrapElement\n\t */\n\t_unwrapChildren( parent, startOffset, endOffset, unwrapElement ) {\n\t\tlet i = startOffset;\n\t\tconst unwrapPositions = [];\n\n\t\t// Iterate over each element between provided offsets inside parent.\n\t\t// We don't use tree walker or range iterator because we will be removing and merging potentially multiple nodes,\n\t\t// so it could get messy. It is safer to it manually in this case.\n\t\twhile ( i < endOffset ) {\n\t\t\tconst child = parent.getChild( i );\n\n\t\t\t// Skip all text nodes. There should be no container element's here either.\n\t\t\tif ( !child.is( 'attributeElement' ) ) {\n\t\t\t\ti++;\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t//\n\t\t\t// (In all examples, assume that `unwrapElement` is `<span class=\"foo\">` element.)\n\t\t\t//\n\t\t\t// If the child is similar to the given attribute element, unwrap it - it will be completely removed.\n\t\t\t//\n\t\t\t// <p><span class=\"foo\">abc</span>xyz</p> --> <p>abcxyz</p>\n\t\t\t//\n\t\t\tif ( child.isSimilar( unwrapElement ) ) {\n\t\t\t\tconst unwrapped = child.getChildren();\n\t\t\t\tconst count = child.childCount;\n\n\t\t\t\t// Replace wrapper element with its children\n\t\t\t\tchild._remove();\n\t\t\t\tparent._insertChild( i, unwrapped );\n\n\t\t\t\tthis._removeFromClonedElementsGroup( child );\n\n\t\t\t\t// Save start and end position of moved items.\n\t\t\t\tunwrapPositions.push(\n\t\t\t\t\tnew Position( parent, i ),\n\t\t\t\t\tnew Position( parent, i + count )\n\t\t\t\t);\n\n\t\t\t\t// Skip elements that were unwrapped. Assuming there won't be another element to unwrap in child elements.\n\t\t\t\ti += count;\n\t\t\t\tendOffset += count - 1;\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t//\n\t\t\t// If the child is not similar but is an attribute element, try partial unwrapping - remove the same attributes/styles/classes.\n\t\t\t// Partial unwrapping will happen only if the elements have the same name.\n\t\t\t//\n\t\t\t// <p><span class=\"foo bar\">abc</span>xyz</p> --> <p><span class=\"bar\">abc</span>xyz</p>\n\t\t\t// <p><i class=\"foo\">abc</i>xyz</p> --> <p><i class=\"foo\">abc</i>xyz</p>\n\t\t\t//\n\t\t\tif ( this._unwrapAttributeElement( unwrapElement, child ) ) {\n\t\t\t\tunwrapPositions.push(\n\t\t\t\t\tnew Position( parent, i ),\n\t\t\t\t\tnew Position( parent, i + 1 )\n\t\t\t\t);\n\n\t\t\t\ti++;\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t//\n\t\t\t// If other nested attribute is found, look through it's children for elements to unwrap.\n\t\t\t//\n\t\t\t// <p><i><span class=\"foo\">abc</span></i><p> --> <p><i>abc</i><p>\n\t\t\t//\n\t\t\tthis._unwrapChildren( child, 0, child.childCount, unwrapElement );\n\n\t\t\ti++;\n\t\t}\n\n\t\t// Merge at each unwrap.\n\t\tlet offsetChange = 0;\n\n\t\tfor ( const position of unwrapPositions ) {\n\t\t\tposition.offset -= offsetChange;\n\n\t\t\t// Do not merge with elements outside selected children.\n\t\t\tif ( position.offset == startOffset || position.offset == endOffset ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst newPosition = this.mergeAttributes( position );\n\n\t\t\t// If nodes were merged - other merge offsets will change.\n\t\t\tif ( !newPosition.isEqual( position ) ) {\n\t\t\t\toffsetChange++;\n\t\t\t\tendOffset--;\n\t\t\t}\n\t\t}\n\n\t\treturn Range._createFromParentsAndOffsets( parent, startOffset, parent, endOffset );\n\t}\n\n\t/**\n\t * Helper function for `view.writer.wrap`. Wraps range with provided attribute element.\n\t * This method will also merge newly added attribute element with its siblings whenever possible.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError} `view-writer-wrap-invalid-attribute` when passed attribute element is not\n\t * an instance of {@link module:engine/view/attributeelement~AttributeElement AttributeElement}.\n\t *\n\t * @private\n\t * @param {module:engine/view/range~Range} range\n\t * @param {module:engine/view/attributeelement~AttributeElement} attribute\n\t * @returns {module:engine/view/range~Range} New range after wrapping, spanning over wrapping attribute element.\n\t */\n\t_wrapRange( range, attribute ) {\n\t\t// Break attributes at range start and end.\n\t\tconst { start: breakStart, end: breakEnd } = this._breakAttributesRange( range, true );\n\t\tconst parentContainer = breakStart.parent;\n\n\t\t// Wrap all children with attribute.\n\t\tconst newRange = this._wrapChildren( parentContainer, breakStart.offset, breakEnd.offset, attribute );\n\n\t\t// Merge attributes at the both ends and return a new range.\n\t\tconst start = this.mergeAttributes( newRange.start );\n\n\t\t// If start position was merged - move end position back.\n\t\tif ( !start.isEqual( newRange.start ) ) {\n\t\t\tnewRange.end.offset--;\n\t\t}\n\t\tconst end = this.mergeAttributes( newRange.end );\n\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Helper function for {@link #wrap}. Wraps position with provided attribute element.\n\t * This method will also merge newly added attribute element with its siblings whenever possible.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError} `view-writer-wrap-invalid-attribute` when passed attribute element is not\n\t * an instance of {@link module:engine/view/attributeelement~AttributeElement AttributeElement}.\n\t *\n\t * @private\n\t * @param {module:engine/view/position~Position} position\n\t * @param {module:engine/view/attributeelement~AttributeElement} attribute\n\t * @returns {module:engine/view/position~Position} New position after wrapping.\n\t */\n\t_wrapPosition( position, attribute ) {\n\t\t// Return same position when trying to wrap with attribute similar to position parent.\n\t\tif ( attribute.isSimilar( position.parent ) ) {\n\t\t\treturn movePositionToTextNode( position.clone() );\n\t\t}\n\n\t\t// When position is inside text node - break it and place new position between two text nodes.\n\t\tif ( position.parent.is( 'text' ) ) {\n\t\t\tposition = breakTextNode( position );\n\t\t}\n\n\t\t// Create fake element that will represent position, and will not be merged with other attributes.\n\t\tconst fakePosition = this.createAttributeElement();\n\t\tfakePosition._priority = Number.POSITIVE_INFINITY;\n\t\tfakePosition.isSimilar = () => false;\n\n\t\t// Insert fake element in position location.\n\t\tposition.parent._insertChild( position.offset, fakePosition );\n\n\t\t// Range around inserted fake attribute element.\n\t\tconst wrapRange = new Range( position, position.getShiftedBy( 1 ) );\n\n\t\t// Wrap fake element with attribute (it will also merge if possible).\n\t\tthis.wrap( wrapRange, attribute );\n\n\t\t// Remove fake element and place new position there.\n\t\tconst newPosition = new Position( fakePosition.parent, fakePosition.index );\n\t\tfakePosition._remove();\n\n\t\t// If position is placed between text nodes - merge them and return position inside.\n\t\tconst nodeBefore = newPosition.nodeBefore;\n\t\tconst nodeAfter = newPosition.nodeAfter;\n\n\t\tif ( nodeBefore instanceof Text && nodeAfter instanceof Text ) {\n\t\t\treturn mergeTextNodes( nodeBefore, nodeAfter );\n\t\t}\n\n\t\t// If position is next to text node - move position inside.\n\t\treturn movePositionToTextNode( newPosition );\n\t}\n\n\t/**\n\t * \tWraps one {@link module:engine/view/attributeelement~AttributeElement AttributeElement} into another by\n\t * \tmerging them if possible. When merging is possible - all attributes, styles and classes are moved from wrapper\n\t * \telement to element being wrapped.\n\t *\n\t * \t@private\n\t * \t@param {module:engine/view/attributeelement~AttributeElement} wrapper Wrapper AttributeElement.\n\t * \t@param {module:engine/view/attributeelement~AttributeElement} toWrap AttributeElement to wrap using wrapper element.\n\t * \t@returns {Boolean} Returns `true` if elements are merged.\n\t */\n\t_wrapAttributeElement( wrapper, toWrap ) {\n\t\tif ( !canBeJoined( wrapper, toWrap ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Can't merge if name or priority differs.\n\t\tif ( wrapper.name !== toWrap.name || wrapper.priority !== toWrap.priority ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if attributes can be merged.\n\t\tfor ( const key of wrapper.getAttributeKeys() ) {\n\t\t\t// Classes and styles should be checked separately.\n\t\t\tif ( key === 'class' || key === 'style' ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If some attributes are different we cannot wrap.\n\t\t\tif ( toWrap.hasAttribute( key ) && toWrap.getAttribute( key ) !== wrapper.getAttribute( key ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Check if styles can be merged.\n\t\tfor ( const key of wrapper.getStyleNames() ) {\n\t\t\tif ( toWrap.hasStyle( key ) && toWrap.getStyle( key ) !== wrapper.getStyle( key ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Move all attributes/classes/styles from wrapper to wrapped AttributeElement.\n\t\tfor ( const key of wrapper.getAttributeKeys() ) {\n\t\t\t// Classes and styles should be checked separately.\n\t\t\tif ( key === 'class' || key === 'style' ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Move only these attributes that are not present - other are similar.\n\t\t\tif ( !toWrap.hasAttribute( key ) ) {\n\t\t\t\tthis.setAttribute( key, wrapper.getAttribute( key ), toWrap );\n\t\t\t}\n\t\t}\n\n\t\tfor ( const key of wrapper.getStyleNames() ) {\n\t\t\tif ( !toWrap.hasStyle( key ) ) {\n\t\t\t\tthis.setStyle( key, wrapper.getStyle( key ), toWrap );\n\t\t\t}\n\t\t}\n\n\t\tfor ( const key of wrapper.getClassNames() ) {\n\t\t\tif ( !toWrap.hasClass( key ) ) {\n\t\t\t\tthis.addClass( key, toWrap );\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Unwraps {@link module:engine/view/attributeelement~AttributeElement AttributeElement} from another by removing\n\t * corresponding attributes, classes and styles. All attributes, classes and styles from wrapper should be present\n\t * inside element being unwrapped.\n\t *\n\t * @private\n\t * @param {module:engine/view/attributeelement~AttributeElement} wrapper Wrapper AttributeElement.\n\t * @param {module:engine/view/attributeelement~AttributeElement} toUnwrap AttributeElement to unwrap using wrapper element.\n\t * @returns {Boolean} Returns `true` if elements are unwrapped.\n\t **/\n\t_unwrapAttributeElement( wrapper, toUnwrap ) {\n\t\tif ( !canBeJoined( wrapper, toUnwrap ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Can't unwrap if name or priority differs.\n\t\tif ( wrapper.name !== toUnwrap.name || wrapper.priority !== toUnwrap.priority ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if AttributeElement has all wrapper attributes.\n\t\tfor ( const key of wrapper.getAttributeKeys() ) {\n\t\t\t// Classes and styles should be checked separately.\n\t\t\tif ( key === 'class' || key === 'style' ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If some attributes are missing or different we cannot unwrap.\n\t\t\tif ( !toUnwrap.hasAttribute( key ) || toUnwrap.getAttribute( key ) !== wrapper.getAttribute( key ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Check if AttributeElement has all wrapper classes.\n\t\tif ( !toUnwrap.hasClass( ...wrapper.getClassNames() ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if AttributeElement has all wrapper styles.\n\t\tfor ( const key of wrapper.getStyleNames() ) {\n\t\t\t// If some styles are missing or different we cannot unwrap.\n\t\t\tif ( !toUnwrap.hasStyle( key ) || toUnwrap.getStyle( key ) !== wrapper.getStyle( key ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// Remove all wrapper's attributes from unwrapped element.\n\t\tfor ( const key of wrapper.getAttributeKeys() ) {\n\t\t\t// Classes and styles should be checked separately.\n\t\t\tif ( key === 'class' || key === 'style' ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tthis.removeAttribute( key, toUnwrap );\n\t\t}\n\n\t\t// Remove all wrapper's classes from unwrapped element.\n\t\tthis.removeClass( Array.from( wrapper.getClassNames() ), toUnwrap );\n\n\t\t// Remove all wrapper's styles from unwrapped element.\n\t\tthis.removeStyle( Array.from( wrapper.getStyleNames() ), toUnwrap );\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Helper function used by other `DowncastWriter` methods. Breaks attribute elements at the boundaries of given range.\n\t *\n\t * @private\n\t * @param {module:engine/view/range~Range} range Range which `start` and `end` positions will be used to break attributes.\n\t * @param {Boolean} [forceSplitText=false] If set to `true`, will break text nodes even if they are directly in container element.\n\t * This behavior will result in incorrect view state, but is needed by other view writing methods which then fixes view state.\n\t * @returns {module:engine/view/range~Range} New range with located at break positions.\n\t */\n\t_breakAttributesRange( range, forceSplitText = false ) {\n\t\tconst rangeStart = range.start;\n\t\tconst rangeEnd = range.end;\n\n\t\tvalidateRangeContainer( range, this.document );\n\n\t\t// Break at the collapsed position. Return new collapsed range.\n\t\tif ( range.isCollapsed ) {\n\t\t\tconst position = this._breakAttributes( range.start, forceSplitText );\n\n\t\t\treturn new Range( position, position );\n\t\t}\n\n\t\tconst breakEnd = this._breakAttributes( rangeEnd, forceSplitText );\n\t\tconst count = breakEnd.parent.childCount;\n\t\tconst breakStart = this._breakAttributes( rangeStart, forceSplitText );\n\n\t\t// Calculate new break end offset.\n\t\tbreakEnd.offset += breakEnd.parent.childCount - count;\n\n\t\treturn new Range( breakStart, breakEnd );\n\t}\n\n\t/**\n\t * Helper function used by other `DowncastWriter` methods. Breaks attribute elements at given position.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-cannot-break-empty-element` when break position\n\t * is placed inside {@link module:engine/view/emptyelement~EmptyElement EmptyElement}.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-cannot-break-ui-element` when break position\n\t * is placed inside {@link module:engine/view/uielement~UIElement UIElement}.\n\t *\n\t * @private\n\t * @param {module:engine/view/position~Position} position Position where to break attributes.\n\t * @param {Boolean} [forceSplitText=false] If set to `true`, will break text nodes even if they are directly in container element.\n\t * This behavior will result in incorrect view state, but is needed by other view writing methods which then fixes view state.\n\t * @returns {module:engine/view/position~Position} New position after breaking the attributes.\n\t */\n\t_breakAttributes( position, forceSplitText = false ) {\n\t\tconst positionOffset = position.offset;\n\t\tconst positionParent = position.parent;\n\n\t\t// If position is placed inside EmptyElement - throw an exception as we cannot break inside.\n\t\tif ( position.parent.is( 'emptyElement' ) ) {\n\t\t\t/**\n\t\t\t * Cannot break inside EmptyElement instance.\n\t\t\t *\n\t\t\t * @error view-writer-cannot-break-empty-element\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-writer-cannot-break-empty-element', this.document );\n\t\t}\n\n\t\t// If position is placed inside UIElement - throw an exception as we cannot break inside.\n\t\tif ( position.parent.is( 'uiElement' ) ) {\n\t\t\t/**\n\t\t\t * Cannot break inside UIElement instance.\n\t\t\t *\n\t\t\t * @error view-writer-cannot-break-ui-element\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-writer-cannot-break-ui-element', this.document );\n\t\t}\n\n\t\t// There are no attributes to break and text nodes breaking is not forced.\n\t\tif ( !forceSplitText && positionParent.is( 'text' ) && isContainerOrFragment( positionParent.parent ) ) {\n\t\t\treturn position.clone();\n\t\t}\n\n\t\t// Position's parent is container, so no attributes to break.\n\t\tif ( isContainerOrFragment( positionParent ) ) {\n\t\t\treturn position.clone();\n\t\t}\n\n\t\t// Break text and start again in new position.\n\t\tif ( positionParent.is( 'text' ) ) {\n\t\t\treturn this._breakAttributes( breakTextNode( position ), forceSplitText );\n\t\t}\n\n\t\tconst length = positionParent.childCount;\n\n\t\t// <p>foo<b><u>bar{}</u></b></p>\n\t\t// <p>foo<b><u>bar</u>[]</b></p>\n\t\t// <p>foo<b><u>bar</u></b>[]</p>\n\t\tif ( positionOffset == length ) {\n\t\t\tconst newPosition = new Position( positionParent.parent, positionParent.index + 1 );\n\n\t\t\treturn this._breakAttributes( newPosition, forceSplitText );\n\t\t} else {\n\t\t\t// <p>foo<b><u>{}bar</u></b></p>\n\t\t\t// <p>foo<b>[]<u>bar</u></b></p>\n\t\t\t// <p>foo{}<b><u>bar</u></b></p>\n\t\t\tif ( positionOffset === 0 ) {\n\t\t\t\tconst newPosition = new Position( positionParent.parent, positionParent.index );\n\n\t\t\t\treturn this._breakAttributes( newPosition, forceSplitText );\n\t\t\t}\n\t\t\t// <p>foo<b><u>b{}ar</u></b></p>\n\t\t\t// <p>foo<b><u>b[]ar</u></b></p>\n\t\t\t// <p>foo<b><u>b</u>[]<u>ar</u></b></p>\n\t\t\t// <p>foo<b><u>b</u></b>[]<b><u>ar</u></b></p>\n\t\t\telse {\n\t\t\t\tconst offsetAfter = positionParent.index + 1;\n\n\t\t\t\t// Break element.\n\t\t\t\tconst clonedNode = positionParent._clone();\n\n\t\t\t\t// Insert cloned node to position's parent node.\n\t\t\t\tpositionParent.parent._insertChild( offsetAfter, clonedNode );\n\t\t\t\tthis._addToClonedElementsGroup( clonedNode );\n\n\t\t\t\t// Get nodes to move.\n\t\t\t\tconst count = positionParent.childCount - positionOffset;\n\t\t\t\tconst nodesToMove = positionParent._removeChildren( positionOffset, count );\n\n\t\t\t\t// Move nodes to cloned node.\n\t\t\t\tclonedNode._appendChild( nodesToMove );\n\n\t\t\t\t// Create new position to work on.\n\t\t\t\tconst newPosition = new Position( positionParent.parent, offsetAfter );\n\n\t\t\t\treturn this._breakAttributes( newPosition, forceSplitText );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Stores the information that an {@link module:engine/view/attributeelement~AttributeElement attribute element} was\n\t * added to the tree. Saves the reference to the group in the given element and updates the group, so other elements\n\t * from the group now keep a reference to the given attribute element.\n\t *\n\t * The clones group can be obtained using {@link module:engine/view/attributeelement~AttributeElement#getElementsWithSameId}.\n\t *\n\t * Does nothing if added element has no {@link module:engine/view/attributeelement~AttributeElement#id id}.\n\t *\n\t * @private\n\t * @param {module:engine/view/attributeelement~AttributeElement} element Attribute element to save.\n\t */\n\t_addToClonedElementsGroup( element ) {\n\t\t// Add only if the element is in document tree.\n\t\tif ( !element.root.is( 'rootElement' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Traverse the element's children recursively to find other attribute elements that also might got inserted.\n\t\t// The loop is at the beginning so we can make fast returns later in the code.\n\t\tif ( element.is( 'element' ) ) {\n\t\t\tfor ( const child of element.getChildren() ) {\n\t\t\t\tthis._addToClonedElementsGroup( child );\n\t\t\t}\n\t\t}\n\n\t\tconst id = element.id;\n\n\t\tif ( !id ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet group = this._cloneGroups.get( id );\n\n\t\tif ( !group ) {\n\t\t\tgroup = new Set();\n\t\t\tthis._cloneGroups.set( id, group );\n\t\t}\n\n\t\tgroup.add( element );\n\t\telement._clonesGroup = group;\n\t}\n\n\t/**\n\t * Removes all the information about the given {@link module:engine/view/attributeelement~AttributeElement attribute element}\n\t * from its clones group.\n\t *\n\t * Keep in mind, that the element will still keep a reference to the group (but the group will not keep a reference to it).\n\t * This allows to reference the whole group even if the element was already removed from the tree.\n\t *\n\t * Does nothing if the element has no {@link module:engine/view/attributeelement~AttributeElement#id id}.\n\t *\n\t * @private\n\t * @param {module:engine/view/attributeelement~AttributeElement} element Attribute element to remove.\n\t */\n\t_removeFromClonedElementsGroup( element ) {\n\t\t// Traverse the element's children recursively to find other attribute elements that also got removed.\n\t\t// The loop is at the beginning so we can make fast returns later in the code.\n\t\tif ( element.is( 'element' ) ) {\n\t\t\tfor ( const child of element.getChildren() ) {\n\t\t\t\tthis._removeFromClonedElementsGroup( child );\n\t\t\t}\n\t\t}\n\n\t\tconst id = element.id;\n\n\t\tif ( !id ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst group = this._cloneGroups.get( id );\n\n\t\tif ( !group ) {\n\t\t\treturn;\n\t\t}\n\n\t\tgroup.delete( element );\n\t\t// Not removing group from element on purpose!\n\t\t// If other parts of code have reference to this element, they will be able to get references to other elements from the group.\n\t}\n}\n\n// Helper function for `view.writer.wrap`. Checks if given element has any children that are not ui elements.\nfunction _hasNonUiChildren( parent ) {\n\treturn Array.from( parent.getChildren() ).some( child => !child.is( 'uiElement' ) );\n}\n\n/**\n * Attribute element need to be instance of attribute element.\n *\n * @error view-writer-wrap-invalid-attribute\n */\n\n// Returns first parent container of specified {@link module:engine/view/position~Position Position}.\n// Position's parent node is checked as first, then next parents are checked.\n// Note that {@link module:engine/view/documentfragment~DocumentFragment DocumentFragment} is treated like a container.\n//\n// @param {module:engine/view/position~Position} position Position used as a start point to locate parent container.\n// @returns {module:engine/view/containerelement~ContainerElement|module:engine/view/documentfragment~DocumentFragment|undefined}\n// Parent container element or `undefined` if container is not found.\nfunction getParentContainer( position ) {\n\tlet parent = position.parent;\n\n\twhile ( !isContainerOrFragment( parent ) ) {\n\t\tif ( !parent ) {\n\t\t\treturn undefined;\n\t\t}\n\t\tparent = parent.parent;\n\t}\n\n\treturn parent;\n}\n\n// Checks if first {@link module:engine/view/attributeelement~AttributeElement AttributeElement} provided to the function\n// can be wrapped otuside second element. It is done by comparing elements'\n// {@link module:engine/view/attributeelement~AttributeElement#priority priorities}, if both have same priority\n// {@link module:engine/view/element~Element#getIdentity identities} are compared.\n//\n// @param {module:engine/view/attributeelement~AttributeElement} a\n// @param {module:engine/view/attributeelement~AttributeElement} b\n// @returns {Boolean}\nfunction shouldABeOutsideB( a, b ) {\n\tif ( a.priority < b.priority ) {\n\t\treturn true;\n\t} else if ( a.priority > b.priority ) {\n\t\treturn false;\n\t}\n\n\t// When priorities are equal and names are different - use identities.\n\treturn a.getIdentity() < b.getIdentity();\n}\n\n// Returns new position that is moved to near text node. Returns same position if there is no text node before of after\n// specified position.\n//\n//\t\t<p>foo[]</p> -> <p>foo{}</p>\n//\t\t<p>[]foo</p> -> <p>{}foo</p>\n//\n// @param {module:engine/view/position~Position} position\n// @returns {module:engine/view/position~Position} Position located inside text node or same position if there is no text nodes\n// before or after position location.\nfunction movePositionToTextNode( position ) {\n\tconst nodeBefore = position.nodeBefore;\n\n\tif ( nodeBefore && nodeBefore.is( 'text' ) ) {\n\t\treturn new Position( nodeBefore, nodeBefore.data.length );\n\t}\n\n\tconst nodeAfter = position.nodeAfter;\n\n\tif ( nodeAfter && nodeAfter.is( 'text' ) ) {\n\t\treturn new Position( nodeAfter, 0 );\n\t}\n\n\treturn position;\n}\n\n// Breaks text node into two text nodes when possible.\n//\n//\t\t<p>foo{}bar</p> -> <p>foo[]bar</p>\n//\t\t<p>{}foobar</p> -> <p>[]foobar</p>\n//\t\t<p>foobar{}</p> -> <p>foobar[]</p>\n//\n// @param {module:engine/view/position~Position} position Position that need to be placed inside text node.\n// @returns {module:engine/view/position~Position} New position after breaking text node.\nfunction breakTextNode( position ) {\n\tif ( position.offset == position.parent.data.length ) {\n\t\treturn new Position( position.parent.parent, position.parent.index + 1 );\n\t}\n\n\tif ( position.offset === 0 ) {\n\t\treturn new Position( position.parent.parent, position.parent.index );\n\t}\n\n\t// Get part of the text that need to be moved.\n\tconst textToMove = position.parent.data.slice( position.offset );\n\n\t// Leave rest of the text in position's parent.\n\tposition.parent._data = position.parent.data.slice( 0, position.offset );\n\n\t// Insert new text node after position's parent text node.\n\tposition.parent.parent._insertChild( position.parent.index + 1, new Text( textToMove ) );\n\n\t// Return new position between two newly created text nodes.\n\treturn new Position( position.parent.parent, position.parent.index + 1 );\n}\n\n// Merges two text nodes into first node. Removes second node and returns merge position.\n//\n// @param {module:engine/view/text~Text} t1 First text node to merge. Data from second text node will be moved at the end of\n// this text node.\n// @param {module:engine/view/text~Text} t2 Second text node to merge. This node will be removed after merging.\n// @returns {module:engine/view/position~Position} Position after merging text nodes.\nfunction mergeTextNodes( t1, t2 ) {\n\t// Merge text data into first text node and remove second one.\n\tconst nodeBeforeLength = t1.data.length;\n\tt1._data += t2.data;\n\tt2._remove();\n\n\treturn new Position( t1, nodeBeforeLength );\n}\n\n// Checks if provided nodes are valid to insert. Checks if each node is an instance of\n// {@link module:engine/view/text~Text Text} or {@link module:engine/view/attributeelement~AttributeElement AttributeElement},\n// {@link module:engine/view/containerelement~ContainerElement ContainerElement},\n// {@link module:engine/view/emptyelement~EmptyElement EmptyElement} or\n// {@link module:engine/view/uielement~UIElement UIElement}.\n//\n// Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-insert-invalid-node` when nodes to insert\n// contains instances that are not {@link module:engine/view/text~Text Texts},\n// {@link module:engine/view/emptyelement~EmptyElement EmptyElements},\n// {@link module:engine/view/uielement~UIElement UIElements},\n// {@link module:engine/view/attributeelement~AttributeElement AttributeElements} or\n// {@link module:engine/view/containerelement~ContainerElement ContainerElements}.\n//\n// @param Iterable.<module:engine/view/text~Text|module:engine/view/attributeelement~AttributeElement\n// |module:engine/view/containerelement~ContainerElement> nodes\n// @param {Object} errorContext\nfunction validateNodesToInsert( nodes, errorContext ) {\n\tfor ( const node of nodes ) {\n\t\tif ( !validNodesToInsert.some( ( validNode => node instanceof validNode ) ) ) { // eslint-disable-line no-use-before-define\n\t\t\t/**\n\t\t\t * Inserted nodes should be valid to insert. of {@link module:engine/view/attributeelement~AttributeElement AttributeElement},\n\t\t\t * {@link module:engine/view/containerelement~ContainerElement ContainerElement},\n\t\t\t * {@link module:engine/view/emptyelement~EmptyElement EmptyElement},\n\t\t\t * {@link module:engine/view/uielement~UIElement UIElement}, {@link module:engine/view/text~Text Text}.\n\t\t\t *\n\t\t\t * @error view-writer-insert-invalid-node\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-writer-insert-invalid-node', errorContext );\n\t\t}\n\n\t\tif ( !node.is( 'text' ) ) {\n\t\t\tvalidateNodesToInsert( node.getChildren(), errorContext );\n\t\t}\n\t}\n}\n\nconst validNodesToInsert = [ Text, AttributeElement, ContainerElement, EmptyElement, UIElement ];\n\n// Checks if node is ContainerElement or DocumentFragment, because in most cases they should be treated the same way.\n//\n// @param {module:engine/view/node~Node} node\n// @returns {Boolean} Returns `true` if node is instance of ContainerElement or DocumentFragment.\nfunction isContainerOrFragment( node ) {\n\treturn node && ( node.is( 'containerElement' ) || node.is( 'documentFragment' ) );\n}\n\n// Checks if {@link module:engine/view/range~Range#start range start} and {@link module:engine/view/range~Range#end range end} are placed\n// inside same {@link module:engine/view/containerelement~ContainerElement container element}.\n// Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-writer-invalid-range-container` when validation fails.\n//\n// @param {module:engine/view/range~Range} range\n// @param {Object} errorContext\nfunction validateRangeContainer( range, errorContext ) {\n\tconst startContainer = getParentContainer( range.start );\n\tconst endContainer = getParentContainer( range.end );\n\n\tif ( !startContainer || !endContainer || startContainer !== endContainer ) {\n\t\t/**\n\t\t * Range container is invalid. This can happen if {@link module:engine/view/range~Range#start range start} and\n\t\t * {@link module:engine/view/range~Range#end range end} positions are not placed inside same container or\n\t\t * parent container for these positions cannot be found.\n\t\t *\n\t\t * @error view-writer-invalid-range-container\n\t\t */\n\n\t\tthrow new CKEditorError( 'view-writer-invalid-range-container', errorContext );\n\t}\n}\n\n// Checks if two attribute elements can be joined together. Elements can be joined together if, and only if\n// they do not have ids specified.\n//\n// @private\n// @param {module:engine/view/element~Element} a\n// @param {module:engine/view/element~Element} b\n// @returns {Boolean}\nfunction canBeJoined( a, b ) {\n\treturn a.id === null && b.id === null;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/istext\n */\n\n/**\n * Checks if the object is a native DOM Text node.\n *\n * @param {*} obj\n * @returns {Boolean}\n */\nexport default function isText( obj ) {\n\treturn Object.prototype.toString.call( obj ) == '[object Text]';\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nimport { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport isText from '@ckeditor/ckeditor5-utils/src/dom/istext';\n\n/**\n * Set of utils related to block and inline fillers handling.\n *\n * Browsers do not allow to put caret in elements which does not have height. Because of it, we need to fill all\n * empty elements which should be selectable with elements or characters called \"fillers\". Unfortunately there is no one\n * universal filler, this is why two types are uses:\n *\n * * Block filler is an element which fill block elements, like `<p>`. CKEditor uses `<br>` as a block filler during the editing,\n * as browsers do natively. So instead of an empty `<p>` there will be `<p><br></p>`. The advantage of block filler is that\n * it is transparent for the selection, so when the caret is before the `<br>` and user presses right arrow he will be\n * moved to the next paragraph, not after the `<br>`. The disadvantage is that it breaks a block, so it can not be used\n * in the middle of a line of text. The {@link module:engine/view/filler~BR_FILLER `<br>` filler} can be replaced with any other\n * character in the data output, for instance {@link module:engine/view/filler~NBSP_FILLER non-breaking space}.\n *\n * * Inline filler is a filler which does not break a line of text, so it can be used inside the text, for instance in the empty\n * `<b>` surrendered by text: `foo<b></b>bar`, if we want to put the caret there. CKEditor uses a sequence of the zero-width\n * spaces as an {@link module:engine/view/filler~INLINE_FILLER inline filler} having the predetermined\n * {@link module:engine/view/filler~INLINE_FILLER_LENGTH length}. A sequence is used, instead of a single character to\n * avoid treating random zero-width spaces as the inline filler. Disadvantage of the inline filler is that it is not\n * transparent for the selection. The arrow key moves the caret between zero-width spaces characters, so the additional\n * code is needed to handle the caret.\n *\n * Both inline and block fillers are handled by the {@link module:engine/view/renderer~Renderer renderer} and are not present in the\n * view.\n *\n * @module engine/view/filler\n */\n\n/**\n * Non-breaking space filler creator. This is a function which creates `&nbsp;` text node.\n * It defines how the filler is created.\n *\n * @see module:engine/view/filler~BR_FILLER\n * @function\n */\nexport const NBSP_FILLER = domDocument => domDocument.createTextNode( '\\u00A0' );\n\n/**\n * `<br>` filler creator. This is a function which creates `<br data-cke-filler=\"true\">` element.\n * It defines how the filler is created.\n *\n * @see module:engine/view/filler~NBSP_FILLER\n * @function\n */\nexport const BR_FILLER = domDocument => {\n\tconst fillerBr = domDocument.createElement( 'br' );\n\tfillerBr.dataset.ckeFiller = true;\n\n\treturn fillerBr;\n};\n\n/**\n * Length of the {@link module:engine/view/filler~INLINE_FILLER INLINE_FILLER}.\n */\nexport const INLINE_FILLER_LENGTH = 7;\n\n/**\n * Inline filler which is a sequence of the zero width spaces.\n */\nexport const INLINE_FILLER = ( () => {\n\tlet inlineFiller = '';\n\n\tfor ( let i = 0; i < INLINE_FILLER_LENGTH; i++ ) {\n\t\tinlineFiller += '\\u200b';\n\t}\n\n\treturn inlineFiller;\n} )(); // Usu IIF so the INLINE_FILLER appears as a constant in the docs.\n\n/**\n * Checks if the node is a text node which starts with the {@link module:engine/view/filler~INLINE_FILLER inline filler}.\n *\n *\t\tstartsWithFiller( document.createTextNode( INLINE_FILLER ) ); // true\n *\t\tstartsWithFiller( document.createTextNode( INLINE_FILLER + 'foo' ) ); // true\n *\t\tstartsWithFiller( document.createTextNode( 'foo' ) ); // false\n *\t\tstartsWithFiller( document.createElement( 'p' ) ); // false\n *\n * @param {Node} domNode DOM node.\n * @returns {Boolean} True if the text node starts with the {@link module:engine/view/filler~INLINE_FILLER inline filler}.\n */\nexport function startsWithFiller( domNode ) {\n\treturn isText( domNode ) && ( domNode.data.substr( 0, INLINE_FILLER_LENGTH ) === INLINE_FILLER );\n}\n\n/**\n * Checks if the text node contains only the {@link module:engine/view/filler~INLINE_FILLER inline filler}.\n *\n *\t\tisInlineFiller( document.createTextNode( INLINE_FILLER ) ); // true\n *\t\tisInlineFiller( document.createTextNode( INLINE_FILLER + 'foo' ) ); // false\n *\n * @param {Text} domText DOM text node.\n * @returns {Boolean} True if the text node contains only the {@link module:engine/view/filler~INLINE_FILLER inline filler}.\n */\nexport function isInlineFiller( domText ) {\n\treturn domText.data.length == INLINE_FILLER_LENGTH && startsWithFiller( domText );\n}\n\n/**\n * Get string data from the text node, removing an {@link module:engine/view/filler~INLINE_FILLER inline filler} from it,\n * if text node contains it.\n *\n *\t\tgetDataWithoutFiller( document.createTextNode( INLINE_FILLER + 'foo' ) ) == 'foo' // true\n *\t\tgetDataWithoutFiller( document.createTextNode( 'foo' ) ) == 'foo' // true\n *\n * @param {Text} domText DOM text node, possible with inline filler.\n * @returns {String} Data without filler.\n */\nexport function getDataWithoutFiller( domText ) {\n\tif ( startsWithFiller( domText ) ) {\n\t\treturn domText.data.slice( INLINE_FILLER_LENGTH );\n\t} else {\n\t\treturn domText.data;\n\t}\n}\n\n/**\n * Assign key observer which move cursor from the end of the inline filler to the beginning of it when\n * the left arrow is pressed, so the filler does not break navigation.\n *\n * @param {module:engine/view/view~View} view View controller instance we should inject quirks handling on.\n */\nexport function injectQuirksHandling( view ) {\n\tview.document.on( 'keydown', jumpOverInlineFiller );\n}\n\n// Move cursor from the end of the inline filler to the beginning of it when, so the filler does not break navigation.\nfunction jumpOverInlineFiller( evt, data ) {\n\tif ( data.keyCode == keyCodes.arrowleft ) {\n\t\tconst domSelection = data.domTarget.ownerDocument.defaultView.getSelection();\n\n\t\tif ( domSelection.rangeCount == 1 && domSelection.getRangeAt( 0 ).collapsed ) {\n\t\t\tconst domParent = domSelection.getRangeAt( 0 ).startContainer;\n\t\t\tconst domOffset = domSelection.getRangeAt( 0 ).startOffset;\n\n\t\t\tif ( startsWithFiller( domParent ) && domOffset <= INLINE_FILLER_LENGTH ) {\n\t\t\t\tdomSelection.collapse( domParent, 0 );\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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// Transform text or any iterable into arrays for easier, consistent processing.\n\tif ( !Array.isArray( a ) ) {\n\t\ta = Array.from( a );\n\t}\n\n\tif ( !Array.isArray( b ) ) {\n\t\tb = Array.from( 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.<Object>} 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.<String>} 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-2019, 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/diff\n */\n\nimport fastDiff from '../src/fastdiff';\n\n// The following code is based on the \"O(NP) Sequence Comparison Algorithm\"\n// by Sun Wu, Udi Manber, Gene Myers, Webb Miller.\n\n/**\n * Calculates the difference between two arrays or strings producing an array containing a list of changes\n * necessary to transform input into output.\n *\n *\t\tdiff( 'aba', 'acca' ); // [ 'equal', 'insert', 'insert', 'delete', 'equal' ]\n *\n * This function is based on the \"O(NP) Sequence Comparison Algorithm\" by Sun Wu, Udi Manber, Gene Myers, Webb Miller.\n * Unfortunately, while it gives the most precise results, its to complex for longer strings/arrow (above 200 items).\n * Therefore, `diff()` automatically switches to {@link module:utils/fastdiff~fastDiff `fastDiff()`} when detecting\n * such a scenario. The return formats of both functions are identical.\n *\n * @param {Array|String} a Input array or string.\n * @param {Array|String} b Output array or string.\n * @param {Function} [cmp] Optional function used to compare array values, by default === is used.\n * @returns {Array} Array of changes.\n */\nexport default function diff( a, b, cmp ) {\n\t// Set the comparator function.\n\tcmp = cmp || function( a, b ) {\n\t\treturn a === b;\n\t};\n\n\tconst aLength = a.length;\n\tconst bLength = b.length;\n\n\t// Perform `fastDiff` for longer strings/arrays (see #269).\n\tif ( aLength > 200 || bLength > 200 || aLength + bLength > 300 ) {\n\t\treturn diff.fastDiff( a, b, cmp, true );\n\t}\n\n\t// Temporary action type statics.\n\tlet _insert, _delete;\n\n\t// Swapped the arrays to use the shorter one as the first one.\n\tif ( bLength < aLength ) {\n\t\tconst tmp = a;\n\n\t\ta = b;\n\t\tb = tmp;\n\n\t\t// We swap the action types as well.\n\t\t_insert = 'delete';\n\t\t_delete = 'insert';\n\t} else {\n\t\t_insert = 'insert';\n\t\t_delete = 'delete';\n\t}\n\n\tconst m = a.length;\n\tconst n = b.length;\n\tconst delta = n - m;\n\n\t// Edit scripts, for each diagonal.\n\tconst es = {};\n\t// Furthest points, the furthest y we can get on each diagonal.\n\tconst fp = {};\n\n\tfunction snake( k ) {\n\t\t// We use -1 as an alternative below to handle initial values ( instead of filling the fp with -1 first ).\n\t\t// Furthest points (y) on the diagonal below k.\n\t\tconst y1 = ( fp[ k - 1 ] !== undefined ? fp[ k - 1 ] : -1 ) + 1;\n\t\t// Furthest points (y) on the diagonal above k.\n\t\tconst y2 = fp[ k + 1 ] !== undefined ? fp[ k + 1 ] : -1;\n\t\t// The way we should go to get further.\n\t\tconst dir = y1 > y2 ? -1 : 1;\n\n\t\t// Clone previous changes array (if any).\n\t\tif ( es[ k + dir ] ) {\n\t\t\tes[ k ] = es[ k + dir ].slice( 0 );\n\t\t}\n\n\t\t// Create changes array.\n\t\tif ( !es[ k ] ) {\n\t\t\tes[ k ] = [];\n\t\t}\n\n\t\t// Push the action.\n\t\tes[ k ].push( y1 > y2 ? _insert : _delete );\n\n\t\t// Set the beginning coordinates.\n\t\tlet y = Math.max( y1, y2 );\n\t\tlet x = y - k;\n\n\t\t// Traverse the diagonal as long as the values match.\n\t\twhile ( x < m && y < n && cmp( a[ x ], b[ y ] ) ) {\n\t\t\tx++;\n\t\t\ty++;\n\t\t\t// Push no change action.\n\t\t\tes[ k ].push( 'equal' );\n\t\t}\n\n\t\treturn y;\n\t}\n\n\tlet p = 0;\n\tlet k;\n\n\t// Traverse the graph until we reach the end of the longer string.\n\tdo {\n\t\t// Updates furthest points and edit scripts for diagonals below delta.\n\t\tfor ( k = -p; k < delta; k++ ) {\n\t\t\tfp[ k ] = snake( k );\n\t\t}\n\n\t\t// Updates furthest points and edit scripts for diagonals above delta.\n\t\tfor ( k = delta + p; k > delta; k-- ) {\n\t\t\tfp[ k ] = snake( k );\n\t\t}\n\n\t\t// Updates furthest point and edit script for the delta diagonal.\n\t\t// note that the delta diagonal is the one which goes through the sink (m, n).\n\t\tfp[ delta ] = snake( delta );\n\n\t\tp++;\n\t} while ( fp[ delta ] !== n );\n\n\t// Return the final list of edit changes.\n\t// We remove the first item that represents the action for the injected nulls.\n\treturn es[ delta ].slice( 1 );\n}\n\n// Store the API in static property to easily overwrite it in tests.\n// Too bad dependency injection does not work in Webpack + ES 6 (const) + Babel.\ndiff.fastDiff = fastDiff;\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/insertat\n */\n\n/**\n * Inserts node to the parent at given index.\n *\n * @param {Element} parentElement Parent element.\n * @param {Number} index Insertions index.\n * @param {Node} nodeToInsert Node to insert.\n */\nexport default function insertAt( parentElement, index, nodeToInsert ) {\n\tparentElement.insertBefore( nodeToInsert, parentElement.childNodes[ index ] || null );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/remove\n */\n\n/**\n * Removes given node from parent.\n *\n * @param {Node} node Node to remove.\n */\nexport default function remove( node ) {\n\tconst parent = node.parentNode;\n\n\tif ( parent ) {\n\t\tparent.removeChild( node );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/isnode\n */\n\n/**\n * Checks if the object is a native DOM Node.\n *\n * @param {*} obj\n * @returns {Boolean}\n */\nexport default function isNode( obj ) {\n\tif ( obj ) {\n\t\tif ( obj.defaultView ) {\n\t\t\treturn obj instanceof obj.defaultView.Document;\n\t\t} else if ( obj.ownerDocument && obj.ownerDocument.defaultView ) {\n\t\t\treturn obj instanceof obj.ownerDocument.defaultView.Node;\n\t\t}\n\t}\n\n\treturn false;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* globals Node */\n\n/**\n * @module engine/view/renderer\n */\n\nimport ViewText from './text';\nimport ViewPosition from './position';\nimport { INLINE_FILLER, INLINE_FILLER_LENGTH, startsWithFiller, isInlineFiller } from './filler';\n\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport diff from '@ckeditor/ckeditor5-utils/src/diff';\nimport insertAt from '@ckeditor/ckeditor5-utils/src/dom/insertat';\nimport remove from '@ckeditor/ckeditor5-utils/src/dom/remove';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport isText from '@ckeditor/ckeditor5-utils/src/dom/istext';\nimport isNode from '@ckeditor/ckeditor5-utils/src/dom/isnode';\nimport fastDiff from '@ckeditor/ckeditor5-utils/src/fastdiff';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\n/**\n * Renderer is responsible for updating the DOM structure and the DOM selection based on\n * the {@link module:engine/view/renderer~Renderer#markToSync information about updated view nodes}.\n * In other words, it renders the view to the DOM.\n *\n * Its main responsibility is to make only the necessary, minimal changes to the DOM. However, unlike in many\n * virtual DOM implementations, the primary reason for doing minimal changes is not the performance but ensuring\n * that native editing features such as text composition, autocompletion, spell checking, selection's x-index are\n * affected as little as possible.\n *\n * Renderer uses {@link module:engine/view/domconverter~DomConverter} to transform view nodes and positions\n * to and from the DOM.\n */\nexport default class Renderer {\n\t/**\n\t * Creates a renderer instance.\n\t *\n\t * @param {module:engine/view/domconverter~DomConverter} domConverter Converter instance.\n\t * @param {module:engine/view/documentselection~DocumentSelection} selection View selection.\n\t */\n\tconstructor( domConverter, selection ) {\n\t\t/**\n\t\t * Set of DOM Documents instances.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set.<Document>}\n\t\t */\n\t\tthis.domDocuments = new Set();\n\n\t\t/**\n\t\t * Converter instance.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/domconverter~DomConverter}\n\t\t */\n\t\tthis.domConverter = domConverter;\n\n\t\t/**\n\t\t * Set of nodes which attributes changed and may need to be rendered.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set.<module:engine/view/node~Node>}\n\t\t */\n\t\tthis.markedAttributes = new Set();\n\n\t\t/**\n\t\t * Set of elements which child lists changed and may need to be rendered.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set.<module:engine/view/node~Node>}\n\t\t */\n\t\tthis.markedChildren = new Set();\n\n\t\t/**\n\t\t * Set of text nodes which text data changed and may need to be rendered.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set.<module:engine/view/node~Node>}\n\t\t */\n\t\tthis.markedTexts = new Set();\n\n\t\t/**\n\t\t * View selection. Renderer updates DOM selection based on the view selection.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/documentselection~DocumentSelection}\n\t\t */\n\t\tthis.selection = selection;\n\n\t\t/**\n\t\t * Indicates if the view document is focused and selection can be rendered. Selection will not be rendered if\n\t\t * this is set to `false`.\n\t\t *\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis.isFocused = false;\n\n\t\t/**\n\t\t * The text node in which the inline filler was rendered.\n\t\t *\n\t\t * @private\n\t\t * @member {Text}\n\t\t */\n\t\tthis._inlineFiller = null;\n\n\t\t/**\n\t\t * DOM element containing fake selection.\n\t\t *\n\t\t * @private\n\t\t * @type {null|HTMLElement}\n\t\t */\n\t\tthis._fakeSelectionContainer = null;\n\t}\n\n\t/**\n\t * Marks a view node to be updated in the DOM by {@link #render `render()`}.\n\t *\n\t * Note that only view nodes whose parents have corresponding DOM elements need to be marked to be synchronized.\n\t *\n\t * @see #markedAttributes\n\t * @see #markedChildren\n\t * @see #markedTexts\n\t *\n\t * @param {module:engine/view/document~ChangeType} type Type of the change.\n\t * @param {module:engine/view/node~Node} node Node to be marked.\n\t */\n\tmarkToSync( type, node ) {\n\t\tif ( type === 'text' ) {\n\t\t\tif ( this.domConverter.mapViewToDom( node.parent ) ) {\n\t\t\t\tthis.markedTexts.add( node );\n\t\t\t}\n\t\t} else {\n\t\t\t// If the node has no DOM element it is not rendered yet,\n\t\t\t// its children/attributes do not need to be marked to be sync.\n\t\t\tif ( !this.domConverter.mapViewToDom( node ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( type === 'attributes' ) {\n\t\t\t\tthis.markedAttributes.add( node );\n\t\t\t} else if ( type === 'children' ) {\n\t\t\t\tthis.markedChildren.add( node );\n\t\t\t} else {\n\t\t\t\t/**\n\t\t\t\t * Unknown type passed to Renderer.markToSync.\n\t\t\t\t *\n\t\t\t\t * @error renderer-unknown-type\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'view-renderer-unknown-type: Unknown type passed to Renderer.markToSync.', this );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Renders all buffered changes ({@link #markedAttributes}, {@link #markedChildren} and {@link #markedTexts}) and\n\t * the current view selection (if needed) to the DOM by applying a minimal set of changes to it.\n\t *\n\t * Renderer tries not to break the text composition (e.g. IME) and x-index of the selection,\n\t * so it does as little as it is needed to update the DOM.\n\t *\n\t * Renderer also handles {@link module:engine/view/filler fillers}. Especially, it checks if the inline filler is needed\n\t * at the selection position and adds or removes it. To prevent breaking text composition inline filler will not be\n\t * removed as long as the selection is in the text node which needed it at first.\n\t */\n\trender() {\n\t\tlet inlineFillerPosition;\n\n\t\t// Refresh mappings.\n\t\tfor ( const element of this.markedChildren ) {\n\t\t\tthis._updateChildrenMappings( element );\n\t\t}\n\n\t\t// There was inline filler rendered in the DOM but it's not\n\t\t// at the selection position any more, so we can remove it\n\t\t// (cause even if it's needed, it must be placed in another location).\n\t\tif ( this._inlineFiller && !this._isSelectionInInlineFiller() ) {\n\t\t\tthis._removeInlineFiller();\n\t\t}\n\n\t\t// If we've got the filler, let's try to guess its position in the view.\n\t\tif ( this._inlineFiller ) {\n\t\t\tinlineFillerPosition = this._getInlineFillerPosition();\n\t\t}\n\t\t// Otherwise, if it's needed, create it at the selection position.\n\t\telse if ( this._needsInlineFillerAtSelection() ) {\n\t\t\tinlineFillerPosition = this.selection.getFirstPosition();\n\n\t\t\t// Do not use `markToSync` so it will be added even if the parent is already added.\n\t\t\tthis.markedChildren.add( inlineFillerPosition.parent );\n\t\t}\n\n\t\tfor ( const element of this.markedAttributes ) {\n\t\t\tthis._updateAttrs( element );\n\t\t}\n\n\t\tfor ( const element of this.markedChildren ) {\n\t\t\tthis._updateChildren( element, { inlineFillerPosition } );\n\t\t}\n\n\t\tfor ( const node of this.markedTexts ) {\n\t\t\tif ( !this.markedChildren.has( node.parent ) && this.domConverter.mapViewToDom( node.parent ) ) {\n\t\t\t\tthis._updateText( node, { inlineFillerPosition } );\n\t\t\t}\n\t\t}\n\n\t\t// Check whether the inline filler is required and where it really is in the DOM.\n\t\t// At this point in most cases it will be in the DOM, but there are exceptions.\n\t\t// For example, if the inline filler was deep in the created DOM structure, it will not be created.\n\t\t// Similarly, if it was removed at the beginning of this function and then neither text nor children were updated,\n\t\t// it will not be present.\n\t\t// Fix those and similar scenarios.\n\t\tif ( inlineFillerPosition ) {\n\t\t\tconst fillerDomPosition = this.domConverter.viewPositionToDom( inlineFillerPosition );\n\t\t\tconst domDocument = fillerDomPosition.parent.ownerDocument;\n\n\t\t\tif ( !startsWithFiller( fillerDomPosition.parent ) ) {\n\t\t\t\t// Filler has not been created at filler position. Create it now.\n\t\t\t\tthis._inlineFiller = addInlineFiller( domDocument, fillerDomPosition.parent, fillerDomPosition.offset );\n\t\t\t} else {\n\t\t\t\t// Filler has been found, save it.\n\t\t\t\tthis._inlineFiller = fillerDomPosition.parent;\n\t\t\t}\n\t\t} else {\n\t\t\t// There is no filler needed.\n\t\t\tthis._inlineFiller = null;\n\t\t}\n\n\t\tthis._updateSelection();\n\t\tthis._updateFocus();\n\n\t\tthis.markedTexts.clear();\n\t\tthis.markedAttributes.clear();\n\t\tthis.markedChildren.clear();\n\t}\n\n\t/**\n\t * Updates mappings of view element's children.\n\t *\n\t * Children that were replaced in the view structure by similar elements (same tag name) are treated as 'replaced'.\n\t * This means that their mappings can be updated so the new view elements are mapped to the existing DOM elements.\n\t * Thanks to that these elements do not need to be re-rendered completely.\n\t *\n\t * @private\n\t * @param {module:engine/view/node~Node} viewElement The view element whose children mappings will be updated.\n\t */\n\t_updateChildrenMappings( viewElement ) {\n\t\tconst domElement = this.domConverter.mapViewToDom( viewElement );\n\n\t\tif ( !domElement ) {\n\t\t\t// If there is no `domElement` it means that it was already removed from DOM and there is no need to process it.\n\t\t\treturn;\n\t\t}\n\n\t\tconst actualDomChildren = this.domConverter.mapViewToDom( viewElement ).childNodes;\n\t\tconst expectedDomChildren = Array.from(\n\t\t\tthis.domConverter.viewChildrenToDom( viewElement, domElement.ownerDocument, { withChildren: false } )\n\t\t);\n\t\tconst diff = this._diffNodeLists( actualDomChildren, expectedDomChildren );\n\t\tconst actions = this._findReplaceActions( diff, actualDomChildren, expectedDomChildren );\n\n\t\tif ( actions.indexOf( 'replace' ) !== -1 ) {\n\t\t\tconst counter = { equal: 0, insert: 0, delete: 0 };\n\n\t\t\tfor ( const action of actions ) {\n\t\t\t\tif ( action === 'replace' ) {\n\t\t\t\t\tconst insertIndex = counter.equal + counter.insert;\n\t\t\t\t\tconst deleteIndex = counter.equal + counter.delete;\n\t\t\t\t\tconst viewChild = viewElement.getChild( insertIndex );\n\n\t\t\t\t\t// The 'uiElement' is a special one and its children are not stored in a view (#799),\n\t\t\t\t\t// so we cannot use it with replacing flow (since it uses view children during rendering\n\t\t\t\t\t// which will always result in rendering empty element).\n\t\t\t\t\tif ( viewChild && !viewChild.is( 'uiElement' ) ) {\n\t\t\t\t\t\tthis._updateElementMappings( viewChild, actualDomChildren[ deleteIndex ] );\n\t\t\t\t\t}\n\n\t\t\t\t\tremove( expectedDomChildren[ insertIndex ] );\n\t\t\t\t\tcounter.equal++;\n\t\t\t\t} else {\n\t\t\t\t\tcounter[ action ]++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Updates mappings of a given view element.\n\t *\n\t * @private\n\t * @param {module:engine/view/node~Node} viewElement The view element whose mappings will be updated.\n\t * @param {Node} domElement The DOM element representing the given view element.\n\t */\n\t_updateElementMappings( viewElement, domElement ) {\n\t\t// Remap 'DomConverter' bindings.\n\t\tthis.domConverter.unbindDomElement( domElement );\n\t\tthis.domConverter.bindElements( domElement, viewElement );\n\n\t\t// View element may have children which needs to be updated, but are not marked, mark them to update.\n\t\tthis.markedChildren.add( viewElement );\n\n\t\t// Because we replace new view element mapping with the existing one, the corresponding DOM element\n\t\t// will not be rerendered. The new view element may have different attributes than the previous one.\n\t\t// Since its corresponding DOM element will not be rerendered, new attributes will not be added\n\t\t// to the DOM, so we need to mark it here to make sure its attributes gets updated. See #1427 for more\n\t\t// detailed case study.\n\t\t// Also there are cases where replaced element is removed from the view structure and then has\n\t\t// its attributes changed or removed. In such cases the element will not be present in `markedAttributes`\n\t\t// and also may be the same (`element.isSimilar()`) as the reused element not having its attributes updated.\n\t\t// To prevent such situations we always mark reused element to have its attributes rerenderd (#1560).\n\t\tthis.markedAttributes.add( viewElement );\n\t}\n\n\t/**\n\t * Gets the position of the inline filler based on the current selection.\n\t * Here, we assume that we know that the filler is needed and\n\t * {@link #_isSelectionInInlineFiller is at the selection position}, and, since it is needed,\n\t * it is somewhere at the selection position.\n\t *\n\t * Note: The filler position cannot be restored based on the filler's DOM text node, because\n\t * when this method is called (before rendering), the bindings will often be broken. View-to-DOM\n\t * bindings are only dependable after rendering.\n\t *\n\t * @private\n\t * @returns {module:engine/view/position~Position}\n\t */\n\t_getInlineFillerPosition() {\n\t\tconst firstPos = this.selection.getFirstPosition();\n\n\t\tif ( firstPos.parent.is( 'text' ) ) {\n\t\t\treturn ViewPosition._createBefore( this.selection.getFirstPosition().parent );\n\t\t} else {\n\t\t\treturn firstPos;\n\t\t}\n\t}\n\n\t/**\n\t * Returns `true` if the selection has not left the inline filler's text node.\n\t * If it is `true`, it means that the filler had been added for a reason and the selection did not\n\t * leave the filler's text node. For example, the user can be in the middle of a composition so it should not be touched.\n\t *\n\t * @private\n\t * @returns {Boolean} `true` if the inline filler and selection are in the same place.\n\t */\n\t_isSelectionInInlineFiller() {\n\t\tif ( this.selection.rangeCount != 1 || !this.selection.isCollapsed ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Note, we can't check if selection's position equals position of the\n\t\t// this._inlineFiller node, because of #663. We may not be able to calculate\n\t\t// the filler's position in the view at this stage.\n\t\t// Instead, we check it the other way – whether selection is anchored in\n\t\t// that text node or next to it.\n\n\t\t// Possible options are:\n\t\t// \"FILLER{}\"\n\t\t// \"FILLERadded-text{}\"\n\t\tconst selectionPosition = this.selection.getFirstPosition();\n\t\tconst position = this.domConverter.viewPositionToDom( selectionPosition );\n\n\t\tif ( position && isText( position.parent ) && startsWithFiller( position.parent ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Removes the inline filler.\n\t *\n\t * @private\n\t */\n\t_removeInlineFiller() {\n\t\tconst domFillerNode = this._inlineFiller;\n\n\t\t// Something weird happened and the stored node doesn't contain the filler's text.\n\t\tif ( !startsWithFiller( domFillerNode ) ) {\n\t\t\t/**\n\t\t\t * The inline filler node was lost. Most likely, something overwrote the filler text node\n\t\t\t * in the DOM.\n\t\t\t *\n\t\t\t * @error view-renderer-filler-was-lost\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-renderer-filler-was-lost: The inline filler node was lost.', this );\n\t\t}\n\n\t\tif ( isInlineFiller( domFillerNode ) ) {\n\t\t\tdomFillerNode.parentNode.removeChild( domFillerNode );\n\t\t} else {\n\t\t\tdomFillerNode.data = domFillerNode.data.substr( INLINE_FILLER_LENGTH );\n\t\t}\n\n\t\tthis._inlineFiller = null;\n\t}\n\n\t/**\n\t * Checks if the inline {@link module:engine/view/filler filler} should be added.\n\t *\n\t * @private\n\t * @returns {Boolean} `true` if the inline filler should be added.\n\t */\n\t_needsInlineFillerAtSelection() {\n\t\tif ( this.selection.rangeCount != 1 || !this.selection.isCollapsed ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst selectionPosition = this.selection.getFirstPosition();\n\t\tconst selectionParent = selectionPosition.parent;\n\t\tconst selectionOffset = selectionPosition.offset;\n\n\t\t// If there is no DOM root we do not care about fillers.\n\t\tif ( !this.domConverter.mapViewToDom( selectionParent.root ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( !( selectionParent.is( 'element' ) ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Prevent adding inline filler inside elements with contenteditable=false.\n\t\t// https://github.com/ckeditor/ckeditor5-engine/issues/1170\n\t\tif ( !isEditable( selectionParent ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// We have block filler, we do not need inline one.\n\t\tif ( selectionOffset === selectionParent.getFillerOffset() ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst nodeBefore = selectionPosition.nodeBefore;\n\t\tconst nodeAfter = selectionPosition.nodeAfter;\n\n\t\tif ( nodeBefore instanceof ViewText || nodeAfter instanceof ViewText ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks if text needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t * @param {module:engine/view/text~Text} viewText View text to update.\n\t * @param {Object} options\n\t * @param {module:engine/view/position~Position} options.inlineFillerPosition The position where the inline\n\t * filler should be rendered.\n\t */\n\t_updateText( viewText, options ) {\n\t\tconst domText = this.domConverter.findCorrespondingDomText( viewText );\n\t\tconst newDomText = this.domConverter.viewToDom( viewText, domText.ownerDocument );\n\n\t\tconst actualText = domText.data;\n\t\tlet expectedText = newDomText.data;\n\n\t\tconst filler = options.inlineFillerPosition;\n\n\t\tif ( filler && filler.parent == viewText.parent && filler.offset == viewText.index ) {\n\t\t\texpectedText = INLINE_FILLER + expectedText;\n\t\t}\n\n\t\tif ( actualText != expectedText ) {\n\t\t\tconst actions = fastDiff( actualText, expectedText );\n\n\t\t\tfor ( const action of actions ) {\n\t\t\t\tif ( action.type === 'insert' ) {\n\t\t\t\t\tdomText.insertData( action.index, action.values.join( '' ) );\n\t\t\t\t} else { // 'delete'\n\t\t\t\t\tdomText.deleteData( action.index, action.howMany );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if attribute list needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} viewElement The view element to update.\n\t */\n\t_updateAttrs( viewElement ) {\n\t\tconst domElement = this.domConverter.mapViewToDom( viewElement );\n\n\t\tif ( !domElement ) {\n\t\t\t// If there is no `domElement` it means that 'viewElement' is outdated as its mapping was updated\n\t\t\t// in 'this._updateChildrenMappings()'. There is no need to process it as new view element which\n\t\t\t// replaced old 'viewElement' mapping was also added to 'this.markedAttributes'\n\t\t\t// in 'this._updateChildrenMappings()' so it will be processed separately.\n\t\t\treturn;\n\t\t}\n\n\t\tconst domAttrKeys = Array.from( domElement.attributes ).map( attr => attr.name );\n\t\tconst viewAttrKeys = viewElement.getAttributeKeys();\n\n\t\t// Add or overwrite attributes.\n\t\tfor ( const key of viewAttrKeys ) {\n\t\t\tdomElement.setAttribute( key, viewElement.getAttribute( key ) );\n\t\t}\n\n\t\t// Remove from DOM attributes which do not exists in the view.\n\t\tfor ( const key of domAttrKeys ) {\n\t\t\tif ( !viewElement.hasAttribute( key ) ) {\n\t\t\t\tdomElement.removeAttribute( key );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if elements child list needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} viewElement View element to update.\n\t * @param {Object} options\n\t * @param {module:engine/view/position~Position} options.inlineFillerPosition The position where the inline\n\t * filler should be rendered.\n\t */\n\t_updateChildren( viewElement, options ) {\n\t\tconst domElement = this.domConverter.mapViewToDom( viewElement );\n\n\t\tif ( !domElement ) {\n\t\t\t// If there is no `domElement` it means that it was already removed from DOM.\n\t\t\t// There is no need to process it. It will be processed when re-inserted.\n\t\t\treturn;\n\t\t}\n\n\t\tconst inlineFillerPosition = options.inlineFillerPosition;\n\t\tconst actualDomChildren = this.domConverter.mapViewToDom( viewElement ).childNodes;\n\t\tconst expectedDomChildren = Array.from(\n\t\t\tthis.domConverter.viewChildrenToDom( viewElement, domElement.ownerDocument, { bind: true, inlineFillerPosition } )\n\t\t);\n\n\t\t// Inline filler element has to be created as it is present in the DOM, but not in the view. It is required\n\t\t// during diffing so text nodes could be compared correctly and also during rendering to maintain\n\t\t// proper order and indexes while updating the DOM.\n\t\tif ( inlineFillerPosition && inlineFillerPosition.parent === viewElement ) {\n\t\t\taddInlineFiller( domElement.ownerDocument, expectedDomChildren, inlineFillerPosition.offset );\n\t\t}\n\n\t\tconst diff = this._diffNodeLists( actualDomChildren, expectedDomChildren );\n\n\t\tlet i = 0;\n\t\tconst nodesToUnbind = new Set();\n\n\t\tfor ( const action of diff ) {\n\t\t\tif ( action === 'insert' ) {\n\t\t\t\tinsertAt( domElement, i, expectedDomChildren[ i ] );\n\t\t\t\ti++;\n\t\t\t} else if ( action === 'delete' ) {\n\t\t\t\tnodesToUnbind.add( actualDomChildren[ i ] );\n\t\t\t\tremove( actualDomChildren[ i ] );\n\t\t\t} else { // 'equal'\n\t\t\t\t// Force updating text nodes inside elements which did not change and do not need to be re-rendered (#1125).\n\t\t\t\tthis._markDescendantTextToSync( this.domConverter.domToView( expectedDomChildren[ i ] ) );\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\n\t\t// Unbind removed nodes. When node does not have a parent it means that it was removed from DOM tree during\n\t\t// comparision with the expected DOM. We don't need to check child nodes, because if child node was reinserted,\n\t\t// it was moved to DOM tree out of the removed node.\n\t\tfor ( const node of nodesToUnbind ) {\n\t\t\tif ( !node.parentNode ) {\n\t\t\t\tthis.domConverter.unbindDomElement( node );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Shorthand for diffing two arrays or node lists of DOM nodes.\n\t *\n\t * @private\n\t * @param {Array.<Node>|NodeList} actualDomChildren Actual DOM children\n\t * @param {Array.<Node>|NodeList} expectedDomChildren Expected DOM children.\n\t * @returns {Array.<String>} The list of actions based on the {@link module:utils/diff~diff} function.\n\t */\n\t_diffNodeLists( actualDomChildren, expectedDomChildren ) {\n\t\tactualDomChildren = filterOutFakeSelectionContainer( actualDomChildren, this._fakeSelectionContainer );\n\n\t\treturn diff( actualDomChildren, expectedDomChildren, sameNodes.bind( null, this.domConverter ) );\n\t}\n\n\t/**\n\t * Finds DOM nodes that were replaced with the similar nodes (same tag name) in the view. All nodes are compared\n\t * within one `insert`/`delete` action group, for example:\n\t *\n\t * \t\tActual DOM:\t\t<p><b>Foo</b>Bar<i>Baz</i><b>Bax</b></p>\n\t * \t\tExpected DOM:\t<p>Bar<b>123</b><i>Baz</i><b>456</b></p>\n\t * \t\tInput actions:\t[ insert, insert, delete, delete, equal, insert, delete ]\n\t * \t\tOutput actions:\t[ insert, replace, delete, equal, replace ]\n\t *\n\t * @private\n\t * @param {Array.<String>} actions Actions array which is a result of the {@link module:utils/diff~diff} function.\n\t * @param {Array.<Node>|NodeList} actualDom Actual DOM children\n\t * @param {Array.<Node>} expectedDom Expected DOM children.\n\t * @returns {Array.<String>} Actions array modified with the `replace` actions.\n\t */\n\t_findReplaceActions( actions, actualDom, expectedDom ) {\n\t\t// If there is no both 'insert' and 'delete' actions, no need to check for replaced elements.\n\t\tif ( actions.indexOf( 'insert' ) === -1 || actions.indexOf( 'delete' ) === -1 ) {\n\t\t\treturn actions;\n\t\t}\n\n\t\tlet newActions = [];\n\t\tlet actualSlice = [];\n\t\tlet expectedSlice = [];\n\n\t\tconst counter = { equal: 0, insert: 0, delete: 0 };\n\n\t\tfor ( const action of actions ) {\n\t\t\tif ( action === 'insert' ) {\n\t\t\t\texpectedSlice.push( expectedDom[ counter.equal + counter.insert ] );\n\t\t\t} else if ( action === 'delete' ) {\n\t\t\t\tactualSlice.push( actualDom[ counter.equal + counter.delete ] );\n\t\t\t} else { // equal\n\t\t\t\tnewActions = newActions.concat( diff( actualSlice, expectedSlice, areSimilar ).map( x => x === 'equal' ? 'replace' : x ) );\n\t\t\t\tnewActions.push( 'equal' );\n\t\t\t\t// Reset stored elements on 'equal'.\n\t\t\t\tactualSlice = [];\n\t\t\t\texpectedSlice = [];\n\t\t\t}\n\t\t\tcounter[ action ]++;\n\t\t}\n\n\t\treturn newActions.concat( diff( actualSlice, expectedSlice, areSimilar ).map( x => x === 'equal' ? 'replace' : x ) );\n\t}\n\n\t/**\n\t * Marks text nodes to be synchronized.\n\t *\n\t * If a text node is passed, it will be marked. If an element is passed, all descendant text nodes inside it will be marked.\n\t *\n\t * @private\n\t * @param {module:engine/view/node~Node} viewNode View node to sync.\n\t */\n\t_markDescendantTextToSync( viewNode ) {\n\t\tif ( !viewNode ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( viewNode.is( 'text' ) ) {\n\t\t\tthis.markedTexts.add( viewNode );\n\t\t} else if ( viewNode.is( 'element' ) ) {\n\t\t\tfor ( const child of viewNode.getChildren() ) {\n\t\t\t\tthis._markDescendantTextToSync( child );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the selection needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t */\n\t_updateSelection() {\n\t\t// If there is no selection - remove DOM and fake selections.\n\t\tif ( this.selection.rangeCount === 0 ) {\n\t\t\tthis._removeDomSelection();\n\t\t\tthis._removeFakeSelection();\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst domRoot = this.domConverter.mapViewToDom( this.selection.editableElement );\n\n\t\t// Do nothing if there is no focus, or there is no DOM element corresponding to selection's editable element.\n\t\tif ( !this.isFocused || !domRoot ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Render selection.\n\t\tif ( this.selection.isFake ) {\n\t\t\tthis._updateFakeSelection( domRoot );\n\t\t} else {\n\t\t\tthis._removeFakeSelection();\n\t\t\tthis._updateDomSelection( domRoot );\n\t\t}\n\t}\n\n\t/**\n\t * Updates the fake selection.\n\t *\n\t * @private\n\t * @param {HTMLElement} domRoot A valid DOM root where the fake selection container should be added.\n\t */\n\t_updateFakeSelection( domRoot ) {\n\t\tconst domDocument = domRoot.ownerDocument;\n\n\t\tif ( !this._fakeSelectionContainer ) {\n\t\t\tthis._fakeSelectionContainer = createFakeSelectionContainer( domDocument );\n\t\t}\n\n\t\tconst container = this._fakeSelectionContainer;\n\n\t\t// Bind fake selection container with the current selection *position*.\n\t\tthis.domConverter.bindFakeSelection( container, this.selection );\n\n\t\tif ( !this._fakeSelectionNeedsUpdate( domRoot ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !container.parentElement || container.parentElement != domRoot ) {\n\t\t\tdomRoot.appendChild( container );\n\t\t}\n\n\t\tcontainer.textContent = this.selection.fakeSelectionLabel || '\\u00A0';\n\n\t\tconst domSelection = domDocument.getSelection();\n\t\tconst domRange = domDocument.createRange();\n\n\t\tdomSelection.removeAllRanges();\n\t\tdomRange.selectNodeContents( container );\n\t\tdomSelection.addRange( domRange );\n\t}\n\n\t/**\n\t * Updates the DOM selection.\n\t *\n\t * @private\n\t * @param {HTMLElement} domRoot A valid DOM root where the DOM selection should be rendered.\n\t */\n\t_updateDomSelection( domRoot ) {\n\t\tconst domSelection = domRoot.ownerDocument.defaultView.getSelection();\n\n\t\t// Let's check whether DOM selection needs updating at all.\n\t\tif ( !this._domSelectionNeedsUpdate( domSelection ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Multi-range selection is not available in most browsers, and, at least in Chrome, trying to\n\t\t// set such selection, that is not continuous, throws an error. Because of that, we will just use anchor\n\t\t// and focus of view selection.\n\t\t// Since we are not supporting multi-range selection, we also do not need to check if proper editable is\n\t\t// selected. If there is any editable selected, it is okay (editable is taken from selection anchor).\n\t\tconst anchor = this.domConverter.viewPositionToDom( this.selection.anchor );\n\t\tconst focus = this.domConverter.viewPositionToDom( this.selection.focus );\n\n\t\t// Focus the new editing host.\n\t\t// Otherwise, FF may throw an error (https://github.com/ckeditor/ckeditor5/issues/721).\n\t\tdomRoot.focus();\n\n\t\tdomSelection.collapse( anchor.parent, anchor.offset );\n\t\tdomSelection.extend( focus.parent, focus.offset );\n\n\t\t// Firefox–specific hack (https://github.com/ckeditor/ckeditor5-engine/issues/1439).\n\t\tif ( env.isGecko ) {\n\t\t\tfixGeckoSelectionAfterBr( focus, domSelection );\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether a given DOM selection needs to be updated.\n\t *\n\t * @private\n\t * @param {Selection} domSelection The DOM selection to check.\n\t * @returns {Boolean}\n\t */\n\t_domSelectionNeedsUpdate( domSelection ) {\n\t\tif ( !this.domConverter.isDomSelectionCorrect( domSelection ) ) {\n\t\t\t// Current DOM selection is in incorrect position. We need to update it.\n\t\t\treturn true;\n\t\t}\n\n\t\tconst oldViewSelection = domSelection && this.domConverter.domSelectionToView( domSelection );\n\n\t\tif ( oldViewSelection && this.selection.isEqual( oldViewSelection ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If selection is not collapsed, it does not need to be updated if it is similar.\n\t\tif ( !this.selection.isCollapsed && this.selection.isSimilar( oldViewSelection ) ) {\n\t\t\t// Selection did not changed and is correct, do not update.\n\t\t\treturn false;\n\t\t}\n\n\t\t// Selections are not similar.\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks whether the fake selection needs to be updated.\n\t *\n\t * @private\n\t * @param {HTMLElement} domRoot A valid DOM root where a new fake selection container should be added.\n\t * @returns {Boolean}\n\t */\n\t_fakeSelectionNeedsUpdate( domRoot ) {\n\t\tconst container = this._fakeSelectionContainer;\n\t\tconst domSelection = domRoot.ownerDocument.getSelection();\n\n\t\t// Fake selection needs to be updated if there's no fake selection container, or the container currently sits\n\t\t// in a different root.\n\t\tif ( !container || container.parentElement !== domRoot ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Make sure that the selection actually is within the fake selection.\n\t\tif ( domSelection.anchorNode !== container && !container.contains( domSelection.anchorNode ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn container.textContent !== this.selection.fakeSelectionLabel;\n\t}\n\n\t/**\n\t * Removes the DOM selection.\n\t *\n\t * @private\n\t */\n\t_removeDomSelection() {\n\t\tfor ( const doc of this.domDocuments ) {\n\t\t\tconst domSelection = doc.getSelection();\n\n\t\t\tif ( domSelection.rangeCount ) {\n\t\t\t\tconst activeDomElement = doc.activeElement;\n\t\t\t\tconst viewElement = this.domConverter.mapDomToView( activeDomElement );\n\n\t\t\t\tif ( activeDomElement && viewElement ) {\n\t\t\t\t\tdoc.getSelection().removeAllRanges();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Removes the fake selection.\n\t *\n\t * @private\n\t */\n\t_removeFakeSelection() {\n\t\tconst container = this._fakeSelectionContainer;\n\n\t\tif ( container ) {\n\t\t\tcontainer.remove();\n\t\t}\n\t}\n\n\t/**\n\t * Checks if focus needs to be updated and possibly updates it.\n\t *\n\t * @private\n\t */\n\t_updateFocus() {\n\t\tif ( this.isFocused ) {\n\t\t\tconst editable = this.selection.editableElement;\n\n\t\t\tif ( editable ) {\n\t\t\t\tthis.domConverter.focus( editable );\n\t\t\t}\n\t\t}\n\t}\n}\n\nmix( Renderer, ObservableMixin );\n\n// Checks if provided element is editable.\n//\n// @private\n// @param {module:engine/view/element~Element} element\n// @returns {Boolean}\nfunction isEditable( element ) {\n\tif ( element.getAttribute( 'contenteditable' ) == 'false' ) {\n\t\treturn false;\n\t}\n\n\tconst parent = element.findAncestor( element => element.hasAttribute( 'contenteditable' ) );\n\n\treturn !parent || parent.getAttribute( 'contenteditable' ) == 'true';\n}\n\n// Adds inline filler at a given position.\n//\n// The position can be given as an array of DOM nodes and an offset in that array,\n// or a DOM parent element and an offset in that element.\n//\n// @private\n// @param {Document} domDocument\n// @param {Element|Array.<Node>} domParentOrArray\n// @param {Number} offset\n// @returns {Text} The DOM text node that contains an inline filler.\nfunction addInlineFiller( domDocument, domParentOrArray, offset ) {\n\tconst childNodes = domParentOrArray instanceof Array ? domParentOrArray : domParentOrArray.childNodes;\n\tconst nodeAfterFiller = childNodes[ offset ];\n\n\tif ( isText( nodeAfterFiller ) ) {\n\t\tnodeAfterFiller.data = INLINE_FILLER + nodeAfterFiller.data;\n\n\t\treturn nodeAfterFiller;\n\t} else {\n\t\tconst fillerNode = domDocument.createTextNode( INLINE_FILLER );\n\n\t\tif ( Array.isArray( domParentOrArray ) ) {\n\t\t\tchildNodes.splice( offset, 0, fillerNode );\n\t\t} else {\n\t\t\tinsertAt( domParentOrArray, offset, fillerNode );\n\t\t}\n\n\t\treturn fillerNode;\n\t}\n}\n\n// Whether two DOM nodes should be considered as similar.\n// Nodes are considered similar if they have the same tag name.\n//\n// @private\n// @param {Node} node1\n// @param {Node} node2\n// @returns {Boolean}\nfunction areSimilar( node1, node2 ) {\n\treturn isNode( node1 ) && isNode( node2 ) &&\n\t\t!isText( node1 ) && !isText( node2 ) &&\n\t\tnode1.tagName.toLowerCase() === node2.tagName.toLowerCase();\n}\n\n// Whether two dom nodes should be considered as the same.\n// Two nodes which are considered the same are:\n//\n//\t\t* Text nodes with the same text.\n//\t\t* Element nodes represented by the same object.\n//\t\t* Two block filler elements.\n//\n// @private\n// @param {String} blockFillerMode Block filler mode, see {@link module:engine/view/domconverter~DomConverter#blockFillerMode}.\n// @param {Node} node1\n// @param {Node} node2\n// @returns {Boolean}\nfunction sameNodes( domConverter, actualDomChild, expectedDomChild ) {\n\t// Elements.\n\tif ( actualDomChild === expectedDomChild ) {\n\t\treturn true;\n\t}\n\t// Texts.\n\telse if ( isText( actualDomChild ) && isText( expectedDomChild ) ) {\n\t\treturn actualDomChild.data === expectedDomChild.data;\n\t}\n\t// Block fillers.\n\telse if ( domConverter.isBlockFiller( actualDomChild ) &&\n\t\tdomConverter.isBlockFiller( expectedDomChild ) ) {\n\t\treturn true;\n\t}\n\n\t// Not matching types.\n\treturn false;\n}\n\n// The following is a Firefox–specific hack (https://github.com/ckeditor/ckeditor5-engine/issues/1439).\n// When the native DOM selection is at the end of the block and preceded by <br /> e.g.\n//\n//\t\t<p>foo<br/>[]</p>\n//\n// which happens a lot when using the soft line break, the browser fails to (visually) move the\n// caret to the new line. A quick fix is as simple as force–refreshing the selection with the same range.\nfunction fixGeckoSelectionAfterBr( focus, domSelection ) {\n\tconst parent = focus.parent;\n\n\t// This fix works only when the focus point is at the very end of an element.\n\t// There is no point in running it in cases unrelated to the browser bug.\n\tif ( parent.nodeType != Node.ELEMENT_NODE || focus.offset != parent.childNodes.length - 1 ) {\n\t\treturn;\n\t}\n\n\tconst childAtOffset = parent.childNodes[ focus.offset ];\n\n\t// To stay on the safe side, the fix being as specific as possible, it targets only the\n\t// selection which is at the very end of the element and preceded by <br />.\n\tif ( childAtOffset && childAtOffset.tagName == 'BR' ) {\n\t\tdomSelection.addRange( domSelection.getRangeAt( 0 ) );\n\t}\n}\n\nfunction filterOutFakeSelectionContainer( domChildList, fakeSelectionContainer ) {\n\tconst childList = Array.from( domChildList );\n\n\tif ( childList.length == 0 || !fakeSelectionContainer ) {\n\t\treturn childList;\n\t}\n\n\tconst last = childList[ childList.length - 1 ];\n\n\tif ( last == fakeSelectionContainer ) {\n\t\tchildList.pop();\n\t}\n\n\treturn childList;\n}\n\n// Creates a fake selection container for a given document.\n//\n// @private\n// @param {Document} domDocument\n// @returns {HTMLElement}\nfunction createFakeSelectionContainer( domDocument ) {\n\tconst container = domDocument.createElement( 'div' );\n\n\tObject.assign( container.style, {\n\t\tposition: 'fixed',\n\t\ttop: 0,\n\t\tleft: '-9999px',\n\t\t// See https://github.com/ckeditor/ckeditor5/issues/752.\n\t\twidth: '42px'\n\t} );\n\n\t// Fill it with a text node so we can update it later.\n\tcontainer.textContent = '\\u00A0';\n\n\treturn container;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* globals window, document */\n\n/**\n * @module utils/dom/global\n */\n\n/**\n * A helper (module) giving an access to the global DOM objects such as `window` and\n * `document`. Accessing these objects using this helper allows easy and bulletproof\n * testing, i.e. stubbing native properties:\n *\n *\t\timport global from 'ckeditor5/utils/dom/global.js';\n *\n *\t\t// This stub will work for any code using global module.\n *\t\ttestUtils.sinon.stub( global, 'window', {\n *\t\t\tinnerWidth: 10000\n *\t\t} );\n *\n *\t\tconsole.log( global.window.innerWidth );\n */\nexport default { window, document };\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/indexof\n */\n\n/**\n * Returns index of the node in the parent element.\n *\n * @param {Node} node Node which index is tested.\n * @returns {Number} Index of the node in the parent element. Returns 0 if node has no parent.\n */\nexport default function indexOf( node ) {\n\tlet index = 0;\n\n\twhile ( node.previousSibling ) {\n\t\tnode = node.previousSibling;\n\t\tindex++;\n\t}\n\n\treturn index;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* globals Node */\n\n/**\n * @module utils/dom/getancestors\n */\n\n/**\n * Returns all ancestors of given DOM node, starting from the top-most (root). Includes the given node itself. If the\n * node is a part of `DocumentFragment` that `DocumentFragment` will be returned. In contrary, if the node is\n * appended to a `Document`, that `Document` will not be returned (algorithms operating on DOM tree care for `Document#documentElement`\n * at most, which will be returned).\n *\n * @param {Node} node DOM node.\n * @returns {Array.<Node|DocumentFragment>} Array of given `node` parents.\n */\nexport default function getAncestors( node ) {\n\tconst nodes = [];\n\n\t// We are interested in `Node`s `DocumentFragment`s only.\n\twhile ( node && node.nodeType != Node.DOCUMENT_NODE ) {\n\t\tnodes.unshift( node );\n\t\tnode = node.parentNode;\n\t}\n\n\treturn nodes;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/domconverter\n */\n\n/* globals document, Node, NodeFilter, Text */\n\nimport ViewText from './text';\nimport ViewElement from './element';\nimport ViewPosition from './position';\nimport ViewRange from './range';\nimport ViewSelection from './selection';\nimport ViewDocumentFragment from './documentfragment';\nimport ViewTreeWalker from './treewalker';\nimport { BR_FILLER, getDataWithoutFiller, INLINE_FILLER_LENGTH, isInlineFiller, NBSP_FILLER, startsWithFiller } from './filler';\n\nimport global from '@ckeditor/ckeditor5-utils/src/dom/global';\nimport indexOf from '@ckeditor/ckeditor5-utils/src/dom/indexof';\nimport getAncestors from '@ckeditor/ckeditor5-utils/src/dom/getancestors';\nimport getCommonAncestor from '@ckeditor/ckeditor5-utils/src/dom/getcommonancestor';\nimport isText from '@ckeditor/ckeditor5-utils/src/dom/istext';\nimport { isElement } from 'lodash-es';\n\n// eslint-disable-next-line new-cap\nconst BR_FILLER_REF = BR_FILLER( document );\n\n/**\n * DomConverter is a set of tools to do transformations between DOM nodes and view nodes. It also handles\n * {@link module:engine/view/domconverter~DomConverter#bindElements binding} these nodes.\n *\n * The instance of DOMConverter is available in {@link module:engine/view/view~View#domConverter `editor.editing.view.domConverter`}.\n *\n * DomConverter does not check which nodes should be rendered (use {@link module:engine/view/renderer~Renderer}), does not keep a\n * state of a tree nor keeps synchronization between tree view and DOM tree (use {@link module:engine/view/document~Document}).\n *\n * DomConverter keeps DOM elements to View element bindings, so when the converter will be destroyed, the binding will\n * be lost. Two converters will keep separate binding maps, so one tree view can be bound with two DOM trees.\n */\nexport default class DomConverter {\n\t/**\n\t * Creates DOM converter.\n\t *\n\t * @param {Object} options Object with configuration options.\n\t * @param {module:engine/view/filler~BlockFillerMode} [options.blockFillerMode='br'] The type of the block filler to use.\n\t */\n\tconstructor( options = {} ) {\n\t\t/**\n\t\t * The mode of a block filler used by DOM converter.\n\t\t *\n\t\t * @readonly\n\t\t * @member {'br'|'nbsp'} module:engine/view/domconverter~DomConverter#blockFillerMode\n\t\t */\n\t\tthis.blockFillerMode = options.blockFillerMode || 'br';\n\n\t\t/**\n\t\t * Elements which are considered pre-formatted elements.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Array.<String>} module:engine/view/domconverter~DomConverter#preElements\n\t\t */\n\t\tthis.preElements = [ 'pre' ];\n\n\t\t/**\n\t\t * Elements which are considered block elements (and hence should be filled with a\n\t\t * {@link #isBlockFiller block filler}).\n\t\t *\n\t\t * Whether an element is considered a block element also affects handling of trailing whitespaces.\n\t\t *\n\t\t * You can extend this array if you introduce support for block elements which are not yet recognized here.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Array.<String>} module:engine/view/domconverter~DomConverter#blockElements\n\t\t */\n\t\tthis.blockElements = [ 'p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'dd', 'dt', 'figcaption' ];\n\n\t\t/**\n\t\t * Block {@link module:engine/view/filler filler} creator, which is used to create all block fillers during the\n\t\t * view to DOM conversion and to recognize block fillers during the DOM to view conversion.\n\t\t *\n\t\t * @readonly\n\t\t * @private\n\t\t * @member {Function} module:engine/view/domconverter~DomConverter#_blockFiller\n\t\t */\n\t\tthis._blockFiller = this.blockFillerMode == 'br' ? BR_FILLER : NBSP_FILLER;\n\n\t\t/**\n\t\t * DOM to View mapping.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakMap} module:engine/view/domconverter~DomConverter#_domToViewMapping\n\t\t */\n\t\tthis._domToViewMapping = new WeakMap();\n\n\t\t/**\n\t\t * View to DOM mapping.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakMap} module:engine/view/domconverter~DomConverter#_viewToDomMapping\n\t\t */\n\t\tthis._viewToDomMapping = new WeakMap();\n\n\t\t/**\n\t\t * Holds mapping between fake selection containers and corresponding view selections.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakMap} module:engine/view/domconverter~DomConverter#_fakeSelectionMapping\n\t\t */\n\t\tthis._fakeSelectionMapping = new WeakMap();\n\t}\n\n\t/**\n\t * Binds given DOM element that represents fake selection to a **position** of a\n\t * {@link module:engine/view/documentselection~DocumentSelection document selection}.\n\t * Document selection copy is stored and can be retrieved by\n\t * {@link module:engine/view/domconverter~DomConverter#fakeSelectionToView} method.\n\t *\n\t * @param {HTMLElement} domElement\n\t * @param {module:engine/view/documentselection~DocumentSelection} viewDocumentSelection\n\t */\n\tbindFakeSelection( domElement, viewDocumentSelection ) {\n\t\tthis._fakeSelectionMapping.set( domElement, new ViewSelection( viewDocumentSelection ) );\n\t}\n\n\t/**\n\t * Returns {@link module:engine/view/selection~Selection view selection} instance corresponding to\n\t * given DOM element that represents fake selection. Returns `undefined` if binding to given DOM element does not exists.\n\t *\n\t * @param {HTMLElement} domElement\n\t * @returns {module:engine/view/selection~Selection|undefined}\n\t */\n\tfakeSelectionToView( domElement ) {\n\t\treturn this._fakeSelectionMapping.get( domElement );\n\t}\n\n\t/**\n\t * Binds DOM and View elements, so it will be possible to get corresponding elements using\n\t * {@link module:engine/view/domconverter~DomConverter#mapDomToView} and\n\t * {@link module:engine/view/domconverter~DomConverter#mapViewToDom}.\n\t *\n\t * @param {HTMLElement} domElement DOM element to bind.\n\t * @param {module:engine/view/element~Element} viewElement View element to bind.\n\t */\n\tbindElements( domElement, viewElement ) {\n\t\tthis._domToViewMapping.set( domElement, viewElement );\n\t\tthis._viewToDomMapping.set( viewElement, domElement );\n\t}\n\n\t/**\n\t * Unbinds given `domElement` from the view element it was bound to. Unbinding is deep, meaning that all children of\n\t * `domElement` will be unbound too.\n\t *\n\t * @param {HTMLElement} domElement DOM element to unbind.\n\t */\n\tunbindDomElement( domElement ) {\n\t\tconst viewElement = this._domToViewMapping.get( domElement );\n\n\t\tif ( viewElement ) {\n\t\t\tthis._domToViewMapping.delete( domElement );\n\t\t\tthis._viewToDomMapping.delete( viewElement );\n\n\t\t\t// Use Array.from because of MS Edge (#923).\n\t\t\tfor ( const child of Array.from( domElement.childNodes ) ) {\n\t\t\t\tthis.unbindDomElement( child );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Binds DOM and View document fragments, so it will be possible to get corresponding document fragments using\n\t * {@link module:engine/view/domconverter~DomConverter#mapDomToView} and\n\t * {@link module:engine/view/domconverter~DomConverter#mapViewToDom}.\n\t *\n\t * @param {DocumentFragment} domFragment DOM document fragment to bind.\n\t * @param {module:engine/view/documentfragment~DocumentFragment} viewFragment View document fragment to bind.\n\t */\n\tbindDocumentFragments( domFragment, viewFragment ) {\n\t\tthis._domToViewMapping.set( domFragment, viewFragment );\n\t\tthis._viewToDomMapping.set( viewFragment, domFragment );\n\t}\n\n\t/**\n\t * Converts view to DOM. For all text nodes, not bound elements and document fragments new items will\n\t * be created. For bound elements and document fragments function will return corresponding items.\n\t *\n\t * @param {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment} viewNode\n\t * View node or document fragment to transform.\n\t * @param {Document} domDocument Document which will be used to create DOM nodes.\n\t * @param {Object} [options] Conversion options.\n\t * @param {Boolean} [options.bind=false] Determines whether new elements will be bound.\n\t * @param {Boolean} [options.withChildren=true] If `true`, node's and document fragment's children will be converted too.\n\t * @returns {Node|DocumentFragment} Converted node or DocumentFragment.\n\t */\n\tviewToDom( viewNode, domDocument, options = {} ) {\n\t\tif ( viewNode.is( 'text' ) ) {\n\t\t\tconst textData = this._processDataFromViewText( viewNode );\n\n\t\t\treturn domDocument.createTextNode( textData );\n\t\t} else {\n\t\t\tif ( this.mapViewToDom( viewNode ) ) {\n\t\t\t\treturn this.mapViewToDom( viewNode );\n\t\t\t}\n\n\t\t\tlet domElement;\n\n\t\t\tif ( viewNode.is( 'documentFragment' ) ) {\n\t\t\t\t// Create DOM document fragment.\n\t\t\t\tdomElement = domDocument.createDocumentFragment();\n\n\t\t\t\tif ( options.bind ) {\n\t\t\t\t\tthis.bindDocumentFragments( domElement, viewNode );\n\t\t\t\t}\n\t\t\t} else if ( viewNode.is( 'uiElement' ) ) {\n\t\t\t\t// UIElement has its own render() method (see #799).\n\t\t\t\tdomElement = viewNode.render( domDocument );\n\n\t\t\t\tif ( options.bind ) {\n\t\t\t\t\tthis.bindElements( domElement, viewNode );\n\t\t\t\t}\n\n\t\t\t\treturn domElement;\n\t\t\t} else {\n\t\t\t\t// Create DOM element.\n\t\t\t\tif ( viewNode.hasAttribute( 'xmlns' ) ) {\n\t\t\t\t\tdomElement = domDocument.createElementNS( viewNode.getAttribute( 'xmlns' ), viewNode.name );\n\t\t\t\t} else {\n\t\t\t\t\tdomElement = domDocument.createElement( viewNode.name );\n\t\t\t\t}\n\n\t\t\t\tif ( options.bind ) {\n\t\t\t\t\tthis.bindElements( domElement, viewNode );\n\t\t\t\t}\n\n\t\t\t\t// Copy element's attributes.\n\t\t\t\tfor ( const key of viewNode.getAttributeKeys() ) {\n\t\t\t\t\tdomElement.setAttribute( key, viewNode.getAttribute( key ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( options.withChildren || options.withChildren === undefined ) {\n\t\t\t\tfor ( const child of this.viewChildrenToDom( viewNode, domDocument, options ) ) {\n\t\t\t\t\tdomElement.appendChild( child );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn domElement;\n\t\t}\n\t}\n\n\t/**\n\t * Converts children of the view element to DOM using the\n\t * {@link module:engine/view/domconverter~DomConverter#viewToDom} method.\n\t * Additionally, this method adds block {@link module:engine/view/filler filler} to the list of children, if needed.\n\t *\n\t * @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} viewElement Parent view element.\n\t * @param {Document} domDocument Document which will be used to create DOM nodes.\n\t * @param {Object} options See {@link module:engine/view/domconverter~DomConverter#viewToDom} options parameter.\n\t * @returns {Iterable.<Node>} DOM nodes.\n\t */\n\t* viewChildrenToDom( viewElement, domDocument, options = {} ) {\n\t\tconst fillerPositionOffset = viewElement.getFillerOffset && viewElement.getFillerOffset();\n\t\tlet offset = 0;\n\n\t\tfor ( const childView of viewElement.getChildren() ) {\n\t\t\tif ( fillerPositionOffset === offset ) {\n\t\t\t\tyield this._blockFiller( domDocument );\n\t\t\t}\n\n\t\t\tyield this.viewToDom( childView, domDocument, options );\n\n\t\t\toffset++;\n\t\t}\n\n\t\tif ( fillerPositionOffset === offset ) {\n\t\t\tyield this._blockFiller( domDocument );\n\t\t}\n\t}\n\n\t/**\n\t * Converts view {@link module:engine/view/range~Range} to DOM range.\n\t * Inline and block {@link module:engine/view/filler fillers} are handled during the conversion.\n\t *\n\t * @param {module:engine/view/range~Range} viewRange View range.\n\t * @returns {Range} DOM range.\n\t */\n\tviewRangeToDom( viewRange ) {\n\t\tconst domStart = this.viewPositionToDom( viewRange.start );\n\t\tconst domEnd = this.viewPositionToDom( viewRange.end );\n\n\t\tconst domRange = document.createRange();\n\t\tdomRange.setStart( domStart.parent, domStart.offset );\n\t\tdomRange.setEnd( domEnd.parent, domEnd.offset );\n\n\t\treturn domRange;\n\t}\n\n\t/**\n\t * Converts view {@link module:engine/view/position~Position} to DOM parent and offset.\n\t *\n\t * Inline and block {@link module:engine/view/filler fillers} are handled during the conversion.\n\t * If the converted position is directly before inline filler it is moved inside the filler.\n\t *\n\t * @param {module:engine/view/position~Position} viewPosition View position.\n\t * @returns {Object|null} position DOM position or `null` if view position could not be converted to DOM.\n\t * @returns {Node} position.parent DOM position parent.\n\t * @returns {Number} position.offset DOM position offset.\n\t */\n\tviewPositionToDom( viewPosition ) {\n\t\tconst viewParent = viewPosition.parent;\n\n\t\tif ( viewParent.is( 'text' ) ) {\n\t\t\tconst domParent = this.findCorrespondingDomText( viewParent );\n\n\t\t\tif ( !domParent ) {\n\t\t\t\t// Position is in a view text node that has not been rendered to DOM yet.\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tlet offset = viewPosition.offset;\n\n\t\t\tif ( startsWithFiller( domParent ) ) {\n\t\t\t\toffset += INLINE_FILLER_LENGTH;\n\t\t\t}\n\n\t\t\treturn { parent: domParent, offset };\n\t\t} else {\n\t\t\t// viewParent is instance of ViewElement.\n\t\t\tlet domParent, domBefore, domAfter;\n\n\t\t\tif ( viewPosition.offset === 0 ) {\n\t\t\t\tdomParent = this.mapViewToDom( viewParent );\n\n\t\t\t\tif ( !domParent ) {\n\t\t\t\t\t// Position is in a view element that has not been rendered to DOM yet.\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tdomAfter = domParent.childNodes[ 0 ];\n\t\t\t} else {\n\t\t\t\tconst nodeBefore = viewPosition.nodeBefore;\n\n\t\t\t\tdomBefore = nodeBefore.is( 'text' ) ?\n\t\t\t\t\tthis.findCorrespondingDomText( nodeBefore ) :\n\t\t\t\t\tthis.mapViewToDom( viewPosition.nodeBefore );\n\n\t\t\t\tif ( !domBefore ) {\n\t\t\t\t\t// Position is after a view element that has not been rendered to DOM yet.\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tdomParent = domBefore.parentNode;\n\t\t\t\tdomAfter = domBefore.nextSibling;\n\t\t\t}\n\n\t\t\t// If there is an inline filler at position return position inside the filler. We should never return\n\t\t\t// the position before the inline filler.\n\t\t\tif ( isText( domAfter ) && startsWithFiller( domAfter ) ) {\n\t\t\t\treturn { parent: domAfter, offset: INLINE_FILLER_LENGTH };\n\t\t\t}\n\n\t\t\tconst offset = domBefore ? indexOf( domBefore ) + 1 : 0;\n\n\t\t\treturn { parent: domParent, offset };\n\t\t}\n\t}\n\n\t/**\n\t * Converts DOM to view. For all text nodes, not bound elements and document fragments new items will\n\t * be created. For bound elements and document fragments function will return corresponding items. For\n\t * {@link module:engine/view/filler fillers} `null` will be returned.\n\t * For all DOM elements rendered by {@link module:engine/view/uielement~UIElement} that UIElement will be returned.\n\t *\n\t * @param {Node|DocumentFragment} domNode DOM node or document fragment to transform.\n\t * @param {Object} [options] Conversion options.\n\t * @param {Boolean} [options.bind=false] Determines whether new elements will be bound.\n\t * @param {Boolean} [options.withChildren=true] If `true`, node's and document fragment's children will be converted too.\n\t * @param {Boolean} [options.keepOriginalCase=false] If `false`, node's tag name will be converter to lower case.\n\t * @returns {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment|null} Converted node or document fragment\n\t * or `null` if DOM node is a {@link module:engine/view/filler filler} or the given node is an empty text node.\n\t */\n\tdomToView( domNode, options = {} ) {\n\t\tif ( this.isBlockFiller( domNode, this.blockFillerMode ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// When node is inside UIElement return that UIElement as it's view representation.\n\t\tconst uiElement = this.getParentUIElement( domNode, this._domToViewMapping );\n\n\t\tif ( uiElement ) {\n\t\t\treturn uiElement;\n\t\t}\n\n\t\tif ( isText( domNode ) ) {\n\t\t\tif ( isInlineFiller( domNode ) ) {\n\t\t\t\treturn null;\n\t\t\t} else {\n\t\t\t\tconst textData = this._processDataFromDomText( domNode );\n\n\t\t\t\treturn textData === '' ? null : new ViewText( textData );\n\t\t\t}\n\t\t} else if ( this.isComment( domNode ) ) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\tif ( this.mapDomToView( domNode ) ) {\n\t\t\t\treturn this.mapDomToView( domNode );\n\t\t\t}\n\n\t\t\tlet viewElement;\n\n\t\t\tif ( this.isDocumentFragment( domNode ) ) {\n\t\t\t\t// Create view document fragment.\n\t\t\t\tviewElement = new ViewDocumentFragment();\n\n\t\t\t\tif ( options.bind ) {\n\t\t\t\t\tthis.bindDocumentFragments( domNode, viewElement );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Create view element.\n\t\t\t\tconst viewName = options.keepOriginalCase ? domNode.tagName : domNode.tagName.toLowerCase();\n\t\t\t\tviewElement = new ViewElement( viewName );\n\n\t\t\t\tif ( options.bind ) {\n\t\t\t\t\tthis.bindElements( domNode, viewElement );\n\t\t\t\t}\n\n\t\t\t\t// Copy element's attributes.\n\t\t\t\tconst attrs = domNode.attributes;\n\n\t\t\t\tfor ( let i = attrs.length - 1; i >= 0; i-- ) {\n\t\t\t\t\tviewElement._setAttribute( attrs[ i ].name, attrs[ i ].value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( options.withChildren || options.withChildren === undefined ) {\n\t\t\t\tfor ( const child of this.domChildrenToView( domNode, options ) ) {\n\t\t\t\t\tviewElement._appendChild( child );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn viewElement;\n\t\t}\n\t}\n\n\t/**\n\t * Converts children of the DOM element to view nodes using\n\t * the {@link module:engine/view/domconverter~DomConverter#domToView} method.\n\t * Additionally this method omits block {@link module:engine/view/filler filler}, if it exists in the DOM parent.\n\t *\n\t * @param {HTMLElement} domElement Parent DOM element.\n\t * @param {Object} options See {@link module:engine/view/domconverter~DomConverter#domToView} options parameter.\n\t * @returns {Iterable.<module:engine/view/node~Node>} View nodes.\n\t */\n\t* domChildrenToView( domElement, options = {} ) {\n\t\tfor ( let i = 0; i < domElement.childNodes.length; i++ ) {\n\t\t\tconst domChild = domElement.childNodes[ i ];\n\t\t\tconst viewChild = this.domToView( domChild, options );\n\n\t\t\tif ( viewChild !== null ) {\n\t\t\t\tyield viewChild;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Converts DOM selection to view {@link module:engine/view/selection~Selection}.\n\t * Ranges which cannot be converted will be omitted.\n\t *\n\t * @param {Selection} domSelection DOM selection.\n\t * @returns {module:engine/view/selection~Selection} View selection.\n\t */\n\tdomSelectionToView( domSelection ) {\n\t\t// DOM selection might be placed in fake selection container.\n\t\t// If container contains fake selection - return corresponding view selection.\n\t\tif ( domSelection.rangeCount === 1 ) {\n\t\t\tlet container = domSelection.getRangeAt( 0 ).startContainer;\n\n\t\t\t// The DOM selection might be moved to the text node inside the fake selection container.\n\t\t\tif ( isText( container ) ) {\n\t\t\t\tcontainer = container.parentNode;\n\t\t\t}\n\n\t\t\tconst viewSelection = this.fakeSelectionToView( container );\n\n\t\t\tif ( viewSelection ) {\n\t\t\t\treturn viewSelection;\n\t\t\t}\n\t\t}\n\n\t\tconst isBackward = this.isDomSelectionBackward( domSelection );\n\n\t\tconst viewRanges = [];\n\n\t\tfor ( let i = 0; i < domSelection.rangeCount; i++ ) {\n\t\t\t// DOM Range have correct start and end, no matter what is the DOM Selection direction. So we don't have to fix anything.\n\t\t\tconst domRange = domSelection.getRangeAt( i );\n\t\t\tconst viewRange = this.domRangeToView( domRange );\n\n\t\t\tif ( viewRange ) {\n\t\t\t\tviewRanges.push( viewRange );\n\t\t\t}\n\t\t}\n\n\t\treturn new ViewSelection( viewRanges, { backward: isBackward } );\n\t}\n\n\t/**\n\t * Converts DOM Range to view {@link module:engine/view/range~Range}.\n\t * If the start or end position can not be converted `null` is returned.\n\t *\n\t * @param {Range} domRange DOM range.\n\t * @returns {module:engine/view/range~Range|null} View range.\n\t */\n\tdomRangeToView( domRange ) {\n\t\tconst viewStart = this.domPositionToView( domRange.startContainer, domRange.startOffset );\n\t\tconst viewEnd = this.domPositionToView( domRange.endContainer, domRange.endOffset );\n\n\t\tif ( viewStart && viewEnd ) {\n\t\t\treturn new ViewRange( viewStart, viewEnd );\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Converts DOM parent and offset to view {@link module:engine/view/position~Position}.\n\t *\n\t * If the position is inside a {@link module:engine/view/filler filler} which has no corresponding view node,\n\t * position of the filler will be converted and returned.\n\t *\n\t * If the position is inside DOM element rendered by {@link module:engine/view/uielement~UIElement}\n\t * that position will be converted to view position before that UIElement.\n\t *\n\t * If structures are too different and it is not possible to find corresponding position then `null` will be returned.\n\t *\n\t * @param {Node} domParent DOM position parent.\n\t * @param {Number} domOffset DOM position offset.\n\t * @returns {module:engine/view/position~Position} viewPosition View position.\n\t */\n\tdomPositionToView( domParent, domOffset ) {\n\t\tif ( this.isBlockFiller( domParent, this.blockFillerMode ) ) {\n\t\t\treturn this.domPositionToView( domParent.parentNode, indexOf( domParent ) );\n\t\t}\n\n\t\t// If position is somewhere inside UIElement - return position before that element.\n\t\tconst viewElement = this.mapDomToView( domParent );\n\n\t\tif ( viewElement && viewElement.is( 'uiElement' ) ) {\n\t\t\treturn ViewPosition._createBefore( viewElement );\n\t\t}\n\n\t\tif ( isText( domParent ) ) {\n\t\t\tif ( isInlineFiller( domParent ) ) {\n\t\t\t\treturn this.domPositionToView( domParent.parentNode, indexOf( domParent ) );\n\t\t\t}\n\n\t\t\tconst viewParent = this.findCorrespondingViewText( domParent );\n\t\t\tlet offset = domOffset;\n\n\t\t\tif ( !viewParent ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( startsWithFiller( domParent ) ) {\n\t\t\t\toffset -= INLINE_FILLER_LENGTH;\n\t\t\t\toffset = offset < 0 ? 0 : offset;\n\t\t\t}\n\n\t\t\treturn new ViewPosition( viewParent, offset );\n\t\t}\n\t\t// domParent instanceof HTMLElement.\n\t\telse {\n\t\t\tif ( domOffset === 0 ) {\n\t\t\t\tconst viewParent = this.mapDomToView( domParent );\n\n\t\t\t\tif ( viewParent ) {\n\t\t\t\t\treturn new ViewPosition( viewParent, 0 );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst domBefore = domParent.childNodes[ domOffset - 1 ];\n\t\t\t\tconst viewBefore = isText( domBefore ) ?\n\t\t\t\t\tthis.findCorrespondingViewText( domBefore ) :\n\t\t\t\t\tthis.mapDomToView( domBefore );\n\n\t\t\t\t// TODO #663\n\t\t\t\tif ( viewBefore && viewBefore.parent ) {\n\t\t\t\t\treturn new ViewPosition( viewBefore.parent, viewBefore.index + 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Returns corresponding view {@link module:engine/view/element~Element Element} or\n\t * {@link module:engine/view/documentfragment~DocumentFragment} for provided DOM element or\n\t * document fragment. If there is no view item {@link module:engine/view/domconverter~DomConverter#bindElements bound}\n\t * to the given DOM - `undefined` is returned.\n\t * For all DOM elements rendered by {@link module:engine/view/uielement~UIElement} that UIElement will be returned.\n\t *\n\t * @param {DocumentFragment|Element} domElementOrDocumentFragment DOM element or document fragment.\n\t * @returns {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment|undefined}\n\t * Corresponding view element, document fragment or `undefined` if no element was bound.\n\t */\n\tmapDomToView( domElementOrDocumentFragment ) {\n\t\treturn this.getParentUIElement( domElementOrDocumentFragment ) || this._domToViewMapping.get( domElementOrDocumentFragment );\n\t}\n\n\t/**\n\t * Finds corresponding text node. Text nodes are not {@link module:engine/view/domconverter~DomConverter#bindElements bound},\n\t * corresponding text node is returned based on the sibling or parent.\n\t *\n\t * If the directly previous sibling is a {@link module:engine/view/domconverter~DomConverter#bindElements bound} element, it is used\n\t * to find the corresponding text node.\n\t *\n\t * If this is a first child in the parent and the parent is a {@link module:engine/view/domconverter~DomConverter#bindElements bound}\n\t * element, it is used to find the corresponding text node.\n\t *\n\t * For all text nodes rendered by {@link module:engine/view/uielement~UIElement} that UIElement will be returned.\n\t *\n\t * Otherwise `null` is returned.\n\t *\n\t * Note that for the block or inline {@link module:engine/view/filler filler} this method returns `null`.\n\t *\n\t * @param {Text} domText DOM text node.\n\t * @returns {module:engine/view/text~Text|null} Corresponding view text node or `null`, if it was not possible to find a\n\t * corresponding node.\n\t */\n\tfindCorrespondingViewText( domText ) {\n\t\tif ( isInlineFiller( domText ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// If DOM text was rendered by UIElement - return that element.\n\t\tconst uiElement = this.getParentUIElement( domText );\n\n\t\tif ( uiElement ) {\n\t\t\treturn uiElement;\n\t\t}\n\n\t\tconst previousSibling = domText.previousSibling;\n\n\t\t// Try to use previous sibling to find the corresponding text node.\n\t\tif ( previousSibling ) {\n\t\t\tif ( !( this.isElement( previousSibling ) ) ) {\n\t\t\t\t// The previous is text or comment.\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst viewElement = this.mapDomToView( previousSibling );\n\n\t\t\tif ( viewElement ) {\n\t\t\t\tconst nextSibling = viewElement.nextSibling;\n\n\t\t\t\t// It might be filler which has no corresponding view node.\n\t\t\t\tif ( nextSibling instanceof ViewText ) {\n\t\t\t\t\treturn viewElement.nextSibling;\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Try to use parent to find the corresponding text node.\n\t\telse {\n\t\t\tconst viewElement = this.mapDomToView( domText.parentNode );\n\n\t\t\tif ( viewElement ) {\n\t\t\t\tconst firstChild = viewElement.getChild( 0 );\n\n\t\t\t\t// It might be filler which has no corresponding view node.\n\t\t\t\tif ( firstChild instanceof ViewText ) {\n\t\t\t\t\treturn firstChild;\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Returns corresponding DOM item for provided {@link module:engine/view/element~Element Element} or\n\t * {@link module:engine/view/documentfragment~DocumentFragment DocumentFragment}.\n\t * To find a corresponding text for {@link module:engine/view/text~Text view Text instance}\n\t * use {@link #findCorrespondingDomText}.\n\t *\n\t * @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} viewNode\n\t * View element or document fragment.\n\t * @returns {Node|DocumentFragment|undefined} Corresponding DOM node or document fragment.\n\t */\n\tmapViewToDom( documentFragmentOrElement ) {\n\t\treturn this._viewToDomMapping.get( documentFragmentOrElement );\n\t}\n\n\t/**\n\t * Finds corresponding text node. Text nodes are not {@link module:engine/view/domconverter~DomConverter#bindElements bound},\n\t * corresponding text node is returned based on the sibling or parent.\n\t *\n\t * If the directly previous sibling is a {@link module:engine/view/domconverter~DomConverter#bindElements bound} element, it is used\n\t * to find the corresponding text node.\n\t *\n\t * If this is a first child in the parent and the parent is a {@link module:engine/view/domconverter~DomConverter#bindElements bound}\n\t * element, it is used to find the corresponding text node.\n\t *\n\t * Otherwise `null` is returned.\n\t *\n\t * @param {module:engine/view/text~Text} viewText View text node.\n\t * @returns {Text|null} Corresponding DOM text node or `null`, if it was not possible to find a corresponding node.\n\t */\n\tfindCorrespondingDomText( viewText ) {\n\t\tconst previousSibling = viewText.previousSibling;\n\n\t\t// Try to use previous sibling to find the corresponding text node.\n\t\tif ( previousSibling && this.mapViewToDom( previousSibling ) ) {\n\t\t\treturn this.mapViewToDom( previousSibling ).nextSibling;\n\t\t}\n\n\t\t// If this is a first node, try to use parent to find the corresponding text node.\n\t\tif ( !previousSibling && viewText.parent && this.mapViewToDom( viewText.parent ) ) {\n\t\t\treturn this.mapViewToDom( viewText.parent ).childNodes[ 0 ];\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Focuses DOM editable that is corresponding to provided {@link module:engine/view/editableelement~EditableElement}.\n\t *\n\t * @param {module:engine/view/editableelement~EditableElement} viewEditable\n\t */\n\tfocus( viewEditable ) {\n\t\tconst domEditable = this.mapViewToDom( viewEditable );\n\n\t\tif ( domEditable && domEditable.ownerDocument.activeElement !== domEditable ) {\n\t\t\t// Save the scrollX and scrollY positions before the focus.\n\t\t\tconst { scrollX, scrollY } = global.window;\n\t\t\tconst scrollPositions = [];\n\n\t\t\t// Save all scrollLeft and scrollTop values starting from domEditable up to\n\t\t\t// document#documentElement.\n\t\t\tforEachDomNodeAncestor( domEditable, node => {\n\t\t\t\tconst { scrollLeft, scrollTop } = node;\n\n\t\t\t\tscrollPositions.push( [ scrollLeft, scrollTop ] );\n\t\t\t} );\n\n\t\t\tdomEditable.focus();\n\n\t\t\t// Restore scrollLeft and scrollTop values starting from domEditable up to\n\t\t\t// document#documentElement.\n\t\t\t// https://github.com/ckeditor/ckeditor5-engine/issues/951\n\t\t\t// https://github.com/ckeditor/ckeditor5-engine/issues/957\n\t\t\tforEachDomNodeAncestor( domEditable, node => {\n\t\t\t\tconst [ scrollLeft, scrollTop ] = scrollPositions.shift();\n\n\t\t\t\tnode.scrollLeft = scrollLeft;\n\t\t\t\tnode.scrollTop = scrollTop;\n\t\t\t} );\n\n\t\t\t// Restore the scrollX and scrollY positions after the focus.\n\t\t\t// https://github.com/ckeditor/ckeditor5-engine/issues/951\n\t\t\tglobal.window.scrollTo( scrollX, scrollY );\n\t\t}\n\t}\n\n\t/**\n\t * Returns `true` when `node.nodeType` equals `Node.ELEMENT_NODE`.\n\t *\n\t * @param {Node} node Node to check.\n\t * @returns {Boolean}\n\t */\n\tisElement( node ) {\n\t\treturn node && node.nodeType == Node.ELEMENT_NODE;\n\t}\n\n\t/**\n\t * Returns `true` when `node.nodeType` equals `Node.DOCUMENT_FRAGMENT_NODE`.\n\t *\n\t * @param {Node} node Node to check.\n\t * @returns {Boolean}\n\t */\n\tisDocumentFragment( node ) {\n\t\treturn node && node.nodeType == Node.DOCUMENT_FRAGMENT_NODE;\n\t}\n\n\t/**\n\t * Returns `true` when `node.nodeType` equals `Node.COMMENT_NODE`.\n\t *\n\t * @param {Node} node Node to check.\n\t * @returns {Boolean}\n\t */\n\tisComment( node ) {\n\t\treturn node && node.nodeType == Node.COMMENT_NODE;\n\t}\n\n\t/**\n\t * Checks if the node is an instance of the block filler for this DOM converter.\n\t *\n\t *\t\tconst converter = new DomConverter( { blockFillerMode: 'br' } );\n\t *\n\t *\t\tconverter.isBlockFiller( BR_FILLER( document ) ); // true\n\t *\t\tconverter.isBlockFiller( NBSP_FILLER( document ) ); // false\n\t *\n\t * **Note:**: For the `'nbsp'` mode the method also checks context of a node so it cannot be a detached node.\n\t *\n\t * @param {Node} domNode DOM node to check.\n\t * @returns {Boolean} True if a node is considered a block filler for given mode.\n\t */\n\tisBlockFiller( domNode ) {\n\t\treturn this.blockFillerMode == 'br' ? domNode.isEqualNode( BR_FILLER_REF ) : isNbspBlockFiller( domNode, this.blockElements );\n\t}\n\n\t/**\n\t * Returns `true` if given selection is a backward selection, that is, if it's `focus` is before `anchor`.\n\t *\n\t * @param {Selection} DOM Selection instance to check.\n\t * @returns {Boolean}\n\t */\n\tisDomSelectionBackward( selection ) {\n\t\tif ( selection.isCollapsed ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Since it takes multiple lines of code to check whether a \"DOM Position\" is before/after another \"DOM Position\",\n\t\t// we will use the fact that range will collapse if it's end is before it's start.\n\t\tconst range = document.createRange();\n\n\t\trange.setStart( selection.anchorNode, selection.anchorOffset );\n\t\trange.setEnd( selection.focusNode, selection.focusOffset );\n\n\t\tconst backward = range.collapsed;\n\n\t\trange.detach();\n\n\t\treturn backward;\n\t}\n\n\t/**\n\t * Returns parent {@link module:engine/view/uielement~UIElement} for provided DOM node. Returns `null` if there is no\n\t * parent UIElement.\n\t *\n\t * @param {Node} domNode\n\t * @returns {module:engine/view/uielement~UIElement|null}\n\t */\n\tgetParentUIElement( domNode ) {\n\t\tconst ancestors = getAncestors( domNode );\n\n\t\t// Remove domNode from the list.\n\t\tancestors.pop();\n\n\t\twhile ( ancestors.length ) {\n\t\t\tconst domNode = ancestors.pop();\n\t\t\tconst viewNode = this._domToViewMapping.get( domNode );\n\n\t\t\tif ( viewNode && viewNode.is( 'uiElement' ) ) {\n\t\t\t\treturn viewNode;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Checks if given selection's boundaries are at correct places.\n\t *\n\t * The following places are considered as incorrect for selection boundaries:\n\t * * before or in the middle of the inline filler sequence,\n\t * * inside the DOM element which represents {@link module:engine/view/uielement~UIElement a view ui element}.\n\t *\n\t * @param {Selection} domSelection DOM Selection object to be checked.\n\t * @returns {Boolean} `true` if the given selection is at a correct place, `false` otherwise.\n\t */\n\tisDomSelectionCorrect( domSelection ) {\n\t\treturn this._isDomSelectionPositionCorrect( domSelection.anchorNode, domSelection.anchorOffset ) &&\n\t\t\tthis._isDomSelectionPositionCorrect( domSelection.focusNode, domSelection.focusOffset );\n\t}\n\n\t/**\n\t * Checks if the given DOM position is a correct place for selection boundary. See {@link #isDomSelectionCorrect}.\n\t *\n\t * @private\n\t * @param {Element} domParent Position parent.\n\t * @param {Number} offset Position offset.\n\t * @returns {Boolean} `true` if given position is at a correct place for selection boundary, `false` otherwise.\n\t */\n\t_isDomSelectionPositionCorrect( domParent, offset ) {\n\t\t// If selection is before or in the middle of inline filler string, it is incorrect.\n\t\tif ( isText( domParent ) && startsWithFiller( domParent ) && offset < INLINE_FILLER_LENGTH ) {\n\t\t\t// Selection in a text node, at wrong position (before or in the middle of filler).\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.isElement( domParent ) && startsWithFiller( domParent.childNodes[ offset ] ) ) {\n\t\t\t// Selection in an element node, before filler text node.\n\t\t\treturn false;\n\t\t}\n\n\t\tconst viewParent = this.mapDomToView( domParent );\n\n\t\t// If selection is in `view.UIElement`, it is incorrect. Note that `mapDomToView()` returns `view.UIElement`\n\t\t// also for any dom element that is inside the view ui element (so we don't need to perform any additional checks).\n\t\tif ( viewParent && viewParent.is( 'uiElement' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Takes text data from a given {@link module:engine/view/text~Text#data} and processes it so\n\t * it is correctly displayed in the DOM.\n\t *\n\t * Following changes are done:\n\t *\n\t * * a space at the beginning is changed to `&nbsp;` if this is the first text node in its container\n\t * element or if a previous text node ends with a space character,\n\t * * space at the end of the text node is changed to `&nbsp;` if there are two spaces at the end of a node or if next node\n\t * starts with a space or if it is the last text node in its container,\n\t * * remaining spaces are replaced to a chain of spaces and `&nbsp;` (e.g. `'x x'` becomes `'x &nbsp; x'`).\n\t *\n\t * Content of {@link #preElements} is not processed.\n\t *\n\t * @private\n\t * @param {module:engine/view/text~Text} node View text node to process.\n\t * @returns {String} Processed text data.\n\t */\n\t_processDataFromViewText( node ) {\n\t\tlet data = node.data;\n\n\t\t// If any of node ancestors has a name which is in `preElements` array, then currently processed\n\t\t// view text node is (will be) in preformatted element. We should not change whitespaces then.\n\t\tif ( node.getAncestors().some( parent => this.preElements.includes( parent.name ) ) ) {\n\t\t\treturn data;\n\t\t}\n\n\t\t// 1. Replace the first space with a nbsp if the previous node ends with a space or there is no previous node\n\t\t// (container element boundary).\n\t\tif ( data.charAt( 0 ) == ' ' ) {\n\t\t\tconst prevNode = this._getTouchingViewTextNode( node, false );\n\t\t\tconst prevEndsWithSpace = prevNode && this._nodeEndsWithSpace( prevNode );\n\n\t\t\tif ( prevEndsWithSpace || !prevNode ) {\n\t\t\t\tdata = '\\u00A0' + data.substr( 1 );\n\t\t\t}\n\t\t}\n\n\t\t// 2. Replace the last space with nbsp if there are two spaces at the end or if the next node starts with space or there is no\n\t\t// next node (container element boundary).\n\t\t//\n\t\t// Keep in mind that Firefox prefers $nbsp; before tag, not inside it:\n\t\t//\n\t\t// Foo <span>&nbsp;bar</span> <-- bad.\n\t\t// Foo&nbsp;<span> bar</span> <-- good.\n\t\t//\n\t\t// More here: https://github.com/ckeditor/ckeditor5-engine/issues/1747.\n\t\tif ( data.charAt( data.length - 1 ) == ' ' ) {\n\t\t\tconst nextNode = this._getTouchingViewTextNode( node, true );\n\n\t\t\tif ( data.charAt( data.length - 2 ) == ' ' || !nextNode || nextNode.data.charAt( 0 ) == ' ' ) {\n\t\t\t\tdata = data.substr( 0, data.length - 1 ) + '\\u00A0';\n\t\t\t}\n\t\t}\n\n\t\t// 3. Create space+nbsp pairs.\n\t\treturn data.replace( / {2}/g, ' \\u00A0' );\n\t}\n\n\t/**\n\t * Checks whether given node ends with a space character after changing appropriate space characters to `&nbsp;`s.\n\t *\n\t * @private\n\t * @param {module:engine/view/text~Text} node Node to check.\n\t * @returns {Boolean} `true` if given `node` ends with space, `false` otherwise.\n\t */\n\t_nodeEndsWithSpace( node ) {\n\t\tif ( node.getAncestors().some( parent => this.preElements.includes( parent.name ) ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst data = this._processDataFromViewText( node );\n\n\t\treturn data.charAt( data.length - 1 ) == ' ';\n\t}\n\n\t/**\n\t * Takes text data from native `Text` node and processes it to a correct {@link module:engine/view/text~Text view text node} data.\n\t *\n\t * Following changes are done:\n\t *\n\t * * multiple whitespaces are replaced to a single space,\n\t * * space at the beginning of a text node is removed if it is the first text node in its container\n\t * element or if the previous text node ends with a space character,\n\t * * space at the end of the text node is removed if there are two spaces at the end of a node or if next node\n\t * starts with a space or if it is the last text node in its container\n\t * * nbsps are converted to spaces.\n\t *\n\t * @param {Node} node DOM text node to process.\n\t * @returns {String} Processed data.\n\t * @private\n\t */\n\t_processDataFromDomText( node ) {\n\t\tlet data = node.data;\n\n\t\tif ( _hasDomParentOfType( node, this.preElements ) ) {\n\t\t\treturn getDataWithoutFiller( node );\n\t\t}\n\n\t\t// Change all consecutive whitespace characters (from the [ \\n\\t\\r] set –\n\t\t// see https://github.com/ckeditor/ckeditor5-engine/issues/822#issuecomment-311670249) to a single space character.\n\t\t// That's how multiple whitespaces are treated when rendered, so we normalize those whitespaces.\n\t\t// We're replacing 1+ (and not 2+) to also normalize singular \\n\\t\\r characters (#822).\n\t\tdata = data.replace( /[ \\n\\t\\r]{1,}/g, ' ' );\n\n\t\tconst prevNode = this._getTouchingInlineDomNode( node, false );\n\t\tconst nextNode = this._getTouchingInlineDomNode( node, true );\n\n\t\tconst shouldLeftTrim = this._checkShouldLeftTrimDomText( prevNode );\n\t\tconst shouldRightTrim = this._checkShouldRightTrimDomText( node, nextNode );\n\n\t\t// If the previous dom text node does not exist or it ends by whitespace character, remove space character from the beginning\n\t\t// of this text node. Such space character is treated as a whitespace.\n\t\tif ( shouldLeftTrim ) {\n\t\t\tdata = data.replace( /^ /, '' );\n\t\t}\n\n\t\t// If the next text node does not exist remove space character from the end of this text node.\n\t\tif ( shouldRightTrim ) {\n\t\t\tdata = data.replace( / $/, '' );\n\t\t}\n\n\t\t// At the beginning and end of a block element, Firefox inserts normal space + <br> instead of non-breaking space.\n\t\t// This means that the text node starts/end with normal space instead of non-breaking space.\n\t\t// This causes a problem because the normal space would be removed in `.replace` calls above. To prevent that,\n\t\t// the inline filler is removed only after the data is initially processed (by the `.replace` above). See ckeditor5#692.\n\t\tdata = getDataWithoutFiller( new Text( data ) );\n\n\t\t// At this point we should have removed all whitespaces from DOM text data.\n\t\t//\n\t\t// Now, We will reverse the process that happens in `_processDataFromViewText`.\n\t\t//\n\t\t// We have to change &nbsp; chars, that were in DOM text data because of rendering reasons, to spaces.\n\t\t// First, change all ` \\u00A0` pairs (space + &nbsp;) to two spaces. DOM converter changes two spaces from model/view to\n\t\t// ` \\u00A0` to ensure proper rendering. Since here we convert back, we recognize those pairs and change them back to ` `.\n\t\tdata = data.replace( / \\u00A0/g, ' ' );\n\n\t\t// Then, let's change the last nbsp to a space.\n\t\tif ( /( |\\u00A0)\\u00A0$/.test( data ) || !nextNode || ( nextNode.data && nextNode.data.charAt( 0 ) == ' ' ) ) {\n\t\t\tdata = data.replace( /\\u00A0$/, ' ' );\n\t\t}\n\n\t\t// Then, change &nbsp; character that is at the beginning of the text node to space character.\n\t\t// We do that replacement only if this is the first node or the previous node ends on whitespace character.\n\t\tif ( shouldLeftTrim ) {\n\t\t\tdata = data.replace( /^\\u00A0/, ' ' );\n\t\t}\n\n\t\t// At this point, all whitespaces should be removed and all &nbsp; created for rendering reasons should be\n\t\t// changed to normal space. All left &nbsp; are &nbsp; inserted intentionally.\n\t\treturn data;\n\t}\n\n\t/**\n\t * Helper function which checks if a DOM text node, preceded by the given `prevNode` should\n\t * be trimmed from the left side.\n\t *\n\t * @param {Node} prevNode\n\t */\n\t_checkShouldLeftTrimDomText( prevNode ) {\n\t\tif ( !prevNode ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( isElement( prevNode ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn /[^\\S\\u00A0]/.test( prevNode.data.charAt( prevNode.data.length - 1 ) );\n\t}\n\n\t/**\n\t * Helper function which checks if a DOM text node, succeeded by the given `nextNode` should\n\t * be trimmed from the right side.\n\t *\n\t * @param {Node} node\n\t * @param {Node} nextNode\n\t */\n\t_checkShouldRightTrimDomText( node, nextNode ) {\n\t\tif ( nextNode ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn !startsWithFiller( node );\n\t}\n\n\t/**\n\t * Helper function. For given {@link module:engine/view/text~Text view text node}, it finds previous or next sibling\n\t * that is contained in the same container element. If there is no such sibling, `null` is returned.\n\t *\n\t * @param {module:engine/view/text~Text} node Reference node.\n\t * @param {Boolean} getNext\n\t * @returns {module:engine/view/text~Text|null} Touching text node or `null` if there is no next or previous touching text node.\n\t */\n\t_getTouchingViewTextNode( node, getNext ) {\n\t\tconst treeWalker = new ViewTreeWalker( {\n\t\t\tstartPosition: getNext ? ViewPosition._createAfter( node ) : ViewPosition._createBefore( node ),\n\t\t\tdirection: getNext ? 'forward' : 'backward'\n\t\t} );\n\n\t\tfor ( const value of treeWalker ) {\n\t\t\t// ViewContainerElement is found on a way to next ViewText node, so given `node` was first/last\n\t\t\t// text node in its container element.\n\t\t\tif ( value.item.is( 'containerElement' ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t// <br> found – it works like a block boundary, so do not scan further.\n\t\t\telse if ( value.item.is( 'br' ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t// Found a text node in the same container element.\n\t\t\telse if ( value.item.is( 'textProxy' ) ) {\n\t\t\t\treturn value.item;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Helper function. For the given text node, it finds the closest touching node which is either\n\t * a text node or a `<br>`. The search is terminated at block element boundaries and if a matching node\n\t * wasn't found so far, `null` is returned.\n\t *\n\t * In the following DOM structure:\n\t *\n\t *\t\t<p>foo<b>bar</b><br>bom</p>\n\t *\n\t * * `foo` doesn't have its previous touching inline node (`null` is returned),\n\t * * `foo`'s next touching inline node is `bar`\n\t * * `bar`'s next touching inline node is `<br>`\n\t *\n\t * This method returns text nodes and `<br>` elements because these types of nodes affect how\n\t * spaces in the given text node need to be converted.\n\t *\n\t * @private\n\t * @param {Text} node\n\t * @param {Boolean} getNext\n\t * @returns {Text|Element|null}\n\t */\n\t_getTouchingInlineDomNode( node, getNext ) {\n\t\tif ( !node.parentNode ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst direction = getNext ? 'nextNode' : 'previousNode';\n\t\tconst document = node.ownerDocument;\n\t\tconst topmostParent = getAncestors( node )[ 0 ];\n\n\t\tconst treeWalker = document.createTreeWalker( topmostParent, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT, {\n\t\t\tacceptNode( node ) {\n\t\t\t\tif ( isText( node ) ) {\n\t\t\t\t\treturn NodeFilter.FILTER_ACCEPT;\n\t\t\t\t}\n\n\t\t\t\tif ( node.tagName == 'BR' ) {\n\t\t\t\t\treturn NodeFilter.FILTER_ACCEPT;\n\t\t\t\t}\n\n\t\t\t\treturn NodeFilter.FILTER_SKIP;\n\t\t\t}\n\t\t} );\n\n\t\ttreeWalker.currentNode = node;\n\n\t\tconst touchingNode = treeWalker[ direction ]();\n\n\t\tif ( touchingNode !== null ) {\n\t\t\tconst lca = getCommonAncestor( node, touchingNode );\n\n\t\t\t// If there is common ancestor between the text node and next/prev text node,\n\t\t\t// and there are no block elements on a way from the text node to that ancestor,\n\t\t\t// and there are no block elements on a way from next/prev text node to that ancestor...\n\t\t\tif (\n\t\t\t\tlca &&\n\t\t\t\t!_hasDomParentOfType( node, this.blockElements, lca ) &&\n\t\t\t\t!_hasDomParentOfType( touchingNode, this.blockElements, lca )\n\t\t\t) {\n\t\t\t\t// Then they are in the same container element.\n\t\t\t\treturn touchingNode;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n}\n\n// Helper function.\n// Used to check if given native `Element` or `Text` node has parent with tag name from `types` array.\n//\n// @param {Node} node\n// @param {Array.<String>} types\n// @param {Boolean} [boundaryParent] Can be given if parents should be checked up to a given element (excluding that element).\n// @returns {Boolean} `true` if such parent exists or `false` if it does not.\nfunction _hasDomParentOfType( node, types, boundaryParent ) {\n\tlet parents = getAncestors( node );\n\n\tif ( boundaryParent ) {\n\t\tparents = parents.slice( parents.indexOf( boundaryParent ) + 1 );\n\t}\n\n\treturn parents.some( parent => parent.tagName && types.includes( parent.tagName.toLowerCase() ) );\n}\n\n// A helper that executes given callback for each DOM node's ancestor, starting from the given node\n// and ending in document#documentElement.\n//\n// @param {Node} node\n// @param {Function} callback A callback to be executed for each ancestor.\nfunction forEachDomNodeAncestor( node, callback ) {\n\twhile ( node && node != global.document ) {\n\t\tcallback( node );\n\t\tnode = node.parentNode;\n\t}\n}\n\n// Checks if given node is a nbsp block filler.\n//\n// A &nbsp; is a block filler only if it is a single child of a block element.\n//\n// @param {Node} domNode DOM node.\n// @returns {Boolean}\nfunction isNbspBlockFiller( domNode, blockElements ) {\n\tconst isNBSP = isText( domNode ) && domNode.data == '\\u00A0';\n\n\treturn isNBSP && hasBlockParent( domNode, blockElements ) && domNode.parentNode.childNodes.length === 1;\n}\n\n// Checks if domNode has block parent.\n//\n// @param {Node} domNode DOM node.\n// @returns {Boolean}\nfunction hasBlockParent( domNode, blockElements ) {\n\tconst parent = domNode.parentNode;\n\n\treturn parent && parent.tagName && blockElements.includes( parent.tagName.toLowerCase() );\n}\n\n/**\n * Enum representing type of the block filler.\n *\n * Possible values:\n *\n * * `br` - for `<br>` block filler used in editing view,\n * * `nbsp` - for `&nbsp;` block fillers used in the data.\n *\n * @typedef {String} module:engine/view/filler~BlockFillerMode\n */\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/getcommonancestor\n */\n\nimport getAncestors from './getancestors';\n\n/**\n * Searches and returns the lowest common ancestor of two given nodes.\n *\n * @param {Node} nodeA First node.\n * @param {Node} nodeB Second node.\n * @returns {Node|DocumentFragment|Document|null} Lowest common ancestor of both nodes or `null` if nodes do not have a common ancestor.\n */\nexport default function getCommonAncestor( nodeA, nodeB ) {\n\tconst ancestorsA = getAncestors( nodeA );\n\tconst ancestorsB = getAncestors( nodeB );\n\n\tlet i = 0;\n\n\t// It does not matter which array is shorter.\n\twhile ( ancestorsA[ i ] == ancestorsB[ i ] && ancestorsA[ i ] ) {\n\t\ti++;\n\t}\n\n\treturn i === 0 ? null : ancestorsA[ i - 1 ];\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/iswindow\n */\n\n/**\n * Checks if the object is a native DOM Window.\n *\n * @param {*} obj\n * @returns {Boolean}\n */\nexport default function isWindow( obj ) {\n\tconst stringifiedObject = Object.prototype.toString.apply( obj );\n\n\t// Returns `true` for the `window` object in browser environments.\n\tif ( stringifiedObject == '[object Window]' ) {\n\t\treturn true;\n\t}\n\n\t// Returns `true` for the `window` object in the Electron environment.\n\tif ( stringifiedObject == '[object global]' ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/emittermixin\n */\n\nimport { default as EmitterMixin, _getEmitterListenedTo, _setEmitterId } from '../emittermixin';\nimport uid from '../uid';\nimport isNode from './isnode';\nimport isWindow from './iswindow';\nimport { extend } from 'lodash-es';\n\n/**\n * Mixin that injects the DOM events API into its host. It provides the API\n * compatible with {@link module:utils/emittermixin~EmitterMixin}.\n *\n * DOM emitter mixin is by default available in the {@link module:ui/view~View} class,\n * but it can also be mixed into any other class:\n *\n *\t\timport mix from '../utils/mix.js';\n *\t\timport DomEmitterMixin from '../utils/dom/emittermixin.js';\n *\n *\t\tclass SomeView {}\n *\t\tmix( SomeView, DomEmitterMixin );\n *\n *\t\tconst view = new SomeView();\n *\t\tview.listenTo( domElement, ( evt, domEvt ) => {\n *\t\t\tconsole.log( evt, domEvt );\n *\t\t} );\n *\n * @mixin EmitterMixin\n * @mixes module:utils/emittermixin~EmitterMixin\n * @implements module:utils/dom/emittermixin~Emitter\n */\nconst DomEmitterMixin = extend( {}, EmitterMixin, {\n\t/**\n\t * Registers a callback function to be executed when an event is fired in a specific Emitter or DOM Node.\n\t * It is backwards compatible with {@link module:utils/emittermixin~EmitterMixin#listenTo}.\n\t *\n\t * @param {module:utils/emittermixin~Emitter|Node} emitter The object that fires the event.\n\t * @param {String} event The name of the event.\n\t * @param {Function} callback The function to be called on event.\n\t * @param {Object} [options={}] Additional options.\n\t * @param {module:utils/priorities~PriorityString|Number} [options.priority='normal'] The priority of this event callback. The higher\n\t * the priority value the sooner the callback will be fired. Events having the same priority are called in the\n\t * order they were added.\n\t * @param {Boolean} [options.useCapture=false] Indicates that events of this type will be dispatched to the registered\n\t * listener before being dispatched to any EventTarget beneath it in the DOM tree.\n\t */\n\tlistenTo( emitter, ...rest ) {\n\t\t// Check if emitter is an instance of DOM Node. If so, replace the argument with\n\t\t// corresponding ProxyEmitter (or create one if not existing).\n\t\tif ( isNode( emitter ) || isWindow( emitter ) ) {\n\t\t\tconst proxy = this._getProxyEmitter( emitter ) || new ProxyEmitter( emitter );\n\n\t\t\tproxy.attach( ...rest );\n\n\t\t\temitter = proxy;\n\t\t}\n\n\t\t// Execute parent class method with Emitter (or ProxyEmitter) instance.\n\t\tEmitterMixin.listenTo.call( this, emitter, ...rest );\n\t},\n\n\t/**\n\t * Stops listening for events. It can be used at different levels:\n\t * It is backwards compatible with {@link module:utils/emittermixin~EmitterMixin#listenTo}.\n\t *\n\t * * To stop listening to a specific callback.\n\t * * To stop listening to a specific event.\n\t * * To stop listening to all events fired by a specific object.\n\t * * To stop listening to all events fired by all object.\n\t *\n\t * @param {module:utils/emittermixin~Emitter|Node} [emitter] The object to stop listening to. If omitted, stops it for all objects.\n\t * @param {String} [event] (Requires the `emitter`) The name of the event to stop listening to. If omitted, stops it\n\t * for all events from `emitter`.\n\t * @param {Function} [callback] (Requires the `event`) The function to be removed from the call list for the given\n\t * `event`.\n\t */\n\tstopListening( emitter, event, callback ) {\n\t\t// Check if emitter is an instance of DOM Node. If so, replace the argument with corresponding ProxyEmitter.\n\t\tif ( isNode( emitter ) || isWindow( emitter ) ) {\n\t\t\tconst proxy = this._getProxyEmitter( emitter );\n\n\t\t\t// Element has no listeners.\n\t\t\tif ( !proxy ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\temitter = proxy;\n\t\t}\n\n\t\t// Execute parent class method with Emitter (or ProxyEmitter) instance.\n\t\tEmitterMixin.stopListening.call( this, emitter, event, callback );\n\n\t\tif ( emitter instanceof ProxyEmitter ) {\n\t\t\temitter.detach( event );\n\t\t}\n\t},\n\n\t/**\n\t * Retrieves ProxyEmitter instance for given DOM Node residing in this Host.\n\t *\n\t * @pivate\n\t * @param {Node} node DOM Node of the ProxyEmitter.\n\t * @returns {module:utils/dom/emittermixin~ProxyEmitter} ProxyEmitter instance or null.\n\t */\n\t_getProxyEmitter( node ) {\n\t\treturn _getEmitterListenedTo( this, getNodeUID( node ) );\n\t}\n} );\n\nexport default DomEmitterMixin;\n\n/**\n * Creates a ProxyEmitter instance. Such an instance is a bridge between a DOM Node firing events\n * and any Host listening to them. It is backwards compatible with {@link module:utils/emittermixin~EmitterMixin#on}.\n *\n * listenTo( click, ... )\n * +-----------------------------------------+\n * | stopListening( ... ) |\n * +----------------------------+ | addEventListener( click, ... )\n * | Host | | +---------------------------------------------+\n * +----------------------------+ | | removeEventListener( click, ... ) |\n * | _listeningTo: { | +----------v-------------+ |\n * | UID: { | | ProxyEmitter | |\n * | emitter: ProxyEmitter, | +------------------------+ +------------v----------+\n * | callbacks: { | | events: { | | Node (HTMLElement) |\n * | click: [ callbacks ] | | click: [ callbacks ] | +-----------------------+\n * | } | | }, | | data-ck-expando: UID |\n * | } | | _domNode: Node, | +-----------------------+\n * | } | | _domListeners: {}, | |\n * | +------------------------+ | | _emitterId: UID | |\n * | | DomEmitterMixin | | +--------------^---------+ |\n * | +------------------------+ | | | |\n * +--------------^-------------+ | +---------------------------------------------+\n * | | click (DOM Event)\n * +-----------------------------------------+\n * fire( click, DOM Event )\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n * @implements module:utils/dom/emittermixin~Emitter\n * @private\n */\nclass ProxyEmitter {\n\t/**\n\t * @param {Node} node DOM Node that fires events.\n\t * @returns {Object} ProxyEmitter instance bound to the DOM Node.\n\t */\n\tconstructor( node ) {\n\t\t// Set emitter ID to match DOM Node \"expando\" property.\n\t\t_setEmitterId( this, getNodeUID( node ) );\n\n\t\t// Remember the DOM Node this ProxyEmitter is bound to.\n\t\tthis._domNode = node;\n\t}\n}\n\nextend( ProxyEmitter.prototype, EmitterMixin, {\n\t/**\n\t * Collection of native DOM listeners.\n\t *\n\t * @private\n\t * @member {Object} module:utils/dom/emittermixin~ProxyEmitter#_domListeners\n\t */\n\n\t/**\n\t * Registers a callback function to be executed when an event is fired.\n\t *\n\t * It attaches a native DOM listener to the DOM Node. When fired,\n\t * a corresponding Emitter event will also fire with DOM Event object as an argument.\n\t *\n\t * @method module:utils/dom/emittermixin~ProxyEmitter#attach\n\t * @param {String} event The name of the event.\n\t * @param {Function} callback The function to be called on event.\n\t * @param {Object} [options={}] Additional options.\n\t * @param {Boolean} [options.useCapture=false] Indicates that events of this type will be dispatched to the registered\n\t * listener before being dispatched to any EventTarget beneath it in the DOM tree.\n\t */\n\tattach( event, callback, options = {} ) {\n\t\t// If the DOM Listener for given event already exist it is pointless\n\t\t// to attach another one.\n\t\tif ( this._domListeners && this._domListeners[ event ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst domListener = this._createDomListener( event, !!options.useCapture );\n\n\t\t// Attach the native DOM listener to DOM Node.\n\t\tthis._domNode.addEventListener( event, domListener, !!options.useCapture );\n\n\t\tif ( !this._domListeners ) {\n\t\t\tthis._domListeners = {};\n\t\t}\n\n\t\t// Store the native DOM listener in this ProxyEmitter. It will be helpful\n\t\t// when stopping listening to the event.\n\t\tthis._domListeners[ event ] = domListener;\n\t},\n\n\t/**\n\t * Stops executing the callback on the given event.\n\t *\n\t * @method module:utils/dom/emittermixin~ProxyEmitter#detach\n\t * @param {String} event The name of the event.\n\t */\n\tdetach( event ) {\n\t\tlet events;\n\n\t\t// Remove native DOM listeners which are orphans. If no callbacks\n\t\t// are awaiting given event, detach native DOM listener from DOM Node.\n\t\t// See: {@link attach}.\n\n\t\tif ( this._domListeners[ event ] && ( !( events = this._events[ event ] ) || !events.callbacks.length ) ) {\n\t\t\tthis._domListeners[ event ].removeListener();\n\t\t}\n\t},\n\n\t/**\n\t * Creates a native DOM listener callback. When the native DOM event\n\t * is fired it will fire corresponding event on this ProxyEmitter.\n\t * Note: A native DOM Event is passed as an argument.\n\t *\n\t * @private\n\t * @method module:utils/dom/emittermixin~ProxyEmitter#_createDomListener\n\t * @param {String} event The name of the event.\n\t * @param {Boolean} useCapture Indicates whether the listener was created for capturing event.\n\t * @returns {Function} The DOM listener callback.\n\t */\n\t_createDomListener( event, useCapture ) {\n\t\tconst domListener = domEvt => {\n\t\t\tthis.fire( event, domEvt );\n\t\t};\n\n\t\t// Supply the DOM listener callback with a function that will help\n\t\t// detach it from the DOM Node, when it is no longer necessary.\n\t\t// See: {@link detach}.\n\t\tdomListener.removeListener = () => {\n\t\t\tthis._domNode.removeEventListener( event, domListener, useCapture );\n\t\t\tdelete this._domListeners[ event ];\n\t\t};\n\n\t\treturn domListener;\n\t}\n} );\n\n// Gets an unique DOM Node identifier. The identifier will be set if not defined.\n//\n// @private\n// @param {Node} node\n// @returns {String} UID for given DOM Node.\nfunction getNodeUID( node ) {\n\treturn node[ 'data-ck-expando' ] || ( node[ 'data-ck-expando' ] = uid() );\n}\n\n/**\n * Interface representing classes which mix in {@link module:utils/dom/emittermixin~EmitterMixin}.\n *\n * @interface Emitter\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/observer\n */\n\nimport DomEmitterMixin from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Abstract base observer class. Observers are classes which listen to DOM events, do the preliminary\n * processing and fire events on the {@link module:engine/view/document~Document} objects.\n * Observers can also add features to the view, for instance by updating its status or marking elements\n * which need refresh on DOM events.\n *\n * @abstract\n */\nexport default class Observer {\n\t/**\n\t * Creates an instance of the observer.\n\t *\n\t * @param {module:engine/view/view~View} view\n\t */\n\tconstructor( view ) {\n\t\t/**\n\t\t * Instance of the view controller.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/view~View}\n\t\t */\n\t\tthis.view = view;\n\n\t\t/**\n\t\t * Reference to the {@link module:engine/view/document~Document} object.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/document~Document}\n\t\t */\n\t\tthis.document = view.document;\n\n\t\t/**\n\t\t * State of the observer. If it is disabled events will not be fired.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis.isEnabled = false;\n\t}\n\n\t/**\n\t * Enables the observer. This method is called when the observer is registered to the\n\t * {@link module:engine/view/view~View} and after {@link module:engine/view/view~View#forceRender rendering}\n\t * (all observers are {@link #disable disabled} before rendering).\n\t *\n\t * A typical use case for disabling observers is that mutation observers need to be disabled for the rendering.\n\t * However, a child class may not need to be disabled, so it can implement an empty method.\n\t *\n\t * @see module:engine/view/observer/observer~Observer#disable\n\t */\n\tenable() {\n\t\tthis.isEnabled = true;\n\t}\n\n\t/**\n\t * Disables the observer. This method is called before\n\t * {@link module:engine/view/view~View#forceRender rendering} to prevent firing events during rendering.\n\t *\n\t * @see module:engine/view/observer/observer~Observer#enable\n\t */\n\tdisable() {\n\t\tthis.isEnabled = false;\n\t}\n\n\t/**\n\t * Disables and destroys the observer, among others removes event listeners created by the observer.\n\t */\n\tdestroy() {\n\t\tthis.disable();\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Starts observing the given root element.\n\t *\n\t * @method #observe\n\t * @param {HTMLElement} domElement\n\t * @param {String} name The name of the root element.\n\t */\n}\n\nmix( Observer, DomEmitterMixin );\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n}\n\nexport default setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n return this.__data__.has(value);\n}\n\nexport default setCacheHas;\n","import MapCache from './_MapCache.js';\nimport setCacheAdd from './_setCacheAdd.js';\nimport setCacheHas from './_setCacheHas.js';\n\n/**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\nfunction SetCache(values) {\n var index = -1,\n length = values == null ? 0 : values.length;\n\n this.__data__ = new MapCache;\n while (++index < length) {\n this.add(values[index]);\n }\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\n\nexport default SetCache;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\nfunction arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n}\n\nexport default arraySome;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n return cache.has(key);\n}\n\nexport default cacheHas;\n","import SetCache from './_SetCache.js';\nimport arraySome from './_arraySome.js';\nimport cacheHas from './_cacheHas.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n arrLength = array.length,\n othLength = other.length;\n\n if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(array);\n if (stacked && stack.get(other)) {\n return stacked == other;\n }\n var index = -1,\n result = true,\n seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n stack.set(array, other);\n stack.set(other, array);\n\n // Ignore non-index properties.\n while (++index < arrLength) {\n var arrValue = array[index],\n othValue = other[index];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, arrValue, index, other, array, stack)\n : customizer(arrValue, othValue, index, array, other, stack);\n }\n if (compared !== undefined) {\n if (compared) {\n continue;\n }\n result = false;\n break;\n }\n // Recursively compare arrays (susceptible to call stack limits).\n if (seen) {\n if (!arraySome(other, function(othValue, othIndex) {\n if (!cacheHas(seen, othIndex) &&\n (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n return seen.push(othIndex);\n }\n })) {\n result = false;\n break;\n }\n } else if (!(\n arrValue === othValue ||\n equalFunc(arrValue, othValue, bitmask, customizer, stack)\n )) {\n result = false;\n break;\n }\n }\n stack['delete'](array);\n stack['delete'](other);\n return result;\n}\n\nexport default equalArrays;\n","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n}\n\nexport default mapToArray;\n","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n}\n\nexport default setToArray;\n","import Symbol from './_Symbol.js';\nimport Uint8Array from './_Uint8Array.js';\nimport eq from './eq.js';\nimport equalArrays from './_equalArrays.js';\nimport mapToArray from './_mapToArray.js';\nimport setToArray from './_setToArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n switch (tag) {\n case dataViewTag:\n if ((object.byteLength != other.byteLength) ||\n (object.byteOffset != other.byteOffset)) {\n return false;\n }\n object = object.buffer;\n other = other.buffer;\n\n case arrayBufferTag:\n if ((object.byteLength != other.byteLength) ||\n !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n return false;\n }\n return true;\n\n case boolTag:\n case dateTag:\n case numberTag:\n // Coerce booleans to `1` or `0` and dates to milliseconds.\n // Invalid dates are coerced to `NaN`.\n return eq(+object, +other);\n\n case errorTag:\n return object.name == other.name && object.message == other.message;\n\n case regexpTag:\n case stringTag:\n // Coerce regexes to strings and treat strings, primitives and objects,\n // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n // for more details.\n return object == (other + '');\n\n case mapTag:\n var convert = mapToArray;\n\n case setTag:\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n convert || (convert = setToArray);\n\n if (object.size != other.size && !isPartial) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked) {\n return stacked == other;\n }\n bitmask |= COMPARE_UNORDERED_FLAG;\n\n // Recursively compare objects (susceptible to call stack limits).\n stack.set(object, other);\n var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n stack['delete'](object);\n return result;\n\n case symbolTag:\n if (symbolValueOf) {\n return symbolValueOf.call(object) == symbolValueOf.call(other);\n }\n }\n return false;\n}\n\nexport default equalByTag;\n","import getAllKeys from './_getAllKeys.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n objProps = getAllKeys(object),\n objLength = objProps.length,\n othProps = getAllKeys(other),\n othLength = othProps.length;\n\n if (objLength != othLength && !isPartial) {\n return false;\n }\n var index = objLength;\n while (index--) {\n var key = objProps[index];\n if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n return false;\n }\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked && stack.get(other)) {\n return stacked == other;\n }\n var result = true;\n stack.set(object, other);\n stack.set(other, object);\n\n var skipCtor = isPartial;\n while (++index < objLength) {\n key = objProps[index];\n var objValue = object[key],\n othValue = other[key];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, objValue, key, other, object, stack)\n : customizer(objValue, othValue, key, object, other, stack);\n }\n // Recursively compare objects (susceptible to call stack limits).\n if (!(compared === undefined\n ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n : compared\n )) {\n result = false;\n break;\n }\n skipCtor || (skipCtor = key == 'constructor');\n }\n if (result && !skipCtor) {\n var objCtor = object.constructor,\n othCtor = other.constructor;\n\n // Non `Object` object instances with different constructors are not equal.\n if (objCtor != othCtor &&\n ('constructor' in object && 'constructor' in other) &&\n !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n result = false;\n }\n }\n stack['delete'](object);\n stack['delete'](other);\n return result;\n}\n\nexport default equalObjects;\n","import Stack from './_Stack.js';\nimport equalArrays from './_equalArrays.js';\nimport equalByTag from './_equalByTag.js';\nimport equalObjects from './_equalObjects.js';\nimport getTag from './_getTag.js';\nimport isArray from './isArray.js';\nimport isBuffer from './isBuffer.js';\nimport isTypedArray from './isTypedArray.js';\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n var objIsArr = isArray(object),\n othIsArr = isArray(other),\n objTag = objIsArr ? arrayTag : getTag(object),\n othTag = othIsArr ? arrayTag : getTag(other);\n\n objTag = objTag == argsTag ? objectTag : objTag;\n othTag = othTag == argsTag ? objectTag : othTag;\n\n var objIsObj = objTag == objectTag,\n othIsObj = othTag == objectTag,\n isSameTag = objTag == othTag;\n\n if (isSameTag && isBuffer(object)) {\n if (!isBuffer(other)) {\n return false;\n }\n objIsArr = true;\n objIsObj = false;\n }\n if (isSameTag && !objIsObj) {\n stack || (stack = new Stack);\n return (objIsArr || isTypedArray(object))\n ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n }\n if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n if (objIsWrapped || othIsWrapped) {\n var objUnwrapped = objIsWrapped ? object.value() : object,\n othUnwrapped = othIsWrapped ? other.value() : other;\n\n stack || (stack = new Stack);\n return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n }\n }\n if (!isSameTag) {\n return false;\n }\n stack || (stack = new Stack);\n return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n}\n\nexport default baseIsEqualDeep;\n","import baseIsEqualDeep from './_baseIsEqualDeep.js';\nimport isObjectLike from './isObjectLike.js';\n\n/**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Unordered comparison\n * 2 - Partial comparison\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, bitmask, customizer, stack) {\n if (value === other) {\n return true;\n }\n if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n return value !== value && other !== other;\n }\n return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\n}\n\nexport default baseIsEqual;\n","import baseIsEqual from './_baseIsEqual.js';\n\n/**\n * This method is like `_.isEqual` except that it accepts `customizer` which\n * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n * are handled by the method instead. The `customizer` is invoked with up to\n * six arguments: (objValue, othValue [, index|key, object, other, stack]).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * function isGreeting(value) {\n * return /^h(?:i|ello)$/.test(value);\n * }\n *\n * function customizer(objValue, othValue) {\n * if (isGreeting(objValue) && isGreeting(othValue)) {\n * return true;\n * }\n * }\n *\n * var array = ['hello', 'goodbye'];\n * var other = ['hi', 'goodbye'];\n *\n * _.isEqualWith(array, other, customizer);\n * // => true\n */\nfunction isEqualWith(value, other, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n var result = customizer ? customizer(value, other) : undefined;\n return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;\n}\n\nexport default isEqualWith;\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/mutationobserver\n */\n\n/* globals window */\n\nimport Observer from './observer';\nimport ViewSelection from '../selection';\nimport { startsWithFiller, getDataWithoutFiller } from '../filler';\nimport { isEqualWith } from 'lodash-es';\n\n/**\n * Mutation observer class observes changes in the DOM, fires {@link module:engine/view/document~Document#event:mutations} event, mark view\n * elements as changed and call {@link module:engine/view/renderer~Renderer#render}.\n * Because all mutated nodes are marked as \"to be rendered\" and the\n * {@link module:engine/view/renderer~Renderer#render} is called, all changes will be reverted, unless the mutation will be handled by the\n * {@link module:engine/view/document~Document#event:mutations} event listener. It means user will see only handled changes, and the editor\n * will block all changes which are not handled.\n *\n * Mutation Observer also take care of reducing number of mutations which are fired. It removes duplicates and\n * mutations on elements which do not have corresponding view elements. Also\n * {@link module:engine/view/observer/mutationobserver~MutatedText text mutation} is fired only if parent element do not change child list.\n *\n * Note that this observer is attached by the {@link module:engine/view/view~View} and is available by default.\n *\n * @extends module:engine/view/observer/observer~Observer\n */\nexport default class MutationObserver extends Observer {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\t/**\n\t\t * Native mutation observer config.\n\t\t *\n\t\t * @private\n\t\t * @member {Object}\n\t\t */\n\t\tthis._config = {\n\t\t\tchildList: true,\n\t\t\tcharacterData: true,\n\t\t\tcharacterDataOldValue: true,\n\t\t\tsubtree: true\n\t\t};\n\n\t\t/**\n\t\t * Reference to the {@link module:engine/view/view~View#domConverter}.\n\t\t *\n\t\t * @member {module:engine/view/domconverter~DomConverter}\n\t\t */\n\t\tthis.domConverter = view.domConverter;\n\n\t\t/**\n\t\t * Reference to the {@link module:engine/view/view~View#_renderer}.\n\t\t *\n\t\t * @member {module:engine/view/renderer~Renderer}\n\t\t */\n\t\tthis.renderer = view._renderer;\n\n\t\t/**\n\t\t * Observed DOM elements.\n\t\t *\n\t\t * @private\n\t\t * @member {Array.<HTMLElement>}\n\t\t */\n\t\tthis._domElements = [];\n\n\t\t/**\n\t\t * Native mutation observer.\n\t\t *\n\t\t * @private\n\t\t * @member {MutationObserver}\n\t\t */\n\t\tthis._mutationObserver = new window.MutationObserver( this._onMutations.bind( this ) );\n\t}\n\n\t/**\n\t * Synchronously fires {@link module:engine/view/document~Document#event:mutations} event with all mutations in record queue.\n\t * At the same time empties the queue so mutations will not be fired twice.\n\t */\n\tflush() {\n\t\tthis._onMutations( this._mutationObserver.takeRecords() );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tobserve( domElement ) {\n\t\tthis._domElements.push( domElement );\n\n\t\tif ( this.isEnabled ) {\n\t\t\tthis._mutationObserver.observe( domElement, this._config );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tenable() {\n\t\tsuper.enable();\n\n\t\tfor ( const domElement of this._domElements ) {\n\t\t\tthis._mutationObserver.observe( domElement, this._config );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdisable() {\n\t\tsuper.disable();\n\n\t\tthis._mutationObserver.disconnect();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\tthis._mutationObserver.disconnect();\n\t}\n\n\t/**\n\t * Handles mutations. Deduplicates, mark view elements to sync, fire event and call render.\n\t *\n\t * @private\n\t * @param {Array.<Object>} domMutations Array of native mutations.\n\t */\n\t_onMutations( domMutations ) {\n\t\t// As a result of this.flush() we can have an empty collection.\n\t\tif ( domMutations.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst domConverter = this.domConverter;\n\n\t\t// Use map and set for deduplication.\n\t\tconst mutatedTexts = new Map();\n\t\tconst mutatedElements = new Set();\n\n\t\t// Handle `childList` mutations first, so we will be able to check if the `characterData` mutation is in the\n\t\t// element with changed structure anyway.\n\t\tfor ( const mutation of domMutations ) {\n\t\t\tif ( mutation.type === 'childList' ) {\n\t\t\t\tconst element = domConverter.mapDomToView( mutation.target );\n\n\t\t\t\t// Do not collect mutations from UIElements.\n\t\t\t\tif ( element && element.is( 'uiElement' ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( element && !this._isBogusBrMutation( mutation ) ) {\n\t\t\t\t\tmutatedElements.add( element );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Handle `characterData` mutations later, when we have the full list of nodes which changed structure.\n\t\tfor ( const mutation of domMutations ) {\n\t\t\tconst element = domConverter.mapDomToView( mutation.target );\n\n\t\t\t// Do not collect mutations from UIElements.\n\t\t\tif ( element && element.is( 'uiElement' ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( mutation.type === 'characterData' ) {\n\t\t\t\tconst text = domConverter.findCorrespondingViewText( mutation.target );\n\n\t\t\t\tif ( text && !mutatedElements.has( text.parent ) ) {\n\t\t\t\t\t// Use text as a key, for deduplication. If there will be another mutation on the same text element\n\t\t\t\t\t// we will have only one in the map.\n\t\t\t\t\tmutatedTexts.set( text, {\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\toldText: text.data,\n\t\t\t\t\t\tnewText: getDataWithoutFiller( mutation.target ),\n\t\t\t\t\t\tnode: text\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\t// When we added first letter to the text node which had only inline filler, for the DOM it is mutation\n\t\t\t\t// on text, but for the view, where filler text node did not existed, new text node was created, so we\n\t\t\t\t// need to fire 'children' mutation instead of 'text'.\n\t\t\t\telse if ( !text && startsWithFiller( mutation.target ) ) {\n\t\t\t\t\tmutatedElements.add( domConverter.mapDomToView( mutation.target.parentNode ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Now we build the list of mutations to fire and mark elements. We did not do it earlier to avoid marking the\n\t\t// same node multiple times in case of duplication.\n\n\t\t// List of mutations we will fire.\n\t\tconst viewMutations = [];\n\n\t\tfor ( const mutatedText of mutatedTexts.values() ) {\n\t\t\tthis.renderer.markToSync( 'text', mutatedText.node );\n\t\t\tviewMutations.push( mutatedText );\n\t\t}\n\n\t\tfor ( const viewElement of mutatedElements ) {\n\t\t\tconst domElement = domConverter.mapViewToDom( viewElement );\n\t\t\tconst viewChildren = Array.from( viewElement.getChildren() );\n\t\t\tconst newViewChildren = Array.from( domConverter.domChildrenToView( domElement, { withChildren: false } ) );\n\n\t\t\t// It may happen that as a result of many changes (sth was inserted and then removed),\n\t\t\t// both elements haven't really changed. #1031\n\t\t\tif ( !isEqualWith( viewChildren, newViewChildren, sameNodes ) ) {\n\t\t\t\tthis.renderer.markToSync( 'children', viewElement );\n\n\t\t\t\tviewMutations.push( {\n\t\t\t\t\ttype: 'children',\n\t\t\t\t\toldChildren: viewChildren,\n\t\t\t\t\tnewChildren: newViewChildren,\n\t\t\t\t\tnode: viewElement\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\t// Retrieve `domSelection` using `ownerDocument` of one of mutated nodes.\n\t\t// There should not be simultaneous mutation in multiple documents, so it's fine.\n\t\tconst domSelection = domMutations[ 0 ].target.ownerDocument.getSelection();\n\n\t\tlet viewSelection = null;\n\n\t\tif ( domSelection && domSelection.anchorNode ) {\n\t\t\t// If `domSelection` is inside a dom node that is already bound to a view node from view tree, get\n\t\t\t// corresponding selection in the view and pass it together with `viewMutations`. The `viewSelection` may\n\t\t\t// be used by features handling mutations.\n\t\t\t// Only one range is supported.\n\n\t\t\tconst viewSelectionAnchor = domConverter.domPositionToView( domSelection.anchorNode, domSelection.anchorOffset );\n\t\t\tconst viewSelectionFocus = domConverter.domPositionToView( domSelection.focusNode, domSelection.focusOffset );\n\n\t\t\t// Anchor and focus has to be properly mapped to view.\n\t\t\tif ( viewSelectionAnchor && viewSelectionFocus ) {\n\t\t\t\tviewSelection = new ViewSelection( viewSelectionAnchor );\n\t\t\t\tviewSelection.setFocus( viewSelectionFocus );\n\t\t\t}\n\t\t}\n\n\t\tthis.document.fire( 'mutations', viewMutations, viewSelection );\n\n\t\t// If nothing changes on `mutations` event, at this point we have \"dirty DOM\" (changed) and de-synched\n\t\t// view (which has not been changed). In order to \"reset DOM\" we render the view again.\n\t\tthis.view.forceRender();\n\n\t\tfunction sameNodes( child1, child2 ) {\n\t\t\t// First level of comparison (array of children vs array of children) – use the Lodash's default behavior.\n\t\t\tif ( Array.isArray( child1 ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Elements.\n\t\t\tif ( child1 === child2 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t// Texts.\n\t\t\telse if ( child1.is( 'text' ) && child2.is( 'text' ) ) {\n\t\t\t\treturn child1.data === child2.data;\n\t\t\t}\n\n\t\t\t// Not matching types.\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Checks if mutation was generated by the browser inserting bogus br on the end of the block element.\n\t * Such mutations are generated while pressing space or performing native spellchecker correction\n\t * on the end of the block element in Firefox browser.\n\t *\n\t * @private\n\t * @param {Object} mutation Native mutation object.\n\t * @returns {Boolean}\n\t */\n\t_isBogusBrMutation( mutation ) {\n\t\tlet addedNode = null;\n\n\t\t// Check if mutation added only one node on the end of its parent.\n\t\tif ( mutation.nextSibling === null && mutation.removedNodes.length === 0 && mutation.addedNodes.length == 1 ) {\n\t\t\taddedNode = this.domConverter.domToView( mutation.addedNodes[ 0 ], {\n\t\t\t\twithChildren: false\n\t\t\t} );\n\t\t}\n\n\t\treturn addedNode && addedNode.is( 'element', 'br' );\n\t}\n}\n\n/**\n * Fired when mutation occurred. If tree view is not changed on this event, DOM will be reverted to the state before\n * mutation, so all changes which should be applied, should be handled on this event.\n *\n * Introduced by {@link module:engine/view/observer/mutationobserver~MutationObserver}.\n *\n * Note that because {@link module:engine/view/observer/mutationobserver~MutationObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/mutationobserver~MutationObserver\n * @event module:engine/view/document~Document#event:mutations\n * @param {Array.<module:engine/view/observer/mutationobserver~MutatedText|module:engine/view/observer/mutationobserver~MutatedChildren>}\n * viewMutations Array of mutations.\n * For mutated texts it will be {@link module:engine/view/observer/mutationobserver~MutatedText} and for mutated elements it will be\n * {@link module:engine/view/observer/mutationobserver~MutatedChildren}. You can recognize the type based on the `type` property.\n * @param {module:engine/view/selection~Selection|null} viewSelection View selection that is a result of converting DOM selection to view.\n * Keep in\n * mind that the DOM selection is already \"updated\", meaning that it already acknowledges changes done in mutation.\n */\n\n/**\n * Mutation item for text.\n *\n * @see module:engine/view/document~Document#event:mutations\n * @see module:engine/view/observer/mutationobserver~MutatedChildren\n *\n * @typedef {Object} module:engine/view/observer/mutationobserver~MutatedText\n *\n * @property {String} type For text mutations it is always 'text'.\n * @property {module:engine/view/text~Text} node Mutated text node.\n * @property {String} oldText Old text.\n * @property {String} newText New text.\n */\n\n/**\n * Mutation item for child nodes.\n *\n * @see module:engine/view/document~Document#event:mutations\n * @see module:engine/view/observer/mutationobserver~MutatedText\n *\n * @typedef {Object} module:engine/view/observer/mutationobserver~MutatedChildren\n *\n * @property {String} type For child nodes mutations it is always 'children'.\n * @property {module:engine/view/element~Element} node Parent of the mutated children.\n * @property {Array.<module:engine/view/node~Node>} oldChildren Old child nodes.\n * @property {Array.<module:engine/view/node~Node>} newChildren New child nodes.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/domeventdata\n */\n\nimport { extend } from 'lodash-es';\n\n/**\n * Information about a DOM event in context of the {@link module:engine/view/document~Document}.\n * It wraps the native event, which usually should not be used as the wrapper contains\n * additional data (like key code for keyboard events).\n */\nexport default class DomEventData {\n\t/**\n\t * @param {module:engine/view/view~View} view The instance of the view controller.\n\t * @param {Event} domEvent The DOM event.\n\t * @param {Object} [additionalData] Additional properties that the instance should contain.\n\t */\n\tconstructor( view, domEvent, additionalData ) {\n\t\t/**\n\t\t * Instance of the view controller.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/view~View} module:engine/view/observer/observer~Observer.DomEvent#view\n\t\t */\n\t\tthis.view = view;\n\n\t\t/**\n\t\t * The instance of the document.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/document~Document} module:engine/view/observer/observer~Observer.DomEvent#document\n\t\t */\n\t\tthis.document = view.document;\n\n\t\t/**\n\t\t * The DOM event.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Event} module:engine/view/observer/observer~Observer.DomEvent#domEvent\n\t\t */\n\t\tthis.domEvent = domEvent;\n\n\t\t/**\n\t\t * The DOM target.\n\t\t *\n\t\t * @readonly\n\t\t * @member {HTMLElement} module:engine/view/observer/observer~Observer.DomEvent#target\n\t\t */\n\t\tthis.domTarget = domEvent.target;\n\n\t\textend( this, additionalData );\n\t}\n\n\t/**\n\t * The tree view element representing the target.\n\t *\n\t * @readonly\n\t * @type module:engine/view/element~Element\n\t */\n\tget target() {\n\t\treturn this.view.domConverter.mapDomToView( this.domTarget );\n\t}\n\n\t/**\n\t * Prevents the native's event default action.\n\t */\n\tpreventDefault() {\n\t\tthis.domEvent.preventDefault();\n\t}\n\n\t/**\n\t * Stops native event propagation.\n\t */\n\tstopPropagation() {\n\t\tthis.domEvent.stopPropagation();\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/domeventobserver\n */\n\nimport Observer from './observer';\nimport DomEventData from './domeventdata';\n\n/**\n * Base class for DOM event observers. This class handles\n * {@link module:engine/view/observer/observer~Observer#observe adding} listeners to DOM elements,\n * {@link module:engine/view/observer/observer~Observer#disable disabling} and\n * {@link module:engine/view/observer/observer~Observer#enable re-enabling} events.\n * Child class needs to define\n * {@link module:engine/view/observer/domeventobserver~DomEventObserver#domEventType DOM event type} and\n * {@link module:engine/view/observer/domeventobserver~DomEventObserver#onDomEvent callback}.\n *\n * For instance:\n *\n *\t\tclass ClickObserver extends DomEventObserver {\n *\t\t\t// It can also be defined as a normal property in the constructor.\n *\t\t\tget domEventType() {\n *\t\t\t\treturn 'click';\n *\t\t\t}\n *\n *\t\t\tonDomEvent( domEvent ) {\n *\t\t\t\tthis.fire( 'click', domEvent );\n *\t\t\t}\n *\t\t}\n *\n * @extends module:engine/view/observer/observer~Observer\n */\nexport default class DomEventObserver extends Observer {\n\t/**\n\t * Type of the DOM event the observer should listen on. Array of types can be defined\n\t * if the obsever should listen to multiple DOM events.\n\t *\n\t * @readonly\n\t * @member {String|Array.<String>} #domEventType\n\t */\n\n\t/**\n\t * Callback which should be called when the DOM event occurred. Note that the callback will not be called if\n\t * observer {@link #isEnabled is not enabled}.\n\t *\n\t * @see #domEventType\n\t * @abstract\n\t * @method #onDomEvent\n\t */\n\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\t/**\n\t\t * If set to `true` DOM events will be listened on the capturing phase.\n\t\t * Default value is `false`.\n\t\t *\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis.useCapture = false;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tobserve( domElement ) {\n\t\tconst types = typeof this.domEventType == 'string' ? [ this.domEventType ] : this.domEventType;\n\n\t\ttypes.forEach( type => {\n\t\t\tthis.listenTo( domElement, type, ( eventInfo, domEvent ) => {\n\t\t\t\tif ( this.isEnabled ) {\n\t\t\t\t\tthis.onDomEvent( domEvent );\n\t\t\t\t}\n\t\t\t}, { useCapture: this.useCapture } );\n\t\t} );\n\t}\n\n\t/**\n\t * Calls `Document#fire()` if observer {@link #isEnabled is enabled}.\n\t *\n\t * @see module:utils/emittermixin~EmitterMixin#fire\n\t * @param {String} eventType The event type (name).\n\t * @param {Event} domEvent The DOM event.\n\t * @param {Object} [additionalData] The additional data which should extend the\n\t * {@link module:engine/view/observer/domeventdata~DomEventData event data} object.\n\t */\n\tfire( eventType, domEvent, additionalData ) {\n\t\tif ( this.isEnabled ) {\n\t\t\tthis.document.fire( eventType, new DomEventData( this.view, domEvent, additionalData ) );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/keyobserver\n */\n\nimport DomEventObserver from './domeventobserver';\nimport { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';\n\n/**\n * Observer for events connected with pressing keyboard keys.\n *\n * Note that this observer is attached by the {@link module:engine/view/view~View} and is available by default.\n *\n * @extends module:engine/view/observer/domeventobserver~DomEventObserver\n */\nexport default class KeyObserver extends DomEventObserver {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tthis.domEventType = [ 'keydown', 'keyup' ];\n\t}\n\n\tonDomEvent( domEvt ) {\n\t\tthis.fire( domEvt.type, domEvt, {\n\t\t\tkeyCode: domEvt.keyCode,\n\n\t\t\taltKey: domEvt.altKey,\n\t\t\tctrlKey: domEvt.ctrlKey || domEvt.metaKey,\n\t\t\tshiftKey: domEvt.shiftKey,\n\n\t\t\tget keystroke() {\n\t\t\t\treturn getCode( this );\n\t\t\t}\n\t\t} );\n\t}\n}\n\n/**\n * Fired when a key has been pressed.\n *\n * Introduced by {@link module:engine/view/observer/keyobserver~KeyObserver}.\n *\n * Note that because {@link module:engine/view/observer/keyobserver~KeyObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/keyobserver~KeyObserver\n * @event module:engine/view/document~Document#event:keydown\n * @param {module:engine/view/observer/keyobserver~KeyEventData} keyEventData\n */\n\n/**\n * Fired when a key has been released.\n *\n * Introduced by {@link module:engine/view/observer/keyobserver~KeyObserver}.\n *\n * Note that because {@link module:engine/view/observer/keyobserver~KeyObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/keyobserver~KeyObserver\n * @event module:engine/view/document~Document#event:keyup\n * @param {module:engine/view/observer/keyobserver~KeyEventData} keyEventData\n */\n\n/**\n * The value of both events - {@link module:engine/view/document~Document#event:keydown} and\n * {@link module:engine/view/document~Document#event:keyup}.\n *\n * @class module:engine/view/observer/keyobserver~KeyEventData\n * @extends module:engine/view/observer/domeventdata~DomEventData\n * @implements module:utils/keyboard~KeystrokeInfo\n */\n\n/**\n * Code of the whole keystroke. See {@link module:utils/keyboard~getCode}.\n *\n * @readonly\n * @member {Number} module:engine/view/observer/keyobserver~KeyEventData#keystroke\n */\n","import root from './_root.js';\n\n/**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\nvar now = function() {\n return root.Date.now();\n};\n\nexport default now;\n","import baseGetTag from './_baseGetTag.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nexport default isSymbol;\n","import isObject from './isObject.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** Used to match leading and trailing whitespace. */\nvar reTrim = /^\\s+|\\s+$/g;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nexport default toNumber;\n","import isObject from './isObject.js';\nimport now from './now.js';\nimport toNumber from './toNumber.js';\n\n/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max,\n nativeMin = Math.min;\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\nfunction debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n timeWaiting = wait - timeSinceLastCall;\n\n return maxing\n ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n clearTimeout(timerId);\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n\nexport default debounce;\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/fakeselectionobserver\n */\n\nimport Observer from './observer';\nimport ViewSelection from '../selection';\nimport { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport { debounce } from 'lodash-es';\n\n/**\n * Fake selection observer class. If view selection is fake it is placed in dummy DOM container. This observer listens\n * on {@link module:engine/view/document~Document#event:keydown keydown} events and handles moving fake view selection to the correct place\n * if arrow keys are pressed.\n * Fires {@link module:engine/view/document~Document#event:selectionChange selectionChange event} simulating natural behaviour of\n * {@link module:engine/view/observer/selectionobserver~SelectionObserver SelectionObserver}.\n *\n * @extends module:engine/view/observer/observer~Observer\n */\nexport default class FakeSelectionObserver extends Observer {\n\t/**\n\t * Creates new FakeSelectionObserver instance.\n\t *\n\t * @param {module:engine/view/view~View} view\n\t */\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\t/**\n\t\t * Fires debounced event `selectionChangeDone`. It uses `lodash#debounce` method to delay function call.\n\t\t *\n\t\t * @private\n\t\t * @param {Object} data Selection change data.\n\t\t * @method #_fireSelectionChangeDoneDebounced\n\t\t */\n\t\tthis._fireSelectionChangeDoneDebounced = debounce( data => this.document.fire( 'selectionChangeDone', data ), 200 );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tobserve() {\n\t\tconst document = this.document;\n\n\t\tdocument.on( 'keydown', ( eventInfo, data ) => {\n\t\t\tconst selection = document.selection;\n\n\t\t\tif ( selection.isFake && _isArrowKeyCode( data.keyCode ) && this.isEnabled ) {\n\t\t\t\t// Prevents default key down handling - no selection change will occur.\n\t\t\t\tdata.preventDefault();\n\n\t\t\t\tthis._handleSelectionMove( data.keyCode );\n\t\t\t}\n\t\t}, { priority: 'lowest' } );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\tthis._fireSelectionChangeDoneDebounced.cancel();\n\t}\n\n\t/**\n\t * Handles collapsing view selection according to given key code. If left or up key is provided - new selection will be\n\t * collapsed to left. If right or down key is pressed - new selection will be collapsed to right.\n\t *\n\t * This method fires {@link module:engine/view/document~Document#event:selectionChange} and\n\t * {@link module:engine/view/document~Document#event:selectionChangeDone} events imitating behaviour of\n\t * {@link module:engine/view/observer/selectionobserver~SelectionObserver}.\n\t *\n\t * @private\n\t * @param {Number} keyCode\n\t * @fires module:engine/view/document~Document#event:selectionChange\n\t * @fires module:engine/view/document~Document#event:selectionChangeDone\n\t */\n\t_handleSelectionMove( keyCode ) {\n\t\tconst selection = this.document.selection;\n\t\tconst newSelection = new ViewSelection( selection.getRanges(), { backward: selection.isBackward, fake: false } );\n\n\t\t// Left or up arrow pressed - move selection to start.\n\t\tif ( keyCode == keyCodes.arrowleft || keyCode == keyCodes.arrowup ) {\n\t\t\tnewSelection.setTo( newSelection.getFirstPosition() );\n\t\t}\n\n\t\t// Right or down arrow pressed - move selection to end.\n\t\tif ( keyCode == keyCodes.arrowright || keyCode == keyCodes.arrowdown ) {\n\t\t\tnewSelection.setTo( newSelection.getLastPosition() );\n\t\t}\n\n\t\tconst data = {\n\t\t\toldSelection: selection,\n\t\t\tnewSelection,\n\t\t\tdomSelection: null\n\t\t};\n\n\t\t// Fire dummy selection change event.\n\t\tthis.document.fire( 'selectionChange', data );\n\n\t\t// Call` #_fireSelectionChangeDoneDebounced` every time when `selectionChange` event is fired.\n\t\t// This function is debounced what means that `selectionChangeDone` event will be fired only when\n\t\t// defined int the function time will elapse since the last time the function was called.\n\t\t// So `selectionChangeDone` will be fired when selection will stop changing.\n\t\tthis._fireSelectionChangeDoneDebounced( data );\n\t}\n}\n\n// Checks if one of the arrow keys is pressed.\n//\n// @private\n// @param {Number} keyCode\n// @returns {Boolean}\nfunction _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 * @license Copyright (c) 2003-2019, 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 engine/view/observer/selectionobserver\n */\n\n/* global setInterval, clearInterval */\n\nimport Observer from './observer';\nimport MutationObserver from './mutationobserver';\nimport { debounce } from 'lodash-es';\n\n/**\n * Selection observer class observes selection changes in the document. If selection changes on the document this\n * observer checks if there are any mutations and if DOM selection is different than the\n * {@link module:engine/view/document~Document#selection view selection}. Selection observer fires\n * {@link module:engine/view/document~Document#event:selectionChange} event only if selection change was the only change in the document\n * and DOM selection is different then the view selection.\n *\n * Note that this observer is attached by the {@link module:engine/view/view~View} and is available by default.\n *\n * @see module:engine/view/observer/mutationobserver~MutationObserver\n * @extends module:engine/view/observer/observer~Observer\n */\nexport default class SelectionObserver extends Observer {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\t/**\n\t\t * Instance of the mutation observer. Selection observer calls\n\t\t * {@link module:engine/view/observer/mutationobserver~MutationObserver#flush} to ensure that the mutations will be handled\n\t\t * before the {@link module:engine/view/document~Document#event:selectionChange} event is fired.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/observer/mutationobserver~MutationObserver}\n\t\t * module:engine/view/observer/selectionobserver~SelectionObserver#mutationObserver\n\t\t */\n\t\tthis.mutationObserver = view.getObserver( MutationObserver );\n\n\t\t/**\n\t\t * Reference to the view {@link module:engine/view/documentselection~DocumentSelection} object used to compare\n\t\t * new selection with it.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/documentselection~DocumentSelection}\n\t\t * module:engine/view/observer/selectionobserver~SelectionObserver#selection\n\t\t */\n\t\tthis.selection = this.document.selection;\n\n\t\t/* eslint-disable max-len */\n\t\t/**\n\t\t * Reference to the {@link module:engine/view/view~View#domConverter}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/domconverter~DomConverter} module:engine/view/observer/selectionobserver~SelectionObserver#domConverter\n\t\t */\n\t\t/* eslint-enable max-len */\n\t\tthis.domConverter = view.domConverter;\n\n\t\t/**\n\t\t * Set of documents which have added \"selectionchange\" listener to avoid adding listener twice to the same\n\t\t * document.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakSet.<Document>} module:engine/view/observer/selectionobserver~SelectionObserver#_documents\n\t\t */\n\t\tthis._documents = new WeakSet();\n\n\t\t/**\n\t\t * Fires debounced event `selectionChangeDone`. It uses `lodash#debounce` method to delay function call.\n\t\t *\n\t\t * @private\n\t\t * @param {Object} data Selection change data.\n\t\t * @method #_fireSelectionChangeDoneDebounced\n\t\t */\n\t\tthis._fireSelectionChangeDoneDebounced = debounce( data => this.document.fire( 'selectionChangeDone', data ), 200 );\n\n\t\tthis._clearInfiniteLoopInterval = setInterval( () => this._clearInfiniteLoop(), 1000 );\n\n\t\t/**\n\t\t * Private property to check if the code does not enter infinite loop.\n\t\t *\n\t\t * @private\n\t\t * @member {Number} module:engine/view/observer/selectionobserver~SelectionObserver#_loopbackCounter\n\t\t */\n\t\tthis._loopbackCounter = 0;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tobserve( domElement ) {\n\t\tconst domDocument = domElement.ownerDocument;\n\n\t\t// Add listener once per each document.\n\t\tif ( this._documents.has( domDocument ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.listenTo( domDocument, 'selectionchange', () => {\n\t\t\tthis._handleSelectionChange( domDocument );\n\t\t} );\n\n\t\tthis._documents.add( domDocument );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\tclearInterval( this._clearInfiniteLoopInterval );\n\t\tthis._fireSelectionChangeDoneDebounced.cancel();\n\t}\n\n\t/**\n\t * Selection change listener. {@link module:engine/view/observer/mutationobserver~MutationObserver#flush Flush} mutations, check if\n\t * selection changes and fires {@link module:engine/view/document~Document#event:selectionChange} event on every change\n\t * and {@link module:engine/view/document~Document#event:selectionChangeDone} when selection stop changing.\n\t *\n\t * @private\n\t * @param {Document} domDocument DOM document.\n\t */\n\t_handleSelectionChange( domDocument ) {\n\t\t// Selection is handled when document is not focused but is read-only. This is because in read-only\n\t\t// mode contenteditable is set as false and editor won't receive focus but we still need to know\n\t\t// selection position.\n\t\tif ( !this.isEnabled || ( !this.document.isFocused && !this.document.isReadOnly ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Ensure the mutation event will be before selection event on all browsers.\n\t\tthis.mutationObserver.flush();\n\n\t\t// If there were mutations then the view will be re-rendered by the mutation observer and selection\n\t\t// will be updated, so selections will equal and event will not be fired, as expected.\n\t\tconst domSelection = domDocument.defaultView.getSelection();\n\t\tconst newViewSelection = this.domConverter.domSelectionToView( domSelection );\n\n\t\tif ( this.selection.isEqual( newViewSelection ) && this.domConverter.isDomSelectionCorrect( domSelection ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Ensure we are not in the infinite loop (#400).\n\t\t// This counter is reset each second. 60 selection changes in 1 second is enough high number\n\t\t// to be very difficult (impossible) to achieve using just keyboard keys (during normal editor use).\n\t\tif ( ++this._loopbackCounter > 60 ) {\n\t\t\t// Selection change observer detected an infinite rendering loop.\n\t\t\t// Most probably you try to put the selection in the position which is not allowed\n\t\t\t// by the browser and browser fixes it automatically what causes `selectionchange` event on\n\t\t\t// which a loopback through a model tries to re-render the wrong selection and again.\n\t\t\t//\n\t\t\t// @if CK_DEBUG // console.warn( 'Selection change observer detected an infinite rendering loop.' );\n\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.selection.isSimilar( newViewSelection ) ) {\n\t\t\t// If selection was equal and we are at this point of algorithm, it means that it was incorrect.\n\t\t\t// Just re-render it, no need to fire any events, etc.\n\t\t\tthis.view.forceRender();\n\t\t} else {\n\t\t\tconst data = {\n\t\t\t\toldSelection: this.selection,\n\t\t\t\tnewSelection: newViewSelection,\n\t\t\t\tdomSelection\n\t\t\t};\n\n\t\t\t// Prepare data for new selection and fire appropriate events.\n\t\t\tthis.document.fire( 'selectionChange', data );\n\n\t\t\t// Call` #_fireSelectionChangeDoneDebounced` every time when `selectionChange` event is fired.\n\t\t\t// This function is debounced what means that `selectionChangeDone` event will be fired only when\n\t\t\t// defined int the function time will elapse since the last time the function was called.\n\t\t\t// So `selectionChangeDone` will be fired when selection will stop changing.\n\t\t\tthis._fireSelectionChangeDoneDebounced( data );\n\t\t}\n\t}\n\n\t/**\n\t * Clears `SelectionObserver` internal properties connected with preventing infinite loop.\n\t *\n\t * @protected\n\t */\n\t_clearInfiniteLoop() {\n\t\tthis._loopbackCounter = 0;\n\t}\n}\n\n/**\n * Fired when selection has changed. This event is fired only when the selection change was the only change that happened\n * in the document, and old selection is different then the new selection.\n *\n * Introduced by {@link module:engine/view/observer/selectionobserver~SelectionObserver}.\n *\n * Note that because {@link module:engine/view/observer/selectionobserver~SelectionObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/selectionobserver~SelectionObserver\n * @event module:engine/view/document~Document#event:selectionChange\n * @param {Object} data\n * @param {module:engine/view/documentselection~DocumentSelection} data.oldSelection Old View selection which is\n * {@link module:engine/view/document~Document#selection}.\n * @param {module:engine/view/selection~Selection} data.newSelection New View selection which is converted DOM selection.\n * @param {Selection} data.domSelection Native DOM selection.\n */\n\n/**\n * Fired when selection stops changing.\n *\n * Introduced by {@link module:engine/view/observer/selectionobserver~SelectionObserver}.\n *\n * Note that because {@link module:engine/view/observer/selectionobserver~SelectionObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/selectionobserver~SelectionObserver\n * @event module:engine/view/document~Document#event:selectionChangeDone\n * @param {Object} data\n * @param {module:engine/view/documentselection~DocumentSelection} data.oldSelection Old View selection which is\n * {@link module:engine/view/document~Document#selection}.\n * @param {module:engine/view/selection~Selection} data.newSelection New View selection which is converted DOM selection.\n * @param {Selection} data.domSelection Native DOM selection.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/focusobserver\n */\n\n/* globals setTimeout, clearTimeout */\n\nimport DomEventObserver from './domeventobserver';\n\n/**\n * {@link module:engine/view/document~Document#event:focus Focus}\n * and {@link module:engine/view/document~Document#event:blur blur} events observer.\n * Focus observer handle also {@link module:engine/view/rooteditableelement~RootEditableElement#isFocused isFocused} property of the\n * {@link module:engine/view/rooteditableelement~RootEditableElement root elements}.\n *\n * Note that this observer is attached by the {@link module:engine/view/view~View} and is available by default.\n *\n * @extends module:engine/view/observer/domeventobserver~DomEventObserver\n */\nexport default class FocusObserver extends DomEventObserver {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tthis.domEventType = [ 'focus', 'blur' ];\n\t\tthis.useCapture = true;\n\t\tconst document = this.document;\n\n\t\tdocument.on( 'focus', () => {\n\t\t\tdocument.isFocused = true;\n\n\t\t\t// Unfortunately native `selectionchange` event is fired asynchronously.\n\t\t\t// We need to wait until `SelectionObserver` handle the event and then render. Otherwise rendering will\n\t\t\t// overwrite new DOM selection with selection from the view.\n\t\t\t// See https://github.com/ckeditor/ckeditor5-engine/issues/795 for more details.\n\t\t\t// Long timeout is needed to solve #676 and https://github.com/ckeditor/ckeditor5-engine/issues/1157 issues.\n\t\t\tthis._renderTimeoutId = setTimeout( () => view.forceRender(), 50 );\n\t\t} );\n\n\t\tdocument.on( 'blur', ( evt, data ) => {\n\t\t\tconst selectedEditable = document.selection.editableElement;\n\n\t\t\tif ( selectedEditable === null || selectedEditable === data.target ) {\n\t\t\t\tdocument.isFocused = false;\n\n\t\t\t\t// Re-render the document to update view elements.\n\t\t\t\tview.forceRender();\n\t\t\t}\n\t\t} );\n\n\t\t/**\n\t\t * Identifier of the timeout currently used by focus listener to delay rendering execution.\n\t\t *\n\t\t * @private\n\t\t * @member {Number} #_renderTimeoutId\n\t\t */\n\t}\n\n\tonDomEvent( domEvent ) {\n\t\tthis.fire( domEvent.type, domEvent );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tif ( this._renderTimeoutId ) {\n\t\t\tclearTimeout( this._renderTimeoutId );\n\t\t}\n\n\t\tsuper.destroy();\n\t}\n}\n\n/**\n * Fired when one of the editables gets focus.\n *\n * Introduced by {@link module:engine/view/observer/focusobserver~FocusObserver}.\n *\n * Note that because {@link module:engine/view/observer/focusobserver~FocusObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/focusobserver~FocusObserver\n * @event module:engine/view/document~Document#event:focus\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n\n/**\n * Fired when one of the editables loses focus.\n *\n * Introduced by {@link module:engine/view/observer/focusobserver~FocusObserver}.\n *\n * Note that because {@link module:engine/view/observer/focusobserver~FocusObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/focusobserver~FocusObserver\n * @event module:engine/view/document~Document#event:blur\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/compositionobserver\n */\n\nimport DomEventObserver from './domeventobserver';\n\n/**\n * {@link module:engine/view/document~Document#event:compositionstart Compositionstart},\n * {@link module:engine/view/document~Document#event:compositionupdate compositionupdate} and\n * {@link module:engine/view/document~Document#event:compositionend compositionend} events observer.\n *\n * Note that this observer is attached by the {@link module:engine/view/view~View} and is available by default.\n *\n * @extends module:engine/view/observer/domeventobserver~DomEventObserver\n */\nexport default class CompositionObserver extends DomEventObserver {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tthis.domEventType = [ 'compositionstart', 'compositionupdate', 'compositionend' ];\n\t\tconst document = this.document;\n\n\t\tdocument.on( 'compositionstart', () => {\n\t\t\tdocument.isComposing = true;\n\t\t} );\n\n\t\tdocument.on( 'compositionend', () => {\n\t\t\tdocument.isComposing = false;\n\t\t} );\n\t}\n\n\tonDomEvent( domEvent ) {\n\t\tthis.fire( domEvent.type, domEvent );\n\t}\n}\n\n/**\n * Fired when composition starts inside one of the editables.\n *\n * Introduced by {@link module:engine/view/observer/compositionobserver~CompositionObserver}.\n *\n * Note that because {@link module:engine/view/observer/compositionobserver~CompositionObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/compositionobserver~CompositionObserver\n * @event module:engine/view/document~Document#event:compositionstart\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n\n/**\n * Fired when composition is updated inside one of the editables.\n *\n * Introduced by {@link module:engine/view/observer/compositionobserver~CompositionObserver}.\n *\n * Note that because {@link module:engine/view/observer/compositionobserver~CompositionObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/compositionobserver~CompositionObserver\n * @event module:engine/view/document~Document#event:compositionupdate\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n\n/**\n * Fired when composition ends inside one of the editables.\n *\n * Introduced by {@link module:engine/view/observer/compositionobserver~CompositionObserver}.\n *\n * Note that because {@link module:engine/view/observer/compositionobserver~CompositionObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/compositionobserver~CompositionObserver\n * @event module:engine/view/document~Document#event:compositionend\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n","/**\n * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md.\n */\n\n/**\n * @module engine/view/observer/inputobserver\n */\n\nimport DomEventObserver from './domeventobserver';\n\n/**\n * Observer for events connected with data input.\n *\n * Note that this observer is attached by the {@link module:engine/view/view~View} and is available by default.\n *\n * @extends module:engine/view/observer/domeventobserver~DomEventObserver\n */\nexport default class InputObserver extends DomEventObserver {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tthis.domEventType = [ 'beforeinput' ];\n\t}\n\n\tonDomEvent( domEvent ) {\n\t\tthis.fire( domEvent.type, domEvent );\n\t}\n}\n\n/**\n * Fired before browser inputs (or deletes) some data.\n *\n * This event is available only on browsers which support DOM `beforeinput` event.\n *\n * Introduced by {@link module:engine/view/observer/inputobserver~InputObserver}.\n *\n * Note that because {@link module:engine/view/observer/inputobserver~InputObserver} is attached by the\n * {@link module:engine/view/view~View} this event is available by default.\n *\n * @see module:engine/view/observer/inputobserver~InputObserver\n * @event module:engine/view/document~Document#event:beforeinput\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/isrange\n */\n\n/**\n * Checks if the object is a native DOM Range.\n *\n * @param {*} obj\n * @returns {Boolean}\n */\nexport default function isRange( obj ) {\n\treturn Object.prototype.toString.apply( obj ) == '[object Range]';\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/getborderwidths\n */\n\n/**\n * Returns an object containing CSS border widths of a specified HTML element.\n *\n * @param {HTMLElement} element An element which has CSS borders.\n * @returns {Object} An object containing `top`, `left`, `right` and `bottom` properties\n * with numerical values of the `border-[top,left,right,bottom]-width` CSS styles.\n */\nexport default function getBorderWidths( element ) {\n\t// Call getComputedStyle on the window the element document belongs to.\n\tconst style = element.ownerDocument.defaultView.getComputedStyle( element );\n\n\treturn {\n\t\ttop: parseInt( style.borderTopWidth, 10 ),\n\t\tright: parseInt( style.borderRightWidth, 10 ),\n\t\tbottom: parseInt( style.borderBottomWidth, 10 ),\n\t\tleft: parseInt( style.borderLeftWidth, 10 )\n\t};\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/rect\n */\n\nimport isRange from './isrange';\nimport isWindow from './iswindow';\nimport getBorderWidths from './getborderwidths';\nimport isText from './istext';\nimport { isElement } from 'lodash-es';\n\nconst rectProperties = [ 'top', 'right', 'bottom', 'left', 'width', 'height' ];\n\n/**\n * A helper class representing a `ClientRect` object, e.g. value returned by\n * the native `object.getBoundingClientRect()` method. Provides a set of methods\n * to manipulate the rect and compare it against other rect instances.\n */\nexport default class Rect {\n\t/**\n\t * Creates an instance of rect.\n\t *\n\t *\t\t// Rect of an HTMLElement.\n\t *\t\tconst rectA = new Rect( document.body );\n\t *\n\t *\t\t// Rect of a DOM Range.\n\t *\t\tconst rectB = new Rect( document.getSelection().getRangeAt( 0 ) );\n\t *\n\t *\t\t// Rect of a window (web browser viewport).\n\t *\t\tconst rectC = new Rect( window );\n\t *\n\t *\t\t// Rect out of an object.\n\t *\t\tconst rectD = new Rect( { top: 0, right: 10, bottom: 10, left: 0, width: 10, height: 10 } );\n\t *\n\t *\t\t// Rect out of another Rect instance.\n\t *\t\tconst rectE = new Rect( rectD );\n\t *\n\t *\t\t// Rect out of a ClientRect.\n\t *\t\tconst rectF = new Rect( document.body.getClientRects().item( 0 ) );\n\t *\n\t * **Note**: By default a rect of an HTML element includes its CSS borders and scrollbars (if any)\n\t * ant the rect of a `window` includes scrollbars too. Use {@link #excludeScrollbarsAndBorders}\n\t * to get the inner part of the rect.\n\t *\n\t * @param {HTMLElement|Range|Window|ClientRect|module:utils/dom/rect~Rect|Object} source A source object to create the rect.\n\t */\n\tconstructor( source ) {\n\t\tconst isSourceRange = isRange( source );\n\n\t\t/**\n\t\t * The object this rect is for.\n\t\t *\n\t\t * @protected\n\t\t * @readonly\n\t\t * @member {HTMLElement|Range|ClientRect|module:utils/dom/rect~Rect|Object} #_source\n\t\t */\n\t\tObject.defineProperty( this, '_source', {\n\t\t\t// If the source is a Rect instance, copy it's #_source.\n\t\t\tvalue: source._source || source,\n\t\t\twritable: true,\n\t\t\tenumerable: false\n\t\t} );\n\n\t\tif ( isElement( source ) || isSourceRange ) {\n\t\t\t// The `Rect` class depends on `getBoundingClientRect` and `getClientRects` DOM methods. If the source\n\t\t\t// of a rect in an HTML element or a DOM range but it does not belong to any rendered DOM tree, these methods\n\t\t\t// will fail to obtain the geometry and the rect instance makes little sense to the features using it.\n\t\t\t// To get rid of this warning make sure the source passed to the constructor is a descendant of `window.document.body`.\n\t\t\t// @if CK_DEBUG // const sourceNode = isSourceRange ? source.startContainer : source;\n\t\t\t// @if CK_DEBUG // if ( !sourceNode.ownerDocument || !sourceNode.ownerDocument.body.contains( sourceNode ) ) {\n\t\t\t// @if CK_DEBUG // \tconsole.warn(\n\t\t\t// @if CK_DEBUG // \t\t'rect-source-not-in-dom: The source of this rect does not belong to any rendered DOM tree.',\n\t\t\t// @if CK_DEBUG // \t\t{ source } );\n\t\t\t// @if CK_DEBUG // }\n\n\t\t\tif ( isSourceRange ) {\n\t\t\t\tcopyRectProperties( this, Rect.getDomRangeRects( source )[ 0 ] );\n\t\t\t} else {\n\t\t\t\tcopyRectProperties( this, source.getBoundingClientRect() );\n\t\t\t}\n\t\t} else if ( isWindow( source ) ) {\n\t\t\tconst { innerWidth, innerHeight } = source;\n\n\t\t\tcopyRectProperties( this, {\n\t\t\t\ttop: 0,\n\t\t\t\tright: innerWidth,\n\t\t\t\tbottom: innerHeight,\n\t\t\t\tleft: 0,\n\t\t\t\twidth: innerWidth,\n\t\t\t\theight: innerHeight\n\t\t\t} );\n\t\t} else {\n\t\t\tcopyRectProperties( this, source );\n\t\t}\n\n\t\t/**\n\t\t * The \"top\" value of the rect.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #top\n\t\t */\n\n\t\t/**\n\t\t * The \"right\" value of the rect.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #right\n\t\t */\n\n\t\t/**\n\t\t * The \"bottom\" value of the rect.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #bottom\n\t\t */\n\n\t\t/**\n\t\t * The \"left\" value of the rect.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #left\n\t\t */\n\n\t\t/**\n\t\t * The \"width\" value of the rect.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #width\n\t\t */\n\n\t\t/**\n\t\t * The \"height\" value of the rect.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #height\n\t\t */\n\t}\n\n\t/**\n\t * Returns a clone of the rect.\n\t *\n\t * @returns {module:utils/dom/rect~Rect} A cloned rect.\n\t */\n\tclone() {\n\t\treturn new Rect( this );\n\t}\n\n\t/**\n\t * Moves the rect so that its upper–left corner lands in desired `[ x, y ]` location.\n\t *\n\t * @param {Number} x Desired horizontal location.\n\t * @param {Number} y Desired vertical location.\n\t * @returns {module:utils/dom/rect~Rect} A rect which has been moved.\n\t */\n\tmoveTo( x, y ) {\n\t\tthis.top = y;\n\t\tthis.right = x + this.width;\n\t\tthis.bottom = y + this.height;\n\t\tthis.left = x;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Moves the rect in–place by a dedicated offset.\n\t *\n\t * @param {Number} x A horizontal offset.\n\t * @param {Number} y A vertical offset\n\t * @returns {module:utils/dom/rect~Rect} A rect which has been moved.\n\t */\n\tmoveBy( x, y ) {\n\t\tthis.top += y;\n\t\tthis.right += x;\n\t\tthis.left += x;\n\t\tthis.bottom += y;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns a new rect a a result of intersection with another rect.\n\t *\n\t * @param {module:utils/dom/rect~Rect} anotherRect\n\t * @returns {module:utils/dom/rect~Rect}\n\t */\n\tgetIntersection( anotherRect ) {\n\t\tconst rect = {\n\t\t\ttop: Math.max( this.top, anotherRect.top ),\n\t\t\tright: Math.min( this.right, anotherRect.right ),\n\t\t\tbottom: Math.min( this.bottom, anotherRect.bottom ),\n\t\t\tleft: Math.max( this.left, anotherRect.left )\n\t\t};\n\n\t\trect.width = rect.right - rect.left;\n\t\trect.height = rect.bottom - rect.top;\n\n\t\tif ( rect.width < 0 || rect.height < 0 ) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn new Rect( rect );\n\t\t}\n\t}\n\n\t/**\n\t * Returns the area of intersection with another rect.\n\t *\n\t * @param {module:utils/dom/rect~Rect} anotherRect [description]\n\t * @returns {Number} Area of intersection.\n\t */\n\tgetIntersectionArea( anotherRect ) {\n\t\tconst rect = this.getIntersection( anotherRect );\n\n\t\tif ( rect ) {\n\t\t\treturn rect.getArea();\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the area of the rect.\n\t *\n\t * @returns {Number}\n\t */\n\tgetArea() {\n\t\treturn this.width * this.height;\n\t}\n\n\t/**\n\t * Returns a new rect, a part of the original rect, which is actually visible to the user,\n\t * e.g. an original rect cropped by parent element rects which have `overflow` set in CSS\n\t * other than `\"visible\"`.\n\t *\n\t * If there's no such visible rect, which is when the rect is limited by one or many of\n\t * the ancestors, `null` is returned.\n\t *\n\t * @returns {module:utils/dom/rect~Rect|null} A visible rect instance or `null`, if there's none.\n\t */\n\tgetVisible() {\n\t\tconst source = this._source;\n\t\tlet visibleRect = this.clone();\n\n\t\t// There's no ancestor to crop <body> with the overflow.\n\t\tif ( !isBody( source ) ) {\n\t\t\tlet parent = source.parentNode || source.commonAncestorContainer;\n\n\t\t\t// Check the ancestors all the way up to the <body>.\n\t\t\twhile ( parent && !isBody( parent ) ) {\n\t\t\t\tconst parentRect = new Rect( parent );\n\t\t\t\tconst intersectionRect = visibleRect.getIntersection( parentRect );\n\n\t\t\t\tif ( intersectionRect ) {\n\t\t\t\t\tif ( intersectionRect.getArea() < visibleRect.getArea() ) {\n\t\t\t\t\t\t// Reduce the visible rect to the intersection.\n\t\t\t\t\t\tvisibleRect = intersectionRect;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// There's no intersection, the rect is completely invisible.\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tparent = parent.parentNode;\n\t\t\t}\n\t\t}\n\n\t\treturn visibleRect;\n\t}\n\n\t/**\n\t * Checks if all property values ({@link #top}, {@link #left}, {@link #right},\n\t * {@link #bottom}, {@link #width} and {@link #height}) are the equal in both rect\n\t * instances.\n\t *\n\t * @param {module:utils/dom/rect~Rect} rect A rect instance to compare with.\n\t * @returns {Boolean} `true` when Rects are equal. `false` otherwise.\n\t */\n\tisEqual( anotherRect ) {\n\t\tfor ( const prop of rectProperties ) {\n\t\t\tif ( this[ prop ] !== anotherRect[ prop ] ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Checks whether a rect fully contains another rect instance.\n\t *\n\t * @param {module:utils/dom/rect~Rect} anotherRect\n\t * @returns {Boolean} `true` if contains, `false` otherwise.\n\t */\n\tcontains( anotherRect ) {\n\t\tconst intersectRect = this.getIntersection( anotherRect );\n\n\t\treturn !!( intersectRect && intersectRect.isEqual( anotherRect ) );\n\t}\n\n\t/**\n\t * Excludes scrollbars and CSS borders from the rect.\n\t *\n\t * * Borders are removed when {@link #_source} is an HTML element.\n\t * * Scrollbars are excluded from HTML elements and the `window`.\n\t *\n\t * @returns {module:utils/dom/rect~Rect} A rect which has been updated.\n\t */\n\texcludeScrollbarsAndBorders() {\n\t\tconst source = this._source;\n\t\tlet scrollBarWidth, scrollBarHeight, direction;\n\n\t\tif ( isWindow( source ) ) {\n\t\t\tscrollBarWidth = source.innerWidth - source.document.documentElement.clientWidth;\n\t\t\tscrollBarHeight = source.innerHeight - source.document.documentElement.clientHeight;\n\t\t\tdirection = source.getComputedStyle( source.document.documentElement ).direction;\n\t\t} else {\n\t\t\tconst borderWidths = getBorderWidths( this._source );\n\n\t\t\tscrollBarWidth = source.offsetWidth - source.clientWidth - borderWidths.left - borderWidths.right;\n\t\t\tscrollBarHeight = source.offsetHeight - source.clientHeight - borderWidths.top - borderWidths.bottom;\n\t\t\tdirection = source.ownerDocument.defaultView.getComputedStyle( source ).direction;\n\n\t\t\tthis.left += borderWidths.left;\n\t\t\tthis.top += borderWidths.top;\n\t\t\tthis.right -= borderWidths.right;\n\t\t\tthis.bottom -= borderWidths.bottom;\n\t\t\tthis.width = this.right - this.left;\n\t\t\tthis.height = this.bottom - this.top;\n\t\t}\n\n\t\tthis.width -= scrollBarWidth;\n\n\t\tif ( direction === 'ltr' ) {\n\t\t\tthis.right -= scrollBarWidth;\n\t\t} else {\n\t\t\tthis.left += scrollBarWidth;\n\t\t}\n\n\t\tthis.height -= scrollBarHeight;\n\t\tthis.bottom -= scrollBarHeight;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Returns an array of rects of the given native DOM Range.\n\t *\n\t * @param {Range} range A native DOM range.\n\t * @returns {Array.<module:utils/dom/rect~Rect>} DOM Range rects.\n\t */\n\tstatic getDomRangeRects( range ) {\n\t\tconst rects = [];\n\t\t// Safari does not iterate over ClientRectList using for...of loop.\n\t\tconst clientRects = Array.from( range.getClientRects() );\n\n\t\tif ( clientRects.length ) {\n\t\t\tfor ( const rect of clientRects ) {\n\t\t\t\trects.push( new Rect( rect ) );\n\t\t\t}\n\t\t}\n\t\t// If there's no client rects for the Range, use parent container's bounding rect\n\t\t// instead and adjust rect's width to simulate the actual geometry of such range.\n\t\t// https://github.com/ckeditor/ckeditor5-utils/issues/153\n\t\t// https://github.com/ckeditor/ckeditor5-ui/issues/317\n\t\telse {\n\t\t\tlet startContainer = range.startContainer;\n\n\t\t\tif ( isText( startContainer ) ) {\n\t\t\t\tstartContainer = startContainer.parentNode;\n\t\t\t}\n\n\t\t\tconst rect = new Rect( startContainer.getBoundingClientRect() );\n\t\t\trect.right = rect.left;\n\t\t\trect.width = 0;\n\n\t\t\trects.push( rect );\n\t\t}\n\n\t\treturn rects;\n\t}\n}\n\n// Acquires all the rect properties from the passed source.\n//\n// @private\n// @param {module:utils/dom/rect~Rect} rect\n// @param {ClientRect|module:utils/dom/rect~Rect|Object} source\nfunction copyRectProperties( rect, source ) {\n\tfor ( const p of rectProperties ) {\n\t\trect[ p ] = source[ p ];\n\t}\n}\n\n// Checks if provided object is a <body> HTML element.\n//\n// @private\n// @param {HTMLElement|Range} elementOrRange\n// @returns {Boolean}\nfunction isBody( elementOrRange ) {\n\tif ( !isElement( elementOrRange ) ) {\n\t\treturn false;\n\t}\n\n\treturn elementOrRange === elementOrRange.ownerDocument.body;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/scroll\n */\n\nimport isRange from './isrange';\nimport Rect from './rect';\nimport isText from './istext';\n\nconst utils = {};\n\n/**\n * Makes any page `HTMLElement` or `Range` (`target`) visible inside the browser viewport.\n * This helper will scroll all `target` ancestors and the web browser viewport to reveal the target to\n * the user. If the `target` is already visible, nothing will happen.\n *\n * @param {HTMLElement|Range} options.target A target, which supposed to become visible to the user.\n * @param {Number} [options.viewportOffset] An offset from the edge of the viewport (in pixels)\n * the `target` will be moved by when the viewport is scrolled. It enhances the user experience\n * by keeping the `target` some distance from the edge of the viewport and thus making it easier to\n * read or edit by the user.\n */\nexport function scrollViewportToShowTarget( { target, viewportOffset = 0 } ) {\n\tconst targetWindow = getWindow( target );\n\tlet currentWindow = targetWindow;\n\tlet currentFrame = null;\n\n\t// Iterate over all windows, starting from target's parent window up to window#top.\n\twhile ( currentWindow ) {\n\t\tlet firstAncestorToScroll;\n\n\t\t// Let's scroll target's ancestors first to reveal it. Then, once the ancestor scrolls\n\t\t// settled down, the algorithm can eventually scroll the viewport of the current window.\n\t\t//\n\t\t// Note: If the current window is target's **original** window (e.g. the first one),\n\t\t// start scrolling the closest parent of the target. If not, scroll the closest parent\n\t\t// of an iframe that resides in the current window.\n\t\tif ( currentWindow == targetWindow ) {\n\t\t\tfirstAncestorToScroll = getParentElement( target );\n\t\t} else {\n\t\t\tfirstAncestorToScroll = getParentElement( currentFrame );\n\t\t}\n\n\t\t// Scroll the target's ancestors first. Once done, scrolling the viewport is easy.\n\t\tscrollAncestorsToShowRect( firstAncestorToScroll, () => {\n\t\t\t// Note: If the target does not belong to the current window **directly**,\n\t\t\t// i.e. it resides in an iframe belonging to the window, obtain the target's rect\n\t\t\t// in the coordinates of the current window. By default, a Rect returns geometry\n\t\t\t// relative to the current window's viewport. To make it work in a parent window,\n\t\t\t// it must be shifted.\n\t\t\treturn getRectRelativeToWindow( target, currentWindow );\n\t\t} );\n\n\t\t// Obtain the rect of the target after it has been scrolled within its ancestors.\n\t\t// It's time to scroll the viewport.\n\t\tconst targetRect = getRectRelativeToWindow( target, currentWindow );\n\n\t\tscrollWindowToShowRect( currentWindow, targetRect, viewportOffset );\n\n\t\tif ( currentWindow.parent != currentWindow ) {\n\t\t\t// Keep the reference to the <iframe> element the \"previous current window\" was\n\t\t\t// rendered within. It will be useful to re–calculate the rect of the target\n\t\t\t// in the parent window's relative geometry. The target's rect must be shifted\n\t\t\t// by it's iframe's position.\n\t\t\tcurrentFrame = currentWindow.frameElement;\n\t\t\tcurrentWindow = currentWindow.parent;\n\n\t\t\t// If the current window has some parent but frameElement is inaccessible, then they have\n\t\t\t// different domains/ports and, due to security reasons, accessing and scrolling\n\t\t\t// the parent window won't be possible.\n\t\t\t// See https://github.com/ckeditor/ckeditor5/issues/930.\n\t\t\tif ( !currentFrame ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tcurrentWindow = null;\n\t\t}\n\t}\n}\n\n/**\n * Makes any page `HTMLElement` or `Range` (target) visible within its scrollable ancestors,\n * e.g. if they have `overflow: scroll` CSS style.\n *\n * @param {HTMLElement|Range} target A target, which supposed to become visible to the user.\n */\nexport function scrollAncestorsToShowTarget( target ) {\n\tconst targetParent = getParentElement( target );\n\n\tscrollAncestorsToShowRect( targetParent, () => {\n\t\treturn new Rect( target );\n\t} );\n}\n\n// TODO: Using a property value shorthand in the top of the file\n// causes JSDoc to throw errors. See https://github.com/cksource/docs-builder/issues/75.\nObject.assign( utils, {\n\tscrollViewportToShowTarget,\n\tscrollAncestorsToShowTarget\n} );\n\n// Makes a given rect visible within its parent window.\n//\n// Note: Avoid the situation where the caret is still in the viewport, but totally\n// at the edge of it. In such situation, if it moved beyond the viewport in the next\n// action e.g. after paste, the scrolling would move it to the viewportOffset level\n// and it all would look like the caret visually moved up/down:\n//\n// 1.\n//\t\t| foo[]\n//\t\t| <--- N px of space below the caret\n//\t\t+---------------------------------...\n//\n// 2. *paste*\n// 3.\n//\t\t|\n//\t\t|\n//\t\t+-foo-----------------------------...\n//\t\t bar[] <--- caret below viewport, scrolling...\n//\n// 4. *scrolling*\n// 5.\n//\t\t|\n//\t\t| foo\n//\t\t| bar[] <--- caret precisely at the edge\n//\t\t+---------------------------------...\n//\n// To prevent this, this method checks the rects moved by the viewportOffset to cover\n// the upper/lower edge of the viewport. It makes sure if the action repeats, there's\n// no twitching – it's a purely visual improvement:\n//\n// 5. (after fix)\n//\t\t|\n//\t\t| foo\n//\t\t| bar[]\n//\t\t| <--- N px of space below the caret\n//\t\t+---------------------------------...\n//\n// @private\n// @param {Window} window A window which is scrolled to reveal the rect.\n// @param {module:utils/dom/rect~Rect} rect A rect which is to be revealed.\n// @param {Number} viewportOffset See scrollViewportToShowTarget.\nfunction scrollWindowToShowRect( window, rect, viewportOffset ) {\n\tconst targetShiftedDownRect = rect.clone().moveBy( 0, viewportOffset );\n\tconst targetShiftedUpRect = rect.clone().moveBy( 0, -viewportOffset );\n\tconst viewportRect = new Rect( window ).excludeScrollbarsAndBorders();\n\n\tconst rects = [ targetShiftedUpRect, targetShiftedDownRect ];\n\n\tif ( !rects.every( rect => viewportRect.contains( rect ) ) ) {\n\t\tlet { scrollX, scrollY } = window;\n\n\t\tif ( isAbove( targetShiftedUpRect, viewportRect ) ) {\n\t\t\tscrollY -= viewportRect.top - rect.top + viewportOffset;\n\t\t} else if ( isBelow( targetShiftedDownRect, viewportRect ) ) {\n\t\t\tscrollY += rect.bottom - viewportRect.bottom + viewportOffset;\n\t\t}\n\n\t\t// TODO: Web browsers scroll natively to place the target in the middle\n\t\t// of the viewport. It's not a very popular case, though.\n\t\tif ( isLeftOf( rect, viewportRect ) ) {\n\t\t\tscrollX -= viewportRect.left - rect.left + viewportOffset;\n\t\t} else if ( isRightOf( rect, viewportRect ) ) {\n\t\t\tscrollX += rect.right - viewportRect.right + viewportOffset;\n\t\t}\n\n\t\twindow.scrollTo( scrollX, scrollY );\n\t}\n}\n\n// Recursively scrolls element ancestors to visually reveal a rect.\n//\n// @private\n// @param {HTMLElement} A parent The first ancestors to start scrolling.\n// @param {Function} getRect A function which returns the Rect, which is to be revealed.\nfunction scrollAncestorsToShowRect( parent, getRect ) {\n\tconst parentWindow = getWindow( parent );\n\tlet parentRect, targetRect;\n\n\twhile ( parent != parentWindow.document.body ) {\n\t\ttargetRect = getRect();\n\t\tparentRect = new Rect( parent ).excludeScrollbarsAndBorders();\n\n\t\tif ( !parentRect.contains( targetRect ) ) {\n\t\t\tif ( isAbove( targetRect, parentRect ) ) {\n\t\t\t\tparent.scrollTop -= parentRect.top - targetRect.top;\n\t\t\t} else if ( isBelow( targetRect, parentRect ) ) {\n\t\t\t\tparent.scrollTop += targetRect.bottom - parentRect.bottom;\n\t\t\t}\n\n\t\t\tif ( isLeftOf( targetRect, parentRect ) ) {\n\t\t\t\tparent.scrollLeft -= parentRect.left - targetRect.left;\n\t\t\t} else if ( isRightOf( targetRect, parentRect ) ) {\n\t\t\t\tparent.scrollLeft += targetRect.right - parentRect.right;\n\t\t\t}\n\t\t}\n\n\t\tparent = parent.parentNode;\n\t}\n}\n\n// Determines if a given `Rect` extends beyond the bottom edge of the second `Rect`.\n//\n// @private\n// @param {module:utils/dom/rect~Rect} firstRect\n// @param {module:utils/dom/rect~Rect} secondRect\nfunction isBelow( firstRect, secondRect ) {\n\treturn firstRect.bottom > secondRect.bottom;\n}\n\n// Determines if a given `Rect` extends beyond the top edge of the second `Rect`.\n//\n// @private\n// @param {module:utils/dom/rect~Rect} firstRect\n// @param {module:utils/dom/rect~Rect} secondRect\nfunction isAbove( firstRect, secondRect ) {\n\treturn firstRect.top < secondRect.top;\n}\n\n// Determines if a given `Rect` extends beyond the left edge of the second `Rect`.\n//\n// @private\n// @param {module:utils/dom/rect~Rect} firstRect\n// @param {module:utils/dom/rect~Rect} secondRect\nfunction isLeftOf( firstRect, secondRect ) {\n\treturn firstRect.left < secondRect.left;\n}\n\n// Determines if a given `Rect` extends beyond the right edge of the second `Rect`.\n//\n// @private\n// @param {module:utils/dom/rect~Rect} firstRect\n// @param {module:utils/dom/rect~Rect} secondRect\nfunction isRightOf( firstRect, secondRect ) {\n\treturn firstRect.right > secondRect.right;\n}\n\n// Returns the closest window of an element or range.\n//\n// @private\n// @param {HTMLElement|Range} firstRect\n// @returns {Window}\nfunction getWindow( elementOrRange ) {\n\tif ( isRange( elementOrRange ) ) {\n\t\treturn elementOrRange.startContainer.ownerDocument.defaultView;\n\t} else {\n\t\treturn elementOrRange.ownerDocument.defaultView;\n\t}\n}\n\n// Returns the closest parent of an element or DOM range.\n//\n// @private\n// @param {HTMLElement|Range} firstRect\n// @returns {HTMLelement}\nfunction getParentElement( elementOrRange ) {\n\tif ( isRange( elementOrRange ) ) {\n\t\tlet parent = elementOrRange.commonAncestorContainer;\n\n\t\t// If a Range is attached to the Text, use the closest element ancestor.\n\t\tif ( isText( parent ) ) {\n\t\t\tparent = parent.parentNode;\n\t\t}\n\n\t\treturn parent;\n\t} else {\n\t\treturn elementOrRange.parentNode;\n\t}\n}\n\n// Returns the rect of an element or range residing in an iframe.\n// The result rect is relative to the geometry of the passed window instance.\n//\n// @private\n// @param {HTMLElement|Range} target Element or range which rect should be returned.\n// @param {Window} relativeWindow A window the rect should be relative to.\n// @returns {module:utils/dom/rect~Rect}\nfunction getRectRelativeToWindow( target, relativeWindow ) {\n\tconst targetWindow = getWindow( target );\n\tconst rect = new Rect( target );\n\n\tif ( targetWindow === relativeWindow ) {\n\t\treturn rect;\n\t} else {\n\t\tlet currentWindow = targetWindow;\n\n\t\twhile ( currentWindow != relativeWindow ) {\n\t\t\tconst frame = currentWindow.frameElement;\n\t\t\tconst frameRect = new Rect( frame ).excludeScrollbarsAndBorders();\n\n\t\t\trect.moveBy( frameRect.left, frameRect.top );\n\n\t\t\tcurrentWindow = currentWindow.parent;\n\t\t}\n\t}\n\n\treturn rect;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/view\n */\n\nimport Document from './document';\nimport DowncastWriter from './downcastwriter';\nimport Renderer from './renderer';\nimport DomConverter from './domconverter';\nimport Position from './position';\nimport Range from './range';\nimport Selection from './selection';\n\nimport MutationObserver from './observer/mutationobserver';\nimport KeyObserver from './observer/keyobserver';\nimport FakeSelectionObserver from './observer/fakeselectionobserver';\nimport SelectionObserver from './observer/selectionobserver';\nimport FocusObserver from './observer/focusobserver';\nimport CompositionObserver from './observer/compositionobserver';\nimport InputObserver from './observer/inputobserver';\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport { scrollViewportToShowTarget } from '@ckeditor/ckeditor5-utils/src/dom/scroll';\nimport { injectUiElementHandling } from './uielement';\nimport { injectQuirksHandling } from './filler';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\n/**\n * Editor's view controller class. Its main responsibility is DOM - View management for editing purposes, to provide\n * abstraction over the DOM structure and events and hide all browsers quirks.\n *\n * View controller renders view document to DOM whenever view structure changes. To determine when view can be rendered,\n * all changes need to be done using the {@link module:engine/view/view~View#change} method, using\n * {@link module:engine/view/downcastwriter~DowncastWriter}:\n *\n *\t\tview.change( writer => {\n *\t\t\twriter.insert( position, writer.createText( 'foo' ) );\n *\t\t} );\n *\n * View controller also register {@link module:engine/view/observer/observer~Observer observers} which observes changes\n * on DOM and fire events on the {@link module:engine/view/document~Document Document}.\n * Note that the following observers are added by the class constructor and are always available:\n *\n * * {@link module:engine/view/observer/mutationobserver~MutationObserver},\n * * {@link module:engine/view/observer/selectionobserver~SelectionObserver},\n * * {@link module:engine/view/observer/focusobserver~FocusObserver},\n * * {@link module:engine/view/observer/keyobserver~KeyObserver},\n * * {@link module:engine/view/observer/fakeselectionobserver~FakeSelectionObserver}.\n * * {@link module:engine/view/observer/compositionobserver~CompositionObserver}.\n *\n * This class also {@link module:engine/view/view~View#attachDomRoot binds the DOM and the view elements}.\n *\n * If you do not need full a DOM - view management, and only want to transform a tree of view elements to a tree of DOM\n * elements you do not need this controller. You can use the {@link module:engine/view/domconverter~DomConverter DomConverter} instead.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class View {\n\tconstructor() {\n\t\t/**\n\t\t * Instance of the {@link module:engine/view/document~Document} associated with this view controller.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/view/document~Document}\n\t\t */\n\t\tthis.document = new Document();\n\n\t\t/**\n\t\t * Instance of the {@link module:engine/view/domconverter~DomConverter domConverter} used by\n\t\t * {@link module:engine/view/view~View#_renderer renderer}\n\t\t * and {@link module:engine/view/observer/observer~Observer observers}.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/view/domconverter~DomConverter}\n\t\t */\n\t\tthis.domConverter = new DomConverter();\n\n\t\t/**\n\t\t * Roots of the DOM tree. Map on the `HTMLElement`s with roots names as keys.\n\t\t *\n\t\t * @readonly\n\t\t * @type {Map.<String, HTMLElement>}\n\t\t */\n\t\tthis.domRoots = new Map();\n\n\t\t/**\n\t\t * Used to prevent calling {@link #forceRender} and {@link #change} during rendering view to the DOM.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} #isRenderingInProgress\n\t\t */\n\t\tthis.set( 'isRenderingInProgress', false );\n\n\t\t/**\n\t\t * Instance of the {@link module:engine/view/renderer~Renderer renderer}.\n\t\t *\n\t\t * @protected\n\t\t * @type {module:engine/view/renderer~Renderer}\n\t\t */\n\t\tthis._renderer = new Renderer( this.domConverter, this.document.selection );\n\t\tthis._renderer.bind( 'isFocused' ).to( this.document );\n\n\t\t/**\n\t\t * A DOM root attributes cache. It saves the initial values of DOM root attributes before the DOM element\n\t\t * is {@link module:engine/view/view~View#attachDomRoot attached} to the view so later on, when\n\t\t * the view is destroyed ({@link module:engine/view/view~View#detachDomRoot}), they can be easily restored.\n\t\t * This way, the DOM element can go back to the (clean) state as if the editing view never used it.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakMap.<HTMLElement,Object>}\n\t\t */\n\t\tthis._initialDomRootAttributes = new WeakMap();\n\n\t\t/**\n\t\t * Map of registered {@link module:engine/view/observer/observer~Observer observers}.\n\t\t *\n\t\t * @private\n\t\t * @type {Map.<Function, module:engine/view/observer/observer~Observer>}\n\t\t */\n\t\tthis._observers = new Map();\n\n\t\t/**\n\t\t * Is set to `true` when {@link #change view changes} are currently in progress.\n\t\t *\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._ongoingChange = false;\n\n\t\t/**\n\t\t * Used to prevent calling {@link #forceRender} and {@link #change} during rendering view to the DOM.\n\t\t *\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._postFixersInProgress = false;\n\n\t\t/**\n\t\t * Internal flag to temporary disable rendering. See the usage in the {@link #_disableRendering}.\n\t\t *\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._renderingDisabled = false;\n\n\t\t/**\n\t\t * Internal flag that disables rendering when there are no changes since the last rendering.\n\t\t * It stores information about changed selection and changed elements from attached document roots.\n\t\t *\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._hasChangedSinceTheLastRendering = false;\n\n\t\t/**\n\t\t * DowncastWriter instance used in {@link #change change method} callbacks.\n\t\t *\n\t\t * @private\n\t\t * @type {module:engine/view/downcastwriter~DowncastWriter}\n\t\t */\n\t\tthis._writer = new DowncastWriter( this.document );\n\n\t\t// Add default observers.\n\t\tthis.addObserver( MutationObserver );\n\t\tthis.addObserver( SelectionObserver );\n\t\tthis.addObserver( FocusObserver );\n\t\tthis.addObserver( KeyObserver );\n\t\tthis.addObserver( FakeSelectionObserver );\n\t\tthis.addObserver( CompositionObserver );\n\n\t\tif ( env.isAndroid ) {\n\t\t\tthis.addObserver( InputObserver );\n\t\t}\n\n\t\t// Inject quirks handlers.\n\t\tinjectQuirksHandling( this );\n\t\tinjectUiElementHandling( this );\n\n\t\t// Use 'normal' priority so that rendering is performed as first when using that priority.\n\t\tthis.on( 'render', () => {\n\t\t\tthis._render();\n\n\t\t\t// Informs that layout has changed after render.\n\t\t\tthis.document.fire( 'layoutChanged' );\n\n\t\t\t// Reset the `_hasChangedSinceTheLastRendering` flag after rendering.\n\t\t\tthis._hasChangedSinceTheLastRendering = false;\n\t\t} );\n\n\t\t// Listen to the document selection changes directly.\n\t\tthis.listenTo( this.document.selection, 'change', () => {\n\t\t\tthis._hasChangedSinceTheLastRendering = true;\n\t\t} );\n\t}\n\n\t/**\n\t * Attaches a DOM root element to the view element and enable all observers on that element.\n\t * Also {@link module:engine/view/renderer~Renderer#markToSync mark element} to be synchronized\n\t * with the view what means that all child nodes will be removed and replaced with content of the view root.\n\t *\n\t * This method also will change view element name as the same as tag name of given dom root.\n\t * Name is always transformed to lower case.\n\t *\n\t * **Note:** Use {@link #detachDomRoot `detachDomRoot()`} to revert this action.\n\t *\n\t * @param {Element} domRoot DOM root element.\n\t * @param {String} [name='main'] Name of the root.\n\t */\n\tattachDomRoot( domRoot, name = 'main' ) {\n\t\tconst viewRoot = this.document.getRoot( name );\n\n\t\t// Set view root name the same as DOM root tag name.\n\t\tviewRoot._name = domRoot.tagName.toLowerCase();\n\n\t\tconst initialDomRootAttributes = {};\n\n\t\t// 1. Copy and cache the attributes to remember the state of the element before attaching.\n\t\t// The cached attributes will be restored in detachDomRoot() so the element goes to the\n\t\t// clean state as if the editing view never used it.\n\t\t// 2. Apply the attributes using the view writer, so they all go under the control of the engine.\n\t\t// The editing view takes over the attribute management completely because various\n\t\t// features (e.g. addPlaceholder()) require dynamic changes of those attributes and they\n\t\t// cannot be managed by the engine and the UI library at the same time.\n\t\tfor ( const { name, value } of Array.from( domRoot.attributes ) ) {\n\t\t\tinitialDomRootAttributes[ name ] = value;\n\n\t\t\t// Do not use writer.setAttribute() for the class attribute. The EditableUIView class\n\t\t\t// and its descendants could have already set some using the writer.addClass() on the view\n\t\t\t// document root. They haven't been rendered yet so they are not present in the DOM root.\n\t\t\t// Using writer.setAttribute( 'class', ... ) would override them completely.\n\t\t\tif ( name === 'class' ) {\n\t\t\t\tthis._writer.addClass( value.split( ' ' ), viewRoot );\n\t\t\t} else {\n\t\t\t\tthis._writer.setAttribute( name, value, viewRoot );\n\t\t\t}\n\t\t}\n\n\t\tthis._initialDomRootAttributes.set( domRoot, initialDomRootAttributes );\n\n\t\tconst updateContenteditableAttribute = () => {\n\t\t\tthis._writer.setAttribute( 'contenteditable', !viewRoot.isReadOnly, viewRoot );\n\n\t\t\tif ( viewRoot.isReadOnly ) {\n\t\t\t\tthis._writer.addClass( 'ck-read-only', viewRoot );\n\t\t\t} else {\n\t\t\t\tthis._writer.removeClass( 'ck-read-only', viewRoot );\n\t\t\t}\n\t\t};\n\n\t\t// Set initial value.\n\t\tupdateContenteditableAttribute();\n\n\t\tthis.domRoots.set( name, domRoot );\n\t\tthis.domConverter.bindElements( domRoot, viewRoot );\n\t\tthis._renderer.markToSync( 'children', viewRoot );\n\t\tthis._renderer.markToSync( 'attributes', viewRoot );\n\t\tthis._renderer.domDocuments.add( domRoot.ownerDocument );\n\n\t\tviewRoot.on( 'change:children', ( evt, node ) => this._renderer.markToSync( 'children', node ) );\n\t\tviewRoot.on( 'change:attributes', ( evt, node ) => this._renderer.markToSync( 'attributes', node ) );\n\t\tviewRoot.on( 'change:text', ( evt, node ) => this._renderer.markToSync( 'text', node ) );\n\t\tviewRoot.on( 'change:isReadOnly', () => this.change( updateContenteditableAttribute ) );\n\n\t\tviewRoot.on( 'change', () => {\n\t\t\tthis._hasChangedSinceTheLastRendering = true;\n\t\t} );\n\n\t\tfor ( const observer of this._observers.values() ) {\n\t\t\tobserver.observe( domRoot, name );\n\t\t}\n\t}\n\n\t/**\n\t * Detaches a DOM root element from the view element and restores its attributes to the state before\n\t * {@link #attachDomRoot `attachDomRoot()`}.\n\t *\n\t * @param {String} name Name of the root to detach.\n\t */\n\tdetachDomRoot( name ) {\n\t\tconst domRoot = this.domRoots.get( name );\n\n\t\t// Remove all root attributes so the DOM element is \"bare\".\n\t\tArray.from( domRoot.attributes ).forEach( ( { name } ) => domRoot.removeAttribute( name ) );\n\n\t\tconst initialDomRootAttributes = this._initialDomRootAttributes.get( domRoot );\n\n\t\t// Revert all view root attributes back to the state before attachDomRoot was called.\n\t\tfor ( const attribute in initialDomRootAttributes ) {\n\t\t\tdomRoot.setAttribute( attribute, initialDomRootAttributes[ attribute ] );\n\t\t}\n\n\t\tthis.domRoots.delete( name );\n\t\tthis.domConverter.unbindDomElement( domRoot );\n\t}\n\n\t/**\n\t * Gets DOM root element.\n\t *\n\t * @param {String} [name='main'] Name of the root.\n\t * @returns {Element} DOM root element instance.\n\t */\n\tgetDomRoot( name = 'main' ) {\n\t\treturn this.domRoots.get( name );\n\t}\n\n\t/**\n\t * Creates observer of the given type if not yet created, {@link module:engine/view/observer/observer~Observer#enable enables} it\n\t * and {@link module:engine/view/observer/observer~Observer#observe attaches} to all existing and future\n\t * {@link #domRoots DOM roots}.\n\t *\n\t * Note: Observers are recognized by their constructor (classes). A single observer will be instantiated and used only\n\t * when registered for the first time. This means that features and other components can register a single observer\n\t * multiple times without caring whether it has been already added or not.\n\t *\n\t * @param {Function} Observer The constructor of an observer to add.\n\t * Should create an instance inheriting from {@link module:engine/view/observer/observer~Observer}.\n\t * @returns {module:engine/view/observer/observer~Observer} Added observer instance.\n\t */\n\taddObserver( Observer ) {\n\t\tlet observer = this._observers.get( Observer );\n\n\t\tif ( observer ) {\n\t\t\treturn observer;\n\t\t}\n\n\t\tobserver = new Observer( this );\n\n\t\tthis._observers.set( Observer, observer );\n\n\t\tfor ( const [ name, domElement ] of this.domRoots ) {\n\t\t\tobserver.observe( domElement, name );\n\t\t}\n\n\t\tobserver.enable();\n\n\t\treturn observer;\n\t}\n\n\t/**\n\t * Returns observer of the given type or `undefined` if such observer has not been added yet.\n\t *\n\t * @param {Function} Observer The constructor of an observer to get.\n\t * @returns {module:engine/view/observer/observer~Observer|undefined} Observer instance or undefined.\n\t */\n\tgetObserver( Observer ) {\n\t\treturn this._observers.get( Observer );\n\t}\n\n\t/**\n\t * Disables all added observers.\n\t */\n\tdisableObservers() {\n\t\tfor ( const observer of this._observers.values() ) {\n\t\t\tobserver.disable();\n\t\t}\n\t}\n\n\t/**\n\t * Enables all added observers.\n\t */\n\tenableObservers() {\n\t\tfor ( const observer of this._observers.values() ) {\n\t\t\tobserver.enable();\n\t\t}\n\t}\n\n\t/**\n\t * Scrolls the page viewport and {@link #domRoots} with their ancestors to reveal the\n\t * caret, if not already visible to the user.\n\t */\n\tscrollToTheSelection() {\n\t\tconst range = this.document.selection.getFirstRange();\n\n\t\tif ( range ) {\n\t\t\tscrollViewportToShowTarget( {\n\t\t\t\ttarget: this.domConverter.viewRangeToDom( range ),\n\t\t\t\tviewportOffset: 20\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * It will focus DOM element representing {@link module:engine/view/editableelement~EditableElement EditableElement}\n\t * that is currently having selection inside.\n\t */\n\tfocus() {\n\t\tif ( !this.document.isFocused ) {\n\t\t\tconst editable = this.document.selection.editableElement;\n\n\t\t\tif ( editable ) {\n\t\t\t\tthis.domConverter.focus( editable );\n\t\t\t\tthis.forceRender();\n\t\t\t} else {\n\t\t\t\t// Before focusing view document, selection should be placed inside one of the view's editables.\n\t\t\t\t// Normally its selection will be converted from model document (which have default selection), but\n\t\t\t\t// when using view document on its own, we need to manually place selection before focusing it.\n\t\t\t\t//\n\t\t\t\t// @if CK_DEBUG // console.warn( 'There is no selection in any editable to focus.' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * The `change()` method is the primary way of changing the view. You should use it to modify any node in the view tree.\n\t * It makes sure that after all changes are made the view is rendered to the DOM (assuming that the view will be changed\n\t * inside the callback). It prevents situations when the DOM is updated when the view state is not yet correct. It allows\n\t * to nest calls one inside another and still performs a single rendering after all those changes are made.\n\t * It also returns the return value of its callback.\n\t *\n\t *\t\tconst text = view.change( writer => {\n\t *\t\t\tconst newText = writer.createText( 'foo' );\n\t *\t\t\twriter.insert( position1, newText );\n\t *\n\t *\t\t\tview.change( writer => {\n\t *\t\t\t\twriter.insert( position2, writer.createText( 'bar' ) );\n\t *\t\t\t} );\n\t *\n\t * \t\t\twriter.remove( range );\n\t *\n\t * \t\t\treturn newText;\n\t *\t\t} );\n\t *\n\t * When the outermost change block is done and rendering to the DOM is over the\n\t * {@link module:engine/view/view~View#event:render `View#render`} event is fired.\n\t *\n\t * This method throws a `applying-view-changes-on-rendering` error when\n\t * the change block is used after rendering to the DOM has started.\n\t *\n\t * @param {Function} callback Callback function which may modify the view.\n\t * @returns {*} Value returned by the callback.\n\t */\n\tchange( callback ) {\n\t\tif ( this.isRenderingInProgress || this._postFixersInProgress ) {\n\t\t\t/**\n\t\t\t * Thrown when there is an attempt to make changes to the view tree when it is in incorrect state. This may\n\t\t\t * cause some unexpected behaviour and inconsistency between the DOM and the view.\n\t\t\t * This may be caused by:\n\t\t\t *\n\t\t\t * * calling {@link #change} or {@link #forceRender} during rendering process,\n\t\t\t * * calling {@link #change} or {@link #forceRender} inside of\n\t\t\t * {@link module:engine/view/document~Document#registerPostFixer post-fixer function}.\n\t\t\t *\n\t\t\t * @error cannot-change-view-tree\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'cannot-change-view-tree: ' +\n\t\t\t\t'Attempting to make changes to the view when it is in an incorrect state: rendering or post-fixers are in progress. ' +\n\t\t\t\t'This may cause some unexpected behavior and inconsistency between the DOM and the view.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\t// Recursive call to view.change() method - execute listener immediately.\n\t\t\tif ( this._ongoingChange ) {\n\t\t\t\treturn callback( this._writer );\n\t\t\t}\n\n\t\t\t// This lock will assure that all recursive calls to view.change() will end up in same block - one \"render\"\n\t\t\t// event for all nested calls.\n\t\t\tthis._ongoingChange = true;\n\t\t\tconst callbackResult = callback( this._writer );\n\t\t\tthis._ongoingChange = false;\n\n\t\t\t// This lock is used by editing controller to render changes from outer most model.change() once. As plugins might call\n\t\t\t// view.change() inside model.change() block - this will ensures that postfixers and rendering are called once after all\n\t\t\t// changes. Also, we don't need to render anything if there're no changes since last rendering.\n\t\t\tif ( !this._renderingDisabled && this._hasChangedSinceTheLastRendering ) {\n\t\t\t\tthis._postFixersInProgress = true;\n\t\t\t\tthis.document._callPostFixers( this._writer );\n\t\t\t\tthis._postFixersInProgress = false;\n\n\t\t\t\tthis.fire( 'render' );\n\t\t\t}\n\n\t\t\treturn callbackResult;\n\t\t} catch ( err ) {\n\t\t\tCKEditorError.rethrowUnexpectedError( err, this );\n\t\t}\n\t}\n\n\t/**\n\t * Forces rendering {@link module:engine/view/document~Document view document} to DOM. If any view changes are\n\t * currently in progress, rendering will start after all {@link #change change blocks} are processed.\n\t *\n\t * Note that this method is dedicated for special cases. All view changes should be wrapped in the {@link #change}\n\t * block and the view will automatically check whether it needs to render DOM or not.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `applying-view-changes-on-rendering` when\n\t * trying to re-render when rendering to DOM has already started.\n\t */\n\tforceRender() {\n\t\tthis._hasChangedSinceTheLastRendering = true;\n\t\tthis.change( () => {} );\n\t}\n\n\t/**\n\t * Destroys this instance. Makes sure that all observers are destroyed and listeners removed.\n\t */\n\tdestroy() {\n\t\tfor ( const observer of this._observers.values() ) {\n\t\t\tobserver.destroy();\n\t\t}\n\n\t\tthis.document.destroy();\n\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Creates position at the given location. The location can be specified as:\n\t *\n\t * * a {@link module:engine/view/position~Position position},\n\t * * parent element and offset (offset defaults to `0`),\n\t * * parent element and `'end'` (sets position at the end of that element),\n\t * * {@link module:engine/view/item~Item view item} and `'before'` or `'after'` (sets position before or after given view item).\n\t *\n\t * This method is a shortcut to other constructors such as:\n\t *\n\t * * {@link #createPositionBefore},\n\t * * {@link #createPositionAfter},\n\t *\n\t * @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/view/item~Item view item}.\n\t */\n\tcreatePositionAt( itemOrPosition, offset ) {\n\t\treturn Position._createAt( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Creates a new position after given view item.\n\t *\n\t * @param {module:engine/view/item~Item} item View item after which the position should be located.\n\t * @returns {module:engine/view/position~Position}\n\t */\n\tcreatePositionAfter( item ) {\n\t\treturn Position._createAfter( item );\n\t}\n\n\t/**\n\t * Creates a new position before given view item.\n\t *\n\t * @param {module:engine/view/item~Item} item View item before which the position should be located.\n\t * @returns {module:engine/view/position~Position}\n\t */\n\tcreatePositionBefore( item ) {\n\t\treturn Position._createBefore( item );\n\t}\n\n\t/**\n\t * Creates a range spanning from `start` position to `end` position.\n\t *\n\t * **Note:** This factory method creates it's own {@link module:engine/view/position~Position} instances basing on passed values.\n\t *\n\t * @param {module:engine/view/position~Position} start Start position.\n\t * @param {module:engine/view/position~Position} [end] End position. If not set, range will be collapsed at `start` position.\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRange( start, end ) {\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Creates a range that starts before given {@link module:engine/view/item~Item view item} and ends after it.\n\t *\n\t * @param {module:engine/view/item~Item} item\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRangeOn( item ) {\n\t\treturn Range._createOn( item );\n\t}\n\n\t/**\n\t * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of\n\t * that element and ends after the last child of that element.\n\t *\n\t * @param {module:engine/view/element~Element} element Element which is a parent for the range.\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRangeIn( element ) {\n\t\treturn Range._createIn( element );\n\t}\n\n\t/**\n\t Creates new {@link module:engine/view/selection~Selection} instance.\n\t *\n\t * \t\t// Creates empty selection without ranges.\n\t *\t\tconst selection = view.createSelection();\n\t *\n\t *\t\t// Creates selection at the given range.\n\t *\t\tconst range = view.createRange( start, end );\n\t *\t\tconst selection = view.createSelection( range );\n\t *\n\t *\t\t// Creates selection at the given ranges\n\t * \t\tconst ranges = [ view.createRange( start1, end2 ), view.createRange( star2, end2 ) ];\n\t *\t\tconst selection = view.createSelection( ranges );\n\t *\n\t *\t\t// Creates selection from the other selection.\n\t *\t\tconst otherSelection = view.createSelection();\n\t *\t\tconst selection = view.createSelection( otherSelection );\n\t *\n\t *\t\t// Creates selection from the document selection.\n\t *\t\tconst selection = view.createSelection( editor.editing.view.document.selection );\n\t *\n\t * \t\t// Creates selection at the given position.\n\t *\t\tconst position = view.createPositionFromPath( root, path );\n\t *\t\tconst selection = view.createSelection( position );\n\t *\n\t *\t\t// Creates collapsed selection at the position of given item and offset.\n\t *\t\tconst paragraph = view.createContainerElement( 'paragraph' );\n\t *\t\tconst selection = view.createSelection( paragraph, offset );\n\t *\n\t *\t\t// Creates a range inside an {@link module:engine/view/element~Element element} which starts before the\n\t *\t\t// first child of that element and ends after the last child of that element.\n\t *\t\tconst selection = view.createSelection( paragraph, 'in' );\n\t *\n\t *\t\t// Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends\n\t *\t\t// just after the item.\n\t *\t\tconst selection = view.createSelection( paragraph, 'on' );\n\t *\n\t * `Selection`'s factory method allow passing additional options (`backward`, `fake` and `label`) as the last argument.\n\t *\n\t *\t\t// Creates backward selection.\n\t *\t\tconst selection = view.createSelection( range, { backward: true } );\n\t *\n\t * Fake selection does not render as browser native selection over selected elements and is hidden to the user.\n\t * This way, no native selection UI artifacts are displayed to the user and selection over elements can be\n\t * represented in other way, for example by applying proper CSS class.\n\t *\n\t * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM\n\t * (and be properly handled by screen readers).\n\t *\n\t *\t\t// Creates fake selection with label.\n\t *\t\tconst selection = view.createSelection( range, { fake: true, label: 'foo' } );\n\t *\n\t * @param {module:engine/view/selection~Selectable} [selectable=null]\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Offset or place when selectable is an `Item`.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`.\n\t * @param {String} [options.label] Label for the fake selection.\n\t * @returns {module:engine/view/selection~Selection}\n\t */\n\tcreateSelection( selectable, placeOrOffset, options ) {\n\t\treturn new Selection( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Disables or enables rendering. If the flag is set to `true` then the rendering will be disabled.\n\t * If the flag is set to `false` and if there was some change in the meantime, then the rendering action will be performed.\n\t *\n\t * @protected\n\t * @param {Boolean} flag A flag indicates whether the rendering should be disabled.\n\t */\n\t_disableRendering( flag ) {\n\t\tthis._renderingDisabled = flag;\n\n\t\tif ( flag == false ) {\n\t\t\t// Render when you stop blocking rendering.\n\t\t\tthis.change( () => {} );\n\t\t}\n\t}\n\n\t/**\n\t * Renders all changes. In order to avoid triggering the observers (e.g. mutations) all observers are disabled\n\t * before rendering and re-enabled after that.\n\t *\n\t * @private\n\t */\n\t_render() {\n\t\tthis.isRenderingInProgress = true;\n\t\tthis.disableObservers();\n\t\tthis._renderer.render();\n\t\tthis.enableObservers();\n\t\tthis.isRenderingInProgress = false;\n\t}\n\n\t/**\n\t * Fired after a topmost {@link module:engine/view/view~View#change change block} and all\n\t * {@link module:engine/view/document~Document#registerPostFixer post-fixers} are executed.\n\t *\n\t * Actual rendering is performed as a first listener on 'normal' priority.\n\t *\n\t *\t\tview.on( 'render', () => {\n\t *\t\t\t// Rendering to the DOM is complete.\n\t *\t\t} );\n\t *\n\t * This event is useful when you want to update interface elements after the rendering, e.g. position of the\n\t * balloon panel. If you wants to change view structure use\n\t * {@link module:engine/view/document~Document#registerPostFixer post-fixers}.\n\t *\n\t * @event module:engine/view/view~View#event:render\n\t */\n}\n\nmix( View, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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/tomap\n */\n\nimport objectToMap from './objecttomap';\nimport { isPlainObject } from 'lodash-es';\n\n/**\n * Transforms object or iterable to map. Iterable needs to be in the format acceptable by the `Map` constructor.\n *\n *\t\tmap = toMap( { 'foo': 1, 'bar': 2 } );\n *\t\tmap = toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );\n *\t\tmap = toMap( anotherMap );\n *\n * @param {Object|Iterable} data Object or iterable to transform.\n * @returns {Map} Map created from data.\n */\nexport default function toMap( data ) {\n\tif ( isPlainObject( data ) ) {\n\t\treturn objectToMap( data );\n\t} else {\n\t\treturn new Map( data );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/node\n */\n\nimport toMap from '@ckeditor/ckeditor5-utils/src/tomap';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';\n\n// To check if component is loaded more than once.\nimport '@ckeditor/ckeditor5-utils/src/version';\n\n/**\n * Model node. Most basic structure of model tree.\n *\n * This is an abstract class that is a base for other classes representing different nodes in model.\n *\n * **Note:** If a node is detached from the model tree, you can manipulate it using it's API.\n * However, it is **very important** that nodes already attached to model tree should be only changed through\n * {@link module:engine/model/writer~Writer Writer API}.\n *\n * Changes done by `Node` methods, like {@link module:engine/model/element~Element#_insertChild _insertChild} or\n * {@link module:engine/model/node~Node#_setAttribute _setAttribute}\n * do not generate {@link module:engine/model/operation/operation~Operation operations}\n * which are essential for correct editor work if you modify nodes in {@link module:engine/model/document~Document document} root.\n *\n * The flow of working on `Node` (and classes that inherits from it) is as such:\n * 1. You can create a `Node` instance, modify it using it's API.\n * 2. Add `Node` to the model using `Batch` API.\n * 3. Change `Node` that was already added to the model using `Batch` API.\n *\n * Similarly, you cannot use `Batch` API on a node that has not been added to the model tree, with the exception\n * of {@link module:engine/model/writer~Writer#insert inserting} that node to the model tree.\n *\n * Be aware that using {@link module:engine/model/writer~Writer#remove remove from Batch API} does not allow to use `Node` API because\n * the information about `Node` is still kept in model document.\n *\n * In case of {@link module:engine/model/element~Element element node}, adding and removing children also counts as changing a node and\n * follows same rules.\n */\nexport default class Node {\n\t/**\n\t * Creates a model node.\n\t *\n\t * This is an abstract class, so this constructor should not be used directly.\n\t *\n\t * @abstract\n\t * @param {Object} [attrs] Node's attributes. See {@link module:utils/tomap~toMap} for a list of accepted values.\n\t */\n\tconstructor( attrs ) {\n\t\t/**\n\t\t * Parent of this node. It could be {@link module:engine/model/element~Element}\n\t\t * or {@link module:engine/model/documentfragment~DocumentFragment}.\n\t\t * Equals to `null` if the node has no parent.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment|null}\n\t\t */\n\t\tthis.parent = null;\n\n\t\t/**\n\t\t * Attributes set on this node.\n\t\t *\n\t\t * @private\n\t\t * @member {Map} module:engine/model/node~Node#_attrs\n\t\t */\n\t\tthis._attrs = toMap( attrs );\n\t}\n\n\t/**\n\t * Index of this node in it's parent or `null` if the node has no parent.\n\t *\n\t * Accessing this property throws an error if this node's parent element does not contain it.\n\t * This means that model tree got broken.\n\t *\n\t * @readonly\n\t * @type {Number|null}\n\t */\n\tget index() {\n\t\tlet pos;\n\n\t\tif ( !this.parent ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( ( pos = this.parent.getChildIndex( this ) ) === null ) {\n\t\t\tthrow new CKEditorError( 'model-node-not-found-in-parent: The node\\'s parent does not contain this node.', this );\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t/**\n\t * Offset at which this node starts in it's parent. It is equal to the sum of {@link #offsetSize offsetSize}\n\t * of all it's previous siblings. Equals to `null` if node has no parent.\n\t *\n\t * Accessing this property throws an error if this node's parent element does not contain it.\n\t * This means that model tree got broken.\n\t *\n\t * @readonly\n\t * @type {Number|null}\n\t */\n\tget startOffset() {\n\t\tlet pos;\n\n\t\tif ( !this.parent ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( ( pos = this.parent.getChildStartOffset( this ) ) === null ) {\n\t\t\tthrow new CKEditorError( 'model-node-not-found-in-parent: The node\\'s parent does not contain this node.', this );\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t/**\n\t * Offset size of this node. Represents how much \"offset space\" is occupied by the node in it's parent.\n\t * It is important for {@link module:engine/model/position~Position position}. When node has `offsetSize` greater than `1`, position\n\t * can be placed between that node start and end. `offsetSize` greater than `1` is for nodes that represents more\n\t * than one entity, i.e. {@link module:engine/model/text~Text text node}.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget offsetSize() {\n\t\treturn 1;\n\t}\n\n\t/**\n\t * Offset at which this node ends in it's parent. It is equal to the sum of this node's\n\t * {@link module:engine/model/node~Node#startOffset start offset} and {@link #offsetSize offset size}.\n\t * Equals to `null` if the node has no parent.\n\t *\n\t * @readonly\n\t * @type {Number|null}\n\t */\n\tget endOffset() {\n\t\tif ( !this.parent ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.startOffset + this.offsetSize;\n\t}\n\n\t/**\n\t * Node's next sibling or `null` if the node is a last child of it's parent or if the node has no parent.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/node~Node|null}\n\t */\n\tget nextSibling() {\n\t\tconst index = this.index;\n\n\t\treturn ( index !== null && this.parent.getChild( index + 1 ) ) || null;\n\t}\n\n\t/**\n\t * Node's previous sibling or `null` if the node is a first child of it's parent or if the node has no parent.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/node~Node|null}\n\t */\n\tget previousSibling() {\n\t\tconst index = this.index;\n\n\t\treturn ( index !== null && this.parent.getChild( index - 1 ) ) || null;\n\t}\n\n\t/**\n\t * The top-most ancestor of the node. If node has no parent it is the root itself. If the node is a part\n\t * of {@link module:engine/model/documentfragment~DocumentFragment}, it's `root` is equal to that `DocumentFragment`.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/node~Node|module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\tlet root = this; // eslint-disable-line consistent-this\n\n\t\twhile ( root.parent ) {\n\t\t\troot = root.parent;\n\t\t}\n\n\t\treturn root;\n\t}\n\n\t/**\n\t * {@link module:engine/model/document~Document Document} that owns this node or `null` if the node has no parent or is inside\n\t * a {@link module:engine/model/documentfragment~DocumentFragment DocumentFragment}.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/document~Document|null}\n\t */\n\tget document() {\n\t\t// This is a top element of a sub-tree.\n\t\tif ( this.root == this ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Root may be `DocumentFragment` which does not have document property.\n\t\treturn this.root.document || null;\n\t}\n\n\t/**\n\t * Gets path to the node. The path is an array containing starting offsets of consecutive ancestors of this node,\n\t * beginning from {@link module:engine/model/node~Node#root root}, down to this node's starting offset. The path can be used to\n\t * create {@link module:engine/model/position~Position Position} instance.\n\t *\n\t *\t\tconst abc = new Text( 'abc' );\n\t *\t\tconst foo = new Text( 'foo' );\n\t *\t\tconst h1 = new Element( 'h1', null, new Text( 'header' ) );\n\t *\t\tconst p = new Element( 'p', null, [ abc, foo ] );\n\t *\t\tconst div = new Element( 'div', null, [ h1, p ] );\n\t *\t\tfoo.getPath(); // Returns [ 1, 3 ]. `foo` is in `p` which is in `div`. `p` starts at offset 1, while `foo` at 3.\n\t *\t\th1.getPath(); // Returns [ 0 ].\n\t *\t\tdiv.getPath(); // Returns [].\n\t *\n\t * @returns {Array.<Number>} The path.\n\t */\n\tgetPath() {\n\t\tconst path = [];\n\t\tlet node = this; // eslint-disable-line consistent-this\n\n\t\twhile ( node.parent ) {\n\t\t\tpath.unshift( node.startOffset );\n\t\t\tnode = node.parent;\n\t\t}\n\n\t\treturn path;\n\t}\n\n\t/**\n\t * Returns ancestors array of this node.\n\t *\n\t * @param {Object} options Options object.\n\t * @param {Boolean} [options.includeSelf=false] When set to `true` this node will be also included in parent's array.\n\t * @param {Boolean} [options.parentFirst=false] When set to `true`, array will be sorted from node's parent to root element,\n\t * otherwise root element will be the first item in the array.\n\t * @returns {Array} Array with ancestors.\n\t */\n\tgetAncestors( options = { includeSelf: false, parentFirst: false } ) {\n\t\tconst ancestors = [];\n\t\tlet parent = options.includeSelf ? this : this.parent;\n\n\t\twhile ( parent ) {\n\t\t\tancestors[ options.parentFirst ? 'push' : 'unshift' ]( parent );\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn ancestors;\n\t}\n\n\t/**\n\t * Returns a {@link module:engine/model/element~Element} or {@link module:engine/model/documentfragment~DocumentFragment}\n\t * which is a common ancestor of both nodes.\n\t *\n\t * @param {module:engine/model/node~Node} node The second node.\n\t * @param {Object} options Options object.\n\t * @param {Boolean} [options.includeSelf=false] When set to `true` both nodes will be considered \"ancestors\" too.\n\t * Which means that if e.g. node A is inside B, then their common ancestor will be B.\n\t * @returns {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment|null}\n\t */\n\tgetCommonAncestor( node, options = {} ) {\n\t\tconst ancestorsA = this.getAncestors( options );\n\t\tconst ancestorsB = node.getAncestors( options );\n\n\t\tlet i = 0;\n\n\t\twhile ( ancestorsA[ i ] == ancestorsB[ i ] && ancestorsA[ i ] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i === 0 ? null : ancestorsA[ i - 1 ];\n\t}\n\n\t/**\n\t * Returns whether this node is before given node. `false` is returned if nodes are in different trees (for example,\n\t * in different {@link module:engine/model/documentfragment~DocumentFragment}s).\n\t *\n\t * @param {module:engine/model/node~Node} node Node to compare with.\n\t * @returns {Boolean}\n\t */\n\tisBefore( node ) {\n\t\t// Given node is not before this node if they are same.\n\t\tif ( this == node ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Return `false` if it is impossible to compare nodes.\n\t\tif ( this.root !== node.root ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst thisPath = this.getPath();\n\t\tconst nodePath = node.getPath();\n\n\t\tconst result = compareArrays( thisPath, nodePath );\n\n\t\tswitch ( result ) {\n\t\t\tcase 'prefix':\n\t\t\t\treturn true;\n\n\t\t\tcase 'extension':\n\t\t\t\treturn false;\n\n\t\t\tdefault:\n\t\t\t\treturn thisPath[ result ] < nodePath[ result ];\n\t\t}\n\t}\n\n\t/**\n\t * Returns whether this node is after given node. `false` is returned if nodes are in different trees (for example,\n\t * in different {@link module:engine/model/documentfragment~DocumentFragment}s).\n\t *\n\t * @param {module:engine/model/node~Node} node Node to compare with.\n\t * @returns {Boolean}\n\t */\n\tisAfter( node ) {\n\t\t// Given node is not before this node if they are same.\n\t\tif ( this == node ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Return `false` if it is impossible to compare nodes.\n\t\tif ( this.root !== node.root ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// In other cases, just check if the `node` is before, and return the opposite.\n\t\treturn !this.isBefore( node );\n\t}\n\n\t/**\n\t * Checks if the node has an attribute with given key.\n\t *\n\t * @param {String} key Key of attribute to check.\n\t * @returns {Boolean} `true` if attribute with given key is set on node, `false` otherwise.\n\t */\n\thasAttribute( key ) {\n\t\treturn this._attrs.has( key );\n\t}\n\n\t/**\n\t * Gets an attribute value for given key or `undefined` if that attribute is not set on node.\n\t *\n\t * @param {String} key Key of attribute to look for.\n\t * @returns {*} Attribute value or `undefined`.\n\t */\n\tgetAttribute( key ) {\n\t\treturn this._attrs.get( key );\n\t}\n\n\t/**\n\t * Returns iterator that iterates over this node's attributes.\n\t *\n\t * Attributes are returned as arrays containing two items. First one is attribute key and second is attribute value.\n\t * This format is accepted by native `Map` object and also can be passed in `Node` constructor.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\tgetAttributes() {\n\t\treturn this._attrs.entries();\n\t}\n\n\t/**\n\t * Returns iterator that iterates over this node's attribute keys.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\tgetAttributeKeys() {\n\t\treturn this._attrs.keys();\n\t}\n\n\t/**\n\t * Converts `Node` to plain object and returns it.\n\t *\n\t * @returns {Object} `Node` converted to plain object.\n\t */\n\ttoJSON() {\n\t\tconst json = {};\n\n\t\t// Serializes attributes to the object.\n\t\t// attributes = { a: 'foo', b: 1, c: true }.\n\t\tif ( this._attrs.size ) {\n\t\t\tjson.attributes = Array.from( this._attrs ).reduce( ( result, attr ) => {\n\t\t\t\tresult[ attr[ 0 ] ] = attr[ 1 ];\n\n\t\t\t\treturn result;\n\t\t\t}, {} );\n\t\t}\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t * This method is useful when processing model objects that are of unknown type. For example, a function\n\t * may return a {@link module:engine/model/documentfragment~DocumentFragment} or a {@link module:engine/model/node~Node}\n\t * that can be either a text node or an element. This method can be used to check what kind of object is returned.\n\t *\n\t *\t\tsomeObject.is( 'element' ); // -> true if this is an element\n\t *\t\tsomeObject.is( 'node' ); // -> true if this is a node (a text node or an element)\n\t *\t\tsomeObject.is( 'documentFragment' ); // -> true if this is a document fragment\n\t *\n\t * Since this method is also available on a range of view objects, you can prefix the type of the object with\n\t * `model:` or `view:` to check, for example, if this is the model's or view's element:\n\t *\n\t *\t\tmodelElement.is( 'model:element' ); // -> true\n\t *\t\tmodelElement.is( 'view:element' ); // -> false\n\t *\n\t * By using this method it is also possible to check a name of an element:\n\t *\n\t *\t\timageElement.is( 'image' ); // -> true\n\t *\t\timageElement.is( 'element', 'image' ); // -> same as above\n\t *\t\timageElement.is( 'model:element', 'image' ); // -> same as above, but more precise\n\t *\n\t * The list of model objects which implement the `is()` method:\n\t *\n\t * * {@link module:engine/model/node~Node#is `Node#is()`}\n\t * * {@link module:engine/model/text~Text#is `Text#is()`}\n\t * * {@link module:engine/model/element~Element#is `Element#is()`}\n\t * * {@link module:engine/model/rootelement~RootElement#is `RootElement#is()`}\n\t * * {@link module:engine/model/position~Position#is `Position#is()`}\n\t * * {@link module:engine/model/liveposition~LivePosition#is `LivePosition#is()`}\n\t * * {@link module:engine/model/range~Range#is `Range#is()`}\n\t * * {@link module:engine/model/liverange~LiveRange#is `LiveRange#is()`}\n\t * * {@link module:engine/model/documentfragment~DocumentFragment#is `DocumentFragment#is()`}\n\t * * {@link module:engine/model/selection~Selection#is `Selection#is()`}\n\t * * {@link module:engine/model/documentselection~DocumentSelection#is `DocumentSelection#is()`}\n\t * * {@link module:engine/model/markercollection~Marker#is `Marker#is()`}\n\t * * {@link module:engine/model/textproxy~TextProxy#is `TextProxy#is()`}\n\t *\n\t * @method #is\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'node' || type == 'model:node';\n\t}\n\n\t/**\n\t * Creates a copy of this node, that is a node with exactly same attributes, and returns it.\n\t *\n\t * @protected\n\t * @returns {module:engine/model/node~Node} Node with same attributes as this node.\n\t */\n\t_clone() {\n\t\treturn new Node( this._attrs );\n\t}\n\n\t/**\n\t * Removes this node from it's parent.\n\t *\n\t * @see module:engine/model/writer~Writer#remove\n\t * @protected\n\t */\n\t_remove() {\n\t\tthis.parent._removeChildren( this.index );\n\t}\n\n\t/**\n\t * Sets attribute on the node. If attribute with the same key already is set, it's value is overwritten.\n\t *\n\t * @see module:engine/model/writer~Writer#setAttribute\n\t * @protected\n\t * @param {String} key Key of attribute to set.\n\t * @param {*} value Attribute value.\n\t */\n\t_setAttribute( key, value ) {\n\t\tthis._attrs.set( key, value );\n\t}\n\n\t/**\n\t * Removes all attributes from the node and sets given attributes.\n\t *\n\t * @see module:engine/model/writer~Writer#setAttributes\n\t * @protected\n\t * @param {Object} [attrs] Attributes to set. See {@link module:utils/tomap~toMap} for a list of accepted values.\n\t */\n\t_setAttributesTo( attrs ) {\n\t\tthis._attrs = toMap( attrs );\n\t}\n\n\t/**\n\t * Removes an attribute with given key from the node.\n\t *\n\t * @see module:engine/model/writer~Writer#removeAttribute\n\t * @protected\n\t * @param {String} key Key of attribute to remove.\n\t * @returns {Boolean} `true` if the attribute was set on the element, `false` otherwise.\n\t */\n\t_removeAttribute( key ) {\n\t\treturn this._attrs.delete( key );\n\t}\n\n\t/**\n\t * Removes all attributes from the node.\n\t *\n\t * @see module:engine/model/writer~Writer#clearAttributes\n\t * @protected\n\t */\n\t_clearAttributes() {\n\t\tthis._attrs.clear();\n\t}\n}\n\n/**\n * The node's parent does not contain this node.\n *\n * This error may be thrown from corrupted trees.\n *\n * @error model-node-not-found-in-parent\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/text\n */\n\nimport Node from './node';\n\n/**\n * Model text node. Type of {@link module:engine/model/node~Node node} that contains {@link module:engine/model/text~Text#data text data}.\n *\n * **Important:** see {@link module:engine/model/node~Node} to read about restrictions using `Text` and `Node` API.\n *\n * **Note:** keep in mind that `Text` instances might indirectly got removed from model tree when model is changed.\n * This happens when {@link module:engine/model/writer~Writer model writer} is used to change model and the text node is merged with\n * another text node. Then, both text nodes are removed and a new text node is inserted into the model. Because of\n * this behavior, keeping references to `Text` is not recommended. Instead, consider creating\n * {@link module:engine/model/liveposition~LivePosition live position} placed before the text node.\n *\n * @extends module:engine/model/node~Node\n */\nexport default class Text extends Node {\n\t/**\n\t * Creates a text node.\n\t *\n\t * **Note:** Constructor of this class shouldn't be used directly in the code.\n\t * Use the {@link module:engine/model/writer~Writer#createText} method instead.\n\t *\n\t * @protected\n\t * @param {String} data Node's text.\n\t * @param {Object} [attrs] Node's attributes. See {@link module:utils/tomap~toMap} for a list of accepted values.\n\t */\n\tconstructor( data, attrs ) {\n\t\tsuper( attrs );\n\n\t\t/**\n\t\t * Text data contained in this text node.\n\t\t *\n\t\t * @protected\n\t\t * @type {String}\n\t\t */\n\t\tthis._data = data || '';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget offsetSize() {\n\t\treturn this.data.length;\n\t}\n\n\t/**\n\t * Returns a text data contained in the node.\n\t *\n\t * @readonly\n\t * @type {String}\n\t */\n\tget data() {\n\t\treturn this._data;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\ttext.is( 'text' ); // -> true\n\t *\t\ttext.is( 'node' ); // -> true\n\t *\t\ttext.is( 'model:text' ); // -> true\n\t *\t\ttext.is( 'model:node' ); // -> true\n\t *\n\t *\t\ttext.is( 'view:text' ); // -> false\n\t *\t\ttext.is( 'documentSelection' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'text' || type == 'model:text' || super.is( type );\n\t}\n\n\t/**\n\t * Converts `Text` instance to plain object and returns it.\n\t *\n\t * @returns {Object} `Text` instance converted to plain object.\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.data = this.data;\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Creates a copy of this text node and returns it. Created text node has same text data and attributes as original text node.\n\t *\n\t * @protected\n\t * @returns {module:engine/model/text~Text} `Text` instance created using given plain object.\n\t */\n\t_clone() {\n\t\treturn new Text( this.data, this.getAttributes() );\n\t}\n\n\t/**\n\t * Creates a `Text` instance from given plain object (i.e. parsed JSON string).\n\t *\n\t * @param {Object} json Plain object to be converted to `Text`.\n\t * @returns {module:engine/model/text~Text} `Text` instance created using given plain object.\n\t */\n\tstatic fromJSON( json ) {\n\t\treturn new Text( json.data, json.attributes );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/textproxy\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * `TextProxy` represents a part of {@link module:engine/model/text~Text text node}.\n *\n * Since {@link module:engine/model/position~Position positions} can be placed between characters of a text node,\n * {@link module:engine/model/range~Range ranges} may contain only parts of text nodes. When {@link module:engine/model/range~Range#getItems\n * getting items}\n * contained in such range, we need to represent a part of that text node, since returning the whole text node would be incorrect.\n * `TextProxy` solves this issue.\n *\n * `TextProxy` has an API similar to {@link module:engine/model/text~Text Text} and allows to do most of the common tasks performed\n * on model nodes.\n *\n * **Note:** Some `TextProxy` instances may represent whole text node, not just a part of it.\n * See {@link module:engine/model/textproxy~TextProxy#isPartial}.\n *\n * **Note:** `TextProxy` is not an instance of {@link module:engine/model/node~Node node}. Keep this in mind when using it as a\n * parameter of methods.\n *\n * **Note:** `TextProxy` is a readonly interface. If you want to perform changes on model data represented by a `TextProxy`\n * use {@link module:engine/model/writer~Writer model writer API}.\n *\n * **Note:** `TextProxy` instances are created on the fly, basing on the current state of model. Because of this, it is\n * highly unrecommended to store references to `TextProxy` instances. `TextProxy` instances are not refreshed when\n * model changes, so they might get invalidated. Instead, consider creating {@link module:engine/model/liveposition~LivePosition live\n * position}.\n *\n * `TextProxy` instances are created by {@link module:engine/model/treewalker~TreeWalker model tree walker}. You should not need to create\n * an instance of this class by your own.\n */\nexport default class TextProxy {\n\t/**\n\t * Creates a text proxy.\n\t *\n\t * @protected\n\t * @param {module:engine/model/text~Text} textNode Text node which part is represented by this text proxy.\n\t * @param {Number} offsetInText Offset in {@link module:engine/model/textproxy~TextProxy#textNode text node} from which the text proxy\n\t * starts.\n\t * @param {Number} length Text proxy length, that is how many text node's characters, starting from `offsetInText` it represents.\n\t * @constructor\n\t */\n\tconstructor( textNode, offsetInText, length ) {\n\t\t/**\n\t\t * Text node which part is represented by this text proxy.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/text~Text}\n\t\t */\n\t\tthis.textNode = textNode;\n\n\t\tif ( offsetInText < 0 || offsetInText > textNode.offsetSize ) {\n\t\t\t/**\n\t\t\t * Given `offsetInText` value is incorrect.\n\t\t\t *\n\t\t\t * @error model-textproxy-wrong-offsetintext\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'model-textproxy-wrong-offsetintext: Given offsetInText value is incorrect.', this );\n\t\t}\n\n\t\tif ( length < 0 || offsetInText + length > textNode.offsetSize ) {\n\t\t\t/**\n\t\t\t * Given `length` value is incorrect.\n\t\t\t *\n\t\t\t * @error model-textproxy-wrong-length\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'model-textproxy-wrong-length: Given length value is incorrect.', this );\n\t\t}\n\n\t\t/**\n\t\t * Text data represented by this text proxy.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.data = textNode.data.substring( offsetInText, offsetInText + length );\n\n\t\t/**\n\t\t * Offset in {@link module:engine/model/textproxy~TextProxy#textNode text node} from which the text proxy starts.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t */\n\t\tthis.offsetInText = offsetInText;\n\t}\n\n\t/**\n\t * Offset at which this text proxy starts in it's parent.\n\t *\n\t * @see module:engine/model/node~Node#startOffset\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget startOffset() {\n\t\treturn this.textNode.startOffset !== null ? this.textNode.startOffset + this.offsetInText : null;\n\t}\n\n\t/**\n\t * Offset size of this text proxy. Equal to the number of characters represented by the text proxy.\n\t *\n\t * @see module:engine/model/node~Node#offsetSize\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget offsetSize() {\n\t\treturn this.data.length;\n\t}\n\n\t/**\n\t * Offset at which this text proxy ends in it's parent.\n\t *\n\t * @see module:engine/model/node~Node#endOffset\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget endOffset() {\n\t\treturn this.startOffset !== null ? this.startOffset + this.offsetSize : null;\n\t}\n\n\t/**\n\t * Flag indicating whether `TextProxy` instance covers only part of the original {@link module:engine/model/text~Text text node}\n\t * (`true`) or the whole text node (`false`).\n\t *\n\t * This is `false` when text proxy starts at the very beginning of {@link module:engine/model/textproxy~TextProxy#textNode textNode}\n\t * ({@link module:engine/model/textproxy~TextProxy#offsetInText offsetInText} equals `0`) and text proxy sizes is equal to\n\t * text node size.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isPartial() {\n\t\treturn this.offsetSize !== this.textNode.offsetSize;\n\t}\n\n\t/**\n\t * Parent of this text proxy, which is same as parent of text node represented by this text proxy.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment|null}\n\t */\n\tget parent() {\n\t\treturn this.textNode.parent;\n\t}\n\n\t/**\n\t * Root of this text proxy, which is same as root of text node represented by this text proxy.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/node~Node|module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this.textNode.root;\n\t}\n\n\t/**\n\t * {@link module:engine/model/document~Document Document} that owns text node represented by this text proxy or `null` if the text node\n\t * has no parent or is inside a {@link module:engine/model/documentfragment~DocumentFragment DocumentFragment}.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/document~Document|null}\n\t */\n\tget document() {\n\t\treturn this.textNode.document;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\ttextProxy.is( 'textProxy' ); // -> true\n\t *\t\ttextProxy.is( 'model:textProxy' ); // -> true\n\t *\n\t *\t\ttextProxy.is( 'view:textProxy' ); // -> false\n\t *\t\ttextProxy.is( 'range' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'textProxy' || type == 'model:textProxy';\n\t}\n\n\t/**\n\t * Gets path to this text proxy.\n\t *\n\t * @see module:engine/model/node~Node#getPath\n\t * @returns {Array.<Number>}\n\t */\n\tgetPath() {\n\t\tconst path = this.textNode.getPath();\n\n\t\tif ( path.length > 0 ) {\n\t\t\tpath[ path.length - 1 ] += this.offsetInText;\n\t\t}\n\n\t\treturn path;\n\t}\n\n\t/**\n\t * Returns ancestors array of this text proxy.\n\t *\n\t * @param {Object} options Options object.\n\t * @param {Boolean} [options.includeSelf=false] When set to `true` this text proxy will be also included in parent's array.\n\t * @param {Boolean} [options.parentFirst=false] When set to `true`, array will be sorted from text proxy parent to root element,\n\t * otherwise root element will be the first item in the array.\n\t * @returns {Array} Array with ancestors.\n\t */\n\tgetAncestors( options = { includeSelf: false, parentFirst: false } ) {\n\t\tconst ancestors = [];\n\t\tlet parent = options.includeSelf ? this : this.parent;\n\n\t\twhile ( parent ) {\n\t\t\tancestors[ options.parentFirst ? 'push' : 'unshift' ]( parent );\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn ancestors;\n\t}\n\n\t/**\n\t * Checks if this text proxy has an attribute for given key.\n\t *\n\t * @param {String} key Key of attribute to check.\n\t * @returns {Boolean} `true` if attribute with given key is set on text proxy, `false` otherwise.\n\t */\n\thasAttribute( key ) {\n\t\treturn this.textNode.hasAttribute( key );\n\t}\n\n\t/**\n\t * Gets an attribute value for given key or `undefined` if that attribute is not set on text proxy.\n\t *\n\t * @param {String} key Key of attribute to look for.\n\t * @returns {*} Attribute value or `undefined`.\n\t */\n\tgetAttribute( key ) {\n\t\treturn this.textNode.getAttribute( key );\n\t}\n\n\t/**\n\t * Returns iterator that iterates over this node's attributes. Attributes are returned as arrays containing two\n\t * items. First one is attribute key and second is attribute value.\n\t *\n\t * This format is accepted by native `Map` object and also can be passed in `Node` constructor.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\tgetAttributes() {\n\t\treturn this.textNode.getAttributes();\n\t}\n\n\t/**\n\t * Returns iterator that iterates over this node's attribute keys.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\tgetAttributeKeys() {\n\t\treturn this.textNode.getAttributeKeys();\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/nodelist\n */\n\nimport Node from './node';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Provides an interface to operate on a list of {@link module:engine/model/node~Node nodes}. `NodeList` is used internally\n * in classes like {@link module:engine/model/element~Element Element}\n * or {@link module:engine/model/documentfragment~DocumentFragment DocumentFragment}.\n */\nexport default class NodeList {\n\t/**\n\t * Creates an empty node list.\n\t *\n\t * @protected\n\t * @param {Iterable.<module:engine/model/node~Node>} nodes Nodes contained in this node list.\n\t */\n\tconstructor( nodes ) {\n\t\t/**\n\t\t * Nodes contained in this node list.\n\t\t *\n\t\t * @private\n\t\t * @member {Array.<module:engine/model/node~Node>}\n\t\t */\n\t\tthis._nodes = [];\n\n\t\tif ( nodes ) {\n\t\t\tthis._insertNodes( 0, nodes );\n\t\t}\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Iterates over all nodes contained inside this node list.\n\t *\n\t * @returns {Iterable.<module:engine/model/node~Node>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this._nodes[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Number of nodes contained inside this node list.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget length() {\n\t\treturn this._nodes.length;\n\t}\n\n\t/**\n\t * Sum of {@link module:engine/model/node~Node#offsetSize offset sizes} of all nodes contained inside this node list.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget maxOffset() {\n\t\treturn this._nodes.reduce( ( sum, node ) => sum + node.offsetSize, 0 );\n\t}\n\n\t/**\n\t * Gets the node at the given index. Returns `null` if incorrect index was passed.\n\t *\n\t * @param {Number} index Index of node.\n\t * @returns {module:engine/model/node~Node|null} Node at given index.\n\t */\n\tgetNode( index ) {\n\t\treturn this._nodes[ index ] || null;\n\t}\n\n\t/**\n\t * Returns an index of the given node. Returns `null` if given node is not inside this node list.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number|null} Child node's index.\n\t */\n\tgetNodeIndex( node ) {\n\t\tconst index = this._nodes.indexOf( node );\n\n\t\treturn index == -1 ? null : index;\n\t}\n\n\t/**\n\t * Returns the starting offset of given node. Starting offset is equal to the sum of\n\t * {@link module:engine/model/node~Node#offsetSize offset sizes} of all nodes that are before this node in this node list.\n\t *\n\t * @param {module:engine/model/node~Node} node Node to look for.\n\t * @returns {Number|null} Node's starting offset.\n\t */\n\tgetNodeStartOffset( node ) {\n\t\tconst index = this.getNodeIndex( node );\n\n\t\treturn index === null ? null : this._nodes.slice( 0, index ).reduce( ( sum, node ) => sum + node.offsetSize, 0 );\n\t}\n\n\t/**\n\t * Converts index to offset in node list.\n\t *\n\t * Returns starting offset of a node that is at given index. Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError}\n\t * `model-nodelist-index-out-of-bounds` if given index is less than `0` or more than {@link #length}.\n\t *\n\t * @param {Number} index Node's index.\n\t * @returns {Number} Node's starting offset.\n\t */\n\tindexToOffset( index ) {\n\t\tif ( index == this._nodes.length ) {\n\t\t\treturn this.maxOffset;\n\t\t}\n\n\t\tconst node = this._nodes[ index ];\n\n\t\tif ( !node ) {\n\t\t\t/**\n\t\t\t * Given index cannot be found in the node list.\n\t\t\t *\n\t\t\t * @error nodelist-index-out-of-bounds\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'model-nodelist-index-out-of-bounds: Given index cannot be found in the node list.', this );\n\t\t}\n\n\t\treturn this.getNodeStartOffset( node );\n\t}\n\n\t/**\n\t * Converts offset in node list to index.\n\t *\n\t * Returns index of a node that occupies given offset. Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError}\n\t * `model-nodelist-offset-out-of-bounds` if given offset is less than `0` or more than {@link #maxOffset}.\n\t *\n\t * @param {Number} offset Offset to look for.\n\t * @returns {Number} Index of a node that occupies given offset.\n\t */\n\toffsetToIndex( offset ) {\n\t\tlet totalOffset = 0;\n\n\t\tfor ( const node of this._nodes ) {\n\t\t\tif ( offset >= totalOffset && offset < totalOffset + node.offsetSize ) {\n\t\t\t\treturn this.getNodeIndex( node );\n\t\t\t}\n\n\t\t\ttotalOffset += node.offsetSize;\n\t\t}\n\n\t\tif ( totalOffset != offset ) {\n\t\t\t/**\n\t\t\t * Given offset cannot be found in the node list.\n\t\t\t *\n\t\t\t * @error model-nodelist-offset-out-of-bounds\n\t\t\t * @param {Number} offset\n\t\t\t * @param {module:engine/model/nodelist~NodeList} nodeList Stringified node list.\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'model-nodelist-offset-out-of-bounds: Given offset cannot be found in the node list.',\n\t\t\t\tthis,\n\t\t\t\t{\n\t\t\t\t\toffset,\n\t\t\t\t\tnodeList: this\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\treturn this.length;\n\t}\n\n\t/**\n\t * Inserts given nodes at given index.\n\t *\n\t * @protected\n\t * @param {Number} index Index at which nodes should be inserted.\n\t * @param {Iterable.<module:engine/model/node~Node>} nodes Nodes to be inserted.\n\t */\n\t_insertNodes( index, nodes ) {\n\t\t// Validation.\n\t\tfor ( const node of nodes ) {\n\t\t\tif ( !( node instanceof Node ) ) {\n\t\t\t\t/**\n\t\t\t\t * Trying to insert an object which is not a Node instance.\n\t\t\t\t *\n\t\t\t\t * @error nodelist-insertNodes-not-node\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'model-nodelist-insertNodes-not-node: Trying to insert an object which is not a Node instance.',\n\t\t\t\t\tthis\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._nodes.splice( index, 0, ...nodes );\n\t}\n\n\t/**\n\t * Removes one or more nodes starting at the given index.\n\t *\n\t * @protected\n\t * @param {Number} indexStart Index of the first node to remove.\n\t * @param {Number} [howMany=1] Number of nodes to remove.\n\t * @returns {Array.<module:engine/model/node~Node>} Array containing removed nodes.\n\t */\n\t_removeNodes( indexStart, howMany = 1 ) {\n\t\treturn this._nodes.splice( indexStart, howMany );\n\t}\n\n\t/**\n\t * Converts `NodeList` instance to an array containing nodes that were inserted in the node list. Nodes\n\t * are also converted to their plain object representation.\n\t *\n\t * @returns {Array.<module:engine/model/node~Node>} `NodeList` instance converted to `Array`.\n\t */\n\ttoJSON() {\n\t\treturn this._nodes.map( node => node.toJSON() );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/element\n */\n\nimport Node from './node';\nimport NodeList from './nodelist';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\n\n/**\n * Model element. Type of {@link module:engine/model/node~Node node} that has a {@link module:engine/model/element~Element#name name} and\n * {@link module:engine/model/element~Element#getChildren child nodes}.\n *\n * **Important**: see {@link module:engine/model/node~Node} to read about restrictions using `Element` and `Node` API.\n *\n * @extends module:engine/model/node~Node\n */\nexport default class Element extends Node {\n\t/**\n\t * Creates a model element.\n\t *\n\t * **Note:** Constructor of this class shouldn't be used directly in the code.\n\t * Use the {@link module:engine/model/writer~Writer#createElement} method instead.\n\t *\n\t * @protected\n\t * @param {String} name Element's name.\n\t * @param {Object} [attrs] Element's attributes. See {@link module:utils/tomap~toMap} for a list of accepted values.\n\t * @param {module:engine/model/node~Node|Iterable.<module:engine/model/node~Node>} [children]\n\t * One or more nodes to be inserted as children of created element.\n\t */\n\tconstructor( name, attrs, children ) {\n\t\tsuper( attrs );\n\n\t\t/**\n\t\t * Element name.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} module:engine/model/element~Element#name\n\t\t */\n\t\tthis.name = name;\n\n\t\t/**\n\t\t * List of children nodes.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/nodelist~NodeList} module:engine/model/element~Element#_children\n\t\t */\n\t\tthis._children = new NodeList();\n\n\t\tif ( children ) {\n\t\t\tthis._insertChild( 0, children );\n\t\t}\n\t}\n\n\t/**\n\t * Number of this element's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget childCount() {\n\t\treturn this._children.length;\n\t}\n\n\t/**\n\t * Sum of {@link module:engine/model/node~Node#offsetSize offset sizes} of all of this element's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget maxOffset() {\n\t\treturn this._children.maxOffset;\n\t}\n\n\t/**\n\t * Is `true` if there are no nodes inside this element, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isEmpty() {\n\t\treturn this.childCount === 0;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\telement.is( 'element' ); // -> true\n\t *\t\telement.is( 'node' ); // -> true\n\t *\t\telement.is( 'model:element' ); // -> true\n\t *\t\telement.is( 'model:node' ); // -> true\n\t *\n\t *\t\telement.is( 'view:element' ); // -> false\n\t *\t\telement.is( 'documentSelection' ); // -> false\n\t *\n\t * Assuming that the object being checked is an element, you can also check its\n\t * {@link module:engine/model/element~Element#name name}:\n\t *\n\t *\t\telement.is( 'image' ); // -> true if this is an <image> element\n\t *\t\telement.is( 'element', 'image' ); // -> same as above\n\t *\t\ttext.is( 'image' ); -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name = null ) {\n\t\tconst cutType = type.replace( /^model:/, '' );\n\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'element' || cutType == this.name || super.is( type );\n\t\t} else {\n\t\t\treturn cutType == 'element' && name == this.name;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the child at the given index.\n\t *\n\t * @param {Number} index Index of child.\n\t * @returns {module:engine/model/node~Node} Child node.\n\t */\n\tgetChild( index ) {\n\t\treturn this._children.getNode( index );\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all of this element's children.\n\t *\n\t * @returns {Iterable.<module:engine/model/node~Node>}\n\t */\n\tgetChildren() {\n\t\treturn this._children[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Returns an index of the given child node. Returns `null` if given node is not a child of this element.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number} Child node's index in this element.\n\t */\n\tgetChildIndex( node ) {\n\t\treturn this._children.getNodeIndex( node );\n\t}\n\n\t/**\n\t * Returns the starting offset of given child. Starting offset is equal to the sum of\n\t * {@link module:engine/model/node~Node#offsetSize offset sizes} of all node's siblings that are before it. Returns `null` if\n\t * given node is not a child of this element.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number} Child node's starting offset.\n\t */\n\tgetChildStartOffset( node ) {\n\t\treturn this._children.getNodeStartOffset( node );\n\t}\n\n\t/**\n\t * Returns index of a node that occupies given offset. If given offset is too low, returns `0`. If given offset is\n\t * too high, returns {@link module:engine/model/element~Element#getChildIndex index after last child}.\n\t *\n\t *\t\tconst textNode = new Text( 'foo' );\n\t *\t\tconst pElement = new Element( 'p' );\n\t *\t\tconst divElement = new Element( [ textNode, pElement ] );\n\t *\t\tdivElement.offsetToIndex( -1 ); // Returns 0, because offset is too low.\n\t *\t\tdivElement.offsetToIndex( 0 ); // Returns 0, because offset 0 is taken by `textNode` which is at index 0.\n\t *\t\tdivElement.offsetToIndex( 1 ); // Returns 0, because `textNode` has `offsetSize` equal to 3, so it occupies offset 1 too.\n\t *\t\tdivElement.offsetToIndex( 2 ); // Returns 0.\n\t *\t\tdivElement.offsetToIndex( 3 ); // Returns 1.\n\t *\t\tdivElement.offsetToIndex( 4 ); // Returns 2. There are no nodes at offset 4, so last available index is returned.\n\t *\n\t * @param {Number} offset Offset to look for.\n\t * @returns {Number}\n\t */\n\toffsetToIndex( offset ) {\n\t\treturn this._children.offsetToIndex( offset );\n\t}\n\n\t/**\n\t * Returns a descendant node by its path relative to this element.\n\t *\n\t *\t\t// <this>a<b>c</b></this>\n\t *\t\tthis.getNodeByPath( [ 0 ] ); // -> \"a\"\n\t *\t\tthis.getNodeByPath( [ 1 ] ); // -> <b>\n\t *\t\tthis.getNodeByPath( [ 1, 0 ] ); // -> \"c\"\n\t *\n\t * @param {Array.<Number>} relativePath Path of the node to find, relative to this element.\n\t * @returns {module:engine/model/node~Node}\n\t */\n\tgetNodeByPath( relativePath ) {\n\t\tlet node = this; // eslint-disable-line consistent-this\n\n\t\tfor ( const index of relativePath ) {\n\t\t\tnode = node.getChild( node.offsetToIndex( index ) );\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Converts `Element` instance to plain object and returns it. Takes care of converting all of this element's children.\n\t *\n\t * @returns {Object} `Element` instance converted to plain object.\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.name = this.name;\n\n\t\tif ( this._children.length > 0 ) {\n\t\t\tjson.children = [];\n\n\t\t\tfor ( const node of this._children ) {\n\t\t\t\tjson.children.push( node.toJSON() );\n\t\t\t}\n\t\t}\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Creates a copy of this element and returns it. Created element has the same name and attributes as the original element.\n\t * If clone is deep, the original element's children are also cloned. If not, then empty element is removed.\n\t *\n\t * @protected\n\t * @param {Boolean} [deep=false] If set to `true` clones element and all its children recursively. When set to `false`,\n\t * element will be cloned without any child.\n\t */\n\t_clone( deep = false ) {\n\t\tconst children = deep ? Array.from( this._children ).map( node => node._clone( true ) ) : null;\n\n\t\treturn new Element( this.name, this.getAttributes(), children );\n\t}\n\n\t/**\n\t * {@link module:engine/model/element~Element#_insertChild Inserts} one or more nodes at the end of this element.\n\t *\n\t * @see module:engine/model/writer~Writer#append\n\t * @protected\n\t * @param {module:engine/model/item~Item|Iterable.<module:engine/model/item~Item>} nodes Nodes to be inserted.\n\t */\n\t_appendChild( nodes ) {\n\t\tthis._insertChild( this.childCount, nodes );\n\t}\n\n\t/**\n\t * Inserts one or more nodes at the given index and sets {@link module:engine/model/node~Node#parent parent} of these nodes\n\t * to this element.\n\t *\n\t * @see module:engine/model/writer~Writer#insert\n\t * @protected\n\t * @param {Number} index Index at which nodes should be inserted.\n\t * @param {module:engine/model/item~Item|Iterable.<module:engine/model/item~Item>} items Items to be inserted.\n\t */\n\t_insertChild( index, items ) {\n\t\tconst nodes = normalize( items );\n\n\t\tfor ( const node of nodes ) {\n\t\t\t// If node that is being added to this element is already inside another element, first remove it from the old parent.\n\t\t\tif ( node.parent !== null ) {\n\t\t\t\tnode._remove();\n\t\t\t}\n\n\t\t\tnode.parent = this;\n\t\t}\n\n\t\tthis._children._insertNodes( index, nodes );\n\t}\n\n\t/**\n\t * Removes one or more nodes starting at the given index and sets\n\t * {@link module:engine/model/node~Node#parent parent} of these nodes to `null`.\n\t *\n\t * @see module:engine/model/writer~Writer#remove\n\t * @protected\n\t * @param {Number} index Index of the first node to remove.\n\t * @param {Number} [howMany=1] Number of nodes to remove.\n\t * @returns {Array.<module:engine/model/node~Node>} Array containing removed nodes.\n\t */\n\t_removeChildren( index, howMany = 1 ) {\n\t\tconst nodes = this._children._removeNodes( index, howMany );\n\n\t\tfor ( const node of nodes ) {\n\t\t\tnode.parent = null;\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t/**\n\t * Creates an `Element` instance from given plain object (i.e. parsed JSON string).\n\t * Converts `Element` children to proper nodes.\n\t *\n\t * @param {Object} json Plain object to be converted to `Element`.\n\t * @returns {module:engine/model/element~Element} `Element` instance created using given plain object.\n\t */\n\tstatic fromJSON( json ) {\n\t\tlet children = null;\n\n\t\tif ( json.children ) {\n\t\t\tchildren = [];\n\n\t\t\tfor ( const child of json.children ) {\n\t\t\t\tif ( child.name ) {\n\t\t\t\t\t// If child has name property, it is an Element.\n\t\t\t\t\tchildren.push( Element.fromJSON( child ) );\n\t\t\t\t} else {\n\t\t\t\t\t// Otherwise, it is a Text node.\n\t\t\t\t\tchildren.push( Text.fromJSON( child ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn new Element( json.name, json.attributes, children );\n\t}\n}\n\n// Converts strings to Text and non-iterables to arrays.\n//\n// @param {String|module:engine/model/item~Item|Iterable.<String|module:engine/model/item~Item>}\n// @returns {Iterable.<module:engine/model/node~Node>}\nfunction normalize( nodes ) {\n\t// Separate condition because string is iterable.\n\tif ( typeof nodes == 'string' ) {\n\t\treturn [ new Text( nodes ) ];\n\t}\n\n\tif ( !isIterable( nodes ) ) {\n\t\tnodes = [ nodes ];\n\t}\n\n\t// Array.from to enable .map() on non-arrays.\n\treturn Array.from( nodes )\n\t\t.map( node => {\n\t\t\tif ( typeof node == 'string' ) {\n\t\t\t\treturn new Text( node );\n\t\t\t}\n\n\t\t\tif ( node instanceof TextProxy ) {\n\t\t\t\treturn new Text( node.data, node.getAttributes() );\n\t\t\t}\n\n\t\t\treturn node;\n\t\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/treewalker\n */\n\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport Element from './element';\nimport Position from './position';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Position iterator class. It allows to iterate forward and backward over the document.\n */\nexport default class TreeWalker {\n\t/**\n\t * Creates a range iterator. All parameters are optional, but you have to specify either `boundaries` or `startPosition`.\n\t *\n\t * @constructor\n\t * @param {Object} [options={}] Object with configuration.\n\t * @param {'forward'|'backward'} [options.direction='forward'] Walking direction.\n\t * @param {module:engine/model/range~Range} [options.boundaries=null] Range to define boundaries of the iterator.\n\t * @param {module:engine/model/position~Position} [options.startPosition] Starting position.\n\t * @param {Boolean} [options.singleCharacters=false] Flag indicating whether all consecutive characters with the same attributes\n\t * should be returned one by one as multiple {@link module:engine/model/textproxy~TextProxy} (`true`) objects or as one\n\t * {@link module:engine/model/textproxy~TextProxy} (`false`).\n\t * @param {Boolean} [options.shallow=false] Flag indicating whether iterator should enter elements or not. If the\n\t * iterator is shallow child nodes of any iterated node will not be returned along with `elementEnd` tag.\n\t * @param {Boolean} [options.ignoreElementEnd=false] Flag indicating whether iterator should ignore `elementEnd`\n\t * tags. If the option is true walker will not return a parent node of start position. If this option is `true`\n\t * each {@link module:engine/model/element~Element} will be returned once, while if the option is `false` they might be returned\n\t * twice: for `'elementStart'` and `'elementEnd'`.\n\t */\n\tconstructor( options = {} ) {\n\t\tif ( !options.boundaries && !options.startPosition ) {\n\t\t\t/**\n\t\t\t * Neither boundaries nor starting position of a `TreeWalker` have been defined.\n\t\t\t *\n\t\t\t * @error model-tree-walker-no-start-position\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-tree-walker-no-start-position: Neither boundaries nor starting position have been defined.',\n\t\t\t\tnull\n\t\t\t);\n\t\t}\n\n\t\tconst direction = options.direction || 'forward';\n\n\t\tif ( direction != 'forward' && direction != 'backward' ) {\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-tree-walker-unknown-direction: Only `backward` and `forward` direction allowed.',\n\t\t\t\toptions,\n\t\t\t\t{ direction }\n\t\t\t);\n\t\t}\n\n\t\t/**\n\t\t * Walking direction. Defaults `'forward'`.\n\t\t *\n\t\t * @readonly\n\t\t * @member {'backward'|'forward'} module:engine/model/treewalker~TreeWalker#direction\n\t\t */\n\t\tthis.direction = direction;\n\n\t\t/**\n\t\t * Iterator boundaries.\n\t\t *\n\t\t * When the iterator is walking `'forward'` on the end of boundary or is walking `'backward'`\n\t\t * on the start of boundary, then `{ done: true }` is returned.\n\t\t *\n\t\t * If boundaries are not defined they are set before first and after last child of the root node.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/range~Range} module:engine/model/treewalker~TreeWalker#boundaries\n\t\t */\n\t\tthis.boundaries = options.boundaries || null;\n\n\t\t/**\n\t\t * Iterator position. This is always static position, even if the initial position was a\n\t\t * {@link module:engine/model/liveposition~LivePosition live position}. If start position is not defined then position depends\n\t\t * on {@link #direction}. If direction is `'forward'` position starts form the beginning, when direction\n\t\t * is `'backward'` position starts from the end.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/position~Position} module:engine/model/treewalker~TreeWalker#position\n\t\t */\n\t\tif ( options.startPosition ) {\n\t\t\tthis.position = options.startPosition.clone();\n\t\t} else {\n\t\t\tthis.position = Position._createAt( this.boundaries[ this.direction == 'backward' ? 'end' : 'start' ] );\n\t\t}\n\n\t\t// Reset position stickiness in case it was set to other value, as the stickiness is kept after cloning.\n\t\tthis.position.stickiness = 'toNone';\n\n\t\t/**\n\t\t * Flag indicating whether all consecutive characters with the same attributes should be\n\t\t * returned as one {@link module:engine/model/textproxy~TextProxy} (`true`) or one by one (`false`).\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} module:engine/model/treewalker~TreeWalker#singleCharacters\n\t\t */\n\t\tthis.singleCharacters = !!options.singleCharacters;\n\n\t\t/**\n\t\t * Flag indicating whether iterator should enter elements or not. If the iterator is shallow child nodes of any\n\t\t * iterated node will not be returned along with `elementEnd` tag.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} module:engine/model/treewalker~TreeWalker#shallow\n\t\t */\n\t\tthis.shallow = !!options.shallow;\n\n\t\t/**\n\t\t * Flag indicating whether iterator should ignore `elementEnd` tags. If the option is true walker will not\n\t\t * return a parent node of the start position. If this option is `true` each {@link module:engine/model/element~Element} will\n\t\t * be returned once, while if the option is `false` they might be returned twice:\n\t\t * for `'elementStart'` and `'elementEnd'`.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} module:engine/model/treewalker~TreeWalker#ignoreElementEnd\n\t\t */\n\t\tthis.ignoreElementEnd = !!options.ignoreElementEnd;\n\n\t\t/**\n\t\t * Start boundary cached for optimization purposes.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/element~Element} module:engine/model/treewalker~TreeWalker#_boundaryStartParent\n\t\t */\n\t\tthis._boundaryStartParent = this.boundaries ? this.boundaries.start.parent : null;\n\n\t\t/**\n\t\t * End boundary cached for optimization purposes.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/element~Element} module:engine/model/treewalker~TreeWalker#_boundaryEndParent\n\t\t */\n\t\tthis._boundaryEndParent = this.boundaries ? this.boundaries.end.parent : null;\n\n\t\t/**\n\t\t * Parent of the most recently visited node. Cached for optimization purposes.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment}\n\t\t * module:engine/model/treewalker~TreeWalker#_visitedParent\n\t\t */\n\t\tthis._visitedParent = this.position.parent;\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * @returns {Iterable.<module:engine/model/treewalker~TreeWalkerValue>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Moves {@link #position} in the {@link #direction} skipping values as long as the callback function returns `true`.\n\t *\n\t * For example:\n\t *\n\t * \t\twalker.skip( value => value.type == 'text' ); // <paragraph>[]foo</paragraph> -> <paragraph>foo[]</paragraph>\n\t * \t\twalker.skip( () => true ); // Move the position to the end: <paragraph>[]foo</paragraph> -> <paragraph>foo</paragraph>[]\n\t * \t\twalker.skip( () => false ); // Do not move the position.\n\t *\n\t * @param {Function} skip Callback function. Gets {@link module:engine/model/treewalker~TreeWalkerValue} and should\n\t * return `true` if the value should be skipped or `false` if not.\n\t */\n\tskip( skip ) {\n\t\tlet done, value, prevPosition, prevVisitedParent;\n\n\t\tdo {\n\t\t\tprevPosition = this.position;\n\t\t\tprevVisitedParent = this._visitedParent;\n\n\t\t\t( { done, value } = this.next() );\n\t\t} while ( !done && skip( value ) );\n\n\t\tif ( !done ) {\n\t\t\tthis.position = prevPosition;\n\t\t\tthis._visitedParent = prevVisitedParent;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the next tree walker's value.\n\t *\n\t * @returns {module:engine/model/treewalker~TreeWalkerValue} Next tree walker's value.\n\t */\n\tnext() {\n\t\tif ( this.direction == 'forward' ) {\n\t\t\treturn this._next();\n\t\t} else {\n\t\t\treturn this._previous();\n\t\t}\n\t}\n\n\t/**\n\t * Makes a step forward in model. Moves the {@link #position} to the next position and returns the encountered value.\n\t *\n\t * @private\n\t * @returns {Object}\n\t * @returns {Boolean} return.done True if iterator is done.\n\t * @returns {module:engine/model/treewalker~TreeWalkerValue} return.value Information about taken step.\n\t */\n\t_next() {\n\t\tconst previousPosition = this.position;\n\t\tconst position = this.position.clone();\n\t\tconst parent = this._visitedParent;\n\n\t\t// We are at the end of the root.\n\t\tif ( parent.parent === null && position.offset === parent.maxOffset ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\t// We reached the walker boundary.\n\t\tif ( parent === this._boundaryEndParent && position.offset == this.boundaries.end.offset ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\tconst node = position.textNode ? position.textNode : position.nodeAfter;\n\n\t\tif ( node instanceof Element ) {\n\t\t\tif ( !this.shallow ) {\n\t\t\t\t// Manual operations on path internals for optimization purposes. Here and in the rest of the method.\n\t\t\t\tposition.path.push( 0 );\n\t\t\t\tthis._visitedParent = node;\n\t\t\t} else {\n\t\t\t\tposition.offset++;\n\t\t\t}\n\n\t\t\tthis.position = position;\n\n\t\t\treturn formatReturnValue( 'elementStart', node, previousPosition, position, 1 );\n\t\t} else if ( node instanceof Text ) {\n\t\t\tlet charactersCount;\n\n\t\t\tif ( this.singleCharacters ) {\n\t\t\t\tcharactersCount = 1;\n\t\t\t} else {\n\t\t\t\tlet offset = node.endOffset;\n\n\t\t\t\tif ( this._boundaryEndParent == parent && this.boundaries.end.offset < offset ) {\n\t\t\t\t\toffset = this.boundaries.end.offset;\n\t\t\t\t}\n\n\t\t\t\tcharactersCount = offset - position.offset;\n\t\t\t}\n\n\t\t\tconst offsetInTextNode = position.offset - node.startOffset;\n\t\t\tconst item = new TextProxy( node, offsetInTextNode, charactersCount );\n\n\t\t\tposition.offset += charactersCount;\n\t\t\tthis.position = position;\n\n\t\t\treturn formatReturnValue( 'text', item, previousPosition, position, charactersCount );\n\t\t} else {\n\t\t\t// `node` is not set, we reached the end of current `parent`.\n\t\t\tposition.path.pop();\n\t\t\tposition.offset++;\n\t\t\tthis.position = position;\n\t\t\tthis._visitedParent = parent.parent;\n\n\t\t\tif ( this.ignoreElementEnd ) {\n\t\t\t\treturn this._next();\n\t\t\t} else {\n\t\t\t\treturn formatReturnValue( 'elementEnd', parent, previousPosition, position );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Makes a step backward in model. Moves the {@link #position} to the previous position and returns the encountered value.\n\t *\n\t * @private\n\t * @returns {Object}\n\t * @returns {Boolean} return.done True if iterator is done.\n\t * @returns {module:engine/model/treewalker~TreeWalkerValue} return.value Information about taken step.\n\t */\n\t_previous() {\n\t\tconst previousPosition = this.position;\n\t\tconst position = this.position.clone();\n\t\tconst parent = this._visitedParent;\n\n\t\t// We are at the beginning of the root.\n\t\tif ( parent.parent === null && position.offset === 0 ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\t// We reached the walker boundary.\n\t\tif ( parent == this._boundaryStartParent && position.offset == this.boundaries.start.offset ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\t// Get node just before current position\n\t\tconst node = position.textNode ? position.textNode : position.nodeBefore;\n\n\t\tif ( node instanceof Element ) {\n\t\t\tposition.offset--;\n\n\t\t\tif ( !this.shallow ) {\n\t\t\t\tposition.path.push( node.maxOffset );\n\t\t\t\tthis.position = position;\n\t\t\t\tthis._visitedParent = node;\n\n\t\t\t\tif ( this.ignoreElementEnd ) {\n\t\t\t\t\treturn this._previous();\n\t\t\t\t} else {\n\t\t\t\t\treturn formatReturnValue( 'elementEnd', node, previousPosition, position );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.position = position;\n\n\t\t\t\treturn formatReturnValue( 'elementStart', node, previousPosition, position, 1 );\n\t\t\t}\n\t\t} else if ( node instanceof Text ) {\n\t\t\tlet charactersCount;\n\n\t\t\tif ( this.singleCharacters ) {\n\t\t\t\tcharactersCount = 1;\n\t\t\t} else {\n\t\t\t\tlet offset = node.startOffset;\n\n\t\t\t\tif ( this._boundaryStartParent == parent && this.boundaries.start.offset > offset ) {\n\t\t\t\t\toffset = this.boundaries.start.offset;\n\t\t\t\t}\n\n\t\t\t\tcharactersCount = position.offset - offset;\n\t\t\t}\n\n\t\t\tconst offsetInTextNode = position.offset - node.startOffset;\n\t\t\tconst item = new TextProxy( node, offsetInTextNode - charactersCount, charactersCount );\n\n\t\t\tposition.offset -= charactersCount;\n\t\t\tthis.position = position;\n\n\t\t\treturn formatReturnValue( 'text', item, previousPosition, position, charactersCount );\n\t\t} else {\n\t\t\t// `node` is not set, we reached the beginning of current `parent`.\n\t\t\tposition.path.pop();\n\t\t\tthis.position = position;\n\t\t\tthis._visitedParent = parent.parent;\n\n\t\t\treturn formatReturnValue( 'elementStart', parent, previousPosition, position, 1 );\n\t\t}\n\t}\n}\n\nfunction formatReturnValue( type, item, previousPosition, nextPosition, length ) {\n\treturn {\n\t\tdone: false,\n\t\tvalue: {\n\t\t\ttype,\n\t\t\titem,\n\t\t\tpreviousPosition,\n\t\t\tnextPosition,\n\t\t\tlength\n\t\t}\n\t};\n}\n\n/**\n * Type of the step made by {@link module:engine/model/treewalker~TreeWalker}.\n * Possible values: `'elementStart'` if walker is at the beginning of a node, `'elementEnd'` if walker is at the end of node,\n * `'character'` if walker traversed over a character, or `'text'` if walker traversed over multiple characters (available in\n * character merging mode, see {@link module:engine/model/treewalker~TreeWalker#constructor}).\n *\n * @typedef {'elementStart'|'elementEnd'|'character'|'text'} module:engine/model/treewalker~TreeWalkerValueType\n */\n\n/**\n * Object returned by {@link module:engine/model/treewalker~TreeWalker} when traversing tree model.\n *\n * @typedef {Object} module:engine/model/treewalker~TreeWalkerValue\n * @property {module:engine/model/treewalker~TreeWalkerValueType} type\n * @property {module:engine/model/item~Item} item Item between old and new positions of {@link module:engine/model/treewalker~TreeWalker}.\n * @property {module:engine/model/position~Position} previousPosition Previous position of the iterator.\n * * Forward iteration: For `'elementEnd'` it is the last position inside the element. For all other types it is the\n * position before the item.\n * * Backward iteration: For `'elementStart'` it is the first position inside the element. For all other types it is\n * the position after item.\n * @property {module:engine/model/position~Position} nextPosition Next position of the iterator.\n * * Forward iteration: For `'elementStart'` it is the first position inside the element. For all other types it is\n * the position after the item.\n * * Backward iteration: For `'elementEnd'` it is last position inside element. For all other types it is the position\n * before the item.\n * @property {Number} [length] Length of the item. For `'elementStart'` and `'character'` it is 1. For `'text'` it is\n * the length of the text. For `'elementEnd'` it is `undefined`.\n */\n\n/**\n * Tree walking directions.\n *\n * @typedef {'forward'|'backward'} module:engine/view/treewalker~TreeWalkerDirection\n */\n","/**\n * Gets the last element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the last element of `array`.\n * @example\n *\n * _.last([1, 2, 3]);\n * // => 3\n */\nfunction last(array) {\n var length = array == null ? 0 : array.length;\n return length ? array[length - 1] : undefined;\n}\n\nexport default last;\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/position\n */\n\nimport TreeWalker from './treewalker';\nimport compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport Text from './text';\nimport { last } from 'lodash-es';\n\n// To check if component is loaded more than once.\nimport '@ckeditor/ckeditor5-utils/src/version';\n\n/**\n * Represents a position in the model tree.\n *\n * A position is represented by its {@link module:engine/model/position~Position#root} and\n * a {@link module:engine/model/position~Position#path} in that root.\n *\n * You can create position instances via its constructor or the `createPosition*()` factory methods of\n * {@link module:engine/model/model~Model} and {@link module:engine/model/writer~Writer}.\n *\n * **Note:** Position is based on offsets, not indexes. This means that a position between two text nodes\n * `foo` and `bar` has offset `3`, not `1`. See {@link module:engine/model/position~Position#path} for more information.\n *\n * Since a position in the model is represented by a {@link module:engine/model/position~Position#root position root} and\n * {@link module:engine/model/position~Position#path position path} it is possible to create positions placed in non-existing places.\n * This requirement is important for operational transformation algorithms.\n *\n * Also, {@link module:engine/model/operation/operation~Operation operations}\n * kept in the {@link module:engine/model/document~Document#history document history}\n * are storing positions (and ranges) which were correct when those operations were applied, but may not be correct\n * after the document has changed.\n *\n * When changes are applied to the model, it may also happen that {@link module:engine/model/position~Position#parent position parent}\n * will change even if position path has not changed. Keep in mind, that if a position leads to non-existing element,\n * {@link module:engine/model/position~Position#parent} and some other properties and methods will throw errors.\n *\n * In most cases, position with wrong path is caused by an error in code, but it is sometimes needed, as described above.\n */\nexport default class Position {\n\t/**\n\t * Creates a position.\n\t *\n\t * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} root Root of the position.\n\t * @param {Array.<Number>} path Position path. See {@link module:engine/model/position~Position#path}.\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.\n\t * See {@link module:engine/model/position~PositionStickiness}.\n\t */\n\tconstructor( root, path, stickiness = 'toNone' ) {\n\t\tif ( !root.is( 'element' ) && !root.is( 'documentFragment' ) ) {\n\t\t\t/**\n\t\t\t * Position root is invalid.\n\t\t\t *\n\t\t\t * Positions can only be anchored in elements or document fragments.\n\t\t\t *\n\t\t\t * @error model-position-root-invalid\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-position-root-invalid: Position root invalid.',\n\t\t\t\troot\n\t\t\t);\n\t\t}\n\n\t\tif ( !( path instanceof Array ) || path.length === 0 ) {\n\t\t\t/**\n\t\t\t * Position path must be an array with at least one item.\n\t\t\t *\n\t\t\t * @error model-position-path-incorrect-format\n\t\t\t * @param path\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-position-path-incorrect-format: Position path must be an array with at least one item.',\n\t\t\t\troot,\n\t\t\t\t{ path }\n\t\t\t);\n\t\t}\n\n\t\t// Normalize the root and path (if element was passed).\n\t\tpath = root.getPath().concat( path );\n\t\troot = root.root;\n\n\t\t/**\n\t\t * Root of the position path.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment}\n\t\t * module:engine/model/position~Position#root\n\t\t */\n\t\tthis.root = root;\n\n\t\t/**\n\t\t * Position of the node in the tree. **Path contains offsets, not indexes.**\n\t\t *\n\t\t * Position can be placed before, after or in a {@link module:engine/model/node~Node node} if that node has\n\t\t * {@link module:engine/model/node~Node#offsetSize} greater than `1`. Items in position path are\n\t\t * {@link module:engine/model/node~Node#startOffset starting offsets} of position ancestors, starting from direct root children,\n\t\t * down to the position offset in it's parent.\n\t\t *\n\t\t *\t\t ROOT\n\t\t *\t\t |- P before: [ 0 ] after: [ 1 ]\n\t\t *\t\t |- UL before: [ 1 ] after: [ 2 ]\n\t\t *\t\t |- LI before: [ 1, 0 ] after: [ 1, 1 ]\n\t\t *\t\t | |- foo before: [ 1, 0, 0 ] after: [ 1, 0, 3 ]\n\t\t *\t\t |- LI before: [ 1, 1 ] after: [ 1, 2 ]\n\t\t *\t\t |- bar before: [ 1, 1, 0 ] after: [ 1, 1, 3 ]\n\t\t *\n\t\t * `foo` and `bar` are representing {@link module:engine/model/text~Text text nodes}. Since text nodes has offset size\n\t\t * greater than `1` you can place position offset between their start and end:\n\t\t *\n\t\t *\t\t ROOT\n\t\t *\t\t |- P\n\t\t *\t\t |- UL\n\t\t *\t\t |- LI\n\t\t *\t\t | |- f^o|o ^ has path: [ 1, 0, 1 ] | has path: [ 1, 0, 2 ]\n\t\t *\t\t |- LI\n\t\t *\t\t |- b^a|r ^ has path: [ 1, 1, 1 ] | has path: [ 1, 1, 2 ]\n\t\t *\n\t\t * @readonly\n\t\t * @member {Array.<Number>} module:engine/model/position~Position#path\n\t\t */\n\t\tthis.path = path;\n\n\t\t/**\n\t\t * Position stickiness. See {@link module:engine/model/position~PositionStickiness}.\n\t\t *\n\t\t * @member {module:engine/model/position~PositionStickiness} module:engine/model/position~Position#stickiness\n\t\t */\n\t\tthis.stickiness = stickiness;\n\t}\n\n\t/**\n\t * Offset at which this position is located in its {@link module:engine/model/position~Position#parent parent}. It is equal\n\t * to the last item in position {@link module:engine/model/position~Position#path path}.\n\t *\n\t * @type {Number}\n\t */\n\tget offset() {\n\t\treturn last( this.path );\n\t}\n\n\t/**\n\t * @param {Number} newOffset\n\t */\n\tset offset( newOffset ) {\n\t\tthis.path[ this.path.length - 1 ] = newOffset;\n\t}\n\n\t/**\n\t * Parent element of this position.\n\t *\n\t * Keep in mind that `parent` value is calculated when the property is accessed.\n\t * If {@link module:engine/model/position~Position#path position path}\n\t * leads to a non-existing element, `parent` property will throw error.\n\t *\n\t * Also it is a good idea to cache `parent` property if it is used frequently in an algorithm (i.e. in a long loop).\n\t *\n\t * @readonly\n\t * @type {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tget parent() {\n\t\tlet parent = this.root;\n\n\t\tfor ( let i = 0; i < this.path.length - 1; i++ ) {\n\t\t\tparent = parent.getChild( parent.offsetToIndex( this.path[ i ] ) );\n\n\t\t\tif ( !parent ) {\n\t\t\t\tthrow new CKEditorError( 'model-position-path-incorrect: The position\\'s path is incorrect.', this, { position: this } );\n\t\t\t}\n\t\t}\n\n\t\tif ( parent.is( 'text' ) ) {\n\t\t\t/**\n\t\t\t * The position's path is incorrect. This means that a position does not point to\n\t\t\t * a correct place in the tree and hence, some of its methods and getters cannot work correctly.\n\t\t\t *\n\t\t\t * **Note**: Unlike DOM and view positions, in the model, the\n\t\t\t * {@link module:engine/model/position~Position#parent position's parent} is always an element or a document fragment.\n\t\t\t * The last offset in the {@link module:engine/model/position~Position#path position's path} is the point in this element where\n\t\t\t * this position points.\n\t\t\t *\n\t\t\t * Read more about model positions and offsets in\n\t\t\t * the {@glink framework/guides/architecture/editing-engine#indexes-and-offsets Editing engine architecture guide}.\n\t\t\t *\n\t\t\t * @error position-incorrect-path\n\t\t\t * @param {module:engine/model/position~Position} position The incorrect position.\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'model-position-path-incorrect: The position\\'s path is incorrect.', this, { position: this } );\n\t\t}\n\n\t\treturn parent;\n\t}\n\n\t/**\n\t * Position {@link module:engine/model/position~Position#offset offset} converted to an index in position's parent node. It is\n\t * equal to the {@link module:engine/model/node~Node#index index} of a node after this position. If position is placed\n\t * in text node, position index is equal to the index of that text node.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget index() {\n\t\treturn this.parent.offsetToIndex( this.offset );\n\t}\n\n\t/**\n\t * Returns {@link module:engine/model/text~Text text node} instance in which this position is placed or `null` if this\n\t * position is not in a text node.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/text~Text|null}\n\t */\n\tget textNode() {\n\t\tconst node = this.parent.getChild( this.index );\n\n\t\treturn ( node instanceof Text && node.startOffset < this.offset ) ? node : null;\n\t}\n\n\t/**\n\t * Node directly after this position or `null` if this position is in text node.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/node~Node|null}\n\t */\n\tget nodeAfter() {\n\t\treturn this.textNode === null ? this.parent.getChild( this.index ) : null;\n\t}\n\n\t/**\n\t * Node directly before this position or `null` if this position is in text node.\n\t *\n\t * @readonly\n\t * @type {Node}\n\t */\n\tget nodeBefore() {\n\t\treturn this.textNode === null ? this.parent.getChild( this.index - 1 ) : null;\n\t}\n\n\t/**\n\t * Is `true` if position is at the beginning of its {@link module:engine/model/position~Position#parent parent}, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isAtStart() {\n\t\treturn this.offset === 0;\n\t}\n\n\t/**\n\t * Is `true` if position is at the end of its {@link module:engine/model/position~Position#parent parent}, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isAtEnd() {\n\t\treturn this.offset == this.parent.maxOffset;\n\t}\n\n\t/**\n\t * Checks whether this position is before or after given position.\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @param {module:engine/model/position~Position} otherPosition Position to compare with.\n\t * @returns {module:engine/model/position~PositionRelation}\n\t */\n\tcompareWith( otherPosition ) {\n\t\tif ( this.root != otherPosition.root ) {\n\t\t\treturn 'different';\n\t\t}\n\n\t\tconst result = compareArrays( this.path, otherPosition.path );\n\n\t\tswitch ( result ) {\n\t\t\tcase 'same':\n\t\t\t\treturn 'same';\n\n\t\t\tcase 'prefix':\n\t\t\t\treturn 'before';\n\n\t\t\tcase 'extension':\n\t\t\t\treturn 'after';\n\n\t\t\tdefault:\n\t\t\t\treturn this.path[ result ] < otherPosition.path[ result ] ? 'before' : 'after';\n\t\t}\n\t}\n\n\t/**\n\t * Gets the farthest position which matches the callback using\n\t * {@link module:engine/model/treewalker~TreeWalker TreeWalker}.\n\t *\n\t * For example:\n\t *\n\t * \t\tgetLastMatchingPosition( value => value.type == 'text' );\n\t * \t\t// <paragraph>[]foo</paragraph> -> <paragraph>foo[]</paragraph>\n\t *\n\t * \t\tgetLastMatchingPosition( value => value.type == 'text', { direction: 'backward' } );\n\t * \t\t// <paragraph>foo[]</paragraph> -> <paragraph>[]foo</paragraph>\n\t *\n\t * \t\tgetLastMatchingPosition( value => false );\n\t * \t\t// Do not move the position.\n\t *\n\t * @param {Function} skip Callback function. Gets {@link module:engine/model/treewalker~TreeWalkerValue} and should\n\t * return `true` if the value should be skipped or `false` if not.\n\t * @param {Object} options Object with configuration options. See {@link module:engine/model/treewalker~TreeWalker}.\n\t *\n\t * @returns {module:engine/model/position~Position} The position after the last item which matches the `skip` callback test.\n\t */\n\tgetLastMatchingPosition( skip, options = {} ) {\n\t\toptions.startPosition = this;\n\n\t\tconst treeWalker = new TreeWalker( options );\n\t\ttreeWalker.skip( skip );\n\n\t\treturn treeWalker.position;\n\t}\n\n\t/**\n\t * Returns a path to this position's parent. Parent path is equal to position {@link module:engine/model/position~Position#path path}\n\t * but without the last item.\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @returns {Array.<Number>} Path to the parent.\n\t */\n\tgetParentPath() {\n\t\treturn this.path.slice( 0, -1 );\n\t}\n\n\t/**\n\t * Returns ancestors array of this position, that is this position's parent and its ancestors.\n\t *\n\t * @returns {Array.<module:engine/model/item~Item>} Array with ancestors.\n\t */\n\tgetAncestors() {\n\t\tif ( this.parent.is( 'documentFragment' ) ) {\n\t\t\treturn [ this.parent ];\n\t\t} else {\n\t\t\treturn this.parent.getAncestors( { includeSelf: true } );\n\t\t}\n\t}\n\n\t/**\n\t * Returns the slice of two position {@link #path paths} which is identical. The {@link #root roots}\n\t * of these two paths must be identical.\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @param {module:engine/model/position~Position} position The second position.\n\t * @returns {Array.<Number>} The common path.\n\t */\n\tgetCommonPath( position ) {\n\t\tif ( this.root != position.root ) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// We find on which tree-level start and end have the lowest common ancestor\n\t\tconst cmp = compareArrays( this.path, position.path );\n\t\t// If comparison returned string it means that arrays are same.\n\t\tconst diffAt = ( typeof cmp == 'string' ) ? Math.min( this.path.length, position.path.length ) : cmp;\n\n\t\treturn this.path.slice( 0, diffAt );\n\t}\n\n\t/**\n\t * Returns an {@link module:engine/model/element~Element} or {@link module:engine/model/documentfragment~DocumentFragment}\n\t * which is a common ancestor of both positions. The {@link #root roots} of these two positions must be identical.\n\t *\n\t * @param {module:engine/model/position~Position} position The second position.\n\t * @returns {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment|null}\n\t */\n\tgetCommonAncestor( position ) {\n\t\tconst ancestorsA = this.getAncestors();\n\t\tconst ancestorsB = position.getAncestors();\n\n\t\tlet i = 0;\n\n\t\twhile ( ancestorsA[ i ] == ancestorsB[ i ] && ancestorsA[ i ] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i === 0 ? null : ancestorsA[ i - 1 ];\n\t}\n\n\t/**\n\t * Returns a new instance of `Position`, that has same {@link #parent parent} but it's offset\n\t * is shifted by `shift` value (can be a negative value).\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @param {Number} shift Offset shift. Can be a negative value.\n\t * @returns {module:engine/model/position~Position} Shifted position.\n\t */\n\tgetShiftedBy( shift ) {\n\t\tconst shifted = this.clone();\n\n\t\tconst offset = shifted.offset + shift;\n\t\tshifted.offset = offset < 0 ? 0 : offset;\n\n\t\treturn shifted;\n\t}\n\n\t/**\n\t * Checks whether this position is after given position.\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @see module:engine/model/position~Position#isBefore\n\t * @param {module:engine/model/position~Position} otherPosition Position to compare with.\n\t * @returns {Boolean} True if this position is after given position.\n\t */\n\tisAfter( otherPosition ) {\n\t\treturn this.compareWith( otherPosition ) == 'after';\n\t}\n\n\t/**\n\t * Checks whether this position is before given position.\n\t *\n\t * **Note:** watch out when using negation of the value returned by this method, because the negation will also\n\t * be `true` if positions are in different roots and you might not expect this. You should probably use\n\t * `a.isAfter( b ) || a.isEqual( b )` or `!a.isBefore( p ) && a.root == b.root` in most scenarios. If your\n\t * condition uses multiple `isAfter` and `isBefore` checks, build them so they do not use negated values, i.e.:\n\t *\n\t *\t\tif ( a.isBefore( b ) && c.isAfter( d ) ) {\n\t *\t\t\t// do A.\n\t *\t\t} else {\n\t *\t\t\t// do B.\n\t *\t\t}\n\t *\n\t * or, if you have only one if-branch:\n\t *\n\t *\t\tif ( !( a.isBefore( b ) && c.isAfter( d ) ) {\n\t *\t\t\t// do B.\n\t *\t\t}\n\t *\n\t * rather than:\n\t *\n\t *\t\tif ( !a.isBefore( b ) || && !c.isAfter( d ) ) {\n\t *\t\t\t// do B.\n\t *\t\t} else {\n\t *\t\t\t// do A.\n\t *\t\t}\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @param {module:engine/model/position~Position} otherPosition Position to compare with.\n\t * @returns {Boolean} True if this position is before given position.\n\t */\n\tisBefore( otherPosition ) {\n\t\treturn this.compareWith( otherPosition ) == 'before';\n\t}\n\n\t/**\n\t * Checks whether this position is equal to given position.\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @param {module:engine/model/position~Position} otherPosition Position to compare with.\n\t * @returns {Boolean} True if positions are same.\n\t */\n\tisEqual( otherPosition ) {\n\t\treturn this.compareWith( otherPosition ) == 'same';\n\t}\n\n\t/**\n\t * Checks whether this position is touching given position. Positions touch when there are no text nodes\n\t * or empty nodes in a range between them. Technically, those positions are not equal but in many cases\n\t * they are very similar or even indistinguishable.\n\t *\n\t * @param {module:engine/model/position~Position} otherPosition Position to compare with.\n\t * @returns {Boolean} True if positions touch.\n\t */\n\tisTouching( otherPosition ) {\n\t\tlet left = null;\n\t\tlet right = null;\n\t\tconst compare = this.compareWith( otherPosition );\n\n\t\tswitch ( compare ) {\n\t\t\tcase 'same':\n\t\t\t\treturn true;\n\n\t\t\tcase 'before':\n\t\t\t\tleft = Position._createAt( this );\n\t\t\t\tright = Position._createAt( otherPosition );\n\t\t\t\tbreak;\n\n\t\t\tcase 'after':\n\t\t\t\tleft = Position._createAt( otherPosition );\n\t\t\t\tright = Position._createAt( this );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\n\t\t// Cached for optimization purposes.\n\t\tlet leftParent = left.parent;\n\n\t\twhile ( left.path.length + right.path.length ) {\n\t\t\tif ( left.isEqual( right ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif ( left.path.length > right.path.length ) {\n\t\t\t\tif ( left.offset !== leftParent.maxOffset ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tleft.path = left.path.slice( 0, -1 );\n\t\t\t\tleftParent = leftParent.parent;\n\t\t\t\tleft.offset++;\n\t\t\t} else {\n\t\t\t\tif ( right.offset !== 0 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tright.path = right.path.slice( 0, -1 );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tposition.is( 'position' ); // -> true\n\t *\t\tposition.is( 'model:position' ); // -> true\n\t *\n\t *\t\tposition.is( 'view:position' ); // -> false\n\t *\t\tposition.is( 'documentSelection' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'position' || type == 'model:position';\n\t}\n\n\t/**\n\t * Checks if two positions are in the same parent.\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @param {module:engine/model/position~Position} position Position to compare with.\n\t * @returns {Boolean} `true` if positions have the same parent, `false` otherwise.\n\t */\n\thasSameParentAs( position ) {\n\t\tif ( this.root !== position.root ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst thisParentPath = this.getParentPath();\n\t\tconst posParentPath = position.getParentPath();\n\n\t\treturn compareArrays( thisParentPath, posParentPath ) == 'same';\n\t}\n\n\t/**\n\t * Returns a copy of this position that is transformed by given `operation`.\n\t *\n\t * The new position's parameters are updated accordingly to the effect of the `operation`.\n\t *\n\t * For example, if `n` nodes are inserted before the position, the returned position {@link ~Position#offset} will be\n\t * increased by `n`. If the position was in a merged element, it will be accordingly moved to the new element, etc.\n\t *\n\t * This method is safe to use it on non-existing positions (for example during operational transformation).\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation Operation to transform by.\n\t * @returns {module:engine/model/position~Position} Transformed position.\n\t */\n\tgetTransformedByOperation( operation ) {\n\t\tlet result;\n\n\t\tswitch ( operation.type ) {\n\t\t\tcase 'insert':\n\t\t\t\tresult = this._getTransformedByInsertOperation( operation );\n\t\t\t\tbreak;\n\t\t\tcase 'move':\n\t\t\tcase 'remove':\n\t\t\tcase 'reinsert':\n\t\t\t\tresult = this._getTransformedByMoveOperation( operation );\n\t\t\t\tbreak;\n\t\t\tcase 'split':\n\t\t\t\tresult = this._getTransformedBySplitOperation( operation );\n\t\t\t\tbreak;\n\t\t\tcase 'merge':\n\t\t\t\tresult = this._getTransformedByMergeOperation( operation );\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tresult = Position._createAt( this );\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Returns a copy of this position transformed by an insert operation.\n\t *\n\t * @protected\n\t * @param {module:engine/model/operation/insertoperation~InsertOperation} operation\n\t * @returns {module:engine/model/position~Position}\n\t */\n\t_getTransformedByInsertOperation( operation ) {\n\t\treturn this._getTransformedByInsertion( operation.position, operation.howMany );\n\t}\n\n\t/**\n\t * Returns a copy of this position transformed by a move operation.\n\t *\n\t * @protected\n\t * @param {module:engine/model/operation/moveoperation~MoveOperation} operation\n\t * @returns {module:engine/model/position~Position}\n\t */\n\t_getTransformedByMoveOperation( operation ) {\n\t\treturn this._getTransformedByMove( operation.sourcePosition, operation.targetPosition, operation.howMany );\n\t}\n\n\t/**\n\t * Returns a copy of this position transformed by a split operation.\n\t *\n\t * @protected\n\t * @param {module:engine/model/operation/splitoperation~SplitOperation} operation\n\t * @returns {module:engine/model/position~Position}\n\t */\n\t_getTransformedBySplitOperation( operation ) {\n\t\tconst movedRange = operation.movedRange;\n\n\t\tconst isContained = movedRange.containsPosition( this ) ||\n\t\t\t( movedRange.start.isEqual( this ) && this.stickiness == 'toNext' );\n\n\t\tif ( isContained ) {\n\t\t\treturn this._getCombined( operation.splitPosition, operation.moveTargetPosition );\n\t\t} else {\n\t\t\tif ( operation.graveyardPosition ) {\n\t\t\t\treturn this._getTransformedByMove( operation.graveyardPosition, operation.insertionPosition, 1 );\n\t\t\t} else {\n\t\t\t\treturn this._getTransformedByInsertion( operation.insertionPosition, 1 );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns a copy of this position transformed by merge operation.\n\t *\n\t * @protected\n\t * @param {module:engine/model/operation/mergeoperation~MergeOperation} operation\n\t * @returns {module:engine/model/position~Position}\n\t */\n\t_getTransformedByMergeOperation( operation ) {\n\t\tconst movedRange = operation.movedRange;\n\t\tconst isContained = movedRange.containsPosition( this ) || movedRange.start.isEqual( this );\n\n\t\tlet pos;\n\n\t\tif ( isContained ) {\n\t\t\tpos = this._getCombined( operation.sourcePosition, operation.targetPosition );\n\n\t\t\tif ( operation.sourcePosition.isBefore( operation.targetPosition ) ) {\n\t\t\t\t// Above happens during OT when the merged element is moved before the merged-to element.\n\t\t\t\tpos = pos._getTransformedByDeletion( operation.deletionPosition, 1 );\n\t\t\t}\n\t\t} else if ( this.isEqual( operation.deletionPosition ) ) {\n\t\t\tpos = Position._createAt( operation.deletionPosition );\n\t\t} else {\n\t\t\tpos = this._getTransformedByMove( operation.deletionPosition, operation.graveyardPosition, 1 );\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t/**\n\t * Returns a copy of this position that is updated by removing `howMany` nodes starting from `deletePosition`.\n\t * It may happen that this position is in a removed node. If that is the case, `null` is returned instead.\n\t *\n\t * @protected\n\t * @param {module:engine/model/position~Position} deletePosition Position before the first removed node.\n\t * @param {Number} howMany How many nodes are removed.\n\t * @returns {module:engine/model/position~Position|null} Transformed position or `null`.\n\t */\n\t_getTransformedByDeletion( deletePosition, howMany ) {\n\t\tconst transformed = Position._createAt( this );\n\n\t\t// This position can't be affected if deletion was in a different root.\n\t\tif ( this.root != deletePosition.root ) {\n\t\t\treturn transformed;\n\t\t}\n\n\t\tif ( compareArrays( deletePosition.getParentPath(), this.getParentPath() ) == 'same' ) {\n\t\t\t// If nodes are removed from the node that is pointed by this position...\n\t\t\tif ( deletePosition.offset < this.offset ) {\n\t\t\t\t// And are removed from before an offset of that position...\n\t\t\t\tif ( deletePosition.offset + howMany > this.offset ) {\n\t\t\t\t\t// Position is in removed range, it's no longer in the tree.\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\t// Decrement the offset accordingly.\n\t\t\t\t\ttransformed.offset -= howMany;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( compareArrays( deletePosition.getParentPath(), this.getParentPath() ) == 'prefix' ) {\n\t\t\t// If nodes are removed from a node that is on a path to this position...\n\t\t\tconst i = deletePosition.path.length - 1;\n\n\t\t\tif ( deletePosition.offset <= this.path[ i ] ) {\n\t\t\t\t// And are removed from before next node of that path...\n\t\t\t\tif ( deletePosition.offset + howMany > this.path[ i ] ) {\n\t\t\t\t\t// If the next node of that path is removed return null\n\t\t\t\t\t// because the node containing this position got removed.\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\t// Otherwise, decrement index on that path.\n\t\t\t\t\ttransformed.path[ i ] -= howMany;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn transformed;\n\t}\n\n\t/**\n\t * Returns a copy of this position that is updated by inserting `howMany` nodes at `insertPosition`.\n\t *\n\t * @protected\n\t * @param {module:engine/model/position~Position} insertPosition Position where nodes are inserted.\n\t * @param {Number} howMany How many nodes are inserted.\n\t * @returns {module:engine/model/position~Position} Transformed position.\n\t */\n\t_getTransformedByInsertion( insertPosition, howMany ) {\n\t\tconst transformed = Position._createAt( this );\n\n\t\t// This position can't be affected if insertion was in a different root.\n\t\tif ( this.root != insertPosition.root ) {\n\t\t\treturn transformed;\n\t\t}\n\n\t\tif ( compareArrays( insertPosition.getParentPath(), this.getParentPath() ) == 'same' ) {\n\t\t\t// If nodes are inserted in the node that is pointed by this position...\n\t\t\tif ( insertPosition.offset < this.offset || ( insertPosition.offset == this.offset && this.stickiness != 'toPrevious' ) ) {\n\t\t\t\t// And are inserted before an offset of that position...\n\t\t\t\t// \"Push\" this positions offset.\n\t\t\t\ttransformed.offset += howMany;\n\t\t\t}\n\t\t} else if ( compareArrays( insertPosition.getParentPath(), this.getParentPath() ) == 'prefix' ) {\n\t\t\t// If nodes are inserted in a node that is on a path to this position...\n\t\t\tconst i = insertPosition.path.length - 1;\n\n\t\t\tif ( insertPosition.offset <= this.path[ i ] ) {\n\t\t\t\t// And are inserted before next node of that path...\n\t\t\t\t// \"Push\" the index on that path.\n\t\t\t\ttransformed.path[ i ] += howMany;\n\t\t\t}\n\t\t}\n\n\t\treturn transformed;\n\t}\n\n\t/**\n\t * Returns a copy of this position that is updated by moving `howMany` nodes from `sourcePosition` to `targetPosition`.\n\t *\n\t * @protected\n\t * @param {module:engine/model/position~Position} sourcePosition Position before the first element to move.\n\t * @param {module:engine/model/position~Position} targetPosition Position where moved elements will be inserted.\n\t * @param {Number} howMany How many consecutive nodes to move, starting from `sourcePosition`.\n\t * @returns {module:engine/model/position~Position} Transformed position.\n\t */\n\t_getTransformedByMove( sourcePosition, targetPosition, howMany ) {\n\t\t// Update target position, as it could be affected by nodes removal.\n\t\ttargetPosition = targetPosition._getTransformedByDeletion( sourcePosition, howMany );\n\n\t\tif ( sourcePosition.isEqual( targetPosition ) ) {\n\t\t\t// If `targetPosition` is equal to `sourcePosition` this isn't really any move. Just return position as it is.\n\t\t\treturn Position._createAt( this );\n\t\t}\n\n\t\t// Moving a range removes nodes from their original position. We acknowledge this by proper transformation.\n\t\tconst transformed = this._getTransformedByDeletion( sourcePosition, howMany );\n\n\t\tconst isMoved = transformed === null ||\n\t\t\t( sourcePosition.isEqual( this ) && this.stickiness == 'toNext' ) ||\n\t\t\t( sourcePosition.getShiftedBy( howMany ).isEqual( this ) && this.stickiness == 'toPrevious' );\n\n\t\tif ( isMoved ) {\n\t\t\t// This position is inside moved range (or sticks to it).\n\t\t\t// In this case, we calculate a combination of this position, move source position and target position.\n\t\t\treturn this._getCombined( sourcePosition, targetPosition );\n\t\t} else {\n\t\t\t// This position is not inside a removed range.\n\t\t\t//\n\t\t\t// In next step, we simply reflect inserting `howMany` nodes, which might further affect the position.\n\t\t\treturn transformed._getTransformedByInsertion( targetPosition, howMany );\n\t\t}\n\t}\n\n\t/**\n\t * Returns a new position that is a combination of this position and given positions.\n\t *\n\t * The combined position is a copy of this position transformed by moving a range starting at `source` position\n\t * to the `target` position. It is expected that this position is inside the moved range.\n\t *\n\t * Example:\n\t *\n\t *\t\tlet original = model.createPositionFromPath( root, [ 2, 3, 1 ] );\n\t *\t\tlet source = model.createPositionFromPath( root, [ 2, 2 ] );\n\t *\t\tlet target = model.createPositionFromPath( otherRoot, [ 1, 1, 3 ] );\n\t *\t\toriginal._getCombined( source, target ); // path is [ 1, 1, 4, 1 ], root is `otherRoot`\n\t *\n\t * Explanation:\n\t *\n\t * We have a position `[ 2, 3, 1 ]` and move some nodes from `[ 2, 2 ]` to `[ 1, 1, 3 ]`. The original position\n\t * was inside moved nodes and now should point to the new place. The moved nodes will be after\n\t * positions `[ 1, 1, 3 ]`, `[ 1, 1, 4 ]`, `[ 1, 1, 5 ]`. Since our position was in the second moved node,\n\t * the transformed position will be in a sub-tree of a node at `[ 1, 1, 4 ]`. Looking at original path, we\n\t * took care of `[ 2, 3 ]` part of it. Now we have to add the rest of the original path to the transformed path.\n\t * Finally, the transformed position will point to `[ 1, 1, 4, 1 ]`.\n\t *\n\t * @protected\n\t * @param {module:engine/model/position~Position} source Beginning of the moved range.\n\t * @param {module:engine/model/position~Position} target Position where the range is moved.\n\t * @returns {module:engine/model/position~Position} Combined position.\n\t */\n\t_getCombined( source, target ) {\n\t\tconst i = source.path.length - 1;\n\n\t\t// The first part of a path to combined position is a path to the place where nodes were moved.\n\t\tconst combined = Position._createAt( target );\n\t\tcombined.stickiness = this.stickiness;\n\n\t\t// Then we have to update the rest of the path.\n\n\t\t// Fix the offset because this position might be after `from` position and we have to reflect that.\n\t\tcombined.offset = combined.offset + this.path[ i ] - source.offset;\n\n\t\t// Then, add the rest of the path.\n\t\t// If this position is at the same level as `from` position nothing will get added.\n\t\tcombined.path = combined.path.concat( this.path.slice( i + 1 ) );\n\n\t\treturn combined;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\treturn {\n\t\t\troot: this.root.toJSON(),\n\t\t\tpath: Array.from( this.path ),\n\t\t\tstickiness: this.stickiness\n\t\t};\n\t}\n\n\t/**\n\t * Returns a new position that is equal to current position.\n\t *\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tclone() {\n\t\treturn new this.constructor( this.root, this.path, this.stickiness );\n\t}\n\n\t/**\n\t * Creates position at the given location. The location can be specified as:\n\t *\n\t * * a {@link module:engine/model/position~Position position},\n\t * * parent element and offset (offset defaults to `0`),\n\t * * parent element and `'end'` (sets position at the end of that element),\n\t * * {@link module:engine/model/item~Item model item} and `'before'` or `'after'` (sets position before or after given model item).\n\t *\n\t * This method is a shortcut to other factory methods such as:\n\t *\n\t * * {@link module:engine/model/position~Position._createBefore},\n\t * * {@link module:engine/model/position~Position._createAfter}.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when the\n\t * first parameter is a {@link module:engine/model/item~Item model item}.\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness. Used only when the\n\t * first parameter is a {@link module:engine/model/item~Item model item}.\n\t * @protected\n\t */\n\tstatic _createAt( itemOrPosition, offset, stickiness = 'toNone' ) {\n\t\tif ( itemOrPosition instanceof Position ) {\n\t\t\treturn new Position( itemOrPosition.root, itemOrPosition.path, itemOrPosition.stickiness );\n\t\t} else {\n\t\t\tconst node = itemOrPosition;\n\n\t\t\tif ( offset == 'end' ) {\n\t\t\t\toffset = node.maxOffset;\n\t\t\t} else if ( offset == 'before' ) {\n\t\t\t\treturn this._createBefore( node, stickiness );\n\t\t\t} else if ( offset == 'after' ) {\n\t\t\t\treturn this._createAfter( node, stickiness );\n\t\t\t} else if ( offset !== 0 && !offset ) {\n\t\t\t\t/**\n\t\t\t\t * {@link module:engine/model/model~Model#createPositionAt `Model#createPositionAt()`}\n\t\t\t\t * requires the offset to be specified when the first parameter is a model item.\n\t\t\t\t *\n\t\t\t\t * @error model-createPositionAt-offset-required\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'model-createPositionAt-offset-required: ' +\n\t\t\t\t\t'Model#createPositionAt() requires the offset when the first parameter is a model item.',\n\t\t\t\t\t[ this, itemOrPosition ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif ( !node.is( 'element' ) && !node.is( 'documentFragment' ) ) {\n\t\t\t\t/**\n\t\t\t\t * Position parent have to be a model element or model document fragment.\n\t\t\t\t *\n\t\t\t\t * @error model-position-parent-incorrect\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'model-position-parent-incorrect: Position parent have to be a element or document fragment.',\n\t\t\t\t\t[ this, itemOrPosition ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst path = node.getPath();\n\n\t\t\tpath.push( offset );\n\n\t\t\treturn new this( node.root, path, stickiness );\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new position, after given {@link module:engine/model/item~Item model item}.\n\t *\n\t * @param {module:engine/model/item~Item} item Item after which the position should be placed.\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.\n\t * @returns {module:engine/model/position~Position}\n\t * @protected\n\t */\n\tstatic _createAfter( item, stickiness ) {\n\t\tif ( !item.parent ) {\n\t\t\t/**\n\t\t\t * You can not make a position after a root element.\n\t\t\t *\n\t\t\t * @error model-position-after-root\n\t\t\t * @param {module:engine/model/item~Item} root\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-position-after-root: You cannot make a position after root.',\n\t\t\t\t[ this, item ],\n\t\t\t\t{ root: item }\n\t\t\t);\n\t\t}\n\n\t\treturn this._createAt( item.parent, item.endOffset, stickiness );\n\t}\n\n\t/**\n\t * Creates a new position, before the given {@link module:engine/model/item~Item model item}.\n\t *\n\t * @param {module:engine/model/item~Item} item Item before which the position should be placed.\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.\n\t * @returns {module:engine/model/position~Position}\n\t * @protected\n\t */\n\tstatic _createBefore( item, stickiness ) {\n\t\tif ( !item.parent ) {\n\t\t\t/**\n\t\t\t * You can not make a position before a root element.\n\t\t\t *\n\t\t\t * @error model-position-before-root\n\t\t\t * @param {module:engine/model/item~Item} root\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-position-before-root: You cannot make a position before root.',\n\t\t\t\titem,\n\t\t\t\t{ root: item }\n\t\t\t);\n\t\t}\n\n\t\treturn this._createAt( item.parent, item.startOffset, stickiness );\n\t}\n\n\t/**\n\t * Creates a `Position` instance from given plain object (i.e. parsed JSON string).\n\t *\n\t * @param {Object} json Plain object to be converted to `Position`.\n\t * @param {module:engine/model/document~Document} doc Document object that will be position owner.\n\t * @returns {module:engine/model/position~Position} `Position` instance created using given plain object.\n\t */\n\tstatic fromJSON( json, doc ) {\n\t\tif ( json.root === '$graveyard' ) {\n\t\t\tconst pos = new Position( doc.graveyard, json.path );\n\t\t\tpos.stickiness = json.stickiness;\n\n\t\t\treturn pos;\n\t\t}\n\n\t\tif ( !doc.getRoot( json.root ) ) {\n\t\t\t/**\n\t\t\t * Cannot create position for document. Root with specified name does not exist.\n\t\t\t *\n\t\t\t * @error model-position-fromjson-no-root\n\t\t\t * @param {String} rootName\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-position-fromjson-no-root: Cannot create position for document. Root with specified name does not exist.',\n\t\t\t\tdoc,\n\t\t\t\t{ rootName: json.root }\n\t\t\t);\n\t\t}\n\n\t\treturn new Position( doc.getRoot( json.root ), json.path, json.stickiness );\n\t}\n}\n\n/**\n * A flag indicating whether this position is `'before'` or `'after'` or `'same'` as given position.\n * If positions are in different roots `'different'` flag is returned.\n *\n * @typedef {String} module:engine/model/position~PositionRelation\n */\n\n/**\n * Represents how position is \"sticking\" with neighbour nodes. Used to define how position should be transformed (moved)\n * in edge cases. Possible values: `'toNone'`, `'toNext'`, `'toPrevious'`.\n *\n * Examples:\n *\n *\t\tInsert. Position is at | and nodes are inserted at the same position, marked as ^:\n *\n *\t\t- sticks to none: <p>f^|oo</p> -> <p>fbar|oo</p>\n *\t\t- sticks to next node: <p>f^|oo</p> -> <p>fbar|oo</p>\n *\t\t- sticks to previous node: <p>f|^oo</p> -> <p>f|baroo</p>\n *\n *\n *\t\tMove. Position is at | and range [oo] is moved to position ^:\n *\n *\t\t- sticks to none: <p>f|[oo]</p><p>b^ar</p> -> <p>f|</p><p>booar</p>\n *\t\t- sticks to none: <p>f[oo]|</p><p>b^ar</p> -> <p>f|</p><p>booar</p>\n *\n *\t\t- sticks to next node: <p>f|[oo]</p><p>b^ar</p> -> <p>f</p><p>b|ooar</p>\n *\t\t- sticks to next node: <p>f[oo]|</p><p>b^ar</p> -> <p>f|</p><p>booar</p>\n *\n *\t\t- sticks to previous node: <p>f|[oo]</p><p>b^ar</p> -> <p>f|</p><p>booar</p>\n *\t\t- sticks to previous node: <p>f[oo]|</p><p>b^ar</p> -> <p>f</p><p>boo|ar</p>\n *\n * @typedef {String} module:engine/model/position~PositionStickiness\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/range\n */\n\nimport Position from './position';\nimport TreeWalker from './treewalker';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';\n\n/**\n * Represents a range in the model tree.\n *\n * A range is defined by its {@link module:engine/model/range~Range#start} and {@link module:engine/model/range~Range#end}\n * positions.\n *\n * You can create range instances via its constructor or the `createRange*()` factory methods of\n * {@link module:engine/model/model~Model} and {@link module:engine/model/writer~Writer}.\n */\nexport default class Range {\n\t/**\n\t * Creates a range spanning from `start` position to `end` position.\n\t *\n\t * @param {module:engine/model/position~Position} start Start position.\n\t * @param {module:engine/model/position~Position} [end] End position. If not set, range will be collapsed at `start` position.\n\t */\n\tconstructor( start, end = null ) {\n\t\t/**\n\t\t * Start position.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/position~Position}\n\t\t */\n\t\tthis.start = Position._createAt( start );\n\n\t\t/**\n\t\t * End position.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/position~Position}\n\t\t */\n\t\tthis.end = end ? Position._createAt( end ) : Position._createAt( start );\n\n\t\t// If the range is collapsed, treat in a similar way as a position and set its boundaries stickiness to 'toNone'.\n\t\t// In other case, make the boundaries stick to the \"inside\" of the range.\n\t\tthis.start.stickiness = this.isCollapsed ? 'toNone' : 'toNext';\n\t\tthis.end.stickiness = this.isCollapsed ? 'toNone' : 'toPrevious';\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Iterates over all {@link module:engine/model/item~Item items} that are in this range and returns\n\t * them together with additional information like length or {@link module:engine/model/position~Position positions},\n\t * grouped as {@link module:engine/model/treewalker~TreeWalkerValue}.\n\t * It iterates over all {@link module:engine/model/textproxy~TextProxy text contents} that are inside the range\n\t * and all the {@link module:engine/model/element~Element}s that are entered into when iterating over this range.\n\t *\n\t * This iterator uses {@link module:engine/model/treewalker~TreeWalker} with `boundaries` set to this range\n\t * and `ignoreElementEnd` option set to `true`.\n\t *\n\t * @returns {Iterable.<module:engine/model/treewalker~TreeWalkerValue>}\n\t */\n\t* [ Symbol.iterator ]() {\n\t\tyield* new TreeWalker( { boundaries: this, ignoreElementEnd: true } );\n\t}\n\n\t/**\n\t * Returns whether the range is collapsed, that is if {@link #start} and\n\t * {@link #end} positions are equal.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isCollapsed() {\n\t\treturn this.start.isEqual( this.end );\n\t}\n\n\t/**\n\t * Returns whether this range is flat, that is if {@link #start} position and\n\t * {@link #end} position are in the same {@link module:engine/model/position~Position#parent}.\n\t *\n\t * @type {Boolean}\n\t */\n\tget isFlat() {\n\t\tconst startParentPath = this.start.getParentPath();\n\t\tconst endParentPath = this.end.getParentPath();\n\n\t\treturn compareArrays( startParentPath, endParentPath ) == 'same';\n\t}\n\n\t/**\n\t * Range root element.\n\t *\n\t * @type {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this.start.root;\n\t}\n\n\t/**\n\t * Checks whether this range contains given {@link module:engine/model/position~Position position}.\n\t *\n\t * @param {module:engine/model/position~Position} position Position to check.\n\t * @returns {Boolean} `true` if given {@link module:engine/model/position~Position position} is contained\n\t * in this range,`false` otherwise.\n\t */\n\tcontainsPosition( position ) {\n\t\treturn position.isAfter( this.start ) && position.isBefore( this.end );\n\t}\n\n\t/**\n\t * Checks whether this range contains given {@link ~Range range}.\n\t *\n\t * @param {module:engine/model/range~Range} otherRange Range to check.\n\t * @param {Boolean} [loose=false] Whether the check is loose or strict. If the check is strict (`false`), compared range cannot\n\t * start or end at the same position as this range boundaries. If the check is loose (`true`), compared range can start, end or\n\t * even be equal to this range. Note that collapsed ranges are always compared in strict mode.\n\t * @returns {Boolean} `true` if given {@link ~Range range} boundaries are contained by this range, `false` otherwise.\n\t */\n\tcontainsRange( otherRange, loose = false ) {\n\t\tif ( otherRange.isCollapsed ) {\n\t\t\tloose = false;\n\t\t}\n\n\t\tconst containsStart = this.containsPosition( otherRange.start ) || ( loose && this.start.isEqual( otherRange.start ) );\n\t\tconst containsEnd = this.containsPosition( otherRange.end ) || ( loose && this.end.isEqual( otherRange.end ) );\n\n\t\treturn containsStart && containsEnd;\n\t}\n\n\t/**\n\t * Checks whether given {@link module:engine/model/item~Item} is inside this range.\n\t *\n\t * @param {module:engine/model/item~Item} item Model item to check.\n\t */\n\tcontainsItem( item ) {\n\t\tconst pos = Position._createBefore( item );\n\n\t\treturn this.containsPosition( pos ) || this.start.isEqual( pos );\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\trange.is( 'range' ); // -> true\n\t *\t\trange.is( 'model:range' ); // -> true\n\t *\n\t *\t\trange.is( 'view:range' ); // -> false\n\t *\t\trange.is( 'documentSelection' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'range' || type == 'model:range';\n\t}\n\n\t/**\n\t * Two ranges are equal if their {@link #start} and {@link #end} positions are equal.\n\t *\n\t * @param {module:engine/model/range~Range} otherRange Range to compare with.\n\t * @returns {Boolean} `true` if ranges are equal, `false` otherwise.\n\t */\n\tisEqual( otherRange ) {\n\t\treturn this.start.isEqual( otherRange.start ) && this.end.isEqual( otherRange.end );\n\t}\n\n\t/**\n\t * Checks and returns whether this range intersects with given range.\n\t *\n\t * @param {module:engine/model/range~Range} otherRange Range to compare with.\n\t * @returns {Boolean} `true` if ranges intersect, `false` otherwise.\n\t */\n\tisIntersecting( otherRange ) {\n\t\treturn this.start.isBefore( otherRange.end ) && this.end.isAfter( otherRange.start );\n\t}\n\n\t/**\n\t * Computes which part(s) of this {@link ~Range range} is not a part of given {@link ~Range range}.\n\t * Returned array contains zero, one or two {@link ~Range ranges}.\n\t *\n\t * Examples:\n\t *\n\t *\t\tlet range = model.createRange(\n\t *\t\t\tmodel.createPositionFromPath( root, [ 2, 7 ] ),\n\t *\t\t\tmodel.createPositionFromPath( root, [ 4, 0, 1 ] )\n\t *\t\t);\n\t *\t\tlet otherRange = model.createRange( model.createPositionFromPath( root, [ 1 ] ), model.createPositionFromPath( root, [ 5 ] ) );\n\t *\t\tlet transformed = range.getDifference( otherRange );\n\t *\t\t// transformed array has no ranges because `otherRange` contains `range`\n\t *\n\t *\t\totherRange = model.createRange( model.createPositionFromPath( root, [ 1 ] ), model.createPositionFromPath( root, [ 3 ] ) );\n\t *\t\ttransformed = range.getDifference( otherRange );\n\t *\t\t// transformed array has one range: from [ 3 ] to [ 4, 0, 1 ]\n\t *\n\t *\t\totherRange = model.createRange( model.createPositionFromPath( root, [ 3 ] ), model.createPositionFromPath( root, [ 4 ] ) );\n\t *\t\ttransformed = range.getDifference( otherRange );\n\t *\t\t// transformed array has two ranges: from [ 2, 7 ] to [ 3 ] and from [ 4 ] to [ 4, 0, 1 ]\n\t *\n\t * @param {module:engine/model/range~Range} otherRange Range to differentiate against.\n\t * @returns {Array.<module:engine/model/range~Range>} The difference between ranges.\n\t */\n\tgetDifference( otherRange ) {\n\t\tconst ranges = [];\n\n\t\tif ( this.isIntersecting( otherRange ) ) {\n\t\t\t// Ranges intersect.\n\n\t\t\tif ( this.containsPosition( otherRange.start ) ) {\n\t\t\t\t// Given range start is inside this range. This means that we have to\n\t\t\t\t// add shrunken range - from the start to the middle of this range.\n\t\t\t\tranges.push( new Range( this.start, otherRange.start ) );\n\t\t\t}\n\n\t\t\tif ( this.containsPosition( otherRange.end ) ) {\n\t\t\t\t// Given range end is inside this range. This means that we have to\n\t\t\t\t// add shrunken range - from the middle of this range to the end.\n\t\t\t\tranges.push( new Range( otherRange.end, this.end ) );\n\t\t\t}\n\t\t} else {\n\t\t\t// Ranges do not intersect, return the original range.\n\t\t\tranges.push( new Range( this.start, this.end ) );\n\t\t}\n\n\t\treturn ranges;\n\t}\n\n\t/**\n\t * Returns an intersection of this {@link ~Range range} and given {@link ~Range range}.\n\t * Intersection is a common part of both of those ranges. If ranges has no common part, returns `null`.\n\t *\n\t * Examples:\n\t *\n\t *\t\tlet range = model.createRange(\n\t *\t\t\tmodel.createPositionFromPath( root, [ 2, 7 ] ),\n\t *\t\t\tmodel.createPositionFromPath( root, [ 4, 0, 1 ] )\n\t *\t\t);\n\t *\t\tlet otherRange = model.createRange( model.createPositionFromPath( root, [ 1 ] ), model.createPositionFromPath( root, [ 2 ] ) );\n\t *\t\tlet transformed = range.getIntersection( otherRange ); // null - ranges have no common part\n\t *\n\t *\t\totherRange = model.createRange( model.createPositionFromPath( root, [ 3 ] ), model.createPositionFromPath( root, [ 5 ] ) );\n\t *\t\ttransformed = range.getIntersection( otherRange ); // range from [ 3 ] to [ 4, 0, 1 ]\n\t *\n\t * @param {module:engine/model/range~Range} otherRange Range to check for intersection.\n\t * @returns {module:engine/model/range~Range|null} A common part of given ranges or `null` if ranges have no common part.\n\t */\n\tgetIntersection( otherRange ) {\n\t\tif ( this.isIntersecting( otherRange ) ) {\n\t\t\t// Ranges intersect, so a common range will be returned.\n\t\t\t// At most, it will be same as this range.\n\t\t\tlet commonRangeStart = this.start;\n\t\t\tlet commonRangeEnd = this.end;\n\n\t\t\tif ( this.containsPosition( otherRange.start ) ) {\n\t\t\t\t// Given range start is inside this range. This means thaNt we have to\n\t\t\t\t// shrink common range to the given range start.\n\t\t\t\tcommonRangeStart = otherRange.start;\n\t\t\t}\n\n\t\t\tif ( this.containsPosition( otherRange.end ) ) {\n\t\t\t\t// Given range end is inside this range. This means that we have to\n\t\t\t\t// shrink common range to the given range end.\n\t\t\t\tcommonRangeEnd = otherRange.end;\n\t\t\t}\n\n\t\t\treturn new Range( commonRangeStart, commonRangeEnd );\n\t\t}\n\n\t\t// Ranges do not intersect, so they do not have common part.\n\t\treturn null;\n\t}\n\n\t/**\n\t * Computes and returns the smallest set of {@link #isFlat flat} ranges, that covers this range in whole.\n\t *\n\t * See an example of a model structure (`[` and `]` are range boundaries):\n\t *\n\t *\t\troot root\n\t *\t\t |- element DIV DIV P2 P3 DIV\n\t *\t\t | |- element H H P1 f o o b a r H P4\n\t *\t\t | | |- \"fir[st\" fir[st lorem se]cond ipsum\n\t *\t\t | |- element P1\n\t *\t\t | | |- \"lorem\" ||\n\t *\t\t |- element P2 ||\n\t *\t\t | |- \"foo\" VV\n\t *\t\t |- element P3\n\t *\t\t | |- \"bar\" root\n\t *\t\t |- element DIV DIV [P2 P3] DIV\n\t *\t\t | |- element H H [P1] f o o b a r H P4\n\t *\t\t | | |- \"se]cond\" fir[st] lorem [se]cond ipsum\n\t *\t\t | |- element P4\n\t *\t\t | | |- \"ipsum\"\n\t *\n\t * As it can be seen, letters contained in the range are: `stloremfoobarse`, spread across different parents.\n\t * We are looking for minimal set of flat ranges that contains the same nodes.\n\t *\n\t * Minimal flat ranges for above range `( [ 0, 0, 3 ], [ 3, 0, 2 ] )` will be:\n\t *\n\t *\t\t( [ 0, 0, 3 ], [ 0, 0, 5 ] ) = \"st\"\n\t *\t\t( [ 0, 1 ], [ 0, 2 ] ) = element P1 (\"lorem\")\n\t *\t\t( [ 1 ], [ 3 ] ) = element P2, element P3 (\"foobar\")\n\t *\t\t( [ 3, 0, 0 ], [ 3, 0, 2 ] ) = \"se\"\n\t *\n\t * **Note:** if an {@link module:engine/model/element~Element element} is not wholly contained in this range, it won't be returned\n\t * in any of the returned flat ranges. See in the example how `H` elements at the beginning and at the end of the range\n\t * were omitted. Only their parts that were wholly in the range were returned.\n\t *\n\t * **Note:** this method is not returning flat ranges that contain no nodes.\n\t *\n\t * @returns {Array.<module:engine/model/range~Range>} Array of flat ranges covering this range.\n\t */\n\tgetMinimalFlatRanges() {\n\t\tconst ranges = [];\n\t\tconst diffAt = this.start.getCommonPath( this.end ).length;\n\n\t\tconst pos = Position._createAt( this.start );\n\t\tlet posParent = pos.parent;\n\n\t\t// Go up.\n\t\twhile ( pos.path.length > diffAt + 1 ) {\n\t\t\tconst howMany = posParent.maxOffset - pos.offset;\n\n\t\t\tif ( howMany !== 0 ) {\n\t\t\t\tranges.push( new Range( pos, pos.getShiftedBy( howMany ) ) );\n\t\t\t}\n\n\t\t\tpos.path = pos.path.slice( 0, -1 );\n\t\t\tpos.offset++;\n\t\t\tposParent = posParent.parent;\n\t\t}\n\n\t\t// Go down.\n\t\twhile ( pos.path.length <= this.end.path.length ) {\n\t\t\tconst offset = this.end.path[ pos.path.length - 1 ];\n\t\t\tconst howMany = offset - pos.offset;\n\n\t\t\tif ( howMany !== 0 ) {\n\t\t\t\tranges.push( new Range( pos, pos.getShiftedBy( howMany ) ) );\n\t\t\t}\n\n\t\t\tpos.offset = offset;\n\t\t\tpos.path.push( 0 );\n\t\t}\n\n\t\treturn ranges;\n\t}\n\n\t/**\n\t * Creates a {@link module:engine/model/treewalker~TreeWalker TreeWalker} instance with this range as a boundary.\n\t *\n\t * For example, to iterate over all items in the entire document root:\n\t *\n\t *\t\t// Create a range spanning over the entire root content:\n\t *\t\tconst range = editor.model.createRangeIn( editor.model.document.getRoot() );\n\t *\n\t *\t\t// Iterate over all items in this range:\n\t *\t\tfor ( const value of range.getWalker() ) {\n\t *\t\t\tconsole.log( value.item );\n\t *\t\t}\n\t *\n\t * @param {Object} options Object with configuration options. See {@link module:engine/model/treewalker~TreeWalker}.\n\t * @param {module:engine/model/position~Position} [options.startPosition]\n\t * @param {Boolean} [options.singleCharacters=false]\n\t * @param {Boolean} [options.shallow=false]\n\t * @param {Boolean} [options.ignoreElementEnd=false]\n\t */\n\tgetWalker( options = {} ) {\n\t\toptions.boundaries = this;\n\n\t\treturn new TreeWalker( options );\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all {@link module:engine/model/item~Item items} that are in this range and returns\n\t * them.\n\t *\n\t * This method uses {@link module:engine/model/treewalker~TreeWalker} with `boundaries` set to this range and `ignoreElementEnd` option\n\t * set to `true`. However it returns only {@link module:engine/model/item~Item model items},\n\t * not {@link module:engine/model/treewalker~TreeWalkerValue}.\n\t *\n\t * You may specify additional options for the tree walker. See {@link module:engine/model/treewalker~TreeWalker} for\n\t * a full list of available options.\n\t *\n\t * @method getItems\n\t * @param {Object} options Object with configuration options. See {@link module:engine/model/treewalker~TreeWalker}.\n\t * @returns {Iterable.<module:engine/model/item~Item>}\n\t */\n\t* getItems( options = {} ) {\n\t\toptions.boundaries = this;\n\t\toptions.ignoreElementEnd = true;\n\n\t\tconst treeWalker = new TreeWalker( options );\n\n\t\tfor ( const value of treeWalker ) {\n\t\t\tyield value.item;\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all {@link module:engine/model/position~Position positions} that are boundaries or\n\t * contained in this range.\n\t *\n\t * This method uses {@link module:engine/model/treewalker~TreeWalker} with `boundaries` set to this range. However it returns only\n\t * {@link module:engine/model/position~Position positions}, not {@link module:engine/model/treewalker~TreeWalkerValue}.\n\t *\n\t * You may specify additional options for the tree walker. See {@link module:engine/model/treewalker~TreeWalker} for\n\t * a full list of available options.\n\t *\n\t * @param {Object} options Object with configuration options. See {@link module:engine/model/treewalker~TreeWalker}.\n\t * @returns {Iterable.<module:engine/model/position~Position>}\n\t */\n\t* getPositions( options = {} ) {\n\t\toptions.boundaries = this;\n\n\t\tconst treeWalker = new TreeWalker( options );\n\n\t\tyield treeWalker.position;\n\n\t\tfor ( const value of treeWalker ) {\n\t\t\tyield value.nextPosition;\n\t\t}\n\t}\n\n\t/**\n\t * Returns a range that is a result of transforming this range by given `operation`.\n\t *\n\t * **Note:** transformation may break one range into multiple ranges (for example, when a part of the range is\n\t * moved to a different part of document tree). For this reason, an array is returned by this method and it\n\t * may contain one or more `Range` instances.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation Operation to transform range by.\n\t * @returns {Array.<module:engine/model/range~Range>} Range which is the result of transformation.\n\t */\n\tgetTransformedByOperation( operation ) {\n\t\tswitch ( operation.type ) {\n\t\t\tcase 'insert':\n\t\t\t\treturn this._getTransformedByInsertOperation( operation );\n\t\t\tcase 'move':\n\t\t\tcase 'remove':\n\t\t\tcase 'reinsert':\n\t\t\t\treturn this._getTransformedByMoveOperation( operation );\n\t\t\tcase 'split':\n\t\t\t\treturn [ this._getTransformedBySplitOperation( operation ) ];\n\t\t\tcase 'merge':\n\t\t\t\treturn [ this._getTransformedByMergeOperation( operation ) ];\n\t\t}\n\n\t\treturn [ new Range( this.start, this.end ) ];\n\t}\n\n\t/**\n\t * Returns a range that is a result of transforming this range by multiple `operations`.\n\t *\n\t * @see ~Range#getTransformedByOperation\n\t * @param {Iterable.<module:engine/model/operation/operation~Operation>} operations Operations to transform the range by.\n\t * @returns {Array.<module:engine/model/range~Range>} Range which is the result of transformation.\n\t */\n\tgetTransformedByOperations( operations ) {\n\t\tconst ranges = [ new Range( this.start, this.end ) ];\n\n\t\tfor ( const operation of operations ) {\n\t\t\tfor ( let i = 0; i < ranges.length; i++ ) {\n\t\t\t\tconst result = ranges[ i ].getTransformedByOperation( operation );\n\n\t\t\t\tranges.splice( i, 1, ...result );\n\t\t\t\ti += result.length - 1;\n\t\t\t}\n\t\t}\n\n\t\t// It may happen that a range is split into two, and then the part of second \"piece\" is moved into first\n\t\t// \"piece\". In this case we will have incorrect third range, which should not be included in the result --\n\t\t// because it is already included in the first \"piece\". In this loop we are looking for all such ranges that\n\t\t// are inside other ranges and we simply remove them.\n\t\tfor ( let i = 0; i < ranges.length; i++ ) {\n\t\t\tconst range = ranges[ i ];\n\n\t\t\tfor ( let j = i + 1; j < ranges.length; j++ ) {\n\t\t\t\tconst next = ranges[ j ];\n\n\t\t\t\tif ( range.containsRange( next ) || next.containsRange( range ) || range.isEqual( next ) ) {\n\t\t\t\t\tranges.splice( j, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ranges;\n\t}\n\n\t/**\n\t * Returns an {@link module:engine/model/element~Element} or {@link module:engine/model/documentfragment~DocumentFragment}\n\t * which is a common ancestor of the range's both ends (in which the entire range is contained).\n\t *\n\t * @returns {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment|null}\n\t */\n\tgetCommonAncestor() {\n\t\treturn this.start.getCommonAncestor( this.end );\n\t}\n\n\t/**\n\t * Converts `Range` to plain object and returns it.\n\t *\n\t * @returns {Object} `Node` converted to plain object.\n\t */\n\ttoJSON() {\n\t\treturn {\n\t\t\tstart: this.start.toJSON(),\n\t\t\tend: this.end.toJSON()\n\t\t};\n\t}\n\n\t/**\n\t * Returns a new range that is equal to current range.\n\t *\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tclone() {\n\t\treturn new this.constructor( this.start, this.end );\n\t}\n\n\t/**\n\t * Returns a result of transforming a copy of this range by insert operation.\n\t *\n\t * One or more ranges may be returned as a result of this transformation.\n\t *\n\t * @protected\n\t * @param {module:engine/model/operation/insertoperation~InsertOperation} operation\n\t * @returns {Array.<module:engine/model/range~Range>}\n\t */\n\t_getTransformedByInsertOperation( operation, spread = false ) {\n\t\treturn this._getTransformedByInsertion( operation.position, operation.howMany, spread );\n\t}\n\n\t/**\n\t * Returns a result of transforming a copy of this range by move operation.\n\t *\n\t * One or more ranges may be returned as a result of this transformation.\n\t *\n\t * @protected\n\t * @param {module:engine/model/operation/moveoperation~MoveOperation} operation\n\t * @returns {Array.<module:engine/model/range~Range>}\n\t */\n\t_getTransformedByMoveOperation( operation, spread = false ) {\n\t\tconst sourcePosition = operation.sourcePosition;\n\t\tconst howMany = operation.howMany;\n\t\tconst targetPosition = operation.targetPosition;\n\n\t\treturn this._getTransformedByMove( sourcePosition, targetPosition, howMany, spread );\n\t}\n\n\t/**\n\t * Returns a result of transforming a copy of this range by split operation.\n\t *\n\t * Always one range is returned. The transformation is done in a way to not break the range.\n\t *\n\t * @protected\n\t * @param {module:engine/model/operation/splitoperation~SplitOperation} operation\n\t * @returns {module:engine/model/range~Range}\n\t */\n\t_getTransformedBySplitOperation( operation ) {\n\t\tconst start = this.start._getTransformedBySplitOperation( operation );\n\t\tlet end = this.end._getTransformedBySplitOperation( operation );\n\n\t\tif ( this.end.isEqual( operation.insertionPosition ) ) {\n\t\t\tend = this.end.getShiftedBy( 1 );\n\t\t}\n\n\t\t// Below may happen when range contains graveyard element used by split operation.\n\t\tif ( start.root != end.root ) {\n\t\t\t// End position was next to the moved graveyard element and was moved with it.\n\t\t\t// Fix it by using old `end` which has proper `root`.\n\t\t\tend = this.end.getShiftedBy( -1 );\n\t\t}\n\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Returns a result of transforming a copy of this range by merge operation.\n\t *\n\t * Always one range is returned. The transformation is done in a way to not break the range.\n\t *\n\t * @protected\n\t * @param {module:engine/model/operation/mergeoperation~MergeOperation} operation\n\t * @returns {module:engine/model/range~Range}\n\t */\n\t_getTransformedByMergeOperation( operation ) {\n\t\t// Special case when the marker is set on \"the closing tag\" of an element. Marker can be set like that during\n\t\t// transformations, especially when a content of a few block elements were removed. For example:\n\t\t//\n\t\t// {} is the transformed range, [] is the removed range.\n\t\t// <p>F[o{o</p><p>B}ar</p><p>Xy]z</p>\n\t\t//\n\t\t// <p>Fo{o</p><p>B}ar</p><p>z</p>\n\t\t// <p>F{</p><p>B}ar</p><p>z</p>\n\t\t// <p>F{</p>}<p>z</p>\n\t\t// <p>F{}z</p>\n\t\t//\n\t\tif ( this.start.isEqual( operation.targetPosition ) && this.end.isEqual( operation.deletionPosition ) ) {\n\t\t\treturn new Range( this.start );\n\t\t}\n\n\t\tlet start = this.start._getTransformedByMergeOperation( operation );\n\t\tlet end = this.end._getTransformedByMergeOperation( operation );\n\n\t\tif ( start.root != end.root ) {\n\t\t\t// This happens when the end position was next to the merged (deleted) element.\n\t\t\t// Then, the end position was moved to the graveyard root. In this case we need to fix\n\t\t\t// the range cause its boundaries would be in different roots.\n\t\t\tend = this.end.getShiftedBy( -1 );\n\t\t}\n\n\t\tif ( start.isAfter( end ) ) {\n\t\t\t// This happens in three following cases:\n\t\t\t//\n\t\t\t// Case 1: Merge operation source position is before the target position (due to some transformations, OT, etc.)\n\t\t\t// This means that start can be moved before the end of the range.\n\t\t\t//\n\t\t\t// Before: <p>a{a</p><p>b}b</p><p>cc</p>\n\t\t\t// Merge: <p>b}b</p><p>cca{a</p>\n\t\t\t// Fix: <p>{b}b</p><p>ccaa</p>\n\t\t\t//\n\t\t\t// Case 2: Range start is before merged node but not directly.\n\t\t\t// Result should include all nodes that were in the original range.\n\t\t\t//\n\t\t\t// Before: <p>aa</p>{<p>cc</p><p>b}b</p>\n\t\t\t// Merge: <p>aab}b</p>{<p>cc</p>\n\t\t\t// Fix: <p>aa{bb</p><p>cc</p>}\n\t\t\t//\n\t\t\t// The range is expanded by an additional `b` letter but it is better than dropping the whole `cc` paragraph.\n\t\t\t//\n\t\t\t// Case 3: Range start is directly before merged node.\n\t\t\t// Resulting range should include only nodes from the merged element:\n\t\t\t//\n\t\t\t// Before: <p>aa</p>{<p>b}b</p><p>cc</p>\n\t\t\t// Merge: <p>aab}b</p>{<p>cc</p>\n\t\t\t// Fix: <p>aa{b}b</p><p>cc</p>\n\t\t\t//\n\n\t\t\tif ( operation.sourcePosition.isBefore( operation.targetPosition ) ) {\n\t\t\t\t// Case 1.\n\t\t\t\tstart = Position._createAt( end );\n\t\t\t\tstart.offset = 0;\n\t\t\t} else {\n\t\t\t\tif ( !operation.deletionPosition.isEqual( start ) ) {\n\t\t\t\t\t// Case 2.\n\t\t\t\t\tend = operation.deletionPosition;\n\t\t\t\t}\n\n\t\t\t\t// In both case 2 and 3 start is at the end of the merge-to element.\n\t\t\t\tstart = operation.targetPosition;\n\t\t\t}\n\n\t\t\treturn new Range( start, end );\n\t\t}\n\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Returns an array containing one or two {@link ~Range ranges} that are a result of transforming this\n\t * {@link ~Range range} by inserting `howMany` nodes at `insertPosition`. Two {@link ~Range ranges} are\n\t * returned if the insertion was inside this {@link ~Range range} and `spread` is set to `true`.\n\t *\n\t * Examples:\n\t *\n\t *\t\tlet range = model.createRange(\n\t *\t\t\tmodel.createPositionFromPath( root, [ 2, 7 ] ),\n\t *\t\t\tmodel.createPositionFromPath( root, [ 4, 0, 1 ] )\n\t *\t\t);\n\t *\t\tlet transformed = range._getTransformedByInsertion( model.createPositionFromPath( root, [ 1 ] ), 2 );\n\t *\t\t// transformed array has one range from [ 4, 7 ] to [ 6, 0, 1 ]\n\t *\n\t *\t\ttransformed = range._getTransformedByInsertion( model.createPositionFromPath( root, [ 4, 0, 0 ] ), 4 );\n\t *\t\t// transformed array has one range from [ 2, 7 ] to [ 4, 0, 5 ]\n\t *\n\t *\t\ttransformed = range._getTransformedByInsertion( model.createPositionFromPath( root, [ 3, 2 ] ), 4 );\n\t *\t\t// transformed array has one range, which is equal to original range\n\t *\n\t *\t\ttransformed = range._getTransformedByInsertion( model.createPositionFromPath( root, [ 3, 2 ] ), 4, true );\n\t *\t\t// transformed array has two ranges: from [ 2, 7 ] to [ 3, 2 ] and from [ 3, 6 ] to [ 4, 0, 1 ]\n\t *\n\t * @protected\n\t * @param {module:engine/model/position~Position} insertPosition Position where nodes are inserted.\n\t * @param {Number} howMany How many nodes are inserted.\n\t * @param {Boolean} [spread] Flag indicating whether this {~Range range} should be spread if insertion\n\t * was inside the range. Defaults to `false`.\n\t * @returns {Array.<module:engine/model/range~Range>} Result of the transformation.\n\t */\n\t_getTransformedByInsertion( insertPosition, howMany, spread = false ) {\n\t\tif ( spread && this.containsPosition( insertPosition ) ) {\n\t\t\t// Range has to be spread. The first part is from original start to the spread point.\n\t\t\t// The other part is from spread point to the original end, but transformed by\n\t\t\t// insertion to reflect insertion changes.\n\n\t\t\treturn [\n\t\t\t\tnew Range( this.start, insertPosition ),\n\t\t\t\tnew Range(\n\t\t\t\t\tinsertPosition.getShiftedBy( howMany ),\n\t\t\t\t\tthis.end._getTransformedByInsertion( insertPosition, howMany )\n\t\t\t\t)\n\t\t\t];\n\t\t} else {\n\t\t\tconst range = new Range( this.start, this.end );\n\n\t\t\trange.start = range.start._getTransformedByInsertion( insertPosition, howMany );\n\t\t\trange.end = range.end._getTransformedByInsertion( insertPosition, howMany );\n\n\t\t\treturn [ range ];\n\t\t}\n\t}\n\n\t/**\n\t * Returns an array containing {@link ~Range ranges} that are a result of transforming this\n\t * {@link ~Range range} by moving `howMany` nodes from `sourcePosition` to `targetPosition`.\n\t *\n\t * @protected\n\t * @param {module:engine/model/position~Position} sourcePosition Position from which nodes are moved.\n\t * @param {module:engine/model/position~Position} targetPosition Position to where nodes are moved.\n\t * @param {Number} howMany How many nodes are moved.\n\t * @param {Boolean} [spread=false] Whether the range should be spread if the move points inside the range.\n\t * @returns {Array.<module:engine/model/range~Range>} Result of the transformation.\n\t */\n\t_getTransformedByMove( sourcePosition, targetPosition, howMany, spread = false ) {\n\t\t// Special case for transforming a collapsed range. Just transform it like a position.\n\t\tif ( this.isCollapsed ) {\n\t\t\tconst newPos = this.start._getTransformedByMove( sourcePosition, targetPosition, howMany );\n\n\t\t\treturn [ new Range( newPos ) ];\n\t\t}\n\n\t\t// Special case for transformation when a part of the range is moved towards the range.\n\t\t//\n\t\t// Examples:\n\t\t//\n\t\t// <div><p>ab</p><p>c[d</p></div><p>e]f</p> --> <div><p>ab</p></div><p>c[d</p><p>e]f</p>\n\t\t// <p>e[f</p><div><p>a]b</p><p>cd</p></div> --> <p>e[f</p><p>a]b</p><div><p>cd</p></div>\n\t\t//\n\t\t// Without this special condition, the default algorithm leaves an \"artifact\" range from one of `differenceSet` parts:\n\t\t//\n\t\t// <div><p>ab</p><p>c[d</p></div><p>e]f</p> --> <div><p>ab</p>{</div>}<p>c[d</p><p>e]f</p>\n\t\t//\n\t\t// This special case is applied only if the range is to be kept together (not spread).\n\t\tconst moveRange = Range._createFromPositionAndShift( sourcePosition, howMany );\n\t\tconst insertPosition = targetPosition._getTransformedByDeletion( sourcePosition, howMany );\n\n\t\tif ( this.containsPosition( targetPosition ) && !spread ) {\n\t\t\tif ( moveRange.containsPosition( this.start ) || moveRange.containsPosition( this.end ) ) {\n\t\t\t\tconst start = this.start._getTransformedByMove( sourcePosition, targetPosition, howMany );\n\t\t\t\tconst end = this.end._getTransformedByMove( sourcePosition, targetPosition, howMany );\n\n\t\t\t\treturn [ new Range( start, end ) ];\n\t\t\t}\n\t\t}\n\n\t\t// Default algorithm.\n\t\tlet result;\n\n\t\tconst differenceSet = this.getDifference( moveRange );\n\t\tlet difference = null;\n\n\t\tconst common = this.getIntersection( moveRange );\n\n\t\tif ( differenceSet.length == 1 ) {\n\t\t\t// `moveRange` and this range may intersect but may be separate.\n\t\t\tdifference = new Range(\n\t\t\t\tdifferenceSet[ 0 ].start._getTransformedByDeletion( sourcePosition, howMany ),\n\t\t\t\tdifferenceSet[ 0 ].end._getTransformedByDeletion( sourcePosition, howMany )\n\t\t\t);\n\t\t} else if ( differenceSet.length == 2 ) {\n\t\t\t// `moveRange` is inside this range.\n\t\t\tdifference = new Range(\n\t\t\t\tthis.start,\n\t\t\t\tthis.end._getTransformedByDeletion( sourcePosition, howMany )\n\t\t\t);\n\t\t} // else, `moveRange` contains this range.\n\n\t\tif ( difference ) {\n\t\t\tresult = difference._getTransformedByInsertion( insertPosition, howMany, common !== null || spread );\n\t\t} else {\n\t\t\tresult = [];\n\t\t}\n\n\t\tif ( common ) {\n\t\t\tconst transformedCommon = new Range(\n\t\t\t\tcommon.start._getCombined( moveRange.start, insertPosition ),\n\t\t\t\tcommon.end._getCombined( moveRange.start, insertPosition )\n\t\t\t);\n\n\t\t\tif ( result.length == 2 ) {\n\t\t\t\tresult.splice( 1, 0, transformedCommon );\n\t\t\t} else {\n\t\t\t\tresult.push( transformedCommon );\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Returns a copy of this range that is transformed by deletion of `howMany` nodes from `deletePosition`.\n\t *\n\t * If the deleted range is intersecting with the transformed range, the transformed range will be shrank.\n\t *\n\t * If the deleted range contains transformed range, `null` will be returned.\n\t *\n\t * @protected\n\t * @param {module:engine/model/position~Position} deletionPosition Position from which nodes are removed.\n\t * @param {Number} howMany How many nodes are removed.\n\t * @returns {module:engine/model/range~Range|null} Result of the transformation.\n\t */\n\t_getTransformedByDeletion( deletePosition, howMany ) {\n\t\tlet newStart = this.start._getTransformedByDeletion( deletePosition, howMany );\n\t\tlet newEnd = this.end._getTransformedByDeletion( deletePosition, howMany );\n\n\t\tif ( newStart == null && newEnd == null ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( newStart == null ) {\n\t\t\tnewStart = deletePosition;\n\t\t}\n\n\t\tif ( newEnd == null ) {\n\t\t\tnewEnd = deletePosition;\n\t\t}\n\n\t\treturn new Range( newStart, newEnd );\n\t}\n\n\t/**\n\t * Creates a new range, spreading from specified {@link module:engine/model/position~Position position} to a position moved by\n\t * given `shift`. If `shift` is a negative value, shifted position is treated as the beginning of the range.\n\t *\n\t * @protected\n\t * @param {module:engine/model/position~Position} position Beginning of the range.\n\t * @param {Number} shift How long the range should be.\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tstatic _createFromPositionAndShift( position, shift ) {\n\t\tconst start = position;\n\t\tconst end = position.getShiftedBy( shift );\n\n\t\treturn shift > 0 ? new this( start, end ) : new this( end, start );\n\t}\n\n\t/**\n\t * Creates a range inside an {@link module:engine/model/element~Element element} which starts before the first child of\n\t * that element and ends after the last child of that element.\n\t *\n\t * @protected\n\t * @param {module:engine/model/element~Element} element Element which is a parent for the range.\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tstatic _createIn( element ) {\n\t\treturn new this( Position._createAt( element, 0 ), Position._createAt( element, element.maxOffset ) );\n\t}\n\n\t/**\n\t * Creates a range that starts before given {@link module:engine/model/item~Item model item} and ends after it.\n\t *\n\t * @protected\n\t * @param {module:engine/model/item~Item} item\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tstatic _createOn( item ) {\n\t\treturn this._createFromPositionAndShift( Position._createBefore( item ), item.offsetSize );\n\t}\n\n\t/**\n\t * Combines all ranges from the passed array into a one range. At least one range has to be passed.\n\t * Passed ranges must not have common parts.\n\t *\n\t * The first range from the array is a reference range. If other ranges start or end on the exactly same position where\n\t * the reference range, they get combined into one range.\n\t *\n\t *\t\t[ ][] [ ][ ][ ][ ][] [ ] // Passed ranges, shown sorted\n\t *\t\t[ ] // The result of the function if the first range was a reference range.\n\t *\t [ ] // The result of the function if the third-to-seventh range was a reference range.\n\t *\t [ ] // The result of the function if the last range was a reference range.\n\t *\n\t * @param {Array.<module:engine/model/range~Range>} ranges Ranges to combine.\n\t * @returns {module:engine/model/range~Range} Combined range.\n\t */\n\tstatic _createFromRanges( ranges ) {\n\t\tif ( ranges.length === 0 ) {\n\t\t\t/**\n\t\t\t * At least one range has to be passed to\n\t\t\t * {@link module:engine/model/range~Range._createFromRanges `Range._createFromRanges()`}.\n\t\t\t *\n\t\t\t * @error range-create-from-ranges-empty-array\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'range-create-from-ranges-empty-array: At least one range has to be passed.',\n\t\t\t\tnull\n\t\t\t);\n\t\t} else if ( ranges.length == 1 ) {\n\t\t\treturn ranges[ 0 ].clone();\n\t\t}\n\n\t\t// 1. Set the first range in `ranges` array as a reference range.\n\t\t// If we are going to return just a one range, one of the ranges need to be the reference one.\n\t\t// Other ranges will be stuck to that range, if possible.\n\t\tconst ref = ranges[ 0 ];\n\n\t\t// 2. Sort all the ranges so it's easier to process them.\n\t\tranges.sort( ( a, b ) => {\n\t\t\treturn a.start.isAfter( b.start ) ? 1 : -1;\n\t\t} );\n\n\t\t// 3. Check at which index the reference range is now.\n\t\tconst refIndex = ranges.indexOf( ref );\n\n\t\t// 4. At this moment we don't need the original range.\n\t\t// We are going to modify the result and we need to return a new instance of Range.\n\t\t// We have to create a copy of the reference range.\n\t\tconst result = new this( ref.start, ref.end );\n\n\t\t// 5. Ranges should be checked and glued starting from the range that is closest to the reference range.\n\t\t// Since ranges are sorted, start with the range with index that is closest to reference range index.\n\t\tif ( refIndex > 0 ) {\n\t\t\tfor ( let i = refIndex - 1; true; i++ ) {\n\t\t\t\tif ( ranges[ i ].end.isEqual( result.start ) ) {\n\t\t\t\t\tresult.start = Position._createAt( ranges[ i ].start );\n\t\t\t\t} else {\n\t\t\t\t\t// If ranges are not starting/ending at the same position there is no point in looking further.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 6. Ranges should be checked and glued starting from the range that is closest to the reference range.\n\t\t// Since ranges are sorted, start with the range with index that is closest to reference range index.\n\t\tfor ( let i = refIndex + 1; i < ranges.length; i++ ) {\n\t\t\tif ( ranges[ i ].start.isEqual( result.end ) ) {\n\t\t\t\tresult.end = Position._createAt( ranges[ i ].end );\n\t\t\t} else {\n\t\t\t\t// If ranges are not starting/ending at the same position there is no point in looking further.\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Creates a `Range` instance from given plain object (i.e. parsed JSON string).\n\t *\n\t * @param {Object} json Plain object to be converted to `Range`.\n\t * @param {module:engine/model/document~Document} doc Document object that will be range owner.\n\t * @returns {module:engine/model/element~Element} `Range` instance created using given plain object.\n\t */\n\tstatic fromJSON( json, doc ) {\n\t\treturn new this( Position.fromJSON( json.start, doc ), Position.fromJSON( json.end, doc ) );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/conversion/mapper\n */\n\nimport ModelPosition from '../model/position';\nimport ModelRange from '../model/range';\n\nimport ViewPosition from '../view/position';\nimport ViewRange from '../view/range';\nimport ViewText from '../view/text';\n\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Maps elements, positions and markers between {@link module:engine/view/document~Document the view} and\n * {@link module:engine/model/model the model}.\n *\n * The instance of the Mapper used for the editing pipeline is available in\n * {@link module:engine/controller/editingcontroller~EditingController#mapper `editor.editing.mapper`}.\n *\n * Mapper uses bound elements to find corresponding elements and positions, so, to get proper results,\n * all model elements should be {@link module:engine/conversion/mapper~Mapper#bindElements bound}.\n *\n * To map complex model to/from view relations, you may provide custom callbacks for\n * {@link module:engine/conversion/mapper~Mapper#event:modelToViewPosition modelToViewPosition event} and\n * {@link module:engine/conversion/mapper~Mapper#event:viewToModelPosition viewToModelPosition event} that are fired whenever\n * a position mapping request occurs.\n * Those events are fired by {@link module:engine/conversion/mapper~Mapper#toViewPosition toViewPosition}\n * and {@link module:engine/conversion/mapper~Mapper#toModelPosition toModelPosition} methods. `Mapper` adds it's own default callbacks\n * with `'lowest'` priority. To override default `Mapper` mapping, add custom callback with higher priority and\n * stop the event.\n */\nexport default class Mapper {\n\t/**\n\t * Creates an instance of the mapper.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Model element to view element mapping.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakMap}\n\t\t */\n\t\tthis._modelToViewMapping = new WeakMap();\n\n\t\t/**\n\t\t * View element to model element mapping.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakMap}\n\t\t */\n\t\tthis._viewToModelMapping = new WeakMap();\n\n\t\t/**\n\t\t * A map containing callbacks between view element names and functions evaluating length of view elements\n\t\t * in model.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._viewToModelLengthCallbacks = new Map();\n\n\t\t/**\n\t\t * Model marker name to view elements mapping.\n\t\t *\n\t\t * Keys are `String`s while values are `Set`s with {@link module:engine/view/element~Element view elements}.\n\t\t * One marker (name) can be mapped to multiple elements.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._markerNameToElements = new Map();\n\n\t\t/**\n\t\t * View element to model marker names mapping.\n\t\t *\n\t\t * This is reverse to {@link ~Mapper#_markerNameToElements} map.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._elementToMarkerNames = new Map();\n\n\t\t/**\n\t\t * Stores marker names of markers which has changed due to unbinding a view element (so it is assumed that the view element\n\t\t * has been removed, moved or renamed).\n\t\t *\n\t\t * @private\n\t\t * @member {Set.<module:engine/model/markercollection~Marker>}\n\t\t */\n\t\tthis._unboundMarkerNames = new Set();\n\n\t\t// Default mapper algorithm for mapping model position to view position.\n\t\tthis.on( 'modelToViewPosition', ( evt, data ) => {\n\t\t\tif ( data.viewPosition ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst viewContainer = this._modelToViewMapping.get( data.modelPosition.parent );\n\n\t\t\tdata.viewPosition = this._findPositionIn( viewContainer, data.modelPosition.offset );\n\t\t}, { priority: 'low' } );\n\n\t\t// Default mapper algorithm for mapping view position to model position.\n\t\tthis.on( 'viewToModelPosition', ( evt, data ) => {\n\t\t\tif ( data.modelPosition ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst viewBlock = this.findMappedViewAncestor( data.viewPosition );\n\t\t\tconst modelParent = this._viewToModelMapping.get( viewBlock );\n\t\t\tconst modelOffset = this._toModelOffset( data.viewPosition.parent, data.viewPosition.offset, viewBlock );\n\n\t\t\tdata.modelPosition = ModelPosition._createAt( modelParent, modelOffset );\n\t\t}, { priority: 'low' } );\n\t}\n\n\t/**\n\t * Marks model and view elements as corresponding. Corresponding elements can be retrieved by using\n\t * the {@link module:engine/conversion/mapper~Mapper#toModelElement toModelElement} and\n\t * {@link module:engine/conversion/mapper~Mapper#toViewElement toViewElement} methods.\n\t * The information that elements are bound is also used to translate positions.\n\t *\n\t * @param {module:engine/model/element~Element} modelElement Model element.\n\t * @param {module:engine/view/element~Element} viewElement View element.\n\t */\n\tbindElements( modelElement, viewElement ) {\n\t\tthis._modelToViewMapping.set( modelElement, viewElement );\n\t\tthis._viewToModelMapping.set( viewElement, modelElement );\n\t}\n\n\t/**\n\t * Unbinds given {@link module:engine/view/element~Element view element} from the map.\n\t *\n\t * **Note:** view-to-model binding will be removed, if it existed. However, corresponding model-to-view binding\n\t * will be removed only if model element is still bound to passed `viewElement`.\n\t *\n\t * This behavior lets for re-binding model element to another view element without fear of losing the new binding\n\t * when the previously bound view element is unbound.\n\t *\n\t * @param {module:engine/view/element~Element} viewElement View element to unbind.\n\t */\n\tunbindViewElement( viewElement ) {\n\t\tconst modelElement = this.toModelElement( viewElement );\n\n\t\tthis._viewToModelMapping.delete( viewElement );\n\n\t\tif ( this._elementToMarkerNames.has( viewElement ) ) {\n\t\t\tfor ( const markerName of this._elementToMarkerNames.get( viewElement ) ) {\n\t\t\t\tthis._unboundMarkerNames.add( markerName );\n\t\t\t}\n\t\t}\n\n\t\tif ( this._modelToViewMapping.get( modelElement ) == viewElement ) {\n\t\t\tthis._modelToViewMapping.delete( modelElement );\n\t\t}\n\t}\n\n\t/**\n\t * Unbinds given {@link module:engine/model/element~Element model element} from the map.\n\t *\n\t * **Note:** model-to-view binding will be removed, if it existed. However, corresponding view-to-model binding\n\t * will be removed only if view element is still bound to passed `modelElement`.\n\t *\n\t * This behavior lets for re-binding view element to another model element without fear of losing the new binding\n\t * when the previously bound model element is unbound.\n\t *\n\t * @param {module:engine/model/element~Element} modelElement Model element to unbind.\n\t */\n\tunbindModelElement( modelElement ) {\n\t\tconst viewElement = this.toViewElement( modelElement );\n\n\t\tthis._modelToViewMapping.delete( modelElement );\n\n\t\tif ( this._viewToModelMapping.get( viewElement ) == modelElement ) {\n\t\t\tthis._viewToModelMapping.delete( viewElement );\n\t\t}\n\t}\n\n\t/**\n\t * Binds given marker name with given {@link module:engine/view/element~Element view element}. The element\n\t * will be added to the current set of elements bound with given marker name.\n\t *\n\t * @param {module:engine/view/element~Element} element Element to bind.\n\t * @param {String} name Marker name.\n\t */\n\tbindElementToMarker( element, name ) {\n\t\tconst elements = this._markerNameToElements.get( name ) || new Set();\n\t\telements.add( element );\n\n\t\tconst names = this._elementToMarkerNames.get( element ) || new Set();\n\t\tnames.add( name );\n\n\t\tthis._markerNameToElements.set( name, elements );\n\t\tthis._elementToMarkerNames.set( element, names );\n\t}\n\n\t/**\n\t * Unbinds an element from given marker name.\n\t *\n\t * @param {module:engine/view/element~Element} element Element to unbind.\n\t * @param {String} name Marker name.\n\t */\n\tunbindElementFromMarkerName( element, name ) {\n\t\tconst nameToElements = this._markerNameToElements.get( name );\n\n\t\tif ( nameToElements ) {\n\t\t\tnameToElements.delete( element );\n\n\t\t\tif ( nameToElements.size == 0 ) {\n\t\t\t\tthis._markerNameToElements.delete( name );\n\t\t\t}\n\t\t}\n\n\t\tconst elementToNames = this._elementToMarkerNames.get( element );\n\n\t\tif ( elementToNames ) {\n\t\t\telementToNames.delete( name );\n\n\t\t\tif ( elementToNames.size == 0 ) {\n\t\t\t\tthis._elementToMarkerNames.delete( element );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns all marker names of markers which has changed due to unbinding a view element (so it is assumed that the view element\n\t * has been removed, moved or renamed) since the last flush. After returning, the marker names list is cleared.\n\t *\n\t * @returns {Array.<String>}\n\t */\n\tflushUnboundMarkerNames() {\n\t\tconst markerNames = Array.from( this._unboundMarkerNames );\n\n\t\tthis._unboundMarkerNames.clear();\n\n\t\treturn markerNames;\n\t}\n\n\t/**\n\t * Removes all model to view and view to model bindings.\n\t */\n\tclearBindings() {\n\t\tthis._modelToViewMapping = new WeakMap();\n\t\tthis._viewToModelMapping = new WeakMap();\n\t\tthis._markerNameToElements = new Map();\n\t\tthis._elementToMarkerNames = new Map();\n\t\tthis._unboundMarkerNames = new Set();\n\t}\n\n\t/**\n\t * Gets the corresponding model element.\n\t *\n\t * **Note:** {@link module:engine/view/uielement~UIElement} does not have corresponding element in model.\n\t *\n\t * @param {module:engine/view/element~Element} viewElement View element.\n\t * @returns {module:engine/model/element~Element|undefined} Corresponding model element or `undefined` if not found.\n\t */\n\ttoModelElement( viewElement ) {\n\t\treturn this._viewToModelMapping.get( viewElement );\n\t}\n\n\t/**\n\t * Gets the corresponding view element.\n\t *\n\t * @param {module:engine/model/element~Element} modelElement Model element.\n\t * @returns {module:engine/view/element~Element|undefined} Corresponding view element or `undefined` if not found.\n\t */\n\ttoViewElement( modelElement ) {\n\t\treturn this._modelToViewMapping.get( modelElement );\n\t}\n\n\t/**\n\t * Gets the corresponding model range.\n\t *\n\t * @param {module:engine/view/range~Range} viewRange View range.\n\t * @returns {module:engine/model/range~Range} Corresponding model range.\n\t */\n\ttoModelRange( viewRange ) {\n\t\treturn new ModelRange( this.toModelPosition( viewRange.start ), this.toModelPosition( viewRange.end ) );\n\t}\n\n\t/**\n\t * Gets the corresponding view range.\n\t *\n\t * @param {module:engine/model/range~Range} modelRange Model range.\n\t * @returns {module:engine/view/range~Range} Corresponding view range.\n\t */\n\ttoViewRange( modelRange ) {\n\t\treturn new ViewRange( this.toViewPosition( modelRange.start ), this.toViewPosition( modelRange.end ) );\n\t}\n\n\t/**\n\t * Gets the corresponding model position.\n\t *\n\t * @fires viewToModelPosition\n\t * @param {module:engine/view/position~Position} viewPosition View position.\n\t * @returns {module:engine/model/position~Position} Corresponding model position.\n\t */\n\ttoModelPosition( viewPosition ) {\n\t\tconst data = {\n\t\t\tviewPosition,\n\t\t\tmapper: this\n\t\t};\n\n\t\tthis.fire( 'viewToModelPosition', data );\n\n\t\treturn data.modelPosition;\n\t}\n\n\t/**\n\t * Gets the corresponding view position.\n\t *\n\t * @fires modelToViewPosition\n\t * @param {module:engine/model/position~Position} modelPosition Model position.\n\t * @param {Object} [options] Additional options for position mapping process.\n\t * @param {Boolean} [options.isPhantom=false] Should be set to `true` if the model position to map is pointing to a place\n\t * in model tree which no longer exists. For example, it could be an end of a removed model range.\n\t * @returns {module:engine/view/position~Position} Corresponding view position.\n\t */\n\ttoViewPosition( modelPosition, options = { isPhantom: false } ) {\n\t\tconst data = {\n\t\t\tmodelPosition,\n\t\t\tmapper: this,\n\t\t\tisPhantom: options.isPhantom\n\t\t};\n\n\t\tthis.fire( 'modelToViewPosition', data );\n\n\t\treturn data.viewPosition;\n\t}\n\n\t/**\n\t * Gets all view elements bound to the given marker name.\n\t *\n\t * @param {String} name Marker name.\n\t * @returns {Set.<module:engine/view/element~Element>|null} View elements bound with given marker name or `null`\n\t * if no elements are bound to given marker name.\n\t */\n\tmarkerNameToElements( name ) {\n\t\tconst boundElements = this._markerNameToElements.get( name );\n\n\t\tif ( !boundElements ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst elements = new Set();\n\n\t\tfor ( const element of boundElements ) {\n\t\t\tif ( element.is( 'attributeElement' ) ) {\n\t\t\t\tfor ( const clone of element.getElementsWithSameId() ) {\n\t\t\t\t\telements.add( clone );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\telements.add( element );\n\t\t\t}\n\t\t}\n\n\t\treturn elements;\n\t}\n\n\t/**\n\t * Registers a callback that evaluates the length in the model of a view element with given name.\n\t *\n\t * The callback is fired with one argument, which is a view element instance. The callback is expected to return\n\t * a number representing the length of view element in model.\n\t *\n\t *\t\t// List item in view may contain nested list, which have other list items. In model though,\n\t *\t\t// the lists are represented by flat structure. Because of those differences, length of list view element\n\t *\t\t// may be greater than one. In the callback it's checked how many nested list items are in evaluated list item.\n\t *\n\t *\t\tfunction getViewListItemLength( element ) {\n\t *\t\t\tlet length = 1;\n\t *\n\t *\t\t\tfor ( let child of element.getChildren() ) {\n\t *\t\t\t\tif ( child.name == 'ul' || child.name == 'ol' ) {\n\t *\t\t\t\t\tfor ( let item of child.getChildren() ) {\n\t *\t\t\t\t\t\tlength += getViewListItemLength( item );\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\n\t *\t\t\treturn length;\n\t *\t\t}\n\t *\n\t *\t\tmapper.registerViewToModelLength( 'li', getViewListItemLength );\n\t *\n\t * @param {String} viewElementName Name of view element for which callback is registered.\n\t * @param {Function} lengthCallback Function return a length of view element instance in model.\n\t */\n\tregisterViewToModelLength( viewElementName, lengthCallback ) {\n\t\tthis._viewToModelLengthCallbacks.set( viewElementName, lengthCallback );\n\t}\n\n\t/**\n\t * For given `viewPosition`, finds and returns the closest ancestor of this position that has a mapping to\n\t * the model.\n\t *\n\t * @param {module:engine/view/position~Position} viewPosition Position for which mapped ancestor should be found.\n\t * @returns {module:engine/view/element~Element}\n\t */\n\tfindMappedViewAncestor( viewPosition ) {\n\t\tlet parent = viewPosition.parent;\n\n\t\twhile ( !this._viewToModelMapping.has( parent ) ) {\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn parent;\n\t}\n\n\t/**\n\t * Calculates model offset based on the view position and the block element.\n\t *\n\t * Example:\n\t *\n\t *\t\t<p>foo<b>ba|r</b></p> // _toModelOffset( b, 2, p ) -> 5\n\t *\n\t * Is a sum of:\n\t *\n\t *\t\t<p>foo|<b>bar</b></p> // _toModelOffset( p, 3, p ) -> 3\n\t *\t\t<p>foo<b>ba|r</b></p> // _toModelOffset( b, 2, b ) -> 2\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} viewParent Position parent.\n\t * @param {Number} viewOffset Position offset.\n\t * @param {module:engine/view/element~Element} viewBlock Block used as a base to calculate offset.\n\t * @returns {Number} Offset in the model.\n\t */\n\t_toModelOffset( viewParent, viewOffset, viewBlock ) {\n\t\tif ( viewBlock != viewParent ) {\n\t\t\t// See example.\n\t\t\tconst offsetToParentStart = this._toModelOffset( viewParent.parent, viewParent.index, viewBlock );\n\t\t\tconst offsetInParent = this._toModelOffset( viewParent, viewOffset, viewParent );\n\n\t\t\treturn offsetToParentStart + offsetInParent;\n\t\t}\n\n\t\t// viewBlock == viewParent, so we need to calculate the offset in the parent element.\n\n\t\t// If the position is a text it is simple (\"ba|r\" -> 2).\n\t\tif ( viewParent.is( 'text' ) ) {\n\t\t\treturn viewOffset;\n\t\t}\n\n\t\t// If the position is in an element we need to sum lengths of siblings ( <b> bar </b> foo | -> 3 + 3 = 6 ).\n\t\tlet modelOffset = 0;\n\n\t\tfor ( let i = 0; i < viewOffset; i++ ) {\n\t\t\tmodelOffset += this.getModelLength( viewParent.getChild( i ) );\n\t\t}\n\n\t\treturn modelOffset;\n\t}\n\n\t/**\n\t * Gets the length of the view element in the model.\n\t *\n\t * The length is calculated as follows:\n\t * * if {@link #registerViewToModelLength length mapping callback} is provided for given `viewNode` it is used to\n\t * evaluate model length (`viewNode` is used as first and only parameter passed to the callback),\n\t * * length of a {@link module:engine/view/text~Text text node} is equal to the length of it's\n\t * {@link module:engine/view/text~Text#data data},\n\t * * length of a {@link module:engine/view/uielement~UIElement ui element} is equal to 0,\n\t * * length of a mapped {@link module:engine/view/element~Element element} is equal to 1,\n\t * * length of a not-mapped {@link module:engine/view/element~Element element} is equal to the length of it's children.\n\t *\n\t * Examples:\n\t *\n\t *\t\tfoo -> 3 // Text length is equal to it's data length.\n\t *\t\t<p>foo</p> -> 1 // Length of an element which is mapped is by default equal to 1.\n\t *\t\t<b>foo</b> -> 3 // Length of an element which is not mapped is a length of its children.\n\t *\t\t<div><p>x</p><p>y</p></div> -> 2 // Assuming that <div> is not mapped and <p> are mapped.\n\t *\n\t * @param {module:engine/view/element~Element} viewNode View node.\n\t * @returns {Number} Length of the node in the tree model.\n\t */\n\tgetModelLength( viewNode ) {\n\t\tif ( this._viewToModelLengthCallbacks.get( viewNode.name ) ) {\n\t\t\tconst callback = this._viewToModelLengthCallbacks.get( viewNode.name );\n\n\t\t\treturn callback( viewNode );\n\t\t} else if ( this._viewToModelMapping.has( viewNode ) ) {\n\t\t\treturn 1;\n\t\t} else if ( viewNode.is( 'text' ) ) {\n\t\t\treturn viewNode.data.length;\n\t\t} else if ( viewNode.is( 'uiElement' ) ) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\tlet len = 0;\n\n\t\t\tfor ( const child of viewNode.getChildren() ) {\n\t\t\t\tlen += this.getModelLength( child );\n\t\t\t}\n\n\t\t\treturn len;\n\t\t}\n\t}\n\n\t/**\n\t * Finds the position in the view node (or its children) with the expected model offset.\n\t *\n\t * Example:\n\t *\n\t *\t\t<p>fo<b>bar</b>bom</p> -> expected offset: 4\n\t *\n\t *\t\t_findPositionIn( p, 4 ):\n\t *\t\t<p>|fo<b>bar</b>bom</p> -> expected offset: 4, actual offset: 0\n\t *\t\t<p>fo|<b>bar</b>bom</p> -> expected offset: 4, actual offset: 2\n\t *\t\t<p>fo<b>bar</b>|bom</p> -> expected offset: 4, actual offset: 5 -> we are too far\n\t *\n\t *\t\t_findPositionIn( b, 4 - ( 5 - 3 ) ):\n\t *\t\t<p>fo<b>|bar</b>bom</p> -> expected offset: 2, actual offset: 0\n\t *\t\t<p>fo<b>bar|</b>bom</p> -> expected offset: 2, actual offset: 3 -> we are too far\n\t *\n\t *\t\t_findPositionIn( bar, 2 - ( 3 - 3 ) ):\n\t *\t\tWe are in the text node so we can simple find the offset.\n\t *\t\t<p>fo<b>ba|r</b>bom</p> -> expected offset: 2, actual offset: 2 -> position found\n\t *\n\t * @private\n\t * @param {module:engine/view/element~Element} viewParent Tree view element in which we are looking for the position.\n\t * @param {Number} expectedOffset Expected offset.\n\t * @returns {module:engine/view/position~Position} Found position.\n\t */\n\t_findPositionIn( viewParent, expectedOffset ) {\n\t\t// Last scanned view node.\n\t\tlet viewNode;\n\t\t// Length of the last scanned view node.\n\t\tlet lastLength = 0;\n\n\t\tlet modelOffset = 0;\n\t\tlet viewOffset = 0;\n\n\t\t// In the text node it is simple: offset in the model equals offset in the text.\n\t\tif ( viewParent.is( 'text' ) ) {\n\t\t\treturn new ViewPosition( viewParent, expectedOffset );\n\t\t}\n\n\t\t// In other cases we add lengths of child nodes to find the proper offset.\n\n\t\t// If it is smaller we add the length.\n\t\twhile ( modelOffset < expectedOffset ) {\n\t\t\tviewNode = viewParent.getChild( viewOffset );\n\t\t\tlastLength = this.getModelLength( viewNode );\n\t\t\tmodelOffset += lastLength;\n\t\t\tviewOffset++;\n\t\t}\n\n\t\t// If it equals we found the position.\n\t\tif ( modelOffset == expectedOffset ) {\n\t\t\treturn this._moveViewPositionToTextNode( new ViewPosition( viewParent, viewOffset ) );\n\t\t}\n\t\t// If it is higher we need to enter last child.\n\t\telse {\n\t\t\t// ( modelOffset - lastLength ) is the offset to the child we enter,\n\t\t\t// so we subtract it from the expected offset to fine the offset in the child.\n\t\t\treturn this._findPositionIn( viewNode, expectedOffset - ( modelOffset - lastLength ) );\n\t\t}\n\t}\n\n\t/**\n\t * Because we prefer positions in text nodes over positions next to text node moves view position to the text node\n\t * if it was next to it.\n\t *\n\t *\t\t<p>[]<b>foo</b></p> -> <p>[]<b>foo</b></p> // do not touch if position is not directly next to text\n\t *\t\t<p>foo[]<b>foo</b></p> -> <p>foo{}<b>foo</b></p> // move to text node\n\t *\t\t<p><b>[]foo</b></p> -> <p><b>{}foo</b></p> // move to text node\n\t *\n\t * @private\n\t * @param {module:engine/view/position~Position} viewPosition Position potentially next to text node.\n\t * @returns {module:engine/view/position~Position} Position in text node if possible.\n\t */\n\t_moveViewPositionToTextNode( viewPosition ) {\n\t\t// If the position is just after text node, put it at the end of that text node.\n\t\t// If the position is just before text node, put it at the beginning of that text node.\n\t\tconst nodeBefore = viewPosition.nodeBefore;\n\t\tconst nodeAfter = viewPosition.nodeAfter;\n\n\t\tif ( nodeBefore instanceof ViewText ) {\n\t\t\treturn new ViewPosition( nodeBefore, nodeBefore.data.length );\n\t\t} else if ( nodeAfter instanceof ViewText ) {\n\t\t\treturn new ViewPosition( nodeAfter, 0 );\n\t\t}\n\n\t\t// Otherwise, just return the given position.\n\t\treturn viewPosition;\n\t}\n\n\t/**\n\t * Fired for each model-to-view position mapping request. The purpose of this event is to enable custom model-to-view position\n\t * mapping. Callbacks added to this event take {@link module:engine/model/position~Position model position} and are expected to\n\t * calculate {@link module:engine/view/position~Position view position}. Calculated view position should be added as `viewPosition`\n\t * value in `data` object that is passed as one of parameters to the event callback.\n\t *\n\t * \t\t// Assume that \"captionedImage\" model element is converted to <img> and following <span> elements in view,\n\t * \t\t// and the model element is bound to <img> element. Force mapping model positions inside \"captionedImage\" to that\n\t * \t\t// <span> element.\n\t *\t\tmapper.on( 'modelToViewPosition', ( evt, data ) => {\n\t *\t\t\tconst positionParent = modelPosition.parent;\n\t *\n\t *\t\t\tif ( positionParent.name == 'captionedImage' ) {\n\t *\t\t\t\tconst viewImg = data.mapper.toViewElement( positionParent );\n\t *\t\t\t\tconst viewCaption = viewImg.nextSibling; // The <span> element.\n\t *\n\t *\t\t\t\tdata.viewPosition = new ViewPosition( viewCaption, modelPosition.offset );\n\t *\n\t *\t\t\t\t// Stop the event if other callbacks should not modify calculated value.\n\t *\t\t\t\tevt.stop();\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * **Note:** keep in mind that sometimes a \"phantom\" model position is being converted. \"Phantom\" model position is\n\t * a position that points to a non-existing place in model. Such position might still be valid for conversion, though\n\t * (it would point to a correct place in view when converted). One example of such situation is when a range is\n\t * removed from model, there may be a need to map the range's end (which is no longer valid model position). To\n\t * handle such situation, check `data.isPhantom` flag:\n\t *\n\t * \t\t// Assume that there is \"customElement\" model element and whenever position is before it, we want to move it\n\t * \t\t// to the inside of the view element bound to \"customElement\".\n\t *\t\tmapper.on( 'modelToViewPosition', ( evt, data ) => {\n\t *\t\t\tif ( data.isPhantom ) {\n\t *\t\t\t\treturn;\n\t *\t\t\t}\n\t *\n\t *\t\t\t// Below line might crash for phantom position that does not exist in model.\n\t *\t\t\tconst sibling = data.modelPosition.nodeBefore;\n\t *\n\t *\t\t\t// Check if this is the element we are interested in.\n\t *\t\t\tif ( !sibling.is( 'customElement' ) ) {\n\t *\t\t\t\treturn;\n\t *\t\t\t}\n\t *\n\t *\t\t\tconst viewElement = data.mapper.toViewElement( sibling );\n\t *\n\t *\t\t\tdata.viewPosition = new ViewPosition( sibling, 0 );\n\t *\n\t *\t\t\tevt.stop();\n\t *\t\t} );\n\t *\n\t * **Note:** default mapping callback is provided with `low` priority setting and does not cancel the event, so it is possible to\n\t * attach a custom callback after default callback and also use `data.viewPosition` calculated by default callback\n\t * (for example to fix it).\n\t *\n\t * **Note:** default mapping callback will not fire if `data.viewPosition` is already set.\n\t *\n\t * **Note:** these callbacks are called **very often**. For efficiency reasons, it is advised to use them only when position\n\t * mapping between given model and view elements is unsolvable using just elements mapping and default algorithm. Also,\n\t * the condition that checks if special case scenario happened should be as simple as possible.\n\t *\n\t * @event modelToViewPosition\n\t * @param {Object} data Data pipeline object that can store and pass data between callbacks. The callback should add\n\t * `viewPosition` value to that object with calculated {@link module:engine/view/position~Position view position}.\n\t * @param {module:engine/conversion/mapper~Mapper} data.mapper Mapper instance that fired the event.\n\t */\n\n\t/**\n\t * Fired for each view-to-model position mapping request. See {@link module:engine/conversion/mapper~Mapper#event:modelToViewPosition}.\n\t *\n\t * \t\t// See example in `modelToViewPosition` event description.\n\t * \t\t// This custom mapping will map positions from <span> element next to <img> to the \"captionedImage\" element.\n\t *\t\tmapper.on( 'viewToModelPosition', ( evt, data ) => {\n\t *\t\t\tconst positionParent = viewPosition.parent;\n\t *\n\t *\t\t\tif ( positionParent.hasClass( 'image-caption' ) ) {\n\t *\t\t\t\tconst viewImg = positionParent.previousSibling;\n\t *\t\t\t\tconst modelImg = data.mapper.toModelElement( viewImg );\n\t *\n\t *\t\t\t\tdata.modelPosition = new ModelPosition( modelImg, viewPosition.offset );\n\t *\t\t\t\tevt.stop();\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * **Note:** default mapping callback is provided with `low` priority setting and does not cancel the event, so it is possible to\n\t * attach a custom callback after default callback and also use `data.modelPosition` calculated by default callback\n\t * (for example to fix it).\n\t *\n\t * **Note:** default mapping callback will not fire if `data.modelPosition` is already set.\n\t *\n\t * **Note:** these callbacks are called **very often**. For efficiency reasons, it is advised to use them only when position\n\t * mapping between given model and view elements is unsolvable using just elements mapping and default algorithm. Also,\n\t * the condition that checks if special case scenario happened should be as simple as possible.\n\t *\n\t * @event viewToModelPosition\n\t * @param {Object} data Data pipeline object that can store and pass data between callbacks. The callback should add\n\t * `modelPosition` value to that object with calculated {@link module:engine/model/position~Position model position}.\n\t * @param {module:engine/conversion/mapper~Mapper} data.mapper Mapper instance that fired the event.\n\t */\n}\n\nmix( Mapper, EmitterMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/conversion/modelconsumable\n */\n\nimport TextProxy from '../model/textproxy';\n\n/**\n * Manages a list of consumable values for {@link module:engine/model/item~Item model items}.\n *\n * Consumables are various aspects of the model. A model item can be broken down into singular properties that might be\n * taken into consideration when converting that item.\n *\n * `ModelConsumable` is used by {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher} while analyzing changed\n * parts of {@link module:engine/model/document~Document the document}. The added / changed / removed model items are broken down\n * into singular properties (the item itself and it's attributes). All those parts are saved in `ModelConsumable`. Then,\n * during conversion, when given part of model item is converted (i.e. the view element has been inserted into the view,\n * but without attributes), consumable value is removed from `ModelConsumable`.\n *\n * For model items, `ModelConsumable` stores consumable values of one of following types: `insert`, `addattribute:<attributeKey>`,\n * `changeattributes:<attributeKey>`, `removeattributes:<attributeKey>`.\n *\n * In most cases, it is enough to let {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}\n * gather consumable values, so there is no need to use\n * {@link module:engine/conversion/modelconsumable~ModelConsumable#add add method} directly.\n * However, it is important to understand how consumable values can be\n * {@link module:engine/conversion/modelconsumable~ModelConsumable#consume consumed}.\n * See {@link module:engine/conversion/downcasthelpers default downcast converters} for more information.\n *\n * Keep in mind, that one conversion event may have multiple callbacks (converters) attached to it. Each of those is\n * able to convert one or more parts of the model. However, when one of those callbacks actually converts\n * something, other should not, because they would duplicate the results. Using `ModelConsumable` helps avoiding\n * this situation, because callbacks should only convert those values, which were not yet consumed from `ModelConsumable`.\n *\n * Consuming multiple values in a single callback:\n *\n *\t\t// Converter for custom `image` element that might have a `caption` element inside which changes\n *\t\t// how the image is displayed in the view:\n *\t\t//\n *\t\t// Model:\n *\t\t//\n *\t\t// [image]\n *\t\t// └─ [caption]\n *\t\t// └─ foo\n *\t\t//\n *\t\t// View:\n *\t\t//\n *\t\t// <figure>\n *\t\t// ├─ <img />\n *\t\t// └─ <caption>\n *\t\t// └─ foo\n *\t\tmodelConversionDispatcher.on( 'insert:image', ( evt, data, conversionApi ) => {\n *\t\t\t// First, consume the `image` element.\n *\t\t\tconversionApi.consumable.consume( data.item, 'insert' );\n *\n *\t\t\t// Just create normal image element for the view.\n *\t\t\t// Maybe it will be \"decorated\" later.\n *\t\t\tconst viewImage = new ViewElement( 'img' );\n *\t\t\tconst insertPosition = conversionApi.mapper.toViewPosition( data.range.start );\n *\t\t\tconst viewWriter = conversionApi.writer;\n *\n *\t\t\t// Check if the `image` element has children.\n *\t\t\tif ( data.item.childCount > 0 ) {\n *\t\t\t\tconst modelCaption = data.item.getChild( 0 );\n *\n *\t\t\t\t// `modelCaption` insertion change is consumed from consumable values.\n *\t\t\t\t// It will not be converted by other converters, but it's children (probably some text) will be.\n *\t\t\t\t// Through mapping, converters for text will know where to insert contents of `modelCaption`.\n *\t\t\t\tif ( conversionApi.consumable.consume( modelCaption, 'insert' ) ) {\n *\t\t\t\t\tconst viewCaption = new ViewElement( 'figcaption' );\n *\n *\t\t\t\t\tconst viewImageHolder = new ViewElement( 'figure', null, [ viewImage, viewCaption ] );\n *\n *\t\t\t\t\tconversionApi.mapper.bindElements( modelCaption, viewCaption );\n *\t\t\t\t\tconversionApi.mapper.bindElements( data.item, viewImageHolder );\n *\t\t\t\t\tviewWriter.insert( insertPosition, viewImageHolder );\n *\t\t\t\t}\n *\t\t\t} else {\n *\t\t\t\tconversionApi.mapper.bindElements( data.item, viewImage );\n *\t\t\t\tviewWriter.insert( insertPosition, viewImage );\n *\t\t\t}\n *\n *\t\t\tevt.stop();\n *\t\t} );\n */\nexport default class ModelConsumable {\n\t/**\n\t * Creates an empty consumables list.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Contains list of consumable values.\n\t\t *\n\t\t * @private\n\t\t * @member {Map} module:engine/conversion/modelconsumable~ModelConsumable#_consumable\n\t\t */\n\t\tthis._consumable = new Map();\n\n\t\t/**\n\t\t * For each {@link module:engine/model/textproxy~TextProxy} added to `ModelConsumable`, this registry holds parent\n\t\t * of that `TextProxy` and start and end indices of that `TextProxy`. This allows identification of `TextProxy`\n\t\t * instances that points to the same part of the model but are different instances. Each distinct `TextProxy`\n\t\t * is given unique `Symbol` which is then registered as consumable. This process is transparent for `ModelConsumable`\n\t\t * API user because whenever `TextProxy` is added, tested, consumed or reverted, internal mechanisms of\n\t\t * `ModelConsumable` translates `TextProxy` to that unique `Symbol`.\n\t\t *\n\t\t * @private\n\t\t * @member {Map} module:engine/conversion/modelconsumable~ModelConsumable#_textProxyRegistry\n\t\t */\n\t\tthis._textProxyRegistry = new Map();\n\t}\n\n\t/**\n\t * Adds a consumable value to the consumables list and links it with given model item.\n\t *\n\t *\t\tmodelConsumable.add( modelElement, 'insert' ); // Add `modelElement` insertion change to consumable values.\n\t *\t\tmodelConsumable.add( modelElement, 'addAttribute:bold' ); // Add `bold` attribute insertion on `modelElement` change.\n\t *\t\tmodelConsumable.add( modelElement, 'removeAttribute:bold' ); // Add `bold` attribute removal on `modelElement` change.\n\t *\t\tmodelConsumable.add( modelSelection, 'selection' ); // Add `modelSelection` to consumable values.\n\t *\t\tmodelConsumable.add( modelRange, 'range' ); // Add `modelRange` to consumable values.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item\n\t * Model item, range or selection that has the consumable.\n\t * @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.\n\t * Second colon and everything after will be cut. Passing event name is a safe and good practice.\n\t */\n\tadd( item, type ) {\n\t\ttype = _normalizeConsumableType( type );\n\n\t\tif ( item instanceof TextProxy ) {\n\t\t\titem = this._getSymbolForTextProxy( item );\n\t\t}\n\n\t\tif ( !this._consumable.has( item ) ) {\n\t\t\tthis._consumable.set( item, new Map() );\n\t\t}\n\n\t\tthis._consumable.get( item ).set( type, true );\n\t}\n\n\t/**\n\t * Removes given consumable value from given model item.\n\t *\n\t *\t\tmodelConsumable.consume( modelElement, 'insert' ); // Remove `modelElement` insertion change from consumable values.\n\t *\t\tmodelConsumable.consume( modelElement, 'addAttribute:bold' ); // Remove `bold` attribute insertion on `modelElement` change.\n\t *\t\tmodelConsumable.consume( modelElement, 'removeAttribute:bold' ); // Remove `bold` attribute removal on `modelElement` change.\n\t *\t\tmodelConsumable.consume( modelSelection, 'selection' ); // Remove `modelSelection` from consumable values.\n\t *\t\tmodelConsumable.consume( modelRange, 'range' ); // Remove 'modelRange' from consumable values.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item\n\t * Model item, range or selection from which consumable will be consumed.\n\t * @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.\n\t * Second colon and everything after will be cut. Passing event name is a safe and good practice.\n\t * @returns {Boolean} `true` if consumable value was available and was consumed, `false` otherwise.\n\t */\n\tconsume( item, type ) {\n\t\ttype = _normalizeConsumableType( type );\n\n\t\tif ( item instanceof TextProxy ) {\n\t\t\titem = this._getSymbolForTextProxy( item );\n\t\t}\n\n\t\tif ( this.test( item, type ) ) {\n\t\t\tthis._consumable.get( item ).set( type, false );\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Tests whether there is a consumable value of given type connected with given model item.\n\t *\n\t *\t\tmodelConsumable.test( modelElement, 'insert' ); // Check for `modelElement` insertion change.\n\t *\t\tmodelConsumable.test( modelElement, 'addAttribute:bold' ); // Check for `bold` attribute insertion on `modelElement` change.\n\t *\t\tmodelConsumable.test( modelElement, 'removeAttribute:bold' ); // Check for `bold` attribute removal on `modelElement` change.\n\t *\t\tmodelConsumable.test( modelSelection, 'selection' ); // Check if `modelSelection` is consumable.\n\t *\t\tmodelConsumable.test( modelRange, 'range' ); // Check if `modelRange` is consumable.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item\n\t * Model item, range or selection to be tested.\n\t * @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.\n\t * Second colon and everything after will be cut. Passing event name is a safe and good practice.\n\t * @returns {null|Boolean} `null` if such consumable was never added, `false` if the consumable values was\n\t * already consumed or `true` if it was added and not consumed yet.\n\t */\n\ttest( item, type ) {\n\t\ttype = _normalizeConsumableType( type );\n\n\t\tif ( item instanceof TextProxy ) {\n\t\t\titem = this._getSymbolForTextProxy( item );\n\t\t}\n\n\t\tconst itemConsumables = this._consumable.get( item );\n\n\t\tif ( itemConsumables === undefined ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst value = itemConsumables.get( type );\n\n\t\tif ( value === undefined ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn value;\n\t}\n\n\t/**\n\t * Reverts consuming of consumable value.\n\t *\n\t *\t\tmodelConsumable.revert( modelElement, 'insert' ); // Revert consuming `modelElement` insertion change.\n\t *\t\tmodelConsumable.revert( modelElement, 'addAttribute:bold' ); // Revert consuming `bold` attribute insert from `modelElement`.\n\t *\t\tmodelConsumable.revert( modelElement, 'removeAttribute:bold' ); // Revert consuming `bold` attribute remove from `modelElement`.\n\t *\t\tmodelConsumable.revert( modelSelection, 'selection' ); // Revert consuming `modelSelection`.\n\t *\t\tmodelConsumable.revert( modelRange, 'range' ); // Revert consuming `modelRange`.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item\n\t * Model item, range or selection to be reverted.\n\t * @param {String} type Consumable type.\n\t * @returns {null|Boolean} `true` if consumable has been reversed, `false` otherwise. `null` if the consumable has\n\t * never been added.\n\t */\n\trevert( item, type ) {\n\t\ttype = _normalizeConsumableType( type );\n\n\t\tif ( item instanceof TextProxy ) {\n\t\t\titem = this._getSymbolForTextProxy( item );\n\t\t}\n\n\t\tconst test = this.test( item, type );\n\n\t\tif ( test === false ) {\n\t\t\tthis._consumable.get( item ).set( type, true );\n\n\t\t\treturn true;\n\t\t} else if ( test === true ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Gets a unique symbol for passed {@link module:engine/model/textproxy~TextProxy} instance. All `TextProxy` instances that\n\t * have same parent, same start index and same end index will get the same symbol.\n\t *\n\t * Used internally to correctly consume `TextProxy` instances.\n\t *\n\t * @private\n\t * @param {module:engine/model/textproxy~TextProxy} textProxy `TextProxy` instance to get a symbol for.\n\t * @returns {Symbol} Symbol representing all equal instances of `TextProxy`.\n\t */\n\t_getSymbolForTextProxy( textProxy ) {\n\t\tlet symbol = null;\n\n\t\tconst startMap = this._textProxyRegistry.get( textProxy.startOffset );\n\n\t\tif ( startMap ) {\n\t\t\tconst endMap = startMap.get( textProxy.endOffset );\n\n\t\t\tif ( endMap ) {\n\t\t\t\tsymbol = endMap.get( textProxy.parent );\n\t\t\t}\n\t\t}\n\n\t\tif ( !symbol ) {\n\t\t\tsymbol = this._addSymbolForTextProxy( textProxy.startOffset, textProxy.endOffset, textProxy.parent );\n\t\t}\n\n\t\treturn symbol;\n\t}\n\n\t/**\n\t * Adds a symbol for given properties that characterizes a {@link module:engine/model/textproxy~TextProxy} instance.\n\t *\n\t * Used internally to correctly consume `TextProxy` instances.\n\t *\n\t * @private\n\t * @param {Number} startIndex Text proxy start index in it's parent.\n\t * @param {Number} endIndex Text proxy end index in it's parent.\n\t * @param {module:engine/model/element~Element} parent Text proxy parent.\n\t * @returns {Symbol} Symbol generated for given properties.\n\t */\n\t_addSymbolForTextProxy( start, end, parent ) {\n\t\tconst symbol = Symbol( 'textProxySymbol' );\n\t\tlet startMap, endMap;\n\n\t\tstartMap = this._textProxyRegistry.get( start );\n\n\t\tif ( !startMap ) {\n\t\t\tstartMap = new Map();\n\t\t\tthis._textProxyRegistry.set( start, startMap );\n\t\t}\n\n\t\tendMap = startMap.get( end );\n\n\t\tif ( !endMap ) {\n\t\t\tendMap = new Map();\n\t\t\tstartMap.set( end, endMap );\n\t\t}\n\n\t\tendMap.set( parent, symbol );\n\n\t\treturn symbol;\n\t}\n}\n\n// Returns a normalized consumable type name from given string. A normalized consumable type name is a string that has\n// at most one colon, for example: `insert` or `addMarker:highlight`. If string to normalize has more \"parts\" (more colons),\n// the other parts are dropped, for example: `addattribute:bold:$text` -> `addattributes:bold`.\n//\n// @param {String} type Consumable type.\n// @returns {String} Normalized consumable type.\nfunction _normalizeConsumableType( type ) {\n\tconst parts = type.split( ':' );\n\n\treturn parts.length > 1 ? parts[ 0 ] + ':' + parts[ 1 ] : parts[ 0 ];\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/conversion/downcastdispatcher\n */\n\nimport Consumable from './modelconsumable';\nimport Range from '../model/range';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport { extend } from 'lodash-es';\n\n/**\n * `DowncastDispatcher` is a central point of downcasting (conversion from model to view), which is a process of reacting to changes\n * in the model and firing a set of events. Callbacks listening to those events are called converters. Those\n * converters role is to convert the model changes to changes in view (for example, adding view nodes or\n * changing attributes on view elements).\n *\n * During conversion process, `DowncastDispatcher` fires events, basing on state of the model and prepares\n * data for those events. It is important to understand that those events are connected with changes done on model,\n * for example: \"node has been inserted\" or \"attribute has changed\". This is in a contrary to upcasting (view to model conversion),\n * where we convert view state (view nodes) to a model tree.\n *\n * The events are prepared basing on a diff created by {@link module:engine/model/differ~Differ Differ}, which buffers them\n * and then passes to `DowncastDispatcher` as a diff between old model state and new model state.\n *\n * Note, that because changes are converted there is a need to have a mapping between model structure and view structure.\n * To map positions and elements during downcast (model to view conversion) use {@link module:engine/conversion/mapper~Mapper}.\n *\n * `DowncastDispatcher` fires following events for model tree changes:\n *\n * * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert insert}\n * if a range of nodes has been inserted to the model tree,\n * * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:remove remove}\n * if a range of nodes has been removed from the model tree,\n * * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute attribute}\n * if attribute has been added, changed or removed from a model node.\n *\n * For {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert insert}\n * and {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute attribute},\n * `DowncastDispatcher` generates {@link module:engine/conversion/modelconsumable~ModelConsumable consumables}.\n * These are used to have a control over which changes has been already consumed. It is useful when some converters\n * overwrite other or converts multiple changes (for example converts insertion of an element and also converts that\n * element's attributes during insertion).\n *\n * Additionally, `DowncastDispatcher` fires events for {@link module:engine/model/markercollection~Marker marker} changes:\n *\n * * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:addMarker} if a marker has been added,\n * * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:removeMarker} if a marker has been removed.\n *\n * Note, that changing a marker is done through removing the marker from the old range, and adding on the new range,\n * so both those events are fired.\n *\n * Finally, `DowncastDispatcher` also handles firing events for {@link module:engine/model/selection model selection}\n * conversion:\n *\n * * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:selection}\n * which converts selection from model to view,\n * * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute}\n * which is fired for every selection attribute,\n * * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:addMarker}\n * which is fired for every marker which contains selection.\n *\n * Unlike model tree and markers, events for selection are not fired for changes but for selection state.\n *\n * When providing custom listeners for `DowncastDispatcher` remember to check whether given change has not been\n * {@link module:engine/conversion/modelconsumable~ModelConsumable#consume consumed} yet.\n *\n * When providing custom listeners for `DowncastDispatcher` keep in mind that any callback that had\n * {@link module:engine/conversion/modelconsumable~ModelConsumable#consume consumed} a value from a consumable and\n * converted the change should also stop the event (for efficiency purposes).\n *\n * When providing custom listeners for `DowncastDispatcher` remember to use provided\n * {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer} to apply changes to the view document.\n *\n * Example of a custom converter for `DowncastDispatcher`:\n *\n *\t\t// We will convert inserting \"paragraph\" model element into the model.\n *\t\tdowncastDispatcher.on( 'insert:paragraph', ( evt, data, conversionApi ) => {\n *\t\t\t// Remember to check whether the change has not been consumed yet and consume it.\n *\t\t\tif ( conversionApi.consumable.consume( data.item, 'insert' ) ) {\n *\t\t\t\treturn;\n *\t\t\t}\n *\n *\t\t\t// Translate position in model to position in view.\n *\t\t\tconst viewPosition = conversionApi.mapper.toViewPosition( data.range.start );\n *\n *\t\t\t// Create <p> element that will be inserted in view at `viewPosition`.\n *\t\t\tconst viewElement = conversionApi.writer.createContainerElement( 'p' );\n *\n *\t\t\t// Bind the newly created view element to model element so positions will map accordingly in future.\n *\t\t\tconversionApi.mapper.bindElements( data.item, viewElement );\n *\n *\t\t\t// Add the newly created view element to the view.\n *\t\t\tconversionApi.writer.insert( viewPosition, viewElement );\n *\n *\t\t\t// Remember to stop the event propagation.\n *\t\t\tevt.stop();\n *\t\t} );\n */\nexport default class DowncastDispatcher {\n\t/**\n\t * Creates a `DowncastDispatcher` instance.\n\t *\n\t * @see module:engine/conversion/downcastdispatcher~DowncastConversionApi\n\t * @param {Object} conversionApi Additional properties for interface that will be passed to events fired\n\t * by `DowncastDispatcher`.\n\t */\n\tconstructor( conversionApi ) {\n\t\t/**\n\t\t * Interface passed by dispatcher to the events callbacks.\n\t\t *\n\t\t * @member {module:engine/conversion/downcastdispatcher~DowncastConversionApi}\n\t\t */\n\t\tthis.conversionApi = extend( { dispatcher: this }, conversionApi );\n\t}\n\n\t/**\n\t * Takes {@link module:engine/model/differ~Differ model differ} object with buffered changes and fires conversion basing on it.\n\t *\n\t * @param {module:engine/model/differ~Differ} differ Differ object with buffered changes.\n\t * @param {module:engine/model/markercollection~MarkerCollection} markers Markers connected with converted model.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that should be used to modify view document.\n\t */\n\tconvertChanges( differ, markers, writer ) {\n\t\t// Before the view is updated, remove markers which have changed.\n\t\tfor ( const change of differ.getMarkersToRemove() ) {\n\t\t\tthis.convertMarkerRemove( change.name, change.range, writer );\n\t\t}\n\n\t\t// Convert changes that happened on model tree.\n\t\tfor ( const entry of differ.getChanges() ) {\n\t\t\tif ( entry.type == 'insert' ) {\n\t\t\t\tthis.convertInsert( Range._createFromPositionAndShift( entry.position, entry.length ), writer );\n\t\t\t} else if ( entry.type == 'remove' ) {\n\t\t\t\tthis.convertRemove( entry.position, entry.length, entry.name, writer );\n\t\t\t} else {\n\t\t\t\t// entry.type == 'attribute'.\n\t\t\t\tthis.convertAttribute( entry.range, entry.attributeKey, entry.attributeOldValue, entry.attributeNewValue, writer );\n\t\t\t}\n\t\t}\n\n\t\tfor ( const markerName of this.conversionApi.mapper.flushUnboundMarkerNames() ) {\n\t\t\tconst markerRange = markers.get( markerName ).getRange();\n\n\t\t\tthis.convertMarkerRemove( markerName, markerRange, writer );\n\t\t\tthis.convertMarkerAdd( markerName, markerRange, writer );\n\t\t}\n\n\t\t// After the view is updated, convert markers which have changed.\n\t\tfor ( const change of differ.getMarkersToAdd() ) {\n\t\t\tthis.convertMarkerAdd( change.name, change.range, writer );\n\t\t}\n\t}\n\n\t/**\n\t * Starts conversion of a range insertion.\n\t *\n\t * For each node in the range, {@link #event:insert insert event is fired}. For each attribute on each node,\n\t * {@link #event:attribute attribute event is fired}.\n\t *\n\t * @fires insert\n\t * @fires attribute\n\t * @param {module:engine/model/range~Range} range Inserted range.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that should be used to modify view document.\n\t */\n\tconvertInsert( range, writer ) {\n\t\tthis.conversionApi.writer = writer;\n\n\t\t// Create a list of things that can be consumed, consisting of nodes and their attributes.\n\t\tthis.conversionApi.consumable = this._createInsertConsumable( range );\n\n\t\t// Fire a separate insert event for each node and text fragment contained in the range.\n\t\tfor ( const value of range ) {\n\t\t\tconst item = value.item;\n\t\t\tconst itemRange = Range._createFromPositionAndShift( value.previousPosition, value.length );\n\t\t\tconst data = {\n\t\t\t\titem,\n\t\t\t\trange: itemRange\n\t\t\t};\n\n\t\t\tthis._testAndFire( 'insert', data );\n\n\t\t\t// Fire a separate addAttribute event for each attribute that was set on inserted items.\n\t\t\t// This is important because most attributes converters will listen only to add/change/removeAttribute events.\n\t\t\t// If we would not add this part, attributes on inserted nodes would not be converted.\n\t\t\tfor ( const key of item.getAttributeKeys() ) {\n\t\t\t\tdata.attributeKey = key;\n\t\t\t\tdata.attributeOldValue = null;\n\t\t\t\tdata.attributeNewValue = item.getAttribute( key );\n\n\t\t\t\tthis._testAndFire( `attribute:${ key }`, data );\n\t\t\t}\n\t\t}\n\n\t\tthis._clearConversionApi();\n\t}\n\n\t/**\n\t * Fires conversion of a single node removal. Fires {@link #event:remove remove event} with provided data.\n\t *\n\t * @param {module:engine/model/position~Position} position Position from which node was removed.\n\t * @param {Number} length Offset size of removed node.\n\t * @param {String} name Name of removed node.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that should be used to modify view document.\n\t */\n\tconvertRemove( position, length, name, writer ) {\n\t\tthis.conversionApi.writer = writer;\n\n\t\tthis.fire( 'remove:' + name, { position, length }, this.conversionApi );\n\n\t\tthis._clearConversionApi();\n\t}\n\n\t/**\n\t * Starts conversion of attribute change on given `range`.\n\t *\n\t * For each node in the given `range`, {@link #event:attribute attribute event} is fired with the passed data.\n\t *\n\t * @fires attribute\n\t * @param {module:engine/model/range~Range} range Changed range.\n\t * @param {String} key Key of the attribute that has changed.\n\t * @param {*} oldValue Attribute value before the change or `null` if the attribute has not been set before.\n\t * @param {*} newValue New attribute value or `null` if the attribute has been removed.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that should be used to modify view document.\n\t */\n\tconvertAttribute( range, key, oldValue, newValue, writer ) {\n\t\tthis.conversionApi.writer = writer;\n\n\t\t// Create a list with attributes to consume.\n\t\tthis.conversionApi.consumable = this._createConsumableForRange( range, `attribute:${ key }` );\n\n\t\t// Create a separate attribute event for each node in the range.\n\t\tfor ( const value of range ) {\n\t\t\tconst item = value.item;\n\t\t\tconst itemRange = Range._createFromPositionAndShift( value.previousPosition, value.length );\n\t\t\tconst data = {\n\t\t\t\titem,\n\t\t\t\trange: itemRange,\n\t\t\t\tattributeKey: key,\n\t\t\t\tattributeOldValue: oldValue,\n\t\t\t\tattributeNewValue: newValue\n\t\t\t};\n\n\t\t\tthis._testAndFire( `attribute:${ key }`, data );\n\t\t}\n\n\t\tthis._clearConversionApi();\n\t}\n\n\t/**\n\t * Starts model selection conversion.\n\t *\n\t * Fires events for given {@link module:engine/model/selection~Selection selection} to start selection conversion.\n\t *\n\t * @fires selection\n\t * @fires addMarker\n\t * @fires attribute\n\t * @param {module:engine/model/selection~Selection} selection Selection to convert.\n\t * @param {module:engine/model/markercollection~MarkerCollection} markers Markers connected with converted model.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that should be used to modify view document.\n\t */\n\tconvertSelection( selection, markers, writer ) {\n\t\tconst markersAtSelection = Array.from( markers.getMarkersAtPosition( selection.getFirstPosition() ) );\n\n\t\tthis.conversionApi.writer = writer;\n\t\tthis.conversionApi.consumable = this._createSelectionConsumable( selection, markersAtSelection );\n\n\t\tthis.fire( 'selection', { selection }, this.conversionApi );\n\n\t\tif ( !selection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( const marker of markersAtSelection ) {\n\t\t\tconst markerRange = marker.getRange();\n\n\t\t\tif ( !shouldMarkerChangeBeConverted( selection.getFirstPosition(), marker, this.conversionApi.mapper ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst data = {\n\t\t\t\titem: selection,\n\t\t\t\tmarkerName: marker.name,\n\t\t\t\tmarkerRange\n\t\t\t};\n\n\t\t\tif ( this.conversionApi.consumable.test( selection, 'addMarker:' + marker.name ) ) {\n\t\t\t\tthis.fire( 'addMarker:' + marker.name, data, this.conversionApi );\n\t\t\t}\n\t\t}\n\n\t\tfor ( const key of selection.getAttributeKeys() ) {\n\t\t\tconst data = {\n\t\t\t\titem: selection,\n\t\t\t\trange: selection.getFirstRange(),\n\t\t\t\tattributeKey: key,\n\t\t\t\tattributeOldValue: null,\n\t\t\t\tattributeNewValue: selection.getAttribute( key )\n\t\t\t};\n\n\t\t\t// Do not fire event if the attribute has been consumed.\n\t\t\tif ( this.conversionApi.consumable.test( selection, 'attribute:' + data.attributeKey ) ) {\n\t\t\t\tthis.fire( 'attribute:' + data.attributeKey + ':$text', data, this.conversionApi );\n\t\t\t}\n\t\t}\n\n\t\tthis._clearConversionApi();\n\t}\n\n\t/**\n\t * Converts added marker. Fires {@link #event:addMarker addMarker} event for each item\n\t * in marker's range. If range is collapsed single event is dispatched. See event description for more details.\n\t *\n\t * @fires addMarker\n\t * @param {String} markerName Marker name.\n\t * @param {module:engine/model/range~Range} markerRange Marker range.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that should be used to modify view document.\n\t */\n\tconvertMarkerAdd( markerName, markerRange, writer ) {\n\t\t// Do not convert if range is in graveyard or not in the document (e.g. in DocumentFragment).\n\t\tif ( !markerRange.root.document || markerRange.root.rootName == '$graveyard' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.conversionApi.writer = writer;\n\n\t\t// In markers' case, event name == consumable name.\n\t\tconst eventName = 'addMarker:' + markerName;\n\n\t\t//\n\t\t// First, fire an event for the whole marker.\n\t\t//\n\t\tconst consumable = new Consumable();\n\t\tconsumable.add( markerRange, eventName );\n\n\t\tthis.conversionApi.consumable = consumable;\n\n\t\tthis.fire( eventName, { markerName, markerRange }, this.conversionApi );\n\n\t\t//\n\t\t// Do not fire events for each item inside the range if the range got consumed.\n\t\t//\n\t\tif ( !consumable.test( markerRange, eventName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t//\n\t\t// Then, fire an event for each item inside the marker range.\n\t\t//\n\t\tthis.conversionApi.consumable = this._createConsumableForRange( markerRange, eventName );\n\n\t\tfor ( const item of markerRange.getItems() ) {\n\t\t\t// Do not fire event for already consumed items.\n\t\t\tif ( !this.conversionApi.consumable.test( item, eventName ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst data = { item, range: Range._createOn( item ), markerName, markerRange };\n\n\t\t\tthis.fire( eventName, data, this.conversionApi );\n\t\t}\n\n\t\tthis._clearConversionApi();\n\t}\n\n\t/**\n\t * Fires conversion of marker removal. Fires {@link #event:removeMarker removeMarker} event with provided data.\n\t *\n\t * @fires removeMarker\n\t * @param {String} markerName Marker name.\n\t * @param {module:engine/model/range~Range} markerRange Marker range.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that should be used to modify view document.\n\t */\n\tconvertMarkerRemove( markerName, markerRange, writer ) {\n\t\t// Do not convert if range is in graveyard or not in the document (e.g. in DocumentFragment).\n\t\tif ( !markerRange.root.document || markerRange.root.rootName == '$graveyard' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.conversionApi.writer = writer;\n\n\t\tthis.fire( 'removeMarker:' + markerName, { markerName, markerRange }, this.conversionApi );\n\n\t\tthis._clearConversionApi();\n\t}\n\n\t/**\n\t * Creates {@link module:engine/conversion/modelconsumable~ModelConsumable} with values to consume from given range,\n\t * assuming that the range has just been inserted to the model.\n\t *\n\t * @private\n\t * @param {module:engine/model/range~Range} range Inserted range.\n\t * @returns {module:engine/conversion/modelconsumable~ModelConsumable} Values to consume.\n\t */\n\t_createInsertConsumable( range ) {\n\t\tconst consumable = new Consumable();\n\n\t\tfor ( const value of range ) {\n\t\t\tconst item = value.item;\n\n\t\t\tconsumable.add( item, 'insert' );\n\n\t\t\tfor ( const key of item.getAttributeKeys() ) {\n\t\t\t\tconsumable.add( item, 'attribute:' + key );\n\t\t\t}\n\t\t}\n\n\t\treturn consumable;\n\t}\n\n\t/**\n\t * Creates {@link module:engine/conversion/modelconsumable~ModelConsumable} with values to consume for given range.\n\t *\n\t * @private\n\t * @param {module:engine/model/range~Range} range Affected range.\n\t * @param {String} type Consumable type.\n\t * @returns {module:engine/conversion/modelconsumable~ModelConsumable} Values to consume.\n\t */\n\t_createConsumableForRange( range, type ) {\n\t\tconst consumable = new Consumable();\n\n\t\tfor ( const item of range.getItems() ) {\n\t\t\tconsumable.add( item, type );\n\t\t}\n\n\t\treturn consumable;\n\t}\n\n\t/**\n\t * Creates {@link module:engine/conversion/modelconsumable~ModelConsumable} with selection consumable values.\n\t *\n\t * @private\n\t * @param {module:engine/model/selection~Selection} selection Selection to create consumable from.\n\t * @param {Iterable.<module:engine/model/markercollection~Marker>} markers Markers which contains selection.\n\t * @returns {module:engine/conversion/modelconsumable~ModelConsumable} Values to consume.\n\t */\n\t_createSelectionConsumable( selection, markers ) {\n\t\tconst consumable = new Consumable();\n\n\t\tconsumable.add( selection, 'selection' );\n\n\t\tfor ( const marker of markers ) {\n\t\t\tconsumable.add( selection, 'addMarker:' + marker.name );\n\t\t}\n\n\t\tfor ( const key of selection.getAttributeKeys() ) {\n\t\t\tconsumable.add( selection, 'attribute:' + key );\n\t\t}\n\n\t\treturn consumable;\n\t}\n\n\t/**\n\t * Tests passed `consumable` to check whether given event can be fired and if so, fires it.\n\t *\n\t * @private\n\t * @fires insert\n\t * @fires attribute\n\t * @param {String} type Event type.\n\t * @param {Object} data Event data.\n\t */\n\t_testAndFire( type, data ) {\n\t\tif ( !this.conversionApi.consumable.test( data.item, type ) ) {\n\t\t\t// Do not fire event if the item was consumed.\n\t\t\treturn;\n\t\t}\n\n\t\tconst name = data.item.name || '$text';\n\n\t\tthis.fire( type + ':' + name, data, this.conversionApi );\n\t}\n\n\t/**\n\t * Clears conversion API object.\n\t *\n\t * @private\n\t */\n\t_clearConversionApi() {\n\t\tdelete this.conversionApi.writer;\n\t\tdelete this.conversionApi.consumable;\n\t}\n\n\t/**\n\t * Fired for inserted nodes.\n\t *\n\t * `insert` is a namespace for a class of events. Names of actually called events follow this pattern:\n\t * `insert:name`. `name` is either `'$text'`, when {@link module:engine/model/text~Text a text node} has been inserted,\n\t * or {@link module:engine/model/element~Element#name name} of inserted element.\n\t *\n\t * This way listeners can either listen to a general `insert` event or specific event (for example `insert:paragraph`).\n\t *\n\t * @event insert\n\t * @param {Object} data Additional information about the change.\n\t * @param {module:engine/model/item~Item} data.item Inserted item.\n\t * @param {module:engine/model/range~Range} data.range Range spanning over inserted item.\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface\n\t * to be used by callback, passed in `DowncastDispatcher` constructor.\n\t */\n\n\t/**\n\t * Fired for removed nodes.\n\t *\n\t * `remove` is a namespace for a class of events. Names of actually called events follow this pattern:\n\t * `remove:name`. `name` is either `'$text'`, when {@link module:engine/model/text~Text a text node} has been removed,\n\t * or the {@link module:engine/model/element~Element#name name} of removed element.\n\t *\n\t * This way listeners can either listen to a general `remove` event or specific event (for example `remove:paragraph`).\n\t *\n\t * @event remove\n\t * @param {Object} data Additional information about the change.\n\t * @param {module:engine/model/position~Position} data.position Position from which the node has been removed.\n\t * @param {Number} data.length Offset size of the removed node.\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface\n\t * to be used by callback, passed in `DowncastDispatcher` constructor.\n\t */\n\n\t/**\n\t * Fired in the following cases:\n\t *\n\t * * when an attribute has been added, changed, or removed from a node,\n\t * * when a node with an attribute is inserted,\n\t * * when collapsed model selection attribute is converted.\n\t *\n\t * `attribute` is a namespace for a class of events. Names of actually called events follow this pattern:\n\t * `attribute:attributeKey:name`. `attributeKey` is the key of added/changed/removed attribute.\n\t * `name` is either `'$text'` if change was on {@link module:engine/model/text~Text a text node},\n\t * or the {@link module:engine/model/element~Element#name name} of element which attribute has changed.\n\t *\n\t * This way listeners can either listen to a general `attribute:bold` event or specific event (for example `attribute:src:image`).\n\t *\n\t * @event attribute\n\t * @param {Object} data Additional information about the change.\n\t * @param {module:engine/model/item~Item|module:engine/model/documentselection~DocumentSelection} data.item Changed item\n\t * or converted selection.\n\t * @param {module:engine/model/range~Range} data.range Range spanning over changed item or selection range.\n\t * @param {String} data.attributeKey Attribute key.\n\t * @param {*} data.attributeOldValue Attribute value before the change. This is `null` when selection attribute is converted.\n\t * @param {*} data.attributeNewValue New attribute value.\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface\n\t * to be used by callback, passed in `DowncastDispatcher` constructor.\n\t */\n\n\t/**\n\t * Fired for {@link module:engine/model/selection~Selection selection} changes.\n\t *\n\t * @event selection\n\t * @param {module:engine/model/selection~Selection} selection Selection that is converted.\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface\n\t * to be used by callback, passed in `DowncastDispatcher` constructor.\n\t */\n\n\t/**\n\t * Fired when a new marker is added to the model. Also fired when collapsed model selection that is inside marker is converted.\n\t *\n\t * `addMarker` is a namespace for a class of events. Names of actually called events follow this pattern:\n\t * `addMarker:markerName`. By specifying certain marker names, you can make the events even more gradual. For example,\n\t * if markers are named `foo:abc`, `foo:bar`, then it is possible to listen to `addMarker:foo` or `addMarker:foo:abc` and\n\t * `addMarker:foo:bar` events.\n\t *\n\t * If the marker range is not collapsed:\n\t *\n\t * * the event is fired for each item in the marker range one by one,\n\t * * `conversionApi.consumable` includes each item of the marker range and the consumable value is same as event name.\n\t *\n\t * If the marker range is collapsed:\n\t *\n\t * * there is only one event,\n\t * * `conversionApi.consumable` includes marker range with event name.\n\t *\n\t * If selection inside a marker is converted:\n\t *\n\t * * there is only one event,\n\t * * `conversionApi.consumable` includes selection instance with event name.\n\t *\n\t * @event addMarker\n\t * @param {Object} data Additional information about the change.\n\t * @param {module:engine/model/item~Item|module:engine/model/selection~Selection} data.item Item inside the new marker or\n\t * the selection that is being converted.\n\t * @param {module:engine/model/range~Range} [data.range] Range spanning over converted item. Available only in marker conversion, if\n\t * the marker range was not collapsed.\n\t * @param {module:engine/model/range~Range} data.markerRange Marker range.\n\t * @param {String} data.markerName Marker name.\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface\n\t * to be used by callback, passed in `DowncastDispatcher` constructor.\n\t */\n\n\t/**\n\t * Fired when marker is removed from the model.\n\t *\n\t * `removeMarker` is a namespace for a class of events. Names of actually called events follow this pattern:\n\t * `removeMarker:markerName`. By specifying certain marker names, you can make the events even more gradual. For example,\n\t * if markers are named `foo:abc`, `foo:bar`, then it is possible to listen to `removeMarker:foo` or `removeMarker:foo:abc` and\n\t * `removeMarker:foo:bar` events.\n\t *\n\t * @event removeMarker\n\t * @param {Object} data Additional information about the change.\n\t * @param {module:engine/model/range~Range} data.markerRange Marker range.\n\t * @param {String} data.markerName Marker name.\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface\n\t * to be used by callback, passed in `DowncastDispatcher` constructor.\n\t */\n}\n\nmix( DowncastDispatcher, EmitterMixin );\n\n// Helper function, checks whether change of `marker` at `modelPosition` should be converted. Marker changes are not\n// converted if they happen inside an element with custom conversion method.\n//\n// @param {module:engine/model/position~Position} modelPosition\n// @param {module:engine/model/markercollection~Marker} marker\n// @param {module:engine/conversion/mapper~Mapper} mapper\n// @returns {Boolean}\nfunction shouldMarkerChangeBeConverted( modelPosition, marker, mapper ) {\n\tconst range = marker.getRange();\n\tconst ancestors = Array.from( modelPosition.getAncestors() );\n\tancestors.shift(); // Remove root element. It cannot be passed to `model.Range#containsItem`.\n\tancestors.reverse();\n\n\tconst hasCustomHandling = ancestors.some( element => {\n\t\tif ( range.containsItem( element ) ) {\n\t\t\tconst viewElement = mapper.toViewElement( element );\n\n\t\t\treturn !!viewElement.getCustomProperty( 'addHighlight' );\n\t\t}\n\t} );\n\n\treturn !hasCustomHandling;\n}\n\n/**\n * Conversion interface that is registered for given {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}\n * and is passed as one of parameters when {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher dispatcher}\n * fires it's events.\n *\n * @interface module:engine/conversion/downcastdispatcher~DowncastConversionApi\n */\n\n/**\n * The {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher} instance.\n *\n * @member {module:engine/conversion/downcastdispatcher~DowncastDispatcher} #dispatcher\n */\n\n/**\n * Stores information about what parts of processed model item are still waiting to be handled. After a piece of model item\n * was converted, appropriate consumable value should be {@link module:engine/conversion/modelconsumable~ModelConsumable#consume consumed}.\n *\n * @member {module:engine/conversion/modelconsumable~ModelConsumable} #consumable\n */\n\n/**\n * The {@link module:engine/conversion/mapper~Mapper} instance.\n *\n * @member {module:engine/conversion/mapper~Mapper} #mapper\n */\n\n/**\n * The {@link module:engine/view/downcastwriter~DowncastWriter} instance used to manipulate data during conversion.\n *\n * @member {module:engine/view/downcastwriter~DowncastWriter} #writer\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/selection\n */\n\nimport Position from './position';\nimport Element from './element';\nimport Node from './node';\nimport Range from './range';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\n\n/**\n * Selection is a set of {@link module:engine/model/range~Range ranges}. It has a direction specified by its\n * {@link module:engine/model/selection~Selection#anchor anchor} and {@link module:engine/model/selection~Selection#focus focus}\n * (it can be {@link module:engine/model/selection~Selection#isBackward forward or backward}).\n * Additionally, selection may have its own attributes (think – whether text typed in in this selection\n * should have those attributes – e.g. whether you type a bolded text).\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class Selection {\n\t/**\n\t * Creates a new selection instance based on the given {@link module:engine/model/selection~Selectable selectable}\n\t * or creates an empty selection if no arguments were passed.\n\t *\n\t *\t\t// Creates empty selection without ranges.\n\t *\t\tconst selection = writer.createSelection();\n\t *\n\t *\t\t// Creates selection at the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tconst selection = writer.createSelection( range );\n\t *\n\t *\t\t// Creates selection at the given ranges\n\t *\t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];\n\t *\t\tconst selection = writer.createSelection( ranges );\n\t *\n\t *\t\t// Creates selection from the other selection.\n\t *\t\t// Note: It doesn't copies selection attributes.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tconst selection = writer.createSelection( otherSelection );\n\t *\n\t *\t\t// Creates selection from the given document selection.\n\t *\t\t// Note: It doesn't copies selection attributes.\n\t *\t\tconst documentSelection = model.document.selection;\n\t *\t\tconst selection = writer.createSelection( documentSelection );\n\t *\n\t *\t\t// Creates selection at the given position.\n\t *\t\tconst position = writer.createPositionFromPath( root, path );\n\t *\t\tconst selection = writer.createSelection( position );\n\t *\n\t *\t\t// Creates selection at the given offset in the given element.\n\t *\t\tconst paragraph = writer.createElement( 'paragraph' );\n\t *\t\tconst selection = writer.createSelection( paragraph, offset );\n\t *\n\t *\t\t// Creates a range inside an {@link module:engine/model/element~Element element} which starts before the\n\t *\t\t// first child of that element and ends after the last child of that element.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'in' );\n\t *\n\t *\t\t// Creates a range on an {@link module:engine/model/item~Item item} which starts before the item and ends\n\t *\t\t// just after the item.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'on' );\n\t *\n\t * Selection's constructor allow passing additional options (`'backward'`) as the last argument.\n\t *\n\t *\t\t// Creates backward selection.\n\t *\t\tconst selection = writer.createSelection( range, { backward: true } );\n\t *\n\t * @param {module:engine/model/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t */\n\tconstructor( selectable, placeOrOffset, options ) {\n\t\t/**\n\t\t * Specifies whether the last added range was added as a backward or forward range.\n\t\t *\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._lastRangeBackward = false;\n\n\t\t/**\n\t\t * Stores selection ranges.\n\t\t *\n\t\t * @protected\n\t\t * @type {Array.<module:engine/model/range~Range>}\n\t\t */\n\t\tthis._ranges = [];\n\n\t\t/**\n\t\t * List of attributes set on current selection.\n\t\t *\n\t\t * @protected\n\t\t * @type {Map.<String,*>}\n\t\t */\n\t\tthis._attrs = new Map();\n\n\t\tif ( selectable ) {\n\t\t\tthis.setTo( selectable, placeOrOffset, options );\n\t\t}\n\t}\n\n\t/**\n\t * Selection anchor. Anchor is the position from which the selection was started. If a user is making a selection\n\t * by dragging the mouse, the anchor is where the user pressed the mouse button (the beggining of the selection).\n\t *\n\t * Anchor and {@link #focus} define the direction of the selection, which is important\n\t * when expanding/shrinking selection. The focus moves, while the anchor should remain in the same place.\n\t *\n\t * Anchor is always set to the {@link module:engine/model/range~Range#start start} or\n\t * {@link module:engine/model/range~Range#end end} position of the last of selection's ranges. Whether it is\n\t * the `start` or `end` depends on the specified `options.backward`. See the {@link #setTo `setTo()`} method.\n\t *\n\t * May be set to `null` if there are no ranges in the selection.\n\t *\n\t * @see #focus\n\t * @readonly\n\t * @type {module:engine/model/position~Position|null}\n\t */\n\tget anchor() {\n\t\tif ( this._ranges.length > 0 ) {\n\t\t\tconst range = this._ranges[ this._ranges.length - 1 ];\n\n\t\t\treturn this._lastRangeBackward ? range.end : range.start;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Selection focus. Focus is the position where the selection ends. If a user is making a selection\n\t * by dragging the mouse, the focus is where the mouse cursor is.\n\t *\n\t * May be set to `null` if there are no ranges in the selection.\n\t *\n\t * @see #anchor\n\t * @readonly\n\t * @type {module:engine/model/position~Position|null}\n\t */\n\tget focus() {\n\t\tif ( this._ranges.length > 0 ) {\n\t\t\tconst range = this._ranges[ this._ranges.length - 1 ];\n\n\t\t\treturn this._lastRangeBackward ? range.start : range.end;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Whether the selection is collapsed. Selection is collapsed when there is exactly one range in it\n\t * and it is collapsed.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isCollapsed() {\n\t\tconst length = this._ranges.length;\n\n\t\tif ( length === 1 ) {\n\t\t\treturn this._ranges[ 0 ].isCollapsed;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the number of ranges in the selection.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget rangeCount() {\n\t\treturn this._ranges.length;\n\t}\n\n\t/**\n\t * Specifies whether the selection's {@link #focus} precedes the selection's {@link #anchor}.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isBackward() {\n\t\treturn !this.isCollapsed && this._lastRangeBackward;\n\t}\n\n\t/**\n\t * Checks whether this selection is equal to the given selection. Selections are equal if they have the same directions,\n\t * the same number of ranges and all ranges from one selection equal to ranges from the another selection.\n\t *\n\t * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} otherSelection\n\t * Selection to compare with.\n\t * @returns {Boolean} `true` if selections are equal, `false` otherwise.\n\t */\n\tisEqual( otherSelection ) {\n\t\tif ( this.rangeCount != otherSelection.rangeCount ) {\n\t\t\treturn false;\n\t\t} else if ( this.rangeCount === 0 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( !this.anchor.isEqual( otherSelection.anchor ) || !this.focus.isEqual( otherSelection.focus ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor ( const thisRange of this._ranges ) {\n\t\t\tlet found = false;\n\n\t\t\tfor ( const otherRange of otherSelection._ranges ) {\n\t\t\t\tif ( thisRange.isEqual( otherRange ) ) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !found ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns an iterable object that iterates over copies of selection ranges.\n\t *\n\t * @returns {Iterable.<module:engine/model/range~Range>}\n\t */\n\t* getRanges() {\n\t\tfor ( const range of this._ranges ) {\n\t\t\tyield new Range( range.start, range.end );\n\t\t}\n\t}\n\n\t/**\n\t * Returns a copy of the first range in the selection.\n\t * First range is the one which {@link module:engine/model/range~Range#start start} position\n\t * {@link module:engine/model/position~Position#isBefore is before} start position of all other ranges\n\t * (not to confuse with the first range added to the selection).\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/range~Range|null}\n\t */\n\tgetFirstRange() {\n\t\tlet first = null;\n\n\t\tfor ( const range of this._ranges ) {\n\t\t\tif ( !first || range.start.isBefore( first.start ) ) {\n\t\t\t\tfirst = range;\n\t\t\t}\n\t\t}\n\n\t\treturn first ? new Range( first.start, first.end ) : null;\n\t}\n\n\t/**\n\t * Returns a copy of the last range in the selection.\n\t * Last range is the one which {@link module:engine/model/range~Range#end end} position\n\t * {@link module:engine/model/position~Position#isAfter is after} end position of all other ranges (not to confuse with the range most\n\t * recently added to the selection).\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/range~Range|null}\n\t */\n\tgetLastRange() {\n\t\tlet last = null;\n\n\t\tfor ( const range of this._ranges ) {\n\t\t\tif ( !last || range.end.isAfter( last.end ) ) {\n\t\t\t\tlast = range;\n\t\t\t}\n\t\t}\n\n\t\treturn last ? new Range( last.start, last.end ) : null;\n\t}\n\n\t/**\n\t * Returns the first position in the selection.\n\t * First position is the position that {@link module:engine/model/position~Position#isBefore is before}\n\t * any other position in the selection.\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/position~Position|null}\n\t */\n\tgetFirstPosition() {\n\t\tconst first = this.getFirstRange();\n\n\t\treturn first ? first.start.clone() : null;\n\t}\n\n\t/**\n\t * Returns the last position in the selection.\n\t * Last position is the position that {@link module:engine/model/position~Position#isAfter is after}\n\t * any other position in the selection.\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/position~Position|null}\n\t */\n\tgetLastPosition() {\n\t\tconst lastRange = this.getLastRange();\n\n\t\treturn lastRange ? lastRange.end.clone() : null;\n\t}\n\n\t/**\n\t * Sets this selection's ranges and direction to the specified location based on the given\n\t * {@link module:engine/model/selection~Selectable selectable}.\n\t *\n\t *\t\t// Removes all selection's ranges.\n\t *\t\tselection.setTo( null );\n\t *\n\t *\t\t// Sets selection to the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tselection.setTo( range );\n\t *\n\t *\t\t// Sets selection to given ranges.\n\t *\t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];\n\t *\t\tselection.setTo( ranges );\n\t *\n\t *\t\t// Sets selection to other selection.\n\t *\t\t// Note: It doesn't copies selection attributes.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tselection.setTo( otherSelection );\n\t *\n\t *\t\t// Sets selection to the given document selection.\n\t *\t\t// Note: It doesn't copies selection attributes.\n\t *\t\tconst documentSelection = new DocumentSelection( doc );\n\t *\t\tselection.setTo( documentSelection );\n\t *\n\t *\t\t// Sets collapsed selection at the given position.\n\t *\t\tconst position = writer.createPositionFromPath( root, path );\n\t *\t\tselection.setTo( position );\n\t *\n\t *\t\t// Sets collapsed selection at the position of the given node and an offset.\n\t *\t\tselection.setTo( paragraph, offset );\n\t *\n\t * Creates a range inside an {@link module:engine/model/element~Element element} which starts before the first child of\n \t * that element and ends after the last child of that element.\n\t *\n\t *\t\tselection.setTo( paragraph, 'in' );\n\t *\n\t * Creates a range on an {@link module:engine/model/item~Item item} which starts before the item and ends just after the item.\n\t *\n\t *\t\tselection.setTo( paragraph, 'on' );\n\t *\n\t * `Selection#setTo()`' method allow passing additional options (`backward`) as the last argument.\n\t *\n\t *\t\t// Sets backward selection.\n\t *\t\tconst selection = writer.createSelection( range, { backward: true } );\n\t *\n\t * @param {module:engine/model/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t */\n\tsetTo( selectable, placeOrOffset, options ) {\n\t\tif ( selectable === null ) {\n\t\t\tthis._setRanges( [] );\n\t\t} else if ( selectable instanceof Selection ) {\n\t\t\tthis._setRanges( selectable.getRanges(), selectable.isBackward );\n\t\t} else if ( selectable && typeof selectable.getRanges == 'function' ) {\n\t\t\t// We assume that the selectable is a DocumentSelection.\n\t\t\t// It can't be imported here, because it would lead to circular imports.\n\t\t\tthis._setRanges( selectable.getRanges(), selectable.isBackward );\n\t\t} else if ( selectable instanceof Range ) {\n\t\t\tthis._setRanges( [ selectable ], !!placeOrOffset && !!placeOrOffset.backward );\n\t\t} else if ( selectable instanceof Position ) {\n\t\t\tthis._setRanges( [ new Range( selectable ) ] );\n\t\t} else if ( selectable instanceof Node ) {\n\t\t\tconst backward = !!options && !!options.backward;\n\t\t\tlet range;\n\n\t\t\tif ( placeOrOffset == 'in' ) {\n\t\t\t\trange = Range._createIn( selectable );\n\t\t\t} else if ( placeOrOffset == 'on' ) {\n\t\t\t\trange = Range._createOn( selectable );\n\t\t\t} else if ( placeOrOffset !== undefined ) {\n\t\t\t\trange = new Range( Position._createAt( selectable, placeOrOffset ) );\n\t\t\t} else {\n\t\t\t\t/**\n\t\t\t\t * selection.setTo requires the second parameter when the first parameter is a node.\n\t\t\t\t *\n\t\t\t\t * @error model-selection-setTo-required-second-parameter\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'model-selection-setTo-required-second-parameter: ' +\n\t\t\t\t\t'selection.setTo requires the second parameter when the first parameter is a node.',\n\t\t\t\t\t[ this, selectable ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis._setRanges( [ range ], backward );\n\t\t} else if ( isIterable( selectable ) ) {\n\t\t\t// We assume that the selectable is an iterable of ranges.\n\t\t\tthis._setRanges( selectable, placeOrOffset && !!placeOrOffset.backward );\n\t\t} else {\n\t\t\t/**\n\t\t\t * Cannot set the selection to the given place.\n\t\t\t *\n\t\t\t * Invalid parameters were specified when setting the selection. Common issues:\n\t\t\t *\n\t\t\t * * A {@link module:engine/model/textproxy~TextProxy} instance was passed instead of\n\t\t\t * a real {@link module:engine/model/text~Text}.\n\t\t\t * * View nodes were passed instead of model nodes.\n\t\t\t * * `null`/`undefined` was passed.\n\t\t\t *\n\t\t\t * @error model-selection-setTo-not-selectable\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-selection-setTo-not-selectable: Cannot set the selection to the given place.',\n\t\t\t\t[ this, selectable ]\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Replaces all ranges that were added to the selection with given array of ranges. Last range of the array\n\t * is treated like the last added range and is used to set {@link module:engine/model/selection~Selection#anchor} and\n\t * {@link module:engine/model/selection~Selection#focus}. Accepts a flag describing in which direction the selection is made.\n\t *\n\t * @protected\n\t * @fires change:range\n\t * @param {Iterable.<module:engine/model/range~Range>} newRanges Ranges to set.\n\t * @param {Boolean} [isLastBackward=false] Flag describing if last added range was selected forward - from start to end (`false`)\n\t * or backward - from end to start (`true`).\n\t */\n\t_setRanges( newRanges, isLastBackward = false ) {\n\t\tnewRanges = Array.from( newRanges );\n\n\t\t// Check whether there is any range in new ranges set that is different than all already added ranges.\n\t\tconst anyNewRange = newRanges.some( newRange => {\n\t\t\tif ( !( newRange instanceof Range ) ) {\n\t\t\t\t/**\n\t\t\t\t * Selection range set to an object that is not an instance of {@link module:engine/model/range~Range}.\n\t\t\t\t *\n\t\t\t\t * Only {@link module:engine/model/range~Range} instances can be used to set a selection.\n\t\t\t\t * Common mistakes leading to this error are:\n\t\t\t\t *\n\t\t\t\t * * using DOM `Range` object,\n\t\t\t\t * * incorrect CKEditor 5 installation with multiple `ckeditor5-engine` packages having different versions.\n\t\t\t\t *\n\t\t\t\t * @error model-selection-set-ranges-not-range\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'model-selection-set-ranges-not-range: ' +\n\t\t\t\t\t'Selection range set to an object that is not an instance of model.Range.',\n\t\t\t\t\t[ this, newRanges ]\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn this._ranges.every( oldRange => {\n\t\t\t\treturn !oldRange.isEqual( newRange );\n\t\t\t} );\n\t\t} );\n\n\t\t// Don't do anything if nothing changed.\n\t\tif ( newRanges.length === this._ranges.length && !anyNewRange ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._removeAllRanges();\n\n\t\tfor ( const range of newRanges ) {\n\t\t\tthis._pushRange( range );\n\t\t}\n\n\t\tthis._lastRangeBackward = !!isLastBackward;\n\n\t\tthis.fire( 'change:range', { directChange: true } );\n\t}\n\n\t/**\n\t * Moves {@link module:engine/model/selection~Selection#focus} to the specified location.\n\t *\n\t * The location can be specified in the same form as\n\t * {@link module:engine/model/writer~Writer#createPositionAt writer.createPositionAt()} parameters.\n\t *\n\t * @fires change:range\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\tsetFocus( itemOrPosition, offset ) {\n\t\tif ( this.anchor === null ) {\n\t\t\t/**\n\t\t\t * Cannot set selection focus if there are no ranges in selection.\n\t\t\t *\n\t\t\t * @error model-selection-setFocus-no-ranges\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-selection-setFocus-no-ranges: Cannot set selection focus if there are no ranges in selection.',\n\t\t\t\t[ this, itemOrPosition ]\n\t\t\t);\n\t\t}\n\n\t\tconst newFocus = Position._createAt( itemOrPosition, offset );\n\n\t\tif ( newFocus.compareWith( this.focus ) == 'same' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst anchor = this.anchor;\n\n\t\tif ( this._ranges.length ) {\n\t\t\tthis._popRange();\n\t\t}\n\n\t\tif ( newFocus.compareWith( anchor ) == 'before' ) {\n\t\t\tthis._pushRange( new Range( newFocus, anchor ) );\n\t\t\tthis._lastRangeBackward = true;\n\t\t} else {\n\t\t\tthis._pushRange( new Range( anchor, newFocus ) );\n\t\t\tthis._lastRangeBackward = false;\n\t\t}\n\n\t\tthis.fire( 'change:range', { directChange: true } );\n\t}\n\n\t/**\n\t * Gets an attribute value for given key or `undefined` if that attribute is not set on the selection.\n\t *\n\t * @param {String} key Key of attribute to look for.\n\t * @returns {*} Attribute value or `undefined`.\n\t */\n\tgetAttribute( key ) {\n\t\treturn this._attrs.get( key );\n\t}\n\n\t/**\n\t * Returns iterable that iterates over this selection's attributes.\n\t *\n\t * Attributes are returned as arrays containing two items. First one is attribute key and second is attribute value.\n\t * This format is accepted by native `Map` object and also can be passed in `Node` constructor.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\tgetAttributes() {\n\t\treturn this._attrs.entries();\n\t}\n\n\t/**\n\t * Returns iterable that iterates over this selection's attribute keys.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\tgetAttributeKeys() {\n\t\treturn this._attrs.keys();\n\t}\n\n\t/**\n\t * Checks if the selection has an attribute for given key.\n\t *\n\t * @param {String} key Key of attribute to check.\n\t * @returns {Boolean} `true` if attribute with given key is set on selection, `false` otherwise.\n\t */\n\thasAttribute( key ) {\n\t\treturn this._attrs.has( key );\n\t}\n\n\t/**\n\t * Removes an attribute with given key from the selection.\n\t *\n\t * If given attribute was set on the selection, fires the {@link #event:change:range} event with\n\t * removed attribute key.\n\t *\n\t * @fires change:attribute\n\t * @param {String} key Key of attribute to remove.\n\t */\n\tremoveAttribute( key ) {\n\t\tif ( this.hasAttribute( key ) ) {\n\t\t\tthis._attrs.delete( key );\n\n\t\t\tthis.fire( 'change:attribute', { attributeKeys: [ key ], directChange: true } );\n\t\t}\n\t}\n\n\t/**\n\t * Sets attribute on the selection. If attribute with the same key already is set, it's value is overwritten.\n\t *\n\t * If the attribute value has changed, fires the {@link #event:change:range} event with\n\t * the attribute key.\n\t *\n\t * @fires change:attribute\n\t * @param {String} key Key of attribute to set.\n\t * @param {*} value Attribute value.\n\t */\n\tsetAttribute( key, value ) {\n\t\tif ( this.getAttribute( key ) !== value ) {\n\t\t\tthis._attrs.set( key, value );\n\n\t\t\tthis.fire( 'change:attribute', { attributeKeys: [ key ], directChange: true } );\n\t\t}\n\t}\n\n\t/**\n\t * Returns the selected element. {@link module:engine/model/element~Element Element} is considered as selected if there is only\n\t * one range in the selection, and that range contains exactly one element.\n\t * Returns `null` if there is no selected element.\n\t *\n\t * @returns {module:engine/model/element~Element|null}\n\t */\n\tgetSelectedElement() {\n\t\tif ( this.rangeCount !== 1 ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst range = this.getFirstRange();\n\t\tconst nodeAfterStart = range.start.nodeAfter;\n\t\tconst nodeBeforeEnd = range.end.nodeBefore;\n\n\t\treturn ( nodeAfterStart instanceof Element && nodeAfterStart == nodeBeforeEnd ) ? nodeAfterStart : null;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tselection.is( 'selection' ); // -> true\n\t *\t\tselection.is( 'model:selection' ); // -> true\n\t *\n\t *\t\tselection.is( 'view:selection' ); // -> false\n\t *\t\tselection.is( 'range' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'selection' || type == 'model:selection';\n\t}\n\n\t/**\n\t * Gets elements of type {@link module:engine/model/schema~Schema#isBlock \"block\"} touched by the selection.\n\t *\n\t * This method's result can be used for example to apply block styling to all blocks covered by this selection.\n\t *\n\t * **Note:** `getSelectedBlocks()` returns blocks that are nested in other non-block elements\n\t * but will not return blocks nested in other blocks.\n\t *\n\t * In this case the function will return exactly all 3 paragraphs (note: `<blockQuote>` is not a block itself):\n\t *\n\t *\t\t<paragraph>[a</paragraph>\n\t *\t\t<blockQuote>\n\t *\t\t\t<paragraph>b</paragraph>\n\t *\t\t</blockQuote>\n\t *\t\t<paragraph>c]d</paragraph>\n\t *\n\t * In this case the paragraph will also be returned, despite the collapsed selection:\n\t *\n\t *\t\t<paragraph>[]a</paragraph>\n\t *\n\t * In such a scenario, however, only blocks A, B & E will be returned as blocks C & D are nested in block B:\n\t *\n\t *\t\t[<blockA></blockA>\n\t *\t\t<blockB>\n\t *\t\t\t<blockC></blockC>\n\t *\t\t\t<blockD></blockD>\n\t *\t\t</blockB>\n\t *\t\t<blockE></blockE>]\n\t *\n\t * If the selection is inside a block all the inner blocks (A & B) are returned:\n\t *\n\t * \t\t<block>\n\t *\t\t\t<blockA>[a</blockA>\n\t * \t\t\t<blockB>b]</blockB>\n\t * \t\t</block>\n\t *\n\t * **Special case**: If a selection ends at the beginning of a block, that block is not returned as from user perspective\n\t * this block wasn't selected. See [#984](https://github.com/ckeditor/ckeditor5-engine/issues/984) for more details.\n\t *\n\t *\t\t<paragraph>[a</paragraph>\n\t *\t\t<paragraph>b</paragraph>\n\t *\t\t<paragraph>]c</paragraph> // this block will not be returned\n\t *\n\t * @returns {Iterable.<module:engine/model/element~Element>}\n\t */\n\t* getSelectedBlocks() {\n\t\tconst visited = new WeakSet();\n\n\t\tfor ( const range of this.getRanges() ) {\n\t\t\t// Get start block of range in case of a collapsed range.\n\t\t\tconst startBlock = getParentBlock( range.start, visited );\n\n\t\t\tif ( startBlock && isTopBlockInRange( startBlock, range ) ) {\n\t\t\t\tyield startBlock;\n\t\t\t}\n\n\t\t\tfor ( const value of range.getWalker() ) {\n\t\t\t\tconst block = value.item;\n\n\t\t\t\tif ( value.type == 'elementEnd' && isUnvisitedTopBlock( block, visited, range ) ) {\n\t\t\t\t\tyield block;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst endBlock = getParentBlock( range.end, visited );\n\n\t\t\t// #984. Don't return the end block if the range ends right at its beginning.\n\t\t\tif ( endBlock && !range.end.isTouching( Position._createAt( endBlock, 0 ) ) && isTopBlockInRange( endBlock, range ) ) {\n\t\t\t\tyield endBlock;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Checks whether the selection contains the entire content of the given element. This means that selection must start\n\t * at a position {@link module:engine/model/position~Position#isTouching touching} the element's start and ends at position\n\t * touching the element's end.\n\t *\n\t * By default, this method will check whether the entire content of the selection's current root is selected.\n\t * Useful to check if e.g. the user has just pressed <kbd>Ctrl</kbd> + <kbd>A</kbd>.\n\t *\n\t * @param {module:engine/model/element~Element} [element=this.anchor.root]\n\t * @returns {Boolean}\n\t */\n\tcontainsEntireContent( element = this.anchor.root ) {\n\t\tconst limitStartPosition = Position._createAt( element, 0 );\n\t\tconst limitEndPosition = Position._createAt( element, 'end' );\n\n\t\treturn limitStartPosition.isTouching( this.getFirstPosition() ) &&\n\t\t\tlimitEndPosition.isTouching( this.getLastPosition() );\n\t}\n\n\t/**\n\t * Adds given range to internal {@link #_ranges ranges array}. Throws an error\n\t * if given range is intersecting with any range that is already stored in this selection.\n\t *\n\t * @protected\n\t * @param {module:engine/model/range~Range} range Range to add.\n\t */\n\t_pushRange( range ) {\n\t\tthis._checkRange( range );\n\t\tthis._ranges.push( new Range( range.start, range.end ) );\n\t}\n\n\t/**\n\t * Checks if given range intersects with ranges that are already in the selection. Throws an error if it does.\n\t *\n\t * @protected\n\t * @param {module:engine/model/range~Range} range Range to check.\n\t */\n\t_checkRange( range ) {\n\t\tfor ( let i = 0; i < this._ranges.length; i++ ) {\n\t\t\tif ( range.isIntersecting( this._ranges[ i ] ) ) {\n\t\t\t\t/**\n\t\t\t\t * Trying to add a range that intersects with another range in the selection.\n\t\t\t\t *\n\t\t\t\t * @error model-selection-range-intersects\n\t\t\t\t * @param {module:engine/model/range~Range} addedRange Range that was added to the selection.\n\t\t\t\t * @param {module:engine/model/range~Range} intersectingRange Range in the selection that intersects with `addedRange`.\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'model-selection-range-intersects: Trying to add a range that intersects with another range in the selection.',\n\t\t\t\t\t[ this, range ],\n\t\t\t\t\t{ addedRange: range, intersectingRange: this._ranges[ i ] }\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Deletes ranges from internal range array. Uses {@link #_popRange _popRange} to\n\t * ensure proper ranges removal.\n\t *\n\t * @protected\n\t */\n\t_removeAllRanges() {\n\t\twhile ( this._ranges.length > 0 ) {\n\t\t\tthis._popRange();\n\t\t}\n\t}\n\n\t/**\n\t * Removes most recently added range from the selection.\n\t *\n\t * @protected\n\t */\n\t_popRange() {\n\t\tthis._ranges.pop();\n\t}\n\n\t/**\n\t * Fired when selection range(s) changed.\n\t *\n\t * @event change:range\n\t * @param {Boolean} directChange In case of {@link module:engine/model/selection~Selection} class it is always set\n\t * to `true` which indicates that the selection change was caused by a direct use of selection's API.\n\t * The {@link module:engine/model/documentselection~DocumentSelection}, however, may change because its position\n\t * was directly changed through the {@link module:engine/model/writer~Writer writer} or because its position was\n\t * changed because the structure of the model has been changed (which means an indirect change).\n\t * The indirect change does not occur in case of normal (detached) selections because they are \"static\" (as \"not live\")\n\t * which mean that they are not updated once the document changes.\n\t */\n\n\t/**\n\t * Fired when selection attribute changed.\n\t *\n\t * @event change:attribute\n\t * @param {Boolean} directChange In case of {@link module:engine/model/selection~Selection} class it is always set\n\t * to `true` which indicates that the selection change was caused by a direct use of selection's API.\n\t * The {@link module:engine/model/documentselection~DocumentSelection}, however, may change because its attributes\n\t * were directly changed through the {@link module:engine/model/writer~Writer writer} or because its position was\n\t * changed in the model and its attributes were refreshed (which means an indirect change).\n\t * The indirect change does not occur in case of normal (detached) selections because they are \"static\" (as \"not live\")\n\t * which mean that they are not updated once the document changes.\n\t * @param {Array.<String>} attributeKeys Array containing keys of attributes that changed.\n\t */\n}\n\nmix( Selection, EmitterMixin );\n\n// Checks whether the given element extends $block in the schema and has a parent (is not a root).\n// Marks it as already visited.\nfunction isUnvisitedBlock( element, visited ) {\n\tif ( visited.has( element ) ) {\n\t\treturn false;\n\t}\n\n\tvisited.add( element );\n\n\treturn element.document.model.schema.isBlock( element ) && element.parent;\n}\n\n// Checks if the given element is a $block was not previously visited and is a top block in a range.\nfunction isUnvisitedTopBlock( element, visited, range ) {\n\treturn isUnvisitedBlock( element, visited ) && isTopBlockInRange( element, range );\n}\n\n// Finds the lowest element in position's ancestors which is a block.\n// It will search until first ancestor that is a limit element.\n// Marks all ancestors as already visited to not include any of them later on.\nfunction getParentBlock( position, visited ) {\n\tconst schema = position.parent.document.model.schema;\n\n\tconst ancestors = position.parent.getAncestors( { parentFirst: true, includeSelf: true } );\n\n\tlet hasParentLimit = false;\n\n\tconst block = ancestors.find( element => {\n\t\t// Stop searching after first parent node that is limit element.\n\t\tif ( hasParentLimit ) {\n\t\t\treturn false;\n\t\t}\n\n\t\thasParentLimit = schema.isLimit( element );\n\n\t\treturn !hasParentLimit && isUnvisitedBlock( element, visited );\n\t} );\n\n\t// Mark all ancestors of this position's parent, because find() might've stopped early and\n\t// the found block may be a child of another block.\n\tancestors.forEach( element => visited.add( element ) );\n\n\treturn block;\n}\n\n// Checks if the blocks is not nested in other block inside a range.\n//\n// @param {module:engine/model/elmenent~Element} block Block to check.\n// @param {module:engine/model/range~Range} range Range to check.\nfunction isTopBlockInRange( block, range ) {\n\tconst parentBlock = findAncestorBlock( block );\n\n\tif ( !parentBlock ) {\n\t\treturn true;\n\t}\n\n\t// Add loose flag to check as parentRange can be equal to range.\n\tconst isParentInRange = range.containsRange( Range._createOn( parentBlock ), true );\n\n\treturn !isParentInRange;\n}\n\n// Returns first ancestor block of a node.\n//\n// @param {module:engine/model/node~Node} node\n// @returns {module:engine/model/node~Node|undefined}\nfunction findAncestorBlock( node ) {\n\tconst schema = node.document.model.schema;\n\n\tlet parent = node.parent;\n\n\twhile ( parent ) {\n\t\tif ( schema.isBlock( parent ) ) {\n\t\t\treturn parent;\n\t\t}\n\n\t\tparent = parent.parent;\n\t}\n}\n\n/**\n * An entity that is used to set selection.\n *\n * See also {@link module:engine/model/selection~Selection#setTo}\n *\n * @typedef {\n * module:engine/model/selection~Selection|\n * module:engine/model/documentselection~DocumentSelection|\n * module:engine/model/position~Position|\n * module:engine/model/range~Range|\n * module:engine/model/node~Node|\n * Iterable.<module:engine/model/range~Range>|\n * null\n * } module:engine/model/selection~Selectable\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/liverange\n */\n\nimport Range from './range';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * `LiveRange` is a type of {@link module:engine/model/range~Range Range}\n * that updates itself as {@link module:engine/model/document~Document document}\n * is changed through operations. It may be used as a bookmark.\n *\n * **Note:** Be very careful when dealing with `LiveRange`. Each `LiveRange` instance bind events that might\n * have to be unbound. Use {@link module:engine/model/liverange~LiveRange#detach detach} whenever you don't need `LiveRange` anymore.\n */\nexport default class LiveRange extends Range {\n\t/**\n\t * Creates a live range.\n\t *\n\t * @see module:engine/model/range~Range\n\t */\n\tconstructor( start, end ) {\n\t\tsuper( start, end );\n\n\t\tbindWithDocument.call( this );\n\t}\n\n\t/**\n\t * Unbinds all events previously bound by `LiveRange`. Use it whenever you don't need `LiveRange` instance\n\t * anymore (i.e. when leaving scope in which it was declared or before re-assigning variable that was\n\t * referring to it).\n\t */\n\tdetach() {\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tliveRange.is( 'range' ); // -> true\n\t *\t\tliveRange.is( 'model:range' ); // -> true\n\t *\t\tliveRange.is( 'liveRange' ); // -> true\n\t *\t\tliveRange.is( 'model:liveRange' ); // -> true\n\t *\n\t *\t\tliveRange.is( 'view:range' ); // -> false\n\t *\t\tliveRange.is( 'documentSelection' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'liveRange' || type == 'model:liveRange' || super.is( type );\n\t}\n\n\t/**\n\t * Creates a {@link module:engine/model/range~Range range instance} that is equal to this live range.\n\t *\n\t * @returns {module:engine/model/range~Range}\n\t */\n\ttoRange() {\n\t\treturn new Range( this.start, this.end );\n\t}\n\n\t/**\n\t * Creates a `LiveRange` instance that is equal to the given range.\n\t *\n\t * @param {module:engine/model/range~Range} range\n\t * @returns {module:engine/model/liverange~LiveRange}\n\t */\n\tstatic fromRange( range ) {\n\t\treturn new LiveRange( range.start, range.end );\n\t}\n\n\t/**\n\t * @see module:engine/model/range~Range._createIn\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liverange~LiveRange._createIn\n\t * @param {module:engine/model/element~Element} element\n\t * @returns {module:engine/model/liverange~LiveRange}\n\t */\n\n\t/**\n\t * @see module:engine/model/range~Range._createOn\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liverange~LiveRange._createOn\n\t * @param {module:engine/model/element~Element} element\n\t * @returns {module:engine/model/liverange~LiveRange}\n\t */\n\n\t/**\n\t * @see module:engine/model/range~Range._createFromPositionAndShift\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liverange~LiveRange._createFromPositionAndShift\n\t * @param {module:engine/model/position~Position} position\n\t * @param {Number} shift\n\t * @returns {module:engine/model/liverange~LiveRange}\n\t */\n\n\t/**\n\t * Fired when `LiveRange` instance boundaries have changed due to changes in the\n\t * {@link module:engine/model/document~Document document}.\n\t *\n\t * @event change:range\n\t * @param {module:engine/model/range~Range} oldRange Range with start and end position equal to start and end position of this live\n\t * range before it got changed.\n\t * @param {Object} data Object with additional information about the change.\n\t * @param {module:engine/model/position~Position|null} data.deletionPosition Source position for remove and merge changes.\n\t * Available if the range was moved to the graveyard root, `null` otherwise.\n\t */\n\n\t/**\n\t * Fired when `LiveRange` instance boundaries have not changed after a change in {@link module:engine/model/document~Document document}\n\t * but the change took place inside the range, effectively changing its content.\n\t *\n\t * @event change:content\n\t * @param {module:engine/model/range~Range} range Range with start and end position equal to start and end position of\n\t * change range.\n\t * @param {Object} data Object with additional information about the change.\n\t * @param {null} data.deletionPosition Due to the nature of this event, this property is always set to `null`. It is passed\n\t * for compatibility with the {@link module:engine/model/liverange~LiveRange#event:change:range} event.\n\t */\n}\n\n// Binds this `LiveRange` to the {@link module:engine/model/document~Document document}\n// that owns this range's {@link module:engine/model/range~Range#root root}.\n//\n// @private\nfunction bindWithDocument() {\n\tthis.listenTo(\n\t\tthis.root.document.model,\n\t\t'applyOperation',\n\t\t( event, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( !operation.isDocumentOperation ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttransform.call( this, operation );\n\t\t},\n\t\t{ priority: 'low' }\n\t);\n}\n\n// Updates this range accordingly to the updates applied to the model. Bases on change events.\n//\n// @private\n// @param {module:engine/model/operation/operation~Operation} operation Executed operation.\nfunction transform( operation ) {\n\t// Transform the range by the operation. Join the result ranges if needed.\n\tconst ranges = this.getTransformedByOperation( operation );\n\tconst result = Range._createFromRanges( ranges );\n\n\tconst boundariesChanged = !result.isEqual( this );\n\tconst contentChanged = doesOperationChangeRangeContent( this, operation );\n\n\tlet deletionPosition = null;\n\n\tif ( boundariesChanged ) {\n\t\t// If range boundaries have changed, fire `change:range` event.\n\t\t//\n\t\tif ( result.root.rootName == '$graveyard' ) {\n\t\t\t// If the range was moved to the graveyard root, set `deletionPosition`.\n\t\t\tif ( operation.type == 'remove' ) {\n\t\t\t\tdeletionPosition = operation.sourcePosition;\n\t\t\t} else {\n\t\t\t\t// Merge operation.\n\t\t\t\tdeletionPosition = operation.deletionPosition;\n\t\t\t}\n\t\t}\n\n\t\tconst oldRange = this.toRange();\n\n\t\tthis.start = result.start;\n\t\tthis.end = result.end;\n\n\t\tthis.fire( 'change:range', oldRange, { deletionPosition } );\n\t} else if ( contentChanged ) {\n\t\t// If range boundaries have not changed, but there was change inside the range, fire `change:content` event.\n\t\tthis.fire( 'change:content', this.toRange(), { deletionPosition } );\n\t}\n}\n\n// Checks whether given operation changes something inside the range (even if it does not change boundaries).\n//\n// @private\n// @param {module:engine/model/range~Range} range Range to check.\n// @param {module:engine/model/operation/operation~Operation} operation Executed operation.\n// @returns {Boolean}\nfunction doesOperationChangeRangeContent( range, operation ) {\n\tswitch ( operation.type ) {\n\t\tcase 'insert':\n\t\t\treturn range.containsPosition( operation.position );\n\t\tcase 'move':\n\t\tcase 'remove':\n\t\tcase 'reinsert':\n\t\tcase 'merge':\n\t\t\treturn range.containsPosition( operation.sourcePosition ) ||\n\t\t\t\trange.start.isEqual( operation.sourcePosition ) ||\n\t\t\t\trange.containsPosition( operation.targetPosition );\n\t\tcase 'split':\n\t\t\treturn range.containsPosition( operation.splitPosition ) || range.containsPosition( operation.insertionPosition );\n\t}\n\n\treturn false;\n}\n\nmix( LiveRange, EmitterMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/documentselection\n */\n\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\n\nimport Selection from './selection';\nimport LiveRange from './liverange';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport toMap from '@ckeditor/ckeditor5-utils/src/tomap';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport uid from '@ckeditor/ckeditor5-utils/src/uid';\n\nconst storePrefix = 'selection:';\n\n/**\n * `DocumentSelection` is a special selection which is used as the\n * {@link module:engine/model/document~Document#selection document's selection}.\n * There can be only one instance of `DocumentSelection` per document.\n *\n * Document selection can only be changed by using the {@link module:engine/model/writer~Writer} instance\n * inside the {@link module:engine/model/model~Model#change `change()`} block, as it provides a secure way to modify model.\n *\n * `DocumentSelection` is automatically updated upon changes in the {@link module:engine/model/document~Document document}\n * to always contain valid ranges. Its attributes are inherited from the text unless set explicitly.\n *\n * Differences between {@link module:engine/model/selection~Selection} and `DocumentSelection` are:\n * * there is always a range in `DocumentSelection` - even if no ranges were added there is a \"default range\"\n * present in the selection,\n * * ranges added to this selection updates automatically when the document changes,\n * * attributes of `DocumentSelection` are updated automatically according to selection ranges.\n *\n * Since `DocumentSelection` uses {@link module:engine/model/liverange~LiveRange live ranges}\n * and is updated when {@link module:engine/model/document~Document document}\n * changes, it cannot be set on {@link module:engine/model/node~Node nodes}\n * that are inside {@link module:engine/model/documentfragment~DocumentFragment document fragment}.\n * If you need to represent a selection in document fragment,\n * use {@link module:engine/model/selection~Selection Selection class} instead.\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class DocumentSelection {\n\t/**\n\t * Creates an empty live selection for given {@link module:engine/model/document~Document}.\n\t *\n\t * @param {module:engine/model/document~Document} doc Document which owns this selection.\n\t */\n\tconstructor( doc ) {\n\t\t/**\n\t\t * Selection used internally by that class (`DocumentSelection` is a proxy to that selection).\n\t\t *\n\t\t * @protected\n\t\t */\n\t\tthis._selection = new LiveSelection( doc );\n\n\t\tthis._selection.delegate( 'change:range' ).to( this );\n\t\tthis._selection.delegate( 'change:attribute' ).to( this );\n\t}\n\n\t/**\n\t * Returns whether the selection is collapsed. Selection is collapsed when there is exactly one range which is\n\t * collapsed.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isCollapsed() {\n\t\treturn this._selection.isCollapsed;\n\t}\n\n\t/**\n\t * Selection anchor. Anchor may be described as a position where the most recent part of the selection starts.\n\t * Together with {@link #focus} they define the direction of selection, which is important\n\t * when expanding/shrinking selection. Anchor is always {@link module:engine/model/range~Range#start start} or\n\t * {@link module:engine/model/range~Range#end end} position of the most recently added range.\n\t *\n\t * Is set to `null` if there are no ranges in selection.\n\t *\n\t * @see #focus\n\t * @readonly\n\t * @type {module:engine/model/position~Position|null}\n\t */\n\tget anchor() {\n\t\treturn this._selection.anchor;\n\t}\n\n\t/**\n\t * Selection focus. Focus is a position where the selection ends.\n\t *\n\t * Is set to `null` if there are no ranges in selection.\n\t *\n\t * @see #anchor\n\t * @readonly\n\t * @type {module:engine/model/position~Position|null}\n\t */\n\tget focus() {\n\t\treturn this._selection.focus;\n\t}\n\n\t/**\n\t * Returns number of ranges in selection.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget rangeCount() {\n\t\treturn this._selection.rangeCount;\n\t}\n\n\t/**\n\t * Describes whether `Documentselection` has own range(s) set, or if it is defaulted to\n\t * {@link module:engine/model/document~Document#_getDefaultRange document's default range}.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget hasOwnRange() {\n\t\treturn this._selection.hasOwnRange;\n\t}\n\n\t/**\n\t * Specifies whether the {@link #focus}\n\t * precedes {@link #anchor}.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isBackward() {\n\t\treturn this._selection.isBackward;\n\t}\n\n\t/**\n\t * Describes whether the gravity is overridden (using {@link module:engine/model/writer~Writer#overrideSelectionGravity}) or not.\n\t *\n\t * Note that the gravity remains overridden as long as will not be restored the same number of times as it was overridden.\n\t *\n\t * @readonly\n\t * @returns {Boolean}\n\t */\n\tget isGravityOverridden() {\n\t\treturn this._selection.isGravityOverridden;\n\t}\n\n\t/**\n\t * A collection of selection markers.\n\t * Marker is a selection marker when selection range is inside the marker range.\n\t *\n\t * @readonly\n\t * @type {module:utils/collection~Collection.<module:engine/model/markercollection~Marker>}\n\t */\n\tget markers() {\n\t\treturn this._selection.markers;\n\t}\n\n\t/**\n\t * Used for the compatibility with the {@link module:engine/model/selection~Selection#isEqual} method.\n\t *\n\t * @protected\n\t */\n\tget _ranges() {\n\t\treturn this._selection._ranges;\n\t}\n\n\t/**\n\t * Returns an iterable that iterates over copies of selection ranges.\n\t *\n\t * @returns {Iterable.<module:engine/model/range~Range>}\n\t */\n\tgetRanges() {\n\t\treturn this._selection.getRanges();\n\t}\n\n\t/**\n\t * Returns the first position in the selection.\n\t * First position is the position that {@link module:engine/model/position~Position#isBefore is before}\n\t * any other position in the selection.\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/position~Position|null}\n\t */\n\tgetFirstPosition() {\n\t\treturn this._selection.getFirstPosition();\n\t}\n\n\t/**\n\t * Returns the last position in the selection.\n\t * Last position is the position that {@link module:engine/model/position~Position#isAfter is after}\n\t * any other position in the selection.\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/position~Position|null}\n\t */\n\tgetLastPosition() {\n\t\treturn this._selection.getLastPosition();\n\t}\n\n\t/**\n\t * Returns a copy of the first range in the selection.\n\t * First range is the one which {@link module:engine/model/range~Range#start start} position\n\t * {@link module:engine/model/position~Position#isBefore is before} start position of all other ranges\n\t * (not to confuse with the first range added to the selection).\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/range~Range|null}\n\t */\n\tgetFirstRange() {\n\t\treturn this._selection.getFirstRange();\n\t}\n\n\t/**\n\t * Returns a copy of the last range in the selection.\n\t * Last range is the one which {@link module:engine/model/range~Range#end end} position\n\t * {@link module:engine/model/position~Position#isAfter is after} end position of all other ranges (not to confuse with the range most\n\t * recently added to the selection).\n\t *\n\t * Returns `null` if there are no ranges in selection.\n\t *\n\t * @returns {module:engine/model/range~Range|null}\n\t */\n\tgetLastRange() {\n\t\treturn this._selection.getLastRange();\n\t}\n\n\t/**\n\t * Gets elements of type {@link module:engine/model/schema~Schema#isBlock \"block\"} touched by the selection.\n\t *\n\t * This method's result can be used for example to apply block styling to all blocks covered by this selection.\n\t *\n\t * **Note:** `getSelectedBlocks()` returns blocks that are nested in other non-block elements\n\t * but will not return blocks nested in other blocks.\n\t *\n\t * In this case the function will return exactly all 3 paragraphs (note: `<blockQuote>` is not a block itself):\n\t *\n\t *\t\t<paragraph>[a</paragraph>\n\t *\t\t<blockQuote>\n\t *\t\t\t<paragraph>b</paragraph>\n\t *\t\t</blockQuote>\n\t *\t\t<paragraph>c]d</paragraph>\n\t *\n\t * In this case the paragraph will also be returned, despite the collapsed selection:\n\t *\n\t *\t\t<paragraph>[]a</paragraph>\n\t *\n\t * In such a scenario, however, only blocks A, B & E will be returned as blocks C & D are nested in block B:\n\t *\n\t *\t\t[<blockA></blockA>\n\t *\t\t<blockB>\n\t *\t\t\t<blockC></blockC>\n\t *\t\t\t<blockD></blockD>\n\t *\t\t</blockB>\n\t *\t\t<blockE></blockE>]\n\t *\n\t * If the selection is inside a block all the inner blocks (A & B) are returned:\n\t *\n\t * \t\t<block>\n\t *\t\t\t<blockA>[a</blockA>\n\t * \t\t\t<blockB>b]</blockB>\n\t * \t\t</block>\n\t *\n\t * **Special case**: If a selection ends at the beginning of a block, that block is not returned as from user perspective\n\t * this block wasn't selected. See [#984](https://github.com/ckeditor/ckeditor5-engine/issues/984) for more details.\n\t *\n\t *\t\t<paragraph>[a</paragraph>\n\t *\t\t<paragraph>b</paragraph>\n\t *\t\t<paragraph>]c</paragraph> // this block will not be returned\n\t *\n\t * @returns {Iterable.<module:engine/model/element~Element>}\n\t */\n\tgetSelectedBlocks() {\n\t\treturn this._selection.getSelectedBlocks();\n\t}\n\n\t/**\n\t * Returns the selected element. {@link module:engine/model/element~Element Element} is considered as selected if there is only\n\t * one range in the selection, and that range contains exactly one element.\n\t * Returns `null` if there is no selected element.\n\t *\n\t * @returns {module:engine/model/element~Element|null}\n\t */\n\tgetSelectedElement() {\n\t\treturn this._selection.getSelectedElement();\n\t}\n\n\t/**\n\t * Checks whether the selection contains the entire content of the given element. This means that selection must start\n\t * at a position {@link module:engine/model/position~Position#isTouching touching} the element's start and ends at position\n\t * touching the element's end.\n\t *\n\t * By default, this method will check whether the entire content of the selection's current root is selected.\n\t * Useful to check if e.g. the user has just pressed <kbd>Ctrl</kbd> + <kbd>A</kbd>.\n\t *\n\t * @param {module:engine/model/element~Element} [element=this.anchor.root]\n\t * @returns {Boolean}\n\t */\n\tcontainsEntireContent( element ) {\n\t\treturn this._selection.containsEntireContent( element );\n\t}\n\n\t/**\n\t * Unbinds all events previously bound by document selection.\n\t */\n\tdestroy() {\n\t\tthis._selection.destroy();\n\t}\n\n\t/**\n\t * Returns iterable that iterates over this selection's attribute keys.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\tgetAttributeKeys() {\n\t\treturn this._selection.getAttributeKeys();\n\t}\n\n\t/**\n\t * Returns iterable that iterates over this selection's attributes.\n\t *\n\t * Attributes are returned as arrays containing two items. First one is attribute key and second is attribute value.\n\t * This format is accepted by native `Map` object and also can be passed in `Node` constructor.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\tgetAttributes() {\n\t\treturn this._selection.getAttributes();\n\t}\n\n\t/**\n\t * Gets an attribute value for given key or `undefined` if that attribute is not set on the selection.\n\t *\n\t * @param {String} key Key of attribute to look for.\n\t * @returns {*} Attribute value or `undefined`.\n\t */\n\tgetAttribute( key ) {\n\t\treturn this._selection.getAttribute( key );\n\t}\n\n\t/**\n\t * Checks if the selection has an attribute for given key.\n\t *\n\t * @param {String} key Key of attribute to check.\n\t * @returns {Boolean} `true` if attribute with given key is set on selection, `false` otherwise.\n\t */\n\thasAttribute( key ) {\n\t\treturn this._selection.hasAttribute( key );\n\t}\n\n\t/**\n\t * Refreshes selection attributes and markers according to the current position in the model.\n\t */\n\trefresh() {\n\t\tthis._selection._updateMarkers();\n\t\tthis._selection._updateAttributes( false );\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tselection.is( 'selection' ); // -> true\n\t *\t\tselection.is( 'documentSelection' ); // -> true\n\t *\t\tselection.is( 'model:selection' ); // -> true\n\t *\t\tselection.is( 'model:documentSelection' ); // -> true\n\t *\n\t *\t\tselection.is( 'view:selection' ); // -> false\n\t *\t\tselection.is( 'element' ); // -> false\n\t *\t\tselection.is( 'node' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'selection' ||\n\t\t\ttype == 'model:selection' ||\n\t\t\ttype == 'documentSelection' ||\n\t\t\ttype == 'model:documentSelection';\n\t}\n\n\t/**\n\t * Moves {@link module:engine/model/documentselection~DocumentSelection#focus} to the specified location.\n\t * Should be used only within the {@link module:engine/model/writer~Writer#setSelectionFocus} method.\n\t *\n\t * The location can be specified in the same form as\n\t * {@link module:engine/model/writer~Writer#createPositionAt writer.createPositionAt()} parameters.\n\t *\n\t * @see module:engine/model/writer~Writer#setSelectionFocus\n\t * @protected\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\t_setFocus( itemOrPosition, offset ) {\n\t\tthis._selection.setFocus( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Sets this selection's ranges and direction to the specified location based on the given\n\t * {@link module:engine/model/selection~Selectable selectable}.\n\t * Should be used only within the {@link module:engine/model/writer~Writer#setSelection} method.\n\t *\n\t * @see module:engine/model/writer~Writer#setSelection\n\t * @protected\n\t * @param {module:engine/model/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t */\n\t_setTo( selectable, placeOrOffset, options ) {\n\t\tthis._selection.setTo( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Sets attribute on the selection. If attribute with the same key already is set, it's value is overwritten.\n\t * Should be used only within the {@link module:engine/model/writer~Writer#setSelectionAttribute} method.\n\t *\n\t * @see module:engine/model/writer~Writer#setSelectionAttribute\n\t * @protected\n\t * @param {String} key Key of the attribute to set.\n\t * @param {*} value Attribute value.\n\t */\n\t_setAttribute( key, value ) {\n\t\tthis._selection.setAttribute( key, value );\n\t}\n\n\t/**\n\t * Removes an attribute with given key from the selection.\n\t * If the given attribute was set on the selection, fires the {@link module:engine/model/selection~Selection#event:change:range}\n\t * event with removed attribute key.\n\t * Should be used only within the {@link module:engine/model/writer~Writer#removeSelectionAttribute} method.\n\t *\n\t * @see module:engine/model/writer~Writer#removeSelectionAttribute\n\t * @protected\n\t * @param {String} key Key of the attribute to remove.\n\t */\n\t_removeAttribute( key ) {\n\t\tthis._selection.removeAttribute( key );\n\t}\n\n\t/**\n\t * Returns an iterable that iterates through all selection attributes stored in current selection's parent.\n\t *\n\t * @protected\n\t * @returns {Iterable.<*>}\n\t */\n\t_getStoredAttributes() {\n\t\treturn this._selection._getStoredAttributes();\n\t}\n\n\t/**\n\t * Temporarily changes the gravity of the selection from the left to the right.\n\t *\n\t * The gravity defines from which direction the selection inherits its attributes. If it's the default left\n\t * gravity, the selection (after being moved by the the user) inherits attributes from its left hand side.\n\t * This method allows to temporarily override this behavior by forcing the gravity to the right.\n\t *\n\t * It returns an unique identifier which is required to restore the gravity. It guarantees the symmetry\n\t * of the process.\n\t *\n\t * @see module:engine/model/writer~Writer#overrideSelectionGravity\n\t * @protected\n\t * @returns {String} The unique id which allows restoring the gravity.\n\t */\n\t_overrideGravity() {\n\t\treturn this._selection.overrideGravity();\n\t}\n\n\t/**\n\t * Restores the {@link ~DocumentSelection#_overrideGravity overridden gravity}.\n\t *\n\t * Restoring the gravity is only possible using the unique identifier returned by\n\t * {@link ~DocumentSelection#_overrideGravity}. Note that the gravity remains overridden as long as won't be restored\n\t * the same number of times it was overridden.\n\t *\n\t * @see module:engine/model/writer~Writer#restoreSelectionGravity\n\t * @protected\n\t * @param {String} uid The unique id returned by {@link #_overrideGravity}.\n\t */\n\t_restoreGravity( uid ) {\n\t\tthis._selection.restoreGravity( uid );\n\t}\n\n\t/**\n\t * Generates and returns an attribute key for selection attributes store, basing on original attribute key.\n\t *\n\t * @protected\n\t * @param {String} key Attribute key to convert.\n\t * @returns {String} Converted attribute key, applicable for selection store.\n\t */\n\tstatic _getStoreAttributeKey( key ) {\n\t\treturn storePrefix + key;\n\t}\n\n\t/**\n\t * Checks whether the given attribute key is an attribute stored on an element.\n\t *\n\t * @protected\n\t * @param {String} key\n\t * @returns {Boolean}\n\t */\n\tstatic _isStoreAttributeKey( key ) {\n\t\treturn key.startsWith( storePrefix );\n\t}\n}\n\nmix( DocumentSelection, EmitterMixin );\n\n/**\n * Fired when selection range(s) changed.\n *\n * @event change:range\n * @param {Boolean} directChange In case of {@link module:engine/model/selection~Selection} class it is always set\n * to `true` which indicates that the selection change was caused by a direct use of selection's API.\n * The {@link module:engine/model/documentselection~DocumentSelection}, however, may change because its position\n * was directly changed through the {@link module:engine/model/writer~Writer writer} or because its position was\n * changed because the structure of the model has been changed (which means an indirect change).\n * The indirect change does not occur in case of normal (detached) selections because they are \"static\" (as \"not live\")\n * which mean that they are not updated once the document changes.\n */\n\n/**\n * Fired when selection attribute changed.\n *\n * @event change:attribute\n * @param {Boolean} directChange In case of {@link module:engine/model/selection~Selection} class it is always set\n * to `true` which indicates that the selection change was caused by a direct use of selection's API.\n * The {@link module:engine/model/documentselection~DocumentSelection}, however, may change because its attributes\n * were directly changed through the {@link module:engine/model/writer~Writer writer} or because its position was\n * changed in the model and its attributes were refreshed (which means an indirect change).\n * The indirect change does not occur in case of normal (detached) selections because they are \"static\" (as \"not live\")\n * which mean that they are not updated once the document changes.\n * @param {Array.<String>} attributeKeys Array containing keys of attributes that changed.\n */\n\n// `LiveSelection` is used internally by {@link module:engine/model/documentselection~DocumentSelection} and shouldn't be used directly.\n//\n// LiveSelection` is automatically updated upon changes in the {@link module:engine/model/document~Document document}\n// to always contain valid ranges. Its attributes are inherited from the text unless set explicitly.\n//\n// Differences between {@link module:engine/model/selection~Selection} and `LiveSelection` are:\n// * there is always a range in `LiveSelection` - even if no ranges were added there is a \"default range\"\n// present in the selection,\n// * ranges added to this selection updates automatically when the document changes,\n// * attributes of `LiveSelection` are updated automatically according to selection ranges.\n//\n// @extends module:engine/model/selection~Selection\n//\n\nclass LiveSelection extends Selection {\n\t// Creates an empty live selection for given {@link module:engine/model/document~Document}.\n\t// @param {module:engine/model/document~Document} doc Document which owns this selection.\n\tconstructor( doc ) {\n\t\tsuper();\n\n\t\t// List of selection markers.\n\t\t// Marker is a selection marker when selection range is inside the marker range.\n\t\t//\n\t\t// @type {module:utils/collection~Collection}\n\t\tthis.markers = new Collection( { idProperty: 'name' } );\n\n\t\t// Document which owns this selection.\n\t\t//\n\t\t// @protected\n\t\t// @member {module:engine/model/model~Model}\n\t\tthis._model = doc.model;\n\n\t\t// Document which owns this selection.\n\t\t//\n\t\t// @protected\n\t\t// @member {module:engine/model/document~Document}\n\t\tthis._document = doc;\n\n\t\t// Keeps mapping of attribute name to priority with which the attribute got modified (added/changed/removed)\n\t\t// last time. Possible values of priority are: `'low'` and `'normal'`.\n\t\t//\n\t\t// Priorities are used by internal `LiveSelection` mechanisms. All attributes set using `LiveSelection`\n\t\t// attributes API are set with `'normal'` priority.\n\t\t//\n\t\t// @private\n\t\t// @member {Map} module:engine/model/liveselection~LiveSelection#_attributePriority\n\t\tthis._attributePriority = new Map();\n\n\t\t// Contains data required to fix ranges which have been moved to the graveyard.\n\t\t// @private\n\t\t// @member {Array} module:engine/model/liveselection~LiveSelection#_fixGraveyardRangesData\n\t\tthis._fixGraveyardRangesData = [];\n\n\t\t// Flag that informs whether the selection ranges have changed. It is changed on true when `LiveRange#change:range` event is fired.\n\t\t// @private\n\t\t// @member {Array} module:engine/model/liveselection~LiveSelection#_hasChangedRange\n\t\tthis._hasChangedRange = false;\n\n\t\t// Each overriding gravity adds an UID to the set and each removal removes it.\n\t\t// Gravity is overridden when there's at least one UID in the set.\n\t\t// Gravity is restored when the set is empty.\n\t\t// This is to prevent conflicts when gravity is overridden by more than one feature at the same time.\n\t\t// @private\n\t\t// @type {Set}\n\t\tthis._overriddenGravityRegister = new Set();\n\n\t\t// Ensure selection is correct after each operation.\n\t\tthis.listenTo( this._model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( !operation.isDocumentOperation || operation.type == 'marker' || operation.type == 'rename' || operation.type == 'noop' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twhile ( this._fixGraveyardRangesData.length ) {\n\t\t\t\tconst { liveRange, sourcePosition } = this._fixGraveyardRangesData.shift();\n\n\t\t\t\tthis._fixGraveyardSelection( liveRange, sourcePosition );\n\t\t\t}\n\n\t\t\tif ( this._hasChangedRange ) {\n\t\t\t\tthis._hasChangedRange = false;\n\t\t\t\tthis.fire( 'change:range', { directChange: false } );\n\t\t\t}\n\t\t}, { priority: 'lowest' } );\n\n\t\t// Ensure selection is correct and up to date after each range change.\n\t\tthis.on( 'change:range', () => {\n\t\t\tfor ( const range of this.getRanges() ) {\n\t\t\t\tif ( !this._document._validateSelectionRange( range ) ) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Range from {@link module:engine/model/documentselection~DocumentSelection document selection}\n\t\t\t\t\t * starts or ends at incorrect position.\n\t\t\t\t\t *\n\t\t\t\t\t * @error document-selection-wrong-position\n\t\t\t\t\t * @param {module:engine/model/range~Range} range\n\t\t\t\t\t */\n\t\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t\t'document-selection-wrong-position: Range from document selection starts or ends at incorrect position.',\n\t\t\t\t\t\tthis,\n\t\t\t\t\t\t{ range }\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t// Update markers data stored by the selection after each marker change.\n\t\tthis.listenTo( this._model.markers, 'update', () => this._updateMarkers() );\n\n\t\t// Ensure selection is up to date after each change block.\n\t\tthis.listenTo( this._document, 'change', ( evt, batch ) => {\n\t\t\tclearAttributesStoredInElement( this._model, batch );\n\t\t} );\n\t}\n\n\tget isCollapsed() {\n\t\tconst length = this._ranges.length;\n\n\t\treturn length === 0 ? this._document._getDefaultRange().isCollapsed : super.isCollapsed;\n\t}\n\n\tget anchor() {\n\t\treturn super.anchor || this._document._getDefaultRange().start;\n\t}\n\n\tget focus() {\n\t\treturn super.focus || this._document._getDefaultRange().end;\n\t}\n\n\tget rangeCount() {\n\t\treturn this._ranges.length ? this._ranges.length : 1;\n\t}\n\n\t// Describes whether `LiveSelection` has own range(s) set, or if it is defaulted to\n\t// {@link module:engine/model/document~Document#_getDefaultRange document's default range}.\n\t//\n\t// @readonly\n\t// @type {Boolean}\n\tget hasOwnRange() {\n\t\treturn this._ranges.length > 0;\n\t}\n\n\t// When set to `true` then selection attributes on node before the caret won't be taken\n\t// into consideration while updating selection attributes.\n\t//\n\t// @protected\n\t// @type {Boolean}\n\tget isGravityOverridden() {\n\t\treturn !!this._overriddenGravityRegister.size;\n\t}\n\n\t// Unbinds all events previously bound by live selection.\n\tdestroy() {\n\t\tfor ( let i = 0; i < this._ranges.length; i++ ) {\n\t\t\tthis._ranges[ i ].detach();\n\t\t}\n\n\t\tthis.stopListening();\n\t}\n\n\t* getRanges() {\n\t\tif ( this._ranges.length ) {\n\t\t\tyield* super.getRanges();\n\t\t} else {\n\t\t\tyield this._document._getDefaultRange();\n\t\t}\n\t}\n\n\tgetFirstRange() {\n\t\treturn super.getFirstRange() || this._document._getDefaultRange();\n\t}\n\n\tgetLastRange() {\n\t\treturn super.getLastRange() || this._document._getDefaultRange();\n\t}\n\n\tsetTo( selectable, optionsOrPlaceOrOffset, options ) {\n\t\tsuper.setTo( selectable, optionsOrPlaceOrOffset, options );\n\t\tthis._updateAttributes( true );\n\t}\n\n\tsetFocus( itemOrPosition, offset ) {\n\t\tsuper.setFocus( itemOrPosition, offset );\n\t\tthis._updateAttributes( true );\n\t}\n\n\tsetAttribute( key, value ) {\n\t\tif ( this._setAttribute( key, value ) ) {\n\t\t\t// Fire event with exact data.\n\t\t\tconst attributeKeys = [ key ];\n\t\t\tthis.fire( 'change:attribute', { attributeKeys, directChange: true } );\n\t\t}\n\t}\n\n\tremoveAttribute( key ) {\n\t\tif ( this._removeAttribute( key ) ) {\n\t\t\t// Fire event with exact data.\n\t\t\tconst attributeKeys = [ key ];\n\t\t\tthis.fire( 'change:attribute', { attributeKeys, directChange: true } );\n\t\t}\n\t}\n\n\toverrideGravity() {\n\t\tconst overrideUid = uid();\n\n\t\t// Remember that another overriding has been requested. It will need to be removed\n\t\t// before the gravity is to be restored.\n\t\tthis._overriddenGravityRegister.add( overrideUid );\n\n\t\tif ( this._overriddenGravityRegister.size === 1 ) {\n\t\t\tthis._updateAttributes( true );\n\t\t}\n\n\t\treturn overrideUid;\n\t}\n\n\trestoreGravity( uid ) {\n\t\tif ( !this._overriddenGravityRegister.has( uid ) ) {\n\t\t\t/**\n\t\t\t * Restoring gravity for an unknown UID is not possible. Make sure you are using a correct\n\t\t\t * UID obtained from the {@link module:engine/model/writer~Writer#overrideSelectionGravity} to restore.\n\t\t\t *\n\t\t\t * @error document-selection-gravity-wrong-restore\n\t\t\t * @param {String} uid The unique identifier returned by\n\t\t\t * {@link module:engine/model/documentselection~DocumentSelection#_overrideGravity}.\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'document-selection-gravity-wrong-restore: Attempting to restore the selection gravity for an unknown UID.',\n\t\t\t\tthis,\n\t\t\t\t{ uid }\n\t\t\t);\n\t\t}\n\n\t\tthis._overriddenGravityRegister.delete( uid );\n\n\t\t// Restore gravity only when all overriding have been restored.\n\t\tif ( !this.isGravityOverridden ) {\n\t\t\tthis._updateAttributes( true );\n\t\t}\n\t}\n\n\t_popRange() {\n\t\tthis._ranges.pop().detach();\n\t}\n\n\t_pushRange( range ) {\n\t\tconst liveRange = this._prepareRange( range );\n\n\t\t// `undefined` is returned when given `range` is in graveyard root.\n\t\tif ( liveRange ) {\n\t\t\tthis._ranges.push( liveRange );\n\t\t}\n\t}\n\n\t// Prepares given range to be added to selection. Checks if it is correct,\n\t// converts it to {@link module:engine/model/liverange~LiveRange LiveRange}\n\t// and sets listeners listening to the range's change event.\n\t//\n\t// @private\n\t// @param {module:engine/model/range~Range} range\n\t_prepareRange( range ) {\n\t\tthis._checkRange( range );\n\n\t\tif ( range.root == this._document.graveyard ) {\n\t\t\t// @if CK_DEBUG // console.warn( 'Trying to add a Range that is in the graveyard root. Range rejected.' );\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst liveRange = LiveRange.fromRange( range );\n\n\t\tliveRange.on( 'change:range', ( evt, oldRange, data ) => {\n\t\t\tthis._hasChangedRange = true;\n\n\t\t\t// If `LiveRange` is in whole moved to the graveyard, save necessary data. It will be fixed on `Model#applyOperation` event.\n\t\t\tif ( liveRange.root == this._document.graveyard ) {\n\t\t\t\tthis._fixGraveyardRangesData.push( {\n\t\t\t\t\tliveRange,\n\t\t\t\t\tsourcePosition: data.deletionPosition\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\treturn liveRange;\n\t}\n\n\t_updateMarkers() {\n\t\tconst markers = [];\n\n\t\tfor ( const marker of this._model.markers ) {\n\t\t\tconst markerRange = marker.getRange();\n\n\t\t\tfor ( const selectionRange of this.getRanges() ) {\n\t\t\t\tif ( markerRange.containsRange( selectionRange, !selectionRange.isCollapsed ) ) {\n\t\t\t\t\tmarkers.push( marker );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor ( const marker of markers ) {\n\t\t\tif ( !this.markers.has( marker ) ) {\n\t\t\t\tthis.markers.add( marker );\n\t\t\t}\n\t\t}\n\n\t\tfor ( const marker of Array.from( this.markers ) ) {\n\t\t\tif ( !markers.includes( marker ) ) {\n\t\t\t\tthis.markers.remove( marker );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Updates this selection attributes according to its ranges and the {@link module:engine/model/document~Document model document}.\n\t//\n\t// @protected\n\t// @param {Boolean} clearAll\n\t// @fires change:attribute\n\t_updateAttributes( clearAll ) {\n\t\tconst newAttributes = toMap( this._getSurroundingAttributes() );\n\t\tconst oldAttributes = toMap( this.getAttributes() );\n\n\t\tif ( clearAll ) {\n\t\t\t// If `clearAll` remove all attributes and reset priorities.\n\t\t\tthis._attributePriority = new Map();\n\t\t\tthis._attrs = new Map();\n\t\t} else {\n\t\t\t// If not, remove only attributes added with `low` priority.\n\t\t\tfor ( const [ key, priority ] of this._attributePriority ) {\n\t\t\t\tif ( priority == 'low' ) {\n\t\t\t\t\tthis._attrs.delete( key );\n\t\t\t\t\tthis._attributePriority.delete( key );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._setAttributesTo( newAttributes );\n\n\t\t// Let's evaluate which attributes really changed.\n\t\tconst changed = [];\n\n\t\t// First, loop through all attributes that are set on selection right now.\n\t\t// Check which of them are different than old attributes.\n\t\tfor ( const [ newKey, newValue ] of this.getAttributes() ) {\n\t\t\tif ( !oldAttributes.has( newKey ) || oldAttributes.get( newKey ) !== newValue ) {\n\t\t\t\tchanged.push( newKey );\n\t\t\t}\n\t\t}\n\n\t\t// Then, check which of old attributes got removed.\n\t\tfor ( const [ oldKey ] of oldAttributes ) {\n\t\t\tif ( !this.hasAttribute( oldKey ) ) {\n\t\t\t\tchanged.push( oldKey );\n\t\t\t}\n\t\t}\n\n\t\t// Fire event with exact data (fire only if anything changed).\n\t\tif ( changed.length > 0 ) {\n\t\t\tthis.fire( 'change:attribute', { attributeKeys: changed, directChange: false } );\n\t\t}\n\t}\n\n\t// Internal method for setting `LiveSelection` attribute. Supports attribute priorities (through `directChange`\n\t// parameter).\n\t//\n\t// @private\n\t// @param {String} key Attribute key.\n\t// @param {*} value Attribute value.\n\t// @param {Boolean} [directChange=true] `true` if the change is caused by `Selection` API, `false` if change\n\t// is caused by `Batch` API.\n\t// @returns {Boolean} Whether value has changed.\n\t_setAttribute( key, value, directChange = true ) {\n\t\tconst priority = directChange ? 'normal' : 'low';\n\n\t\tif ( priority == 'low' && this._attributePriority.get( key ) == 'normal' ) {\n\t\t\t// Priority too low.\n\t\t\treturn false;\n\t\t}\n\n\t\tconst oldValue = super.getAttribute( key );\n\n\t\t// Don't do anything if value has not changed.\n\t\tif ( oldValue === value ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._attrs.set( key, value );\n\n\t\t// Update priorities map.\n\t\tthis._attributePriority.set( key, priority );\n\n\t\treturn true;\n\t}\n\n\t// Internal method for removing `LiveSelection` attribute. Supports attribute priorities (through `directChange`\n\t// parameter).\n\t//\n\t// NOTE: Even if attribute is not present in the selection but is provided to this method, it's priority will\n\t// be changed according to `directChange` parameter.\n\t//\n\t// @private\n\t// @param {String} key Attribute key.\n\t// @param {Boolean} [directChange=true] `true` if the change is caused by `Selection` API, `false` if change\n\t// is caused by `Batch` API.\n\t// @returns {Boolean} Whether attribute was removed. May not be true if such attributes didn't exist or the\n\t// existing attribute had higher priority.\n\t_removeAttribute( key, directChange = true ) {\n\t\tconst priority = directChange ? 'normal' : 'low';\n\n\t\tif ( priority == 'low' && this._attributePriority.get( key ) == 'normal' ) {\n\t\t\t// Priority too low.\n\t\t\treturn false;\n\t\t}\n\n\t\t// Update priorities map.\n\t\tthis._attributePriority.set( key, priority );\n\n\t\t// Don't do anything if value has not changed.\n\t\tif ( !super.hasAttribute( key ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._attrs.delete( key );\n\n\t\treturn true;\n\t}\n\n\t// Internal method for setting multiple `LiveSelection` attributes. Supports attribute priorities (through\n\t// `directChange` parameter).\n\t//\n\t// @private\n\t// @param {Map.<String,*>} attrs Iterable object containing attributes to be set.\n\t// @returns {Set.<String>} Changed attribute keys.\n\t_setAttributesTo( attrs ) {\n\t\tconst changed = new Set();\n\n\t\tfor ( const [ oldKey, oldValue ] of this.getAttributes() ) {\n\t\t\t// Do not remove attribute if attribute with same key and value is about to be set.\n\t\t\tif ( attrs.get( oldKey ) === oldValue ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// All rest attributes will be removed so changed attributes won't change .\n\t\t\tthis._removeAttribute( oldKey, false );\n\t\t}\n\n\t\tfor ( const [ key, value ] of attrs ) {\n\t\t\t// Attribute may not be set because of attributes or because same key/value is already added.\n\t\t\tconst gotAdded = this._setAttribute( key, value, false );\n\n\t\t\tif ( gotAdded ) {\n\t\t\t\tchanged.add( key );\n\t\t\t}\n\t\t}\n\n\t\treturn changed;\n\t}\n\n\t// Returns an iterable that iterates through all selection attributes stored in current selection's parent.\n\t//\n\t// @protected\n\t// @returns {Iterable.<*>}\n\t* _getStoredAttributes() {\n\t\tconst selectionParent = this.getFirstPosition().parent;\n\n\t\tif ( this.isCollapsed && selectionParent.isEmpty ) {\n\t\t\tfor ( const key of selectionParent.getAttributeKeys() ) {\n\t\t\t\tif ( key.startsWith( storePrefix ) ) {\n\t\t\t\t\tconst realKey = key.substr( storePrefix.length );\n\n\t\t\t\t\tyield [ realKey, selectionParent.getAttribute( key ) ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Checks model text nodes that are closest to the selection's first position and returns attributes of first\n\t// found element. If there are no text nodes in selection's first position parent, it returns selection\n\t// attributes stored in that parent.\n\t//\n\t// @private\n\t// @returns {Iterable.<*>} Collection of attributes.\n\t_getSurroundingAttributes() {\n\t\tconst position = this.getFirstPosition();\n\t\tconst schema = this._model.schema;\n\n\t\tlet attrs = null;\n\n\t\tif ( !this.isCollapsed ) {\n\t\t\t// 1. If selection is a range...\n\t\t\tconst range = this.getFirstRange();\n\n\t\t\t// ...look for a first character node in that range and take attributes from it.\n\t\t\tfor ( const value of range ) {\n\t\t\t\t// If the item is an object, we don't want to get attributes from its children.\n\t\t\t\tif ( value.item.is( 'element' ) && schema.isObject( value.item ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( value.type == 'text' ) {\n\t\t\t\t\tattrs = value.item.getAttributes();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// 2. If the selection is a caret or the range does not contain a character node...\n\n\t\t\tconst nodeBefore = position.textNode ? position.textNode : position.nodeBefore;\n\t\t\tconst nodeAfter = position.textNode ? position.textNode : position.nodeAfter;\n\n\t\t\t// When gravity is overridden then don't take node before into consideration.\n\t\t\tif ( !this.isGravityOverridden ) {\n\t\t\t\t// ...look at the node before caret and take attributes from it if it is a character node.\n\t\t\t\tattrs = getAttrsIfCharacter( nodeBefore );\n\t\t\t}\n\n\t\t\t// 3. If not, look at the node after caret...\n\t\t\tif ( !attrs ) {\n\t\t\t\tattrs = getAttrsIfCharacter( nodeAfter );\n\t\t\t}\n\n\t\t\t// 4. If not, try to find the first character on the left, that is in the same node.\n\t\t\t// When gravity is overridden then don't take node before into consideration.\n\t\t\tif ( !this.isGravityOverridden && !attrs ) {\n\t\t\t\tlet node = nodeBefore;\n\n\t\t\t\twhile ( node && !attrs ) {\n\t\t\t\t\tnode = node.previousSibling;\n\t\t\t\t\tattrs = getAttrsIfCharacter( node );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 5. If not found, try to find the first character on the right, that is in the same node.\n\t\t\tif ( !attrs ) {\n\t\t\t\tlet node = nodeAfter;\n\n\t\t\t\twhile ( node && !attrs ) {\n\t\t\t\t\tnode = node.nextSibling;\n\t\t\t\t\tattrs = getAttrsIfCharacter( node );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 6. If not found, selection should retrieve attributes from parent.\n\t\t\tif ( !attrs ) {\n\t\t\t\tattrs = this._getStoredAttributes();\n\t\t\t}\n\t\t}\n\n\t\treturn attrs;\n\t}\n\n\t// Fixes a selection range after it ends up in graveyard root.\n\t//\n\t// @private\n\t// @param {module:engine/model/liverange~LiveRange} liveRange The range from selection, that ended up in the graveyard root.\n\t// @param {module:engine/model/position~Position} removedRangeStart Start position of a range which was removed.\n\t_fixGraveyardSelection( liveRange, removedRangeStart ) {\n\t\t// The start of the removed range is the closest position to the `liveRange` - the original selection range.\n\t\t// This is a good candidate for a fixed selection range.\n\t\tconst positionCandidate = removedRangeStart.clone();\n\n\t\t// Find a range that is a correct selection range and is closest to the start of removed range.\n\t\tconst selectionRange = this._model.schema.getNearestSelectionRange( positionCandidate );\n\n\t\t// Remove the old selection range before preparing and adding new selection range. This order is important,\n\t\t// because new range, in some cases, may intersect with old range (it depends on `getNearestSelectionRange()` result).\n\t\tconst index = this._ranges.indexOf( liveRange );\n\t\tthis._ranges.splice( index, 1 );\n\t\tliveRange.detach();\n\n\t\t// If nearest valid selection range has been found - add it in the place of old range.\n\t\tif ( selectionRange ) {\n\t\t\t// Check the range, convert it to live range, bind events, etc.\n\t\t\tconst newRange = this._prepareRange( selectionRange );\n\n\t\t\t// Add new range in the place of old range.\n\t\t\tthis._ranges.splice( index, 0, newRange );\n\t\t}\n\t\t// If nearest valid selection range cannot be found - just removing the old range is fine.\n\t}\n}\n\n// Helper function for {@link module:engine/model/liveselection~LiveSelection#_updateAttributes}.\n//\n// It takes model item, checks whether it is a text node (or text proxy) and, if so, returns it's attributes. If not, returns `null`.\n//\n// @param {module:engine/model/item~Item|null} node\n// @returns {Boolean}\nfunction getAttrsIfCharacter( node ) {\n\tif ( node instanceof TextProxy || node instanceof Text ) {\n\t\treturn node.getAttributes();\n\t}\n\n\treturn null;\n}\n\n// Removes selection attributes from element which is not empty anymore.\n//\n// @private\n// @param {module:engine/model/model~Model} model\n// @param {module:engine/model/batch~Batch} batch\nfunction clearAttributesStoredInElement( model, batch ) {\n\tconst differ = model.document.differ;\n\n\tfor ( const entry of differ.getChanges() ) {\n\t\tif ( entry.type != 'insert' ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst changeParent = entry.position.parent;\n\t\tconst isNoLongerEmpty = entry.length === changeParent.maxOffset;\n\n\t\tif ( isNoLongerEmpty ) {\n\t\t\tmodel.enqueueChange( batch, writer => {\n\t\t\t\tconst storedAttributes = Array.from( changeParent.getAttributeKeys() )\n\t\t\t\t\t.filter( key => key.startsWith( storePrefix ) );\n\n\t\t\t\tfor ( const key of storedAttributes ) {\n\t\t\t\t\twriter.removeAttribute( key, changeParent );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/conversion/conversionhelpers\n */\n\n/**\n * Base class for conversion helpers.\n */\nexport default class ConversionHelpers {\n\t/**\n\t * Creates a conversion helpers instance.\n\t *\n\t * @param {Array.<module:engine/conversion/downcastdispatcher~DowncastDispatcher|\n\t * module:engine/conversion/upcastdispatcher~UpcastDispatcher>} dispatchers\n\t */\n\tconstructor( dispatchers ) {\n\t\tthis._dispatchers = dispatchers;\n\t}\n\n\t/**\n\t * Registers a conversion helper.\n\t *\n\t * **Note**: See full usage example in the `{@link module:engine/conversion/conversion~Conversion#for conversion.for()}`\n\t * method description.\n\t *\n\t * @param {Function} conversionHelper The function to be called on event.\n\t * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers|module:engine/conversion/upcasthelpers~UpcastHelpers}\n\t */\n\tadd( conversionHelper ) {\n\t\tfor ( const dispatcher of this._dispatchers ) {\n\t\t\tconversionHelper( dispatcher );\n\t\t}\n\n\t\treturn this;\n\t}\n}\n","import baseClone from './_baseClone.js';\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n CLONE_SYMBOLS_FLAG = 4;\n\n/**\n * This method is like `_.clone` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @returns {*} Returns the deep cloned value.\n * @see _.clone\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var deep = _.cloneDeep(objects);\n * console.log(deep[0] === objects[0]);\n * // => false\n */\nfunction cloneDeep(value) {\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);\n}\n\nexport default cloneDeep;\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Contains downcast (model-to-view) converters for {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}.\n *\n * @module engine/conversion/downcasthelpers\n */\n\nimport ModelRange from '../model/range';\nimport ModelSelection from '../model/selection';\nimport ModelElement from '../model/element';\n\nimport ViewAttributeElement from '../view/attributeelement';\nimport DocumentSelection from '../model/documentselection';\nimport ConversionHelpers from './conversionhelpers';\n\nimport { cloneDeep } from 'lodash-es';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Downcast conversion helper functions.\n *\n * @extends module:engine/conversion/conversionhelpers~ConversionHelpers\n */\nexport default class DowncastHelpers extends ConversionHelpers {\n\t/**\n\t * Model element to view element conversion helper.\n\t *\n\t * This conversion results in creating a view element. For example, model `<paragraph>Foo</paragraph>` becomes `<p>Foo</p>` in the view.\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).elementToElement( {\n\t *\t\t\tmodel: 'paragraph',\n\t *\t\t\tview: 'p'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).elementToElement( {\n\t *\t\t\tmodel: 'paragraph',\n\t *\t\t\tview: 'div',\n\t *\t\t\tconverterPriority: 'high'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).elementToElement( {\n\t *\t\t\tmodel: 'fancyParagraph',\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'p',\n\t *\t\t\t\tclasses: 'fancy'\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).elementToElement( {\n\t *\t\t\tmodel: 'heading',\n\t *\t\t\tview: ( modelElement, viewWriter ) => {\n\t *\t\t\t\treturn viewWriter.createContainerElement( 'h' + modelElement.getAttribute( 'level' ) )\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #elementToElement\n\t * @param {Object} config Conversion configuration.\n\t * @param {String} config.model The name of the model element to convert.\n\t * @param {module:engine/view/elementdefinition~ElementDefinition|Function} config.view A view element definition or a function\n\t * that takes the model element and {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}\n\t * as parameters and returns a view container element.\n\t * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}\n\t */\n\telementToElement( config ) {\n\t\treturn this.add( downcastElementToElement( config ) );\n\t}\n\n\t/**\n\t * Model attribute to view element conversion helper.\n\t *\n\t * This conversion results in wrapping view nodes with a view attribute element. For example, a model text node with\n\t * `\"Foo\"` as data and the `bold` attribute becomes `<strong>Foo</strong>` in the view.\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t *\t\t\tmodel: 'bold',\n\t *\t\t\tview: 'strong'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t *\t\t\tmodel: 'bold',\n\t *\t\t\tview: 'b',\n\t *\t\t\tconverterPriority: 'high'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t *\t\t\tmodel: 'invert',\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'span',\n\t *\t\t\t\tclasses: [ 'font-light', 'bg-dark' ]\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'fontSize',\n\t *\t\t\t\tvalues: [ 'big', 'small' ]\n\t *\t\t\t},\n\t *\t\t\tview: {\n\t *\t\t\t\tbig: {\n\t *\t\t\t\t\tname: 'span',\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'font-size': '1.2em'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t},\n\t *\t\t\t\tsmall: {\n\t *\t\t\t\t\tname: 'span',\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'font-size': '0.8em'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t *\t\t\tmodel: 'bold',\n\t *\t\t\tview: ( modelAttributeValue, viewWriter ) => {\n\t *\t\t\t\treturn viewWriter.createAttributeElement( 'span', {\n\t *\t\t\t\t\tstyle: 'font-weight:' + modelAttributeValue\n\t *\t\t\t\t} );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'color',\n\t *\t\t\t\tname: '$text'\n\t *\t\t\t},\n\t *\t\t\tview: ( modelAttributeValue, viewWriter ) => {\n\t *\t\t\t\treturn viewWriter.createAttributeElement( 'span', {\n\t *\t\t\t\t\tstyle: 'color:' + modelAttributeValue\n\t *\t\t\t\t} );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #attributeToElement\n\t * @param {Object} config Conversion configuration.\n\t * @param {String|Object} config.model The key of the attribute to convert from or a `{ key, values }` object. `values` is an array\n\t * of `String`s with possible values if the model attribute is an enumerable.\n\t * @param {module:engine/view/elementdefinition~ElementDefinition|Function|Object} config.view A view element definition or a function\n\t * that takes the model attribute value and {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}\n\t * as parameters and returns a view attribute element. If `config.model.values` is\n\t * given, `config.view` should be an object assigning values from `config.model.values` to view element definitions or functions.\n\t * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n\t * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}\n\t */\n\tattributeToElement( config ) {\n\t\treturn this.add( downcastAttributeToElement( config ) );\n\t}\n\n\t/**\n\t * Model attribute to view attribute conversion helper.\n\t *\n\t * This conversion results in adding an attribute to a view node, basing on an attribute from a model node. For example,\n\t * `<image src='foo.jpg'></image>` is converted to `<img src='foo.jpg'></img>`.\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToAttribute( {\n\t *\t\t\tmodel: 'source',\n\t *\t\t\tview: 'src'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToAttribute( {\n\t *\t\t\tmodel: 'source',\n\t *\t\t\tview: 'href',\n\t *\t\t\tconverterPriority: 'high'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToAttribute( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tname: 'image',\n\t *\t\t\t\tkey: 'source'\n\t *\t\t\t},\n\t *\t\t\tview: 'src'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToAttribute( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tname: 'styled',\n\t *\t\t\t\tvalues: [ 'dark', 'light' ]\n\t *\t\t\t},\n\t *\t\t\tview: {\n\t *\t\t\t\tdark: {\n\t *\t\t\t\t\tkey: 'class',\n\t *\t\t\t\t\tvalue: [ 'styled', 'styled-dark' ]\n\t *\t\t\t\t},\n\t *\t\t\t\tlight: {\n\t *\t\t\t\t\tkey: 'class',\n\t *\t\t\t\t\tvalue: [ 'styled', 'styled-light' ]\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).attributeToAttribute( {\n\t *\t\t\tmodel: 'styled',\n\t *\t\t\tview: modelAttributeValue => ( { key: 'class', value: 'styled-' + modelAttributeValue } )\n\t *\t\t} );\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #attributeToAttribute\n\t * @param {Object} config Conversion configuration.\n\t * @param {String|Object} config.model The key of the attribute to convert from or a `{ key, values, [ name ] }` object describing\n\t * the attribute key, possible values and, optionally, an element name to convert from.\n\t * @param {String|Object|Function} config.view A view attribute key, or a `{ key, value }` object or a function that takes\n\t * the model attribute value and returns a `{ key, value }` object. If `key` is `'class'`, `value` can be a `String` or an\n\t * array of `String`s. If `key` is `'style'`, `value` is an object with key-value pairs. In other cases, `value` is a `String`.\n\t * If `config.model.values` is set, `config.view` should be an object assigning values from `config.model.values` to\n\t * `{ key, value }` objects or a functions.\n\t * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n\t * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}\n\t */\n\tattributeToAttribute( config ) {\n\t\treturn this.add( downcastAttributeToAttribute( config ) );\n\t}\n\n\t/**\n\t * Model marker to view element conversion helper.\n\t *\n\t * This conversion results in creating a view element on the boundaries of the converted marker. If the converted marker\n\t * is collapsed, only one element is created. For example, model marker set like this: `<paragraph>F[oo b]ar</paragraph>`\n\t * becomes `<p>F<span data-marker=\"search\"></span>oo b<span data-marker=\"search\"></span>ar</p>` in the view.\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).markerToElement( {\n\t *\t\t\tmodel: 'search',\n\t *\t\t\tview: 'marker-search'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).markerToElement( {\n\t *\t\t\tmodel: 'search',\n\t *\t\t\tview: 'search-result',\n\t *\t\t\tconverterPriority: 'high'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).markerToElement( {\n\t *\t\t\tmodel: 'search',\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'span',\n\t *\t\t\t\tattributes: {\n\t *\t\t\t\t\t'data-marker': 'search'\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).markerToElement( {\n\t *\t\t\tmodel: 'search',\n\t *\t\t\tview: ( markerData, viewWriter ) => {\n\t *\t\t\t\treturn viewWriter.createUIElement( 'span', {\n\t *\t\t\t\t\t'data-marker': 'search',\n\t *\t\t\t\t\t'data-start': markerData.isOpening\n\t *\t\t\t\t} );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * If a function is passed as the `config.view` parameter, it will be used to generate both boundary elements. The function\n\t * receives the `data` object as a parameter and should return an instance of the\n\t * {@link module:engine/view/uielement~UIElement view UI element}. The `data` object and\n\t * {@link module:engine/conversion/downcastdispatcher~DowncastConversionApi `conversionApi`} are passed from\n\t * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:addMarker}. Additionally,\n\t * the `data.isOpening` parameter is passed, which is set to `true` for the marker start boundary element, and `false` to\n\t * the marker end boundary element.\n\t *\n\t * This kind of conversion is useful for saving data into the database, so it should be used in the data conversion pipeline.\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #markerToElement\n\t * @param {Object} config Conversion configuration.\n\t * @param {String} config.model The name of the model marker (or model marker group) to convert.\n\t * @param {module:engine/view/elementdefinition~ElementDefinition|Function} config.view A view element definition or a function\n\t * that takes the model marker data as a parameter and returns a view UI element.\n\t * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n\t * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}\n\t */\n\tmarkerToElement( config ) {\n\t\treturn this.add( downcastMarkerToElement( config ) );\n\t}\n\n\t/**\n\t * Model marker to highlight conversion helper.\n\t *\n\t * This conversion results in creating a highlight on view nodes. For this kind of conversion,\n\t * {@link module:engine/conversion/downcasthelpers~HighlightDescriptor} should be provided.\n\t *\n\t * For text nodes, a `<span>` {@link module:engine/view/attributeelement~AttributeElement} is created and it wraps all text nodes\n\t * in the converted marker range. For example, a model marker set like this: `<paragraph>F[oo b]ar</paragraph>` becomes\n\t * `<p>F<span class=\"comment\">oo b</span>ar</p>` in the view.\n\t *\n\t * {@link module:engine/view/containerelement~ContainerElement} may provide a custom way of handling highlight. Most often,\n\t * the element itself is given classes and attributes described in the highlight descriptor (instead of being wrapped in `<span>`).\n\t * For example, a model marker set like this: `[<image src=\"foo.jpg\"></image>]` becomes `<img src=\"foo.jpg\" class=\"comment\"></img>`\n\t * in the view.\n\t *\n\t * For container elements, the conversion is two-step. While the converter processes the highlight descriptor and passes it\n\t * to a container element, it is the container element instance itself that applies values from the highlight descriptor.\n\t * So, in a sense, the converter takes care of stating what should be applied on what, while the element decides how to apply that.\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).markerToHighlight( { model: 'comment', view: { classes: 'comment' } } );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).markerToHighlight( {\n\t *\t\t\tmodel: 'comment',\n\t *\t\t\tview: { classes: 'new-comment' },\n\t *\t\t\tconverterPriority: 'high'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'downcast' ).markerToHighlight( {\n\t *\t\t\tmodel: 'comment',\n\t *\t\t\tview: data => {\n\t *\t\t\t\t// Assuming that the marker name is in a form of comment:commentType.\n\t *\t\t\t\tconst commentType = data.markerName.split( ':' )[ 1 ];\n\t *\n\t *\t\t\t\treturn {\n\t *\t\t\t\t\tclasses: [ 'comment', 'comment-' + commentType ]\n\t *\t\t\t\t};\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * If a function is passed as the `config.view` parameter, it will be used to generate the highlight descriptor. The function\n\t * receives the `data` object as a parameter and should return a\n\t * {@link module:engine/conversion/downcasthelpers~HighlightDescriptor highlight descriptor}.\n\t * The `data` object properties are passed from {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:addMarker}.\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #markerToHighlight\n\t * @param {Object} config Conversion configuration.\n\t * @param {String} config.model The name of the model marker (or model marker group) to convert.\n\t * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} config.view A highlight descriptor\n\t * that will be used for highlighting or a function that takes the model marker data as a parameter and returns a highlight descriptor.\n\t * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n\t * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers}\n\t */\n\tmarkerToHighlight( config ) {\n\t\treturn this.add( downcastMarkerToHighlight( config ) );\n\t}\n}\n\n/**\n * Function factory that creates a default downcast converter for text insertion changes.\n *\n * The converter automatically consumes the corresponding value from the consumables list and stops the event (see\n * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).\n *\n *\t\tmodelDispatcher.on( 'insert:$text', insertText() );\n *\n * @returns {Function} Insert text event converter.\n */\nexport function insertText() {\n\treturn ( evt, data, conversionApi ) => {\n\t\tif ( !conversionApi.consumable.consume( data.item, 'insert' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst viewPosition = conversionApi.mapper.toViewPosition( data.range.start );\n\t\tconst viewText = viewWriter.createText( data.item.data );\n\n\t\tviewWriter.insert( viewPosition, viewText );\n\t};\n}\n\n/**\n * Function factory that creates a default downcast converter for node remove changes.\n *\n *\t\tmodelDispatcher.on( 'remove', remove() );\n *\n * @returns {Function} Remove event converter.\n */\nexport function remove() {\n\treturn ( evt, data, conversionApi ) => {\n\t\t// Find view range start position by mapping model position at which the remove happened.\n\t\tconst viewStart = conversionApi.mapper.toViewPosition( data.position );\n\n\t\tconst modelEnd = data.position.getShiftedBy( data.length );\n\t\tconst viewEnd = conversionApi.mapper.toViewPosition( modelEnd, { isPhantom: true } );\n\n\t\tconst viewRange = conversionApi.writer.createRange( viewStart, viewEnd );\n\n\t\t// Trim the range to remove in case some UI elements are on the view range boundaries.\n\t\tconst removed = conversionApi.writer.remove( viewRange.getTrimmed() );\n\n\t\t// After the range is removed, unbind all view elements from the model.\n\t\t// Range inside view document fragment is used to unbind deeply.\n\t\tfor ( const child of conversionApi.writer.createRangeIn( removed ).getItems() ) {\n\t\t\tconversionApi.mapper.unbindViewElement( child );\n\t\t}\n\t};\n}\n\n/**\n * Creates a `<span>` {@link module:engine/view/attributeelement~AttributeElement view attribute element} from the information\n * provided by the {@link module:engine/conversion/downcasthelpers~HighlightDescriptor highlight descriptor} object. If a priority\n * is not provided in the descriptor, the default priority will be used.\n *\n * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor\n * @returns {module:engine/view/attributeelement~AttributeElement}\n */\nexport function createViewElementFromHighlightDescriptor( descriptor ) {\n\tconst viewElement = new ViewAttributeElement( 'span', descriptor.attributes );\n\n\tif ( descriptor.classes ) {\n\t\tviewElement._addClass( descriptor.classes );\n\t}\n\n\tif ( descriptor.priority ) {\n\t\tviewElement._priority = descriptor.priority;\n\t}\n\n\tviewElement._id = descriptor.id;\n\n\treturn viewElement;\n}\n\n/**\n * Function factory that creates a converter which converts a non-collapsed {@link module:engine/model/selection~Selection model selection}\n * to a {@link module:engine/view/documentselection~DocumentSelection view selection}. The converter consumes appropriate\n * value from the `consumable` object and maps model positions from the selection to view positions.\n *\n *\t\tmodelDispatcher.on( 'selection', convertRangeSelection() );\n *\n * @returns {Function} Selection converter.\n */\nexport function convertRangeSelection() {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst selection = data.selection;\n\n\t\tif ( selection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.consume( selection, 'selection' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewRanges = [];\n\n\t\tfor ( const range of selection.getRanges() ) {\n\t\t\tconst viewRange = conversionApi.mapper.toViewRange( range );\n\t\t\tviewRanges.push( viewRange );\n\t\t}\n\n\t\tconversionApi.writer.setSelection( viewRanges, { backward: selection.isBackward } );\n\t};\n}\n\n/**\n * Function factory that creates a converter which converts a collapsed {@link module:engine/model/selection~Selection model selection} to\n * a {@link module:engine/view/documentselection~DocumentSelection view selection}. The converter consumes appropriate\n * value from the `consumable` object, maps the model selection position to the view position and breaks\n * {@link module:engine/view/attributeelement~AttributeElement attribute elements} at the selection position.\n *\n *\t\tmodelDispatcher.on( 'selection', convertCollapsedSelection() );\n *\n * An example of the view state before and after converting the collapsed selection:\n *\n *\t\t <p><strong>f^oo<strong>bar</p>\n *\t\t-> <p><strong>f</strong>^<strong>oo</strong>bar</p>\n *\n * By breaking attribute elements like `<strong>`, the selection is in a correct element. Then, when the selection attribute is\n * converted, broken attributes might be merged again, or the position where the selection is may be wrapped\n * with different, appropriate attribute elements.\n *\n * See also {@link module:engine/conversion/downcasthelpers~clearAttributes} which does a clean-up\n * by merging attributes.\n *\n * @returns {Function} Selection converter.\n */\nexport function convertCollapsedSelection() {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst selection = data.selection;\n\n\t\tif ( !selection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.consume( selection, 'selection' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst modelPosition = selection.getFirstPosition();\n\t\tconst viewPosition = conversionApi.mapper.toViewPosition( modelPosition );\n\t\tconst brokenPosition = viewWriter.breakAttributes( viewPosition );\n\n\t\tviewWriter.setSelection( brokenPosition );\n\t};\n}\n\n/**\n * Function factory that creates a converter which clears artifacts after the previous\n * {@link module:engine/model/selection~Selection model selection} conversion. It removes all empty\n * {@link module:engine/view/attributeelement~AttributeElement view attribute elements} and merges sibling attributes at all start and end\n * positions of all ranges.\n *\n *\t\t <p><strong>^</strong></p>\n *\t\t-> <p>^</p>\n *\n *\t\t <p><strong>foo</strong>^<strong>bar</strong>bar</p>\n *\t\t-> <p><strong>foo^bar<strong>bar</p>\n *\n *\t\t <p><strong>foo</strong><em>^</em><strong>bar</strong>bar</p>\n *\t\t-> <p><strong>foo^bar<strong>bar</p>\n *\n * This listener should be assigned before any converter for the new selection:\n *\n *\t\tmodelDispatcher.on( 'selection', clearAttributes() );\n *\n * See {@link module:engine/conversion/downcasthelpers~convertCollapsedSelection}\n * which does the opposite by breaking attributes in the selection position.\n *\n * @returns {Function} Selection converter.\n */\nexport function clearAttributes() {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst viewSelection = viewWriter.document.selection;\n\n\t\tfor ( const range of viewSelection.getRanges() ) {\n\t\t\t// Not collapsed selection should not have artifacts.\n\t\t\tif ( range.isCollapsed ) {\n\t\t\t\t// Position might be in the node removed by the view writer.\n\t\t\t\tif ( range.end.parent.document ) {\n\t\t\t\t\tconversionApi.writer.mergeAttributes( range.start );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tviewWriter.setSelection( null );\n\t};\n}\n\n/**\n * Function factory that creates a converter which converts set/change/remove attribute changes from the model to the view.\n * It can also be used to convert selection attributes. In that case, an empty attribute element will be created and the\n * selection will be put inside it.\n *\n * Attributes from the model are converted to a view element that will be wrapping these view nodes that are bound to\n * model elements having the given attribute. This is useful for attributes like `bold` that may be set on text nodes in the model\n * but are represented as an element in the view:\n *\n *\t\t[paragraph] MODEL ====> VIEW <p>\n *\t\t\t|- a {bold: true} |- <b>\n *\t\t\t|- b {bold: true} | |- ab\n *\t\t\t|- c |- c\n *\n * Passed `Function` will be provided with the attribute value and then all the parameters of the\n * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute `attribute` event}.\n * It is expected that the function returns an {@link module:engine/view/element~Element}.\n * The result of the function will be the wrapping element.\n * When the provided `Function` does not return any element, no conversion will take place.\n *\n * The converter automatically consumes the corresponding value from the consumables list and stops the event (see\n * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).\n *\n *\t\tmodelDispatcher.on( 'attribute:bold', wrap( ( modelAttributeValue, viewWriter ) => {\n *\t\t\treturn viewWriter.createAttributeElement( 'strong' );\n *\t\t} );\n *\n * @protected\n * @param {Function} elementCreator Function returning a view element that will be used for wrapping.\n * @returns {Function} Set/change attribute converter.\n */\nexport function wrap( elementCreator ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\t// Recreate current wrapping node. It will be used to unwrap view range if the attribute value has changed\n\t\t// or the attribute was removed.\n\t\tconst oldViewElement = elementCreator( data.attributeOldValue, conversionApi.writer );\n\n\t\t// Create node to wrap with.\n\t\tconst newViewElement = elementCreator( data.attributeNewValue, conversionApi.writer );\n\n\t\tif ( !oldViewElement && !newViewElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst viewSelection = viewWriter.document.selection;\n\n\t\tif ( data.item instanceof ModelSelection || data.item instanceof DocumentSelection ) {\n\t\t\t// Selection attribute conversion.\n\t\t\tviewWriter.wrap( viewSelection.getFirstRange(), newViewElement );\n\t\t} else {\n\t\t\t// Node attribute conversion.\n\t\t\tlet viewRange = conversionApi.mapper.toViewRange( data.range );\n\n\t\t\t// First, unwrap the range from current wrapper.\n\t\t\tif ( data.attributeOldValue !== null && oldViewElement ) {\n\t\t\t\tviewRange = viewWriter.unwrap( viewRange, oldViewElement );\n\t\t\t}\n\n\t\t\tif ( data.attributeNewValue !== null && newViewElement ) {\n\t\t\t\tviewWriter.wrap( viewRange, newViewElement );\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Function factory that creates a converter which converts node insertion changes from the model to the view.\n * The function passed will be provided with all the parameters of the dispatcher's\n * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert `insert` event}.\n * It is expected that the function returns an {@link module:engine/view/element~Element}.\n * The result of the function will be inserted into the view.\n *\n * The converter automatically consumes the corresponding value from the consumables list, stops the event (see\n * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}) and binds the model and view elements.\n *\n *\t\tdowncastDispatcher.on(\n *\t\t\t'insert:myElem',\n *\t\t\tinsertElement( ( modelItem, viewWriter ) => {\n *\t\t\t\tconst text = viewWriter.createText( 'myText' );\n *\t\t\t\tconst myElem = viewWriter.createElement( 'myElem', { myAttr: 'my-' + modelItem.getAttribute( 'myAttr' ) }, text );\n *\n *\t\t\t\t// Do something fancy with `myElem` using `modelItem` or other parameters.\n *\n *\t\t\t\treturn myElem;\n *\t\t\t}\n *\t\t) );\n *\n * @protected\n * @param {Function} elementCreator Function returning a view element, which will be inserted.\n * @returns {Function} Insert element event converter.\n */\nexport function insertElement( elementCreator ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst viewElement = elementCreator( data.item, conversionApi.writer );\n\n\t\tif ( !viewElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.consume( data.item, 'insert' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewPosition = conversionApi.mapper.toViewPosition( data.range.start );\n\n\t\tconversionApi.mapper.bindElements( data.item, viewElement );\n\t\tconversionApi.writer.insert( viewPosition, viewElement );\n\t};\n}\n\n/**\n * Function factory that creates a converter which converts marker adding change to the\n * {@link module:engine/view/uielement~UIElement view UI element}.\n *\n * The view UI element that will be added to the view depends on the passed parameter. See {@link ~insertElement}.\n * In case of a non-collapsed range, the UI element will not wrap nodes but separate elements will be placed at the beginning\n * and at the end of the range.\n *\n * This converter binds created UI elements with the marker name using {@link module:engine/conversion/mapper~Mapper#bindElementToMarker}.\n *\n * @protected\n * @param {module:engine/view/uielement~UIElement|Function} elementCreator A view UI element or a function returning the view element\n * that will be inserted.\n * @returns {Function} Insert element event converter.\n */\nexport function insertUIElement( elementCreator ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\t// Create two view elements. One will be inserted at the beginning of marker, one at the end.\n\t\t// If marker is collapsed, only \"opening\" element will be inserted.\n\t\tdata.isOpening = true;\n\t\tconst viewStartElement = elementCreator( data, conversionApi.writer );\n\n\t\tdata.isOpening = false;\n\t\tconst viewEndElement = elementCreator( data, conversionApi.writer );\n\n\t\tif ( !viewStartElement || !viewEndElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst markerRange = data.markerRange;\n\n\t\t// Marker that is collapsed has consumable build differently that non-collapsed one.\n\t\t// For more information see `addMarker` event description.\n\t\t// If marker's range is collapsed - check if it can be consumed.\n\t\tif ( markerRange.isCollapsed && !conversionApi.consumable.consume( markerRange, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If marker's range is not collapsed - consume all items inside.\n\t\tfor ( const value of markerRange ) {\n\t\t\tif ( !conversionApi.consumable.consume( value.item, evt.name ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst mapper = conversionApi.mapper;\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\t// Add \"opening\" element.\n\t\tviewWriter.insert( mapper.toViewPosition( markerRange.start ), viewStartElement );\n\t\tconversionApi.mapper.bindElementToMarker( viewStartElement, data.markerName );\n\n\t\t// Add \"closing\" element only if range is not collapsed.\n\t\tif ( !markerRange.isCollapsed ) {\n\t\t\tviewWriter.insert( mapper.toViewPosition( markerRange.end ), viewEndElement );\n\t\t\tconversionApi.mapper.bindElementToMarker( viewEndElement, data.markerName );\n\t\t}\n\n\t\tevt.stop();\n\t};\n}\n\n// Function factory that returns a default downcast converter for removing a {@link module:engine/view/uielement~UIElement UI element}\n// basing on marker remove change.\n//\n// This converter unbinds elements from the marker name.\n//\n// @returns {Function} Removed UI element converter.\nfunction removeUIElement() {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst elements = conversionApi.mapper.markerNameToElements( data.markerName );\n\n\t\tif ( !elements ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( const element of elements ) {\n\t\t\tconversionApi.mapper.unbindElementFromMarkerName( element, data.markerName );\n\t\t\tconversionApi.writer.clear( conversionApi.writer.createRangeOn( element ), element );\n\t\t}\n\n\t\tconversionApi.writer.clearClonedElementsGroup( data.markerName );\n\n\t\tevt.stop();\n\t};\n}\n\n// Function factory that creates a converter which converts set/change/remove attribute changes from the model to the view.\n//\n// Attributes from the model are converted to the view element attributes in the view. You may provide a custom function to generate\n// a key-value attribute pair to add/change/remove. If not provided, model attributes will be converted to view element\n// attributes on a one-to-one basis.\n//\n// *Note:** The provided attribute creator should always return the same `key` for a given attribute from the model.\n//\n// The converter automatically consumes the corresponding value from the consumables list and stops the event (see\n// {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}).\n//\n//\t\tmodelDispatcher.on( 'attribute:customAttr:myElem', changeAttribute( ( value, data ) => {\n//\t\t\t// Change attribute key from `customAttr` to `class` in the view.\n//\t\t\tconst key = 'class';\n//\t\t\tlet value = data.attributeNewValue;\n//\n//\t\t\t// Force attribute value to 'empty' if the model element is empty.\n//\t\t\tif ( data.item.childCount === 0 ) {\n//\t\t\t\tvalue = 'empty';\n//\t\t\t}\n//\n//\t\t\t// Return the key-value pair.\n//\t\t\treturn { key, value };\n//\t\t} ) );\n//\n// @param {Function} [attributeCreator] Function returning an object with two properties: `key` and `value`, which\n// represent the attribute key and attribute value to be set on a {@link module:engine/view/element~Element view element}.\n// The function is passed the model attribute value as the first parameter and additional data about the change as the second parameter.\n// @returns {Function} Set/change attribute converter.\nfunction changeAttribute( attributeCreator ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst oldAttribute = attributeCreator( data.attributeOldValue, data );\n\t\tconst newAttribute = attributeCreator( data.attributeNewValue, data );\n\n\t\tif ( !oldAttribute && !newAttribute ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewElement = conversionApi.mapper.toViewElement( data.item );\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\t// If model item cannot be mapped to a view element, it means item is not an `Element` instance but a `TextProxy` node.\n\t\t// Only elements can have attributes in a view so do not proceed for anything else (#1587).\n\t\tif ( !viewElement ) {\n\t\t\t/**\n\t\t\t * This error occurs when a {@link module:engine/model/textproxy~TextProxy text node's} attribute is to be downcasted\n\t\t\t * by {@link module:engine/conversion/conversion~Conversion#attributeToAttribute `Attribute to Attribute converter`}.\n\t\t\t * In most cases it is caused by converters misconfiguration when only \"generic\" converter is defined:\n\t\t\t *\n\t\t\t *\t\teditor.conversion.for( 'downcast' ).attributeToAttribute( {\n\t\t\t *\t\t\tmodel: 'attribute-name',\n\t\t\t *\t\t\tview: 'attribute-name'\n\t\t\t *\t\t} ) );\n\t\t\t *\n\t\t\t * and given attribute is used on text node, for example:\n\t\t\t *\n\t\t\t *\t\tmodel.change( writer => {\n\t\t\t *\t\t\twriter.insertText( 'Foo', { 'attribute-name': 'bar' }, parent, 0 );\n\t\t\t *\t\t} );\n\t\t\t *\n\t\t\t * In such cases, to convert the same attribute for both {@link module:engine/model/element~Element}\n\t\t\t * and {@link module:engine/model/textproxy~TextProxy `Text`} nodes, text specific\n\t\t\t * {@link module:engine/conversion/conversion~Conversion#attributeToElement `Attribute to Element converter`}\n\t\t\t * with higher {@link module:utils/priorities~PriorityString priority} must also be defined:\n\t\t\t *\n\t\t\t *\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t\t\t *\t\t\tmodel: {\n\t\t\t *\t\t\t\tkey: 'attribute-name',\n\t\t\t *\t\t\t\tname: '$text'\n\t\t\t *\t\t\t},\n\t\t\t *\t\t\tview: ( value, writer ) => {\n\t\t\t *\t\t\t\treturn writer.createAttributeElement( 'span', { 'attribute-name': value } );\n\t\t\t *\t\t\t},\n\t\t\t *\t\t\tconverterPriority: 'high'\n\t\t\t *\t\t} ) );\n\t\t\t *\n\t\t\t * @error conversion-attribute-to-attribute-on-text\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'conversion-attribute-to-attribute-on-text: ' +\n\t\t\t\t'Trying to convert text node\\'s attribute with attribute-to-attribute converter.',\n\t\t\t\t[ data, conversionApi ]\n\t\t\t);\n\t\t}\n\n\t\t// First remove the old attribute if there was one.\n\t\tif ( data.attributeOldValue !== null && oldAttribute ) {\n\t\t\tif ( oldAttribute.key == 'class' ) {\n\t\t\t\tconst classes = Array.isArray( oldAttribute.value ) ? oldAttribute.value : [ oldAttribute.value ];\n\n\t\t\t\tfor ( const className of classes ) {\n\t\t\t\t\tviewWriter.removeClass( className, viewElement );\n\t\t\t\t}\n\t\t\t} else if ( oldAttribute.key == 'style' ) {\n\t\t\t\tconst keys = Object.keys( oldAttribute.value );\n\n\t\t\t\tfor ( const key of keys ) {\n\t\t\t\t\tviewWriter.removeStyle( key, viewElement );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tviewWriter.removeAttribute( oldAttribute.key, viewElement );\n\t\t\t}\n\t\t}\n\n\t\t// Then set the new attribute.\n\t\tif ( data.attributeNewValue !== null && newAttribute ) {\n\t\t\tif ( newAttribute.key == 'class' ) {\n\t\t\t\tconst classes = Array.isArray( newAttribute.value ) ? newAttribute.value : [ newAttribute.value ];\n\n\t\t\t\tfor ( const className of classes ) {\n\t\t\t\t\tviewWriter.addClass( className, viewElement );\n\t\t\t\t}\n\t\t\t} else if ( newAttribute.key == 'style' ) {\n\t\t\t\tconst keys = Object.keys( newAttribute.value );\n\n\t\t\t\tfor ( const key of keys ) {\n\t\t\t\t\tviewWriter.setStyle( key, newAttribute.value[ key ], viewElement );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tviewWriter.setAttribute( newAttribute.key, newAttribute.value, viewElement );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Function factory that creates a converter which converts the text inside marker's range. The converter wraps the text with\n// {@link module:engine/view/attributeelement~AttributeElement} created from the provided descriptor.\n// See {link module:engine/conversion/downcasthelpers~createViewElementFromHighlightDescriptor}.\n//\n// It can also be used to convert the selection that is inside a marker. In that case, an empty attribute element will be\n// created and the selection will be put inside it.\n//\n// If the highlight descriptor does not provide the `priority` property, `10` will be used.\n//\n// If the highlight descriptor does not provide the `id` property, the name of the marker will be used.\n//\n// This converter binds the created {@link module:engine/view/attributeelement~AttributeElement attribute elemens} with the marker name\n// using the {@link module:engine/conversion/mapper~Mapper#bindElementToMarker} method.\n//\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor\n// @returns {Function}\nfunction highlightText( highlightDescriptor ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tif ( !data.item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !( data.item instanceof ModelSelection || data.item instanceof DocumentSelection ) && !data.item.is( 'textProxy' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst descriptor = prepareDescriptor( highlightDescriptor, data, conversionApi );\n\n\t\tif ( !descriptor ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewElement = createViewElementFromHighlightDescriptor( descriptor );\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst viewSelection = viewWriter.document.selection;\n\n\t\tif ( data.item instanceof ModelSelection || data.item instanceof DocumentSelection ) {\n\t\t\tviewWriter.wrap( viewSelection.getFirstRange(), viewElement, viewSelection );\n\t\t} else {\n\t\t\tconst viewRange = conversionApi.mapper.toViewRange( data.range );\n\t\t\tconst rangeAfterWrap = viewWriter.wrap( viewRange, viewElement );\n\n\t\t\tfor ( const element of rangeAfterWrap.getItems() ) {\n\t\t\t\tif ( element.is( 'attributeElement' ) && element.isSimilar( viewElement ) ) {\n\t\t\t\t\tconversionApi.mapper.bindElementToMarker( element, data.markerName );\n\n\t\t\t\t\t// One attribute element is enough, because all of them are bound together by the view writer.\n\t\t\t\t\t// Mapper uses this binding to get all the elements no matter how many of them are registered in the mapper.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Converter function factory. It creates a function which applies the marker's highlight to an element inside the marker's range.\n//\n// The converter checks if an element has the `addHighlight` function stored as a\n// {@link module:engine/view/element~Element#_setCustomProperty custom property} and, if so, uses it to apply the highlight.\n// In such case the converter will consume all element's children, assuming that they were handled by the element itself.\n//\n// When the `addHighlight` custom property is not present, the element is not converted in any special way.\n// This means that converters will proceed to convert the element's child nodes.\n//\n// If the highlight descriptor does not provide the `priority` property, `10` will be used.\n//\n// If the highlight descriptor does not provide the `id` property, the name of the marker will be used.\n//\n// This converter binds altered {@link module:engine/view/containerelement~ContainerElement container elements} with the marker name using\n// the {@link module:engine/conversion/mapper~Mapper#bindElementToMarker} method.\n//\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor\n// @returns {Function}\nfunction highlightElement( highlightDescriptor ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tif ( !data.item ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !( data.item instanceof ModelElement ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst descriptor = prepareDescriptor( highlightDescriptor, data, conversionApi );\n\n\t\tif ( !descriptor ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.test( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewElement = conversionApi.mapper.toViewElement( data.item );\n\n\t\tif ( viewElement && viewElement.getCustomProperty( 'addHighlight' ) ) {\n\t\t\t// Consume element itself.\n\t\t\tconversionApi.consumable.consume( data.item, evt.name );\n\n\t\t\t// Consume all children nodes.\n\t\t\tfor ( const value of ModelRange._createIn( data.item ) ) {\n\t\t\t\tconversionApi.consumable.consume( value.item, evt.name );\n\t\t\t}\n\n\t\t\tviewElement.getCustomProperty( 'addHighlight' )( viewElement, descriptor, conversionApi.writer );\n\n\t\t\tconversionApi.mapper.bindElementToMarker( viewElement, data.markerName );\n\t\t}\n\t};\n}\n\n// Function factory that creates a converter which converts the removing model marker to the view.\n//\n// Both text nodes and elements are handled by this converter but they are handled a bit differently.\n//\n// Text nodes are unwrapped using the {@link module:engine/view/attributeelement~AttributeElement attribute element} created from the\n// provided highlight descriptor. See {link module:engine/conversion/downcasthelpers~HighlightDescriptor}.\n//\n// For elements, the converter checks if an element has the `removeHighlight` function stored as a\n// {@link module:engine/view/element~Element#_setCustomProperty custom property}. If so, it uses it to remove the highlight.\n// In such case, the children of that element will not be converted.\n//\n// When `removeHighlight` is not present, the element is not converted in any special way.\n// The converter will proceed to convert the element's child nodes instead.\n//\n// If the highlight descriptor does not provide the `priority` property, `10` will be used.\n//\n// If the highlight descriptor does not provide the `id` property, the name of the marker will be used.\n//\n// This converter unbinds elements from the marker name.\n//\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} highlightDescriptor\n// @returns {Function}\nfunction removeHighlight( highlightDescriptor ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\t// This conversion makes sense only for non-collapsed range.\n\t\tif ( data.markerRange.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst descriptor = prepareDescriptor( highlightDescriptor, data, conversionApi );\n\n\t\tif ( !descriptor ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// View element that will be used to unwrap `AttributeElement`s.\n\t\tconst viewHighlightElement = createViewElementFromHighlightDescriptor( descriptor );\n\n\t\t// Get all elements bound with given marker name.\n\t\tconst elements = conversionApi.mapper.markerNameToElements( data.markerName );\n\n\t\tif ( !elements ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( const element of elements ) {\n\t\t\tconversionApi.mapper.unbindElementFromMarkerName( element, data.markerName );\n\n\t\t\tif ( element.is( 'attributeElement' ) ) {\n\t\t\t\tconversionApi.writer.unwrap( conversionApi.writer.createRangeOn( element ), viewHighlightElement );\n\t\t\t} else {\n\t\t\t\t// if element.is( 'containerElement' ).\n\t\t\t\telement.getCustomProperty( 'removeHighlight' )( element, descriptor.id, conversionApi.writer );\n\t\t\t}\n\t\t}\n\n\t\tconversionApi.writer.clearClonedElementsGroup( data.markerName );\n\n\t\tevt.stop();\n\t};\n}\n\n// Model element to view element conversion helper.\n//\n// See {@link ~DowncastHelpers#elementToElement `.elementToElement()` downcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {String} config.model The name of the model element to convert.\n// @param {module:engine/view/elementdefinition~ElementDefinition|Function} config.view A view element definition or a function\n// that takes the model element and {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}\n// as parameters and returns a view container element.\n// @returns {Function} Conversion helper.\nfunction downcastElementToElement( config ) {\n\tconfig = cloneDeep( config );\n\n\tconfig.view = normalizeToElementConfig( config.view, 'container' );\n\n\treturn dispatcher => {\n\t\tdispatcher.on( 'insert:' + config.model, insertElement( config.view ), { priority: config.converterPriority || 'normal' } );\n\t};\n}\n\n// Model attribute to view element conversion helper.\n//\n// See {@link ~DowncastHelpers#attributeToElement `.attributeToElement()` downcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {String|Object} config.model The key of the attribute to convert from or a `{ key, values }` object. `values` is an array\n// of `String`s with possible values if the model attribute is an enumerable.\n// @param {module:engine/view/elementdefinition~ElementDefinition|Function|Object} config.view A view element definition or a function\n// that takes the model attribute value and {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}\n// as parameters and returns a view attribute element. If `config.model.values` is\n// given, `config.view` should be an object assigning values from `config.model.values` to view element definitions or functions.\n// @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n// @returns {Function} Conversion helper.\nfunction downcastAttributeToElement( config ) {\n\tconfig = cloneDeep( config );\n\n\tconst modelKey = config.model.key ? config.model.key : config.model;\n\tlet eventName = 'attribute:' + modelKey;\n\n\tif ( config.model.name ) {\n\t\teventName += ':' + config.model.name;\n\t}\n\n\tif ( config.model.values ) {\n\t\tfor ( const modelValue of config.model.values ) {\n\t\t\tconfig.view[ modelValue ] = normalizeToElementConfig( config.view[ modelValue ], 'attribute' );\n\t\t}\n\t} else {\n\t\tconfig.view = normalizeToElementConfig( config.view, 'attribute' );\n\t}\n\n\tconst elementCreator = getFromAttributeCreator( config );\n\n\treturn dispatcher => {\n\t\tdispatcher.on( eventName, wrap( elementCreator ), { priority: config.converterPriority || 'normal' } );\n\t};\n}\n\n// Model attribute to view attribute conversion helper.\n//\n// See {@link ~DowncastHelpers#attributeToAttribute `.attributeToAttribute()` downcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {String|Object} config.model The key of the attribute to convert from or a `{ key, values, [ name ] }` object describing\n// the attribute key, possible values and, optionally, an element name to convert from.\n// @param {String|Object|Function} config.view A view attribute key, or a `{ key, value }` object or a function that takes\n// the model attribute value and returns a `{ key, value }` object. If `key` is `'class'`, `value` can be a `String` or an\n// array of `String`s. If `key` is `'style'`, `value` is an object with key-value pairs. In other cases, `value` is a `String`.\n// If `config.model.values` is set, `config.view` should be an object assigning values from `config.model.values` to\n// `{ key, value }` objects or a functions.\n// @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n// @returns {Function} Conversion helper.\nfunction downcastAttributeToAttribute( config ) {\n\tconfig = cloneDeep( config );\n\n\tconst modelKey = config.model.key ? config.model.key : config.model;\n\tlet eventName = 'attribute:' + modelKey;\n\n\tif ( config.model.name ) {\n\t\teventName += ':' + config.model.name;\n\t}\n\n\tif ( config.model.values ) {\n\t\tfor ( const modelValue of config.model.values ) {\n\t\t\tconfig.view[ modelValue ] = normalizeToAttributeConfig( config.view[ modelValue ] );\n\t\t}\n\t} else {\n\t\tconfig.view = normalizeToAttributeConfig( config.view );\n\t}\n\n\tconst elementCreator = getFromAttributeCreator( config );\n\n\treturn dispatcher => {\n\t\tdispatcher.on( eventName, changeAttribute( elementCreator ), { priority: config.converterPriority || 'normal' } );\n\t};\n}\n\n// Model marker to view element conversion helper.\n//\n// See {@link ~DowncastHelpers#markerToElement `.markerToElement()` downcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {String} config.model The name of the model marker (or model marker group) to convert.\n// @param {module:engine/view/elementdefinition~ElementDefinition|Function} config.view A view element definition or a function\n// that takes the model marker data as a parameter and returns a view UI element.\n// @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n// @returns {Function} Conversion helper.\nfunction downcastMarkerToElement( config ) {\n\tconfig = cloneDeep( config );\n\n\tconfig.view = normalizeToElementConfig( config.view, 'ui' );\n\n\treturn dispatcher => {\n\t\tdispatcher.on( 'addMarker:' + config.model, insertUIElement( config.view ), { priority: config.converterPriority || 'normal' } );\n\t\tdispatcher.on( 'removeMarker:' + config.model, removeUIElement( config.view ), { priority: config.converterPriority || 'normal' } );\n\t};\n}\n\n// Model marker to highlight conversion helper.\n//\n// See {@link ~DowncastHelpers#markerToElement `.markerToElement()` downcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {String} config.model The name of the model marker (or model marker group) to convert.\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor|Function} config.view A highlight descriptor\n// that will be used for highlighting or a function that takes the model marker data as a parameter and returns a highlight descriptor.\n// @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n// @returns {Function} Conversion helper.\nfunction downcastMarkerToHighlight( config ) {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'addMarker:' + config.model, highlightText( config.view ), { priority: config.converterPriority || 'normal' } );\n\t\tdispatcher.on( 'addMarker:' + config.model, highlightElement( config.view ), { priority: config.converterPriority || 'normal' } );\n\t\tdispatcher.on( 'removeMarker:' + config.model, removeHighlight( config.view ), { priority: config.converterPriority || 'normal' } );\n\t};\n}\n\n// Takes `config.view`, and if it is an {@link module:engine/view/elementdefinition~ElementDefinition}, converts it\n// to a function (because lower level converters accept only element creator functions).\n//\n// @param {module:engine/view/elementdefinition~ElementDefinition|Function} view View configuration.\n// @param {'container'|'attribute'|'ui'} viewElementType View element type to create.\n// @returns {Function} Element creator function to use in lower level converters.\nfunction normalizeToElementConfig( view, viewElementType ) {\n\tif ( typeof view == 'function' ) {\n\t\t// If `view` is already a function, don't do anything.\n\t\treturn view;\n\t}\n\n\treturn ( modelData, viewWriter ) => createViewElementFromDefinition( view, viewWriter, viewElementType );\n}\n\n// Creates a view element instance from the provided {@link module:engine/view/elementdefinition~ElementDefinition} and class.\n//\n// @param {module:engine/view/elementdefinition~ElementDefinition} viewElementDefinition\n// @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter\n// @param {'container'|'attribute'|'ui'} viewElementType\n// @returns {module:engine/view/element~Element}\nfunction createViewElementFromDefinition( viewElementDefinition, viewWriter, viewElementType ) {\n\tif ( typeof viewElementDefinition == 'string' ) {\n\t\t// If `viewElementDefinition` is given as a `String`, normalize it to an object with `name` property.\n\t\tviewElementDefinition = { name: viewElementDefinition };\n\t}\n\n\tlet element;\n\tconst attributes = Object.assign( {}, viewElementDefinition.attributes );\n\n\tif ( viewElementType == 'container' ) {\n\t\telement = viewWriter.createContainerElement( viewElementDefinition.name, attributes );\n\t} else if ( viewElementType == 'attribute' ) {\n\t\tconst options = {\n\t\t\tpriority: viewElementDefinition.priority || ViewAttributeElement.DEFAULT_PRIORITY\n\t\t};\n\n\t\telement = viewWriter.createAttributeElement( viewElementDefinition.name, attributes, options );\n\t} else {\n\t\t// 'ui'.\n\t\telement = viewWriter.createUIElement( viewElementDefinition.name, attributes );\n\t}\n\n\tif ( viewElementDefinition.styles ) {\n\t\tconst keys = Object.keys( viewElementDefinition.styles );\n\n\t\tfor ( const key of keys ) {\n\t\t\tviewWriter.setStyle( key, viewElementDefinition.styles[ key ], element );\n\t\t}\n\t}\n\n\tif ( viewElementDefinition.classes ) {\n\t\tconst classes = viewElementDefinition.classes;\n\n\t\tif ( typeof classes == 'string' ) {\n\t\t\tviewWriter.addClass( classes, element );\n\t\t} else {\n\t\t\tfor ( const className of classes ) {\n\t\t\t\tviewWriter.addClass( className, element );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn element;\n}\n\nfunction getFromAttributeCreator( config ) {\n\tif ( config.model.values ) {\n\t\treturn ( modelAttributeValue, viewWriter ) => {\n\t\t\tconst view = config.view[ modelAttributeValue ];\n\n\t\t\tif ( view ) {\n\t\t\t\treturn view( modelAttributeValue, viewWriter );\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\t} else {\n\t\treturn config.view;\n\t}\n}\n\n// Takes the configuration, adds default parameters if they do not exist and normalizes other parameters to be used in downcast converters\n// for generating a view attribute.\n//\n// @param {Object} view View configuration.\nfunction normalizeToAttributeConfig( view ) {\n\tif ( typeof view == 'string' ) {\n\t\treturn modelAttributeValue => ( { key: view, value: modelAttributeValue } );\n\t} else if ( typeof view == 'object' ) {\n\t\t// { key, value, ... }\n\t\tif ( view.value ) {\n\t\t\treturn () => view;\n\t\t}\n\t\t// { key, ... }\n\t\telse {\n\t\t\treturn modelAttributeValue => ( { key: view.key, value: modelAttributeValue } );\n\t\t}\n\t} else {\n\t\t// function.\n\t\treturn view;\n\t}\n}\n\n// Helper function for `highlight`. Prepares the actual descriptor object using value passed to the converter.\nfunction prepareDescriptor( highlightDescriptor, data, conversionApi ) {\n\t// If passed descriptor is a creator function, call it. If not, just use passed value.\n\tconst descriptor = typeof highlightDescriptor == 'function' ?\n\t\thighlightDescriptor( data, conversionApi ) :\n\t\thighlightDescriptor;\n\n\tif ( !descriptor ) {\n\t\treturn null;\n\t}\n\n\t// Apply default descriptor priority.\n\tif ( !descriptor.priority ) {\n\t\tdescriptor.priority = 10;\n\t}\n\n\t// Default descriptor id is marker name.\n\tif ( !descriptor.id ) {\n\t\tdescriptor.id = data.markerName;\n\t}\n\n\treturn descriptor;\n}\n\n/**\n * An object describing how the marker highlight should be represented in the view.\n *\n * Each text node contained in a highlighted range will be wrapped in a `<span>`\n * {@link module:engine/view/attributeelement~AttributeElement view attribute element} with CSS class(es), attributes and a priority\n * described by this object.\n *\n * Additionally, each {@link module:engine/view/containerelement~ContainerElement container element} can handle displaying the highlight\n * separately by providing the `addHighlight` and `removeHighlight` custom properties. In this case:\n *\n * * The `HighlightDescriptor` object is passed to the `addHighlight` function upon conversion and should be used to apply the highlight to\n * the element.\n * * The descriptor `id` is passed to the `removeHighlight` function upon conversion and should be used to remove the highlight with the\n * given ID from the element.\n *\n * @typedef {Object} module:engine/conversion/downcasthelpers~HighlightDescriptor\n *\n * @property {String|Array.<String>} classes A CSS class or an array of classes to set. If the descriptor is used to\n * create an {@link module:engine/view/attributeelement~AttributeElement attribute element} over text nodes, these classes will be set\n * on that attribute element. If the descriptor is applied to an element, usually these classes will be set on that element, however,\n * this depends on how the element converts the descriptor.\n *\n * @property {String} [id] Descriptor identifier. If not provided, it defaults to the converted marker's name.\n *\n * @property {Number} [priority] Descriptor priority. If not provided, it defaults to `10`. If the descriptor is used to create\n * an {@link module:engine/view/attributeelement~AttributeElement attribute element}, it will be that element's\n * {@link module:engine/view/attributeelement~AttributeElement#priority priority}. If the descriptor is applied to an element,\n * the priority will be used to determine which descriptor is more important.\n *\n * @property {Object} [attributes] Attributes to set. If the descriptor is used to create\n * an {@link module:engine/view/attributeelement~AttributeElement attribute element} over text nodes, these attributes will be set on that\n * attribute element. If the descriptor is applied to an element, usually these attributes will be set on that element, however,\n * this depends on how the element converts the descriptor.\n */\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nimport Matcher from '../view/matcher';\nimport ModelRange from '../model/range';\nimport ConversionHelpers from './conversionhelpers';\n\nimport { cloneDeep } from 'lodash-es';\nimport ModelSelection from '../model/selection';\n\n/**\n * Contains {@link module:engine/view/view view} to {@link module:engine/model/model model} converters for\n * {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher}.\n *\n * @module engine/conversion/upcasthelpers\n */\n\n/**\n * Upcast conversion helper functions.\n *\n * @extends module:engine/conversion/conversionhelpers~ConversionHelpers\n */\nexport default class UpcastHelpers extends ConversionHelpers {\n\t/**\n\t * View element to model element conversion helper.\n\t *\n\t * This conversion results in creating a model element. For example,\n\t * view `<p>Foo</p>` becomes `<paragraph>Foo</paragraph>` in the model.\n\t *\n\t * Keep in mind that the element will be inserted only if it is allowed\n\t * by {@link module:engine/model/schema~Schema schema} configuration.\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToElement( {\n\t *\t\t\tview: 'p',\n\t *\t\t\tmodel: 'paragraph'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToElement( {\n\t *\t\t\tview: 'p',\n\t *\t\t\tmodel: 'paragraph',\n\t *\t\t\tconverterPriority: 'high'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToElement( {\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'p',\n\t *\t\t\t\tclasses: 'fancy'\n\t *\t\t\t},\n\t *\t\t\tmodel: 'fancyParagraph'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToElement( {\n\t * \t\t\tview: {\n\t *\t\t\t\tname: 'p',\n\t *\t\t\t\tclasses: 'heading'\n\t * \t\t\t},\n\t * \t\t\tmodel: ( viewElement, modelWriter ) => {\n\t * \t\t\t\treturn modelWriter.createElement( 'heading', { level: viewElement.getAttribute( 'data-level' ) } );\n\t * \t\t\t}\n\t * \t\t} );\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #elementToElement\n\t * @param {Object} config Conversion configuration.\n\t * @param {module:engine/view/matcher~MatcherPattern} [config.view] Pattern matching all view elements which should be converted. If not\n\t * set, the converter will fire for every view element.\n\t * @param {String|module:engine/model/element~Element|Function} config.model Name of the model element, a model element\n\t * instance or a function that takes a view element and returns a model element. The model element will be inserted in the model.\n\t * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n\t * @returns {module:engine/conversion/upcasthelpers~UpcastHelpers}\n\t */\n\telementToElement( config ) {\n\t\treturn this.add( upcastElementToElement( config ) );\n\t}\n\n\t/**\n\t * View element to model attribute conversion helper.\n\t *\n\t * This conversion results in setting an attribute on a model node. For example, view `<strong>Foo</strong>` becomes\n\t * `Foo` {@link module:engine/model/text~Text model text node} with `bold` attribute set to `true`.\n\t *\n\t * This helper is meant to set a model attribute on all the elements that are inside the converted element:\n\t *\n\t *\t\t<strong>Foo</strong> --> <strong><p>Foo</p></strong> --> <paragraph><$text bold=\"true\">Foo</$text></paragraph>\n\t *\n\t * Above is a sample of HTML code, that goes through autoparagraphing (first step) and then is converted (second step).\n\t * Even though `<strong>` is over `<p>` element, `bold=\"true\"` was added to the text. See\n\t * {@link module:engine/conversion/upcasthelpers~UpcastHelpers#attributeToAttribute} for comparison.\n\t *\n\t * Keep in mind that the attribute will be set only if it is allowed by {@link module:engine/model/schema~Schema schema} configuration.\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToAttribute( {\n\t *\t\t\tview: 'strong',\n\t *\t\t\tmodel: 'bold'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToAttribute( {\n\t *\t\t\tview: 'strong',\n\t *\t\t\tmodel: 'bold',\n\t *\t\t\tconverterPriority: 'high'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToAttribute( {\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'span',\n\t *\t\t\t\tclasses: 'bold'\n\t *\t\t\t},\n\t *\t\t\tmodel: 'bold'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToAttribute( {\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'span',\n\t *\t\t\t\tclasses: [ 'styled', 'styled-dark' ]\n\t *\t\t\t},\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'styled',\n\t *\t\t\t\tvalue: 'dark'\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * \t\teditor.conversion.for( 'upcast' ).elementToAttribute( {\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'span',\n\t *\t\t\t\tstyles: {\n\t *\t\t\t\t\t'font-size': /[\\s\\S]+/\n\t *\t\t\t\t}\n\t *\t\t\t},\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'fontSize',\n\t *\t\t\t\tvalue: viewElement => {\n\t *\t\t\t\t\tconst fontSize = viewElement.getStyle( 'font-size' );\n\t *\t\t\t\t\tconst value = fontSize.substr( 0, fontSize.length - 2 );\n\t *\n\t *\t\t\t\t\tif ( value <= 10 ) {\n\t *\t\t\t\t\t\treturn 'small';\n\t *\t\t\t\t\t} else if ( value > 12 ) {\n\t *\t\t\t\t\t\treturn 'big';\n\t *\t\t\t\t\t}\n\t *\n\t *\t\t\t\t\treturn null;\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #elementToAttribute\n\t * @param {Object} config Conversion configuration.\n\t * @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.\n\t * @param {String|Object} config.model Model attribute key or an object with `key` and `value` properties, describing\n\t * the model attribute. `value` property may be set as a function that takes a view element and returns the value.\n\t * If `String` is given, the model attribute value will be set to `true`.\n\t * @param {module:utils/priorities~PriorityString} [config.converterPriority='low'] Converter priority.\n\t * @returns {module:engine/conversion/upcasthelpers~UpcastHelpers}\n\t */\n\telementToAttribute( config ) {\n\t\treturn this.add( upcastElementToAttribute( config ) );\n\t}\n\n\t/**\n\t * View attribute to model attribute conversion helper.\n\t *\n\t * This conversion results in setting an attribute on a model node. For example, view `<img src=\"foo.jpg\"></img>` becomes\n\t * `<image source=\"foo.jpg\"></image>` in the model.\n\t *\n\t * This helper is meant to convert view attributes from view elements which got converted to the model, so the view attribute\n\t * is set only on the corresponding model node:\n\t *\n\t *\t\t<div class=\"dark\"><div>foo</div></div> --> <div dark=\"true\"><div>foo</div></div>\n\t *\n\t * Above, `class=\"dark\"` attribute is added only to the `<div>` elements that has it. This is in contrary to\n\t * {@link module:engine/conversion/upcasthelpers~UpcastHelpers#elementToAttribute} which sets attributes for\n\t * all the children in the model:\n\t *\n\t *\t\t<strong>Foo</strong> --> <strong><p>Foo</p></strong> --> <paragraph><$text bold=\"true\">Foo</$text></paragraph>\n\t *\n\t * Above is a sample of HTML code, that goes through autoparagraphing (first step) and then is converted (second step).\n\t * Even though `<strong>` is over `<p>` element, `bold=\"true\"` was added to the text.\n\t *\n\t * Keep in mind that the attribute will be set only if it is allowed by {@link module:engine/model/schema~Schema schema} configuration.\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).attributeToAttribute( {\n\t *\t\t\tview: 'src',\n\t *\t\t\tmodel: 'source'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).attributeToAttribute( {\n\t *\t\t\tview: { key: 'src' },\n\t *\t\t\tmodel: 'source'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).attributeToAttribute( {\n\t *\t\t\tview: { key: 'src' },\n\t *\t\t\tmodel: 'source',\n\t *\t\t\tconverterPriority: 'normal'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).attributeToAttribute( {\n\t *\t\t\tview: {\n\t *\t\t\t\tkey: 'data-style',\n\t *\t\t\t\tvalue: /[\\s\\S]+/\n\t *\t\t\t},\n\t *\t\t\tmodel: 'styled'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).attributeToAttribute( {\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'img',\n\t *\t\t\t\tkey: 'class',\n\t *\t\t\t\tvalue: 'styled-dark'\n\t *\t\t\t},\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'styled',\n\t *\t\t\t\tvalue: 'dark'\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).attributeToAttribute( {\n\t *\t\t\tview: {\n\t *\t\t\t\tkey: 'class',\n\t *\t\t\t\tvalue: /styled-[\\S]+/\n\t *\t\t\t},\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'styled'\n\t *\t\t\t\tvalue: viewElement => {\n\t *\t\t\t\t\tconst regexp = /styled-([\\S]+)/;\n\t *\t\t\t\t\tconst match = viewElement.getAttribute( 'class' ).match( regexp );\n\t *\n\t *\t\t\t\t\treturn match[ 1 ];\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #attributeToAttribute\n\t * @param {Object} config Conversion configuration.\n\t * @param {String|Object} config.view Specifies which view attribute will be converted. If a `String` is passed,\n\t * attributes with given key will be converted. If an `Object` is passed, it must have a required `key` property,\n\t * specifying view attribute key, and may have an optional `value` property, specifying view attribute value and optional `name`\n\t * property specifying a view element name from/on which the attribute should be converted. `value` can be given as a `String`,\n\t * a `RegExp` or a function callback, that takes view attribute value as the only parameter and returns `Boolean`.\n\t * @param {String|Object} config.model Model attribute key or an object with `key` and `value` properties, describing\n\t * the model attribute. `value` property may be set as a function that takes a view element and returns the value.\n\t * If `String` is given, the model attribute value will be same as view attribute value.\n\t * @param {module:utils/priorities~PriorityString} [config.converterPriority='low'] Converter priority.\n\t * @returns {module:engine/conversion/upcasthelpers~UpcastHelpers}\n\t */\n\tattributeToAttribute( config ) {\n\t\treturn this.add( upcastAttributeToAttribute( config ) );\n\t}\n\n\t/**\n\t * View element to model marker conversion helper.\n\t *\n\t * This conversion results in creating a model marker. For example, if the marker was stored in a view as an element:\n\t * `<p>Fo<span data-marker=\"comment\" data-comment-id=\"7\"></span>o</p><p>B<span data-marker=\"comment\" data-comment-id=\"7\"></span>ar</p>`,\n\t * after the conversion is done, the marker will be available in\n\t * {@link module:engine/model/model~Model#markers model document markers}.\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToMarker( {\n\t *\t\t\tview: 'marker-search',\n\t *\t\t\tmodel: 'search'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToMarker( {\n\t *\t\t\tview: 'marker-search',\n\t *\t\t\tmodel: 'search',\n\t *\t\t\tconverterPriority: 'high'\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToMarker( {\n\t *\t\t\tview: 'marker-search',\n\t *\t\t\tmodel: viewElement => 'comment:' + viewElement.getAttribute( 'data-comment-id' )\n\t *\t\t} );\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).elementToMarker( {\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'span',\n\t *\t\t\t\tattributes: {\n\t *\t\t\t\t\t'data-marker': 'search'\n\t *\t\t\t\t}\n\t *\t\t\t},\n\t *\t\t\tmodel: 'search'\n\t *\t\t} );\n\t *\n\t * See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter\n\t * to the conversion process.\n\t *\n\t * @method #elementToMarker\n\t * @param {Object} config Conversion configuration.\n\t * @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.\n\t * @param {String|Function} config.model Name of the model marker, or a function that takes a view element and returns\n\t * a model marker name.\n\t * @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n\t * @returns {module:engine/conversion/upcasthelpers~UpcastHelpers}\n\t */\n\telementToMarker( config ) {\n\t\treturn this.add( upcastElementToMarker( config ) );\n\t}\n}\n\n/**\n * Function factory, creates a converter that converts {@link module:engine/view/documentfragment~DocumentFragment view document fragment}\n * or all children of {@link module:engine/view/element~Element} into\n * {@link module:engine/model/documentfragment~DocumentFragment model document fragment}.\n * This is the \"entry-point\" converter for upcast (view to model conversion). This converter starts the conversion of all children\n * of passed view document fragment. Those children {@link module:engine/view/node~Node view nodes} are then handled by other converters.\n *\n * This also a \"default\", last resort converter for all view elements that has not been converted by other converters.\n * When a view element is being converted to the model but it does not have converter specified, that view element\n * will be converted to {@link module:engine/model/documentfragment~DocumentFragment model document fragment} and returned.\n *\n * @returns {Function} Universal converter for view {@link module:engine/view/documentfragment~DocumentFragment fragments} and\n * {@link module:engine/view/element~Element elements} that returns\n * {@link module:engine/model/documentfragment~DocumentFragment model fragment} with children of converted view item.\n */\nexport function convertToModelFragment() {\n\treturn ( evt, data, conversionApi ) => {\n\t\t// Second argument in `consumable.consume` is discarded for ViewDocumentFragment but is needed for ViewElement.\n\t\tif ( !data.modelRange && conversionApi.consumable.consume( data.viewItem, { name: true } ) ) {\n\t\t\tconst { modelRange, modelCursor } = conversionApi.convertChildren( data.viewItem, data.modelCursor );\n\n\t\t\tdata.modelRange = modelRange;\n\t\t\tdata.modelCursor = modelCursor;\n\t\t}\n\t};\n}\n\n/**\n * Function factory, creates a converter that converts {@link module:engine/view/text~Text} to {@link module:engine/model/text~Text}.\n *\n * @returns {Function} {@link module:engine/view/text~Text View text} converter.\n */\nexport function convertText() {\n\treturn ( evt, data, conversionApi ) => {\n\t\tif ( conversionApi.schema.checkChild( data.modelCursor, '$text' ) ) {\n\t\t\tif ( conversionApi.consumable.consume( data.viewItem ) ) {\n\t\t\t\tconst text = conversionApi.writer.createText( data.viewItem.data );\n\n\t\t\t\tconversionApi.writer.insert( text, data.modelCursor );\n\n\t\t\t\tdata.modelRange = ModelRange._createFromPositionAndShift( data.modelCursor, text.offsetSize );\n\t\t\t\tdata.modelCursor = data.modelRange.end;\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Function factory, creates a callback function which converts a {@link module:engine/view/selection~Selection\n * view selection} taken from the {@link module:engine/view/document~Document#event:selectionChange} event\n * and sets in on the {@link module:engine/model/document~Document#selection model}.\n *\n * **Note**: because there is no view selection change dispatcher nor any other advanced view selection to model\n * conversion mechanism, the callback should be set directly on view document.\n *\n *\t\tview.document.on( 'selectionChange', convertSelectionChange( modelDocument, mapper ) );\n *\n * @param {module:engine/model/model~Model} model Data model.\n * @param {module:engine/conversion/mapper~Mapper} mapper Conversion mapper.\n * @returns {Function} {@link module:engine/view/document~Document#event:selectionChange} callback function.\n */\nexport function convertSelectionChange( model, mapper ) {\n\treturn ( evt, data ) => {\n\t\tconst viewSelection = data.newSelection;\n\t\tconst modelSelection = new ModelSelection();\n\n\t\tconst ranges = [];\n\n\t\tfor ( const viewRange of viewSelection.getRanges() ) {\n\t\t\tranges.push( mapper.toModelRange( viewRange ) );\n\t\t}\n\n\t\tmodelSelection.setTo( ranges, { backward: viewSelection.isBackward } );\n\n\t\tif ( !modelSelection.isEqual( model.document.selection ) ) {\n\t\t\tmodel.change( writer => {\n\t\t\t\twriter.setSelection( modelSelection );\n\t\t\t} );\n\t\t}\n\t};\n}\n\n// View element to model element conversion helper.\n//\n// See {@link ~UpcastHelpers#elementToElement `.elementToElement()` upcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {module:engine/view/matcher~MatcherPattern} [config.view] Pattern matching all view elements which should be converted. If not\n// set, the converter will fire for every view element.\n// @param {String|module:engine/model/element~Element|Function} config.model Name of the model element, a model element\n// instance or a function that takes a view element and returns a model element. The model element will be inserted in the model.\n// @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n// @returns {Function} Conversion helper.\nfunction upcastElementToElement( config ) {\n\tconfig = cloneDeep( config );\n\n\tconst converter = prepareToElementConverter( config );\n\n\tconst elementName = getViewElementNameFromConfig( config.view );\n\tconst eventName = elementName ? 'element:' + elementName : 'element';\n\n\treturn dispatcher => {\n\t\tdispatcher.on( eventName, converter, { priority: config.converterPriority || 'normal' } );\n\t};\n}\n\n// View element to model attribute conversion helper.\n//\n// See {@link ~UpcastHelpers#elementToAttribute `.elementToAttribute()` upcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.\n// @param {String|Object} config.model Model attribute key or an object with `key` and `value` properties, describing\n// the model attribute. `value` property may be set as a function that takes a view element and returns the value.\n// If `String` is given, the model attribute value will be set to `true`.\n// @param {module:utils/priorities~PriorityString} [config.converterPriority='low'] Converter priority.\n// @returns {Function} Conversion helper.\nfunction upcastElementToAttribute( config ) {\n\tconfig = cloneDeep( config );\n\n\tnormalizeModelAttributeConfig( config );\n\n\tconst converter = prepareToAttributeConverter( config, false );\n\n\tconst elementName = getViewElementNameFromConfig( config.view );\n\tconst eventName = elementName ? 'element:' + elementName : 'element';\n\n\treturn dispatcher => {\n\t\tdispatcher.on( eventName, converter, { priority: config.converterPriority || 'low' } );\n\t};\n}\n\n// View attribute to model attribute conversion helper.\n//\n// See {@link ~UpcastHelpers#attributeToAttribute `.attributeToAttribute()` upcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {String|Object} config.view Specifies which view attribute will be converted. If a `String` is passed,\n// attributes with given key will be converted. If an `Object` is passed, it must have a required `key` property,\n// specifying view attribute key, and may have an optional `value` property, specifying view attribute value and optional `name`\n// property specifying a view element name from/on which the attribute should be converted. `value` can be given as a `String`,\n// a `RegExp` or a function callback, that takes view attribute value as the only parameter and returns `Boolean`.\n// @param {String|Object} config.model Model attribute key or an object with `key` and `value` properties, describing\n// the model attribute. `value` property may be set as a function that takes a view element and returns the value.\n// If `String` is given, the model attribute value will be same as view attribute value.\n// @param {module:utils/priorities~PriorityString} [config.converterPriority='low'] Converter priority.\n// @returns {Function} Conversion helper.\nfunction upcastAttributeToAttribute( config ) {\n\tconfig = cloneDeep( config );\n\n\tlet viewKey = null;\n\n\tif ( typeof config.view == 'string' || config.view.key ) {\n\t\tviewKey = normalizeViewAttributeKeyValueConfig( config );\n\t}\n\n\tnormalizeModelAttributeConfig( config, viewKey );\n\n\tconst converter = prepareToAttributeConverter( config, true );\n\n\treturn dispatcher => {\n\t\tdispatcher.on( 'element', converter, { priority: config.converterPriority || 'low' } );\n\t};\n}\n\n// View element to model marker conversion helper.\n//\n// See {@link ~UpcastHelpers#elementToMarker `.elementToMarker()` upcast helper} for examples.\n//\n// @param {Object} config Conversion configuration.\n// @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.\n// @param {String|Function} config.model Name of the model marker, or a function that takes a view element and returns\n// a model marker name.\n// @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.\n// @returns {Function} Conversion helper.\nfunction upcastElementToMarker( config ) {\n\tconfig = cloneDeep( config );\n\n\tnormalizeToMarkerConfig( config );\n\n\treturn upcastElementToElement( config );\n}\n\n// Helper function for from-view-element conversion. Checks if `config.view` directly specifies converted view element's name\n// and if so, returns it.\n//\n// @param {Object} config Conversion view config.\n// @returns {String|null} View element name or `null` if name is not directly set.\nfunction getViewElementNameFromConfig( viewConfig ) {\n\tif ( typeof viewConfig == 'string' ) {\n\t\treturn viewConfig;\n\t}\n\n\tif ( typeof viewConfig == 'object' && typeof viewConfig.name == 'string' ) {\n\t\treturn viewConfig.name;\n\t}\n\n\treturn null;\n}\n\n// Helper for to-model-element conversion. Takes a config object and returns a proper converter function.\n//\n// @param {Object} config Conversion configuration.\n// @returns {Function} View to model converter.\nfunction prepareToElementConverter( config ) {\n\tconst matcher = config.view ? new Matcher( config.view ) : null;\n\n\treturn ( evt, data, conversionApi ) => {\n\t\tlet match = {};\n\n\t\t// If `config.view` has not been passed do not try matching. In this case, the converter should fire for all elements.\n\t\tif ( matcher ) {\n\t\t\t// This will be usually just one pattern but we support matchers with many patterns too.\n\t\t\tconst matcherResult = matcher.match( data.viewItem );\n\n\t\t\t// If there is no match, this callback should not do anything.\n\t\t\tif ( !matcherResult ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmatch = matcherResult.match;\n\t\t}\n\n\t\t// Force consuming element's name.\n\t\tmatch.name = true;\n\n\t\t// Create model element basing on config.\n\t\tconst modelElement = getModelElement( config.model, data.viewItem, conversionApi.writer );\n\n\t\t// Do not convert if element building function returned falsy value.\n\t\tif ( !modelElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// When element was already consumed then skip it.\n\t\tif ( !conversionApi.consumable.test( data.viewItem, match ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Find allowed parent for element that we are going to insert.\n\t\t// If current parent does not allow to insert element but one of the ancestors does\n\t\t// then split nodes to allowed parent.\n\t\tconst splitResult = conversionApi.splitToAllowedParent( modelElement, data.modelCursor );\n\n\t\t// When there is no split result it means that we can't insert element to model tree, so let's skip it.\n\t\tif ( !splitResult ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Insert element on allowed position.\n\t\tconversionApi.writer.insert( modelElement, splitResult.position );\n\n\t\t// Convert children and insert to element.\n\t\tconversionApi.convertChildren( data.viewItem, conversionApi.writer.createPositionAt( modelElement, 0 ) );\n\n\t\t// Consume appropriate value from consumable values list.\n\t\tconversionApi.consumable.consume( data.viewItem, match );\n\n\t\tconst parts = conversionApi.getSplitParts( modelElement );\n\n\t\t// Set conversion result range.\n\t\tdata.modelRange = new ModelRange(\n\t\t\tconversionApi.writer.createPositionBefore( modelElement ),\n\t\t\tconversionApi.writer.createPositionAfter( parts[ parts.length - 1 ] )\n\t\t);\n\n\t\t// Now we need to check where the `modelCursor` should be.\n\t\tif ( splitResult.cursorParent ) {\n\t\t\t// If we split parent to insert our element then we want to continue conversion in the new part of the split parent.\n\t\t\t//\n\t\t\t// before: <allowed><notAllowed>foo[]</notAllowed></allowed>\n\t\t\t// after: <allowed><notAllowed>foo</notAllowed><converted></converted><notAllowed>[]</notAllowed></allowed>\n\n\t\t\tdata.modelCursor = conversionApi.writer.createPositionAt( splitResult.cursorParent, 0 );\n\t\t} else {\n\t\t\t// Otherwise just continue after inserted element.\n\n\t\t\tdata.modelCursor = data.modelRange.end;\n\t\t}\n\t};\n}\n\n// Helper function for upcasting-to-element converter. Takes the model configuration, the converted view element\n// and a writer instance and returns a model element instance to be inserted in the model.\n//\n// @param {String|Function|module:engine/model/element~Element} model Model conversion configuration.\n// @param {module:engine/view/node~Node} input The converted view node.\n// @param {module:engine/model/writer~Writer} writer A writer instance to use to create the model element.\nfunction getModelElement( model, input, writer ) {\n\tif ( model instanceof Function ) {\n\t\treturn model( input, writer );\n\t} else {\n\t\treturn writer.createElement( model );\n\t}\n}\n\n// Helper function view-attribute-to-model-attribute helper. Normalizes `config.view` which was set as `String` or\n// as an `Object` with `key`, `value` and `name` properties. Normalized `config.view` has is compatible with\n// {@link module:engine/view/matcher~MatcherPattern}.\n//\n// @param {Object} config Conversion config.\n// @returns {String} Key of the converted view attribute.\nfunction normalizeViewAttributeKeyValueConfig( config ) {\n\tif ( typeof config.view == 'string' ) {\n\t\tconfig.view = { key: config.view };\n\t}\n\n\tconst key = config.view.key;\n\tlet normalized;\n\n\tif ( key == 'class' || key == 'style' ) {\n\t\tconst keyName = key == 'class' ? 'classes' : 'styles';\n\n\t\tnormalized = {\n\t\t\t[ keyName ]: config.view.value\n\t\t};\n\t} else {\n\t\tconst value = typeof config.view.value == 'undefined' ? /[\\s\\S]*/ : config.view.value;\n\n\t\tnormalized = {\n\t\t\tattributes: {\n\t\t\t\t[ key ]: value\n\t\t\t}\n\t\t};\n\t}\n\n\tif ( config.view.name ) {\n\t\tnormalized.name = config.view.name;\n\t}\n\n\tconfig.view = normalized;\n\n\treturn key;\n}\n\n// Helper function that normalizes `config.model` in from-model-attribute conversion. `config.model` can be set\n// as a `String`, an `Object` with only `key` property or an `Object` with `key` and `value` properties. Normalized\n// `config.model` is an `Object` with `key` and `value` properties.\n//\n// @param {Object} config Conversion config.\n// @param {String} viewAttributeKeyToCopy Key of the converted view attribute. If it is set, model attribute value\n// will be equal to view attribute value.\nfunction normalizeModelAttributeConfig( config, viewAttributeKeyToCopy = null ) {\n\tconst defaultModelValue = viewAttributeKeyToCopy === null ? true : viewElement => viewElement.getAttribute( viewAttributeKeyToCopy );\n\n\tconst key = typeof config.model != 'object' ? config.model : config.model.key;\n\tconst value = typeof config.model != 'object' || typeof config.model.value == 'undefined' ? defaultModelValue : config.model.value;\n\n\tconfig.model = { key, value };\n}\n\n// Helper for to-model-attribute conversion. Takes the model attribute name and conversion configuration and returns\n// a proper converter function.\n//\n// @param {String} modelAttributeKey The key of the model attribute to set on a model node.\n// @param {Object|Array.<Object>} config Conversion configuration. It is possible to provide multiple configurations in an array.\n// @param {Boolean} shallow If set to `true` the attribute will be set only on top-level nodes. Otherwise, it will be set\n// on all elements in the range.\nfunction prepareToAttributeConverter( config, shallow ) {\n\tconst matcher = new Matcher( config.view );\n\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst match = matcher.match( data.viewItem );\n\n\t\t// If there is no match, this callback should not do anything.\n\t\tif ( !match ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelKey = config.model.key;\n\t\tconst modelValue = typeof config.model.value == 'function' ? config.model.value( data.viewItem ) : config.model.value;\n\n\t\t// Do not convert if attribute building function returned falsy value.\n\t\tif ( modelValue === null ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( onlyViewNameIsDefined( config.view, data.viewItem ) ) {\n\t\t\tmatch.match.name = true;\n\t\t} else {\n\t\t\t// Do not test or consume `name` consumable.\n\t\t\tdelete match.match.name;\n\t\t}\n\n\t\t// Try to consume appropriate values from consumable values list.\n\t\tif ( !conversionApi.consumable.test( data.viewItem, match.match ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Since we are converting to attribute we need an range on which we will set the attribute.\n\t\t// If the range is not created yet, we will create it.\n\t\tif ( !data.modelRange ) {\n\t\t\t// Convert children and set conversion result as a current data.\n\t\t\tdata = Object.assign( data, conversionApi.convertChildren( data.viewItem, data.modelCursor ) );\n\t\t}\n\n\t\t// Set attribute on current `output`. `Schema` is checked inside this helper function.\n\t\tconst attributeWasSet = setAttributeOn( data.modelRange, { key: modelKey, value: modelValue }, shallow, conversionApi );\n\n\t\tif ( attributeWasSet ) {\n\t\t\tconversionApi.consumable.consume( data.viewItem, match.match );\n\t\t}\n\t};\n}\n\n// Helper function that checks if element name should be consumed in attribute converters.\n//\n// @param {Object} config Conversion view config.\n// @returns {Boolean}\nfunction onlyViewNameIsDefined( viewConfig, viewItem ) {\n\t// https://github.com/ckeditor/ckeditor5-engine/issues/1786\n\tconst configToTest = typeof viewConfig == 'function' ? viewConfig( viewItem ) : viewConfig;\n\n\tif ( typeof configToTest == 'object' && !getViewElementNameFromConfig( configToTest ) ) {\n\t\treturn false;\n\t}\n\n\treturn !configToTest.classes && !configToTest.attributes && !configToTest.styles;\n}\n\n// Helper function for to-model-attribute converter. Sets model attribute on given range. Checks {@link module:engine/model/schema~Schema}\n// to ensure proper model structure.\n//\n// @param {module:engine/model/range~Range} modelRange Model range on which attribute should be set.\n// @param {Object} modelAttribute Model attribute to set.\n// @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion API.\n// @param {Boolean} shallow If set to `true` the attribute will be set only on top-level nodes. Otherwise, it will be set\n// on all elements in the range.\n// @returns {Boolean} `true` if attribute was set on at least one node from given `modelRange`.\nfunction setAttributeOn( modelRange, modelAttribute, shallow, conversionApi ) {\n\tlet result = false;\n\n\t// Set attribute on each item in range according to Schema.\n\tfor ( const node of Array.from( modelRange.getItems( { shallow } ) ) ) {\n\t\tif ( conversionApi.schema.checkAttribute( node, modelAttribute.key ) ) {\n\t\t\tconversionApi.writer.setAttribute( modelAttribute.key, modelAttribute.value, node );\n\n\t\t\tresult = true;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// Helper function for upcasting-to-marker conversion. Takes the config in a format requested by `upcastElementToMarker()`\n// function and converts it to a format that is supported by `_upcastElementToElement()` function.\n//\n// @param {Object} config Conversion configuration.\nfunction normalizeToMarkerConfig( config ) {\n\tconst oldModel = config.model;\n\n\tconfig.model = ( viewElement, modelWriter ) => {\n\t\tconst markerName = typeof oldModel == 'string' ? oldModel : oldModel( viewElement );\n\n\t\treturn modelWriter.createElement( '$marker', { 'data-name': markerName } );\n\t};\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/controller/editingcontroller\n */\n\nimport RootEditableElement from '../view/rooteditableelement';\nimport View from '../view/view';\nimport Mapper from '../conversion/mapper';\nimport DowncastDispatcher from '../conversion/downcastdispatcher';\nimport { clearAttributes, convertCollapsedSelection, convertRangeSelection, insertText, remove } from '../conversion/downcasthelpers';\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport { convertSelectionChange } from '../conversion/upcasthelpers';\n\n/**\n * Controller for the editing pipeline. The editing pipeline controls {@link ~EditingController#model model} rendering,\n * including selection handling. It also creates the {@link ~EditingController#view view} which builds a\n * browser-independent virtualization over the DOM elements. The editing controller also attaches default converters.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class EditingController {\n\t/**\n\t * Creates an editing controller instance.\n\t *\n\t * @param {module:engine/model/model~Model} model Editing model.\n\t */\n\tconstructor( model ) {\n\t\t/**\n\t\t * Editor model.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/model~Model}\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * Editing view controller.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/view/view~View}\n\t\t */\n\t\tthis.view = new View();\n\n\t\t/**\n\t\t * Mapper which describes the model-view binding.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/conversion/mapper~Mapper}\n\t\t */\n\t\tthis.mapper = new Mapper();\n\n\t\t/**\n\t\t * Downcast dispatcher that converts changes from the model to {@link #view the editing view}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/conversion/downcastdispatcher~DowncastDispatcher} #downcastDispatcher\n\t\t */\n\t\tthis.downcastDispatcher = new DowncastDispatcher( {\n\t\t\tmapper: this.mapper\n\t\t} );\n\n\t\tconst doc = this.model.document;\n\t\tconst selection = doc.selection;\n\t\tconst markers = this.model.markers;\n\n\t\t// When plugins listen on model changes (on selection change, post fixers, etc) and change the view as a result of\n\t\t// model's change, they might trigger view rendering before the conversion is completed (e.g. before the selection\n\t\t// is converted). We disable rendering for the length of the outermost model change() block to prevent that.\n\t\t//\n\t\t// See https://github.com/ckeditor/ckeditor5-engine/issues/1528\n\t\tthis.listenTo( this.model, '_beforeChanges', () => {\n\t\t\tthis.view._disableRendering( true );\n\t\t}, { priority: 'highest' } );\n\n\t\tthis.listenTo( this.model, '_afterChanges', () => {\n\t\t\tthis.view._disableRendering( false );\n\t\t}, { priority: 'lowest' } );\n\n\t\t// Whenever model document is changed, convert those changes to the view (using model.Document#differ).\n\t\t// Do it on 'low' priority, so changes are converted after other listeners did their job.\n\t\t// Also convert model selection.\n\t\tthis.listenTo( doc, 'change', () => {\n\t\t\tthis.view.change( writer => {\n\t\t\t\tthis.downcastDispatcher.convertChanges( doc.differ, markers, writer );\n\t\t\t\tthis.downcastDispatcher.convertSelection( selection, markers, writer );\n\t\t\t} );\n\t\t}, { priority: 'low' } );\n\n\t\t// Convert selection from the view to the model when it changes in the view.\n\t\tthis.listenTo( this.view.document, 'selectionChange', convertSelectionChange( this.model, this.mapper ) );\n\n\t\t// Attach default model converters.\n\t\tthis.downcastDispatcher.on( 'insert:$text', insertText(), { priority: 'lowest' } );\n\t\tthis.downcastDispatcher.on( 'remove', remove(), { priority: 'low' } );\n\n\t\t// Attach default model selection converters.\n\t\tthis.downcastDispatcher.on( 'selection', clearAttributes(), { priority: 'low' } );\n\t\tthis.downcastDispatcher.on( 'selection', convertRangeSelection(), { priority: 'low' } );\n\t\tthis.downcastDispatcher.on( 'selection', convertCollapsedSelection(), { priority: 'low' } );\n\n\t\t// Binds {@link module:engine/view/document~Document#roots view roots collection} to\n\t\t// {@link module:engine/model/document~Document#roots model roots collection} so creating\n\t\t// model root automatically creates corresponding view root.\n\t\tthis.view.document.roots.bindTo( this.model.document.roots ).using( root => {\n\t\t\t// $graveyard is a special root that has no reflection in the view.\n\t\t\tif ( root.rootName == '$graveyard' ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst viewRoot = new RootEditableElement( root.name );\n\n\t\t\tviewRoot.rootName = root.rootName;\n\t\t\tviewRoot._document = this.view.document;\n\t\t\tthis.mapper.bindElements( root, viewRoot );\n\n\t\t\treturn viewRoot;\n\t\t} );\n\t}\n\n\t/**\n\t * Removes all event listeners attached to the `EditingController`. Destroys all objects created\n\t * by `EditingController` that need to be destroyed.\n\t */\n\tdestroy() {\n\t\tthis.view.destroy();\n\t\tthis.stopListening();\n\t}\n}\n\nmix( EditingController, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 core/plugincollection\n */\n\n/* globals console */\n\nimport CKEditorError, { attachLinkToDocumentation } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Manages a list of CKEditor plugins, including loading, resolving dependencies and initialization.\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class PluginCollection {\n\t/**\n\t * Creates an instance of the PluginCollection class.\n\t * Allows loading and initializing plugins and their dependencies.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor\n\t * @param {Array.<Function>} [availablePlugins] Plugins (constructors) which the collection will be able to use\n\t * when {@link module:core/plugincollection~PluginCollection#init} is used with plugin names (strings, instead of constructors).\n\t * Usually, the editor will pass its built-in plugins to the collection so they can later be\n\t * used in `config.plugins` or `config.removePlugins` by names.\n\t */\n\tconstructor( editor, availablePlugins = [] ) {\n\t\t/**\n\t\t * @protected\n\t\t * @member {module:core/editor/editor~Editor} module:core/plugin~PluginCollection#_editor\n\t\t */\n\t\tthis._editor = editor;\n\n\t\t/**\n\t\t * Map of plugin constructors which can be retrieved by their names.\n\t\t *\n\t\t * @protected\n\t\t * @member {Map.<String|Function,Function>} module:core/plugin~PluginCollection#_availablePlugins\n\t\t */\n\t\tthis._availablePlugins = new Map();\n\n\t\t/**\n\t\t * @protected\n\t\t * @member {Map} module:core/plugin~PluginCollection#_plugins\n\t\t */\n\t\tthis._plugins = new Map();\n\n\t\tfor ( const PluginConstructor of availablePlugins ) {\n\t\t\tthis._availablePlugins.set( PluginConstructor, PluginConstructor );\n\n\t\t\tif ( PluginConstructor.pluginName ) {\n\t\t\t\tthis._availablePlugins.set( PluginConstructor.pluginName, PluginConstructor );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Returns `[ PluginConstructor, pluginInstance ]` pairs.\n\t *\n\t * @returns {Iterable.<Array>}\n\t */\n\t* [ Symbol.iterator ]() {\n\t\tfor ( const entry of this._plugins ) {\n\t\t\tif ( typeof entry[ 0 ] == 'function' ) {\n\t\t\t\tyield entry;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Gets the plugin instance by its constructor or name.\n\t *\n\t *\t\t// Check if 'Clipboard' plugin was loaded.\n\t *\t\tif ( editor.plugins.has( 'Clipboard' ) ) {\n\t *\t\t\t// Get clipboard plugin instance\n\t *\t\t\tconst clipboard = editor.plugins.get( 'Clipboard' );\n\t *\n\t *\t\t\tthis.listenTo( clipboard, 'inputTransformation', ( evt, data ) => {\n\t *\t\t\t\t// Do something on clipboard input.\n\t *\t\t\t} );\n\t *\t\t}\n\t *\n\t * **Note**: This method will throw error if plugin is not loaded. Use `{@link #has editor.plugins.has()}`\n\t * to check if plugin is available.\n\t *\n\t * @param {Function|String} key The plugin constructor or {@link module:core/plugin~PluginInterface.pluginName name}.\n\t * @returns {module:core/plugin~PluginInterface}\n\t */\n\tget( key ) {\n\t\tconst plugin = this._plugins.get( key );\n\n\t\tif ( !plugin ) {\n\t\t\t/**\n\t\t\t * The plugin is not loaded and could not be obtained.\n\t\t\t *\n\t\t\t * Plugin classes (constructors) need to be provided to the editor and must be loaded before they can be obtained from\n\t\t\t * the plugin collection.\n\t\t\t * This is usually done in CKEditor 5 builds by setting the {@link module:core/editor/editor~Editor.builtinPlugins}\n\t\t\t * property.\n\t\t\t *\n\t\t\t * **Note**: You can use `{@link module:core/plugincollection~PluginCollection#has editor.plugins.has()}`\n\t\t\t * to check if plugin was loaded.\n\t\t\t *\n\t\t\t * @error plugincollection-plugin-not-loaded\n\t\t\t * @param {String} plugin The name of the plugin which is not loaded.\n\t\t\t */\n\t\t\tconst errorMsg = 'plugincollection-plugin-not-loaded: The requested plugin is not loaded.';\n\n\t\t\tlet pluginName = key;\n\n\t\t\tif ( typeof key == 'function' ) {\n\t\t\t\tpluginName = key.pluginName || key.name;\n\t\t\t}\n\n\t\t\tthrow new CKEditorError( errorMsg, this._editor, { plugin: pluginName } );\n\t\t}\n\n\t\treturn plugin;\n\t}\n\n\t/**\n\t * Checks if plugin is loaded.\n\t *\n\t *\t\t// Check if 'Clipboard' plugin was loaded.\n\t *\t\tif ( editor.plugins.has( 'Clipboard' ) ) {\n\t *\t\t\t// Now use clipboard plugin instance:\n\t *\t\t\tconst clipboard = editor.plugins.get( 'Clipboard' );\n\t *\n\t *\t\t\t// ...\n\t *\t\t}\n\t *\n\t * @param {Function|String} key The plugin constructor or {@link module:core/plugin~PluginInterface.pluginName name}.\n\t * @returns {Boolean}\n\t */\n\thas( key ) {\n\t\treturn this._plugins.has( key );\n\t}\n\n\t/**\n\t * Initializes a set of plugins and adds them to the collection.\n\t *\n\t * @param {Array.<Function|String>} plugins An array of {@link module:core/plugin~PluginInterface plugin constructors}\n\t * or {@link module:core/plugin~PluginInterface.pluginName plugin names}. The second option (names) works only if\n\t * `availablePlugins` were passed to the {@link #constructor}.\n\t * @param {Array.<String|Function>} [removePlugins] Names of plugins or plugin constructors\n\t * that should not be loaded (despite being specified in the `plugins` array).\n\t * @returns {Promise.<module:core/plugin~LoadedPlugins>} A promise which gets resolved once all plugins are loaded\n\t * and available in the collection.\n\t */\n\tinit( plugins, removePlugins = [] ) {\n\t\tconst that = this;\n\t\tconst editor = this._editor;\n\t\tconst loading = new Set();\n\t\tconst loaded = [];\n\n\t\tconst pluginConstructors = mapToAvailableConstructors( plugins );\n\t\tconst removePluginConstructors = mapToAvailableConstructors( removePlugins );\n\t\tconst missingPlugins = getMissingPluginNames( plugins );\n\n\t\tif ( missingPlugins ) {\n\t\t\t/**\n\t\t\t * Some plugins are not available and could not be loaded.\n\t\t\t *\n\t\t\t * Plugin classes (constructors) need to be provided to the editor before they can be loaded by name.\n\t\t\t * This is usually done in CKEditor 5 builds by setting the {@link module:core/editor/editor~Editor.builtinPlugins}\n\t\t\t * property.\n\t\t\t *\n\t\t\t * **If you see this warning when using one of the {@glink builds/index CKEditor 5 Builds}**, it means\n\t\t\t * that you try to enable a plugin which was not included in that build. This may be due to a typo\n\t\t\t * in the plugin name or simply because that plugin is not a part of this build. In the latter scenario,\n\t\t\t * read more about {@glink builds/guides/development/custom-builds custom builds}.\n\t\t\t *\n\t\t\t * **If you see this warning when using one of the editor creators directly** (not a build), then it means\n\t\t\t * that you tried loading plugins by name. However, unlike CKEditor 4, CKEditor 5 does not implement a \"plugin loader\".\n\t\t\t * This means that CKEditor 5 does not know where to load the plugin modules from. Therefore, you need to\n\t\t\t * provide each plugin through reference (as a constructor function). Check out the examples in\n\t\t\t * {@glink builds/guides/integration/advanced-setup#scenario-2-building-from-source \"Building from source\"}.\n\t\t\t *\n\t\t\t * @error plugincollection-plugin-not-found\n\t\t\t * @param {Array.<String>} plugins The name of the plugins which could not be loaded.\n\t\t\t */\n\t\t\tconst errorMsg = 'plugincollection-plugin-not-found: Some plugins are not available and could not be loaded.';\n\n\t\t\t// Log the error so it's more visible on the console. Hopefully, for better DX.\n\t\t\tconsole.error( attachLinkToDocumentation( errorMsg ), { plugins: missingPlugins } );\n\n\t\t\treturn Promise.reject( new CKEditorError( errorMsg, this._editor, { plugins: missingPlugins } ) );\n\t\t}\n\n\t\treturn Promise.all( pluginConstructors.map( loadPlugin ) )\n\t\t\t.then( () => initPlugins( loaded, 'init' ) )\n\t\t\t.then( () => initPlugins( loaded, 'afterInit' ) )\n\t\t\t.then( () => loaded );\n\n\t\tfunction loadPlugin( PluginConstructor ) {\n\t\t\tif ( removePluginConstructors.includes( PluginConstructor ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// The plugin is already loaded or being loaded - do nothing.\n\t\t\tif ( that._plugins.has( PluginConstructor ) || loading.has( PluginConstructor ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treturn instantiatePlugin( PluginConstructor )\n\t\t\t\t.catch( err => {\n\t\t\t\t\t/**\n\t\t\t\t\t * It was not possible to load the plugin.\n\t\t\t\t\t *\n\t\t\t\t\t * This is a generic error logged to the console when a JavaSript error is thrown during the initialization\n\t\t\t\t\t * of one of the plugins.\n\t\t\t\t\t *\n\t\t\t\t\t * If you correctly handled the promise returned by the editor's `create()` method (like shown below)\n\t\t\t\t\t * you will find the original error logged to the console, too:\n\t\t\t\t\t *\n\t\t\t\t\t *\t\tClassicEditor.create( document.getElementById( 'editor' ) )\n\t\t\t\t\t *\t\t\t.then( editor => {\n\t\t\t\t\t *\t\t\t\t// ...\n\t\t\t\t\t * \t\t\t} )\n\t\t\t\t\t *\t\t\t.catch( error => {\n\t\t\t\t\t *\t\t\t\tconsole.error( error );\n\t\t\t\t\t *\t\t\t} );\n\t\t\t\t\t *\n\t\t\t\t\t * @error plugincollection-load\n\t\t\t\t\t * @param {String} plugin The name of the plugin that could not be loaded.\n\t\t\t\t\t */\n\t\t\t\t\tconsole.error( attachLinkToDocumentation(\n\t\t\t\t\t\t'plugincollection-load: It was not possible to load the plugin.'\n\t\t\t\t\t), { plugin: PluginConstructor } );\n\n\t\t\t\t\tthrow err;\n\t\t\t\t} );\n\t\t}\n\n\t\tfunction initPlugins( loadedPlugins, method ) {\n\t\t\treturn loadedPlugins.reduce( ( promise, plugin ) => {\n\t\t\t\tif ( !plugin[ method ] ) {\n\t\t\t\t\treturn promise;\n\t\t\t\t}\n\n\t\t\t\treturn promise.then( plugin[ method ].bind( plugin ) );\n\t\t\t}, Promise.resolve() );\n\t\t}\n\n\t\tfunction instantiatePlugin( PluginConstructor ) {\n\t\t\treturn new Promise( resolve => {\n\t\t\t\tloading.add( PluginConstructor );\n\n\t\t\t\tif ( PluginConstructor.requires ) {\n\t\t\t\t\tPluginConstructor.requires.forEach( RequiredPluginConstructorOrName => {\n\t\t\t\t\t\tconst RequiredPluginConstructor = getPluginConstructor( RequiredPluginConstructorOrName );\n\n\t\t\t\t\t\tif ( removePlugins.includes( RequiredPluginConstructor ) ) {\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Cannot load a plugin because one of its dependencies is listed in the `removePlugins` option.\n\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t * @error plugincollection-required\n\t\t\t\t\t\t\t * @param {Function} plugin The required plugin.\n\t\t\t\t\t\t\t * @param {Function} requiredBy The parent plugin.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t\t\t\t'plugincollection-required: Cannot load a plugin because one of its dependencies is listed in' +\n\t\t\t\t\t\t\t\t'the `removePlugins` option.',\n\t\t\t\t\t\t\t\teditor,\n\t\t\t\t\t\t\t\t{ plugin: RequiredPluginConstructor, requiredBy: PluginConstructor }\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tloadPlugin( RequiredPluginConstructor );\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\tconst plugin = new PluginConstructor( editor );\n\t\t\t\tthat._add( PluginConstructor, plugin );\n\t\t\t\tloaded.push( plugin );\n\n\t\t\t\tresolve();\n\t\t\t} );\n\t\t}\n\n\t\tfunction getPluginConstructor( PluginConstructorOrName ) {\n\t\t\tif ( typeof PluginConstructorOrName == 'function' ) {\n\t\t\t\treturn PluginConstructorOrName;\n\t\t\t}\n\n\t\t\treturn that._availablePlugins.get( PluginConstructorOrName );\n\t\t}\n\n\t\tfunction getMissingPluginNames( plugins ) {\n\t\t\tconst missingPlugins = [];\n\n\t\t\tfor ( const pluginNameOrConstructor of plugins ) {\n\t\t\t\tif ( !getPluginConstructor( pluginNameOrConstructor ) ) {\n\t\t\t\t\tmissingPlugins.push( pluginNameOrConstructor );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn missingPlugins.length ? missingPlugins : null;\n\t\t}\n\n\t\tfunction mapToAvailableConstructors( plugins ) {\n\t\t\treturn plugins\n\t\t\t\t.map( pluginNameOrConstructor => getPluginConstructor( pluginNameOrConstructor ) )\n\t\t\t\t.filter( PluginConstructor => !!PluginConstructor );\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all loaded plugins.\n\t *\n\t * @returns {Promise}\n\t */\n\tdestroy() {\n\t\tconst promises = Array.from( this )\n\t\t\t.map( ( [ , pluginInstance ] ) => pluginInstance )\n\t\t\t.filter( pluginInstance => typeof pluginInstance.destroy == 'function' )\n\t\t\t.map( pluginInstance => pluginInstance.destroy() );\n\n\t\treturn Promise.all( promises );\n\t}\n\n\t/**\n\t * Adds the plugin to the collection. Exposed mainly for testing purposes.\n\t *\n\t * @protected\n\t * @param {Function} PluginConstructor The plugin constructor.\n\t * @param {module:core/plugin~PluginInterface} plugin The instance of the plugin.\n\t */\n\t_add( PluginConstructor, plugin ) {\n\t\tthis._plugins.set( PluginConstructor, plugin );\n\n\t\tconst pluginName = PluginConstructor.pluginName;\n\n\t\tif ( !pluginName ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._plugins.has( pluginName ) ) {\n\t\t\t/**\n\t\t\t * Two plugins with the same {@link module:core/plugin~PluginInterface.pluginName} were loaded.\n\t\t\t * This will lead to runtime conflicts between these plugins.\n\t\t\t *\n\t\t\t * In practice, this warning usually means that new plugins were added to an existing CKEditor 5 build.\n\t\t\t * Plugins should always be added to a source version of the editor (`@ckeditor/ckeditor5-editor-*`),\n\t\t\t * not to an editor imported from one of the `@ckeditor/ckeditor5-build-*` packages.\n\t\t\t *\n\t\t\t * Check your import paths and the list of plugins passed to\n\t\t\t * {@link module:core/editor/editor~Editor.create `Editor.create()`}\n\t\t\t * or specified in {@link module:core/editor/editor~Editor.builtinPlugins `Editor.builtinPlugins`}.\n\t\t\t *\n\t\t\t * The second option is that your `node_modules/` directory contains duplicated versions of the same\n\t\t\t * CKEditor 5 packages. Normally, on clean installations, npm deduplicates packages in `node_modules/`, so\n\t\t\t * it may be enough to call `rm -rf node_modules && npm i`. However, if you installed conflicting versions\n\t\t\t * of packages, their dependencies may need to be installed in more than one version which may lead to this\n\t\t\t * warning.\n\t\t\t *\n\t\t\t * Technically speaking, this error occurs because after adding a plugin to an existing editor build\n\t\t\t * dependencies of this plugin are being duplicated.\n\t\t\t * They are already built into that editor build and now get added for the second time as dependencies\n\t\t\t * of the plugin you are installing.\n\t\t\t *\n\t\t\t * Read more about {@glink builds/guides/integration/installing-plugins installing plugins}.\n\t\t\t *\n\t\t\t * @error plugincollection-plugin-name-conflict\n\t\t\t * @param {String} pluginName The duplicated plugin name.\n\t\t\t * @param {Function} plugin1 The first plugin constructor.\n\t\t\t * @param {Function} plugin2 The second plugin constructor.\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'plugincollection-plugin-name-conflict: Two plugins with the same name were loaded.',\n\t\t\t\tnull,\n\t\t\t\t{ pluginName, plugin1: this._plugins.get( pluginName ).constructor, plugin2: PluginConstructor }\n\t\t\t);\n\t\t}\n\n\t\tthis._plugins.set( pluginName, plugin );\n\t}\n}\n\nmix( PluginCollection, EmitterMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 core/commandcollection\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Collection of commands. Its instance is available in {@link module:core/editor/editor~Editor#commands `editor.commands`}.\n */\nexport default class CommandCollection {\n\t/**\n\t * Creates collection instance.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Command map.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._commands = new Map();\n\t}\n\n\t/**\n\t * Registers a new command.\n\t *\n\t * @param {String} commandName The name of the command.\n\t * @param {module:core/command~Command} command\n\t */\n\tadd( commandName, command ) {\n\t\tthis._commands.set( commandName, command );\n\t}\n\n\t/**\n\t * Retrieves a command from the collection.\n\t *\n\t * @param {String} commandName The name of the command.\n\t * @returns {module:core/command~Command}\n\t */\n\tget( commandName ) {\n\t\treturn this._commands.get( commandName );\n\t}\n\n\t/**\n\t * Executes a command.\n\t *\n\t * @param {String} commandName The name of the command.\n\t * @param {*} [...commandParams] Command parameters.\n\t */\n\texecute( commandName, ...args ) {\n\t\tconst command = this.get( commandName );\n\n\t\tif ( !command ) {\n\t\t\t/**\n\t\t\t * Command does not exist.\n\t\t\t *\n\t\t\t * @error commandcollection-command-not-found\n\t\t\t * @param {String} commandName Name of the command.\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'commandcollection-command-not-found: Command does not exist.', this, { commandName } );\n\t\t}\n\n\t\tcommand.execute( ...args );\n\t}\n\n\t/**\n\t * Returns iterator of command names.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\t* names() {\n\t\tyield* this._commands.keys();\n\t}\n\n\t/**\n\t * Returns iterator of command instances.\n\t *\n\t * @returns {Iterable.<module:core/command~Command>}\n\t */\n\t* commands() {\n\t\tyield* this._commands.values();\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Returns `[ commandName, commandInstance ]` pairs.\n\t *\n\t * @returns {Iterable.<Array>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this._commands[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Destroys all collection commands.\n\t */\n\tdestroy() {\n\t\tfor ( const command of this.commands() ) {\n\t\t\tcommand.destroy();\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* globals window */\n\n/**\n * @module utils/translation-service\n */\n\n/* istanbul ignore else */\nif ( !window.CKEDITOR_TRANSLATIONS ) {\n\twindow.CKEDITOR_TRANSLATIONS = {};\n}\n\n/**\n * Adds translations to existing ones.\n * These translations will later be available for the {@link module:utils/translation-service~translate `translate()`} function.\n *\n *\t\tadd( 'pl', {\n *\t\t\t'OK': 'OK',\n *\t\t\t'Cancel [context: reject]': 'Anuluj'\n *\t\t} );\n *\n * If you cannot import this function from this module (e.g. because you use a CKEditor 5 build), then you can\n * still add translations by extending the global `window.CKEDITOR_TRANSLATIONS` object by using a function like\n * the one below:\n *\n *\t\tfunction addTranslations( language, translations ) {\n *\t\t\tif ( !window.CKEDITOR_TRANSLATIONS ) {\n *\t\t\t\twindow.CKEDITOR_TRANSLATIONS = {};\n *\t\t\t}\n *\n *\t\t\tconst dictionary = window.CKEDITOR_TRANSLATIONS[ language ] || ( window.CKEDITOR_TRANSLATIONS[ language ] = {} );\n *\n *\t\t\t// Extend the dictionary for the given language.\n *\t\t\tObject.assign( dictionary, translations );\n *\t\t}\n *\n * @param {String} language Target language.\n * @param {Object.<String, String>} translations Translations which will be added to the dictionary.\n */\nexport function add( language, translations ) {\n\tconst dictionary = window.CKEDITOR_TRANSLATIONS[ language ] || ( window.CKEDITOR_TRANSLATIONS[ language ] = {} );\n\n\tObject.assign( dictionary, translations );\n}\n\n/**\n * Translates string if the translation of the string was previously added to the dictionary.\n * See {@link module:utils/translation-service Translation Service}.\n * This happens in a multi-language mode were translation modules are created by the bundler.\n *\n * When no translation is defined in the dictionary or the dictionary doesn't exist this function returns\n * the original string without the `'[context: ]'` (happens in development and single-language modes).\n *\n * In a single-language mode (when values passed to `t()` were replaced with target language strings) the dictionary\n * is left empty, so this function will return the original strings always.\n *\n *\t\ttranslate( 'pl', 'Cancel [context: reject]' );\n *\n * @param {String} language Target language.\n * @param {String} translationKey String that will be translated.\n * @returns {String} Translated sentence.\n */\nexport function translate( language, translationKey ) {\n\tconst numberOfLanguages = getNumberOfLanguages();\n\n\tif ( numberOfLanguages === 1 ) {\n\t\t// Override the language to the only supported one.\n\t\t// This can't be done in the `Locale` class, because the translations comes after the `Locale` class initialization.\n\t\tlanguage = Object.keys( window.CKEDITOR_TRANSLATIONS )[ 0 ];\n\t}\n\n\tif ( numberOfLanguages === 0 || !hasTranslation( language, translationKey ) ) {\n\t\treturn translationKey.replace( / \\[context: [^\\]]+\\]$/, '' );\n\t}\n\n\tconst dictionary = window.CKEDITOR_TRANSLATIONS[ language ];\n\n\t// In case of missing translations we still need to cut off the `[context: ]` parts.\n\treturn dictionary[ translationKey ].replace( / \\[context: [^\\]]+\\]$/, '' );\n}\n\n/**\n * Clears dictionaries for test purposes.\n *\n * @protected\n */\nexport function _clear() {\n\twindow.CKEDITOR_TRANSLATIONS = {};\n}\n\n// Checks whether the dictionary exists and translation in that dictionary exists.\nfunction hasTranslation( language, translationKey ) {\n\treturn (\n\t\t( language in window.CKEDITOR_TRANSLATIONS ) &&\n\t\t( translationKey in window.CKEDITOR_TRANSLATIONS[ language ] )\n\t);\n}\n\nfunction getNumberOfLanguages() {\n\treturn Object.keys( window.CKEDITOR_TRANSLATIONS ).length;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 { translate } from './translation-service';\n\nconst RTL_LANGUAGE_CODES = [ 'ar', 'fa', 'he', 'ku', 'ug' ];\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 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 {@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 string to the {@link #uiLanguage}. This method is also available in\n\t\t * {@link module:core/editor/editor~Editor#t} and {@link module:ui/view~View#t}.\n\t\t *\n\t\t * The strings may contain placeholders (`%<index>`) for values which are passed as the second argument.\n\t\t * `<index>` is the index in the `values` array.\n\t\t *\n\t\t *\t\teditor.t( 'Created file \"%0\" in %1ms.', [ fileName, timeTaken ] );\n\t\t *\n\t\t * This method's context is statically bound to Locale instance,\n\t\t * so it can be called as a function:\n\t\t *\n\t\t *\t\tconst t = this.t;\n\t\t *\t\tt( 'Label' );\n\t\t *\n\t\t * @method #t\n\t\t * @param {String} str The string to translate.\n\t\t * @param {String[]} [values] Values that should be used to interpolate the string.\n\t\t */\n\t\tthis.t = ( ...args ) => this._t( ...args );\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 has been 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 has been deprecated and will\n\t\t * be removed in the near future. Please use {@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 * Base for the {@link #t} method.\n\t *\n\t * @private\n\t */\n\t_t( str, values ) {\n\t\tlet translatedString = translate( this.uiLanguage, str );\n\n\t\tif ( values ) {\n\t\t\ttranslatedString = translatedString.replace( /%(\\d+)/g, ( match, index ) => {\n\t\t\t\treturn ( index < values.length ) ? values[ index ] : match;\n\t\t\t} );\n\t\t}\n\n\t\treturn translatedString;\n\t}\n}\n\n// Helps determine whether a language is LTR or RTL.\n//\n// @param {String} language The ISO 639-1 language code.\n// @returns {String} 'ltr' or 'rtl\nfunction getLanguageDirection( languageCode ) {\n\treturn RTL_LANGUAGE_CODES.includes( languageCode ) ? 'rtl' : 'ltr';\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/conversion/viewconsumable\n */\n\nimport { isArray } from 'lodash-es';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Class used for handling consumption of view {@link module:engine/view/element~Element elements},\n * {@link module:engine/view/text~Text text nodes} and {@link module:engine/view/documentfragment~DocumentFragment document fragments}.\n * Element's name and its parts (attributes, classes and styles) can be consumed separately. Consuming an element's name\n * does not consume its attributes, classes and styles.\n * To add items for consumption use {@link module:engine/conversion/viewconsumable~ViewConsumable#add add method}.\n * To test items use {@link module:engine/conversion/viewconsumable~ViewConsumable#test test method}.\n * To consume items use {@link module:engine/conversion/viewconsumable~ViewConsumable#consume consume method}.\n * To revert already consumed items use {@link module:engine/conversion/viewconsumable~ViewConsumable#revert revert method}.\n *\n *\t\tviewConsumable.add( element, { name: true } ); // Adds element's name as ready to be consumed.\n *\t\tviewConsumable.add( textNode ); // Adds text node for consumption.\n *\t\tviewConsumable.add( docFragment ); // Adds document fragment for consumption.\n *\t\tviewConsumable.test( element, { name: true } ); // Tests if element's name can be consumed.\n *\t\tviewConsumable.test( textNode ); // Tests if text node can be consumed.\n *\t\tviewConsumable.test( docFragment ); // Tests if document fragment can be consumed.\n *\t\tviewConsumable.consume( element, { name: true } ); // Consume element's name.\n *\t\tviewConsumable.consume( textNode ); // Consume text node.\n *\t\tviewConsumable.consume( docFragment ); // Consume document fragment.\n *\t\tviewConsumable.revert( element, { name: true } ); // Revert already consumed element's name.\n *\t\tviewConsumable.revert( textNode ); // Revert already consumed text node.\n *\t\tviewConsumable.revert( docFragment ); // Revert already consumed document fragment.\n */\nexport default class ViewConsumable {\n\t/**\n\t * Creates new ViewConsumable.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Map of consumable elements. If {@link module:engine/view/element~Element element} is used as a key,\n\t\t * {@link module:engine/conversion/viewconsumable~ViewElementConsumables ViewElementConsumables} instance is stored as value.\n\t\t * For {@link module:engine/view/text~Text text nodes} and\n\t\t * {@link module:engine/view/documentfragment~DocumentFragment document fragments} boolean value is stored as value.\n\t\t *\n\t\t * @protected\n\t\t * @member {Map.<module:engine/conversion/viewconsumable~ViewElementConsumables|Boolean>}\n\t\t*/\n\t\tthis._consumables = new Map();\n\t}\n\n\t/**\n\t * Adds {@link module:engine/view/element~Element view element}, {@link module:engine/view/text~Text text node} or\n\t * {@link module:engine/view/documentfragment~DocumentFragment document fragment} as ready to be consumed.\n\t *\n\t *\t\tviewConsumable.add( p, { name: true } ); // Adds element's name to consume.\n\t *\t\tviewConsumable.add( p, { attributes: 'name' } ); // Adds element's attribute.\n\t *\t\tviewConsumable.add( p, { classes: 'foobar' } ); // Adds element's class.\n\t *\t\tviewConsumable.add( p, { styles: 'color' } ); // Adds element's style\n\t *\t\tviewConsumable.add( p, { attributes: 'name', styles: 'color' } ); // Adds attribute and style.\n\t *\t\tviewConsumable.add( p, { classes: [ 'baz', 'bar' ] } ); // Multiple consumables can be provided.\n\t *\t\tviewConsumable.add( textNode ); // Adds text node to consume.\n\t *\t\tviewConsumable.add( docFragment ); // Adds document fragment to consume.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `viewconsumable-invalid-attribute` when `class` or `style`\n\t * attribute is provided - it should be handled separately by providing actual style/class.\n\t *\n\t *\t\tviewConsumable.add( p, { attributes: 'style' } ); // This call will throw an exception.\n\t *\t\tviewConsumable.add( p, { styles: 'color' } ); // This is properly handled style.\n\t *\n\t * @param {module:engine/view/element~Element|module:engine/view/text~Text|module:engine/view/documentfragment~DocumentFragment} element\n\t * @param {Object} [consumables] Used only if first parameter is {@link module:engine/view/element~Element view element} instance.\n\t * @param {Boolean} consumables.name If set to true element's name will be included.\n\t * @param {String|Array.<String>} consumables.attributes Attribute name or array of attribute names.\n\t * @param {String|Array.<String>} consumables.classes Class name or array of class names.\n\t * @param {String|Array.<String>} consumables.styles Style name or array of style names.\n\t */\n\tadd( element, consumables ) {\n\t\tlet elementConsumables;\n\n\t\t// For text nodes and document fragments just mark them as consumable.\n\t\tif ( element.is( 'text' ) || element.is( 'documentFragment' ) ) {\n\t\t\tthis._consumables.set( element, true );\n\n\t\t\treturn;\n\t\t}\n\n\t\t// For elements create new ViewElementConsumables or update already existing one.\n\t\tif ( !this._consumables.has( element ) ) {\n\t\t\telementConsumables = new ViewElementConsumables();\n\t\t\tthis._consumables.set( element, elementConsumables );\n\t\t} else {\n\t\t\telementConsumables = this._consumables.get( element );\n\t\t}\n\n\t\telementConsumables.add( consumables );\n\t}\n\n\t/**\n\t * Tests if {@link module:engine/view/element~Element view element}, {@link module:engine/view/text~Text text node} or\n\t * {@link module:engine/view/documentfragment~DocumentFragment document fragment} can be consumed.\n\t * It returns `true` when all items included in method's call can be consumed. Returns `false` when\n\t * first already consumed item is found and `null` when first non-consumable item is found.\n\t *\n\t *\t\tviewConsumable.test( p, { name: true } ); // Tests element's name.\n\t *\t\tviewConsumable.test( p, { attributes: 'name' } ); // Tests attribute.\n\t *\t\tviewConsumable.test( p, { classes: 'foobar' } ); // Tests class.\n\t *\t\tviewConsumable.test( p, { styles: 'color' } ); // Tests style.\n\t *\t\tviewConsumable.test( p, { attributes: 'name', styles: 'color' } ); // Tests attribute and style.\n\t *\t\tviewConsumable.test( p, { classes: [ 'baz', 'bar' ] } ); // Multiple consumables can be tested.\n\t *\t\tviewConsumable.test( textNode ); // Tests text node.\n\t *\t\tviewConsumable.test( docFragment ); // Tests document fragment.\n\t *\n\t * Testing classes and styles as attribute will test if all added classes/styles can be consumed.\n\t *\n\t *\t\tviewConsumable.test( p, { attributes: 'class' } ); // Tests if all added classes can be consumed.\n\t *\t\tviewConsumable.test( p, { attributes: 'style' } ); // Tests if all added styles can be consumed.\n\t *\n\t * @param {module:engine/view/element~Element|module:engine/view/text~Text|module:engine/view/documentfragment~DocumentFragment} element\n\t * @param {Object} [consumables] Used only if first parameter is {@link module:engine/view/element~Element view element} instance.\n\t * @param {Boolean} consumables.name If set to true element's name will be included.\n\t * @param {String|Array.<String>} consumables.attributes Attribute name or array of attribute names.\n\t * @param {String|Array.<String>} consumables.classes Class name or array of class names.\n\t * @param {String|Array.<String>} consumables.styles Style name or array of style names.\n\t * @returns {Boolean|null} Returns `true` when all items included in method's call can be consumed. Returns `false`\n\t * when first already consumed item is found and `null` when first non-consumable item is found.\n\t */\n\ttest( element, consumables ) {\n\t\tconst elementConsumables = this._consumables.get( element );\n\n\t\tif ( elementConsumables === undefined ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// For text nodes and document fragments return stored boolean value.\n\t\tif ( element.is( 'text' ) || element.is( 'documentFragment' ) ) {\n\t\t\treturn elementConsumables;\n\t\t}\n\n\t\t// For elements test consumables object.\n\t\treturn elementConsumables.test( consumables );\n\t}\n\n\t/**\n\t * Consumes {@link module:engine/view/element~Element view element}, {@link module:engine/view/text~Text text node} or\n\t * {@link module:engine/view/documentfragment~DocumentFragment document fragment}.\n\t * It returns `true` when all items included in method's call can be consumed, otherwise returns `false`.\n\t *\n\t *\t\tviewConsumable.consume( p, { name: true } ); // Consumes element's name.\n\t *\t\tviewConsumable.consume( p, { attributes: 'name' } ); // Consumes element's attribute.\n\t *\t\tviewConsumable.consume( p, { classes: 'foobar' } ); // Consumes element's class.\n\t *\t\tviewConsumable.consume( p, { styles: 'color' } ); // Consumes element's style.\n\t *\t\tviewConsumable.consume( p, { attributes: 'name', styles: 'color' } ); // Consumes attribute and style.\n\t *\t\tviewConsumable.consume( p, { classes: [ 'baz', 'bar' ] } ); // Multiple consumables can be consumed.\n\t *\t\tviewConsumable.consume( textNode ); // Consumes text node.\n\t *\t\tviewConsumable.consume( docFragment ); // Consumes document fragment.\n\t *\n\t * Consuming classes and styles as attribute will test if all added classes/styles can be consumed.\n\t *\n\t *\t\tviewConsumable.consume( p, { attributes: 'class' } ); // Consume only if all added classes can be consumed.\n\t *\t\tviewConsumable.consume( p, { attributes: 'style' } ); // Consume only if all added styles can be consumed.\n\t *\n\t * @param {module:engine/view/element~Element|module:engine/view/text~Text|module:engine/view/documentfragment~DocumentFragment} element\n\t * @param {Object} [consumables] Used only if first parameter is {@link module:engine/view/element~Element view element} instance.\n\t * @param {Boolean} consumables.name If set to true element's name will be included.\n\t * @param {String|Array.<String>} consumables.attributes Attribute name or array of attribute names.\n\t * @param {String|Array.<String>} consumables.classes Class name or array of class names.\n\t * @param {String|Array.<String>} consumables.styles Style name or array of style names.\n\t * @returns {Boolean} Returns `true` when all items included in method's call can be consumed,\n\t * otherwise returns `false`.\n\t */\n\tconsume( element, consumables ) {\n\t\tif ( this.test( element, consumables ) ) {\n\t\t\tif ( element.is( 'text' ) || element.is( 'documentFragment' ) ) {\n\t\t\t\t// For text nodes and document fragments set value to false.\n\t\t\t\tthis._consumables.set( element, false );\n\t\t\t} else {\n\t\t\t\t// For elements - consume consumables object.\n\t\t\t\tthis._consumables.get( element ).consume( consumables );\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Reverts {@link module:engine/view/element~Element view element}, {@link module:engine/view/text~Text text node} or\n\t * {@link module:engine/view/documentfragment~DocumentFragment document fragment} so they can be consumed once again.\n\t * Method does not revert items that were never previously added for consumption, even if they are included in\n\t * method's call.\n\t *\n\t *\t\tviewConsumable.revert( p, { name: true } ); // Reverts element's name.\n\t *\t\tviewConsumable.revert( p, { attributes: 'name' } ); // Reverts element's attribute.\n\t *\t\tviewConsumable.revert( p, { classes: 'foobar' } ); // Reverts element's class.\n\t *\t\tviewConsumable.revert( p, { styles: 'color' } ); // Reverts element's style.\n\t *\t\tviewConsumable.revert( p, { attributes: 'name', styles: 'color' } ); // Reverts attribute and style.\n\t *\t\tviewConsumable.revert( p, { classes: [ 'baz', 'bar' ] } ); // Multiple names can be reverted.\n\t *\t\tviewConsumable.revert( textNode ); // Reverts text node.\n\t *\t\tviewConsumable.revert( docFragment ); // Reverts document fragment.\n\t *\n\t * Reverting classes and styles as attribute will revert all classes/styles that were previously added for\n\t * consumption.\n\t *\n\t *\t\tviewConsumable.revert( p, { attributes: 'class' } ); // Reverts all classes added for consumption.\n\t *\t\tviewConsumable.revert( p, { attributes: 'style' } ); // Reverts all styles added for consumption.\n\t *\n\t * @param {module:engine/view/element~Element|module:engine/view/text~Text|module:engine/view/documentfragment~DocumentFragment} element\n\t * @param {Object} [consumables] Used only if first parameter is {@link module:engine/view/element~Element view element} instance.\n\t * @param {Boolean} consumables.name If set to true element's name will be included.\n\t * @param {String|Array.<String>} consumables.attributes Attribute name or array of attribute names.\n\t * @param {String|Array.<String>} consumables.classes Class name or array of class names.\n\t * @param {String|Array.<String>} consumables.styles Style name or array of style names.\n\t */\n\trevert( element, consumables ) {\n\t\tconst elementConsumables = this._consumables.get( element );\n\n\t\tif ( elementConsumables !== undefined ) {\n\t\t\tif ( element.is( 'text' ) || element.is( 'documentFragment' ) ) {\n\t\t\t\t// For text nodes and document fragments - set consumable to true.\n\t\t\t\tthis._consumables.set( element, true );\n\t\t\t} else {\n\t\t\t\t// For elements - revert items from consumables object.\n\t\t\t\telementConsumables.revert( consumables );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Creates consumable object from {@link module:engine/view/element~Element view element}. Consumable object will include\n\t * element's name and all its attributes, classes and styles.\n\t *\n\t * @static\n\t * @param {module:engine/view/element~Element} element\n\t * @returns {Object} consumables\n\t */\n\tstatic consumablesFromElement( element ) {\n\t\tconst consumables = {\n\t\t\tname: true,\n\t\t\tattributes: [],\n\t\t\tclasses: [],\n\t\t\tstyles: []\n\t\t};\n\n\t\tconst attributes = element.getAttributeKeys();\n\n\t\tfor ( const attribute of attributes ) {\n\t\t\t// Skip classes and styles - will be added separately.\n\t\t\tif ( attribute == 'style' || attribute == 'class' ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconsumables.attributes.push( attribute );\n\t\t}\n\n\t\tconst classes = element.getClassNames();\n\n\t\tfor ( const className of classes ) {\n\t\t\tconsumables.classes.push( className );\n\t\t}\n\n\t\tconst styles = element.getStyleNames();\n\n\t\tfor ( const style of styles ) {\n\t\t\tconsumables.styles.push( style );\n\t\t}\n\n\t\treturn consumables;\n\t}\n\n\t/**\n\t * Creates {@link module:engine/conversion/viewconsumable~ViewConsumable ViewConsumable} instance from\n\t * {@link module:engine/view/node~Node node} or {@link module:engine/view/documentfragment~DocumentFragment document fragment}.\n\t * Instance will contain all elements, child nodes, attributes, styles and classes added for consumption.\n\t *\n\t * @static\n\t * @param {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment} from View node or document fragment\n\t * from which `ViewConsumable` will be created.\n\t * @param {module:engine/conversion/viewconsumable~ViewConsumable} [instance] If provided, given `ViewConsumable` instance will be used\n\t * to add all consumables. It will be returned instead of a new instance.\n\t */\n\tstatic createFrom( from, instance ) {\n\t\tif ( !instance ) {\n\t\t\tinstance = new ViewConsumable();\n\t\t}\n\n\t\tif ( from.is( 'text' ) ) {\n\t\t\tinstance.add( from );\n\n\t\t\treturn instance;\n\t\t}\n\n\t\t// Add `from` itself, if it is an element.\n\t\tif ( from.is( 'element' ) ) {\n\t\t\tinstance.add( from, ViewConsumable.consumablesFromElement( from ) );\n\t\t}\n\n\t\tif ( from.is( 'documentFragment' ) ) {\n\t\t\tinstance.add( from );\n\t\t}\n\n\t\tfor ( const child of from.getChildren() ) {\n\t\t\tinstance = ViewConsumable.createFrom( child, instance );\n\t\t}\n\n\t\treturn instance;\n\t}\n}\n\n/**\n * This is a private helper-class for {@link module:engine/conversion/viewconsumable~ViewConsumable}.\n * It represents and manipulates consumable parts of a single {@link module:engine/view/element~Element}.\n *\n * @private\n */\nclass ViewElementConsumables {\n\t/**\n\t * Creates ViewElementConsumables instance.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Flag indicating if name of the element can be consumed.\n\t\t *\n\t\t * @private\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis._canConsumeName = null;\n\n\t\t/**\n\t\t * Contains maps of element's consumables: attributes, classes and styles.\n\t\t *\n\t\t * @private\n\t\t * @member {Object}\n\t\t */\n\t\tthis._consumables = {\n\t\t\tattributes: new Map(),\n\t\t\tstyles: new Map(),\n\t\t\tclasses: new Map()\n\t\t};\n\t}\n\n\t/**\n\t * Adds consumable parts of the {@link module:engine/view/element~Element view element}.\n\t * Element's name itself can be marked to be consumed (when element's name is consumed its attributes, classes and\n\t * styles still could be consumed):\n\t *\n\t *\t\tconsumables.add( { name: true } );\n\t *\n\t * Attributes classes and styles:\n\t *\n\t *\t\tconsumables.add( { attributes: 'title', classes: 'foo', styles: 'color' } );\n\t *\t\tconsumables.add( { attributes: [ 'title', 'name' ], classes: [ 'foo', 'bar' ] );\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `viewconsumable-invalid-attribute` when `class` or `style`\n\t * attribute is provided - it should be handled separately by providing `style` and `class` in consumables object.\n\t *\n\t * @param {Object} consumables Object describing which parts of the element can be consumed.\n\t * @param {Boolean} consumables.name If set to `true` element's name will be added as consumable.\n\t * @param {String|Array.<String>} consumables.attributes Attribute name or array of attribute names to add as consumable.\n\t * @param {String|Array.<String>} consumables.classes Class name or array of class names to add as consumable.\n\t * @param {String|Array.<String>} consumables.styles Style name or array of style names to add as consumable.\n\t */\n\tadd( consumables ) {\n\t\tif ( consumables.name ) {\n\t\t\tthis._canConsumeName = true;\n\t\t}\n\n\t\tfor ( const type in this._consumables ) {\n\t\t\tif ( type in consumables ) {\n\t\t\t\tthis._add( type, consumables[ type ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Tests if parts of the {@link module:engine/view/node~Node view node} can be consumed.\n\t *\n\t * Element's name can be tested:\n\t *\n\t *\t\tconsumables.test( { name: true } );\n\t *\n\t * Attributes classes and styles:\n\t *\n\t *\t\tconsumables.test( { attributes: 'title', classes: 'foo', styles: 'color' } );\n\t *\t\tconsumables.test( { attributes: [ 'title', 'name' ], classes: [ 'foo', 'bar' ] );\n\t *\n\t * @param {Object} consumables Object describing which parts of the element should be tested.\n\t * @param {Boolean} consumables.name If set to `true` element's name will be tested.\n\t * @param {String|Array.<String>} consumables.attributes Attribute name or array of attribute names to test.\n\t * @param {String|Array.<String>} consumables.classes Class name or array of class names to test.\n\t * @param {String|Array.<String>} consumables.styles Style name or array of style names to test.\n\t * @returns {Boolean|null} `true` when all tested items can be consumed, `null` when even one of the items\n\t * was never marked for consumption and `false` when even one of the items was already consumed.\n\t */\n\ttest( consumables ) {\n\t\t// Check if name can be consumed.\n\t\tif ( consumables.name && !this._canConsumeName ) {\n\t\t\treturn this._canConsumeName;\n\t\t}\n\n\t\tfor ( const type in this._consumables ) {\n\t\t\tif ( type in consumables ) {\n\t\t\t\tconst value = this._test( type, consumables[ type ] );\n\n\t\t\t\tif ( value !== true ) {\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Return true only if all can be consumed.\n\t\treturn true;\n\t}\n\n\t/**\n\t * Consumes parts of {@link module:engine/view/element~Element view element}. This function does not check if consumable item\n\t * is already consumed - it consumes all consumable items provided.\n\t * Element's name can be consumed:\n\t *\n\t *\t\tconsumables.consume( { name: true } );\n\t *\n\t * Attributes classes and styles:\n\t *\n\t *\t\tconsumables.consume( { attributes: 'title', classes: 'foo', styles: 'color' } );\n\t *\t\tconsumables.consume( { attributes: [ 'title', 'name' ], classes: [ 'foo', 'bar' ] );\n\t *\n\t * @param {Object} consumables Object describing which parts of the element should be consumed.\n\t * @param {Boolean} consumables.name If set to `true` element's name will be consumed.\n\t * @param {String|Array.<String>} consumables.attributes Attribute name or array of attribute names to consume.\n\t * @param {String|Array.<String>} consumables.classes Class name or array of class names to consume.\n\t * @param {String|Array.<String>} consumables.styles Style name or array of style names to consume.\n\t */\n\tconsume( consumables ) {\n\t\tif ( consumables.name ) {\n\t\t\tthis._canConsumeName = false;\n\t\t}\n\n\t\tfor ( const type in this._consumables ) {\n\t\t\tif ( type in consumables ) {\n\t\t\t\tthis._consume( type, consumables[ type ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Revert already consumed parts of {@link module:engine/view/element~Element view Element}, so they can be consumed once again.\n\t * Element's name can be reverted:\n\t *\n\t *\t\tconsumables.revert( { name: true } );\n\t *\n\t * Attributes classes and styles:\n\t *\n\t *\t\tconsumables.revert( { attributes: 'title', classes: 'foo', styles: 'color' } );\n\t *\t\tconsumables.revert( { attributes: [ 'title', 'name' ], classes: [ 'foo', 'bar' ] );\n\t *\n\t * @param {Object} consumables Object describing which parts of the element should be reverted.\n\t * @param {Boolean} consumables.name If set to `true` element's name will be reverted.\n\t * @param {String|Array.<String>} consumables.attributes Attribute name or array of attribute names to revert.\n\t * @param {String|Array.<String>} consumables.classes Class name or array of class names to revert.\n\t * @param {String|Array.<String>} consumables.styles Style name or array of style names to revert.\n\t */\n\trevert( consumables ) {\n\t\tif ( consumables.name ) {\n\t\t\tthis._canConsumeName = true;\n\t\t}\n\n\t\tfor ( const type in this._consumables ) {\n\t\t\tif ( type in consumables ) {\n\t\t\t\tthis._revert( type, consumables[ type ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Helper method that adds consumables of a given type: attribute, class or style.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `viewconsumable-invalid-attribute` when `class` or `style`\n\t * type is provided - it should be handled separately by providing actual style/class type.\n\t *\n\t * @private\n\t * @param {String} type Type of the consumable item: `attributes`, `classes` or `styles`.\n\t * @param {String|Array.<String>} item Consumable item or array of items.\n\t */\n\t_add( type, item ) {\n\t\tconst items = isArray( item ) ? item : [ item ];\n\t\tconst consumables = this._consumables[ type ];\n\n\t\tfor ( const name of items ) {\n\t\t\tif ( type === 'attributes' && ( name === 'class' || name === 'style' ) ) {\n\t\t\t\t/**\n\t\t\t\t * Class and style attributes should be handled separately in\n\t\t\t\t * {@link module:engine/conversion/viewconsumable~ViewConsumable#add `ViewConsumable#add()`}.\n\t\t\t\t *\n\t\t\t\t * What you have done is trying to use:\n\t\t\t\t *\n\t\t\t\t *\t\tconsumables.add( { attributes: [ 'class', 'style' ] } );\n\t\t\t\t *\n\t\t\t\t * While each class and style should be registered separately:\n\t\t\t\t *\n\t\t\t\t *\t\tconsumables.add( { classes: 'some-class', styles: 'font-weight' } );\n\t\t\t\t *\n\t\t\t\t * @error viewconsumable-invalid-attribute\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'viewconsumable-invalid-attribute: Classes and styles should be handled separately.', this );\n\t\t\t}\n\n\t\t\tconsumables.set( name, true );\n\t\t}\n\t}\n\n\t/**\n\t * Helper method that tests consumables of a given type: attribute, class or style.\n\t *\n\t * @private\n\t * @param {String} type Type of the consumable item: `attributes`, `classes` or `styles`.\n\t * @param {String|Array.<String>} item Consumable item or array of items.\n\t * @returns {Boolean|null} Returns `true` if all items can be consumed, `null` when one of the items cannot be\n\t * consumed and `false` when one of the items is already consumed.\n\t */\n\t_test( type, item ) {\n\t\tconst items = isArray( item ) ? item : [ item ];\n\t\tconst consumables = this._consumables[ type ];\n\n\t\tfor ( const name of items ) {\n\t\t\tif ( type === 'attributes' && ( name === 'class' || name === 'style' ) ) {\n\t\t\t\tconst consumableName = name == 'class' ? 'classes' : 'styles';\n\n\t\t\t\t// Check all classes/styles if class/style attribute is tested.\n\t\t\t\tconst value = this._test( consumableName, [ ...this._consumables[ consumableName ].keys() ] );\n\n\t\t\t\tif ( value !== true ) {\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst value = consumables.get( name );\n\t\t\t\t// Return null if attribute is not found.\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tif ( !value ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Helper method that consumes items of a given type: attribute, class or style.\n\t *\n\t * @private\n\t * @param {String} type Type of the consumable item: `attributes`, `classes` or `styles`.\n\t * @param {String|Array.<String>} item Consumable item or array of items.\n\t */\n\t_consume( type, item ) {\n\t\tconst items = isArray( item ) ? item : [ item ];\n\t\tconst consumables = this._consumables[ type ];\n\n\t\tfor ( const name of items ) {\n\t\t\tif ( type === 'attributes' && ( name === 'class' || name === 'style' ) ) {\n\t\t\t\tconst consumableName = name == 'class' ? 'classes' : 'styles';\n\n\t\t\t\t// If class or style is provided for consumption - consume them all.\n\t\t\t\tthis._consume( consumableName, [ ...this._consumables[ consumableName ].keys() ] );\n\t\t\t} else {\n\t\t\t\tconsumables.set( name, false );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Helper method that reverts items of a given type: attribute, class or style.\n\t *\n\t * @private\n\t * @param {String} type Type of the consumable item: `attributes`, `classes` or , `styles`.\n\t * @param {String|Array.<String>} item Consumable item or array of items.\n\t */\n\t_revert( type, item ) {\n\t\tconst items = isArray( item ) ? item : [ item ];\n\t\tconst consumables = this._consumables[ type ];\n\n\t\tfor ( const name of items ) {\n\t\t\tif ( type === 'attributes' && ( name === 'class' || name === 'style' ) ) {\n\t\t\t\tconst consumableName = name == 'class' ? 'classes' : 'styles';\n\n\t\t\t\t// If class or style is provided for reverting - revert them all.\n\t\t\t\tthis._revert( consumableName, [ ...this._consumables[ consumableName ].keys() ] );\n\t\t\t} else {\n\t\t\t\tconst value = consumables.get( name );\n\n\t\t\t\tif ( value === false ) {\n\t\t\t\t\tconsumables.set( name, true );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/schema\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\nimport Range from './range';\nimport Position from './position';\nimport Element from './element';\nimport Text from './text';\nimport TreeWalker from './treewalker';\n\n/**\n * The model's schema. It defines allowed and disallowed structures of nodes as well as nodes' attributes.\n * The schema is usually defined by features and based on them the editing framework and features\n * make decisions how to change and process the model.\n *\n * The instance of schema is available in {@link module:engine/model/model~Model#schema `editor.model.schema`}.\n *\n * Read more about the schema in:\n *\n * * {@glink framework/guides/architecture/editing-engine#schema \"Schema\"} section of the\n * {@glink framework/guides/architecture/editing-engine Introduction to the \"Editing engine architecture\"}.\n * * {@glink framework/guides/deep-dive/schema \"Schema\" deep dive} guide.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class Schema {\n\t/**\n\t * Creates schema instance.\n\t */\n\tconstructor() {\n\t\tthis._sourceDefinitions = {};\n\n\t\t/**\n\t\t * A dictionary containing attribute properties.\n\t\t *\n\t\t * @private\n\t\t * @member {Object.<String,String>}\n\t\t */\n\t\tthis._attributeProperties = {};\n\n\t\tthis.decorate( 'checkChild' );\n\t\tthis.decorate( 'checkAttribute' );\n\n\t\tthis.on( 'checkAttribute', ( evt, args ) => {\n\t\t\targs[ 0 ] = new SchemaContext( args[ 0 ] );\n\t\t}, { priority: 'highest' } );\n\n\t\tthis.on( 'checkChild', ( evt, args ) => {\n\t\t\targs[ 0 ] = new SchemaContext( args[ 0 ] );\n\t\t\targs[ 1 ] = this.getDefinition( args[ 1 ] );\n\t\t}, { priority: 'highest' } );\n\t}\n\n\t/**\n\t * Registers schema item. Can only be called once for every item name.\n\t *\n\t *\t\tschema.register( 'paragraph', {\n\t *\t\t\tinheritAllFrom: '$block'\n\t *\t\t} );\n\t *\n\t * @param {String} itemName\n\t * @param {module:engine/model/schema~SchemaItemDefinition} definition\n\t */\n\tregister( itemName, definition ) {\n\t\tif ( this._sourceDefinitions[ itemName ] ) {\n\t\t\t/**\n\t\t\t * A single item cannot be registered twice in the schema.\n\t\t\t *\n\t\t\t * This situation may happen when:\n\t\t\t *\n\t\t\t * * Two or more plugins called {@link #register `register()`} with the same name. This will usually mean that\n\t\t\t * there is a collision between plugins which try to use the same element in the model. Unfortunately,\n\t\t\t * the only way to solve this is by modifying one of these plugins to use a unique model element name.\n\t\t\t * * A single plugin was loaded twice. This happens when it is installed by npm/yarn in two versions\n\t\t\t * and usually means one or more of the following issues:\n\t\t\t * * a version mismatch (two of your dependencies require two different versions of this plugin),\n\t\t\t * * incorrect imports (this plugin is somehow imported twice in a way which confuses webpack),\n\t\t\t * * mess in `node_modules/` (`rm -rf node_modules/` may help).\n\t\t\t *\n\t\t\t * **Note:** Check the logged `itemName` to better understand which plugin was duplicated/conflicting.\n\t\t\t *\n\t\t\t * @param itemName The name of the model element that is being registered twice.\n\t\t\t * @error schema-cannot-register-item-twice\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'schema-cannot-register-item-twice: A single item cannot be registered twice in the schema.',\n\t\t\t\tthis,\n\t\t\t\t{\n\t\t\t\t\titemName\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tthis._sourceDefinitions[ itemName ] = [\n\t\t\tObject.assign( {}, definition )\n\t\t];\n\n\t\tthis._clearCache();\n\t}\n\n\t/**\n\t * Extends a {@link #register registered} item's definition.\n\t *\n\t * Extending properties such as `allowIn` will add more items to the existing properties,\n\t * while redefining properties such as `isBlock` will override the previously defined ones.\n\t *\n\t *\t\tschema.register( 'foo', {\n\t *\t\t\tallowIn: '$root',\n\t *\t\t\tisBlock: true;\n\t *\t\t} );\n\t *\t\tschema.extend( 'foo', {\n\t *\t\t\tallowIn: 'blockQuote',\n\t *\t\t\tisBlock: false\n\t *\t\t} );\n\t *\n\t *\t\tschema.getDefinition( 'foo' );\n\t *\t\t//\t{\n\t *\t\t//\t\tallowIn: [ '$root', 'blockQuote' ],\n\t *\t\t// \t\tisBlock: false\n\t *\t\t//\t}\n\t *\n\t * @param {String} itemName\n\t * @param {module:engine/model/schema~SchemaItemDefinition} definition\n\t */\n\textend( itemName, definition ) {\n\t\tif ( !this._sourceDefinitions[ itemName ] ) {\n\t\t\t/**\n\t\t\t * Cannot extend an item which was not registered yet.\n\t\t\t *\n\t\t\t * This error happens when a plugin tries to extend the schema definition of an item which was not\n\t\t\t * {@link #register registered} yet.\n\t\t\t *\n\t\t\t * @param itemName The name of the model element which is being extended.\n\t\t\t * @error schema-cannot-extend-missing-item\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'schema-cannot-extend-missing-item: Cannot extend an item which was not registered yet.', this, {\n\t\t\t\titemName\n\t\t\t} );\n\t\t}\n\n\t\tthis._sourceDefinitions[ itemName ].push( Object.assign( {}, definition ) );\n\n\t\tthis._clearCache();\n\t}\n\n\t/**\n\t * Returns all registered items.\n\t *\n\t * @returns {Object.<String,module:engine/model/schema~SchemaCompiledItemDefinition>}\n\t */\n\tgetDefinitions() {\n\t\tif ( !this._compiledDefinitions ) {\n\t\t\tthis._compile();\n\t\t}\n\n\t\treturn this._compiledDefinitions;\n\t}\n\n\t/**\n\t * Returns a definition of the given item or `undefined` if item is not registered.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/schema~SchemaContextItem|String} item\n\t * @returns {module:engine/model/schema~SchemaCompiledItemDefinition}\n\t */\n\tgetDefinition( item ) {\n\t\tlet itemName;\n\n\t\tif ( typeof item == 'string' ) {\n\t\t\titemName = item;\n\t\t} else if ( item.is && ( item.is( 'text' ) || item.is( 'textProxy' ) ) ) {\n\t\t\titemName = '$text';\n\t\t}\n\t\t// Element or module:engine/model/schema~SchemaContextItem.\n\t\telse {\n\t\t\titemName = item.name;\n\t\t}\n\n\t\treturn this.getDefinitions()[ itemName ];\n\t}\n\n\t/**\n\t * Returns `true` if the given item is registered in the schema.\n\t *\n\t *\t\tschema.isRegistered( 'paragraph' ); // -> true\n\t *\t\tschema.isRegistered( editor.model.document.getRoot() ); // -> true\n\t *\t\tschema.isRegistered( 'foo' ); // -> false\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/schema~SchemaContextItem|String} item\n\t */\n\tisRegistered( item ) {\n\t\treturn !!this.getDefinition( item );\n\t}\n\n\t/**\n\t * Returns `true` if the given item is defined to be\n\t * a block by {@link module:engine/model/schema~SchemaItemDefinition}'s `isBlock` property.\n\t *\n\t *\t\tschema.isBlock( 'paragraph' ); // -> true\n\t *\t\tschema.isBlock( '$root' ); // -> false\n\t *\n\t *\t\tconst paragraphElement = writer.createElement( 'paragraph' );\n\t *\t\tschema.isBlock( paragraphElement ); // -> true\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/schema~SchemaContextItem|String} item\n\t */\n\tisBlock( item ) {\n\t\tconst def = this.getDefinition( item );\n\n\t\treturn !!( def && def.isBlock );\n\t}\n\n\t/**\n\t * Returns `true` if the given item is defined to be\n\t * a limit element by {@link module:engine/model/schema~SchemaItemDefinition}'s `isLimit` or `isObject` property\n\t * (all objects are also limits).\n\t *\n\t *\t\tschema.isLimit( 'paragraph' ); // -> false\n\t *\t\tschema.isLimit( '$root' ); // -> true\n\t *\t\tschema.isLimit( editor.model.document.getRoot() ); // -> true\n\t *\t\tschema.isLimit( 'image' ); // -> true\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/schema~SchemaContextItem|String} item\n\t */\n\tisLimit( item ) {\n\t\tconst def = this.getDefinition( item );\n\n\t\tif ( !def ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn !!( def.isLimit || def.isObject );\n\t}\n\n\t/**\n\t * Returns `true` if the given item is defined to be\n\t * an object element by {@link module:engine/model/schema~SchemaItemDefinition}'s `isObject` property.\n\t *\n\t *\t\tschema.isObject( 'paragraph' ); // -> false\n\t *\t\tschema.isObject( 'image' ); // -> true\n\t *\n\t *\t\tconst imageElement = writer.createElement( 'image' );\n\t *\t\tschema.isObject( imageElement ); // -> true\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/schema~SchemaContextItem|String} item\n\t */\n\tisObject( item ) {\n\t\tconst def = this.getDefinition( item );\n\n\t\treturn !!( def && def.isObject );\n\t}\n\n\t/**\n\t * Returns `true` if the given item is defined to be\n\t * an inline element by {@link module:engine/model/schema~SchemaItemDefinition}'s `isInline` property.\n\t *\n\t *\t\tschema.isInline( 'paragraph' ); // -> false\n\t *\t\tschema.isInline( 'softBreak' ); // -> true\n\t *\n\t *\t\tconst text = writer.createText('foo' );\n\t *\t\tschema.isInline( text ); // -> true\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/schema~SchemaContextItem|String} item\n\t */\n\tisInline( item ) {\n\t\tconst def = this.getDefinition( item );\n\n\t\treturn !!( def && def.isInline );\n\t}\n\n\t/**\n\t * Checks whether the given node (`child`) can be a child of the given context.\n\t *\n\t *\t\tschema.checkChild( model.document.getRoot(), paragraph ); // -> false\n\t *\n\t *\t\tschema.register( 'paragraph', {\n\t *\t\t\tallowIn: '$root'\n\t *\t\t} );\n\t *\t\tschema.checkChild( model.document.getRoot(), paragraph ); // -> true\n\t *\n\t * Note: When verifying whether the given node can be a child of the given context, the\n\t * schema also verifies the entire context &mdash; from its root to its last element. Therefore, it is possible\n\t * for `checkChild()` to return `false` even though the context's last element can contain the checked child.\n\t * It happens if one of the context's elements does not allow its child.\n\t *\n\t * @fires checkChild\n\t * @param {module:engine/model/schema~SchemaContextDefinition} context The context in which the child will be checked.\n\t * @param {module:engine/model/node~Node|String} def The child to check.\n\t */\n\tcheckChild( context, def ) {\n\t\t// Note: context and child are already normalized here to a SchemaContext and SchemaCompiledItemDefinition.\n\t\tif ( !def ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this._checkContextMatch( def, context );\n\t}\n\n\t/**\n\t * Checks whether the given attribute can be applied in the given context (on the last\n\t * item of the context).\n\t *\n\t *\t\tschema.checkAttribute( textNode, 'bold' ); // -> false\n\t *\n\t *\t\tschema.extend( '$text', {\n\t *\t\t\tallowAttributes: 'bold'\n\t *\t\t} );\n\t *\t\tschema.checkAttribute( textNode, 'bold' ); // -> true\n\t *\n\t * @fires checkAttribute\n\t * @param {module:engine/model/schema~SchemaContextDefinition} context The context in which the attribute will be checked.\n\t * @param {String} attributeName\n\t */\n\tcheckAttribute( context, attributeName ) {\n\t\tconst def = this.getDefinition( context.last );\n\n\t\tif ( !def ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn def.allowAttributes.includes( attributeName );\n\t}\n\n\t/**\n\t * Checks whether the given element (`elementToMerge`) can be merged with the specified base element (`positionOrBaseElement`).\n\t *\n\t * In other words &mdash; whether `elementToMerge`'s children {@link #checkChild are allowed} in the `positionOrBaseElement`.\n\t *\n\t * This check ensures that elements merged with {@link module:engine/model/writer~Writer#merge `Writer#merge()`}\n\t * will be valid.\n\t *\n\t * Instead of elements, you can pass the instance of the {@link module:engine/model/position~Position} class as the\n\t * `positionOrBaseElement`. It means that the elements before and after the position will be checked whether they can be merged.\n\t *\n\t * @param {module:engine/model/position~Position|module:engine/model/element~Element} positionOrBaseElement The position or base\n\t * element to which the `elementToMerge` will be merged.\n\t * @param {module:engine/model/element~Element} elementToMerge The element to merge. Required if `positionOrBaseElement` is an element.\n\t * @returns {Boolean}\n\t */\n\tcheckMerge( positionOrBaseElement, elementToMerge = null ) {\n\t\tif ( positionOrBaseElement instanceof Position ) {\n\t\t\tconst nodeBefore = positionOrBaseElement.nodeBefore;\n\t\t\tconst nodeAfter = positionOrBaseElement.nodeAfter;\n\n\t\t\tif ( !( nodeBefore instanceof Element ) ) {\n\t\t\t\t/**\n\t\t\t\t * The node before the merge position must be an element.\n\t\t\t\t *\n\t\t\t\t * @error schema-check-merge-no-element-before\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'schema-check-merge-no-element-before: The node before the merge position must be an element.',\n\t\t\t\t\tthis\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif ( !( nodeAfter instanceof Element ) ) {\n\t\t\t\t/**\n\t\t\t\t * The node after the merge position must be an element.\n\t\t\t\t *\n\t\t\t\t * @error schema-check-merge-no-element-after\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'schema-check-merge-no-element-after: The node after the merge position must be an element.',\n\t\t\t\t\tthis\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn this.checkMerge( nodeBefore, nodeAfter );\n\t\t}\n\n\t\tfor ( const child of elementToMerge.getChildren() ) {\n\t\t\tif ( !this.checkChild( positionOrBaseElement, child ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Allows registering a callback to the {@link #checkChild} method calls.\n\t *\n\t * Callbacks allow you to implement rules which are not otherwise possible to achieve\n\t * by using the declarative API of {@link module:engine/model/schema~SchemaItemDefinition}.\n\t * For example, by using this method you can disallow elements in specific contexts.\n\t *\n\t * This method is a shorthand for using the {@link #event:checkChild} event. For even better control,\n\t * you can use that event instead.\n\t *\n\t * Example:\n\t *\n\t *\t\t// Disallow heading1 directly inside a blockQuote.\n\t *\t\tschema.addChildCheck( ( context, childDefinition ) => {\n\t *\t\t\tif ( context.endsWith( 'blockQuote' ) && childDefinition.name == 'heading1' ) {\n\t *\t\t\t\treturn false;\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * Which translates to:\n\t *\n\t *\t\tschema.on( 'checkChild', ( evt, args ) => {\n\t *\t\t\tconst context = args[ 0 ];\n\t *\t\t\tconst childDefinition = args[ 1 ];\n\t *\n\t *\t\t\tif ( context.endsWith( 'blockQuote' ) && childDefinition && childDefinition.name == 'heading1' ) {\n\t *\t\t\t\t// Prevent next listeners from being called.\n\t *\t\t\t\tevt.stop();\n\t *\t\t\t\t// Set the checkChild()'s return value.\n\t *\t\t\t\tevt.return = false;\n\t *\t\t\t}\n\t *\t\t}, { priority: 'high' } );\n\t *\n\t * @param {Function} callback The callback to be called. It is called with two parameters:\n\t * {@link module:engine/model/schema~SchemaContext} (context) instance and\n\t * {@link module:engine/model/schema~SchemaCompiledItemDefinition} (child-to-check definition).\n\t * The callback may return `true/false` to override `checkChild()`'s return value. If it does not return\n\t * a boolean value, the default algorithm (or other callbacks) will define `checkChild()`'s return value.\n\t */\n\taddChildCheck( callback ) {\n\t\tthis.on( 'checkChild', ( evt, [ ctx, childDef ] ) => {\n\t\t\t// checkChild() was called with a non-registered child.\n\t\t\t// In 99% cases such check should return false, so not to overcomplicate all callbacks\n\t\t\t// don't even execute them.\n\t\t\tif ( !childDef ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst retValue = callback( ctx, childDef );\n\n\t\t\tif ( typeof retValue == 'boolean' ) {\n\t\t\t\tevt.stop();\n\t\t\t\tevt.return = retValue;\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\t}\n\n\t/**\n\t * Allows registering a callback to the {@link #checkAttribute} method calls.\n\t *\n\t * Callbacks allow you to implement rules which are not otherwise possible to achieve\n\t * by using the declarative API of {@link module:engine/model/schema~SchemaItemDefinition}.\n\t * For example, by using this method you can disallow attribute if node to which it is applied\n\t * is contained within some other element (e.g. you want to disallow `bold` on `$text` within `heading1`).\n\t *\n\t * This method is a shorthand for using the {@link #event:checkAttribute} event. For even better control,\n\t * you can use that event instead.\n\t *\n\t * Example:\n\t *\n\t *\t\t// Disallow bold on $text inside heading1.\n\t *\t\tschema.addAttributeCheck( ( context, attributeName ) => {\n\t *\t\t\tif ( context.endsWith( 'heading1 $text' ) && attributeName == 'bold' ) {\n\t *\t\t\t\treturn false;\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * Which translates to:\n\t *\n\t *\t\tschema.on( 'checkAttribute', ( evt, args ) => {\n\t *\t\t\tconst context = args[ 0 ];\n\t *\t\t\tconst attributeName = args[ 1 ];\n\t *\n\t *\t\t\tif ( context.endsWith( 'heading1 $text' ) && attributeName == 'bold' ) {\n\t *\t\t\t\t// Prevent next listeners from being called.\n\t *\t\t\t\tevt.stop();\n\t *\t\t\t\t// Set the checkAttribute()'s return value.\n\t *\t\t\t\tevt.return = false;\n\t *\t\t\t}\n\t *\t\t}, { priority: 'high' } );\n\t *\n\t * @param {Function} callback The callback to be called. It is called with two parameters:\n\t * {@link module:engine/model/schema~SchemaContext} (context) instance and attribute name.\n\t * The callback may return `true/false` to override `checkAttribute()`'s return value. If it does not return\n\t * a boolean value, the default algorithm (or other callbacks) will define `checkAttribute()`'s return value.\n\t */\n\taddAttributeCheck( callback ) {\n\t\tthis.on( 'checkAttribute', ( evt, [ ctx, attributeName ] ) => {\n\t\t\tconst retValue = callback( ctx, attributeName );\n\n\t\t\tif ( typeof retValue == 'boolean' ) {\n\t\t\t\tevt.stop();\n\t\t\t\tevt.return = retValue;\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\t}\n\n\t/**\n\t * This method allows assigning additional metadata to the model attributes. For example,\n\t * {@link module:engine/model/schema~AttributeProperties `AttributeProperties#isFormatting` property} is\n\t * used to mark formatting attributes (like `bold` or `italic`).\n\t *\n\t *\t\t// Mark bold as a formatting attribute.\n\t *\t\tschema.setAttributeProperties( 'bold', {\n\t *\t\t\tisFormatting: true\n\t *\t\t} );\n\t *\n\t *\t\t// Override code not to be considered a formatting markup.\n\t *\t\tschema.setAttributeProperties( 'code', {\n\t *\t\t\tisFormatting: false\n\t *\t\t} );\n\t *\n\t * Properties are not limited to members defined in the\n\t * {@link module:engine/model/schema~AttributeProperties `AttributeProperties` type} and you can also use custom properties:\n\t *\n\t *\t\tschema.setAttributeProperties( 'blockQuote', {\n\t *\t\t\tcustomProperty: 'value'\n\t *\t\t} );\n\t *\n\t * Subsequent calls with the same attribute will extend its custom properties:\n\t *\n\t *\t\tschema.setAttributeProperties( 'blockQuote', {\n\t *\t\t\tone: 1\n\t *\t\t} );\n\t *\n\t *\t\tschema.setAttributeProperties( 'blockQuote', {\n\t *\t\t\ttwo: 2\n\t *\t\t} );\n\t *\n\t *\t\tconsole.log( schema.getAttributeProperties( 'blockQuote' ) );\n\t *\t\t// Logs: { one: 1, two: 2 }\n\t *\n\t * @param {String} attributeName A name of the attribute to receive the properties.\n\t * @param {module:engine/model/schema~AttributeProperties} properties A dictionary of properties.\n\t */\n\tsetAttributeProperties( attributeName, properties ) {\n\t\tthis._attributeProperties[ attributeName ] = Object.assign( this.getAttributeProperties( attributeName ), properties );\n\t}\n\n\t/**\n\t * Returns properties associated with a given model attribute. See {@link #setAttributeProperties `setAttributeProperties()`}.\n\t *\n\t * @param {String} attributeName A name of the attribute.\n\t * @returns {module:engine/model/schema~AttributeProperties}\n\t */\n\tgetAttributeProperties( attributeName ) {\n\t\treturn this._attributeProperties[ attributeName ] || {};\n\t}\n\n\t/**\n\t * Returns the lowest {@link module:engine/model/schema~Schema#isLimit limit element} containing the entire\n\t * selection/range/position or the root otherwise.\n\t *\n\t * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection|\n\t * module:engine/model/range~Range|module:engine/model/position~Position} selectionOrRangeOrPosition\n\t * The selection/range/position to check.\n\t * @returns {module:engine/model/element~Element} The lowest limit element containing\n\t * the entire `selectionOrRangeOrPosition`.\n\t */\n\tgetLimitElement( selectionOrRangeOrPosition ) {\n\t\tlet element;\n\n\t\tif ( selectionOrRangeOrPosition instanceof Position ) {\n\t\t\telement = selectionOrRangeOrPosition.parent;\n\t\t} else {\n\t\t\tconst ranges = selectionOrRangeOrPosition instanceof Range ?\n\t\t\t\t[ selectionOrRangeOrPosition ] :\n\t\t\t\tArray.from( selectionOrRangeOrPosition.getRanges() );\n\n\t\t\t// Find the common ancestor for all selection's ranges.\n\t\t\telement = ranges\n\t\t\t\t.reduce( ( element, range ) => {\n\t\t\t\t\tconst rangeCommonAncestor = range.getCommonAncestor();\n\n\t\t\t\t\tif ( !element ) {\n\t\t\t\t\t\treturn rangeCommonAncestor;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn element.getCommonAncestor( rangeCommonAncestor, { includeSelf: true } );\n\t\t\t\t}, null );\n\t\t}\n\n\t\twhile ( !this.isLimit( element ) ) {\n\t\t\tif ( element.parent ) {\n\t\t\t\telement = element.parent;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn element;\n\t}\n\n\t/**\n\t * Checks whether the attribute is allowed in selection:\n\t *\n\t * * if the selection is not collapsed, then checks if the attribute is allowed on any of nodes in that range,\n\t * * if the selection is collapsed, then checks if on the selection position there's a text with the\n\t * specified attribute allowed.\n\t *\n\t * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n\t * Selection which will be checked.\n\t * @param {String} attribute The name of the attribute to check.\n\t * @returns {Boolean}\n\t */\n\tcheckAttributeInSelection( selection, attribute ) {\n\t\tif ( selection.isCollapsed ) {\n\t\t\tconst firstPosition = selection.getFirstPosition();\n\t\t\tconst context = [\n\t\t\t\t...firstPosition.getAncestors(),\n\t\t\t\tnew Text( '', selection.getAttributes() )\n\t\t\t];\n\n\t\t\t// Check whether schema allows for a text with the attribute in the selection.\n\t\t\treturn this.checkAttribute( context, attribute );\n\t\t} else {\n\t\t\tconst ranges = selection.getRanges();\n\n\t\t\t// For all ranges, check nodes in them until you find a node that is allowed to have the attribute.\n\t\t\tfor ( const range of ranges ) {\n\t\t\t\tfor ( const value of range ) {\n\t\t\t\t\tif ( this.checkAttribute( value.item, attribute ) ) {\n\t\t\t\t\t\t// If we found a node that is allowed to have the attribute, return true.\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we haven't found such node, return false.\n\t\treturn false;\n\t}\n\n\t/**\n\t * Transforms the given set of ranges into a set of ranges where the given attribute is allowed (and can be applied).\n\t *\n\t * @param {Array.<module:engine/model/range~Range>} ranges Ranges to be validated.\n\t * @param {String} attribute The name of the attribute to check.\n\t * @returns {Iterable.<module:engine/model/range~Range>} Ranges in which the attribute is allowed.\n\t */\n\t* getValidRanges( ranges, attribute ) {\n\t\tranges = convertToMinimalFlatRanges( ranges );\n\n\t\tfor ( const range of ranges ) {\n\t\t\tyield* this._getValidRangesForRange( range, attribute );\n\t\t}\n\t}\n\n\t/**\n\t * Basing on given `position`, finds and returns a {@link module:engine/model/range~Range range} which is\n\t * nearest to that `position` and is a correct range for selection.\n\t *\n\t * The correct selection range might be collapsed when it is located in a position where the text node can be placed.\n\t * Non-collapsed range is returned when selection can be placed around element marked as an \"object\" in\n\t * the {@link module:engine/model/schema~Schema schema}.\n\t *\n\t * Direction of searching for the nearest correct selection range can be specified as:\n\t *\n\t * * `both` - searching will be performed in both ways,\n\t * * `forward` - searching will be performed only forward,\n\t * * `backward` - searching will be performed only backward.\n\t *\n\t * When valid selection range cannot be found, `null` is returned.\n\t *\n\t * @param {module:engine/model/position~Position} position Reference position where new selection range should be looked for.\n\t * @param {'both'|'forward'|'backward'} [direction='both'] Search direction.\n\t * @returns {module:engine/model/range~Range|null} Nearest selection range or `null` if one cannot be found.\n\t */\n\tgetNearestSelectionRange( position, direction = 'both' ) {\n\t\t// Return collapsed range if provided position is valid.\n\t\tif ( this.checkChild( position, '$text' ) ) {\n\t\t\treturn new Range( position );\n\t\t}\n\n\t\tlet backwardWalker, forwardWalker;\n\n\t\tif ( direction == 'both' || direction == 'backward' ) {\n\t\t\tbackwardWalker = new TreeWalker( { startPosition: position, direction: 'backward' } );\n\t\t}\n\n\t\tif ( direction == 'both' || direction == 'forward' ) {\n\t\t\tforwardWalker = new TreeWalker( { startPosition: position } );\n\t\t}\n\n\t\tfor ( const data of combineWalkers( backwardWalker, forwardWalker ) ) {\n\t\t\tconst type = ( data.walker == backwardWalker ? 'elementEnd' : 'elementStart' );\n\t\t\tconst value = data.value;\n\n\t\t\tif ( value.type == type && this.isObject( value.item ) ) {\n\t\t\t\treturn Range._createOn( value.item );\n\t\t\t}\n\n\t\t\tif ( this.checkChild( value.nextPosition, '$text' ) ) {\n\t\t\t\treturn new Range( value.nextPosition );\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Tries to find position ancestors that allows to insert given node.\n\t * It starts searching from the given position and goes node by node to the top of the model tree\n\t * as long as {@link module:engine/model/schema~Schema#isLimit limit element},\n\t * {@link module:engine/model/schema~Schema#isObject object element} or top-most ancestor won't be reached.\n\t *\n\t * @params {module:engine/model/position~Position} position Position from searching will start.\n\t * @params {module:engine/model/node~Node|String} node Node for which allowed parent should be found or its name.\n\t * @returns {module:engine/model/element~Element|null} element Allowed parent or null if nothing was found.\n\t */\n\tfindAllowedParent( position, node ) {\n\t\tlet parent = position.parent;\n\n\t\twhile ( parent ) {\n\t\t\tif ( this.checkChild( parent, node ) ) {\n\t\t\t\treturn parent;\n\t\t\t}\n\n\t\t\t// Do not split limit elements.\n\t\t\tif ( this.isLimit( parent ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tparent = parent.parent;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Removes attributes disallowed by the schema.\n\t *\n\t * @param {Iterable.<module:engine/model/node~Node>} nodes Nodes that will be filtered.\n\t * @param {module:engine/model/writer~Writer} writer\n\t */\n\tremoveDisallowedAttributes( nodes, writer ) {\n\t\tfor ( const node of nodes ) {\n\t\t\t// When node is a `Text` it has no children, so just filter it out.\n\t\t\tif ( node.is( 'text' ) ) {\n\t\t\t\tremoveDisallowedAttributeFromNode( this, node, writer );\n\t\t\t}\n\t\t\t// In a case of `Element` iterates through positions between nodes inside this element\n\t\t\t// and filter out node before the current position, or position parent when position\n\t\t\t// is at start of an element. Using positions prevent from omitting merged nodes\n\t\t\t// see https://github.com/ckeditor/ckeditor5-engine/issues/1789.\n\t\t\telse {\n\t\t\t\tconst rangeInNode = Range._createIn( node );\n\t\t\t\tconst positionsInRange = rangeInNode.getPositions();\n\n\t\t\t\tfor ( const position of positionsInRange ) {\n\t\t\t\t\tconst item = position.nodeBefore || position.parent;\n\n\t\t\t\t\tremoveDisallowedAttributeFromNode( this, item, writer );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Creates an instance of the schema context.\n\t *\n\t * @param {module:engine/model/schema~SchemaContextDefinition} context\n\t * @returns {module:engine/model/schema~SchemaContext}\n\t */\n\tcreateContext( context ) {\n\t\treturn new SchemaContext( context );\n\t}\n\n\t/**\n\t * @private\n\t */\n\t_clearCache() {\n\t\tthis._compiledDefinitions = null;\n\t}\n\n\t/**\n\t * @private\n\t */\n\t_compile() {\n\t\tconst compiledDefinitions = {};\n\t\tconst sourceRules = this._sourceDefinitions;\n\t\tconst itemNames = Object.keys( sourceRules );\n\n\t\tfor ( const itemName of itemNames ) {\n\t\t\tcompiledDefinitions[ itemName ] = compileBaseItemRule( sourceRules[ itemName ], itemName );\n\t\t}\n\n\t\tfor ( const itemName of itemNames ) {\n\t\t\tcompileAllowContentOf( compiledDefinitions, itemName );\n\t\t}\n\n\t\tfor ( const itemName of itemNames ) {\n\t\t\tcompileAllowWhere( compiledDefinitions, itemName );\n\t\t}\n\n\t\tfor ( const itemName of itemNames ) {\n\t\t\tcompileAllowAttributesOf( compiledDefinitions, itemName );\n\t\t\tcompileInheritPropertiesFrom( compiledDefinitions, itemName );\n\t\t}\n\n\t\tfor ( const itemName of itemNames ) {\n\t\t\tcleanUpAllowIn( compiledDefinitions, itemName );\n\t\t\tcleanUpAllowAttributes( compiledDefinitions, itemName );\n\t\t}\n\n\t\tthis._compiledDefinitions = compiledDefinitions;\n\t}\n\n\t/**\n\t * @private\n\t * @param {module:engine/model/schema~SchemaCompiledItemDefinition} def\n\t * @param {module:engine/model/schema~SchemaContext} context\n\t * @param {Number} contextItemIndex\n\t */\n\t_checkContextMatch( def, context, contextItemIndex = context.length - 1 ) {\n\t\tconst contextItem = context.getItem( contextItemIndex );\n\n\t\tif ( def.allowIn.includes( contextItem.name ) ) {\n\t\t\tif ( contextItemIndex == 0 ) {\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\tconst parentRule = this.getDefinition( contextItem );\n\n\t\t\t\treturn this._checkContextMatch( parentRule, context, contextItemIndex - 1 );\n\t\t\t}\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Takes a flat range and an attribute name. Traverses the range recursively and deeply to find and return all ranges\n\t * inside the given range on which the attribute can be applied.\n\t *\n\t * This is a helper function for {@link ~Schema#getValidRanges}.\n\t *\n\t * @private\n\t * @param {module:engine/model/range~Range} range Range to process.\n\t * @param {String} attribute The name of the attribute to check.\n\t * @returns {Iterable.<module:engine/model/range~Range>} Ranges in which the attribute is allowed.\n\t */\n\t* _getValidRangesForRange( range, attribute ) {\n\t\tlet start = range.start;\n\t\tlet end = range.start;\n\n\t\tfor ( const item of range.getItems( { shallow: true } ) ) {\n\t\t\tif ( item.is( 'element' ) ) {\n\t\t\t\tyield* this._getValidRangesForRange( Range._createIn( item ), attribute );\n\t\t\t}\n\n\t\t\tif ( !this.checkAttribute( item, attribute ) ) {\n\t\t\t\tif ( !start.isEqual( end ) ) {\n\t\t\t\t\tyield new Range( start, end );\n\t\t\t\t}\n\n\t\t\t\tstart = Position._createAfter( item );\n\t\t\t}\n\n\t\t\tend = Position._createAfter( item );\n\t\t}\n\n\t\tif ( !start.isEqual( end ) ) {\n\t\t\tyield new Range( start, end );\n\t\t}\n\t}\n}\n\nmix( Schema, ObservableMixin );\n\n/**\n * Event fired when the {@link #checkChild} method is called. It allows plugging in\n * additional behavior – e.g. implementing rules which cannot be defined using the declarative\n * {@link module:engine/model/schema~SchemaItemDefinition} interface.\n *\n * **Note:** The {@link #addChildCheck} method is a more handy way to register callbacks. Internally,\n * it registers a listener to this event but comes with a simpler API and it is the recommended choice\n * in most of the cases.\n *\n * The {@link #checkChild} method fires an event because it is\n * {@link module:utils/observablemixin~ObservableMixin#decorate decorated} with it. Thanks to that you can\n * use this event in a various way, but the most important use case is overriding standard behaviour of the\n * `checkChild()` method. Let's see a typical listener template:\n *\n *\t\tschema.on( 'checkChild', ( evt, args ) => {\n *\t\t\tconst context = args[ 0 ];\n *\t\t\tconst childDefinition = args[ 1 ];\n *\t\t}, { priority: 'high' } );\n *\n * The listener is added with a `high` priority to be executed before the default method is really called. The `args` callback\n * parameter contains arguments passed to `checkChild( context, child )`. However, the `context` parameter is already\n * normalized to a {@link module:engine/model/schema~SchemaContext} instance and `child` to a\n * {@link module:engine/model/schema~SchemaCompiledItemDefinition} instance, so you don't have to worry about\n * the various ways how `context` and `child` may be passed to `checkChild()`.\n *\n * **Note:** `childDefinition` may be `undefined` if `checkChild()` was called with a non-registered element.\n *\n * So, in order to implement a rule \"disallow `heading1` in `blockQuote`\" you can add such a listener:\n *\n *\t\tschema.on( 'checkChild', ( evt, args ) => {\n *\t\t\tconst context = args[ 0 ];\n *\t\t\tconst childDefinition = args[ 1 ];\n *\n *\t\t\tif ( context.endsWith( 'blockQuote' ) && childDefinition && childDefinition.name == 'heading1' ) {\n *\t\t\t\t// Prevent next listeners from being called.\n *\t\t\t\tevt.stop();\n *\t\t\t\t// Set the checkChild()'s return value.\n *\t\t\t\tevt.return = false;\n *\t\t\t}\n *\t\t}, { priority: 'high' } );\n *\n * Allowing elements in specific contexts will be a far less common use case, because it's normally handled by\n * `allowIn` rule from {@link module:engine/model/schema~SchemaItemDefinition} but if you have a complex scenario\n * where `listItem` should be allowed only in element `foo` which must be in element `bar`, then this would be the way:\n *\n *\t\tschema.on( 'checkChild', ( evt, args ) => {\n *\t\t\tconst context = args[ 0 ];\n *\t\t\tconst childDefinition = args[ 1 ];\n *\n *\t\t\tif ( context.endsWith( 'bar foo' ) && childDefinition.name == 'listItem' ) {\n *\t\t\t\t// Prevent next listeners from being called.\n *\t\t\t\tevt.stop();\n *\t\t\t\t// Set the checkChild()'s return value.\n *\t\t\t\tevt.return = true;\n *\t\t\t}\n *\t\t}, { priority: 'high' } );\n *\n * @event checkChild\n * @param {Array} args The `checkChild()`'s arguments.\n */\n\n/**\n * Event fired when the {@link #checkAttribute} method is called. It allows plugging in\n * additional behavior – e.g. implementing rules which cannot be defined using the declarative\n * {@link module:engine/model/schema~SchemaItemDefinition} interface.\n *\n * **Note:** The {@link #addAttributeCheck} method is a more handy way to register callbacks. Internally,\n * it registers a listener to this event but comes with a simpler API and it is the recommended choice\n * in most of the cases.\n *\n * The {@link #checkAttribute} method fires an event because it's\n * {@link module:utils/observablemixin~ObservableMixin#decorate decorated} with it. Thanks to that you can\n * use this event in a various way, but the most important use case is overriding standard behaviour of the\n * `checkAttribute()` method. Let's see a typical listener template:\n *\n *\t\tschema.on( 'checkAttribute', ( evt, args ) => {\n *\t\t\tconst context = args[ 0 ];\n *\t\t\tconst attributeName = args[ 1 ];\n *\t\t}, { priority: 'high' } );\n *\n * The listener is added with a `high` priority to be executed before the default method is really called. The `args` callback\n * parameter contains arguments passed to `checkAttribute( context, attributeName )`. However, the `context` parameter is already\n * normalized to a {@link module:engine/model/schema~SchemaContext} instance, so you don't have to worry about\n * the various ways how `context` may be passed to `checkAttribute()`.\n *\n * So, in order to implement a rule \"disallow `bold` in a text which is in a `heading1` you can add such a listener:\n *\n *\t\tschema.on( 'checkAttribute', ( evt, args ) => {\n *\t\t\tconst context = args[ 0 ];\n *\t\t\tconst atributeName = args[ 1 ];\n *\n *\t\t\tif ( context.endsWith( 'heading1 $text' ) && attributeName == 'bold' ) {\n *\t\t\t\t// Prevent next listeners from being called.\n *\t\t\t\tevt.stop();\n *\t\t\t\t// Set the checkAttribute()'s return value.\n *\t\t\t\tevt.return = false;\n *\t\t\t}\n *\t\t}, { priority: 'high' } );\n *\n * Allowing attributes in specific contexts will be a far less common use case, because it's normally handled by\n * `allowAttributes` rule from {@link module:engine/model/schema~SchemaItemDefinition} but if you have a complex scenario\n * where `bold` should be allowed only in element `foo` which must be in element `bar`, then this would be the way:\n *\n *\t\tschema.on( 'checkAttribute', ( evt, args ) => {\n *\t\t\tconst context = args[ 0 ];\n *\t\t\tconst atributeName = args[ 1 ];\n *\n *\t\t\tif ( context.endsWith( 'bar foo $text' ) && attributeName == 'bold' ) {\n *\t\t\t\t// Prevent next listeners from being called.\n *\t\t\t\tevt.stop();\n *\t\t\t\t// Set the checkAttribute()'s return value.\n *\t\t\t\tevt.return = true;\n *\t\t\t}\n *\t\t}, { priority: 'high' } );\n *\n * @event checkAttribute\n * @param {Array} args The `checkAttribute()`'s arguments.\n */\n\n/**\n * A definition of a {@link module:engine/model/schema~Schema schema} item.\n *\n * You can define the following rules:\n *\n * * `allowIn` &ndash; A string or an array of strings. Defines in which other items this item will be allowed.\n * * `allowAttributes` &ndash; A string or an array of strings. Defines allowed attributes of the given item.\n * * `allowContentOf` &ndash; A string or an array of strings. Inherits \"allowed children\" from other items.\n * * `allowWhere` &ndash; A string or an array of strings. Inherits \"allowed in\" from other items.\n * * `allowAttributesOf` &ndash; A string or an array of strings. Inherits attributes from other items.\n * * `inheritTypesFrom` &ndash; A string or an array of strings. Inherits `is*` properties of other items.\n * * `inheritAllFrom` &ndash; A string. A shorthand for `allowContentOf`, `allowWhere`, `allowAttributesOf`, `inheritTypesFrom`.\n * * Additionally, you can define the following `is*` properties: `isBlock`, `isLimit`, `isObject`, `isInline`. Read about them below.\n *\n * # The is* properties\n *\n * There are 3 commonly used `is*` properties. Their role is to assign additional semantics to schema items.\n * You can define more properties but you will also need to implement support for them in the existing editor features.\n *\n * * `isBlock` &ndash; Whether this item is paragraph-like. Generally speaking, content is usually made out of blocks\n * like paragraphs, list items, images, headings, etc. All these elements are marked as blocks. A block\n * should not allow another block inside. Note: There is also the `$block` generic item which has `isBlock` set to `true`.\n * Most block type items will inherit from `$block` (through `inheritAllFrom`).\n * * `isLimit` &ndash; It can be understood as whether this element should not be split by <kbd>Enter</kbd>.\n * Examples of limit elements: `$root`, table cell, image caption, etc. In other words, all actions that happen inside\n * a limit element are limited to its content. **Note:** All objects (`isObject`) are treated as limit elements, too.\n * * `isObject` &ndash; Whether an item is \"self-contained\" and should be treated as a whole. Examples of object elements:\n * `image`, `table`, `video`, etc. **Note:** An object is also a limit, so\n * {@link module:engine/model/schema~Schema#isLimit `isLimit()`} returns `true` for object elements automatically.\n * * `isInline` &ndash; Whether an item is \"text-like\" and should be treated as an inline node. Examples of inline elements:\n * `$text`, `softBreak` (`<br>`), etc.\n *\n * # Generic items\n *\n * There are three basic generic items: `$root`, `$block` and `$text`.\n * They are defined as follows:\n *\n *\t\tthis.schema.register( '$root', {\n *\t\t\tisLimit: true\n *\t\t} );\n *\t\tthis.schema.register( '$block', {\n *\t\t\tallowIn: '$root',\n *\t\t\tisBlock: true\n *\t\t} );\n *\t\tthis.schema.register( '$text', {\n *\t\t\tallowIn: '$block',\n *\t\t\tisInline: true\n *\t\t} );\n *\n * They reflect typical editor content that is contained within one root, consists of several blocks\n * (paragraphs, lists items, headings, images) which, in turn, may contain text inside.\n *\n * By inheriting from the generic items you can define new items which will get extended by other editor features.\n * Read more about generic types in the {@glink framework/guides/deep-dive/schema Defining schema} guide.\n *\n * # Example definitions\n *\n * Allow `paragraph` in roots and block quotes:\n *\n *\t\tschema.register( 'paragraph', {\n *\t\t\tallowIn: [ '$root', 'blockQuote' ],\n *\t\t\tisBlock: true\n *\t\t} );\n *\n * Allow `paragraph` everywhere where `$block` is allowed (i.e. in `$root`):\n *\n *\t\tschema.register( 'paragraph', {\n *\t\t\tallowWhere: '$block',\n *\t\t\tisBlock: true\n *\t\t} );\n *\n * Make `image` a block object, which is allowed everywhere where `$block` is.\n * Also, allow `src` and `alt` attributes in it:\n *\n *\t\tschema.register( 'image', {\n *\t\t\tallowWhere: '$block',\n *\t\t\tallowAttributes: [ 'src', 'alt' ],\n *\t\t\tisBlock: true,\n *\t\t\tisObject: true\n *\t\t} );\n *\n * Make `caption` allowed in `image` and make it allow all the content of `$block`s (usually, `$text`).\n * Also, mark it as a limit element so it cannot be split:\n *\n *\t\tschema.register( 'caption', {\n *\t\t\tallowIn: 'image',\n *\t\t\tallowContentOf: '$block',\n *\t\t\tisLimit: true\n *\t\t} );\n *\n * Make `listItem` inherit all from `$block` but also allow additional attributes:\n *\n *\t\tschema.register( 'listItem', {\n *\t\t\tinheritAllFrom: '$block',\n *\t\t\tallowAttributes: [ 'listType', 'listIndent' ]\n *\t\t} );\n *\n * Which translates to:\n *\n *\t\tschema.register( 'listItem', {\n *\t\t\tallowWhere: '$block',\n *\t\t\tallowContentOf: '$block',\n *\t\t\tallowAttributesOf: '$block',\n *\t\t\tinheritTypesFrom: '$block',\n *\t\t\tallowAttributes: [ 'listType', 'listIndent' ]\n *\t\t} );\n *\n * # Tips\n *\n * * Check schema definitions of existing features to see how they are defined.\n * * If you want to publish your feature so other developers can use it, try to use\n * generic items as much as possible.\n * * Keep your model clean. Limit it to the actual data and store information in a normalized way.\n * * Remember about definining the `is*` properties. They do not affect the allowed structures, but they can\n * affect how the editor features treat your elements.\n *\n * @typedef {Object} module:engine/model/schema~SchemaItemDefinition\n */\n\n/**\n * A simplified version of {@link module:engine/model/schema~SchemaItemDefinition} after\n * compilation by the {@link module:engine/model/schema~Schema schema}.\n * Rules fed to the schema by {@link module:engine/model/schema~Schema#register}\n * and {@link module:engine/model/schema~Schema#extend} methods are defined in the\n * {@link module:engine/model/schema~SchemaItemDefinition} format.\n * Later on, they are compiled to `SchemaCompiledItemDefition` so when you use e.g.\n * the {@link module:engine/model/schema~Schema#getDefinition} method you get the compiled version.\n *\n * The compiled version contains only the following properties:\n *\n * * The `name` property,\n * * The `is*` properties,\n * * The `allowIn` array,\n * * The `allowAttributes` array.\n *\n * @typedef {Object} module:engine/model/schema~SchemaCompiledItemDefinition\n */\n\n/**\n * A schema context &mdash; a list of ancestors of a given position in the document.\n *\n * Considering such position:\n *\n *\t\t<$root>\n *\t\t\t<blockQuote>\n *\t\t\t\t<paragraph>\n *\t\t\t\t\t^\n *\t\t\t\t</paragraph>\n *\t\t\t</blockQuote>\n *\t\t</$root>\n *\n * The context of this position is its {@link module:engine/model/position~Position#getAncestors lists of ancestors}:\n *\n *\t\t[ rootElement, blockQuoteElement, paragraphElement ]\n *\n * Contexts are used in the {@link module:engine/model/schema~Schema#event:checkChild `Schema#checkChild`} and\n * {@link module:engine/model/schema~Schema#event:checkAttribute `Schema#checkAttribute`} events as a definition\n * of a place in the document where the check occurs. The context instances are created based on the first arguments\n * of the {@link module:engine/model/schema~Schema#checkChild `Schema#checkChild()`} and\n * {@link module:engine/model/schema~Schema#checkAttribute `Schema#checkAttribute()`} methods so when\n * using these methods you need to use {@link module:engine/model/schema~SchemaContextDefinition}s.\n */\nexport class SchemaContext {\n\t/**\n\t * Creates an instance of the context.\n\t *\n\t * @param {module:engine/model/schema~SchemaContextDefinition} context\n\t */\n\tconstructor( context ) {\n\t\tif ( context instanceof SchemaContext ) {\n\t\t\treturn context;\n\t\t}\n\n\t\tif ( typeof context == 'string' ) {\n\t\t\tcontext = [ context ];\n\t\t} else if ( !Array.isArray( context ) ) {\n\t\t\t// `context` is item or position.\n\t\t\t// Position#getAncestors() doesn't accept any parameters but it works just fine here.\n\t\t\tcontext = context.getAncestors( { includeSelf: true } );\n\t\t}\n\n\t\tif ( context[ 0 ] && typeof context[ 0 ] != 'string' && context[ 0 ].is( 'documentFragment' ) ) {\n\t\t\tcontext.shift();\n\t\t}\n\n\t\tthis._items = context.map( mapContextItem );\n\t}\n\n\t/**\n\t * The number of items.\n\t *\n\t * @type {Number}\n\t */\n\tget length() {\n\t\treturn this._items.length;\n\t}\n\n\t/**\n\t * The last item (the lowest node).\n\t *\n\t * @type {module:engine/model/schema~SchemaContextItem}\n\t */\n\tget last() {\n\t\treturn this._items[ this._items.length - 1 ];\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Iterates over all context items.\n\t *\n\t * @returns {Iterable.<module:engine/model/schema~SchemaContextItem>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this._items[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Returns a new schema context instance with an additional item.\n\t *\n\t * Item can be added as:\n\t *\n\t * \t\tconst context = new SchemaContext( [ '$root' ] );\n\t *\n\t * \t\t// An element.\n\t * \t\tconst fooElement = writer.createElement( 'fooElement' );\n\t * \t\tconst newContext = context.push( fooElement ); // [ '$root', 'fooElement' ]\n\t *\n\t * \t\t// A text node.\n\t * \t\tconst text = writer.createText( 'foobar' );\n\t * \t\tconst newContext = context.push( text ); // [ '$root', '$text' ]\n\t *\n\t * \t\t// A string (element name).\n\t * \t\tconst newContext = context.push( 'barElement' ); // [ '$root', 'barElement' ]\n\t *\n\t * **Note** {@link module:engine/model/node~Node} that is already in the model tree will be added as the only item\n\t * (without ancestors).\n\t *\n\t * @param {String|module:engine/model/node~Node|Array<String|module:engine/model/node~Node>} item An item that will be added\n\t * to the current context.\n\t * @returns {module:engine/model/schema~SchemaContext} A new schema context instance with an additional item.\n\t */\n\tpush( item ) {\n\t\tconst ctx = new SchemaContext( [ item ] );\n\n\t\tctx._items = [ ...this._items, ...ctx._items ];\n\n\t\treturn ctx;\n\t}\n\n\t/**\n\t * Gets an item on the given index.\n\t *\n\t * @returns {module:engine/model/schema~SchemaContextItem}\n\t */\n\tgetItem( index ) {\n\t\treturn this._items[ index ];\n\t}\n\n\t/**\n\t * Returns the names of items.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\t* getNames() {\n\t\tyield* this._items.map( item => item.name );\n\t}\n\n\t/**\n\t * Checks whether the context ends with the given nodes.\n\t *\n\t *\t\tconst ctx = new SchemaContext( [ rootElement, paragraphElement, textNode ] );\n\t *\n\t *\t\tctx.endsWith( '$text' ); // -> true\n\t *\t\tctx.endsWith( 'paragraph $text' ); // -> true\n\t *\t\tctx.endsWith( '$root' ); // -> false\n\t *\t\tctx.endsWith( 'paragraph' ); // -> false\n\t *\n\t * @param {String} query\n\t * @returns {Boolean}\n\t */\n\tendsWith( query ) {\n\t\treturn Array.from( this.getNames() ).join( ' ' ).endsWith( query );\n\t}\n}\n\n/**\n * The definition of a {@link module:engine/model/schema~SchemaContext schema context}.\n *\n * Contexts can be created in multiple ways:\n *\n * * By defining a **node** – in this cases this node and all its ancestors will be used.\n * * By defining a **position** in the document – in this case all its ancestors will be used.\n * * By defining an **array of nodes** – in this case this array defines the entire context.\n * * By defining a **name of node** - in this case node will be \"mocked\". It is not recommended because context\n * will be unrealistic (e.g. attributes of these nodes are not specified). However, at times this may be the only\n * way to define the context (e.g. when checking some hypothetical situation).\n * * By defining an **array of node names** (potentially, mixed with real nodes) – The same as **name of node**\n * but it is possible to create a path.\n * * By defining a {@link module:engine/model/schema~SchemaContext} instance - in this case the same instance as provided\n * will be return.\n *\n * Examples of context definitions passed to the {@link module:engine/model/schema~Schema#checkChild `Schema#checkChild()`}\n * method:\n *\n *\t\t// Assuming that we have a $root > blockQuote > paragraph structure, the following code\n *\t\t// will check node 'foo' in the following context:\n *\t\t// [ rootElement, blockQuoteElement, paragraphElement ]\n *\t\tconst contextDefinition = paragraphElement;\n * \t\tconst childToCheck = 'foo';\n *\t\tschema.checkChild( contextDefinition, childToCheck );\n *\n *\t\t// Also check in [ rootElement, blockQuoteElement, paragraphElement ].\n *\t\tschema.checkChild( model.createPositionAt( paragraphElement, 0 ), 'foo' );\n *\n *\t\t// Check in [ rootElement, paragraphElement ].\n *\t\tschema.checkChild( [ rootElement, paragraphElement ], 'foo' );\n *\n *\t\t// Check only fakeParagraphElement.\n *\t\tschema.checkChild( 'paragraph', 'foo' );\n *\n *\t\t// Check in [ fakeRootElement, fakeBarElement, paragraphElement ].\n *\t\tschema.checkChild( [ '$root', 'bar', paragraphElement ], 'foo' );\n *\n * All these `checkChild()` calls will fire {@link module:engine/model/schema~Schema#event:checkChild `Schema#checkChild`}\n * events in which `args[ 0 ]` is an instance of the context. Therefore, you can write a listener like this:\n *\n *\t\tschema.on( 'checkChild', ( evt, args ) => {\n *\t\t\tconst ctx = args[ 0 ];\n *\n *\t\t\tconsole.log( Array.from( ctx.getNames() ) );\n *\t\t} );\n *\n * Which will log the following:\n *\n *\t\t[ '$root', 'blockQuote', 'paragraph' ]\n *\t\t[ '$root', 'paragraph' ]\n *\t\t[ '$root', 'bar', 'paragraph' ]\n *\n * Note: When using the {@link module:engine/model/schema~Schema#checkAttribute `Schema#checkAttribute()`} method\n * you may want to check whether a text node may have an attribute. A {@link module:engine/model/text~Text} is a\n * correct way to define a context so you can do this:\n *\n *\t\tschema.checkAttribute( textNode, 'bold' );\n *\n * But sometimes you want to check whether a text at a given position might've had some attribute,\n * in which case you can create a context by mising an array of elements with a `'$text'` string:\n *\n *\t\t// Check in [ rootElement, paragraphElement, textNode ].\n *\t\tschema.checkChild( [ ...positionInParagraph.getAncestors(), '$text' ], 'bold' );\n *\n * @typedef {module:engine/model/node~Node|module:engine/model/position~Position|module:engine/model/schema~SchemaContext|\n * String|Array.<String|module:engine/model/node~Node>} module:engine/model/schema~SchemaContextDefinition\n */\n\n/**\n * An item of the {@link module:engine/model/schema~SchemaContext schema context}.\n *\n * It contains 3 properties:\n *\n * * `name` – the name of this item,\n * * `* getAttributeKeys()` – a generator of keys of item attributes,\n * * `getAttribute( keyName )` – a method to get attribute values.\n *\n * The context item interface is a highly simplified version of {@link module:engine/model/node~Node} and its role\n * is to expose only the information which schema checks are able to provide (which is the name of the node and\n * node's attributes).\n *\n *\t\tschema.on( 'checkChild', ( evt, args ) => {\n *\t\t\tconst ctx = args[ 0 ];\n *\t\t\tconst firstItem = ctx.getItem( 0 );\n *\n *\t\t\tconsole.log( firstItem.name ); // -> '$root'\n *\t\t\tconsole.log( firstItem.getAttribute( 'foo' ) ); // -> 'bar'\n *\t\t\tconsole.log( Array.from( firstItem.getAttributeKeys() ) ); // -> [ 'foo', 'faa' ]\n *\t\t} );\n *\n * @typedef {Object} module:engine/model/schema~SchemaContextItem\n */\n\n/**\n * A structure containing additional metadata describing the attribute.\n *\n * See {@link module:engine/model/schema~Schema#setAttributeProperties `Schema#setAttributeProperties()`} for usage examples.\n *\n * @typedef {Object} module:engine/model/schema~AttributeProperties\n * @property {Boolean} [isFormatting] Indicates that the attribute should be considered as a visual formatting, like `bold`, `italic` or\n * `fontSize` rather than semantic attribute (such as `src`, `listType`, etc.). For example, it is used by the \"Remove format\" feature.\n * @property {Boolean} [copyOnEnter] Indicates that given text attribute should be copied to the next block when enter is pressed.\n */\n\nfunction compileBaseItemRule( sourceItemRules, itemName ) {\n\tconst itemRule = {\n\t\tname: itemName,\n\n\t\tallowIn: [],\n\t\tallowContentOf: [],\n\t\tallowWhere: [],\n\n\t\tallowAttributes: [],\n\t\tallowAttributesOf: [],\n\n\t\tinheritTypesFrom: []\n\t};\n\n\tcopyTypes( sourceItemRules, itemRule );\n\n\tcopyProperty( sourceItemRules, itemRule, 'allowIn' );\n\tcopyProperty( sourceItemRules, itemRule, 'allowContentOf' );\n\tcopyProperty( sourceItemRules, itemRule, 'allowWhere' );\n\n\tcopyProperty( sourceItemRules, itemRule, 'allowAttributes' );\n\tcopyProperty( sourceItemRules, itemRule, 'allowAttributesOf' );\n\n\tcopyProperty( sourceItemRules, itemRule, 'inheritTypesFrom' );\n\n\tmakeInheritAllWork( sourceItemRules, itemRule );\n\n\treturn itemRule;\n}\n\nfunction compileAllowContentOf( compiledDefinitions, itemName ) {\n\tfor ( const allowContentOfItemName of compiledDefinitions[ itemName ].allowContentOf ) {\n\t\t// The allowContentOf property may point to an unregistered element.\n\t\tif ( compiledDefinitions[ allowContentOfItemName ] ) {\n\t\t\tconst allowedChildren = getAllowedChildren( compiledDefinitions, allowContentOfItemName );\n\n\t\t\tallowedChildren.forEach( allowedItem => {\n\t\t\t\tallowedItem.allowIn.push( itemName );\n\t\t\t} );\n\t\t}\n\t}\n\n\tdelete compiledDefinitions[ itemName ].allowContentOf;\n}\n\nfunction compileAllowWhere( compiledDefinitions, itemName ) {\n\tfor ( const allowWhereItemName of compiledDefinitions[ itemName ].allowWhere ) {\n\t\tconst inheritFrom = compiledDefinitions[ allowWhereItemName ];\n\n\t\t// The allowWhere property may point to an unregistered element.\n\t\tif ( inheritFrom ) {\n\t\t\tconst allowedIn = inheritFrom.allowIn;\n\n\t\t\tcompiledDefinitions[ itemName ].allowIn.push( ...allowedIn );\n\t\t}\n\t}\n\n\tdelete compiledDefinitions[ itemName ].allowWhere;\n}\n\nfunction compileAllowAttributesOf( compiledDefinitions, itemName ) {\n\tfor ( const allowAttributeOfItem of compiledDefinitions[ itemName ].allowAttributesOf ) {\n\t\tconst inheritFrom = compiledDefinitions[ allowAttributeOfItem ];\n\n\t\tif ( inheritFrom ) {\n\t\t\tconst inheritAttributes = inheritFrom.allowAttributes;\n\n\t\t\tcompiledDefinitions[ itemName ].allowAttributes.push( ...inheritAttributes );\n\t\t}\n\t}\n\n\tdelete compiledDefinitions[ itemName ].allowAttributesOf;\n}\n\nfunction compileInheritPropertiesFrom( compiledDefinitions, itemName ) {\n\tconst item = compiledDefinitions[ itemName ];\n\n\tfor ( const inheritPropertiesOfItem of item.inheritTypesFrom ) {\n\t\tconst inheritFrom = compiledDefinitions[ inheritPropertiesOfItem ];\n\n\t\tif ( inheritFrom ) {\n\t\t\tconst typeNames = Object.keys( inheritFrom ).filter( name => name.startsWith( 'is' ) );\n\n\t\t\tfor ( const name of typeNames ) {\n\t\t\t\tif ( !( name in item ) ) {\n\t\t\t\t\titem[ name ] = inheritFrom[ name ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdelete item.inheritTypesFrom;\n}\n\n// Remove items which weren't registered (because it may break some checks or we'd need to complicate them).\n// Make sure allowIn doesn't contain repeated values.\nfunction cleanUpAllowIn( compiledDefinitions, itemName ) {\n\tconst itemRule = compiledDefinitions[ itemName ];\n\tconst existingItems = itemRule.allowIn.filter( itemToCheck => compiledDefinitions[ itemToCheck ] );\n\n\titemRule.allowIn = Array.from( new Set( existingItems ) );\n}\n\nfunction cleanUpAllowAttributes( compiledDefinitions, itemName ) {\n\tconst itemRule = compiledDefinitions[ itemName ];\n\n\titemRule.allowAttributes = Array.from( new Set( itemRule.allowAttributes ) );\n}\n\nfunction copyTypes( sourceItemRules, itemRule ) {\n\tfor ( const sourceItemRule of sourceItemRules ) {\n\t\tconst typeNames = Object.keys( sourceItemRule ).filter( name => name.startsWith( 'is' ) );\n\n\t\tfor ( const name of typeNames ) {\n\t\t\titemRule[ name ] = sourceItemRule[ name ];\n\t\t}\n\t}\n}\n\nfunction copyProperty( sourceItemRules, itemRule, propertyName ) {\n\tfor ( const sourceItemRule of sourceItemRules ) {\n\t\tif ( typeof sourceItemRule[ propertyName ] == 'string' ) {\n\t\t\titemRule[ propertyName ].push( sourceItemRule[ propertyName ] );\n\t\t} else if ( Array.isArray( sourceItemRule[ propertyName ] ) ) {\n\t\t\titemRule[ propertyName ].push( ...sourceItemRule[ propertyName ] );\n\t\t}\n\t}\n}\n\nfunction makeInheritAllWork( sourceItemRules, itemRule ) {\n\tfor ( const sourceItemRule of sourceItemRules ) {\n\t\tconst inheritFrom = sourceItemRule.inheritAllFrom;\n\n\t\tif ( inheritFrom ) {\n\t\t\titemRule.allowContentOf.push( inheritFrom );\n\t\t\titemRule.allowWhere.push( inheritFrom );\n\t\t\titemRule.allowAttributesOf.push( inheritFrom );\n\t\t\titemRule.inheritTypesFrom.push( inheritFrom );\n\t\t}\n\t}\n}\n\nfunction getAllowedChildren( compiledDefinitions, itemName ) {\n\tconst itemRule = compiledDefinitions[ itemName ];\n\n\treturn getValues( compiledDefinitions ).filter( def => def.allowIn.includes( itemRule.name ) );\n}\n\nfunction getValues( obj ) {\n\treturn Object.keys( obj ).map( key => obj[ key ] );\n}\n\nfunction mapContextItem( ctxItem ) {\n\tif ( typeof ctxItem == 'string' ) {\n\t\treturn {\n\t\t\tname: ctxItem,\n\n\t\t\t* getAttributeKeys() {},\n\n\t\t\tgetAttribute() {}\n\t\t};\n\t} else {\n\t\treturn {\n\t\t\t// '$text' means text nodes and text proxies.\n\t\t\tname: ctxItem.is( 'element' ) ? ctxItem.name : '$text',\n\n\t\t\t* getAttributeKeys() {\n\t\t\t\tyield* ctxItem.getAttributeKeys();\n\t\t\t},\n\n\t\t\tgetAttribute( key ) {\n\t\t\t\treturn ctxItem.getAttribute( key );\n\t\t\t}\n\t\t};\n\t}\n}\n\n// Generator function returning values from provided walkers, switching between them at each iteration. If only one walker\n// is provided it will return data only from that walker.\n//\n// @param {module:engine/module/treewalker~TreeWalker} [backward] Walker iterating in backward direction.\n// @param {module:engine/module/treewalker~TreeWalker} [forward] Walker iterating in forward direction.\n// @returns {Iterable.<Object>} Object returned at each iteration contains `value` and `walker` (informing which walker returned\n// given value) fields.\nfunction* combineWalkers( backward, forward ) {\n\tlet done = false;\n\n\twhile ( !done ) {\n\t\tdone = true;\n\n\t\tif ( backward ) {\n\t\t\tconst step = backward.next();\n\n\t\t\tif ( !step.done ) {\n\t\t\t\tdone = false;\n\t\t\t\tyield {\n\t\t\t\t\twalker: backward,\n\t\t\t\t\tvalue: step.value\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( forward ) {\n\t\t\tconst step = forward.next();\n\n\t\t\tif ( !step.done ) {\n\t\t\t\tdone = false;\n\t\t\t\tyield {\n\t\t\t\t\twalker: forward,\n\t\t\t\t\tvalue: step.value\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Takes an array of non-intersecting ranges. For each of them gets minimal flat ranges covering that range and returns\n// all those minimal flat ranges.\n//\n// @param {Array.<module:engine/model/range~Range>} ranges Ranges to process.\n// @returns {Iterable.<module:engine/model/range~Range>} Minimal flat ranges of given `ranges`.\nfunction* convertToMinimalFlatRanges( ranges ) {\n\tfor ( const range of ranges ) {\n\t\tyield* range.getMinimalFlatRanges();\n\t}\n}\n\nfunction removeDisallowedAttributeFromNode( schema, node, writer ) {\n\tfor ( const attribute of node.getAttributeKeys() ) {\n\t\tif ( !schema.checkAttribute( node, attribute ) ) {\n\t\t\twriter.removeAttribute( attribute, node );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/conversion/upcastdispatcher\n */\n\nimport ViewConsumable from './viewconsumable';\nimport ModelRange from '../model/range';\nimport ModelPosition from '../model/position';\nimport { SchemaContext } from '../model/schema';\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * `UpcastDispatcher` is a central point of {@link module:engine/view/view view} conversion, which is a process of\n * converting given {@link module:engine/view/documentfragment~DocumentFragment view document fragment} or\n * {@link module:engine/view/element~Element} into another structure.\n * In default application, {@link module:engine/view/view view} is converted to {@link module:engine/model/model}.\n *\n * During conversion process, for all {@link module:engine/view/node~Node view nodes} from the converted view document fragment,\n * `UpcastDispatcher` fires corresponding events. Special callbacks called \"converters\" should listen to\n * `UpcastDispatcher` for those events.\n *\n * Each callback, as the second argument, is passed a special object `data` that has `viewItem`, `modelCursor` and\n * `modelRange` properties. `viewItem` property contains {@link module:engine/view/node~Node view node} or\n * {@link module:engine/view/documentfragment~DocumentFragment view document fragment}\n * that is converted at the moment and might be handled by the callback. `modelRange` property should be used to save the result\n * of conversion and is always a {@link module:engine/model/range~Range} when conversion result is correct.\n * `modelCursor` property is a {@link module:engine/model/position~Position position} on which conversion result will be inserted\n * and is a context according to {@link module:engine/model/schema~Schema schema} will be checked before the conversion.\n * See also {@link ~UpcastDispatcher#convert}. It is also shared by reference by all callbacks listening to given event.\n *\n * The third parameter passed to a callback is an instance of {@link ~UpcastDispatcher}\n * which provides additional tools for converters.\n *\n * Examples of providing callbacks for `UpcastDispatcher`:\n *\n *\t\t// Converter for links (<a>).\n *\t\teditor.data.upcastDispatcher.on( 'element:a', ( evt, data, conversionApi ) => {\n *\t\t\tif ( conversionApi.consumable.consume( data.viewItem, { name: true, attributes: [ 'href' ] } ) ) {\n *\t\t\t\t// <a> element is inline and is represented by an attribute in the model.\n *\t\t\t\t// This is why we need to convert only children.\n *\t\t\t\tconst { modelRange } = conversionApi.convertChildren( data.viewItem, data.modelCursor );\n *\n *\t\t\t\tfor ( let item of modelRange.getItems() ) {\n *\t\t\t\t\tif ( conversionApi.schema.checkAttribute( item, 'linkHref' ) ) {\n *\t\t\t\t\t\tconversionApi.writer.setAttribute( 'linkHref', data.viewItem.getAttribute( 'href' ), item );\n *\t\t\t\t\t}\n *\t\t\t\t}\n *\t\t\t}\n *\t\t} );\n *\n *\t\t// Convert <p>'s font-size style.\n *\t\t// Note: You should use a low-priority observer in order to ensure that\n *\t\t// it's executed after the element-to-element converter.\n *\t\teditor.data.upcastDispatcher.on( 'element:p', ( evt, data, conversionApi ) => {\n *\t\t\tconst { consumable, schema, writer } = conversionApi;\n *\n *\t\t\tif ( !consumable.consume( data.viewItem, { style: 'font-size' } ) ) {\n *\t\t\t\treturn;\n *\t\t\t}\n *\n *\t\t\tconst fontSize = data.viewItem.getStyle( 'font-size' );\n *\n *\t\t\t// Don't go for the model element after data.modelCursor because it might happen\n *\t\t\t// that a single view element was converted to multiple model elements. Get all of them.\n *\t\t\tfor ( const item of data.modelRange.getItems( { shallow: true } ) ) {\n *\t\t\t\tif ( schema.checkAttribute( item, 'fontSize' ) ) {\n *\t\t\t\t\twriter.setAttribute( 'fontSize', fontSize, item );\n *\t\t\t\t}\n *\t\t\t}\n *\t\t}, { priority: 'low' } );\n *\n *\t\t// Convert all elements which have no custom converter into paragraph (autoparagraphing).\n * \teditor.data.upcastDispatcher.on( 'element', ( evt, data, conversionApi ) => {\n * \t \t// When element is already consumed by higher priority converters then do nothing.\n * \t \tif ( conversionApi.consumable.test( data.viewItem, { name: data.viewItem.name } ) ) {\n * \t \t\t\tconst paragraph = conversionApi.writer.createElement( 'paragraph' );\n *\n * \t \t\t\t// Find allowed parent for paragraph that we are going to insert. If current parent does not allow\n * \t \t\t\t// to insert paragraph but one of the ancestors does then split nodes to allowed parent.\n * \t \t\t\tconst splitResult = conversionApi.splitToAllowedParent( paragraph, data.modelCursor );\n *\n * \t \t\t\t// When there is no split result it means that we can't insert paragraph in this position.\n * \t \t\t\tif ( splitResult ) {\n * \t \t\t\t\t// Insert paragraph in allowed position.\n * \t \t\t\t\tconversionApi.writer.insert( paragraph, splitResult.position );\n *\n * \t \t\t\t\t// Convert children to paragraph.\n * \t \t\t\t\tconst { modelRange } = conversionApi.convertChildren(\n * \t \t\t\t\t\tdata.viewItem,\n * \t \t\t\t\t\tconversionApi.writer.createPositionAt( paragraph, 0 )\n * \t \t\t\t\t);\n *\n * \t\t\t\t\t\t// Set as conversion result, attribute converters may use this property.\n * \t \t\t\t\tdata.modelRange = conversionApi.writer.createRange(\n * \t \t\t\t\t\tconversionApi.writer.createPositionBefore( paragraph ),\n * \t \t\t\t\t\tmodelRange.end\n * \t \t\t\t\t);\n *\n * \t \t\t\t\t// Continue conversion inside paragraph.\n * \t \t\t\t\tdata.modelCursor = data.modelRange.end;\n * \t \t\t\t}\n * \t \t\t}\n * \t \t}\n * \t }, { priority: 'low' } );\n *\n * Before each conversion process, `UpcastDispatcher` fires {@link ~UpcastDispatcher#event:viewCleanup}\n * event which can be used to prepare tree view for conversion.\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n * @fires viewCleanup\n * @fires element\n * @fires text\n * @fires documentFragment\n */\nexport default class UpcastDispatcher {\n\t/**\n\t * Creates a `UpcastDispatcher` that operates using passed API.\n\t *\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi\n\t * @param {Object} [conversionApi] Additional properties for interface that will be passed to events fired\n\t * by `UpcastDispatcher`.\n\t */\n\tconstructor( conversionApi = {} ) {\n\t\t/**\n\t\t * List of the elements that were created during splitting.\n\t\t *\n\t\t * After conversion process the list is cleared.\n\t\t *\n\t\t * @private\n\t\t * @type {Map.<module:engine/model/element~Element,Array.<module:engine/model/element~Element>>}\n\t\t */\n\t\tthis._splitParts = new Map();\n\n\t\t/**\n\t\t * Position in the temporary structure where the converted content is inserted. The structure reflect the context of\n\t\t * the target position where the content will be inserted. This property is build based on the context parameter of the\n\t\t * convert method.\n\t\t *\n\t\t * @private\n\t\t * @type {module:engine/model/position~Position|null}\n\t\t */\n\t\tthis._modelCursor = null;\n\n\t\t/**\n\t\t * Interface passed by dispatcher to the events callbacks.\n\t\t *\n\t\t * @member {module:engine/conversion/upcastdispatcher~UpcastConversionApi}\n\t\t */\n\t\tthis.conversionApi = Object.assign( {}, conversionApi );\n\n\t\t// `convertItem`, `convertChildren` and `splitToAllowedParent` are bound to this `UpcastDispatcher`\n\t\t// instance and set on `conversionApi`. This way only a part of `UpcastDispatcher` API is exposed.\n\t\tthis.conversionApi.convertItem = this._convertItem.bind( this );\n\t\tthis.conversionApi.convertChildren = this._convertChildren.bind( this );\n\t\tthis.conversionApi.splitToAllowedParent = this._splitToAllowedParent.bind( this );\n\t\tthis.conversionApi.getSplitParts = this._getSplitParts.bind( this );\n\t}\n\n\t/**\n\t * Starts the conversion process. The entry point for the conversion.\n\t *\n\t * @fires element\n\t * @fires text\n\t * @fires documentFragment\n\t * @param {module:engine/view/documentfragment~DocumentFragment|module:engine/view/element~Element} viewItem\n\t * Part of the view to be converted.\n\t * @param {module:engine/model/writer~Writer} writer Instance of model writer.\n\t * @param {module:engine/model/schema~SchemaContextDefinition} [context=['$root']] Elements will be converted according to this context.\n\t * @returns {module:engine/model/documentfragment~DocumentFragment} Model data that is a result of the conversion process\n\t * wrapped in `DocumentFragment`. Converted marker elements will be set as that document fragment's\n\t * {@link module:engine/model/documentfragment~DocumentFragment#markers static markers map}.\n\t */\n\tconvert( viewItem, writer, context = [ '$root' ] ) {\n\t\tthis.fire( 'viewCleanup', viewItem );\n\n\t\t// Create context tree and set position in the top element.\n\t\t// Items will be converted according to this position.\n\t\tthis._modelCursor = createContextTree( context, writer );\n\n\t\t// Store writer in conversion as a conversion API\n\t\t// to be sure that conversion process will use the same batch.\n\t\tthis.conversionApi.writer = writer;\n\n\t\t// Create consumable values list for conversion process.\n\t\tthis.conversionApi.consumable = ViewConsumable.createFrom( viewItem );\n\n\t\t// Custom data stored by converter for conversion process.\n\t\tthis.conversionApi.store = {};\n\n\t\t// Do the conversion.\n\t\tconst { modelRange } = this._convertItem( viewItem, this._modelCursor );\n\n\t\t// Conversion result is always a document fragment so let's create it.\n\t\tconst documentFragment = writer.createDocumentFragment();\n\n\t\t// When there is a conversion result.\n\t\tif ( modelRange ) {\n\t\t\t// Remove all empty elements that were create while splitting.\n\t\t\tthis._removeEmptyElements();\n\n\t\t\t// Move all items that were converted in context tree to the document fragment.\n\t\t\tfor ( const item of Array.from( this._modelCursor.parent.getChildren() ) ) {\n\t\t\t\twriter.append( item, documentFragment );\n\t\t\t}\n\n\t\t\t// Extract temporary markers elements from model and set as static markers collection.\n\t\t\tdocumentFragment.markers = extractMarkersFromModelFragment( documentFragment, writer );\n\t\t}\n\n\t\t// Clear context position.\n\t\tthis._modelCursor = null;\n\n\t\t// Clear split elements lists.\n\t\tthis._splitParts.clear();\n\n\t\t// Clear conversion API.\n\t\tthis.conversionApi.writer = null;\n\t\tthis.conversionApi.store = null;\n\n\t\t// Return fragment as conversion result.\n\t\treturn documentFragment;\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#convertItem\n\t */\n\t_convertItem( viewItem, modelCursor ) {\n\t\tconst data = Object.assign( { viewItem, modelCursor, modelRange: null } );\n\n\t\tif ( viewItem.is( 'element' ) ) {\n\t\t\tthis.fire( 'element:' + viewItem.name, data, this.conversionApi );\n\t\t} else if ( viewItem.is( 'text' ) ) {\n\t\t\tthis.fire( 'text', data, this.conversionApi );\n\t\t} else {\n\t\t\tthis.fire( 'documentFragment', data, this.conversionApi );\n\t\t}\n\n\t\t// Handle incorrect conversion result.\n\t\tif ( data.modelRange && !( data.modelRange instanceof ModelRange ) ) {\n\t\t\t/**\n\t\t\t * Incorrect conversion result was dropped.\n\t\t\t *\n\t\t\t * {@link module:engine/model/range~Range Model range} should be a conversion result.\n\t\t\t *\n\t\t\t * @error view-conversion-dispatcher-incorrect-result\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'view-conversion-dispatcher-incorrect-result: Incorrect conversion result was dropped.', this );\n\t\t}\n\n\t\treturn { modelRange: data.modelRange, modelCursor: data.modelCursor };\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#convertChildren\n\t */\n\t_convertChildren( viewItem, modelCursor ) {\n\t\tconst modelRange = new ModelRange( modelCursor );\n\t\tlet nextModelCursor = modelCursor;\n\n\t\tfor ( const viewChild of Array.from( viewItem.getChildren() ) ) {\n\t\t\tconst result = this._convertItem( viewChild, nextModelCursor );\n\n\t\t\tif ( result.modelRange instanceof ModelRange ) {\n\t\t\t\tmodelRange.end = result.modelRange.end;\n\t\t\t\tnextModelCursor = result.modelCursor;\n\t\t\t}\n\t\t}\n\n\t\treturn { modelRange, modelCursor: nextModelCursor };\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#splitToAllowedParent\n\t */\n\t_splitToAllowedParent( node, modelCursor ) {\n\t\t// Try to find allowed parent.\n\t\tconst allowedParent = this.conversionApi.schema.findAllowedParent( modelCursor, node );\n\n\t\t// When there is no parent that allows to insert node then return `null`.\n\t\tif ( !allowedParent ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// When current position parent allows to insert node then return this position.\n\t\tif ( allowedParent === modelCursor.parent ) {\n\t\t\treturn { position: modelCursor };\n\t\t}\n\n\t\t// When allowed parent is in context tree.\n\t\tif ( this._modelCursor.parent.getAncestors().includes( allowedParent ) ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Split element to allowed parent.\n\t\tconst splitResult = this.conversionApi.writer.split( modelCursor, allowedParent );\n\n\t\t// Using the range returned by `model.Writer#split`, we will pair original elements with their split parts.\n\t\t//\n\t\t// The range returned from the writer spans \"over the split\" or, precisely saying, from the end of the original element (the one\n\t\t// that got split) to the beginning of the other part of that element:\n\t\t//\n\t\t// <limit><a><b><c>X[]Y</c></b><a></limit> ->\n\t\t// <limit><a><b><c>X[</c></b></a><a><b><c>]Y</c></b></a>\n\t\t//\n\t\t// After the split there cannot be any full node between the positions in `splitRange`. The positions are touching.\n\t\t// Also, because of how splitting works, it is easy to notice, that \"closing tags\" are in the reverse order than \"opening tags\".\n\t\t// Also, since we split all those elements, each of them has to have the other part.\n\t\t//\n\t\t// With those observations in mind, we will pair the original elements with their split parts by saving \"closing tags\" and matching\n\t\t// them with \"opening tags\" in the reverse order. For that we can use a stack.\n\t\tconst stack = [];\n\n\t\tfor ( const treeWalkerValue of splitResult.range.getWalker() ) {\n\t\t\tif ( treeWalkerValue.type == 'elementEnd' ) {\n\t\t\t\tstack.push( treeWalkerValue.item );\n\t\t\t} else {\n\t\t\t\t// There should not be any text nodes after the element is split, so the only other value is `elementStart`.\n\t\t\t\tconst originalPart = stack.pop();\n\t\t\t\tconst splitPart = treeWalkerValue.item;\n\n\t\t\t\tthis._registerSplitPair( originalPart, splitPart );\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tposition: splitResult.position,\n\t\t\tcursorParent: splitResult.range.end.parent\n\t\t};\n\t}\n\n\t/**\n\t * Registers that `splitPart` element is a split part of the `originalPart` element.\n\t *\n\t * Data set by this method is used by {@link #_getSplitParts} and {@link #_removeEmptyElements}.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} originalPart\n\t * @param {module:engine/model/element~Element} splitPart\n\t */\n\t_registerSplitPair( originalPart, splitPart ) {\n\t\tif ( !this._splitParts.has( originalPart ) ) {\n\t\t\tthis._splitParts.set( originalPart, [ originalPart ] );\n\t\t}\n\n\t\tconst list = this._splitParts.get( originalPart );\n\n\t\tthis._splitParts.set( splitPart, list );\n\t\tlist.push( splitPart );\n\t}\n\n\t/**\n\t * @private\n\t * @see module:engine/conversion/upcastdispatcher~UpcastConversionApi#getSplitParts\n\t */\n\t_getSplitParts( element ) {\n\t\tlet parts;\n\n\t\tif ( !this._splitParts.has( element ) ) {\n\t\t\tparts = [ element ];\n\t\t} else {\n\t\t\tparts = this._splitParts.get( element );\n\t\t}\n\n\t\treturn parts;\n\t}\n\n\t/**\n\t * Checks if there are any empty elements created while splitting and removes them.\n\t *\n\t * This method works recursively to re-check empty elements again after at least one element was removed in the initial call,\n\t * as some elements might have become empty after other empty elements were removed from them.\n\t *\n\t * @private\n\t */\n\t_removeEmptyElements() {\n\t\tlet anyRemoved = false;\n\n\t\tfor ( const element of this._splitParts.keys() ) {\n\t\t\tif ( element.isEmpty ) {\n\t\t\t\tthis.conversionApi.writer.remove( element );\n\t\t\t\tthis._splitParts.delete( element );\n\n\t\t\t\tanyRemoved = true;\n\t\t\t}\n\t\t}\n\n\t\tif ( anyRemoved ) {\n\t\t\tthis._removeEmptyElements();\n\t\t}\n\t}\n\n\t/**\n\t * Fired before the first conversion event, at the beginning of upcast (view to model conversion) process.\n\t *\n\t * @event viewCleanup\n\t * @param {module:engine/view/documentfragment~DocumentFragment|module:engine/view/element~Element}\n\t * viewItem Part of the view to be converted.\n\t */\n\n\t/**\n\t * Fired when {@link module:engine/view/element~Element} is converted.\n\t *\n\t * `element` is a namespace event for a class of events. Names of actually called events follow this pattern:\n\t * `element:<elementName>` where `elementName` is the name of converted element. This way listeners may listen to\n\t * all elements conversion or to conversion of specific elements.\n\t *\n\t * @event element\n\t * @param {Object} data Conversion data. Keep in mind that this object is shared by reference between all\n\t * callbacks that will be called. This means that callbacks can override values if needed, and those values will\n\t * be available in other callbacks.\n\t * @param {module:engine/view/item~Item} data.viewItem Converted item.\n\t * @param {module:engine/model/position~Position} data.modelCursor Position where a converter should start changes.\n\t * Change this value for the next converter to tell where the conversion should continue.\n\t * @param {module:engine/model/range~Range} data.modelRange The current state of conversion result. Every change to\n\t * converted element should be reflected by setting or modifying this property.\n\t * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion utilities to be used by callback.\n\t */\n\n\t/**\n\t * Fired when {@link module:engine/view/text~Text} is converted.\n\t *\n\t * @event text\n\t * @see #event:element\n\t */\n\n\t/**\n\t * Fired when {@link module:engine/view/documentfragment~DocumentFragment} is converted.\n\t *\n\t * @event documentFragment\n\t * @see #event:element\n\t */\n}\n\nmix( UpcastDispatcher, EmitterMixin );\n\n// Traverses given model item and searches elements which marks marker range. Found element is removed from\n// DocumentFragment but path of this element is stored in a Map which is then returned.\n//\n// @param {module:engine/view/documentfragment~DocumentFragment|module:engine/view/node~Node} modelItem Fragment of model.\n// @returns {Map<String, module:engine/model/range~Range>} List of static markers.\nfunction extractMarkersFromModelFragment( modelItem, writer ) {\n\tconst markerElements = new Set();\n\tconst markers = new Map();\n\n\t// Create ModelTreeWalker.\n\tconst range = ModelRange._createIn( modelItem ).getItems();\n\n\t// Walk through DocumentFragment and collect marker elements.\n\tfor ( const item of range ) {\n\t\t// Check if current element is a marker.\n\t\tif ( item.name == '$marker' ) {\n\t\t\tmarkerElements.add( item );\n\t\t}\n\t}\n\n\t// Walk through collected marker elements store its path and remove its from the DocumentFragment.\n\tfor ( const markerElement of markerElements ) {\n\t\tconst markerName = markerElement.getAttribute( 'data-name' );\n\t\tconst currentPosition = writer.createPositionBefore( markerElement );\n\n\t\t// When marker of given name is not stored it means that we have found the beginning of the range.\n\t\tif ( !markers.has( markerName ) ) {\n\t\t\tmarkers.set( markerName, new ModelRange( currentPosition.clone() ) );\n\t\t// Otherwise is means that we have found end of the marker range.\n\t\t} else {\n\t\t\tmarkers.get( markerName ).end = currentPosition.clone();\n\t\t}\n\n\t\t// Remove marker element from DocumentFragment.\n\t\twriter.remove( markerElement );\n\t}\n\n\treturn markers;\n}\n\n// Creates model fragment according to given context and returns position in the bottom (the deepest) element.\nfunction createContextTree( contextDefinition, writer ) {\n\tlet position;\n\n\tfor ( const item of new SchemaContext( contextDefinition ) ) {\n\t\tconst attributes = {};\n\n\t\tfor ( const key of item.getAttributeKeys() ) {\n\t\t\tattributes[ key ] = item.getAttribute( key );\n\t\t}\n\n\t\tconst current = writer.createElement( item.name, attributes );\n\n\t\tif ( position ) {\n\t\t\twriter.append( current, position );\n\t\t}\n\n\t\tposition = ModelPosition._createAt( current, 0 );\n\t}\n\n\treturn position;\n}\n\n/**\n * Conversion interface that is registered for given {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher}\n * and is passed as one of parameters when {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher dispatcher}\n * fires it's events.\n *\n * @interface module:engine/conversion/upcastdispatcher~UpcastConversionApi\n */\n\n/**\n * Starts conversion of given item by firing an appropriate event.\n *\n * Every fired event is passed (as first parameter) an object with `modelRange` property. Every event may set and/or\n * modify that property. When all callbacks are done, the final value of `modelRange` property is returned by this method.\n * The `modelRange` must be {@link module:engine/model/range~Range model range} or `null` (as set by default).\n *\n * @method #convertItem\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:text\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:documentFragment\n * @param {module:engine/view/item~Item} viewItem Item to convert.\n * @param {module:engine/model/position~Position} modelCursor Position of conversion.\n * @returns {Object} result Conversion result.\n * @returns {module:engine/model/range~Range|null} result.modelRange Model range containing result of item conversion,\n * created and modified by callbacks attached to fired event, or `null` if the conversion result was incorrect.\n * @returns {module:engine/model/position~Position} result.modelCursor Position where conversion should be continued.\n */\n\n/**\n * Starts conversion of all children of given item by firing appropriate events for all those children.\n *\n * @method #convertChildren\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:text\n * @fires module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:documentFragment\n * @param {module:engine/view/item~Item} viewItem Element which children should be converted.\n * @param {module:engine/model/position~Position} modelCursor Position of conversion.\n * @returns {Object} result Conversion result.\n * @returns {module:engine/model/range~Range} result.modelRange Model range containing results of conversion of all children of given item.\n * When no children was converted then range is collapsed.\n * @returns {module:engine/model/position~Position} result.modelCursor Position where conversion should be continued.\n */\n\n/**\n * Checks {@link module:engine/model/schema~Schema schema} to find allowed parent for element that we are going to insert\n * starting from given position. If current parent does not allow to insert element but one of the ancestors does then\n * split nodes to allowed parent.\n *\n * If schema allows to insert node in given position, nothing is split and object with that position is returned.\n *\n * If it was not possible to find allowed parent, `null` is returned, nothing is split.\n *\n * Otherwise, ancestors are split and object with position and the copy of the split element is returned.\n *\n * For instance, if `<image>` is not allowed in `<paragraph>` but is allowed in `$root`:\n *\n *\t\t<paragraph>foo[]bar</paragraph>\n *\n * \t-> split for `<image>` ->\n *\n * \t<paragraph>foo</paragraph>[]<paragraph>bar</paragraph>\n *\n * In the sample above position between `<paragraph>` elements will be returned as `position` and the second `paragraph`\n * as `cursorParent`.\n *\n * @method #splitToAllowedParent\n * @param {module:engine/model/position~Position} position Position on which element is going to be inserted.\n * @param {module:engine/model/node~Node} node Node to insert.\n * @returns {Object|null} Split result. If it was not possible to find allowed position `null` is returned.\n * @returns {module:engine/model/position~Position} position between split elements.\n * @returns {module:engine/model/element~Element} [cursorParent] Element inside which cursor should be placed to\n * continue conversion. When element is not defined it means that there was no split.\n */\n\n/**\n * Returns all the split parts of given `element` that were created during upcasting through using {@link #splitToAllowedParent}.\n * It enables you to easily track those elements and continue processing them after they are split during their children conversion.\n *\n *\t\t<paragraph>Foo<image />bar<image />baz</paragraph> ->\n *\t\t<paragraph>Foo</paragraph><image /><paragraph>bar</paragraph><image /><paragraph>baz</paragraph>\n *\n * For a reference to any of above paragraphs, the function will return all three paragraphs (the original element included),\n * sorted in the order of their creation (the original element is the first one).\n *\n * If given `element` was not split, an array with single element is returned.\n *\n * Example of a usage in a converter code:\n *\n *\t\tconst myElement = conversionApi.writer.createElement( 'myElement' );\n *\n *\t\t// Children conversion may split `myElement`.\n *\t\tconversionApi.convertChildren( myElement, modelCursor );\n *\n *\t\tconst splitParts = conversionApi.getSplitParts( myElement );\n *\t\tconst lastSplitPart = splitParts[ splitParts.length - 1 ];\n *\n *\t\t// Setting `data.modelRange` basing on split parts:\n *\t\tdata.modelRange = conversionApi.writer.createRange(\n *\t\t\tconversionApi.writer.createPositionBefore( myElement ),\n *\t\t\tconversionApi.writer.createPositionAfter( lastSplitPart )\n *\t\t);\n *\n *\t\t// Setting `data.modelCursor` to continue after the last split element:\n *\t\tdata.modelCursor = conversionApi.writer.createPositionAfter( lastSplitPart );\n *\n * **Tip:** if you are unable to get a reference to the original element (for example because the code is split into multiple converters\n * or even classes) but it was already converted, you might want to check first element in `data.modelRange`. This is a common situation\n * if an attribute converter is separated from an element converter.\n *\n * @method #getSplitParts\n * @param {module:engine/model/element~Element} element\n * @returns {Array.<module:engine/model/element~Element>}\n */\n\n/**\n * Stores information about what parts of processed view item are still waiting to be handled. After a piece of view item\n * was converted, appropriate consumable value should be {@link module:engine/conversion/viewconsumable~ViewConsumable#consume consumed}.\n *\n * @member {module:engine/conversion/viewconsumable~ViewConsumable} #consumable\n */\n\n/**\n * Custom data stored by converters for conversion process. Custom properties of this object can be defined and use to\n * pass parameters between converters.\n *\n * The difference between this property and `data` parameter of\n * {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element} is that `data` parameters allows you\n * to pass parameters within a single event and `store` within the whole conversion.\n *\n * @member {Object} #store\n */\n\n/**\n * The model's schema instance.\n *\n * @member {module:engine/model/schema~Schema} #schema\n */\n\n/**\n * The {@link module:engine/model/writer~Writer} instance used to manipulate data during conversion.\n *\n * @member {module:engine/model/writer~Writer} #writer\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/controller/datacontroller\n */\n\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\nimport Mapper from '../conversion/mapper';\n\nimport DowncastDispatcher from '../conversion/downcastdispatcher';\nimport { insertText } from '../conversion/downcasthelpers';\n\nimport UpcastDispatcher from '../conversion/upcastdispatcher';\nimport { convertText, convertToModelFragment } from '../conversion/upcasthelpers';\n\nimport ViewDocumentFragment from '../view/documentfragment';\nimport ViewDocument from '../view/document';\nimport ViewDowncastWriter from '../view/downcastwriter';\n\nimport ModelRange from '../model/range';\n\n/**\n * Controller for the data pipeline. The data pipeline controls how data is retrieved from the document\n * and set inside it. Hence, the controller features two methods which allow to {@link ~DataController#get get}\n * and {@link ~DataController#set set} data of the {@link ~DataController#model model}\n * using given:\n *\n * * {@link module:engine/dataprocessor/dataprocessor~DataProcessor data processor},\n * * downcast converters,\n * * upcast converters.\n *\n * An instance of the data controller is always available in the {@link module:core/editor/editor~Editor#data `editor.data`}\n * property:\n *\n *\t\teditor.data.get( { rootName: 'customRoot' } ); // -> '<p>Hello!</p>'\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class DataController {\n\t/**\n\t * Creates a data controller instance.\n\t *\n\t * @param {module:engine/model/model~Model} model Data model.\n\t * @param {module:engine/dataprocessor/dataprocessor~DataProcessor} [dataProcessor] Data processor that should be used\n\t * by the controller.\n\t */\n\tconstructor( model, dataProcessor ) {\n\t\t/**\n\t\t * Data model.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/model~Model}\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * Data processor used during the conversion.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/dataprocessor/dataprocessor~DataProcessor}\n\t\t */\n\t\tthis.processor = dataProcessor;\n\n\t\t/**\n\t\t * Mapper used for the conversion. It has no permanent bindings, because they are created when getting data and\n\t\t * cleared directly after the data are converted. However, the mapper is defined as a class property, because\n\t\t * it needs to be passed to the `DowncastDispatcher` as a conversion API.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/conversion/mapper~Mapper}\n\t\t */\n\t\tthis.mapper = new Mapper();\n\n\t\t/**\n\t\t * Downcast dispatcher used by the {@link #get get method}. Downcast converters should be attached to it.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/conversion/downcastdispatcher~DowncastDispatcher}\n\t\t */\n\t\tthis.downcastDispatcher = new DowncastDispatcher( {\n\t\t\tmapper: this.mapper\n\t\t} );\n\t\tthis.downcastDispatcher.on( 'insert:$text', insertText(), { priority: 'lowest' } );\n\n\t\t/**\n\t\t * Upcast dispatcher used by the {@link #set set method}. Upcast converters should be attached to it.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/conversion/upcastdispatcher~UpcastDispatcher}\n\t\t */\n\t\tthis.upcastDispatcher = new UpcastDispatcher( {\n\t\t\tschema: model.schema\n\t\t} );\n\n\t\t// Define default converters for text and elements.\n\t\t//\n\t\t// Note that if there is no default converter for the element it will be skipped, for instance `<b>foo</b>` will be\n\t\t// converted to nothing. We add `convertToModelFragment` as a last converter so it converts children of that\n\t\t// element to the document fragment so `<b>foo</b>` will be converted to `foo` if there is no converter for `<b>`.\n\t\tthis.upcastDispatcher.on( 'text', convertText(), { priority: 'lowest' } );\n\t\tthis.upcastDispatcher.on( 'element', convertToModelFragment(), { priority: 'lowest' } );\n\t\tthis.upcastDispatcher.on( 'documentFragment', convertToModelFragment(), { priority: 'lowest' } );\n\n\t\tthis.decorate( 'init' );\n\n\t\t// Fire `ready` event when initialisation has completed. Such low level listener gives possibility\n\t\t// to plug into initialisation pipeline without interrupting the initialisation flow.\n\t\tthis.on( 'init', () => {\n\t\t\tthis.fire( 'ready' );\n\t\t}, { priority: 'lowest' } );\n\t}\n\n\t/**\n\t * Returns the model's data converted by downcast dispatchers attached to {@link #downcastDispatcher} and\n\t * formatted by the {@link #processor data processor}.\n\t *\n\t * @param {Object} [options]\n\t * @param {String} [options.rootName='main'] Root name.\n\t * @param {String} [options.trim='empty'] Whether returned data should be trimmed. This option is set to `empty` by default,\n\t * which means whenever editor content is considered empty, an empty string will be returned. To turn off trimming completely\n\t * use `'none'`. In such cases exact content will be returned (for example `<p>&nbsp;</p>` for an empty editor).\n\t * @returns {String} Output data.\n\t */\n\tget( options ) {\n\t\tconst { rootName = 'main', trim = 'empty' } = options || {};\n\n\t\tif ( !this._checkIfRootsExists( [ rootName ] ) ) {\n\t\t\t/**\n\t\t\t * Cannot get data from a non-existing root. This error is thrown when {@link #get DataController#get() method}\n\t\t\t * is called with non-existent root name. For example, if there is an editor instance with only `main` root,\n\t\t\t * calling {@link #get} like:\n\t\t\t *\n\t\t\t *\t\tdata.get( { rootName: 'root2' } );\n\t\t\t *\n\t\t\t * will throw this error.\n\t\t\t *\n\t\t\t * @error datacontroller-get-non-existent-root\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'datacontroller-get-non-existent-root: Attempting to get data from a non-existing root.', this );\n\t\t}\n\n\t\tconst root = this.model.document.getRoot( rootName );\n\n\t\tif ( trim === 'empty' && !this.model.hasContent( root, { ignoreWhitespaces: true } ) ) {\n\t\t\treturn '';\n\t\t}\n\n\t\treturn this.stringify( root );\n\t}\n\n\t/**\n\t * Returns the content of the given {@link module:engine/model/element~Element model's element} or\n\t * {@link module:engine/model/documentfragment~DocumentFragment model document fragment} converted by the downcast converters\n\t * attached to {@link #downcastDispatcher} and formatted by the {@link #processor data processor}.\n\t *\n\t * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} modelElementOrFragment\n\t * Element whose content will be stringified.\n\t * @returns {String} Output data.\n\t */\n\tstringify( modelElementOrFragment ) {\n\t\t// Model -> view.\n\t\tconst viewDocumentFragment = this.toView( modelElementOrFragment );\n\n\t\t// View -> data.\n\t\treturn this.processor.toData( viewDocumentFragment );\n\t}\n\n\t/**\n\t * Returns the content of the given {@link module:engine/model/element~Element model element} or\n\t * {@link module:engine/model/documentfragment~DocumentFragment model document fragment} converted by the downcast\n\t * converters attached to {@link #downcastDispatcher} to a\n\t * {@link module:engine/view/documentfragment~DocumentFragment view document fragment}.\n\t *\n\t * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} modelElementOrFragment\n\t * Element or document fragment whose content will be converted.\n\t * @returns {module:engine/view/documentfragment~DocumentFragment} Output view DocumentFragment.\n\t */\n\ttoView( modelElementOrFragment ) {\n\t\t// Clear bindings so the call to this method gives correct results.\n\t\tthis.mapper.clearBindings();\n\n\t\t// First, convert elements.\n\t\tconst modelRange = ModelRange._createIn( modelElementOrFragment );\n\n\t\tconst viewDocumentFragment = new ViewDocumentFragment();\n\n\t\t// Create separate ViewDowncastWriter just for data conversion purposes.\n\t\t// We have no view controller and rendering do DOM in DataController so view.change() block is not used here.\n\t\tconst viewWriter = new ViewDowncastWriter( new ViewDocument() );\n\t\tthis.mapper.bindElements( modelElementOrFragment, viewDocumentFragment );\n\n\t\tthis.downcastDispatcher.convertInsert( modelRange, viewWriter );\n\n\t\tif ( !modelElementOrFragment.is( 'documentFragment' ) ) {\n\t\t\t// Then, if a document element is converted, convert markers.\n\t\t\t// From all document markers, get those, which \"intersect\" with the converter element.\n\t\t\tconst markers = _getMarkersRelativeToElement( modelElementOrFragment );\n\n\t\t\tfor ( const [ name, range ] of markers ) {\n\t\t\t\tthis.downcastDispatcher.convertMarkerAdd( name, range, viewWriter );\n\t\t\t}\n\t\t}\n\n\t\treturn viewDocumentFragment;\n\t}\n\n\t/**\n\t * Sets initial input data parsed by the {@link #processor data processor} and\n\t * converted by the {@link #upcastDispatcher view-to-model converters}.\n\t * Initial data can be set only to document that {@link module:engine/model/document~Document#version} is equal 0.\n\t *\n\t * **Note** This method is {@link module:utils/observablemixin~ObservableMixin#decorate decorated} which is\n\t * used by e.g. collaborative editing plugin that syncs remote data on init.\n\t *\n\t * When data is passed as a string it is initialized on a default `main` root:\n\t *\n\t *\t\tdataController.init( '<p>Foo</p>' ); // Initializes data on the `main` root.\n\t *\n\t * To initialize data on a different root or multiple roots at once, object containing `rootName` - `data` pairs should be passed:\n\t *\n\t *\t\tdataController.init( { main: '<p>Foo</p>', title: '<h1>Bar</h1>' } ); // Initializes data on the `main` and `title` roots.\n\t *\n\t * @fires init\n\t * @param {String|Object.<String,String>} data Input data as a string or an object containing `rootName` - `data`\n\t * pairs to initialize data on multiple roots at once.\n\t * @returns {Promise} Promise that is resolved after the data is set on the editor.\n\t */\n\tinit( data ) {\n\t\tif ( this.model.document.version ) {\n\t\t\t/**\n\t\t\t * Cannot set initial data to not empty {@link module:engine/model/document~Document}.\n\t\t\t * Initial data should be set once, during {@link module:core/editor/editor~Editor} initialization,\n\t\t\t * when the {@link module:engine/model/document~Document#version} is equal 0.\n\t\t\t *\n\t\t\t * @error datacontroller-init-document-not-empty\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'datacontroller-init-document-not-empty: Trying to set initial data to not empty document.', this );\n\t\t}\n\n\t\tlet initialData = {};\n\t\tif ( typeof data === 'string' ) {\n\t\t\tinitialData.main = data; // Default root is 'main'. To initiate data on a different root, object should be passed.\n\t\t} else {\n\t\t\tinitialData = data;\n\t\t}\n\n\t\tif ( !this._checkIfRootsExists( Object.keys( initialData ) ) ) {\n\t\t\t/**\n\t\t\t * Cannot init data on a non-existing root. This error is thrown when {@link #init DataController#init() method}\n\t\t\t * is called with non-existent root name. For example, if there is an editor instance with only `main` root,\n\t\t\t * calling {@link #init} like:\n\t\t\t *\n\t\t\t * \t\tdata.init( { main: '<p>Foo</p>', root2: '<p>Bar</p>' } );\n\t\t\t *\n\t\t\t * will throw this error.\n\t\t\t *\n\t\t\t * @error datacontroller-init-non-existent-root\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'datacontroller-init-non-existent-root: Attempting to init data on a non-existing root.', this );\n\t\t}\n\n\t\tthis.model.enqueueChange( 'transparent', writer => {\n\t\t\tfor ( const rootName of Object.keys( initialData ) ) {\n\t\t\t\tconst modelRoot = this.model.document.getRoot( rootName );\n\t\t\t\twriter.insert( this.parse( initialData[ rootName ], modelRoot ), modelRoot, 0 );\n\t\t\t}\n\t\t} );\n\n\t\treturn Promise.resolve();\n\t}\n\n\t/**\n\t * Sets input data parsed by the {@link #processor data processor} and\n\t * converted by the {@link #upcastDispatcher view-to-model converters}.\n\t * This method can be used any time to replace existing editor data by the new one without clearing the\n\t * {@link module:engine/model/document~Document#history document history}.\n\t *\n\t * This method also creates a batch with all the changes applied. If all you need is to parse data, use\n\t * the {@link #parse} method.\n\t *\n\t * When data is passed as a string it is set on a default `main` root:\n\t *\n\t *\t\tdataController.set( '<p>Foo</p>' ); // Sets data on the `main` root.\n\t *\n\t * To set data on a different root or multiple roots at once, object containing `rootName` - `data` pairs should be passed:\n\t *\n\t *\t\tdataController.set( { main: '<p>Foo</p>', title: '<h1>Bar</h1>' } ); // Sets data on the `main` and `title` roots.\n\t *\n\t * @param {String|Object.<String,String>} data Input data as a string or an object containing `rootName` - `data`\n\t * pairs to set data on multiple roots at once.\n\t */\n\tset( data ) {\n\t\tlet newData = {};\n\n\t\tif ( typeof data === 'string' ) {\n\t\t\tnewData.main = data; // Default root is 'main'. To set data on a different root, object should be passed.\n\t\t} else {\n\t\t\tnewData = data;\n\t\t}\n\n\t\tif ( !this._checkIfRootsExists( Object.keys( newData ) ) ) {\n\t\t\t/**\n\t\t\t * Cannot set data on a non-existing root. This error is thrown when {@link #set DataController#set() method}\n\t\t\t * is called with non-existent root name. For example, if there is an editor instance with only `main` root,\n\t\t\t * calling {@link #set} like:\n\t\t\t *\n\t\t\t * \t\tdata.set( { main: '<p>Foo</p>', root2: '<p>Bar</p>' } );\n\t\t\t *\n\t\t\t * will throw this error.\n\t\t\t *\n\t\t\t * @error datacontroller-set-non-existent-root\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'datacontroller-set-non-existent-root: Attempting to set data on a non-existing root.', this );\n\t\t}\n\n\t\tthis.model.enqueueChange( 'transparent', writer => {\n\t\t\twriter.setSelection( null );\n\t\t\twriter.removeSelectionAttribute( this.model.document.selection.getAttributeKeys() );\n\n\t\t\tfor ( const rootName of Object.keys( newData ) ) {\n\t\t\t\t// Save to model.\n\t\t\t\tconst modelRoot = this.model.document.getRoot( rootName );\n\n\t\t\t\twriter.remove( writer.createRangeIn( modelRoot ) );\n\t\t\t\twriter.insert( this.parse( newData[ rootName ], modelRoot ), modelRoot, 0 );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Returns the data parsed by the {@link #processor data processor} and then converted by upcast converters\n\t * attached to the {@link #upcastDispatcher}.\n\t *\n\t * @see #set\n\t * @param {String} data Data to parse.\n\t * @param {module:engine/model/schema~SchemaContextDefinition} [context='$root'] Base context in which the view will\n\t * be converted to the model. See: {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#convert}.\n\t * @returns {module:engine/model/documentfragment~DocumentFragment} Parsed data.\n\t */\n\tparse( data, context = '$root' ) {\n\t\t// data -> view\n\t\tconst viewDocumentFragment = this.processor.toView( data );\n\n\t\t// view -> model\n\t\treturn this.toModel( viewDocumentFragment, context );\n\t}\n\n\t/**\n\t * Returns the result of the given {@link module:engine/view/element~Element view element} or\n\t * {@link module:engine/view/documentfragment~DocumentFragment view document fragment} converted by the\n\t * {@link #upcastDispatcher view-to-model converters}, wrapped by {@link module:engine/model/documentfragment~DocumentFragment}.\n\t *\n\t * When marker elements were converted during the conversion process, it will be set as a document fragment's\n\t * {@link module:engine/model/documentfragment~DocumentFragment#markers static markers map}.\n\t *\n\t * @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} viewElementOrFragment\n\t * Element or document fragment whose content will be converted.\n\t * @param {module:engine/model/schema~SchemaContextDefinition} [context='$root'] Base context in which the view will\n\t * be converted to the model. See: {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#convert}.\n\t * @returns {module:engine/model/documentfragment~DocumentFragment} Output document fragment.\n\t */\n\ttoModel( viewElementOrFragment, context = '$root' ) {\n\t\treturn this.model.change( writer => {\n\t\t\treturn this.upcastDispatcher.convert( viewElementOrFragment, writer, context );\n\t\t} );\n\t}\n\n\t/**\n\t * Removes all event listeners set by the DataController.\n\t */\n\tdestroy() {\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Checks if all provided root names are existing editor roots.\n\t *\n\t * @private\n\t * @param {Array.<String>} rootNames Root names to check.\n\t * @returns {Boolean} Whether all provided root names are existing editor roots.\n\t */\n\t_checkIfRootsExists( rootNames ) {\n\t\tfor ( const rootName of rootNames ) {\n\t\t\tif ( !this.model.document.getRootNames().includes( rootName ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Event fired once data initialisation has finished.\n\t *\n\t * @event ready\n\t */\n\n\t/**\n\t * Event fired after {@link #init init() method} has been run. It can be {@link #listenTo listened to} to adjust/modify\n\t * the initialisation flow. However, if the `init` event is stopped or prevented, the {@link #event:ready ready event}\n\t * should be fired manually.\n\t *\n\t * The `init` event is fired by decorated {@link #init} method.\n\t * See {@link module:utils/observablemixin~ObservableMixin#decorate} for more information and samples.\n\t *\n\t * @event init\n\t */\n}\n\nmix( DataController, ObservableMixin );\n\n// Helper function for downcast conversion.\n//\n// Takes a document element (element that is added to a model document) and checks which markers are inside it\n// and which markers are containing it. If the marker is intersecting with element, the intersection is returned.\nfunction _getMarkersRelativeToElement( element ) {\n\tconst result = [];\n\tconst doc = element.root.document;\n\n\tif ( !doc ) {\n\t\treturn [];\n\t}\n\n\tconst elementRange = ModelRange._createIn( element );\n\n\tfor ( const marker of doc.model.markers ) {\n\t\tconst intersection = elementRange.getIntersection( marker.getRange() );\n\n\t\tif ( intersection ) {\n\t\t\tresult.push( [ marker.name, intersection ] );\n\t\t}\n\t}\n\n\treturn result;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/conversion/conversion\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport UpcastHelpers from './upcasthelpers';\nimport DowncastHelpers from './downcasthelpers';\n\n/**\n * A utility class that helps add converters to upcast and downcast dispatchers.\n *\n * We recommend reading the {@glink framework/guides/architecture/editing-engine Editing engine architecture} guide first to\n * understand the core concepts of the conversion mechanisms.\n *\n * An instance of the conversion manager is available in the\n * {@link module:core/editor/editor~Editor#conversion `editor.conversion`} property\n * and by default has the following groups of dispatchers (i.e. directions of conversion):\n *\n * * `downcast` (editing and data downcasts)\n * * `editingDowncast`\n * * `dataDowncast`\n * * `upcast`\n *\n * # One-way converters\n *\n * To add a converter to a specific group, use the {@link module:engine/conversion/conversion~Conversion#for `for()`}\n * method:\n *\n *\t\t// Add a converter to editing downcast and data downcast.\n *\t\teditor.conversion.for( 'downcast' ).elementToElement( config ) );\n *\n *\t\t// Add a converter to the data pipepline only:\n *\t\teditor.conversion.for( 'dataDowncast' ).elementToElement( dataConversionConfig ) );\n *\n *\t\t// And a slightly different one for the editing pipeline:\n *\t\teditor.conversion.for( 'editingDowncast' ).elementToElement( editingConversionConfig ) );\n *\n * See {@link module:engine/conversion/conversion~Conversion#for `for()`} method documentation to learn more about\n * available conversion helpers and how to use your custom ones.\n *\n * # Two-way converters\n *\n * Besides using one-way converters via the `for()` method, you can also use other methods available in this\n * class to add two-way converters (upcast and downcast):\n *\n * * {@link module:engine/conversion/conversion~Conversion#elementToElement `elementToElement()`} &ndash;\n * Model element to view element and vice versa.\n * * {@link module:engine/conversion/conversion~Conversion#attributeToElement `attributeToElement()`} &ndash;\n * Model attribute to view element and vice versa.\n * * {@link module:engine/conversion/conversion~Conversion#attributeToAttribute `attributeToAttribute()`} &ndash;\n * Model attribute to view element and vice versa.\n */\nexport default class Conversion {\n\t/**\n\t * Creates a new conversion instance.\n\t *\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastDispatcher|\n\t * Array.<module:engine/conversion/downcastdispatcher~DowncastDispatcher>} downcastDispatchers\n\t * @param {module:engine/conversion/upcastdispatcher~UpcastDispatcher|\n\t * Array.<module:engine/conversion/upcastdispatcher~UpcastDispatcher>} upcastDispatchers\n\t */\n\tconstructor( downcastDispatchers, upcastDispatchers ) {\n\t\t/**\n\t\t * Maps dispatchers group name to ConversionHelpers instances.\n\t\t *\n\t\t * @private\n\t\t * @member {Map.<String,module:engine/conversion/conversionhelpers~ConversionHelpers>}\n\t\t */\n\t\tthis._helpers = new Map();\n\n\t\t// Define default 'downcast' & 'upcast' dispatchers groups. Those groups are always available as two-way converters needs them.\n\t\tthis._downcast = Array.isArray( downcastDispatchers ) ? downcastDispatchers : [ downcastDispatchers ];\n\t\tthis._createConversionHelpers( { name: 'downcast', dispatchers: this._downcast, isDowncast: true } );\n\n\t\tthis._upcast = Array.isArray( upcastDispatchers ) ? upcastDispatchers : [ upcastDispatchers ];\n\t\tthis._createConversionHelpers( { name: 'upcast', dispatchers: this._upcast, isDowncast: false } );\n\t}\n\n\t/**\n\t * Define an alias for registered dispatcher.\n\t *\n\t *\t\tconst conversion = new Conversion(\n\t *\t\t\t[ dataDowncastDispatcher, editingDowncastDispatcher ],\n\t *\t\t\tupcastDispatcher\n\t *\t\t);\n\t *\n\t *\t\tconversion.addAlias( 'dataDowncast', dataDowncastDispatcher );\n\t *\n\t * @param {String} alias An alias of a dispatcher.\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastDispatcher|\n\t * module:engine/conversion/upcastdispatcher~UpcastDispatcher} dispatcher Dispatcher which should have an alias.\n\t */\n\taddAlias( alias, dispatcher ) {\n\t\tconst isDowncast = this._downcast.includes( dispatcher );\n\t\tconst isUpcast = this._upcast.includes( dispatcher );\n\n\t\tif ( !isUpcast && !isDowncast ) {\n\t\t\t/**\n\t\t\t * Trying to register and alias for a dispatcher that nas not been registered.\n\t\t\t *\n\t\t\t * @error conversion-add-alias-dispatcher-not-registered\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'conversion-add-alias-dispatcher-not-registered: ' +\n\t\t\t\t'Trying to register and alias for a dispatcher that nas not been registered.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tthis._createConversionHelpers( { name: alias, dispatchers: [ dispatcher ], isDowncast } );\n\t}\n\n\t/**\n\t * Provides a chainable API to assign converters to conversion dispatchers group.\n\t *\n\t * If the given group name has not been registered, the\n\t * {@link module:utils/ckeditorerror~CKEditorError `conversion-for-unknown-group` error} is thrown.\n\t *\n\t * You can use conversion helpers available directly in the `for()` chain or your custom ones via\n\t * the {@link module:engine/conversion/conversionhelpers~ConversionHelpers#add `add()`} method.\n\t *\n\t * # Using bulit-in conversion helpers\n\t *\n\t * The `for()` chain comes with a set of conversion helpers which you can use like this:\n\t *\n\t *\t\teditor.conversion.for( 'downcast' )\n\t *\t\t\t.elementToElement( config1 ) // Adds an element-to-element downcast converter.\n\t *\t\t\t.attributeToElement( config2 ); // Adds an attribute-to-element downcast converter.\n\t *\n\t *\t\teditor.conversion.for( 'upcast' )\n\t *\t\t\t.elementToAttribute( config3 ); // Adds an element-to-attribute upcast converter.\n\t *\n\t * Refer to the documentation of built-in conversion helpers to learn about their configuration options.\n\t *\n\t * * downcast (model-to-view) conversion helpers:\n\t *\n\t *\t* {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`},\n\t *\t* {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToElement `attributeToElement()`},\n\t *\t* {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToAttribute `attributeToAttribute()`}.\n\t *\t* {@link module:engine/conversion/downcasthelpers~DowncastHelpers#markerToElement `markerToElement()`}.\n\t *\t* {@link module:engine/conversion/downcasthelpers~DowncastHelpers#markerToHighlight `markerToHighlight()`}.\n\t *\n\t * * upcast (view-to-model) conversion helpers:\n\t *\n\t *\t* {@link module:engine/conversion/upcasthelpers~UpcastHelpers#elementToElement `elementToElement()`},\n\t *\t* {@link module:engine/conversion/upcasthelpers~UpcastHelpers#elementToAttribute `elementToAttribute()`},\n\t *\t* {@link module:engine/conversion/upcasthelpers~UpcastHelpers#attributeToAttribute `attributeToAttribute()`}.\n\t *\t* {@link module:engine/conversion/upcasthelpers~UpcastHelpers#elementToMarker `elementToMarker()`}.\n\t *\n\t * # Using custom conversion helpers\n\t *\n\t * If you need to implement a nontypical converter, you can do so by calling:\n\t *\n\t *\t\teditor.conversion.for( direction ).add( customHelper );\n\t *\n\t * The `.add()` method takes exactly one parameter, which is a function. This function should accept one parameter that\n\t * is a dispatcher instance. The function should add an actual converter to the passed dispatcher instance.\n\t *\n\t * Example:\n\t *\n\t *\t\teditor.conversion.for( 'upcast' ).add( dispatcher => {\n\t *\t\t\tdispatcher.on( 'element:a', ( evt, data, conversionApi ) => {\n\t *\t\t\t\t// Do something with a view <a> element.\n\t *\t\t\t} );\n\t *\t\t} );\n\t *\n\t * Refer to the documentation of {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher}\n\t * and {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher} to learn how to write\n\t * custom converters.\n\t *\n\t * @param {String} groupName The name of dispatchers group to add the converters to.\n\t * @returns {module:engine/conversion/downcasthelpers~DowncastHelpers|module:engine/conversion/upcasthelpers~UpcastHelpers}\n\t */\n\tfor( groupName ) {\n\t\tif ( !this._helpers.has( groupName ) ) {\n\t\t\t/**\n\t\t\t * Trying to add a converter to an unknown dispatchers group.\n\t\t\t *\n\t\t\t * @error conversion-for-unknown-group\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'conversion-for-unknown-group: Trying to add a converter to an unknown dispatchers group.', this );\n\t\t}\n\n\t\treturn this._helpers.get( groupName );\n\t}\n\n\t/**\n\t * Sets up converters between the model and the view that convert a model element to a view element (and vice versa).\n\t * For example, the model `<paragraph>Foo</paragraph>` is `<p>Foo</p>` in the view.\n\t *\n\t *\t\t// A simple conversion from the `paragraph` model element to the `<p>` view element (and vice versa).\n\t *\t\teditor.conversion.elementToElement( { model: 'paragraph', view: 'p' } );\n\t *\n\t *\t\t// Override other converters by specifying a converter definition with a higher priority.\n\t *\t\teditor.conversion.elementToElement( { model: 'paragraph', view: 'div', converterPriority: 'high' } );\n\t *\n\t *\t\t// View specified as an object instead of a string.\n\t *\t\teditor.conversion.elementToElement( {\n\t *\t\t\tmodel: 'fancyParagraph',\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'p',\n\t *\t\t\t\tclasses: 'fancy'\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\t// Use `upcastAlso` to define other view elements that should also be converted to a `paragraph` element.\n\t *\t\teditor.conversion.elementToElement( {\n\t *\t\t\tmodel: 'paragraph',\n\t *\t\t\tview: 'p',\n\t *\t\t\tupcastAlso: [\n\t *\t\t\t\t'div',\n\t *\t\t\t\t{\n\t *\t\t\t\t\t// Any element with the `display: block` style.\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\tdisplay: 'block'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t]\n\t *\t\t} );\n\t *\n\t *\t\t// `upcastAlso` set as callback enables a conversion of a wide range of different view elements.\n\t *\t\teditor.conversion.elementToElement( {\n\t *\t\t\tmodel: 'heading',\n\t *\t\t\tview: 'h2',\n\t *\t\t\t// Convert \"headling-like\" paragraphs to headings.\n\t *\t\t\tupcastAlso: viewElement => {\n\t *\t\t\t\tconst fontSize = viewElement.getStyle( 'font-size' );\n\t *\n\t *\t\t\t\tif ( !fontSize ) {\n\t *\t\t\t\t\treturn null;\n\t *\t\t\t\t}\n\t *\n\t *\t\t\t\tconst match = fontSize.match( /(\\d+)\\s*px/ );\n\t *\n\t *\t\t\t\tif ( !match ) {\n\t *\t\t\t\t\treturn null;\n\t *\t\t\t\t}\n\t *\n\t *\t\t\t\tconst size = Number( match[ 1 ] );\n\t *\n\t *\t\t\t\tif ( size > 26 ) {\n\t *\t\t\t\t\t// Returned value can be an object with the matched properties.\n\t *\t\t\t\t\t// These properties will be \"consumed\" during the conversion.\n\t *\t\t\t\t\t// See `engine.view.Matcher~MatcherPattern` and `engine.view.Matcher#match` for more details.\n\t *\n\t *\t\t\t\t\treturn { name: true, styles: [ 'font-size' ] };\n\t *\t\t\t\t}\n\t *\n\t *\t\t\t\treturn null;\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * `definition.model` is a `String` with a model element name to convert from or to.\n\t * See {@link module:engine/conversion/conversion~ConverterDefinition} to learn about other parameters.\n\t *\n\t * @param {module:engine/conversion/conversion~ConverterDefinition} definition The converter definition.\n\t */\n\telementToElement( definition ) {\n\t\t// Set up downcast converter.\n\t\tthis.for( 'downcast' ).elementToElement( definition );\n\n\t\t// Set up upcast converter.\n\t\tfor ( const { model, view } of _getAllUpcastDefinitions( definition ) ) {\n\t\t\tthis.for( 'upcast' )\n\t\t\t\t.elementToElement( {\n\t\t\t\t\tmodel,\n\t\t\t\t\tview,\n\t\t\t\t\tconverterPriority: definition.converterPriority\n\t\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Sets up converters between the model and the view that convert a model attribute to a view element (and vice versa).\n\t * For example, a model text node with `\"Foo\"` as data and the `bold` attribute is `<strong>Foo</strong>` in the view.\n\t *\n\t *\t\t// A simple conversion from the `bold=true` attribute to the `<strong>` view element (and vice versa).\n\t *\t\teditor.conversion.attributeToElement( { model: 'bold', view: 'strong' } );\n\t *\n\t *\t\t// Override other converters by specifying a converter definition with a higher priority.\n\t *\t\teditor.conversion.attributeToElement( { model: 'bold', view: 'b', converterPriority: 'high' } );\n\t *\n\t *\t\t// View specified as an object instead of a string.\n\t *\t\teditor.conversion.attributeToElement( {\n\t *\t\t\tmodel: 'bold',\n\t *\t\t\tview: {\n\t *\t\t\t\tname: 'span',\n\t *\t\t\t\tclasses: 'bold'\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\t// Use `config.model.name` to define the conversion only from a given node type, `$text` in this case.\n\t *\t\t// The same attribute on different elements may then be handled by a different converter.\n\t *\t\teditor.conversion.attributeToElement( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'textDecoration',\n\t *\t\t\t\tvalues: [ 'underline', 'lineThrough' ],\n\t *\t\t\t\tname: '$text'\n\t *\t\t\t},\n\t *\t\t\tview: {\n\t *\t\t\t\tunderline: {\n\t *\t\t\t\t\tname: 'span',\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'text-decoration': 'underline'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t},\n\t *\t\t\t\tlineThrough: {\n\t *\t\t\t\t\tname: 'span',\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'text-decoration': 'line-through'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\t// Use `upcastAlso` to define other view elements that should also be converted to the `bold` attribute.\n\t *\t\teditor.conversion.attributeToElement( {\n\t *\t\t\tmodel: 'bold',\n\t *\t\t\tview: 'strong',\n\t *\t\t\tupcastAlso: [\n\t *\t\t\t\t'b',\n\t *\t\t\t\t{\n\t *\t\t\t\t\tname: 'span',\n\t *\t\t\t\t\tclasses: 'bold'\n\t *\t\t\t\t},\n\t *\t\t\t\t{\n\t *\t\t\t\t\tname: 'span',\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'font-weight': 'bold'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t},\n\t *\t\t\t\tviewElement => {\n\t *\t\t\t\t\tconst fontWeight = viewElement.getStyle( 'font-weight' );\n\t *\n\t *\t\t\t\t\tif ( viewElement.is( 'span' ) && fontWeight && /\\d+/.test() && Number( fontWeight ) > 500 ) {\n\t *\t\t\t\t\t\t// Returned value can be an object with the matched properties.\n\t *\t\t\t\t\t\t// These properties will be \"consumed\" during the conversion.\n\t *\t\t\t\t\t\t// See `engine.view.Matcher~MatcherPattern` and `engine.view.Matcher#match` for more details.\n\t *\n\t *\t\t\t\t\t\treturn {\n\t *\t\t\t\t\t\t\tname: true,\n\t *\t\t\t\t\t\t\tstyles: [ 'font-weight' ]\n\t *\t\t\t\t\t\t};\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t]\n\t *\t\t} );\n\t *\n\t *\t\t// Conversion from and to a model attribute key whose value is an enum (`fontSize=big|small`).\n\t *\t\t// `upcastAlso` set as callback enables a conversion of a wide range of different view elements.\n\t *\t\teditor.conversion.attributeToElement( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'fontSize',\n\t *\t\t\t\tvalues: [ 'big', 'small' ]\n\t *\t\t\t},\n\t *\t\t\tview: {\n\t *\t\t\t\tbig: {\n\t *\t\t\t\t\tname: 'span',\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'font-size': '1.2em'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t},\n\t *\t\t\t\tsmall: {\n\t *\t\t\t\t\tname: 'span',\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'font-size': '0.8em'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t},\n\t *\t\t\tupcastAlso: {\n\t *\t\t\t\tbig: viewElement => {\n\t *\t\t\t\t\tconst fontSize = viewElement.getStyle( 'font-size' );\n\t *\n\t *\t\t\t\t\tif ( !fontSize ) {\n\t *\t\t\t\t\t\treturn null;\n\t *\t\t\t\t\t}\n\t *\n\t *\t\t\t\t\tconst match = fontSize.match( /(\\d+)\\s*px/ );\n\t *\n\t *\t\t\t\t\tif ( !match ) {\n\t *\t\t\t\t\t\treturn null;\n\t *\t\t\t\t\t}\n\t *\n\t *\t\t\t\t\tconst size = Number( match[ 1 ] );\n\t *\n\t *\t\t\t\t\tif ( viewElement.is( 'span' ) && size > 10 ) {\n\t *\t\t\t\t\t\t// Returned value can be an object with the matched properties.\n\t *\t\t\t\t\t\t// These properties will be \"consumed\" during the conversion.\n\t *\t\t\t\t\t\t// See `engine.view.Matcher~MatcherPattern` and `engine.view.Matcher#match` for more details.\n\t *\n\t *\t\t\t\t\t\treturn { name: true, styles: [ 'font-size' ] };\n\t *\t\t\t\t\t}\n\t *\n\t *\t\t\t\t\treturn null;\n\t *\t\t\t\t},\n\t *\t\t\t\tsmall: viewElement => {\n\t *\t\t\t\t\tconst fontSize = viewElement.getStyle( 'font-size' );\n\t *\n\t *\t\t\t\t\tif ( !fontSize ) {\n\t *\t\t\t\t\t\treturn null;\n\t *\t\t\t\t\t}\n\t *\n\t *\t\t\t\t\tconst match = fontSize.match( /(\\d+)\\s*px/ );\n\t *\n\t *\t\t\t\t\tif ( !match ) {\n\t *\t\t\t\t\t\treturn null;\n\t *\t\t\t\t\t}\n\t *\n\t *\t\t\t\t\tconst size = Number( match[ 1 ] );\n\t *\n\t *\t\t\t\t\tif ( viewElement.is( 'span' ) && size < 10 ) {\n\t *\t\t\t\t\t\t// Returned value can be an object with the matched properties.\n\t *\t\t\t\t\t\t// These properties will be \"consumed\" during the conversion.\n\t *\t\t\t\t\t\t// See `engine.view.Matcher~MatcherPattern` and `engine.view.Matcher#match` for more details.\n\t *\n\t *\t\t\t\t\t\treturn { name: true, styles: [ 'font-size' ] };\n\t *\t\t\t\t\t}\n\t *\n\t *\t\t\t\t\treturn null;\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * The `definition.model` parameter specifies which model attribute should be converted from or to. It can be a `{ key, value }` object\n\t * describing the attribute key and value to convert or a `String` specifying just the attribute key (then `value` is set to `true`).\n\t * See {@link module:engine/conversion/conversion~ConverterDefinition} to learn about other parameters.\n\t *\n\t * @param {module:engine/conversion/conversion~ConverterDefinition} definition The converter definition.\n\t */\n\tattributeToElement( definition ) {\n\t\t// Set up downcast converter.\n\t\tthis.for( 'downcast' ).attributeToElement( definition );\n\n\t\t// Set up upcast converter.\n\t\tfor ( const { model, view } of _getAllUpcastDefinitions( definition ) ) {\n\t\t\tthis.for( 'upcast' )\n\t\t\t\t.elementToAttribute( {\n\t\t\t\t\tview,\n\t\t\t\t\tmodel,\n\t\t\t\t\tconverterPriority: definition.converterPriority\n\t\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Sets up converters between the model and the view that convert a model attribute to a view attribute (and vice versa).\n\t * For example, `<image src='foo.jpg'></image>` is converted to `<img src='foo.jpg'></img>` (the same attribute key and value).\n\t * This type of converters is intended to be used with {@link module:engine/model/element~Element model element} nodes.\n\t * To convert text attributes {@link module:engine/conversion/conversion~Conversion#attributeToElement `attributeToElement converter`}\n\t * should be set up.\n\t *\n\t *\t\t// A simple conversion from the `source` model attribute to the `src` view attribute (and vice versa).\n\t *\t\teditor.conversion.attributeToAttribute( { model: 'source', view: 'src' } );\n\t *\n\t *\t\t// Attribute values are strictly specified.\n\t *\t\teditor.conversion.attributeToAttribute( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tname: 'image',\n\t *\t\t\t\tkey: 'aside',\n\t *\t\t\t\tvalues: [ 'aside' ]\n\t *\t\t\t},\n\t *\t\t\tview: {\n\t *\t\t\t\taside: {\n\t *\t\t\t\t\tname: 'img',\n\t *\t\t\t\t\tkey: 'class',\n\t *\t\t\t\t\tvalue: [ 'aside', 'half-size' ]\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\t// Set the style attribute.\n\t *\t\teditor.conversion.attributeToAttribute( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tname: 'image',\n\t *\t\t\t\tkey: 'aside',\n\t *\t\t\t\tvalues: [ 'aside' ]\n\t *\t\t\t},\n\t *\t\t\tview: {\n\t *\t\t\t\taside: {\n\t *\t\t\t\t\tname: 'img',\n\t *\t\t\t\t\tkey: 'style',\n\t *\t\t\t\t\tvalue: {\n\t *\t\t\t\t\t\tfloat: 'right',\n\t *\t\t\t\t\t\twidth: '50%',\n\t *\t\t\t\t\t\tmargin: '5px'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\t// Conversion from and to a model attribute key whose value is an enum (`align=right|center`).\n\t *\t\t// Use `upcastAlso` to define other view elements that should also be converted to the `align=right` attribute.\n\t *\t\teditor.conversion.attributeToAttribute( {\n\t *\t\t\tmodel: {\n\t *\t\t\t\tkey: 'align',\n\t *\t\t\t\tvalues: [ 'right', 'center' ]\n\t *\t\t\t},\n\t *\t\t\tview: {\n\t *\t\t\t\tright: {\n\t *\t\t\t\t\tkey: 'class',\n\t *\t\t\t\t\tvalue: 'align-right'\n\t *\t\t\t\t},\n\t *\t\t\t\tcenter: {\n\t *\t\t\t\t\tkey: 'class',\n\t *\t\t\t\t\tvalue: 'align-center'\n\t *\t\t\t\t}\n\t *\t\t\t},\n\t *\t\t\tupcastAlso: {\n\t *\t\t\t\tright: {\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'text-align': 'right'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t},\n\t *\t\t\t\tcenter: {\n\t *\t\t\t\t\tstyles: {\n\t *\t\t\t\t\t\t'text-align': 'center'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * The `definition.model` parameter specifies which model attribute should be converted from and to.\n\t * It can be a `{ key, [ values ], [ name ] }` object or a `String`, which will be treated like `{ key: definition.model }`.\n\t * The `key` property is the model attribute key to convert from and to.\n\t * The `values` are the possible model attribute values. If `values` is not set, the model attribute value will be the same as the\n\t * view attribute value.\n\t * If `name` is set, the conversion will be set up only for model elements with the given name.\n\t *\n\t * The `definition.view` parameter specifies which view attribute should be converted from and to.\n\t * It can be a `{ key, value, [ name ] }` object or a `String`, which will be treated like `{ key: definition.view }`.\n\t * The `key` property is the view attribute key to convert from and to.\n\t * The `value` is the view attribute value to convert from and to. If `definition.value` is not set, the view attribute value will be\n\t * the same as the model attribute value.\n\t * If `key` is `'class'`, `value` can be a `String` or an array of `String`s.\n\t * If `key` is `'style'`, `value` is an object with key-value pairs.\n\t * In other cases, `value` is a `String`.\n\t * If `name` is set, the conversion will be set up only for model elements with the given name.\n\t * If `definition.model.values` is set, `definition.view` is an object that assigns values from `definition.model.values`\n\t * to `{ key, value, [ name ] }` objects.\n\t *\n\t * `definition.upcastAlso` specifies which other matching view elements should also be upcast to the given model configuration.\n\t * If `definition.model.values` is set, `definition.upcastAlso` should be an object assigning values from `definition.model.values`\n\t * to {@link module:engine/view/matcher~MatcherPattern}s or arrays of {@link module:engine/view/matcher~MatcherPattern}s.\n\t *\n\t * **Note:** `definition.model` and `definition.view` form should be mirrored, so the same types of parameters should\n\t * be given in both parameters.\n\t *\n\t * @param {Object} definition The converter definition.\n\t * @param {String|Object} definition.model The model attribute to convert from and to.\n\t * @param {String|Object} definition.view The view attribute to convert from and to.\n\t * @param {module:engine/view/matcher~MatcherPattern|Array.<module:engine/view/matcher~MatcherPattern>} [definition.upcastAlso]\n\t * Any view element matching `definition.upcastAlso` will also be converted to the given model attribute. `definition.upcastAlso`\n\t * is used only if `config.model.values` is specified.\n\t */\n\tattributeToAttribute( definition ) {\n\t\t// Set up downcast converter.\n\t\tthis.for( 'downcast' ).attributeToAttribute( definition );\n\n\t\t// Set up upcast converter.\n\t\tfor ( const { model, view } of _getAllUpcastDefinitions( definition ) ) {\n\t\t\tthis.for( 'upcast' )\n\t\t\t\t.attributeToAttribute( {\n\t\t\t\t\tview,\n\t\t\t\t\tmodel\n\t\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Creates and caches conversion helpers for given dispatchers group.\n\t *\n\t * @private\n\t * @param {Object} options\n\t * @param {String} options.name Group name.\n\t * @param {Array.<module:engine/conversion/downcastdispatcher~DowncastDispatcher|\n\t * module:engine/conversion/upcastdispatcher~UpcastDispatcher>} options.dispatchers\n\t * @param {Boolean} options.isDowncast\n\t */\n\t_createConversionHelpers( { name, dispatchers, isDowncast } ) {\n\t\tif ( this._helpers.has( name ) ) {\n\t\t\t/**\n\t\t\t * Trying to register a group name that has already been registered.\n\t\t\t *\n\t\t\t * @error conversion-group-exists\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'conversion-group-exists: Trying to register a group name that has already been registered.', this );\n\t\t}\n\n\t\tconst helpers = isDowncast ? new DowncastHelpers( dispatchers ) : new UpcastHelpers( dispatchers );\n\n\t\tthis._helpers.set( name, helpers );\n\t}\n}\n\n/**\n * Defines how the model should be converted from and to the view.\n *\n * @typedef {Object} module:engine/conversion/conversion~ConverterDefinition\n *\n * @property {*} [model] The model conversion definition. Describes the model element or model attribute to convert. This parameter differs\n * for different functions that accept `ConverterDefinition`. See the description of the function to learn how to set it.\n * @property {module:engine/view/elementdefinition~ElementDefinition|Object} view The definition of the view element to convert from and\n * to. If `model` describes multiple values, `view` is an object that assigns these values (`view` object keys) to view element definitions\n * (`view` object values).\n * @property {module:engine/view/matcher~MatcherPattern|Array.<module:engine/view/matcher~MatcherPattern>} [upcastAlso]\n * Any view element matching `upcastAlso` will also be converted to the model. If `model` describes multiple values, `upcastAlso`\n * is an object that assigns these values (`upcastAlso` object keys) to {@link module:engine/view/matcher~MatcherPattern}s\n * (`upcastAlso` object values).\n * @property {module:utils/priorities~PriorityString} [converterPriority] The converter priority.\n */\n\n// Helper function that creates a joint array out of an item passed in `definition.view` and items passed in\n// `definition.upcastAlso`.\n//\n// @param {module:engine/conversion/conversion~ConverterDefinition} definition\n// @returns {Array} Array containing view definitions.\nfunction* _getAllUpcastDefinitions( definition ) {\n\tif ( definition.model.values ) {\n\t\tfor ( const value of definition.model.values ) {\n\t\t\tconst model = { key: definition.model.key, value };\n\t\t\tconst view = definition.view[ value ];\n\t\t\tconst upcastAlso = definition.upcastAlso ? definition.upcastAlso[ value ] : undefined;\n\n\t\t\tyield* _getUpcastDefinition( model, view, upcastAlso );\n\t\t}\n\t} else {\n\t\tyield* _getUpcastDefinition( definition.model, definition.view, definition.upcastAlso );\n\t}\n}\n\nfunction* _getUpcastDefinition( model, view, upcastAlso ) {\n\tyield { model, view };\n\n\tif ( upcastAlso ) {\n\t\tupcastAlso = Array.isArray( upcastAlso ) ? upcastAlso : [ upcastAlso ];\n\n\t\tfor ( const upcastAlsoItem of upcastAlso ) {\n\t\t\tyield { model, view: upcastAlsoItem };\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/batch\n */\n\n/**\n * A batch instance groups model changes ({@link module:engine/model/operation/operation~Operation operations}). All operations\n * grouped in a single batch can be reverted together, so you can also think about a batch as of a single undo step. If you want\n * to extend a given undo step, you can add more changes to the batch using {@link module:engine/model/model~Model#enqueueChange}:\n *\n *\t\tmodel.enqueueChange( batch, writer => {\n *\t\t\twriter.insertText( 'foo', paragraph, 'end' );\n *\t\t} );\n *\n * @see module:engine/model/model~Model#enqueueChange\n * @see module:engine/model/model~Model#change\n */\nexport default class Batch {\n\t/**\n\t * Creates a batch instance.\n\t *\n\t * @see module:engine/model/model~Model#enqueueChange\n\t * @see module:engine/model/model~Model#change\n\t * @param {'transparent'|'default'} [type='default'] The type of the batch.\n\t */\n\tconstructor( type = 'default' ) {\n\t\t/**\n\t\t * An array of operations that compose this batch.\n\t\t *\n\t\t * @readonly\n\t\t * @type {Array.<module:engine/model/operation/operation~Operation>}\n\t\t */\n\t\tthis.operations = [];\n\n\t\t/**\n\t\t * The type of the batch.\n\t\t *\n\t\t * It can be one of the following values:\n\t\t * * `'default'` &ndash; All \"normal\" batches. This is the most commonly used type.\n\t\t * * `'transparent'` &ndash; A batch that should be ignored by other features, i.e. an initial batch or collaborative editing\n\t\t * changes.\n\t\t *\n\t\t * @readonly\n\t\t * @type {'transparent'|'default'}\n\t\t */\n\t\tthis.type = type;\n\t}\n\n\t/**\n\t * Returns the base version of this batch, which is equal to the base version of the first operation in the batch.\n\t * If there are no operations in the batch or neither operation has the base version set, it returns `null`.\n\t *\n\t * @readonly\n\t * @type {Number|null}\n\t */\n\tget baseVersion() {\n\t\tfor ( const op of this.operations ) {\n\t\t\tif ( op.baseVersion !== null ) {\n\t\t\t\treturn op.baseVersion;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Adds an operation to the batch instance.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation An operation to add.\n\t * @returns {module:engine/model/operation/operation~Operation} The added operation.\n\t */\n\taddOperation( operation ) {\n\t\toperation.batch = this;\n\t\tthis.operations.push( operation );\n\n\t\treturn operation;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/operation\n */\n\n/**\n * Abstract base operation class.\n *\n * @abstract\n */\nexport default class Operation {\n\t/**\n\t * Base operation constructor.\n\t *\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( baseVersion ) {\n\t\t/**\n\t\t * {@link module:engine/model/document~Document#version} on which operation can be applied. If you try to\n\t\t * {@link module:engine/model/model~Model#applyOperation apply} operation with different base version than the\n\t\t * {@link module:engine/model/document~Document#version document version} the\n\t\t * {@link module:utils/ckeditorerror~CKEditorError model-document-applyOperation-wrong-version} error is thrown.\n\t\t *\n\t\t * @member {Number}\n\t\t */\n\t\tthis.baseVersion = baseVersion;\n\n\t\t/**\n\t\t * Defines whether operation is executed on attached or detached {@link module:engine/model/item~Item items}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} #isDocumentOperation\n\t\t */\n\t\tthis.isDocumentOperation = this.baseVersion !== null;\n\n\t\t/**\n\t\t * {@link module:engine/model/batch~Batch Batch} to which the operation is added or `null` if the operation is not\n\t\t * added to any batch yet.\n\t\t *\n\t\t * @member {module:engine/model/batch~Batch|null} #batch\n\t\t */\n\t\tthis.batch = null;\n\n\t\t/**\n\t\t * Operation type.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} #type\n\t\t */\n\n\t\t/**\n\t\t * Creates and returns an operation that has the same parameters as this operation.\n\t\t *\n\t\t * @method #clone\n\t\t * @returns {module:engine/model/operation/operation~Operation} Clone of this operation.\n\t\t */\n\n\t\t/**\n\t\t * Creates and returns a reverse operation. Reverse operation when executed right after\n\t\t * the original operation will bring back tree model state to the point before the original\n\t\t * operation execution. In other words, it reverses changes done by the original operation.\n\t\t *\n\t\t * Keep in mind that tree model state may change since executing the original operation,\n\t\t * so reverse operation will be \"outdated\". In that case you will need to transform it by\n\t\t * all operations that were executed after the original operation.\n\t\t *\n\t\t * @method #getReversed\n\t\t * @returns {module:engine/model/operation/operation~Operation} Reversed operation.\n\t\t */\n\n\t\t/**\n\t\t * Executes the operation - modifications described by the operation properties will be applied to the model tree.\n\t\t *\n\t\t * @protected\n\t\t * @method #_execute\n\t\t */\n\t}\n\n\t/**\n\t * Checks whether the operation's parameters are correct and the operation can be correctly executed. Throws\n\t * an error if operation is not valid.\n\t *\n\t * @protected\n\t * @method #_validate\n\t */\n\t_validate() {\n\t}\n\n\t/**\n\t * Custom toJSON method to solve child-parent circular dependencies.\n\t *\n\t * @method #toJSON\n\t * @returns {Object} Clone of this object with the operation property replaced with string.\n\t */\n\ttoJSON() {\n\t\t// This method creates only a shallow copy, all nested objects should be defined separately.\n\t\t// See https://github.com/ckeditor/ckeditor5-engine/issues/1477.\n\t\tconst json = Object.assign( {}, this );\n\n\t\tjson.__className = this.constructor.className;\n\n\t\t// Remove reference to the parent `Batch` to avoid circular dependencies.\n\t\tdelete json.batch;\n\n\t\t// Only document operations are shared with other clients so it is not necessary to keep this information.\n\t\tdelete json.isDocumentOperation;\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Name of the operation class used for serialization.\n\t *\n\t * @type {String}\n\t */\n\tstatic get className() {\n\t\treturn 'Operation';\n\t}\n\n\t/**\n\t * Creates Operation object from deserilized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} doc Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/operation~Operation}\n\t */\n\tstatic fromJSON( json ) {\n\t\treturn new this( json.baseVersion );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 module:engine/model/documentfragment\n */\n\nimport NodeList from './nodelist';\nimport Element from './element';\nimport Text from './text';\nimport TextProxy from './textproxy';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\n\n/**\n * DocumentFragment represents a part of model which does not have a common root but it's top-level nodes\n * can be seen as siblings. In other words, it is a detached part of model tree, without a root.\n *\n * DocumentFragment has own {@link module:engine/model/markercollection~MarkerCollection}. Markers from this collection\n * will be set to the {@link module:engine/model/model~Model#markers model markers} by a\n * {@link module:engine/model/writer~Writer#insert} function.\n */\nexport default class DocumentFragment {\n\t/**\n\t * Creates an empty `DocumentFragment`.\n\t *\n\t * **Note:** Constructor of this class shouldn't be used directly in the code.\n\t * Use the {@link module:engine/model/writer~Writer#createDocumentFragment} method instead.\n\t *\n\t * @protected\n\t * @param {module:engine/model/node~Node|Iterable.<module:engine/model/node~Node>} [children]\n\t * Nodes to be contained inside the `DocumentFragment`.\n\t */\n\tconstructor( children ) {\n\t\t/**\n\t\t * DocumentFragment static markers map. This is a list of names and {@link module:engine/model/range~Range ranges}\n\t\t * which will be set as Markers to {@link module:engine/model/model~Model#markers model markers collection}\n\t\t * when DocumentFragment will be inserted to the document.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Map<String,module:engine/model/range~Range>} module:engine/model/documentfragment~DocumentFragment#markers\n\t\t */\n\t\tthis.markers = new Map();\n\n\t\t/**\n\t\t * List of nodes contained inside the document fragment.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/nodelist~NodeList} module:engine/model/documentfragment~DocumentFragment#_children\n\t\t */\n\t\tthis._children = new NodeList();\n\n\t\tif ( children ) {\n\t\t\tthis._insertChild( 0, children );\n\t\t}\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all nodes contained inside this document fragment.\n\t *\n\t * @returns {Iterable.<module:engine/model/node~Node>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this.getChildren();\n\t}\n\n\t/**\n\t * Number of this document fragment's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget childCount() {\n\t\treturn this._children.length;\n\t}\n\n\t/**\n\t * Sum of {@link module:engine/model/node~Node#offsetSize offset sizes} of all of this document fragment's children.\n\t *\n\t * @readonly\n\t * @type {Number}\n\t */\n\tget maxOffset() {\n\t\treturn this._children.maxOffset;\n\t}\n\n\t/**\n\t * Is `true` if there are no nodes inside this document fragment, `false` otherwise.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isEmpty() {\n\t\treturn this.childCount === 0;\n\t}\n\n\t/**\n\t * Artificial root of `DocumentFragment`. Returns itself. Added for compatibility reasons.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tget root() {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Artificial parent of `DocumentFragment`. Returns `null`. Added for compatibility reasons.\n\t *\n\t * @readonly\n\t * @type {null}\n\t */\n\tget parent() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given type.\n\t *\n\t *\t\tdocFrag.is( 'documentFragment' ); // -> true\n\t *\t\tdocFrag.is( 'model:documentFragment' ); // -> true\n\t *\n\t *\t\tdocFrag.is( 'view:documentFragment' ); // -> false\n\t *\t\tdocFrag.is( 'element' ); // -> false\n\t *\t\tdocFrag.is( 'node' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'documentFragment' || type == 'model:documentFragment';\n\t}\n\n\t/**\n\t * Gets the child at the given index. Returns `null` if incorrect index was passed.\n\t *\n\t * @param {Number} index Index of child.\n\t * @returns {module:engine/model/node~Node|null} Child node.\n\t */\n\tgetChild( index ) {\n\t\treturn this._children.getNode( index );\n\t}\n\n\t/**\n\t * Returns an iterator that iterates over all of this document fragment's children.\n\t *\n\t * @returns {Iterable.<module:engine/model/node~Node>}\n\t */\n\tgetChildren() {\n\t\treturn this._children[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Returns an index of the given child node. Returns `null` if given node is not a child of this document fragment.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number|null} Child node's index.\n\t */\n\tgetChildIndex( node ) {\n\t\treturn this._children.getNodeIndex( node );\n\t}\n\n\t/**\n\t * Returns the starting offset of given child. Starting offset is equal to the sum of\n\t * {@link module:engine/model/node~Node#offsetSize offset sizes} of all node's siblings that are before it. Returns `null` if\n\t * given node is not a child of this document fragment.\n\t *\n\t * @param {module:engine/model/node~Node} node Child node to look for.\n\t * @returns {Number|null} Child node's starting offset.\n\t */\n\tgetChildStartOffset( node ) {\n\t\treturn this._children.getNodeStartOffset( node );\n\t}\n\n\t/**\n\t * Returns path to a `DocumentFragment`, which is an empty array. Added for compatibility reasons.\n\t *\n\t * @returns {Array}\n\t */\n\tgetPath() {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Returns a descendant node by its path relative to this element.\n\t *\n\t *\t\t// <this>a<b>c</b></this>\n\t *\t\tthis.getNodeByPath( [ 0 ] ); // -> \"a\"\n\t *\t\tthis.getNodeByPath( [ 1 ] ); // -> <b>\n\t *\t\tthis.getNodeByPath( [ 1, 0 ] ); // -> \"c\"\n\t *\n\t * @param {Array.<Number>} relativePath Path of the node to find, relative to this element.\n\t * @returns {module:engine/model/node~Node|module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tgetNodeByPath( relativePath ) {\n\t\tlet node = this; // eslint-disable-line consistent-this\n\n\t\tfor ( const index of relativePath ) {\n\t\t\tnode = node.getChild( node.offsetToIndex( index ) );\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Converts offset \"position\" to index \"position\".\n\t *\n\t * Returns index of a node that occupies given offset. If given offset is too low, returns `0`. If given offset is\n\t * too high, returns index after last child}.\n\t *\n\t *\t\tconst textNode = new Text( 'foo' );\n\t *\t\tconst pElement = new Element( 'p' );\n\t *\t\tconst docFrag = new DocumentFragment( [ textNode, pElement ] );\n\t *\t\tdocFrag.offsetToIndex( -1 ); // Returns 0, because offset is too low.\n\t *\t\tdocFrag.offsetToIndex( 0 ); // Returns 0, because offset 0 is taken by `textNode` which is at index 0.\n\t *\t\tdocFrag.offsetToIndex( 1 ); // Returns 0, because `textNode` has `offsetSize` equal to 3, so it occupies offset 1 too.\n\t *\t\tdocFrag.offsetToIndex( 2 ); // Returns 0.\n\t *\t\tdocFrag.offsetToIndex( 3 ); // Returns 1.\n\t *\t\tdocFrag.offsetToIndex( 4 ); // Returns 2. There are no nodes at offset 4, so last available index is returned.\n\t *\n\t * @param {Number} offset Offset to look for.\n\t * @returns {Number} Index of a node that occupies given offset.\n\t */\n\toffsetToIndex( offset ) {\n\t\treturn this._children.offsetToIndex( offset );\n\t}\n\n\t/**\n\t * Converts `DocumentFragment` instance to plain object and returns it.\n\t * Takes care of converting all of this document fragment's children.\n\t *\n\t * @returns {Object} `DocumentFragment` instance converted to plain object.\n\t */\n\ttoJSON() {\n\t\tconst json = [];\n\n\t\tfor ( const node of this._children ) {\n\t\t\tjson.push( node.toJSON() );\n\t\t}\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Creates a `DocumentFragment` instance from given plain object (i.e. parsed JSON string).\n\t * Converts `DocumentFragment` children to proper nodes.\n\t *\n\t * @param {Object} json Plain object to be converted to `DocumentFragment`.\n\t * @returns {module:engine/model/documentfragment~DocumentFragment} `DocumentFragment` instance created using given plain object.\n\t */\n\tstatic fromJSON( json ) {\n\t\tconst children = [];\n\n\t\tfor ( const child of json ) {\n\t\t\tif ( child.name ) {\n\t\t\t\t// If child has name property, it is an Element.\n\t\t\t\tchildren.push( Element.fromJSON( child ) );\n\t\t\t} else {\n\t\t\t\t// Otherwise, it is a Text node.\n\t\t\t\tchildren.push( Text.fromJSON( child ) );\n\t\t\t}\n\t\t}\n\n\t\treturn new DocumentFragment( children );\n\t}\n\n\t/**\n\t * {@link #_insertChild Inserts} one or more nodes at the end of this document fragment.\n\t *\n\t * @protected\n\t * @param {module:engine/model/item~Item|Iterable.<module:engine/model/item~Item>} items Items to be inserted.\n\t */\n\t_appendChild( items ) {\n\t\tthis._insertChild( this.childCount, items );\n\t}\n\n\t/**\n\t * Inserts one or more nodes at the given index and sets {@link module:engine/model/node~Node#parent parent} of these nodes\n\t * to this document fragment.\n\t *\n\t * @protected\n\t * @param {Number} index Index at which nodes should be inserted.\n\t * @param {module:engine/model/item~Item|Iterable.<module:engine/model/item~Item>} items Items to be inserted.\n\t */\n\t_insertChild( index, items ) {\n\t\tconst nodes = normalize( items );\n\n\t\tfor ( const node of nodes ) {\n\t\t\t// If node that is being added to this element is already inside another element, first remove it from the old parent.\n\t\t\tif ( node.parent !== null ) {\n\t\t\t\tnode._remove();\n\t\t\t}\n\n\t\t\tnode.parent = this;\n\t\t}\n\n\t\tthis._children._insertNodes( index, nodes );\n\t}\n\n\t/**\n\t * Removes one or more nodes starting at the given index\n\t * and sets {@link module:engine/model/node~Node#parent parent} of these nodes to `null`.\n\t *\n\t * @protected\n\t * @param {Number} index Index of the first node to remove.\n\t * @param {Number} [howMany=1] Number of nodes to remove.\n\t * @returns {Array.<module:engine/model/node~Node>} Array containing removed nodes.\n\t */\n\t_removeChildren( index, howMany = 1 ) {\n\t\tconst nodes = this._children._removeNodes( index, howMany );\n\n\t\tfor ( const node of nodes ) {\n\t\t\tnode.parent = null;\n\t\t}\n\n\t\treturn nodes;\n\t}\n}\n\n// Converts strings to Text and non-iterables to arrays.\n//\n// @param {String|module:engine/model/item~Item|Iterable.<module:engine/model/item~Item>}\n// @returns {Iterable.<module:engine/model/node~Node>}\nfunction normalize( nodes ) {\n\t// Separate condition because string is iterable.\n\tif ( typeof nodes == 'string' ) {\n\t\treturn [ new Text( nodes ) ];\n\t}\n\n\tif ( !isIterable( nodes ) ) {\n\t\tnodes = [ nodes ];\n\t}\n\n\t// Array.from to enable .map() on non-arrays.\n\treturn Array.from( nodes )\n\t\t.map( node => {\n\t\t\tif ( typeof node == 'string' ) {\n\t\t\t\treturn new Text( node );\n\t\t\t}\n\n\t\t\tif ( node instanceof TextProxy ) {\n\t\t\t\treturn new Text( node.data, node.getAttributes() );\n\t\t\t}\n\n\t\t\treturn node;\n\t\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/utils\n */\n\nimport Node from '../node';\nimport Text from '../text';\nimport TextProxy from '../textproxy';\nimport Range from '../range';\nimport DocumentFragment from '../documentfragment';\nimport NodeList from '../nodelist';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Contains functions used for composing model tree by {@link module:engine/model/operation/operation~Operation operations}.\n * Those functions are built on top of {@link module:engine/model/node~Node node}, and it's child classes', APIs.\n *\n * @protected\n * @namespace utils\n */\n\n/**\n * Inserts given nodes at given position.\n *\n * @protected\n * @function module:engine/model/operation/utils~utils.insert\n * @param {module:engine/model/position~Position} position Position at which nodes should be inserted.\n * @param {module:engine/model/node~NodeSet} nodes Nodes to insert.\n * @returns {module:engine/model/range~Range} Range spanning over inserted elements.\n */\nexport function _insert( position, nodes ) {\n\tnodes = _normalizeNodes( nodes );\n\n\t// We have to count offset before inserting nodes because they can get merged and we would get wrong offsets.\n\tconst offset = nodes.reduce( ( sum, node ) => sum + node.offsetSize, 0 );\n\tconst parent = position.parent;\n\n\t// Insertion might be in a text node, we should split it if that's the case.\n\t_splitNodeAtPosition( position );\n\tconst index = position.index;\n\n\t// Insert nodes at given index. After splitting we have a proper index and insertion is between nodes,\n\t// using basic `Element` API.\n\tparent._insertChild( index, nodes );\n\n\t// Merge text nodes, if possible. Merging is needed only at points where inserted nodes \"touch\" \"old\" nodes.\n\t_mergeNodesAtIndex( parent, index + nodes.length );\n\t_mergeNodesAtIndex( parent, index );\n\n\treturn new Range( position, position.getShiftedBy( offset ) );\n}\n\n/**\n * Removed nodes in given range. Only {@link module:engine/model/range~Range#isFlat flat} ranges are accepted.\n *\n * @protected\n * @function module:engine/model/operation/utils~utils._remove\n * @param {module:engine/model/range~Range} range Range containing nodes to remove.\n * @returns {Array.<module:engine/model/node~Node>}\n */\nexport function _remove( range ) {\n\tif ( !range.isFlat ) {\n\t\t/**\n\t\t * Trying to remove a range which starts and ends in different element.\n\t\t *\n\t\t * @error operation-utils-remove-range-not-flat\n\t\t */\n\t\tthrow new CKEditorError(\n\t\t\t'operation-utils-remove-range-not-flat: ' +\n\t\t\t'Trying to remove a range which starts and ends in different element.',\n\t\t\tthis\n\t\t);\n\t}\n\n\tconst parent = range.start.parent;\n\n\t// Range may be inside text nodes, we have to split them if that's the case.\n\t_splitNodeAtPosition( range.start );\n\t_splitNodeAtPosition( range.end );\n\n\t// Remove the text nodes using basic `Element` API.\n\tconst removed = parent._removeChildren( range.start.index, range.end.index - range.start.index );\n\n\t// Merge text nodes, if possible. After some nodes were removed, node before and after removed range will be\n\t// touching at the position equal to the removed range beginning. We check merging possibility there.\n\t_mergeNodesAtIndex( parent, range.start.index );\n\n\treturn removed;\n}\n\n/**\n * Moves nodes in given range to given target position. Only {@link module:engine/model/range~Range#isFlat flat} ranges are accepted.\n *\n * @protected\n * @function module:engine/model/operation/utils~utils.move\n * @param {module:engine/model/range~Range} sourceRange Range containing nodes to move.\n * @param {module:engine/model/position~Position} targetPosition Position to which nodes should be moved.\n * @returns {module:engine/model/range~Range} Range containing moved nodes.\n */\nexport function _move( sourceRange, targetPosition ) {\n\tif ( !sourceRange.isFlat ) {\n\t\t/**\n\t\t * Trying to move a range which starts and ends in different element.\n\t\t *\n\t\t * @error operation-utils-move-range-not-flat\n\t\t */\n\t\tthrow new CKEditorError(\n\t\t\t'operation-utils-move-range-not-flat: ' +\n\t\t\t'Trying to move a range which starts and ends in different element.',\n\t\t\tthis\n\t\t);\n\t}\n\n\tconst nodes = _remove( sourceRange );\n\n\t// We have to fix `targetPosition` because model changed after nodes from `sourceRange` got removed and\n\t// that change might have an impact on `targetPosition`.\n\ttargetPosition = targetPosition._getTransformedByDeletion( sourceRange.start, sourceRange.end.offset - sourceRange.start.offset );\n\n\treturn _insert( targetPosition, nodes );\n}\n\n/**\n * Sets given attribute on nodes in given range. The attributes are only set on top-level nodes of the range, not on its children.\n *\n * @protected\n * @function module:engine/model/operation/utils~utils._setAttribute\n * @param {module:engine/model/range~Range} range Range containing nodes that should have the attribute set. Must be a flat range.\n * @param {String} key Key of attribute to set.\n * @param {*} value Attribute value.\n */\nexport function _setAttribute( range, key, value ) {\n\t// Range might start or end in text nodes, so we have to split them.\n\t_splitNodeAtPosition( range.start );\n\t_splitNodeAtPosition( range.end );\n\n\t// Iterate over all items in the range.\n\tfor ( const item of range.getItems( { shallow: true } ) ) {\n\t\t// Iterator will return `TextProxy` instances but we know that those text proxies will\n\t\t// always represent full text nodes (this is guaranteed thanks to splitting we did before).\n\t\t// So, we can operate on those text proxies' text nodes.\n\t\tconst node = item.is( 'textProxy' ) ? item.textNode : item;\n\n\t\tif ( value !== null ) {\n\t\t\tnode._setAttribute( key, value );\n\t\t} else {\n\t\t\tnode._removeAttribute( key );\n\t\t}\n\n\t\t// After attributes changing it may happen that some text nodes can be merged. Try to merge with previous node.\n\t\t_mergeNodesAtIndex( node.parent, node.index );\n\t}\n\n\t// Try to merge last changed node with it's previous sibling (not covered by the loop above).\n\t_mergeNodesAtIndex( range.end.parent, range.end.index );\n}\n\n/**\n * Normalizes given object or an array of objects to an array of {@link module:engine/model/node~Node nodes}. See\n * {@link module:engine/model/node~NodeSet NodeSet} for details on how normalization is performed.\n *\n * @protected\n * @function module:engine/model/operation/utils~utils.normalizeNodes\n * @param {module:engine/model/node~NodeSet} nodes Objects to normalize.\n * @returns {Array.<module:engine/model/node~Node>} Normalized nodes.\n */\nexport function _normalizeNodes( nodes ) {\n\tconst normalized = [];\n\n\tif ( !( nodes instanceof Array ) ) {\n\t\tnodes = [ nodes ];\n\t}\n\n\t// Convert instances of classes other than Node.\n\tfor ( let i = 0; i < nodes.length; i++ ) {\n\t\tif ( typeof nodes[ i ] == 'string' ) {\n\t\t\tnormalized.push( new Text( nodes[ i ] ) );\n\t\t} else if ( nodes[ i ] instanceof TextProxy ) {\n\t\t\tnormalized.push( new Text( nodes[ i ].data, nodes[ i ].getAttributes() ) );\n\t\t} else if ( nodes[ i ] instanceof DocumentFragment || nodes[ i ] instanceof NodeList ) {\n\t\t\tfor ( const child of nodes[ i ] ) {\n\t\t\t\tnormalized.push( child );\n\t\t\t}\n\t\t} else if ( nodes[ i ] instanceof Node ) {\n\t\t\tnormalized.push( nodes[ i ] );\n\t\t}\n\t\t// Skip unrecognized type.\n\t}\n\n\t// Merge text nodes.\n\tfor ( let i = 1; i < normalized.length; i++ ) {\n\t\tconst node = normalized[ i ];\n\t\tconst prev = normalized[ i - 1 ];\n\n\t\tif ( node instanceof Text && prev instanceof Text && _haveSameAttributes( node, prev ) ) {\n\t\t\t// Doing this instead changing `prev.data` because `data` is readonly.\n\t\t\tnormalized.splice( i - 1, 2, new Text( prev.data + node.data, prev.getAttributes() ) );\n\t\t\ti--;\n\t\t}\n\t}\n\n\treturn normalized;\n}\n\n// Checks if nodes before and after given index in given element are {@link module:engine/model/text~Text text nodes} and\n// merges them into one node if they have same attributes.\n//\n// Merging is done by removing two text nodes and inserting a new text node containing data from both merged text nodes.\n//\n// @private\n// @param {module:engine/model/element~Element} element Parent element of nodes to merge.\n// @param {Number} index Index between nodes to merge.\nfunction _mergeNodesAtIndex( element, index ) {\n\tconst nodeBefore = element.getChild( index - 1 );\n\tconst nodeAfter = element.getChild( index );\n\n\t// Check if both of those nodes are text objects with same attributes.\n\tif ( nodeBefore && nodeAfter && nodeBefore.is( 'text' ) && nodeAfter.is( 'text' ) && _haveSameAttributes( nodeBefore, nodeAfter ) ) {\n\t\t// Append text of text node after index to the before one.\n\t\tconst mergedNode = new Text( nodeBefore.data + nodeAfter.data, nodeBefore.getAttributes() );\n\n\t\t// Remove separate text nodes.\n\t\telement._removeChildren( index - 1, 2 );\n\n\t\t// Insert merged text node.\n\t\telement._insertChild( index - 1, mergedNode );\n\t}\n}\n\n// Checks if given position is in a text node, and if so, splits the text node in two text nodes, each of them\n// containing a part of original text node.\n//\n// @private\n// @param {module:engine/model/position~Position} position Position at which node should be split.\nfunction _splitNodeAtPosition( position ) {\n\tconst textNode = position.textNode;\n\tconst element = position.parent;\n\n\tif ( textNode ) {\n\t\tconst offsetDiff = position.offset - textNode.startOffset;\n\t\tconst index = textNode.index;\n\n\t\telement._removeChildren( index, 1 );\n\n\t\tconst firstPart = new Text( textNode.data.substr( 0, offsetDiff ), textNode.getAttributes() );\n\t\tconst secondPart = new Text( textNode.data.substr( offsetDiff ), textNode.getAttributes() );\n\n\t\telement._insertChild( index, [ firstPart, secondPart ] );\n\t}\n}\n\n// Checks whether two given nodes have same attributes.\n//\n// @private\n// @param {module:engine/model/node~Node} nodeA Node to check.\n// @param {module:engine/model/node~Node} nodeB Node to check.\n// @returns {Boolean} `true` if nodes have same attributes, `false` otherwise.\nfunction _haveSameAttributes( nodeA, nodeB ) {\n\tconst iteratorA = nodeA.getAttributes();\n\tconst iteratorB = nodeB.getAttributes();\n\n\tfor ( const attr of iteratorA ) {\n\t\tif ( attr[ 1 ] !== nodeB.getAttribute( attr[ 0 ] ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\titeratorB.next();\n\t}\n\n\treturn iteratorB.next().done;\n}\n\n/**\n * Value that can be normalized to an array of {@link module:engine/model/node~Node nodes}.\n *\n * Non-arrays are normalized as follows:\n * * {@link module:engine/model/node~Node Node} is left as is,\n * * {@link module:engine/model/textproxy~TextProxy TextProxy} and `String` are normalized to {@link module:engine/model/text~Text Text},\n * * {@link module:engine/model/nodelist~NodeList NodeList} is normalized to an array containing all nodes that are in that node list,\n * * {@link module:engine/model/documentfragment~DocumentFragment DocumentFragment} is normalized to an array containing all of it's\n * * children.\n *\n * Arrays are processed item by item like non-array values and flattened to one array. Normalization always results in\n * a flat array of {@link module:engine/model/node~Node nodes}. Consecutive text nodes (or items normalized to text nodes) will be\n * merged if they have same attributes.\n *\n * @typedef {module:engine/model/node~Node|module:engine/model/textproxy~TextProxy|String|\n * module:engine/model/nodelist~NodeList|module:engine/model/documentfragment~DocumentFragment|Iterable}\n * module:engine/model/node~NodeSet\n */\n","import baseIsEqual from './_baseIsEqual.js';\n\n/**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\nfunction isEqual(value, other) {\n return baseIsEqual(value, other);\n}\n\nexport default isEqual;\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/attributeoperation\n */\n\nimport Operation from './operation';\nimport Range from '../range';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport { _setAttribute } from './utils';\nimport { isEqual } from 'lodash-es';\n\n/**\n * Operation to change nodes' attribute.\n *\n * Using this class you can add, remove or change value of the attribute.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class AttributeOperation extends Operation {\n\t/**\n\t * Creates an operation that changes, removes or adds attributes.\n\t *\n\t * If only `newValue` is set, attribute will be added on a node. Note that all nodes in operation's range must not\n\t * have an attribute with the same key as the added attribute.\n\t *\n\t * If only `oldValue` is set, then attribute with given key will be removed. Note that all nodes in operation's range\n\t * must have an attribute with that key added.\n\t *\n\t * If both `newValue` and `oldValue` are set, then the operation will change the attribute value. Note that all nodes in\n\t * operation's ranges must already have an attribute with given key and `oldValue` as value\n\t *\n\t * @param {module:engine/model/range~Range} range Range on which the operation should be applied. Must be a flat range.\n\t * @param {String} key Key of an attribute to change or remove.\n\t * @param {*} oldValue Old value of the attribute with given key or `null`, if attribute was not set before.\n\t * @param {*} newValue New value of the attribute with given key or `null`, if operation should remove attribute.\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( range, key, oldValue, newValue, baseVersion ) {\n\t\tsuper( baseVersion );\n\n\t\t/**\n\t\t * Range on which operation should be applied.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/range~Range}\n\t\t */\n\t\tthis.range = range.clone();\n\n\t\t/**\n\t\t * Key of an attribute to change or remove.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.key = key;\n\n\t\t/**\n\t\t * Old value of the attribute with given key or `null`, if attribute was not set before.\n\t\t *\n\t\t * @readonly\n\t\t * @member {*}\n\t\t */\n\t\tthis.oldValue = oldValue === undefined ? null : oldValue;\n\n\t\t/**\n\t\t * New value of the attribute with given key or `null`, if operation should remove attribute.\n\t\t *\n\t\t * @readonly\n\t\t * @member {*}\n\t\t */\n\t\tthis.newValue = newValue === undefined ? null : newValue;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\tif ( this.oldValue === null ) {\n\t\t\treturn 'addAttribute';\n\t\t} else if ( this.newValue === null ) {\n\t\t\treturn 'removeAttribute';\n\t\t} else {\n\t\t\treturn 'changeAttribute';\n\t\t}\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/attributeoperation~AttributeOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\treturn new AttributeOperation( this.range, this.key, this.oldValue, this.newValue, this.baseVersion );\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/attributeoperation~AttributeOperation}\n\t */\n\tgetReversed() {\n\t\treturn new AttributeOperation( this.range, this.key, this.newValue, this.oldValue, this.baseVersion + 1 );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.range = this.range.toJSON();\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_validate() {\n\t\tif ( !this.range.isFlat ) {\n\t\t\t/**\n\t\t\t * The range to change is not flat.\n\t\t\t *\n\t\t\t * @error attribute-operation-range-not-flat\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'attribute-operation-range-not-flat: The range to change is not flat.', this );\n\t\t}\n\n\t\tfor ( const item of this.range.getItems( { shallow: true } ) ) {\n\t\t\tif ( this.oldValue !== null && !isEqual( item.getAttribute( this.key ), this.oldValue ) ) {\n\t\t\t\t/**\n\t\t\t\t * Changed node has different attribute value than operation's old attribute value.\n\t\t\t\t *\n\t\t\t\t * @error attribute-operation-wrong-old-value\n\t\t\t\t * @param {module:engine/model/item~Item} item\n\t\t\t\t * @param {String} key\n\t\t\t\t * @param {*} value\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'attribute-operation-wrong-old-value: Changed node has different attribute value than operation\\'s ' +\n\t\t\t\t\t'old attribute value.',\n\t\t\t\t\tthis,\n\t\t\t\t\t{ item, key: this.key, value: this.oldValue }\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif ( this.oldValue === null && this.newValue !== null && item.hasAttribute( this.key ) ) {\n\t\t\t\t/**\n\t\t\t\t * The attribute with given key already exists for the given node.\n\t\t\t\t *\n\t\t\t\t * @error attribute-operation-attribute-exists\n\t\t\t\t * @param {module:engine/model/node~Node} node\n\t\t\t\t * @param {String} key\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'attribute-operation-attribute-exists: The attribute with given key already exists.',\n\t\t\t\t\tthis,\n\t\t\t\t\t{ node: item, key: this.key }\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\t// If value to set is same as old value, don't do anything.\n\t\tif ( !isEqual( this.oldValue, this.newValue ) ) {\n\t\t\t// Execution.\n\t\t\t_setAttribute( this.range, this.key, this.newValue );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'AttributeOperation';\n\t}\n\n\t/**\n\t * Creates `AttributeOperation` object from deserilized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} document Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/attributeoperation~AttributeOperation}\n\t */\n\tstatic fromJSON( json, document ) {\n\t\treturn new AttributeOperation( Range.fromJSON( json.range, document ), json.key, json.oldValue, json.newValue, json.baseVersion );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/detachoperation\n */\n\nimport Operation from './operation';\nimport Range from '../range';\nimport { _remove } from './utils';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Operation to permanently remove node from detached root.\n * Note this operation is only a local operation and won't be send to the other clients.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class DetachOperation extends Operation {\n\t/**\n\t * Creates an insert operation.\n\t *\n\t * @param {module:engine/model/position~Position} sourcePosition\n\t * Position before the first {@link module:engine/model/item~Item model item} to move.\n\t * @param {Number} howMany Offset size of moved range. Moved range will start from `sourcePosition` and end at\n\t * `sourcePosition` with offset shifted by `howMany`.\n\t */\n\tconstructor( sourcePosition, howMany ) {\n\t\tsuper( null );\n\n\t\t/**\n\t\t * Position before the first {@link module:engine/model/item~Item model item} to detach.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} #sourcePosition\n\t\t */\n\t\tthis.sourcePosition = sourcePosition.clone();\n\n\t\t/**\n\t\t * Offset size of moved range.\n\t\t *\n\t\t * @member {Number} #howMany\n\t\t */\n\t\tthis.howMany = howMany;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\treturn 'detach';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.sourcePosition = this.sourcePosition.toJSON();\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_validate() {\n\t\tif ( this.sourcePosition.root.document ) {\n\t\t\t/**\n\t\t\t * Cannot detach document node.\n\t\t\t *\n\t\t\t * @error detach-operation-on-document-node\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'detach-operation-on-document-node: Cannot detach document node.', this );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\t_remove( Range._createFromPositionAndShift( this.sourcePosition, this.howMany ) );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'DetachOperation';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/moveoperation\n */\n\nimport Operation from './operation';\nimport Position from '../position';\nimport Range from '../range';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';\nimport { _move } from './utils';\n\n/**\n * Operation to move a range of {@link module:engine/model/item~Item model items}\n * to given {@link module:engine/model/position~Position target position}.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class MoveOperation extends Operation {\n\t/**\n\t * Creates a move operation.\n\t *\n\t * @param {module:engine/model/position~Position} sourcePosition\n\t * Position before the first {@link module:engine/model/item~Item model item} to move.\n\t * @param {Number} howMany Offset size of moved range. Moved range will start from `sourcePosition` and end at\n\t * `sourcePosition` with offset shifted by `howMany`.\n\t * @param {module:engine/model/position~Position} targetPosition Position at which moved nodes will be inserted.\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( sourcePosition, howMany, targetPosition, baseVersion ) {\n\t\tsuper( baseVersion );\n\n\t\t/**\n\t\t * Position before the first {@link module:engine/model/item~Item model item} to move.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/moveoperation~MoveOperation#sourcePosition\n\t\t */\n\t\tthis.sourcePosition = sourcePosition.clone();\n\t\t// `'toNext'` because `sourcePosition` is a bit like a start of the moved range.\n\t\tthis.sourcePosition.stickiness = 'toNext';\n\n\t\t/**\n\t\t * Offset size of moved range.\n\t\t *\n\t\t * @member {Number} module:engine/model/operation/moveoperation~MoveOperation#howMany\n\t\t */\n\t\tthis.howMany = howMany;\n\n\t\t/**\n\t\t * Position at which moved nodes will be inserted.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/moveoperation~MoveOperation#targetPosition\n\t\t */\n\t\tthis.targetPosition = targetPosition.clone();\n\t\tthis.targetPosition.stickiness = 'toNone';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\tif ( this.targetPosition.root.rootName == '$graveyard' ) {\n\t\t\treturn 'remove';\n\t\t} else if ( this.sourcePosition.root.rootName == '$graveyard' ) {\n\t\t\treturn 'reinsert';\n\t\t}\n\n\t\treturn 'move';\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/moveoperation~MoveOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\treturn new this.constructor( this.sourcePosition, this.howMany, this.targetPosition, this.baseVersion );\n\t}\n\n\t/**\n\t * Returns the start position of the moved range after it got moved. This may be different than\n\t * {@link module:engine/model/operation/moveoperation~MoveOperation#targetPosition} in some cases, i.e. when a range is moved\n\t * inside the same parent but {@link module:engine/model/operation/moveoperation~MoveOperation#targetPosition targetPosition}\n\t * is after {@link module:engine/model/operation/moveoperation~MoveOperation#sourcePosition sourcePosition}.\n\t *\n\t *\t\t vv vv\n\t *\t\tabcdefg ===> adefbcg\n\t *\t\t ^ ^\n\t *\t\t targetPos\tmovedRangeStart\n\t *\t\t offset 6\toffset 4\n\t *\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tgetMovedRangeStart() {\n\t\treturn this.targetPosition._getTransformedByDeletion( this.sourcePosition, this.howMany );\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/moveoperation~MoveOperation}\n\t */\n\tgetReversed() {\n\t\tconst newTargetPosition = this.sourcePosition._getTransformedByInsertion( this.targetPosition, this.howMany );\n\n\t\treturn new this.constructor( this.getMovedRangeStart(), this.howMany, newTargetPosition, this.baseVersion + 1 );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_validate() {\n\t\tconst sourceElement = this.sourcePosition.parent;\n\t\tconst targetElement = this.targetPosition.parent;\n\t\tconst sourceOffset = this.sourcePosition.offset;\n\t\tconst targetOffset = this.targetPosition.offset;\n\n\t\t// Validate whether move operation has correct parameters.\n\t\t// Validation is pretty complex but move operation is one of the core ways to manipulate the document state.\n\t\t// We expect that many errors might be connected with one of scenarios described below.\n\t\tif ( sourceOffset + this.howMany > sourceElement.maxOffset ) {\n\t\t\t/**\n\t\t\t * The nodes which should be moved do not exist.\n\t\t\t *\n\t\t\t * @error move-operation-nodes-do-not-exist\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'move-operation-nodes-do-not-exist: The nodes which should be moved do not exist.', this\n\t\t\t);\n\t\t} else if ( sourceElement === targetElement && sourceOffset < targetOffset && targetOffset < sourceOffset + this.howMany ) {\n\t\t\t/**\n\t\t\t * Trying to move a range of nodes into the middle of that range.\n\t\t\t *\n\t\t\t * @error move-operation-range-into-itself\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'move-operation-range-into-itself: Trying to move a range of nodes to the inside of that range.', this\n\t\t\t);\n\t\t} else if ( this.sourcePosition.root == this.targetPosition.root ) {\n\t\t\tif ( compareArrays( this.sourcePosition.getParentPath(), this.targetPosition.getParentPath() ) == 'prefix' ) {\n\t\t\t\tconst i = this.sourcePosition.path.length - 1;\n\n\t\t\t\tif ( this.targetPosition.path[ i ] >= sourceOffset && this.targetPosition.path[ i ] < sourceOffset + this.howMany ) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Trying to move a range of nodes into one of nodes from that range.\n\t\t\t\t\t *\n\t\t\t\t\t * @error move-operation-node-into-itself\n\t\t\t\t\t */\n\t\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t\t'move-operation-node-into-itself: Trying to move a range of nodes into one of nodes from that range.', this\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\t_move( Range._createFromPositionAndShift( this.sourcePosition, this.howMany ), this.targetPosition );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.sourcePosition = this.sourcePosition.toJSON();\n\t\tjson.targetPosition = this.targetPosition.toJSON();\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'MoveOperation';\n\t}\n\n\t/**\n\t * Creates `MoveOperation` object from deserilized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} document Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/moveoperation~MoveOperation}\n\t */\n\tstatic fromJSON( json, document ) {\n\t\tconst sourcePosition = Position.fromJSON( json.sourcePosition, document );\n\t\tconst targetPosition = Position.fromJSON( json.targetPosition, document );\n\n\t\treturn new this( sourcePosition, json.howMany, targetPosition, json.baseVersion );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/insertoperation\n */\n\nimport Operation from './operation';\nimport Position from '../position';\nimport NodeList from '../nodelist';\nimport MoveOperation from './moveoperation';\nimport { _insert, _normalizeNodes } from './utils';\nimport Text from '../text';\nimport Element from '../element';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Operation to insert one or more nodes at given position in the model.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class InsertOperation extends Operation {\n\t/**\n\t * Creates an insert operation.\n\t *\n\t * @param {module:engine/model/position~Position} position Position of insertion.\n\t * @param {module:engine/model/node~NodeSet} nodes The list of nodes to be inserted.\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( position, nodes, baseVersion ) {\n\t\tsuper( baseVersion );\n\n\t\t/**\n\t\t * Position of insertion.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/insertoperation~InsertOperation#position\n\t\t */\n\t\tthis.position = position.clone();\n\t\tthis.position.stickiness = 'toNone';\n\n\t\t/**\n\t\t * List of nodes to insert.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/nodelist~NodeList} module:engine/model/operation/insertoperation~InsertOperation#nodeList\n\t\t */\n\t\tthis.nodes = new NodeList( _normalizeNodes( nodes ) );\n\n\t\t/**\n\t\t * Flag deciding how the operation should be transformed. If set to `true`, nodes might get additional attributes\n\t\t * during operational transformation. This happens when the operation insertion position is inside of a range\n\t\t * where attributes have changed.\n\t\t *\n\t\t * @member {Boolean} module:engine/model/operation/insertoperation~InsertOperation#shouldReceiveAttributes\n\t\t */\n\t\tthis.shouldReceiveAttributes = false;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\treturn 'insert';\n\t}\n\n\t/**\n\t * Total offset size of inserted nodes.\n\t *\n\t * @returns {Number}\n\t */\n\tget howMany() {\n\t\treturn this.nodes.maxOffset;\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/insertoperation~InsertOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\tconst nodes = new NodeList( [ ...this.nodes ].map( node => node._clone( true ) ) );\n\t\tconst insert = new InsertOperation( this.position, nodes, this.baseVersion );\n\n\t\tinsert.shouldReceiveAttributes = this.shouldReceiveAttributes;\n\n\t\treturn insert;\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/moveoperation~MoveOperation}\n\t */\n\tgetReversed() {\n\t\tconst graveyard = this.position.root.document.graveyard;\n\t\tconst gyPosition = new Position( graveyard, [ 0 ] );\n\n\t\treturn new MoveOperation( this.position, this.nodes.maxOffset, gyPosition, this.baseVersion + 1 );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_validate() {\n\t\tconst targetElement = this.position.parent;\n\n\t\tif ( !targetElement || targetElement.maxOffset < this.position.offset ) {\n\t\t\t/**\n\t\t\t * Insertion position is invalid.\n\t\t\t *\n\t\t\t * @error insert-operation-position-invalid\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'insert-operation-position-invalid: Insertion position is invalid.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\t// What happens here is that we want original nodes be passed to writer because we want original nodes\n\t\t// to be inserted to the model. But in InsertOperation, we want to keep those nodes as they were added\n\t\t// to the operation, not modified. For example, text nodes can get merged or cropped while Elements can\n\t\t// get children. It is important that InsertOperation has the copy of original nodes in intact state.\n\t\tconst originalNodes = this.nodes;\n\t\tthis.nodes = new NodeList( [ ...originalNodes ].map( node => node._clone( true ) ) );\n\n\t\t_insert( this.position, originalNodes );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.position = this.position.toJSON();\n\t\tjson.nodes = this.nodes.toJSON();\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'InsertOperation';\n\t}\n\n\t/**\n\t * Creates `InsertOperation` object from deserilized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} document Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/insertoperation~InsertOperation}\n\t */\n\tstatic fromJSON( json, document ) {\n\t\tconst children = [];\n\n\t\tfor ( const child of json.nodes ) {\n\t\t\tif ( child.name ) {\n\t\t\t\t// If child has name property, it is an Element.\n\t\t\t\tchildren.push( Element.fromJSON( child ) );\n\t\t\t} else {\n\t\t\t\t// Otherwise, it is a Text node.\n\t\t\t\tchildren.push( Text.fromJSON( child ) );\n\t\t\t}\n\t\t}\n\n\t\tconst insert = new InsertOperation( Position.fromJSON( json.position, document ), children, json.baseVersion );\n\t\tinsert.shouldReceiveAttributes = json.shouldReceiveAttributes;\n\n\t\treturn insert;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/markeroperation\n */\n\nimport Operation from './operation';\nimport Range from '../range';\n\n/**\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class MarkerOperation extends Operation {\n\t/**\n\t * @param {String} name Marker name.\n\t * @param {module:engine/model/range~Range} oldRange Marker range before the change.\n\t * @param {module:engine/model/range~Range} newRange Marker range after the change.\n\t * @param {module:engine/model/markercollection~MarkerCollection} markers Marker collection on which change should be executed.\n\t * @param {Boolean} affectsData Specifies whether the marker operation affects the data produced by the data pipeline\n\t * (is persisted in the editor's data).\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( name, oldRange, newRange, markers, affectsData, baseVersion ) {\n\t\tsuper( baseVersion );\n\n\t\t/**\n\t\t * Marker 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 * Marker range before the change.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/range~Range}\n\t\t */\n\t\tthis.oldRange = oldRange ? oldRange.clone() : null;\n\n\t\t/**\n\t\t * Marker range after the change.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/range~Range}\n\t\t */\n\t\tthis.newRange = newRange ? newRange.clone() : null;\n\n\t\t/**\n\t\t * Specifies whether the marker operation affects the data produced by the data pipeline\n\t\t * (is persisted in the editor's data).\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis.affectsData = affectsData;\n\n\t\t/**\n\t\t * Marker collection on which change should be executed.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/markercollection~MarkerCollection}\n\t\t */\n\t\tthis._markers = markers;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\treturn 'marker';\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/markeroperation~MarkerOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\treturn new MarkerOperation( this.name, this.oldRange, this.newRange, this._markers, this.affectsData, this.baseVersion );\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/markeroperation~MarkerOperation}\n\t */\n\tgetReversed() {\n\t\treturn new MarkerOperation( this.name, this.newRange, this.oldRange, this._markers, this.affectsData, this.baseVersion + 1 );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\tconst type = this.newRange ? '_set' : '_remove';\n\n\t\tthis._markers[ type ]( this.name, this.newRange, true, this.affectsData );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tif ( this.oldRange ) {\n\t\t\tjson.oldRange = this.oldRange.toJSON();\n\t\t}\n\n\t\tif ( this.newRange ) {\n\t\t\tjson.newRange = this.newRange.toJSON();\n\t\t}\n\n\t\tdelete json._markers;\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'MarkerOperation';\n\t}\n\n\t/**\n\t * Creates `MarkerOperation` object from deserialized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} document Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/markeroperation~MarkerOperation}\n\t */\n\tstatic fromJSON( json, document ) {\n\t\treturn new MarkerOperation(\n\t\t\tjson.name,\n\t\t\tjson.oldRange ? Range.fromJSON( json.oldRange, document ) : null,\n\t\t\tjson.newRange ? Range.fromJSON( json.newRange, document ) : null,\n\t\t\tdocument.model.markers,\n\t\t\tjson.affectsData,\n\t\t\tjson.baseVersion\n\t\t);\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/renameoperation\n */\n\nimport Operation from './operation';\nimport Element from '../element';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport Position from '../position';\n\n/**\n * Operation to change element's name.\n *\n * Using this class you can change element's name.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class RenameOperation extends Operation {\n\t/**\n\t * Creates an operation that changes element's name.\n\t *\n\t * @param {module:engine/model/position~Position} position Position before an element to change.\n\t * @param {String} oldName Current name of the element.\n\t * @param {String} newName New name for the element.\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( position, oldName, newName, baseVersion ) {\n\t\tsuper( baseVersion );\n\n\t\t/**\n\t\t * Position before an element to change.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/renameoperation~RenameOperation#position\n\t\t */\n\t\tthis.position = position;\n\t\t// This position sticks to the next node because it is a position before the node that we want to change.\n\t\tthis.position.stickiness = 'toNext';\n\n\t\t/**\n\t\t * Current name of the element.\n\t\t *\n\t\t * @member {String} module:engine/model/operation/renameoperation~RenameOperation#oldName\n\t\t */\n\t\tthis.oldName = oldName;\n\n\t\t/**\n\t\t * New name for the element.\n\t\t *\n\t\t * @member {String} module:engine/model/operation/renameoperation~RenameOperation#newName\n\t\t */\n\t\tthis.newName = newName;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\treturn 'rename';\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/renameoperation~RenameOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\treturn new RenameOperation( this.position.clone(), this.oldName, this.newName, this.baseVersion );\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/renameoperation~RenameOperation}\n\t */\n\tgetReversed() {\n\t\treturn new RenameOperation( this.position.clone(), this.newName, this.oldName, this.baseVersion + 1 );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_validate() {\n\t\tconst element = this.position.nodeAfter;\n\n\t\tif ( !( element instanceof Element ) ) {\n\t\t\t/**\n\t\t\t * Given position is invalid or node after it is not instance of Element.\n\t\t\t *\n\t\t\t * @error rename-operation-wrong-position\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'rename-operation-wrong-position: Given position is invalid or node after it is not an instance of Element.',\n\t\t\t\tthis\n\t\t\t);\n\t\t} else if ( element.name !== this.oldName ) {\n\t\t\t/**\n\t\t\t * Element to change has different name than operation's old name.\n\t\t\t *\n\t\t\t * @error rename-operation-wrong-name\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'rename-operation-wrong-name: Element to change has different name than operation\\'s old name.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\tconst element = this.position.nodeAfter;\n\n\t\telement.name = this.newName;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.position = this.position.toJSON();\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'RenameOperation';\n\t}\n\n\t/**\n\t * Creates `RenameOperation` object from deserialized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} document Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/attributeoperation~AttributeOperation}\n\t */\n\tstatic fromJSON( json, document ) {\n\t\treturn new RenameOperation( Position.fromJSON( json.position, document ), json.oldName, json.newName, json.baseVersion );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/rootattributeoperation\n */\n\nimport Operation from './operation';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Operation to change root element's attribute. Using this class you can add, remove or change value of the attribute.\n *\n * This operation is needed, because root elements can't be changed through\n * @link module:engine/model/operation/attributeoperation~AttributeOperation}.\n * It is because {@link module:engine/model/operation/attributeoperation~AttributeOperation}\n * requires a range to change and root element can't\n * be a part of range because every {@link module:engine/model/position~Position} has to be inside a root.\n * {@link module:engine/model/position~Position} can't be created before a root element.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class RootAttributeOperation extends Operation {\n\t/**\n\t * Creates an operation that changes, removes or adds attributes on root element.\n\t *\n\t * @see module:engine/model/operation/attributeoperation~AttributeOperation\n\t * @param {module:engine/model/rootelement~RootElement} root Root element to change.\n\t * @param {String} key Key of an attribute to change or remove.\n\t * @param {*} oldValue Old value of the attribute with given key or `null` if adding a new attribute.\n\t * @param {*} newValue New value to set for the attribute. If `null`, then the operation just removes the attribute.\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( root, key, oldValue, newValue, baseVersion ) {\n\t\tsuper( baseVersion );\n\n\t\t/**\n\t\t * Root element to change.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/rootelement~RootElement}\n\t\t */\n\t\tthis.root = root;\n\n\t\t/**\n\t\t * Key of an attribute to change or remove.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.key = key;\n\n\t\t/**\n\t\t * Old value of the attribute with given key or `null` if adding a new attribute.\n\t\t *\n\t\t * @readonly\n\t\t * @member {*}\n\t\t */\n\t\tthis.oldValue = oldValue;\n\n\t\t/**\n\t\t * New value to set for the attribute. If `null`, then the operation just removes the attribute.\n\t\t *\n\t\t * @readonly\n\t\t * @member {*}\n\t\t */\n\t\tthis.newValue = newValue;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\tif ( this.oldValue === null ) {\n\t\t\treturn 'addRootAttribute';\n\t\t} else if ( this.newValue === null ) {\n\t\t\treturn 'removeRootAttribute';\n\t\t} else {\n\t\t\treturn 'changeRootAttribute';\n\t\t}\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/rootattributeoperation~RootAttributeOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\treturn new RootAttributeOperation( this.root, this.key, this.oldValue, this.newValue, this.baseVersion );\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/rootattributeoperation~RootAttributeOperation}\n\t */\n\tgetReversed() {\n\t\treturn new RootAttributeOperation( this.root, this.key, this.newValue, this.oldValue, this.baseVersion + 1 );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_validate() {\n\t\tif ( this.root != this.root.root || this.root.is( 'documentFragment' ) ) {\n\t\t\t/**\n\t\t\t * The element to change is not a root element.\n\t\t\t *\n\t\t\t * @error rootattribute-operation-not-a-root\n\t\t\t * @param {module:engine/model/rootelement~RootElement} root\n\t\t\t * @param {String} key\n\t\t\t * @param {*} value\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'rootattribute-operation-not-a-root: The element to change is not a root element.',\n\t\t\t\tthis,\n\t\t\t\t{ root: this.root, key: this.key }\n\t\t\t);\n\t\t}\n\n\t\tif ( this.oldValue !== null && this.root.getAttribute( this.key ) !== this.oldValue ) {\n\t\t\t/**\n\t\t\t * The attribute which should be removed does not exists for the given node.\n\t\t\t *\n\t\t\t * @error rootattribute-operation-wrong-old-value\n\t\t\t * @param {module:engine/model/rootelement~RootElement} root\n\t\t\t * @param {String} key\n\t\t\t * @param {*} value\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'rootattribute-operation-wrong-old-value: Changed node has different attribute value than operation\\'s ' +\n\t\t\t\t'old attribute value.',\n\t\t\t\tthis,\n\t\t\t\t{ root: this.root, key: this.key }\n\t\t\t);\n\t\t}\n\n\t\tif ( this.oldValue === null && this.newValue !== null && this.root.hasAttribute( this.key ) ) {\n\t\t\t/**\n\t\t\t * The attribute with given key already exists for the given node.\n\t\t\t *\n\t\t\t * @error rootattribute-operation-attribute-exists\n\t\t\t * @param {module:engine/model/rootelement~RootElement} root\n\t\t\t * @param {String} key\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'rootattribute-operation-attribute-exists: The attribute with given key already exists.',\n\t\t\t\tthis,\n\t\t\t\t{ root: this.root, key: this.key }\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\tif ( this.newValue !== null ) {\n\t\t\tthis.root._setAttribute( this.key, this.newValue );\n\t\t} else {\n\t\t\tthis.root._removeAttribute( this.key );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.root = this.root.toJSON();\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'RootAttributeOperation';\n\t}\n\n\t/**\n\t * Creates RootAttributeOperation object from deserilized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} document Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/rootattributeoperation~RootAttributeOperation}\n\t */\n\tstatic fromJSON( json, document ) {\n\t\tif ( !document.getRoot( json.root ) ) {\n\t\t\t/**\n\t\t\t * Cannot create RootAttributeOperation for document. Root with specified name does not exist.\n\t\t\t *\n\t\t\t * @error rootattributeoperation-fromjson-no-root\n\t\t\t * @param {String} rootName\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'rootattribute-operation-fromjson-no-root: Cannot create RootAttributeOperation. Root with specified name does not exist.',\n\t\t\t\tthis,\n\t\t\t\t{ rootName: json.root }\n\t\t\t);\n\t\t}\n\n\t\treturn new RootAttributeOperation( document.getRoot( json.root ), json.key, json.oldValue, json.newValue, json.baseVersion );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/mergeoperation\n */\n\nimport Operation from './operation';\nimport SplitOperation from './splitoperation';\nimport Position from '../position';\nimport Range from '../range';\nimport { _move } from './utils';\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Operation to merge two {@link module:engine/model/element~Element elements}.\n *\n * The merged element is the parent of {@link ~MergeOperation#sourcePosition} and it is merged into the parent of\n * {@link ~MergeOperation#targetPosition}. All nodes from the merged element are moved to {@link ~MergeOperation#targetPosition}.\n *\n * The merged element is moved to the graveyard at {@link ~MergeOperation#graveyardPosition}.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class MergeOperation extends Operation {\n\t/**\n\t * Creates a merge operation.\n\t *\n\t * @param {module:engine/model/position~Position} sourcePosition Position inside the merged element. All nodes from that\n\t * element after that position will be moved to {@link ~#targetPosition}.\n\t * @param {Number} howMany Summary offset size of nodes which will be moved from the merged element to the new parent.\n\t * @param {module:engine/model/position~Position} targetPosition Position which the nodes from the merged elements will be moved to.\n\t * @param {module:engine/model/position~Position} graveyardPosition Position in graveyard to which the merged element will be moved.\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( sourcePosition, howMany, targetPosition, graveyardPosition, baseVersion ) {\n\t\tsuper( baseVersion );\n\n\t\t/**\n\t\t * Position inside the merged element. All nodes from that element after that position will be moved to {@link ~#targetPosition}.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/mergeoperation~MergeOperation#sourcePosition\n\t\t */\n\t\tthis.sourcePosition = sourcePosition.clone();\n\t\t// This is, and should always remain, the first position in its parent.\n\t\tthis.sourcePosition.stickiness = 'toPrevious';\n\n\t\t/**\n\t\t * Summary offset size of nodes which will be moved from the merged element to the new parent.\n\t\t *\n\t\t * @member {Number} module:engine/model/operation/mergeoperation~MergeOperation#howMany\n\t\t */\n\t\tthis.howMany = howMany;\n\n\t\t/**\n\t\t * Position which the nodes from the merged elements will be moved to.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/mergeoperation~MergeOperation#targetPosition\n\t\t */\n\t\tthis.targetPosition = targetPosition.clone();\n\t\t// Except of a rare scenario in `MergeOperation` x `MergeOperation` transformation,\n\t\t// this is, and should always remain, the last position in its parent.\n\t\tthis.targetPosition.stickiness = 'toNext';\n\n\t\t/**\n\t\t * Position in graveyard to which the merged element will be moved.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/mergeoperation~MergeOperation#graveyardPosition\n\t\t */\n\t\tthis.graveyardPosition = graveyardPosition.clone();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\treturn 'merge';\n\t}\n\n\t/**\n\t * Position before the merged element (which will be deleted).\n\t *\n\t * @readonly\n\t * @type {module:engine/model/position~Position}\n\t */\n\tget deletionPosition() {\n\t\treturn new Position( this.sourcePosition.root, this.sourcePosition.path.slice( 0, -1 ) );\n\t}\n\n\t/**\n\t * Artificial range that contains all the nodes from the merged element that will be moved to {@link ~MergeOperation#sourcePosition}.\n\t * The range starts at {@link ~MergeOperation#sourcePosition} and ends in the same parent, at `POSITIVE_INFINITY` offset.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/range~Range}\n\t */\n\tget movedRange() {\n\t\tconst end = this.sourcePosition.getShiftedBy( Number.POSITIVE_INFINITY );\n\n\t\treturn new Range( this.sourcePosition, end );\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/mergeoperation~MergeOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\treturn new this.constructor( this.sourcePosition, this.howMany, this.targetPosition, this.graveyardPosition, this.baseVersion );\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/splitoperation~SplitOperation}\n\t */\n\tgetReversed() {\n\t\t// Positions in this method are transformed by this merge operation because the split operation bases on\n\t\t// the context after this merge operation happened (because split operation reverses it).\n\t\t// So we need to acknowledge that the merge operation happened and those positions changed a little.\n\t\tconst targetPosition = this.targetPosition._getTransformedByMergeOperation( this );\n\n\t\tconst path = this.sourcePosition.path.slice( 0, -1 );\n\t\tconst insertionPosition = new Position( this.sourcePosition.root, path )._getTransformedByMergeOperation( this );\n\n\t\tconst split = new SplitOperation( targetPosition, this.howMany, this.graveyardPosition, this.baseVersion + 1 );\n\t\tsplit.insertionPosition = insertionPosition;\n\n\t\treturn split;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_validate() {\n\t\tconst sourceElement = this.sourcePosition.parent;\n\t\tconst targetElement = this.targetPosition.parent;\n\n\t\t// Validate whether merge operation has correct parameters.\n\t\tif ( !sourceElement.parent ) {\n\t\t\t/**\n\t\t\t * Merge source position is invalid. The element to be merged must have a parent node.\n\t\t\t *\n\t\t\t * @error merge-operation-source-position-invalid\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'merge-operation-source-position-invalid: Merge source position is invalid.', this );\n\t\t} else if ( !targetElement.parent ) {\n\t\t\t/**\n\t\t\t * Merge target position is invalid. The element to be merged must have a parent node.\n\t\t\t *\n\t\t\t * @error merge-operation-target-position-invalid\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'merge-operation-target-position-invalid: Merge target position is invalid.', this );\n\t\t} else if ( this.howMany != sourceElement.maxOffset ) {\n\t\t\t/**\n\t\t\t * Merge operation specifies wrong number of nodes to move.\n\t\t\t *\n\t\t\t * @error merge-operation-how-many-invalid\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'merge-operation-how-many-invalid: Merge operation specifies wrong number of nodes to move.', this );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\tconst mergedElement = this.sourcePosition.parent;\n\t\tconst sourceRange = Range._createIn( mergedElement );\n\n\t\t_move( sourceRange, this.targetPosition );\n\t\t_move( Range._createOn( mergedElement ), this.graveyardPosition );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.sourcePosition = json.sourcePosition.toJSON();\n\t\tjson.targetPosition = json.targetPosition.toJSON();\n\t\tjson.graveyardPosition = json.graveyardPosition.toJSON();\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'MergeOperation';\n\t}\n\n\t/**\n\t * Creates `MergeOperation` object from deserilized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} document Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/mergeoperation~MergeOperation}\n\t */\n\tstatic fromJSON( json, document ) {\n\t\tconst sourcePosition = Position.fromJSON( json.sourcePosition, document );\n\t\tconst targetPosition = Position.fromJSON( json.targetPosition, document );\n\t\tconst graveyardPosition = Position.fromJSON( json.graveyardPosition, document );\n\n\t\treturn new this( sourcePosition, json.howMany, targetPosition, graveyardPosition, json.baseVersion );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/splitoperation\n */\n\nimport Operation from './operation';\nimport MergeOperation from './mergeoperation';\nimport Position from '../position';\nimport Range from '../range';\nimport { _insert, _move } from './utils';\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Operation to split {@link module:engine/model/element~Element an element} at given\n * {@link module:engine/model/operation/splitoperation~SplitOperation#splitPosition split position} into two elements,\n * both containing a part of the element's original content.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class SplitOperation extends Operation {\n\t/**\n\t * Creates a split operation.\n\t *\n\t * @param {module:engine/model/position~Position} splitPosition Position at which an element should be split.\n\t * @param {Number} howMany Total offset size of elements that are in the split element after `position`.\n\t * @param {module:engine/model/position~Position|null} graveyardPosition Position in the graveyard root before the element which\n\t * should be used as a parent of the nodes after `position`. If it is not set, a copy of the the `position` parent will be used.\n\t * @param {Number|null} baseVersion Document {@link module:engine/model/document~Document#version} on which operation\n\t * can be applied or `null` if the operation operates on detached (non-document) tree.\n\t */\n\tconstructor( splitPosition, howMany, graveyardPosition, baseVersion ) {\n\t\tsuper( baseVersion );\n\n\t\t/**\n\t\t * Position at which an element should be split.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/splitoperation~SplitOperation#splitPosition\n\t\t */\n\t\tthis.splitPosition = splitPosition.clone();\n\t\t// Keep position sticking to the next node. This way any new content added at the place where the element is split\n\t\t// will be left in the original element.\n\t\tthis.splitPosition.stickiness = 'toNext';\n\n\t\t/**\n\t\t * Total offset size of elements that are in the split element after `position`.\n\t\t *\n\t\t * @member {Number} module:engine/model/operation/splitoperation~SplitOperation#howMany\n\t\t */\n\t\tthis.howMany = howMany;\n\n\t\t/**\n\t\t * Position at which the clone of split element (or element from graveyard) will be inserted.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} module:engine/model/operation/splitoperation~SplitOperation#insertionPosition\n\t\t */\n\t\tthis.insertionPosition = SplitOperation.getInsertionPosition( splitPosition );\n\t\tthis.insertionPosition.stickiness = 'toNone';\n\n\t\t/**\n\t\t * Position in the graveyard root before the element which should be used as a parent of the nodes after `position`.\n\t\t * If it is not set, a copy of the the `position` parent will be used.\n\t\t *\n\t\t * The default behavior is to clone the split element. Element from graveyard is used during undo.\n\t\t *\n\t\t * @member {module:engine/model/position~Position|null} #graveyardPosition\n\t\t */\n\t\tthis.graveyardPosition = graveyardPosition ? graveyardPosition.clone() : null;\n\n\t\tif ( this.graveyardPosition ) {\n\t\t\tthis.graveyardPosition.stickiness = 'toNext';\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tget type() {\n\t\treturn 'split';\n\t}\n\n\t/**\n\t * Position inside the new clone of a split element.\n\t *\n\t * This is a position where nodes that are after the split position will be moved to.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/position~Position}\n\t */\n\tget moveTargetPosition() {\n\t\tconst path = this.insertionPosition.path.slice();\n\t\tpath.push( 0 );\n\n\t\treturn new Position( this.insertionPosition.root, path );\n\t}\n\n\t/**\n\t * Artificial range that contains all the nodes from the split element that will be moved to the new element.\n\t * The range starts at {@link ~#splitPosition} and ends in the same parent, at `POSITIVE_INFINITY` offset.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/range~Range}\n\t */\n\tget movedRange() {\n\t\tconst end = this.splitPosition.getShiftedBy( Number.POSITIVE_INFINITY );\n\n\t\treturn new Range( this.splitPosition, end );\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/splitoperation~SplitOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\tconst split = new this.constructor( this.splitPosition, this.howMany, this.graveyardPosition, this.baseVersion );\n\t\tsplit.insertionPosition = this.insertionPosition;\n\n\t\treturn split;\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/mergeoperation~MergeOperation}\n\t */\n\tgetReversed() {\n\t\tconst graveyard = this.splitPosition.root.document.graveyard;\n\t\tconst graveyardPosition = new Position( graveyard, [ 0 ] );\n\n\t\treturn new MergeOperation( this.moveTargetPosition, this.howMany, this.splitPosition, graveyardPosition, this.baseVersion + 1 );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_validate() {\n\t\tconst element = this.splitPosition.parent;\n\t\tconst offset = this.splitPosition.offset;\n\n\t\t// Validate whether split operation has correct parameters.\n\t\tif ( !element || element.maxOffset < offset ) {\n\t\t\t/**\n\t\t\t * Split position is invalid.\n\t\t\t *\n\t\t\t * @error split-operation-position-invalid\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'split-operation-position-invalid: Split position is invalid.', this );\n\t\t} else if ( !element.parent ) {\n\t\t\t/**\n\t\t\t * Cannot split root element.\n\t\t\t *\n\t\t\t * @error split-operation-split-in-root\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'split-operation-split-in-root: Cannot split root element.', this );\n\t\t} else if ( this.howMany != element.maxOffset - this.splitPosition.offset ) {\n\t\t\t/**\n\t\t\t * Split operation specifies wrong number of nodes to move.\n\t\t\t *\n\t\t\t * @error split-operation-how-many-invalid\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'split-operation-how-many-invalid: Split operation specifies wrong number of nodes to move.', this );\n\t\t} else if ( this.graveyardPosition && !this.graveyardPosition.nodeAfter ) {\n\t\t\t/**\n\t\t\t * Graveyard position invalid.\n\t\t\t *\n\t\t\t * @error split-operation-graveyard-position-invalid\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'split-operation-graveyard-position-invalid: Graveyard position invalid.', this );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\t_execute() {\n\t\tconst splitElement = this.splitPosition.parent;\n\n\t\tif ( this.graveyardPosition ) {\n\t\t\t_move( Range._createFromPositionAndShift( this.graveyardPosition, 1 ), this.insertionPosition );\n\t\t} else {\n\t\t\tconst newElement = splitElement._clone();\n\n\t\t\t_insert( this.insertionPosition, newElement );\n\t\t}\n\n\t\tconst sourceRange = new Range(\n\t\t\tPosition._createAt( splitElement, this.splitPosition.offset ),\n\t\t\tPosition._createAt( splitElement, splitElement.maxOffset )\n\t\t);\n\n\t\t_move( sourceRange, this.moveTargetPosition );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\ttoJSON() {\n\t\tconst json = super.toJSON();\n\n\t\tjson.splitPosition = this.splitPosition.toJSON();\n\t\tjson.insertionPosition = this.insertionPosition.toJSON();\n\n\t\tif ( this.graveyardPosition ) {\n\t\t\tjson.graveyardPosition = this.graveyardPosition.toJSON();\n\t\t}\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'SplitOperation';\n\t}\n\n\t/**\n\t * Helper function that returns a default insertion position basing on given `splitPosition`. The default insertion\n\t * position is after the split element.\n\t *\n\t * @param {module:engine/model/position~Position} splitPosition\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tstatic getInsertionPosition( splitPosition ) {\n\t\tconst path = splitPosition.path.slice( 0, -1 );\n\t\tpath[ path.length - 1 ]++;\n\n\t\treturn new Position( splitPosition.root, path );\n\t}\n\n\t/**\n\t * Creates `SplitOperation` object from deserilized object, i.e. from parsed JSON string.\n\t *\n\t * @param {Object} json Deserialized JSON object.\n\t * @param {module:engine/model/document~Document} document Document on which this operation will be applied.\n\t * @returns {module:engine/model/operation/splitoperation~SplitOperation}\n\t */\n\tstatic fromJSON( json, document ) {\n\t\tconst splitPosition = Position.fromJSON( json.splitPosition, document );\n\t\tconst insertionPosition = Position.fromJSON( json.insertionPosition, document );\n\t\tconst graveyardPosition = json.graveyardPosition ? Position.fromJSON( json.graveyardPosition, document ) : null;\n\n\t\tconst split = new this( splitPosition, json.howMany, graveyardPosition, json.baseVersion );\n\t\tsplit.insertionPosition = insertionPosition;\n\n\t\treturn split;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/rootelement\n */\n\nimport Element from './element';\n\n/**\n * Type of {@link module:engine/model/element~Element} that is a root of a model tree.\n * @extends module:engine/model/element~Element\n */\nexport default class RootElement extends Element {\n\t/**\n\t * Creates root element.\n\t *\n\t * @param {module:engine/model/document~Document} doc Document that is an owner of this root.\n\t * @param {String} name Node name.\n\t * @param {String} [rootName='main'] Unique root name used to identify this root\n\t * element by {@link module:engine/model/document~Document}.\n\t */\n\tconstructor( doc, name, rootName = 'main' ) {\n\t\tsuper( name );\n\n\t\t/**\n\t\t * Document that is an owner of this root.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/document~Document}\n\t\t */\n\t\tthis._doc = doc;\n\n\t\t/**\n\t\t * Unique root name used to identify this root element by {@link module:engine/model/document~Document}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.rootName = rootName;\n\t}\n\n\t/**\n\t * {@link module:engine/model/document~Document Document} that owns this root element.\n\t *\n\t * In contrary, to {@link module:engine/model/node~Node node}, root element always have a `document`.\n\t *\n\t * @readonly\n\t * @type {module:engine/model/document~Document|null}\n\t */\n\tget document() {\n\t\treturn this._doc;\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\trootElement.is( 'rootElement' ); // -> true\n\t *\t\trootElement.is( 'element' ); // -> true\n\t *\t\trootElement.is( 'node' ); // -> true\n\t *\t\trootElement.is( 'model:rootElement' ); // -> true\n\t *\t\trootElement.is( 'model:element' ); // -> true\n\t *\t\trootElement.is( 'model:node' ); // -> true\n\t *\n\t *\t\trootElement.is( 'view:element' ); // -> false\n\t *\t\trootElement.is( 'documentFragment' ); // -> false\n\t *\n\t * Assuming that the object being checked is an element, you can also check its\n\t * {@link module:engine/model/element~Element#name name}:\n\t *\n\t *\t\trootElement.is( '$root' ); // -> true if this is a $root element\n\t *\t\trootElement.is( 'rootElement', '$root' ); // -> same as above\n\t *\t\ttext.is( '$root' ); -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type Type to check when `name` parameter is present.\n\t * Otherwise, it acts like the `name` parameter.\n\t * @param {String} [name] Element name.\n\t * @returns {Boolean}\n\t */\n\tis( type, name ) {\n\t\tconst cutType = type.replace( 'model:', '' );\n\t\tif ( !name ) {\n\t\t\treturn cutType == 'rootElement' || super.is( type );\n\t\t} else {\n\t\t\treturn ( cutType == 'rootElement' && name == this.name ) || super.is( type, name );\n\t\t}\n\t}\n\n\t/**\n\t * Converts `RootElement` instance to `String` containing it's name.\n\t *\n\t * @returns {String} `RootElement` instance converted to `String`.\n\t */\n\ttoJSON() {\n\t\treturn this.rootName;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/writer\n */\n\nimport AttributeOperation from './operation/attributeoperation';\nimport DetachOperation from './operation/detachoperation';\nimport InsertOperation from './operation/insertoperation';\nimport MarkerOperation from './operation/markeroperation';\nimport MoveOperation from './operation/moveoperation';\nimport RenameOperation from './operation/renameoperation';\nimport RootAttributeOperation from './operation/rootattributeoperation';\nimport SplitOperation from './operation/splitoperation';\nimport MergeOperation from './operation/mergeoperation';\n\nimport DocumentFragment from './documentfragment';\nimport Text from './text';\nimport Element from './element';\nimport RootElement from './rootelement';\nimport Position from './position';\nimport Range from './range.js';\nimport DocumentSelection from './documentselection';\n\nimport toMap from '@ckeditor/ckeditor5-utils/src/tomap';\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * The model can only be modified by using the writer. It should be used whenever you want to create a node, modify\n * child nodes, attributes or text, set the selection's position and its attributes.\n *\n * The instance of the writer is only available in the {@link module:engine/model/model~Model#change `change()`} or\n * {@link module:engine/model/model~Model#enqueueChange `enqueueChange()`}.\n *\n *\t\tmodel.change( writer => {\n *\t\t\twriter.insertText( 'foo', paragraph, 'end' );\n *\t\t} );\n *\n * Note that the writer should never be stored and used outside of the `change()` and\n * `enqueueChange()` blocks.\n *\n * Note that writer's methods do not check the {@link module:engine/model/schema~Schema}. It is possible\n * to create incorrect model structures by using the writer. Read more about in\n * {@glink framework/guides/deep-dive/schema#who-checks-the-schema \"Who checks the schema?\"}.\n *\n * @see module:engine/model/model~Model#change\n * @see module:engine/model/model~Model#enqueueChange\n */\nexport default class Writer {\n\t/**\n\t * Creates a writer instance.\n\t *\n\t * **Note:** It is not recommended to use it directly. Use {@link module:engine/model/model~Model#change `Model#change()`} or\n\t * {@link module:engine/model/model~Model#enqueueChange `Model#enqueueChange()`} instead.\n\t *\n\t * @protected\n\t * @param {module:engine/model/model~Model} model\n\t * @param {module:engine/model/batch~Batch} batch\n\t */\n\tconstructor( model, batch ) {\n\t\t/**\n\t\t * Instance of the model on which this writer operates.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/model~Model}\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * The batch to which this writer will add changes.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/batch~Batch}\n\t\t */\n\t\tthis.batch = batch;\n\t}\n\n\t/**\n\t * Creates a new {@link module:engine/model/text~Text text node}.\n\t *\n\t *\t\twriter.createText( 'foo' );\n\t *\t\twriter.createText( 'foo', { bold: true } );\n\t *\n\t * @param {String} data Text data.\n\t * @param {Object} [attributes] Text attributes.\n\t * @returns {module:engine/model/text~Text} Created text node.\n\t */\n\tcreateText( data, attributes ) {\n\t\treturn new Text( data, attributes );\n\t}\n\n\t/**\n\t * Creates a new {@link module:engine/model/element~Element element}.\n\t *\n\t *\t\twriter.createElement( 'paragraph' );\n\t *\t\twriter.createElement( 'paragraph', { alignment: 'center' } );\n\t *\n\t * @param {String} name Name of the element.\n\t * @param {Object} [attributes] Elements attributes.\n\t * @returns {module:engine/model/element~Element} Created element.\n\t */\n\tcreateElement( name, attributes ) {\n\t\treturn new Element( name, attributes );\n\t}\n\n\t/**\n\t * Creates a new {@link module:engine/model/documentfragment~DocumentFragment document fragment}.\n\t *\n\t * @returns {module:engine/model/documentfragment~DocumentFragment} Created document fragment.\n\t */\n\tcreateDocumentFragment() {\n\t\treturn new DocumentFragment();\n\t}\n\n\t/**\n\t * Inserts item on given position.\n\t *\n\t *\t\tconst paragraph = writer.createElement( 'paragraph' );\n\t *\t\twriter.insert( paragraph, position );\n\t *\n\t * Instead of using position you can use parent and offset:\n\t *\n\t *\t\tconst text = writer.createText( 'foo' );\n\t *\t\twriter.insert( text, paragraph, 5 );\n\t *\n\t * You can also use `end` instead of the offset to insert at the end:\n\t *\n\t *\t\tconst text = writer.createText( 'foo' );\n\t *\t\twriter.insert( text, paragraph, 'end' );\n\t *\n\t * Or insert before or after another element:\n\t *\n\t *\t\tconst paragraph = writer.createElement( 'paragraph' );\n\t *\t\twriter.insert( paragraph, anotherParagraph, 'after' );\n\t *\n\t * These parameters works the same way as {@link #createPositionAt `writer.createPositionAt()`}.\n\t *\n\t * Note that if the item already has parent it will be removed from the previous parent.\n\t *\n\t * Note that you cannot re-insert a node from a document to a different document or a document fragment. In this case,\n\t * `model-writer-insert-forbidden-move` is thrown.\n\t *\n\t * If you want to move {@link module:engine/model/range~Range range} instead of an\n\t * {@link module:engine/model/item~Item item} use {@link module:engine/model/writer~Writer#move `Writer#move()`}.\n\t *\n\t * **Note:** For a paste-like content insertion mechanism see\n\t * {@link module:engine/model/model~Model#insertContent `model.insertContent()`}.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/documentfragment~DocumentFragment} item Item or document\n\t * fragment to insert.\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * second parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\tinsert( item, itemOrPosition, offset = 0 ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( item instanceof Text && item.data == '' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst position = Position._createAt( itemOrPosition, offset );\n\n\t\t// If item has a parent already.\n\t\tif ( item.parent ) {\n\t\t\t// We need to check if item is going to be inserted within the same document.\n\t\t\tif ( isSameTree( item.root, position.root ) ) {\n\t\t\t\t// If it's we just need to move it.\n\t\t\t\tthis.move( Range._createOn( item ), position );\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// If it isn't the same root.\n\t\t\telse {\n\t\t\t\tif ( item.root.document ) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Cannot move a node from a document to a different tree.\n\t\t\t\t\t * It is forbidden to move a node that was already in a document outside of it.\n\t\t\t\t\t *\n\t\t\t\t\t * @error model-writer-insert-forbidden-move\n\t\t\t\t\t */\n\t\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t\t'model-writer-insert-forbidden-move: ' +\n\t\t\t\t\t\t'Cannot move a node from a document to a different tree. ' +\n\t\t\t\t\t\t'It is forbidden to move a node that was already in a document outside of it.',\n\t\t\t\t\t\tthis\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Move between two different document fragments or from document fragment to a document is possible.\n\t\t\t\t\t// In that case, remove the item from it's original parent.\n\t\t\t\t\tthis.remove( item );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst version = position.root.document ? position.root.document.version : null;\n\n\t\tconst insert = new InsertOperation( position, item, version );\n\n\t\tif ( item instanceof Text ) {\n\t\t\tinsert.shouldReceiveAttributes = true;\n\t\t}\n\n\t\tthis.batch.addOperation( insert );\n\t\tthis.model.applyOperation( insert );\n\n\t\t// When element is a DocumentFragment we need to move its markers to Document#markers.\n\t\tif ( item instanceof DocumentFragment ) {\n\t\t\tfor ( const [ markerName, markerRange ] of item.markers ) {\n\t\t\t\t// We need to migrate marker range from DocumentFragment to Document.\n\t\t\t\tconst rangeRootPosition = Position._createAt( markerRange.root, 0 );\n\t\t\t\tconst range = new Range(\n\t\t\t\t\tmarkerRange.start._getCombined( rangeRootPosition, position ),\n\t\t\t\t\tmarkerRange.end._getCombined( rangeRootPosition, position )\n\t\t\t\t);\n\n\t\t\t\tconst options = { range, usingOperation: true, affectsData: true };\n\n\t\t\t\tif ( this.model.markers.has( markerName ) ) {\n\t\t\t\t\tthis.updateMarker( markerName, options );\n\t\t\t\t} else {\n\t\t\t\t\tthis.addMarker( markerName, options );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Creates and inserts text on given position. You can optionally set text attributes:\n\t *\n\t *\t\twriter.insertText( 'foo', position );\n\t *\t\twriter.insertText( 'foo', { bold: true }, position );\n\t *\n\t * Instead of using position you can use parent and offset or define that text should be inserted at the end\n\t * or before or after other node:\n\t *\n\t *\t\t// Inserts 'foo' in paragraph, at offset 5:\n\t *\t\twriter.insertText( 'foo', paragraph, 5 );\n\t *\t\t// Inserts 'foo' at the end of a paragraph:\n\t *\t\twriter.insertText( 'foo', paragraph, 'end' );\n\t *\t\t// Inserts 'foo' after an image:\n\t *\t\twriter.insertText( 'foo', image, 'after' );\n\t *\n\t * These parameters work in the same way as {@link #createPositionAt `writer.createPositionAt()`}.\n\t *\n\t * @param {String} data Text data.\n\t * @param {Object} [attributes] Text attributes.\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * third parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\tinsertText( text, attributes, itemOrPosition, offset ) {\n\t\tif ( attributes instanceof DocumentFragment || attributes instanceof Element || attributes instanceof Position ) {\n\t\t\tthis.insert( this.createText( text ), attributes, itemOrPosition );\n\t\t} else {\n\t\t\tthis.insert( this.createText( text, attributes ), itemOrPosition, offset );\n\t\t}\n\t}\n\n\t/**\n\t * Creates and inserts element on given position. You can optionally set attributes:\n\t *\n\t *\t\twriter.insertElement( 'paragraph', position );\n\t *\t\twriter.insertElement( 'paragraph', { alignment: 'center' }, position );\n\t *\n\t * Instead of using position you can use parent and offset or define that text should be inserted at the end\n\t * or before or after other node:\n\t *\n\t *\t\t// Inserts paragraph in the root at offset 5:\n\t *\t\twriter.insertElement( 'paragraph', root, 5 );\n\t *\t\t// Inserts paragraph at the end of a blockquote:\n\t *\t\twriter.insertElement( 'paragraph', blockquote, 'end' );\n\t *\t\t// Inserts after an image:\n\t *\t\twriter.insertElement( 'paragraph', image, 'after' );\n\t *\n\t * These parameters works the same way as {@link #createPositionAt `writer.createPositionAt()`}.\n\t *\n\t * @param {String} name Name of the element.\n\t * @param {Object} [attributes] Elements attributes.\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * third parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\tinsertElement( name, attributes, itemOrPosition, offset ) {\n\t\tif ( attributes instanceof DocumentFragment || attributes instanceof Element || attributes instanceof Position ) {\n\t\t\tthis.insert( this.createElement( name ), attributes, itemOrPosition );\n\t\t} else {\n\t\t\tthis.insert( this.createElement( name, attributes ), itemOrPosition, offset );\n\t\t}\n\t}\n\n\t/**\n\t * Inserts item at the end of the given parent.\n\t *\n\t *\t\tconst paragraph = writer.createElement( 'paragraph' );\n\t *\t\twriter.append( paragraph, root );\n\t *\n\t * Note that if the item already has parent it will be removed from the previous parent.\n\t *\n\t * If you want to move {@link module:engine/model/range~Range range} instead of an\n\t * {@link module:engine/model/item~Item item} use {@link module:engine/model/writer~Writer#move `Writer#move()`}.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/documentfragment~DocumentFragment}\n\t * item Item or document fragment to insert.\n\t * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} parent\n\t */\n\tappend( item, parent ) {\n\t\tthis.insert( item, parent, 'end' );\n\t}\n\n\t/**\n\t * Creates text node and inserts it at the end of the parent. You can optionally set text attributes:\n\t *\n\t *\t\twriter.appendText( 'foo', paragraph );\n\t *\t\twriter.appendText( 'foo', { bold: true }, paragraph );\n\t *\n\t * @param {String} text Text data.\n\t * @param {Object} [attributes] Text attributes.\n\t * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} parent\n\t */\n\tappendText( text, attributes, parent ) {\n\t\tif ( attributes instanceof DocumentFragment || attributes instanceof Element ) {\n\t\t\tthis.insert( this.createText( text ), attributes, 'end' );\n\t\t} else {\n\t\t\tthis.insert( this.createText( text, attributes ), parent, 'end' );\n\t\t}\n\t}\n\n\t/**\n\t * Creates element and inserts it at the end of the parent. You can optionally set attributes:\n\t *\n\t *\t\twriter.appendElement( 'paragraph', root );\n\t *\t\twriter.appendElement( 'paragraph', { alignment: 'center' }, root );\n\t *\n\t * @param {String} name Name of the element.\n\t * @param {Object} [attributes] Elements attributes.\n\t * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} parent\n\t */\n\tappendElement( name, attributes, parent ) {\n\t\tif ( attributes instanceof DocumentFragment || attributes instanceof Element ) {\n\t\t\tthis.insert( this.createElement( name ), attributes, 'end' );\n\t\t} else {\n\t\t\tthis.insert( this.createElement( name, attributes ), parent, 'end' );\n\t\t}\n\t}\n\n\t/**\n\t * Sets value of the attribute with given key on a {@link module:engine/model/item~Item model item}\n\t * or on a {@link module:engine/model/range~Range range}.\n\t *\n\t * @param {String} key Attribute key.\n\t * @param {*} value Attribute new value.\n\t * @param {module:engine/model/item~Item|module:engine/model/range~Range} itemOrRange\n\t * Model item or range on which the attribute will be set.\n\t */\n\tsetAttribute( key, value, itemOrRange ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( itemOrRange instanceof Range ) {\n\t\t\tconst ranges = itemOrRange.getMinimalFlatRanges();\n\n\t\t\tfor ( const range of ranges ) {\n\t\t\t\tsetAttributeOnRange( this, key, value, range );\n\t\t\t}\n\t\t} else {\n\t\t\tsetAttributeOnItem( this, key, value, itemOrRange );\n\t\t}\n\t}\n\n\t/**\n\t * Sets values of attributes on a {@link module:engine/model/item~Item model item}\n\t * or on a {@link module:engine/model/range~Range range}.\n\t *\n\t *\t\twriter.setAttributes( {\n\t *\t\t\tbold: true,\n\t *\t\t\titalic: true\n\t *\t\t}, range );\n\t *\n\t * @param {Object} attributes Attributes keys and values.\n\t * @param {module:engine/model/item~Item|module:engine/model/range~Range} itemOrRange\n\t * Model item or range on which the attributes will be set.\n\t */\n\tsetAttributes( attributes, itemOrRange ) {\n\t\tfor ( const [ key, val ] of toMap( attributes ) ) {\n\t\t\tthis.setAttribute( key, val, itemOrRange );\n\t\t}\n\t}\n\n\t/**\n\t * Removes an attribute with given key from a {@link module:engine/model/item~Item model item}\n\t * or from a {@link module:engine/model/range~Range range}.\n\t *\n\t * @param {String} key Attribute key.\n\t * @param {module:engine/model/item~Item|module:engine/model/range~Range} itemOrRange\n\t * Model item or range from which the attribute will be removed.\n\t */\n\tremoveAttribute( key, itemOrRange ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( itemOrRange instanceof Range ) {\n\t\t\tconst ranges = itemOrRange.getMinimalFlatRanges();\n\n\t\t\tfor ( const range of ranges ) {\n\t\t\t\tsetAttributeOnRange( this, key, null, range );\n\t\t\t}\n\t\t} else {\n\t\t\tsetAttributeOnItem( this, key, null, itemOrRange );\n\t\t}\n\t}\n\n\t/**\n\t * Removes all attributes from all elements in the range or from the given item.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/range~Range} itemOrRange\n\t * Model item or range from which all attributes will be removed.\n\t */\n\tclearAttributes( itemOrRange ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tconst removeAttributesFromItem = item => {\n\t\t\tfor ( const attribute of item.getAttributeKeys() ) {\n\t\t\t\tthis.removeAttribute( attribute, item );\n\t\t\t}\n\t\t};\n\n\t\tif ( !( itemOrRange instanceof Range ) ) {\n\t\t\tremoveAttributesFromItem( itemOrRange );\n\t\t} else {\n\t\t\tfor ( const item of itemOrRange.getItems() ) {\n\t\t\t\tremoveAttributesFromItem( item );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Moves all items in the source range to the target position.\n\t *\n\t *\t\twriter.move( sourceRange, targetPosition );\n\t *\n\t * Instead of the target position you can use parent and offset or define that range should be moved to the end\n\t * or before or after chosen item:\n\t *\n\t *\t\t// Moves all items in the range to the paragraph at offset 5:\n\t *\t\twriter.move( sourceRange, paragraph, 5 );\n\t *\t\t// Moves all items in the range to the end of a blockquote:\n\t *\t\twriter.move( sourceRange, blockquote, 'end' );\n\t *\t\t// Moves all items in the range to a position after an image:\n\t *\t\twriter.move( sourceRange, image, 'after' );\n\t *\n\t * These parameters works the same way as {@link #createPositionAt `writer.createPositionAt()`}.\n\t *\n\t * Note that items can be moved only within the same tree. It means that you can move items within the same root\n\t * (element or document fragment) or between {@link module:engine/model/document~Document#roots documents roots},\n\t * but you can not move items from document fragment to the document or from one detached element to another. Use\n\t * {@link module:engine/model/writer~Writer#insert} in such cases.\n\t *\n\t * @param {module:engine/model/range~Range} range Source range.\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * second parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\tmove( range, itemOrPosition, offset ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( !( range instanceof Range ) ) {\n\t\t\t/**\n\t\t\t * Invalid range to move.\n\t\t\t *\n\t\t\t * @error writer-move-invalid-range\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-move-invalid-range: Invalid range to move.', this );\n\t\t}\n\n\t\tif ( !range.isFlat ) {\n\t\t\t/**\n\t\t\t * Range to move is not flat.\n\t\t\t *\n\t\t\t * @error writer-move-range-not-flat\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-move-range-not-flat: Range to move is not flat.', this );\n\t\t}\n\n\t\tconst position = Position._createAt( itemOrPosition, offset );\n\n\t\t// Do not move anything if the move target is same as moved range start.\n\t\tif ( position.isEqual( range.start ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If part of the marker is removed, create additional marker operation for undo purposes.\n\t\tthis._addOperationForAffectedMarkers( 'move', range );\n\n\t\tif ( !isSameTree( range.root, position.root ) ) {\n\t\t\t/**\n\t\t\t * Range is going to be moved within not the same document. Please use\n\t\t\t * {@link module:engine/model/writer~Writer#insert insert} instead.\n\t\t\t *\n\t\t\t * @error writer-move-different-document\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-move-different-document: Range is going to be moved between different documents.', this );\n\t\t}\n\n\t\tconst version = range.root.document ? range.root.document.version : null;\n\t\tconst operation = new MoveOperation( range.start, range.end.offset - range.start.offset, position, version );\n\n\t\tthis.batch.addOperation( operation );\n\t\tthis.model.applyOperation( operation );\n\t}\n\n\t/**\n\t * Removes given model {@link module:engine/model/item~Item item} or {@link module:engine/model/range~Range range}.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/range~Range} itemOrRange Model item or range to remove.\n\t */\n\tremove( itemOrRange ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tconst rangeToRemove = itemOrRange instanceof Range ? itemOrRange : Range._createOn( itemOrRange );\n\t\tconst ranges = rangeToRemove.getMinimalFlatRanges().reverse();\n\n\t\tfor ( const flat of ranges ) {\n\t\t\t// If part of the marker is removed, create additional marker operation for undo purposes.\n\t\t\tthis._addOperationForAffectedMarkers( 'move', flat );\n\n\t\t\tapplyRemoveOperation( flat.start, flat.end.offset - flat.start.offset, this.batch, this.model );\n\t\t}\n\t}\n\n\t/**\n\t * Merges two siblings at the given position.\n\t *\n\t * Node before and after the position have to be an element. Otherwise `writer-merge-no-element-before` or\n\t * `writer-merge-no-element-after` error will be thrown.\n\t *\n\t * @param {module:engine/model/position~Position} position Position between merged elements.\n\t */\n\tmerge( position ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tconst nodeBefore = position.nodeBefore;\n\t\tconst nodeAfter = position.nodeAfter;\n\n\t\t// If part of the marker is removed, create additional marker operation for undo purposes.\n\t\tthis._addOperationForAffectedMarkers( 'merge', position );\n\n\t\tif ( !( nodeBefore instanceof Element ) ) {\n\t\t\t/**\n\t\t\t * Node before merge position must be an element.\n\t\t\t *\n\t\t\t * @error writer-merge-no-element-before\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-merge-no-element-before: Node before merge position must be an element.', this );\n\t\t}\n\n\t\tif ( !( nodeAfter instanceof Element ) ) {\n\t\t\t/**\n\t\t\t * Node after merge position must be an element.\n\t\t\t *\n\t\t\t * @error writer-merge-no-element-after\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-merge-no-element-after: Node after merge position must be an element.', this );\n\t\t}\n\n\t\tif ( !position.root.document ) {\n\t\t\tthis._mergeDetached( position );\n\t\t} else {\n\t\t\tthis._merge( position );\n\t\t}\n\t}\n\n\t/**\n\t * Shortcut for {@link module:engine/model/model~Model#createPositionFromPath `Model#createPositionFromPath()`}.\n\t *\n\t * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} root Root of the position.\n\t * @param {Array.<Number>} path Position path. See {@link module:engine/model/position~Position#path}.\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.\n\t * See {@link module:engine/model/position~PositionStickiness}.\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tcreatePositionFromPath( root, path, stickiness ) {\n\t\treturn this.model.createPositionFromPath( root, path, stickiness );\n\t}\n\n\t/**\n\t * Shortcut for {@link module:engine/model/model~Model#createPositionAt `Model#createPositionAt()`}.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/model/item~Item model item}.\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tcreatePositionAt( itemOrPosition, offset ) {\n\t\treturn this.model.createPositionAt( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Shortcut for {@link module:engine/model/model~Model#createPositionAfter `Model#createPositionAfter()`}.\n\t *\n\t * @param {module:engine/model/item~Item} item Item after which the position should be placed.\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tcreatePositionAfter( item ) {\n\t\treturn this.model.createPositionAfter( item );\n\t}\n\n\t/**\n\t * Shortcut for {@link module:engine/model/model~Model#createPositionBefore `Model#createPositionBefore()`}.\n\t *\n\t * @param {module:engine/model/item~Item} item Item after which the position should be placed.\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tcreatePositionBefore( item ) {\n\t\treturn this.model.createPositionBefore( item );\n\t}\n\n\t/**\n\t * Shortcut for {@link module:engine/model/model~Model#createRange `Model#createRange()`}.\n\t *\n\t * @param {module:engine/model/position~Position} start Start position.\n\t * @param {module:engine/model/position~Position} [end] End position. If not set, range will be collapsed at `start` position.\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tcreateRange( start, end ) {\n\t\treturn this.model.createRange( start, end );\n\t}\n\n\t/**\n\t * Shortcut for {@link module:engine/model/model~Model#createRangeIn `Model#createRangeIn()`}.\n\t *\n\t * @param {module:engine/model/element~Element} element Element which is a parent for the range.\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tcreateRangeIn( element ) {\n\t\treturn this.model.createRangeIn( element );\n\t}\n\n\t/**\n\t * Shortcut for {@link module:engine/model/model~Model#createRangeOn `Model#createRangeOn()`}.\n\t *\n\t * @param {module:engine/model/element~Element} element Element which is a parent for the range.\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tcreateRangeOn( element ) {\n\t\treturn this.model.createRangeOn( element );\n\t}\n\n\t/**\n\t * Shortcut for {@link module:engine/model/model~Model#createSelection `Model#createSelection()`}.\n\t *\n\t * @param {module:engine/model/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @returns {module:engine/model/selection~Selection}\n\t */\n\tcreateSelection( selectable, placeOrOffset, options ) {\n\t\treturn this.model.createSelection( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Performs merge action in a detached tree.\n\t *\n\t * @private\n\t * @param {module:engine/model/position~Position} position Position between merged elements.\n\t */\n\t_mergeDetached( position ) {\n\t\tconst nodeBefore = position.nodeBefore;\n\t\tconst nodeAfter = position.nodeAfter;\n\n\t\tthis.move( Range._createIn( nodeAfter ), Position._createAt( nodeBefore, 'end' ) );\n\t\tthis.remove( nodeAfter );\n\t}\n\n\t/**\n\t * Performs merge action in a non-detached tree.\n\t *\n\t * @private\n\t * @param {module:engine/model/position~Position} position Position between merged elements.\n\t */\n\t_merge( position ) {\n\t\tconst targetPosition = Position._createAt( position.nodeBefore, 'end' );\n\t\tconst sourcePosition = Position._createAt( position.nodeAfter, 0 );\n\n\t\tconst graveyard = position.root.document.graveyard;\n\t\tconst graveyardPosition = new Position( graveyard, [ 0 ] );\n\n\t\tconst version = position.root.document.version;\n\n\t\tconst merge = new MergeOperation( sourcePosition, position.nodeAfter.maxOffset, targetPosition, graveyardPosition, version );\n\n\t\tthis.batch.addOperation( merge );\n\t\tthis.model.applyOperation( merge );\n\t}\n\n\t/**\n\t * Renames the given element.\n\t *\n\t * @param {module:engine/model/element~Element} element The element to rename.\n\t * @param {String} newName New element name.\n\t */\n\trename( element, newName ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( !( element instanceof Element ) ) {\n\t\t\t/**\n\t\t\t * Trying to rename an object which is not an instance of Element.\n\t\t\t *\n\t\t\t * @error writer-rename-not-element-instance\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'writer-rename-not-element-instance: Trying to rename an object which is not an instance of Element.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tconst version = element.root.document ? element.root.document.version : null;\n\t\tconst renameOperation = new RenameOperation( Position._createBefore( element ), element.name, newName, version );\n\n\t\tthis.batch.addOperation( renameOperation );\n\t\tthis.model.applyOperation( renameOperation );\n\t}\n\n\t/**\n\t * Splits elements starting from the given position and going to the top of the model tree as long as given\n\t * `limitElement` is reached. When `limitElement` is not defined then only the parent of the given position will be split.\n\t *\n\t * The element needs to have a parent. It cannot be a root element nor a document fragment.\n\t * The `writer-split-element-no-parent` error will be thrown if you try to split an element with no parent.\n\t *\n\t * @param {module:engine/model/position~Position} position Position of split.\n\t * @param {module:engine/model/node~Node} [limitElement] Stop splitting when this element will be reached.\n\t * @returns {Object} result Split result.\n\t * @returns {module:engine/model/position~Position} result.position Position between split elements.\n\t * @returns {module:engine/model/range~Range} result.range Range that stars from the end of the first split element and ends\n\t * at the beginning of the first copy element.\n\t */\n\tsplit( position, limitElement ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tlet splitElement = position.parent;\n\n\t\tif ( !splitElement.parent ) {\n\t\t\t/**\n\t\t\t * Element with no parent can not be split.\n\t\t\t *\n\t\t\t * @error writer-split-element-no-parent\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-split-element-no-parent: Element with no parent can not be split.', this );\n\t\t}\n\n\t\t// When limit element is not defined lets set splitElement parent as limit.\n\t\tif ( !limitElement ) {\n\t\t\tlimitElement = splitElement.parent;\n\t\t}\n\n\t\tif ( !position.parent.getAncestors( { includeSelf: true } ).includes( limitElement ) ) {\n\t\t\tthrow new CKEditorError( 'writer-split-invalid-limit-element: Limit element is not a position ancestor.', this );\n\t\t}\n\n\t\t// We need to cache elements that will be created as a result of the first split because\n\t\t// we need to create a range from the end of the first split element to the beginning of the\n\t\t// first copy element. This should be handled by LiveRange but it doesn't work on detached nodes.\n\t\tlet firstSplitElement, firstCopyElement;\n\n\t\tdo {\n\t\t\tconst version = splitElement.root.document ? splitElement.root.document.version : null;\n\t\t\tconst howMany = splitElement.maxOffset - position.offset;\n\t\t\tconst split = new SplitOperation( position, howMany, null, version );\n\n\t\t\tthis.batch.addOperation( split );\n\t\t\tthis.model.applyOperation( split );\n\n\t\t\t// Cache result of the first split.\n\t\t\tif ( !firstSplitElement && !firstCopyElement ) {\n\t\t\t\tfirstSplitElement = splitElement;\n\t\t\t\tfirstCopyElement = position.parent.nextSibling;\n\t\t\t}\n\n\t\t\tposition = this.createPositionAfter( position.parent );\n\t\t\tsplitElement = position.parent;\n\t\t} while ( splitElement !== limitElement );\n\n\t\treturn {\n\t\t\tposition,\n\t\t\trange: new Range( Position._createAt( firstSplitElement, 'end' ), Position._createAt( firstCopyElement, 0 ) )\n\t\t};\n\t}\n\n\t/**\n\t * Wraps the given range with the given element or with a new element (if a string was passed).\n\t *\n\t * **Note:** range to wrap should be a \"flat range\" (see {@link module:engine/model/range~Range#isFlat `Range#isFlat`}).\n\t * If not, an error will be thrown.\n\t *\n\t * @param {module:engine/model/range~Range} range Range to wrap.\n\t * @param {module:engine/model/element~Element|String} elementOrString Element or name of element to wrap the range with.\n\t */\n\twrap( range, elementOrString ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( !range.isFlat ) {\n\t\t\t/**\n\t\t\t * Range to wrap is not flat.\n\t\t\t *\n\t\t\t * @error writer-wrap-range-not-flat\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-wrap-range-not-flat: Range to wrap is not flat.', this );\n\t\t}\n\n\t\tconst element = elementOrString instanceof Element ? elementOrString : new Element( elementOrString );\n\n\t\tif ( element.childCount > 0 ) {\n\t\t\t/**\n\t\t\t * Element to wrap with is not empty.\n\t\t\t *\n\t\t\t * @error writer-wrap-element-not-empty\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-wrap-element-not-empty: Element to wrap with is not empty.', this );\n\t\t}\n\n\t\tif ( element.parent !== null ) {\n\t\t\t/**\n\t\t\t * Element to wrap with is already attached to a tree model.\n\t\t\t *\n\t\t\t * @error writer-wrap-element-attached\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-wrap-element-attached: Element to wrap with is already attached to tree model.', this );\n\t\t}\n\n\t\tthis.insert( element, range.start );\n\n\t\t// Shift the range-to-wrap because we just inserted an element before that range.\n\t\tconst shiftedRange = new Range( range.start.getShiftedBy( 1 ), range.end.getShiftedBy( 1 ) );\n\n\t\tthis.move( shiftedRange, Position._createAt( element, 0 ) );\n\t}\n\n\t/**\n\t * Unwraps children of the given element – all its children are moved before it and then the element is removed.\n\t * Throws error if you try to unwrap an element which does not have a parent.\n\t *\n\t * @param {module:engine/model/element~Element} element Element to unwrap.\n\t */\n\tunwrap( element ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( element.parent === null ) {\n\t\t\t/**\n\t\t\t * Trying to unwrap an element which has no parent.\n\t\t\t *\n\t\t\t * @error writer-unwrap-element-no-parent\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-unwrap-element-no-parent: Trying to unwrap an element which has no parent.', this );\n\t\t}\n\n\t\tthis.move( Range._createIn( element ), this.createPositionAfter( element ) );\n\t\tthis.remove( element );\n\t}\n\n\t/**\n\t * Adds a {@link module:engine/model/markercollection~Marker marker}. Marker is a named range, which tracks\n\t * changes in the document and updates its range automatically, when model tree changes.\n\t *\n\t * As the first parameter you can set marker name.\n\t *\n\t * The required `options.usingOperation` parameter lets you decide if the marker should be managed by operations or not. See\n\t * {@link module:engine/model/markercollection~Marker marker class description} to learn about the difference between\n\t * markers managed by operations and not-managed by operations.\n\t *\n\t * The `options.affectsData` parameter, which defaults to `false`, allows you to define if a marker affects the data. It should be\n\t * `true` when the marker change changes the data returned by the\n\t * {@link module:core/editor/utils/dataapimixin~DataApi#getData `editor.getData()`} method.\n\t * When set to `true` it fires the {@link module:engine/model/document~Document#event:change:data `change:data`} event.\n\t * When set to `false` it fires the {@link module:engine/model/document~Document#event:change `change`} event.\n\t *\n\t * Create marker directly base on marker's name:\n\t *\n\t *\t\taddMarker( markerName, { range, usingOperation: false } );\n\t *\n\t * Create marker using operation:\n\t *\n\t *\t\taddMarker( markerName, { range, usingOperation: true } );\n\t *\n\t * Create marker that affects the editor data:\n\t *\n\t *\t\taddMarker( markerName, { range, usingOperation: false, affectsData: true } );\n\t *\n\t * Note: For efficiency reasons, it's best to create and keep as little markers as possible.\n\t *\n\t * @see module:engine/model/markercollection~Marker\n\t * @param {String} name Name of a marker to create - must be unique.\n\t * @param {Object} options\n\t * @param {Boolean} options.usingOperation Flag indicating that the marker should be added by MarkerOperation.\n\t * See {@link module:engine/model/markercollection~Marker#managedUsingOperations}.\n\t * @param {module:engine/model/range~Range} options.range Marker range.\n\t * @param {Boolean} [options.affectsData=false] Flag indicating that the marker changes the editor data.\n\t * @returns {module:engine/model/markercollection~Marker} Marker that was set.\n\t */\n\taddMarker( name, options ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( !options || typeof options.usingOperation != 'boolean' ) {\n\t\t\t/**\n\t\t\t * The `options.usingOperation` parameter is required when adding a new marker.\n\t\t\t *\n\t\t\t * @error writer-addMarker-no-usingOperation\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'writer-addMarker-no-usingOperation: The options.usingOperation parameter is required when adding a new marker.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tconst usingOperation = options.usingOperation;\n\t\tconst range = options.range;\n\t\tconst affectsData = options.affectsData === undefined ? false : options.affectsData;\n\n\t\tif ( this.model.markers.has( name ) ) {\n\t\t\t/**\n\t\t\t * Marker with provided name already exists.\n\t\t\t *\n\t\t\t * @error writer-addMarker-marker-exists\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-addMarker-marker-exists: Marker with provided name already exists.', this );\n\t\t}\n\n\t\tif ( !range ) {\n\t\t\t/**\n\t\t\t * Range parameter is required when adding a new marker.\n\t\t\t *\n\t\t\t * @error writer-addMarker-no-range\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'writer-addMarker-no-range: Range parameter is required when adding a new marker.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tif ( !usingOperation ) {\n\t\t\treturn this.model.markers._set( name, range, usingOperation, affectsData );\n\t\t}\n\n\t\tapplyMarkerOperation( this, name, null, range, affectsData );\n\n\t\treturn this.model.markers.get( name );\n\t}\n\n\t/**\n\t * Adds, updates or refreshes a {@link module:engine/model/markercollection~Marker marker}. Marker is a named range, which tracks\n\t * changes in the document and updates its range automatically, when model tree changes. Still, it is possible to change the\n\t * marker's range directly using this method.\n\t *\n\t * As the first parameter you can set marker name or instance. If none of them is provided, new marker, with a unique\n\t * name is created and returned.\n\t *\n\t * As the second parameter you can set the new marker data or leave this parameter as empty which will just refresh\n\t * the marker by triggering downcast conversion for it. Refreshing the marker is useful when you want to change\n\t * the marker {@link module:engine/view/element~Element view element} without changing any marker data.\n\t *\n\t * \t\tlet isCommentActive = false;\n\t *\n\t * \t\tmodel.conversion.markerToHighlight( {\n\t * \t\t\tmodel: 'comment',\n\t *\t\t\tview: data => {\n\t *\t\t\t\tconst classes = [ 'comment-marker' ];\n\t *\n\t *\t\t\t\tif ( isCommentActive ) {\n\t *\t\t\t\t\tclasses.push( 'comment-marker--active' );\n\t *\t\t\t\t}\n\t *\n\t *\t\t\t\treturn { classes };\n\t *\t\t\t}\n\t * \t\t} );\n\t *\n\t * \t\t// Change the property that indicates if marker is displayed as active or not.\n\t * \t\tisCommentActive = true;\n\t *\n\t * \t\t// And refresh the marker to convert it with additional class.\n\t * \t\tmodel.change( writer => writer.updateMarker( 'comment' ) );\n\t *\n\t * The `options.usingOperation` parameter lets you change if the marker should be managed by operations or not. See\n\t * {@link module:engine/model/markercollection~Marker marker class description} to learn about the difference between\n\t * markers managed by operations and not-managed by operations. It is possible to change this option for an existing marker.\n\t *\n\t * The `options.affectsData` parameter, which defaults to `false`, allows you to define if a marker affects the data. It should be\n\t * `true` when the marker change changes the data returned by\n\t * the {@link module:core/editor/utils/dataapimixin~DataApi#getData `editor.getData()`} method.\n\t * When set to `true` it fires the {@link module:engine/model/document~Document#event:change:data `change:data`} event.\n\t * When set to `false` it fires the {@link module:engine/model/document~Document#event:change `change`} event.\n\t *\n\t * Update marker directly base on marker's name:\n\t *\n\t *\t\tupdateMarker( markerName, { range } );\n\t *\n\t * Update marker using operation:\n\t *\n\t *\t\tupdateMarker( marker, { range, usingOperation: true } );\n\t *\t\tupdateMarker( markerName, { range, usingOperation: true } );\n\t *\n\t * Change marker's option (start using operations to manage it):\n\t *\n\t *\t\tupdateMarker( marker, { usingOperation: true } );\n\t *\n\t * Change marker's option (inform the engine, that the marker does not affect the data anymore):\n\t *\n\t *\t\tupdateMarker( markerName, { affectsData: false } );\n\t *\n\t * @see module:engine/model/markercollection~Marker\n\t * @param {String|module:engine/model/markercollection~Marker} markerOrName Name of a marker to update, or a marker instance.\n\t * @param {Object} [options] If options object is not defined then marker will be refreshed by triggering\n\t * downcast conversion for this marker with the same data.\n\t * @param {module:engine/model/range~Range} [options.range] Marker range to update.\n\t * @param {Boolean} [options.usingOperation] Flag indicated whether the marker should be added by MarkerOperation.\n\t * See {@link module:engine/model/markercollection~Marker#managedUsingOperations}.\n\t * @param {Boolean} [options.affectsData] Flag indicating that the marker changes the editor data.\n\t */\n\tupdateMarker( markerOrName, options ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tconst markerName = typeof markerOrName == 'string' ? markerOrName : markerOrName.name;\n\t\tconst currentMarker = this.model.markers.get( markerName );\n\n\t\tif ( !currentMarker ) {\n\t\t\t/**\n\t\t\t * Marker with provided name does not exists.\n\t\t\t *\n\t\t\t * @error writer-updateMarker-marker-not-exists\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-updateMarker-marker-not-exists: Marker with provided name does not exists.', this );\n\t\t}\n\n\t\tif ( !options ) {\n\t\t\tthis.model.markers._refresh( currentMarker );\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst hasUsingOperationDefined = typeof options.usingOperation == 'boolean';\n\t\tconst affectsDataDefined = typeof options.affectsData == 'boolean';\n\n\t\t// Use previously defined marker's affectsData if the property is not provided.\n\t\tconst affectsData = affectsDataDefined ? options.affectsData : currentMarker.affectsData;\n\n\t\tif ( !hasUsingOperationDefined && !options.range && !affectsDataDefined ) {\n\t\t\t/**\n\t\t\t * One of the options is required - provide range, usingOperations or affectsData.\n\t\t\t *\n\t\t\t * @error writer-updateMarker-wrong-options\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'writer-updateMarker-wrong-options: One of the options is required - provide range, usingOperations or affectsData.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tconst currentRange = currentMarker.getRange();\n\t\tconst updatedRange = options.range ? options.range : currentRange;\n\n\t\tif ( hasUsingOperationDefined && options.usingOperation !== currentMarker.managedUsingOperations ) {\n\t\t\t// The marker type is changed so it's necessary to create proper operations.\n\t\t\tif ( options.usingOperation ) {\n\t\t\t\t// If marker changes to a managed one treat this as synchronizing existing marker.\n\t\t\t\t// Create `MarkerOperation` with `oldRange` set to `null`, so reverse operation will remove the marker.\n\t\t\t\tapplyMarkerOperation( this, markerName, null, updatedRange, affectsData );\n\t\t\t} else {\n\t\t\t\t// If marker changes to a marker that do not use operations then we need to create additional operation\n\t\t\t\t// that removes that marker first.\n\t\t\t\tapplyMarkerOperation( this, markerName, currentRange, null, affectsData );\n\n\t\t\t\t// Although not managed the marker itself should stay in model and its range should be preserver or changed to passed range.\n\t\t\t\tthis.model.markers._set( markerName, updatedRange, undefined, affectsData );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Marker's type doesn't change so update it accordingly.\n\t\tif ( currentMarker.managedUsingOperations ) {\n\t\t\tapplyMarkerOperation( this, markerName, currentRange, updatedRange, affectsData );\n\t\t} else {\n\t\t\tthis.model.markers._set( markerName, updatedRange, undefined, affectsData );\n\t\t}\n\t}\n\n\t/**\n\t * Removes given {@link module:engine/model/markercollection~Marker marker} or marker with given name.\n\t * The marker is removed accordingly to how it has been created, so if the marker was created using operation,\n\t * it will be destroyed using operation.\n\t *\n\t * @param {module:engine/model/markercollection~Marker|String} markerOrName Marker or marker name to remove.\n\t */\n\tremoveMarker( markerOrName ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tconst name = typeof markerOrName == 'string' ? markerOrName : markerOrName.name;\n\n\t\tif ( !this.model.markers.has( name ) ) {\n\t\t\t/**\n\t\t\t * Trying to remove marker which does not exist.\n\t\t\t *\n\t\t\t * @error writer-removeMarker-no-marker\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'writer-removeMarker-no-marker: Trying to remove marker which does not exist.', this );\n\t\t}\n\n\t\tconst marker = this.model.markers.get( name );\n\n\t\tif ( !marker.managedUsingOperations ) {\n\t\t\tthis.model.markers._remove( name );\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst oldRange = marker.getRange();\n\n\t\tapplyMarkerOperation( this, name, oldRange, null, marker.affectsData );\n\t}\n\n\t/**\n\t * Sets the document's selection (ranges and direction) to the specified location based on the given\n\t * {@link module:engine/model/selection~Selectable selectable} or creates an empty selection if no arguments were passed.\n\t *\n\t *\t\t// Sets selection to the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\twriter.setSelection( range );\n\t *\n\t *\t\t// Sets selection to given ranges.\n\t *\t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];\n\t *\t\twriter.setSelection( range );\n\t *\n\t *\t\t// Sets selection to other selection.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\twriter.setSelection( otherSelection );\n\t *\n\t *\t\t// Sets selection to the given document selection.\n\t *\t\tconst documentSelection = model.document.selection;\n\t *\t\twriter.setSelection( documentSelection );\n\t *\n\t *\t\t// Sets collapsed selection at the given position.\n\t *\t\tconst position = writer.createPosition( root, path );\n\t *\t\twriter.setSelection( position );\n\t *\n\t *\t\t// Sets collapsed selection at the position of the given node and an offset.\n\t *\t\twriter.setSelection( paragraph, offset );\n\t *\n\t * Creates a range inside an {@link module:engine/model/element~Element element} which starts before the first child of\n \t * that element and ends after the last child of that element.\n\t *\n\t *\t\twriter.setSelection( paragraph, 'in' );\n\t *\n\t * Creates a range on an {@link module:engine/model/item~Item item} which starts before the item and ends just after the item.\n\t *\n\t *\t\twriter.setSelection( paragraph, 'on' );\n\t *\n\t *\t\t// Removes all selection's ranges.\n\t *\t\twriter.setSelection( null );\n\t *\n\t * `Writer#setSelection()` allow passing additional options (`backward`) as the last argument.\n\t *\n\t *\t\t// Sets selection as backward.\n\t *\t\twriter.setSelection( range, { backward: true } );\n\t *\n\t * Throws `writer-incorrect-use` error when the writer is used outside the `change()` block.\n\t *\n\t * @param {module:engine/model/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t */\n\tsetSelection( selectable, placeOrOffset, options ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tthis.model.document.selection._setTo( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Moves {@link module:engine/model/documentselection~DocumentSelection#focus} to the specified location.\n\t *\n\t * The location can be specified in the same form as\n\t * {@link #createPositionAt `writer.createPositionAt()`} parameters.\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset=0] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\tsetSelectionFocus( itemOrPosition, offset ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tthis.model.document.selection._setFocus( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Sets attribute(s) on the selection. If attribute with the same key already is set, it's value is overwritten.\n\t *\n\t * Using key and value pair:\n\t *\n\t * \twriter.setSelectionAttribute( 'italic', true );\n\t *\n\t * Using key-value object:\n\t *\n\t * \twriter.setSelectionAttribute( { italic: true, bold: false } );\n\t *\n\t * Using iterable object:\n\t *\n\t * \twriter.setSelectionAttribute( new Map( [ [ 'italic', true ] ] ) );\n\t *\n\t * @param {String|Object|Iterable.<*>} keyOrObjectOrIterable Key of the attribute to set\n\t * or object / iterable of key => value attribute pairs.\n\t * @param {*} [value] Attribute value.\n\t */\n\tsetSelectionAttribute( keyOrObjectOrIterable, value ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( typeof keyOrObjectOrIterable === 'string' ) {\n\t\t\tthis._setSelectionAttribute( keyOrObjectOrIterable, value );\n\t\t} else {\n\t\t\tfor ( const [ key, value ] of toMap( keyOrObjectOrIterable ) ) {\n\t\t\t\tthis._setSelectionAttribute( key, value );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Removes attribute(s) with given key(s) from the selection.\n\t *\n\t * Remove one attribute:\n\t *\n\t *\t\twriter.removeSelectionAttribute( 'italic' );\n\t *\n\t * Remove multiple attributes:\n\t *\n\t *\t\twriter.removeSelectionAttribute( [ 'italic', 'bold' ] );\n\t *\n\t * @param {String|Iterable.<String>} keyOrIterableOfKeys Key of the attribute to remove or an iterable of attribute keys to remove.\n\t */\n\tremoveSelectionAttribute( keyOrIterableOfKeys ) {\n\t\tthis._assertWriterUsedCorrectly();\n\n\t\tif ( typeof keyOrIterableOfKeys === 'string' ) {\n\t\t\tthis._removeSelectionAttribute( keyOrIterableOfKeys );\n\t\t} else {\n\t\t\tfor ( const key of keyOrIterableOfKeys ) {\n\t\t\t\tthis._removeSelectionAttribute( key );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Temporarily changes the {@link module:engine/model/documentselection~DocumentSelection#isGravityOverridden gravity}\n\t * of the selection from left to right.\n\t *\n\t * The gravity defines from which direction the selection inherits its attributes. If it's the default left gravity,\n\t * then the selection (after being moved by the user) inherits attributes from its left-hand side.\n\t * This method allows to temporarily override this behavior by forcing the gravity to the right.\n\t *\n\t * For the following model fragment:\n\t *\n\t *\t\t<$text bold=\"true\" linkHref=\"url\">bar[]</$text><$text bold=\"true\">biz</$text>\n\t *\n\t * * Default gravity: selection will have the `bold` and `linkHref` attributes.\n\t * * Overridden gravity: selection will have `bold` attribute.\n\t *\n\t * **Note**: It returns an unique identifier which is required to restore the gravity. It guarantees the symmetry\n\t * of the process.\n\t *\n\t * @returns {String} The unique id which allows restoring the gravity.\n\t */\n\toverrideSelectionGravity() {\n\t\treturn this.model.document.selection._overrideGravity();\n\t}\n\n\t/**\n\t * Restores {@link ~Writer#overrideSelectionGravity} gravity to default.\n\t *\n\t * Restoring the gravity is only possible using the unique identifier returned by\n\t * {@link ~Writer#overrideSelectionGravity}. Note that the gravity remains overridden as long as won't be restored\n\t * the same number of times it was overridden.\n\t *\n\t * @param {String} uid The unique id returned by {@link ~Writer#overrideSelectionGravity}.\n\t */\n\trestoreSelectionGravity( uid ) {\n\t\tthis.model.document.selection._restoreGravity( uid );\n\t}\n\n\t/**\n\t * @private\n\t * @param {String} key Key of the attribute to remove.\n\t * @param {*} value Attribute value.\n\t */\n\t_setSelectionAttribute( key, value ) {\n\t\tconst selection = this.model.document.selection;\n\n\t\t// Store attribute in parent element if the selection is collapsed in an empty node.\n\t\tif ( selection.isCollapsed && selection.anchor.parent.isEmpty ) {\n\t\t\tconst storeKey = DocumentSelection._getStoreAttributeKey( key );\n\n\t\t\tthis.setAttribute( storeKey, value, selection.anchor.parent );\n\t\t}\n\n\t\tselection._setAttribute( key, value );\n\t}\n\n\t/**\n\t * @private\n\t * @param {String} key Key of the attribute to remove.\n\t */\n\t_removeSelectionAttribute( key ) {\n\t\tconst selection = this.model.document.selection;\n\n\t\t// Remove stored attribute from parent element if the selection is collapsed in an empty node.\n\t\tif ( selection.isCollapsed && selection.anchor.parent.isEmpty ) {\n\t\t\tconst storeKey = DocumentSelection._getStoreAttributeKey( key );\n\n\t\t\tthis.removeAttribute( storeKey, selection.anchor.parent );\n\t\t}\n\n\t\tselection._removeAttribute( key );\n\t}\n\n\t/**\n\t * Throws `writer-detached-writer-tries-to-modify-model` error when the writer is used outside of the `change()` block.\n\t *\n\t * @private\n\t */\n\t_assertWriterUsedCorrectly() {\n\t\t/**\n\t\t * Trying to use a writer outside a {@link module:engine/model/model~Model#change `change()`} or\n\t\t * {@link module:engine/model/model~Model#enqueueChange `enqueueChange()`} blocks.\n\t\t *\n\t\t * The writer can only be used inside these blocks which ensures that the model\n\t\t * can only be changed during such \"sessions\".\n\t\t *\n\t\t * @error writer-incorrect-use\n\t\t */\n\t\tif ( this.model._currentWriter !== this ) {\n\t\t\tthrow new CKEditorError( 'writer-incorrect-use: Trying to use a writer outside the change() block.', this );\n\t\t}\n\t}\n\n\t/**\n\t * For given action `type` and `positionOrRange` where the action happens, this function finds all affected markers\n\t * and applies a marker operation with the new marker range equal to the current range. Thanks to this, the marker range\n\t * can be later correctly processed during undo.\n\t *\n\t * @private\n\t * @param {'move'|'merge'} type Writer action type.\n\t * @param {module:engine/model/position~Position|module:engine/model/range~Range} positionOrRange Position or range\n\t * where the writer action happens.\n\t */\n\t_addOperationForAffectedMarkers( type, positionOrRange ) {\n\t\tfor ( const marker of this.model.markers ) {\n\t\t\tif ( !marker.managedUsingOperations ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst markerRange = marker.getRange();\n\t\t\tlet isAffected = false;\n\n\t\t\tif ( type == 'move' ) {\n\t\t\t\tisAffected =\n\t\t\t\t\tpositionOrRange.containsPosition( markerRange.start ) ||\n\t\t\t\t\tpositionOrRange.start.isEqual( markerRange.start ) ||\n\t\t\t\t\tpositionOrRange.containsPosition( markerRange.end ) ||\n\t\t\t\t\tpositionOrRange.end.isEqual( markerRange.end );\n\t\t\t} else {\n\t\t\t\t// if type == 'merge'.\n\t\t\t\tconst elementBefore = positionOrRange.nodeBefore;\n\t\t\t\tconst elementAfter = positionOrRange.nodeAfter;\n\n\t\t\t\t// Start: <p>Foo[</p><p>Bar]</p>\n\t\t\t\t// After merge: <p>Foo[Bar]</p>\n\t\t\t\t// After undoing split: <p>Foo</p><p>[Bar]</p> <-- incorrect, needs remembering for undo.\n\t\t\t\t//\n\t\t\t\tconst affectedInLeftElement = markerRange.start.parent == elementBefore && markerRange.start.isAtEnd;\n\n\t\t\t\t// Start: <p>[Foo</p><p>]Bar</p>\n\t\t\t\t// After merge: <p>[Foo]Bar</p>\n\t\t\t\t// After undoing split: <p>[Foo]</p><p>Bar</p> <-- incorrect, needs remembering for undo.\n\t\t\t\t//\n\t\t\t\tconst affectedInRightElement = markerRange.end.parent == elementAfter && markerRange.end.offset == 0;\n\n\t\t\t\t// Start: <p>[Foo</p>]<p>Bar</p>\n\t\t\t\t// After merge: <p>[Foo]Bar</p>\n\t\t\t\t// After undoing split: <p>[Foo]</p><p>Bar</p> <-- incorrect, needs remembering for undo.\n\t\t\t\t//\n\t\t\t\tconst affectedAfterLeftElement = markerRange.end.nodeAfter == elementAfter;\n\n\t\t\t\t// Start: <p>Foo</p>[<p>Bar]</p>\n\t\t\t\t// After merge: <p>Foo[Bar]</p>\n\t\t\t\t// After undoing split: <p>Foo</p><p>[Bar]</p> <-- incorrect, needs remembering for undo.\n\t\t\t\t//\n\t\t\t\tconst affectedBeforeRightElement = markerRange.start.nodeAfter == elementAfter;\n\n\t\t\t\tisAffected = affectedInLeftElement || affectedInRightElement || affectedAfterLeftElement || affectedBeforeRightElement;\n\t\t\t}\n\n\t\t\tif ( isAffected ) {\n\t\t\t\tthis.updateMarker( marker.name, { range: markerRange } );\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Sets given attribute to each node in given range. When attribute value is null then attribute will be removed.\n//\n// Because attribute operation needs to have the same attribute value on the whole range, this function splits\n// the range into smaller parts.\n//\n// Given `range` must be flat.\n//\n// @private\n// @param {module:engine/model/writer~Writer} writer\n// @param {String} key Attribute key.\n// @param {*} value Attribute new value.\n// @param {module:engine/model/range~Range} range Model range on which the attribute will be set.\nfunction setAttributeOnRange( writer, key, value, range ) {\n\tconst model = writer.model;\n\tconst doc = model.document;\n\n\t// Position of the last split, the beginning of the new range.\n\tlet lastSplitPosition = range.start;\n\n\t// Currently position in the scanning range. Because we need value after the position, it is not a current\n\t// position of the iterator but the previous one (we need to iterate one more time to get the value after).\n\tlet position;\n\n\t// Value before the currently position.\n\tlet valueBefore;\n\n\t// Value after the currently position.\n\tlet valueAfter;\n\n\tfor ( const val of range.getWalker( { shallow: true } ) ) {\n\t\tvalueAfter = val.item.getAttribute( key );\n\n\t\t// At the first run of the iterator the position in undefined. We also do not have a valueBefore, but\n\t\t// because valueAfter may be null, valueBefore may be equal valueAfter ( undefined == null ).\n\t\tif ( position && valueBefore != valueAfter ) {\n\t\t\t// if valueBefore == value there is nothing to change, so we add operation only if these values are different.\n\t\t\tif ( valueBefore != value ) {\n\t\t\t\taddOperation();\n\t\t\t}\n\n\t\t\tlastSplitPosition = position;\n\t\t}\n\n\t\tposition = val.nextPosition;\n\t\tvalueBefore = valueAfter;\n\t}\n\n\t// Because position in the loop is not the iterator position (see let position comment), the last position in\n\t// the while loop will be last but one position in the range. We need to check the last position manually.\n\tif ( position instanceof Position && position != lastSplitPosition && valueBefore != value ) {\n\t\taddOperation();\n\t}\n\n\tfunction addOperation() {\n\t\tconst range = new Range( lastSplitPosition, position );\n\t\tconst version = range.root.document ? doc.version : null;\n\t\tconst operation = new AttributeOperation( range, key, valueBefore, value, version );\n\n\t\twriter.batch.addOperation( operation );\n\t\tmodel.applyOperation( operation );\n\t}\n}\n\n// Sets given attribute to the given node. When attribute value is null then attribute will be removed.\n//\n// @private\n// @param {module:engine/model/writer~Writer} writer\n// @param {String} key Attribute key.\n// @param {*} value Attribute new value.\n// @param {module:engine/model/item~Item} item Model item on which the attribute will be set.\nfunction setAttributeOnItem( writer, key, value, item ) {\n\tconst model = writer.model;\n\tconst doc = model.document;\n\tconst previousValue = item.getAttribute( key );\n\tlet range, operation;\n\n\tif ( previousValue != value ) {\n\t\tconst isRootChanged = item.root === item;\n\n\t\tif ( isRootChanged ) {\n\t\t\t// If we change attributes of root element, we have to use `RootAttributeOperation`.\n\t\t\tconst version = item.document ? doc.version : null;\n\n\t\t\toperation = new RootAttributeOperation( item, key, previousValue, value, version );\n\t\t} else {\n\t\t\trange = new Range( Position._createBefore( item ), writer.createPositionAfter( item ) );\n\n\t\t\tconst version = range.root.document ? doc.version : null;\n\n\t\t\toperation = new AttributeOperation( range, key, previousValue, value, version );\n\t\t}\n\n\t\twriter.batch.addOperation( operation );\n\t\tmodel.applyOperation( operation );\n\t}\n}\n\n// Creates and applies marker operation to {@link module:engine/model/operation/operation~Operation operation}.\n//\n// @private\n// @param {module:engine/model/writer~Writer} writer\n// @param {String} name Marker name.\n// @param {module:engine/model/range~Range} oldRange Marker range before the change.\n// @param {module:engine/model/range~Range} newRange Marker range after the change.\n// @param {Boolean} affectsData\nfunction applyMarkerOperation( writer, name, oldRange, newRange, affectsData ) {\n\tconst model = writer.model;\n\tconst doc = model.document;\n\n\tconst operation = new MarkerOperation( name, oldRange, newRange, model.markers, affectsData, doc.version );\n\n\twriter.batch.addOperation( operation );\n\tmodel.applyOperation( operation );\n}\n\n// Creates `MoveOperation` or `DetachOperation` that removes `howMany` nodes starting from `position`.\n// The operation will be applied on given model instance and added to given operation instance.\n//\n// @private\n// @param {module:engine/model/position~Position} position Position from which nodes are removed.\n// @param {Number} howMany Number of nodes to remove.\n// @param {Batch} batch Batch to which the operation will be added.\n// @param {module:engine/model/model~Model} model Model instance on which operation will be applied.\nfunction applyRemoveOperation( position, howMany, batch, model ) {\n\tlet operation;\n\n\tif ( position.root.document ) {\n\t\tconst doc = model.document;\n\t\tconst graveyardPosition = new Position( doc.graveyard, [ 0 ] );\n\n\t\toperation = new MoveOperation( position, howMany, graveyardPosition, doc.version );\n\t} else {\n\t\toperation = new DetachOperation( position, howMany );\n\t}\n\n\tbatch.addOperation( operation );\n\tmodel.applyOperation( operation );\n}\n\n// Returns `true` if both root elements are the same element or both are documents root elements.\n//\n// Elements in the same tree can be moved (for instance you can move element form one documents root to another, or\n// within the same document fragment), but when element supposed to be moved from document fragment to the document, or\n// to another document it should be removed and inserted to avoid problems with OT. This is because features like undo or\n// collaboration may track changes on the document but ignore changes on detached fragments and should not get\n// unexpected `move` operation.\nfunction isSameTree( rootA, rootB ) {\n\t// If it is the same root this is the same tree.\n\tif ( rootA === rootB ) {\n\t\treturn true;\n\t}\n\n\t// If both roots are documents root it is operation within the document what we still treat as the same tree.\n\tif ( rootA instanceof RootElement && rootB instanceof RootElement ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/differ\n */\n\nimport Position from './position';\nimport Range from './range';\n\n/**\n * Calculates the difference between two model states.\n *\n * Receives operations that are to be applied on the model document. Marks parts of the model document tree which\n * are changed and saves the state of these elements before the change. Then, it compares saved elements with the\n * changed elements, after all changes are applied on the model document. Calculates the diff between saved\n * elements and new ones and returns a change set.\n */\nexport default class Differ {\n\t/**\n\t * Creates a `Differ` instance.\n\t *\n\t * @param {module:engine/model/markercollection~MarkerCollection} markerCollection Model's marker collection.\n\t */\n\tconstructor( markerCollection ) {\n\t\t/**\n\t\t * Reference to the model's marker collection.\n\t\t *\n\t\t * @private\n\t\t * @type {module:engine/model/markercollection~MarkerCollection}\n\t\t */\n\t\tthis._markerCollection = markerCollection;\n\n\t\t/**\n\t\t * A map that stores changes that happened in a given element.\n\t\t *\n\t\t * The keys of the map are references to the model elements.\n\t\t * The values of the map are arrays with changes that were done on this element.\n\t\t *\n\t\t * @private\n\t\t * @type {Map}\n\t\t */\n\t\tthis._changesInElement = new Map();\n\n\t\t/**\n\t\t * A map that stores \"element's children snapshots\". A snapshot is representing children of a given element before\n\t\t * the first change was applied on that element. Snapshot items are objects with two properties: `name`,\n\t\t * containing the element name (or `'$text'` for a text node) and `attributes` which is a map of the node's attributes.\n\t\t *\n\t\t * @private\n\t\t * @type {Map}\n\t\t */\n\t\tthis._elementSnapshots = new Map();\n\n\t\t/**\n\t\t * A map that stores all changed markers.\n\t\t *\n\t\t * The keys of the map are marker names.\n\t\t * The values of the map are objects with the `oldRange` and `newRange` properties. They store the marker range\n\t\t * state before and after the change.\n\t\t *\n\t\t * @private\n\t\t * @type {Map}\n\t\t */\n\t\tthis._changedMarkers = new Map();\n\n\t\t/**\n\t\t * Stores the number of changes that were processed. Used to order the changes chronologically. It is important\n\t\t * when changes are sorted.\n\t\t *\n\t\t * @private\n\t\t * @type {Number}\n\t\t */\n\t\tthis._changeCount = 0;\n\n\t\t/**\n\t\t * For efficiency purposes, `Differ` stores the change set returned by the differ after {@link #getChanges} call.\n\t\t * Cache is reset each time a new operation is buffered. If the cache has not been reset, {@link #getChanges} will\n\t\t * return the cached value instead of calculating it again.\n\t\t *\n\t\t * This property stores those changes that did not take place in graveyard root.\n\t\t *\n\t\t * @private\n\t\t * @type {Array.<Object>|null}\n\t\t */\n\t\tthis._cachedChanges = null;\n\n\t\t/**\n\t\t * For efficiency purposes, `Differ` stores the change set returned by the differ after the {@link #getChanges} call.\n\t\t * The cache is reset each time a new operation is buffered. If the cache has not been reset, {@link #getChanges} will\n\t\t * return the cached value instead of calculating it again.\n\t\t *\n\t\t * This property stores all changes evaluated by `Differ`, including those that took place in the graveyard.\n\t\t *\n\t\t * @private\n\t\t * @type {Array.<Object>|null}\n\t\t */\n\t\tthis._cachedChangesWithGraveyard = null;\n\t}\n\n\t/**\n\t * Informs whether there are any changes buffered in `Differ`.\n\t *\n\t * @readonly\n\t * @type {Boolean}\n\t */\n\tget isEmpty() {\n\t\treturn this._changesInElement.size == 0 && this._changedMarkers.size == 0;\n\t}\n\n\t/**\n\t * Marks given `item` in differ to be \"refreshed\". It means that the item will be marked as removed and inserted in the differ changes\n\t * set, so it will be effectively re-converted when differ changes will be handled by a dispatcher.\n\t *\n\t * @param {module:engine/model/item~Item} item Item to refresh.\n\t */\n\trefreshItem( item ) {\n\t\tif ( this._isInInsertedElement( item.parent ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._markRemove( item.parent, item.startOffset, item.offsetSize );\n\t\tthis._markInsert( item.parent, item.startOffset, item.offsetSize );\n\n\t\tconst range = Range._createOn( item );\n\n\t\tfor ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {\n\t\t\tconst markerRange = marker.getRange();\n\n\t\t\tthis.bufferMarkerChange( marker.name, markerRange, markerRange, marker.affectsData );\n\t\t}\n\n\t\t// Clear cache after each buffered operation as it is no longer valid.\n\t\tthis._cachedChanges = null;\n\t}\n\n\t/**\n\t * Buffers the given operation. An operation has to be buffered before it is executed.\n\t *\n\t * Operation type is checked and it is checked which nodes it will affect. These nodes are then stored in `Differ`\n\t * in the state before the operation is executed.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation An operation to buffer.\n\t */\n\tbufferOperation( operation ) {\n\t\t// Below we take an operation, check its type, then use its parameters in marking (private) methods.\n\t\t// The general rule is to not mark elements inside inserted element. All inserted elements are re-rendered.\n\t\t// Marking changes in them would cause a \"double\" changing then.\n\t\t//\n\t\tswitch ( operation.type ) {\n\t\t\tcase 'insert': {\n\t\t\t\tif ( this._isInInsertedElement( operation.position.parent ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._markInsert( operation.position.parent, operation.position.offset, operation.nodes.maxOffset );\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'addAttribute':\n\t\t\tcase 'removeAttribute':\n\t\t\tcase 'changeAttribute': {\n\t\t\t\tfor ( const item of operation.range.getItems( { shallow: true } ) ) {\n\t\t\t\t\tif ( this._isInInsertedElement( item.parent ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._markAttribute( item );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'remove':\n\t\t\tcase 'move':\n\t\t\tcase 'reinsert': {\n\t\t\t\t// When range is moved to the same position then not mark it as a change.\n\t\t\t\t// See: https://github.com/ckeditor/ckeditor5-engine/issues/1664.\n\t\t\t\tif (\n\t\t\t\t\toperation.sourcePosition.isEqual( operation.targetPosition ) ||\n\t\t\t\t\toperation.sourcePosition.getShiftedBy( operation.howMany ).isEqual( operation.targetPosition )\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst sourceParentInserted = this._isInInsertedElement( operation.sourcePosition.parent );\n\t\t\t\tconst targetParentInserted = this._isInInsertedElement( operation.targetPosition.parent );\n\n\t\t\t\tif ( !sourceParentInserted ) {\n\t\t\t\t\tthis._markRemove( operation.sourcePosition.parent, operation.sourcePosition.offset, operation.howMany );\n\t\t\t\t}\n\n\t\t\t\tif ( !targetParentInserted ) {\n\t\t\t\t\tthis._markInsert( operation.targetPosition.parent, operation.getMovedRangeStart().offset, operation.howMany );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'rename': {\n\t\t\t\tif ( this._isInInsertedElement( operation.position.parent ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._markRemove( operation.position.parent, operation.position.offset, 1 );\n\t\t\t\tthis._markInsert( operation.position.parent, operation.position.offset, 1 );\n\n\t\t\t\tconst range = Range._createFromPositionAndShift( operation.position, 1 );\n\n\t\t\t\tfor ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {\n\t\t\t\t\tconst markerRange = marker.getRange();\n\n\t\t\t\t\tthis.bufferMarkerChange( marker.name, markerRange, markerRange, marker.affectsData );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'split': {\n\t\t\t\tconst splitElement = operation.splitPosition.parent;\n\n\t\t\t\t// Mark that children of the split element were removed.\n\t\t\t\tif ( !this._isInInsertedElement( splitElement ) ) {\n\t\t\t\t\tthis._markRemove( splitElement, operation.splitPosition.offset, operation.howMany );\n\t\t\t\t}\n\n\t\t\t\t// Mark that the new element (split copy) was inserted.\n\t\t\t\tif ( !this._isInInsertedElement( operation.insertionPosition.parent ) ) {\n\t\t\t\t\tthis._markInsert( operation.insertionPosition.parent, operation.insertionPosition.offset, 1 );\n\t\t\t\t}\n\n\t\t\t\t// If the split took the element from the graveyard, mark that the element from the graveyard was removed.\n\t\t\t\tif ( operation.graveyardPosition ) {\n\t\t\t\t\tthis._markRemove( operation.graveyardPosition.parent, operation.graveyardPosition.offset, 1 );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'merge': {\n\t\t\t\t// Mark that the merged element was removed.\n\t\t\t\tconst mergedElement = operation.sourcePosition.parent;\n\n\t\t\t\tif ( !this._isInInsertedElement( mergedElement.parent ) ) {\n\t\t\t\t\tthis._markRemove( mergedElement.parent, mergedElement.startOffset, 1 );\n\t\t\t\t}\n\n\t\t\t\t// Mark that the merged element was inserted into graveyard.\n\t\t\t\tconst graveyardParent = operation.graveyardPosition.parent;\n\n\t\t\t\tthis._markInsert( graveyardParent, operation.graveyardPosition.offset, 1 );\n\n\t\t\t\t// Mark that children of merged element were inserted at new parent.\n\t\t\t\tconst mergedIntoElement = operation.targetPosition.parent;\n\n\t\t\t\tif ( !this._isInInsertedElement( mergedIntoElement ) ) {\n\t\t\t\t\tthis._markInsert( mergedIntoElement, operation.targetPosition.offset, mergedElement.maxOffset );\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Clear cache after each buffered operation as it is no longer valid.\n\t\tthis._cachedChanges = null;\n\t}\n\n\t/**\n\t * Buffers a marker change.\n\t *\n\t * @param {String} markerName The name of the marker that changed.\n\t * @param {module:engine/model/range~Range|null} oldRange Marker range before the change or `null` if the marker has just\n\t * been created.\n\t * @param {module:engine/model/range~Range|null} newRange Marker range after the change or `null` if the marker was removed.\n\t * @param {Boolean} affectsData Flag indicating whether marker affects the editor data.\n\t */\n\tbufferMarkerChange( markerName, oldRange, newRange, affectsData ) {\n\t\tconst buffered = this._changedMarkers.get( markerName );\n\n\t\tif ( !buffered ) {\n\t\t\tthis._changedMarkers.set( markerName, {\n\t\t\t\toldRange,\n\t\t\t\tnewRange,\n\t\t\t\taffectsData\n\t\t\t} );\n\t\t} else {\n\t\t\tbuffered.newRange = newRange;\n\t\t\tbuffered.affectsData = affectsData;\n\n\t\t\tif ( buffered.oldRange == null && buffered.newRange == null ) {\n\t\t\t\t// The marker is going to be removed (`newRange == null`) but it did not exist before the first buffered change\n\t\t\t\t// (`buffered.oldRange == null`). In this case, do not keep the marker in buffer at all.\n\t\t\t\tthis._changedMarkers.delete( markerName );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns all markers that should be removed as a result of buffered changes.\n\t *\n\t * @returns {Array.<Object>} Markers to remove. Each array item is an object containing the `name` and `range` properties.\n\t */\n\tgetMarkersToRemove() {\n\t\tconst result = [];\n\n\t\tfor ( const [ name, change ] of this._changedMarkers ) {\n\t\t\tif ( change.oldRange != null ) {\n\t\t\t\tresult.push( { name, range: change.oldRange } );\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Returns all markers which should be added as a result of buffered changes.\n\t *\n\t * @returns {Array.<Object>} Markers to add. Each array item is an object containing the `name` and `range` properties.\n\t */\n\tgetMarkersToAdd() {\n\t\tconst result = [];\n\n\t\tfor ( const [ name, change ] of this._changedMarkers ) {\n\t\t\tif ( change.newRange != null ) {\n\t\t\t\tresult.push( { name, range: change.newRange } );\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Returns all markers which changed.\n\t *\n\t * @returns {Array.<Object>}\n\t */\n\tgetChangedMarkers() {\n\t\treturn Array.from( this._changedMarkers ).map( item => (\n\t\t\t{\n\t\t\t\tname: item[ 0 ],\n\t\t\t\tdata: {\n\t\t\t\t\toldRange: item[ 1 ].oldRange,\n\t\t\t\t\tnewRange: item[ 1 ].newRange\n\t\t\t\t}\n\t\t\t}\n\t\t) );\n\t}\n\n\t/**\n\t * Checks whether some of the buffered changes affect the editor data.\n\t *\n\t * Types of changes which affect the editor data:\n\t *\n\t * * model structure changes,\n\t * * attribute changes,\n\t * * changes of markers which were defined as `affectingData`.\n\t *\n\t * @returns {Boolean}\n\t */\n\thasDataChanges() {\n\t\tfor ( const [ , change ] of this._changedMarkers ) {\n\t\t\tif ( change.affectsData ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// If markers do not affect the data, check whether there are some changes in elements.\n\t\treturn this._changesInElement.size > 0;\n\t}\n\n\t/**\n\t * Calculates the diff between the old model tree state (the state before the first buffered operations since the last {@link #reset}\n\t * call) and the new model tree state (actual one). It should be called after all buffered operations are executed.\n\t *\n\t * The diff set is returned as an array of diff items, each describing a change done on the model. The items are sorted by\n\t * the position on which the change happened. If a position {@link module:engine/model/position~Position#isBefore is before}\n\t * another one, it will be on an earlier index in the diff set.\n\t *\n\t * Because calculating the diff is a costly operation, the result is cached. If no new operation was buffered since the\n\t * previous {@link #getChanges} call, the next call will return the cached value.\n\t *\n\t * @param {Object} options Additional options.\n\t * @param {Boolean} [options.includeChangesInGraveyard=false] If set to `true`, also changes that happened\n\t * in the graveyard root will be returned. By default, changes in the graveyard root are not returned.\n\t * @returns {Array.<Object>} Diff between the old and the new model tree state.\n\t */\n\tgetChanges( options = { includeChangesInGraveyard: false } ) {\n\t\t// If there are cached changes, just return them instead of calculating changes again.\n\t\tif ( this._cachedChanges ) {\n\t\t\tif ( options.includeChangesInGraveyard ) {\n\t\t\t\treturn this._cachedChangesWithGraveyard.slice();\n\t\t\t} else {\n\t\t\t\treturn this._cachedChanges.slice();\n\t\t\t}\n\t\t}\n\n\t\t// Will contain returned results.\n\t\tconst diffSet = [];\n\n\t\t// Check all changed elements.\n\t\tfor ( const element of this._changesInElement.keys() ) {\n\t\t\t// Get changes for this element and sort them.\n\t\t\tconst changes = this._changesInElement.get( element ).sort( ( a, b ) => {\n\t\t\t\tif ( a.offset === b.offset ) {\n\t\t\t\t\tif ( a.type != b.type ) {\n\t\t\t\t\t\t// If there are multiple changes at the same position, \"remove\" change should be first.\n\t\t\t\t\t\t// If the order is different, for example, we would first add some nodes and then removed them\n\t\t\t\t\t\t// (instead of the nodes that we should remove).\n\t\t\t\t\t\treturn a.type == 'remove' ? -1 : 1;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn a.offset < b.offset ? -1 : 1;\n\t\t\t} );\n\n\t\t\t// Get children of this element before any change was applied on it.\n\t\t\tconst snapshotChildren = this._elementSnapshots.get( element );\n\t\t\t// Get snapshot of current element's children.\n\t\t\tconst elementChildren = _getChildrenSnapshot( element.getChildren() );\n\n\t\t\t// Generate actions basing on changes done on element.\n\t\t\tconst actions = _generateActionsFromChanges( snapshotChildren.length, changes );\n\n\t\t\tlet i = 0; // Iterator in `elementChildren` array -- iterates through current children of element.\n\t\t\tlet j = 0; // Iterator in `snapshotChildren` array -- iterates through old children of element.\n\n\t\t\t// Process every action.\n\t\t\tfor ( const action of actions ) {\n\t\t\t\tif ( action === 'i' ) {\n\t\t\t\t\t// Generate diff item for this element and insert it into the diff set.\n\t\t\t\t\tdiffSet.push( this._getInsertDiff( element, i, elementChildren[ i ].name ) );\n\n\t\t\t\t\ti++;\n\t\t\t\t} else if ( action === 'r' ) {\n\t\t\t\t\t// Generate diff item for this element and insert it into the diff set.\n\t\t\t\t\tdiffSet.push( this._getRemoveDiff( element, i, snapshotChildren[ j ].name ) );\n\n\t\t\t\t\tj++;\n\t\t\t\t} else if ( action === 'a' ) {\n\t\t\t\t\t// Take attributes from saved and current children.\n\t\t\t\t\tconst elementAttributes = elementChildren[ i ].attributes;\n\t\t\t\t\tconst snapshotAttributes = snapshotChildren[ j ].attributes;\n\t\t\t\t\tlet range;\n\n\t\t\t\t\tif ( elementChildren[ i ].name == '$text' ) {\n\t\t\t\t\t\trange = new Range( Position._createAt( element, i ), Position._createAt( element, i + 1 ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst index = element.offsetToIndex( i );\n\t\t\t\t\t\trange = new Range( Position._createAt( element, i ), Position._createAt( element.getChild( index ), 0 ) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Generate diff items for this change (there might be multiple attributes changed and\n\t\t\t\t\t// there is a single diff for each of them) and insert them into the diff set.\n\t\t\t\t\tdiffSet.push( ...this._getAttributesDiff( range, snapshotAttributes, elementAttributes ) );\n\n\t\t\t\t\ti++;\n\t\t\t\t\tj++;\n\t\t\t\t} else {\n\t\t\t\t\t// `action` is 'equal'. Child not changed.\n\t\t\t\t\ti++;\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Then, sort the changes by the position (change at position before other changes is first).\n\t\tdiffSet.sort( ( a, b ) => {\n\t\t\t// If the change is in different root, we don't care much, but we'd like to have all changes in given\n\t\t\t// root \"together\" in the array. So let's just sort them by the root name. It does not matter which root\n\t\t\t// will be processed first.\n\t\t\tif ( a.position.root != b.position.root ) {\n\t\t\t\treturn a.position.root.rootName < b.position.root.rootName ? -1 : 1;\n\t\t\t}\n\n\t\t\t// If change happens at the same position...\n\t\t\tif ( a.position.isEqual( b.position ) ) {\n\t\t\t\t// Keep chronological order of operations.\n\t\t\t\treturn a.changeCount - b.changeCount;\n\t\t\t}\n\n\t\t\t// If positions differ, position \"on the left\" should be earlier in the result.\n\t\t\treturn a.position.isBefore( b.position ) ? -1 : 1;\n\t\t} );\n\n\t\t// Glue together multiple changes (mostly on text nodes).\n\t\tfor ( let i = 1; i < diffSet.length; i++ ) {\n\t\t\tconst prevDiff = diffSet[ i - 1 ];\n\t\t\tconst thisDiff = diffSet[ i ];\n\n\t\t\t// Glue remove changes if they happen on text on same position.\n\t\t\tconst isConsecutiveTextRemove =\n\t\t\t\tprevDiff.type == 'remove' && thisDiff.type == 'remove' &&\n\t\t\t\tprevDiff.name == '$text' && thisDiff.name == '$text' &&\n\t\t\t\tprevDiff.position.isEqual( thisDiff.position );\n\n\t\t\t// Glue insert changes if they happen on text on consecutive fragments.\n\t\t\tconst isConsecutiveTextAdd =\n\t\t\t\tprevDiff.type == 'insert' && thisDiff.type == 'insert' &&\n\t\t\t\tprevDiff.name == '$text' && thisDiff.name == '$text' &&\n\t\t\t\tprevDiff.position.parent == thisDiff.position.parent &&\n\t\t\t\tprevDiff.position.offset + prevDiff.length == thisDiff.position.offset;\n\n\t\t\t// Glue attribute changes if they happen on consecutive fragments and have same key, old value and new value.\n\t\t\tconst isConsecutiveAttributeChange =\n\t\t\t\tprevDiff.type == 'attribute' && thisDiff.type == 'attribute' &&\n\t\t\t\tprevDiff.position.parent == thisDiff.position.parent &&\n\t\t\t\tprevDiff.range.isFlat && thisDiff.range.isFlat &&\n\t\t\t\tprevDiff.position.offset + prevDiff.length == thisDiff.position.offset &&\n\t\t\t\tprevDiff.attributeKey == thisDiff.attributeKey &&\n\t\t\t\tprevDiff.attributeOldValue == thisDiff.attributeOldValue &&\n\t\t\t\tprevDiff.attributeNewValue == thisDiff.attributeNewValue;\n\n\t\t\tif ( isConsecutiveTextRemove || isConsecutiveTextAdd || isConsecutiveAttributeChange ) {\n\t\t\t\tdiffSet[ i - 1 ].length++;\n\n\t\t\t\tif ( isConsecutiveAttributeChange ) {\n\t\t\t\t\tdiffSet[ i - 1 ].range.end = diffSet[ i - 1 ].range.end.getShiftedBy( 1 );\n\t\t\t\t}\n\n\t\t\t\tdiffSet.splice( i, 1 );\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\n\t\t// Remove `changeCount` property from diff items. It is used only for sorting and is internal thing.\n\t\tfor ( const item of diffSet ) {\n\t\t\tdelete item.changeCount;\n\n\t\t\tif ( item.type == 'attribute' ) {\n\t\t\t\tdelete item.position;\n\t\t\t\tdelete item.length;\n\t\t\t}\n\t\t}\n\n\t\tthis._changeCount = 0;\n\n\t\t// Cache changes.\n\t\tthis._cachedChangesWithGraveyard = diffSet.slice();\n\t\tthis._cachedChanges = diffSet.slice().filter( _changesInGraveyardFilter );\n\n\t\tif ( options.includeChangesInGraveyard ) {\n\t\t\treturn this._cachedChangesWithGraveyard;\n\t\t} else {\n\t\t\treturn this._cachedChanges;\n\t\t}\n\t}\n\n\t/**\n\t * Resets `Differ`. Removes all buffered changes.\n\t */\n\treset() {\n\t\tthis._changesInElement.clear();\n\t\tthis._elementSnapshots.clear();\n\t\tthis._changedMarkers.clear();\n\t\tthis._cachedChanges = null;\n\t}\n\n\t/**\n\t * Saves and handles an insert change.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} parent\n\t * @param {Number} offset\n\t * @param {Number} howMany\n\t */\n\t_markInsert( parent, offset, howMany ) {\n\t\tconst changeItem = { type: 'insert', offset, howMany, count: this._changeCount++ };\n\n\t\tthis._markChange( parent, changeItem );\n\t}\n\n\t/**\n\t * Saves and handles a remove change.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} parent\n\t * @param {Number} offset\n\t * @param {Number} howMany\n\t */\n\t_markRemove( parent, offset, howMany ) {\n\t\tconst changeItem = { type: 'remove', offset, howMany, count: this._changeCount++ };\n\n\t\tthis._markChange( parent, changeItem );\n\n\t\tthis._removeAllNestedChanges( parent, offset, howMany );\n\t}\n\n\t/**\n\t * Saves and handles an attribute change.\n\t *\n\t * @private\n\t * @param {module:engine/model/item~Item} item\n\t */\n\t_markAttribute( item ) {\n\t\tconst changeItem = { type: 'attribute', offset: item.startOffset, howMany: item.offsetSize, count: this._changeCount++ };\n\n\t\tthis._markChange( item.parent, changeItem );\n\t}\n\n\t/**\n\t * Saves and handles a model change.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} parent\n\t * @param {Object} changeItem\n\t */\n\t_markChange( parent, changeItem ) {\n\t\t// First, make a snapshot of this parent's children (it will be made only if it was not made before).\n\t\tthis._makeSnapshot( parent );\n\n\t\t// Then, get all changes that already were done on the element (empty array if this is the first change).\n\t\tconst changes = this._getChangesForElement( parent );\n\n\t\t// Then, look through all the changes, and transform them or the new change.\n\t\tthis._handleChange( changeItem, changes );\n\n\t\t// Add the new change.\n\t\tchanges.push( changeItem );\n\n\t\t// Remove incorrect changes. During transformation some change might be, for example, included in another.\n\t\t// In that case, the change will have `howMany` property set to `0` or less. We need to remove those changes.\n\t\tfor ( let i = 0; i < changes.length; i++ ) {\n\t\t\tif ( changes[ i ].howMany < 1 ) {\n\t\t\t\tchanges.splice( i, 1 );\n\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Gets an array of changes that have already been saved for a given element.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} element\n\t * @returns {Array.<Object>}\n\t */\n\t_getChangesForElement( element ) {\n\t\tlet changes;\n\n\t\tif ( this._changesInElement.has( element ) ) {\n\t\t\tchanges = this._changesInElement.get( element );\n\t\t} else {\n\t\t\tchanges = [];\n\n\t\t\tthis._changesInElement.set( element, changes );\n\t\t}\n\n\t\treturn changes;\n\t}\n\n\t/**\n\t * Saves a children snapshot for a given element.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} element\n\t */\n\t_makeSnapshot( element ) {\n\t\tif ( !this._elementSnapshots.has( element ) ) {\n\t\t\tthis._elementSnapshots.set( element, _getChildrenSnapshot( element.getChildren() ) );\n\t\t}\n\t}\n\n\t/**\n\t * For a given newly saved change, compares it with a change already done on the element and modifies the incoming\n\t * change and/or the old change.\n\t *\n\t * @private\n\t * @param {Object} inc Incoming (new) change.\n\t * @param {Array.<Object>} changes An array containing all the changes done on that element.\n\t */\n\t_handleChange( inc, changes ) {\n\t\t// We need a helper variable that will store how many nodes are to be still handled for this change item.\n\t\t// `nodesToHandle` (how many nodes still need to be handled) and `howMany` (how many nodes were affected)\n\t\t// needs to be differentiated.\n\t\t//\n\t\t// This comes up when there are multiple changes that are affected by `inc` change item.\n\t\t//\n\t\t// For example: assume two insert changes: `{ offset: 2, howMany: 1 }` and `{ offset: 5, howMany: 1 }`.\n\t\t// Assume that `inc` change is remove `{ offset: 2, howMany: 2, nodesToHandle: 2 }`.\n\t\t//\n\t\t// Then, we:\n\t\t// - \"forget\" about first insert change (it is \"eaten\" by remove),\n\t\t// - because of that, at the end we will want to remove only one node (`nodesToHandle = 1`),\n\t\t// - but still we have to change offset of the second insert change from `5` to `3`!\n\t\t//\n\t\t// So, `howMany` does not change throughout items transformation and keeps information about how many nodes were affected,\n\t\t// while `nodesToHandle` means how many nodes need to be handled after the change item is transformed by other changes.\n\t\tinc.nodesToHandle = inc.howMany;\n\n\t\tfor ( const old of changes ) {\n\t\t\tconst incEnd = inc.offset + inc.howMany;\n\t\t\tconst oldEnd = old.offset + old.howMany;\n\n\t\t\tif ( inc.type == 'insert' ) {\n\t\t\t\tif ( old.type == 'insert' ) {\n\t\t\t\t\tif ( inc.offset <= old.offset ) {\n\t\t\t\t\t\told.offset += inc.howMany;\n\t\t\t\t\t} else if ( inc.offset < oldEnd ) {\n\t\t\t\t\t\told.howMany += inc.nodesToHandle;\n\t\t\t\t\t\tinc.nodesToHandle = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( old.type == 'remove' ) {\n\t\t\t\t\tif ( inc.offset < old.offset ) {\n\t\t\t\t\t\told.offset += inc.howMany;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( old.type == 'attribute' ) {\n\t\t\t\t\tif ( inc.offset <= old.offset ) {\n\t\t\t\t\t\told.offset += inc.howMany;\n\t\t\t\t\t} else if ( inc.offset < oldEnd ) {\n\t\t\t\t\t\t// This case is more complicated, because attribute change has to be split into two.\n\t\t\t\t\t\t// Example (assume that uppercase and lowercase letters mean different attributes):\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// initial state:\t\tabcxyz\n\t\t\t\t\t\t// attribute change:\taBCXYz\n\t\t\t\t\t\t// incoming insert:\t\taBCfooXYz\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Change ranges cannot intersect because each item has to be described exactly (it was either\n\t\t\t\t\t\t// not changed, inserted, removed, or its attribute was changed). That's why old attribute\n\t\t\t\t\t\t// change has to be split and both parts has to be handled separately from now on.\n\t\t\t\t\t\tconst howMany = old.howMany;\n\n\t\t\t\t\t\told.howMany = inc.offset - old.offset;\n\n\t\t\t\t\t\t// Add the second part of attribute change to the beginning of processed array so it won't\n\t\t\t\t\t\t// be processed again in this loop.\n\t\t\t\t\t\tchanges.unshift( {\n\t\t\t\t\t\t\ttype: 'attribute',\n\t\t\t\t\t\t\toffset: incEnd,\n\t\t\t\t\t\t\thowMany: howMany - old.howMany,\n\t\t\t\t\t\t\tcount: this._changeCount++\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( inc.type == 'remove' ) {\n\t\t\t\tif ( old.type == 'insert' ) {\n\t\t\t\t\tif ( incEnd <= old.offset ) {\n\t\t\t\t\t\told.offset -= inc.howMany;\n\t\t\t\t\t} else if ( incEnd <= oldEnd ) {\n\t\t\t\t\t\tif ( inc.offset < old.offset ) {\n\t\t\t\t\t\t\tconst intersectionLength = incEnd - old.offset;\n\n\t\t\t\t\t\t\told.offset = inc.offset;\n\n\t\t\t\t\t\t\told.howMany -= intersectionLength;\n\t\t\t\t\t\t\tinc.nodesToHandle -= intersectionLength;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\told.howMany -= inc.nodesToHandle;\n\t\t\t\t\t\t\tinc.nodesToHandle = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( inc.offset <= old.offset ) {\n\t\t\t\t\t\t\tinc.nodesToHandle -= old.howMany;\n\t\t\t\t\t\t\told.howMany = 0;\n\t\t\t\t\t\t} else if ( inc.offset < oldEnd ) {\n\t\t\t\t\t\t\tconst intersectionLength = oldEnd - inc.offset;\n\n\t\t\t\t\t\t\told.howMany -= intersectionLength;\n\t\t\t\t\t\t\tinc.nodesToHandle -= intersectionLength;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( old.type == 'remove' ) {\n\t\t\t\t\tif ( incEnd <= old.offset ) {\n\t\t\t\t\t\told.offset -= inc.howMany;\n\t\t\t\t\t} else if ( inc.offset < old.offset ) {\n\t\t\t\t\t\tinc.nodesToHandle += old.howMany;\n\t\t\t\t\t\told.howMany = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( old.type == 'attribute' ) {\n\t\t\t\t\tif ( incEnd <= old.offset ) {\n\t\t\t\t\t\told.offset -= inc.howMany;\n\t\t\t\t\t} else if ( inc.offset < old.offset ) {\n\t\t\t\t\t\tconst intersectionLength = incEnd - old.offset;\n\n\t\t\t\t\t\told.offset = inc.offset;\n\t\t\t\t\t\told.howMany -= intersectionLength;\n\t\t\t\t\t} else if ( inc.offset < oldEnd ) {\n\t\t\t\t\t\tif ( incEnd <= oldEnd ) {\n\t\t\t\t\t\t\t// On first sight in this case we don't need to split attribute operation into two.\n\t\t\t\t\t\t\t// However the changes set is later converted to actions (see `_generateActionsFromChanges`).\n\t\t\t\t\t\t\t// For that reason, no two changes may intersect.\n\t\t\t\t\t\t\t// So we cannot have an attribute change that \"contains\" remove change.\n\t\t\t\t\t\t\t// Attribute change needs to be split.\n\t\t\t\t\t\t\tconst howMany = old.howMany;\n\n\t\t\t\t\t\t\told.howMany = inc.offset - old.offset;\n\n\t\t\t\t\t\t\tconst howManyAfter = howMany - old.howMany - inc.nodesToHandle;\n\n\t\t\t\t\t\t\t// Add the second part of attribute change to the beginning of processed array so it won't\n\t\t\t\t\t\t\t// be processed again in this loop.\n\t\t\t\t\t\t\tchanges.unshift( {\n\t\t\t\t\t\t\t\ttype: 'attribute',\n\t\t\t\t\t\t\t\toffset: inc.offset,\n\t\t\t\t\t\t\t\thowMany: howManyAfter,\n\t\t\t\t\t\t\t\tcount: this._changeCount++\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\told.howMany -= oldEnd - inc.offset;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( inc.type == 'attribute' ) {\n\t\t\t\t// In case of attribute change, `howMany` should be kept same as `nodesToHandle`. It's not an error.\n\t\t\t\tif ( old.type == 'insert' ) {\n\t\t\t\t\tif ( inc.offset < old.offset && incEnd > old.offset ) {\n\t\t\t\t\t\tif ( incEnd > oldEnd ) {\n\t\t\t\t\t\t\t// This case is similar to a case described when incoming change was insert and old change was attribute.\n\t\t\t\t\t\t\t// See comment above.\n\t\t\t\t\t\t\t//\n\t\t\t\t\t\t\t// This time incoming change is attribute. We need to split incoming change in this case too.\n\t\t\t\t\t\t\t// However this time, the second part of the attribute change needs to be processed further\n\t\t\t\t\t\t\t// because there might be other changes that it collides with.\n\t\t\t\t\t\t\tconst attributePart = {\n\t\t\t\t\t\t\t\ttype: 'attribute',\n\t\t\t\t\t\t\t\toffset: oldEnd,\n\t\t\t\t\t\t\t\thowMany: incEnd - oldEnd,\n\t\t\t\t\t\t\t\tcount: this._changeCount++\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tthis._handleChange( attributePart, changes );\n\n\t\t\t\t\t\t\tchanges.push( attributePart );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tinc.nodesToHandle = old.offset - inc.offset;\n\t\t\t\t\t\tinc.howMany = inc.nodesToHandle;\n\t\t\t\t\t} else if ( inc.offset >= old.offset && inc.offset < oldEnd ) {\n\t\t\t\t\t\tif ( incEnd > oldEnd ) {\n\t\t\t\t\t\t\tinc.nodesToHandle = incEnd - oldEnd;\n\t\t\t\t\t\t\tinc.offset = oldEnd;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinc.nodesToHandle = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( old.type == 'remove' ) {\n\t\t\t\t\t// This is a case when attribute change \"contains\" remove change.\n\t\t\t\t\t// The attribute change needs to be split into two because changes cannot intersect.\n\t\t\t\t\tif ( inc.offset < old.offset && incEnd > old.offset ) {\n\t\t\t\t\t\tconst attributePart = {\n\t\t\t\t\t\t\ttype: 'attribute',\n\t\t\t\t\t\t\toffset: old.offset,\n\t\t\t\t\t\t\thowMany: incEnd - old.offset,\n\t\t\t\t\t\t\tcount: this._changeCount++\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tthis._handleChange( attributePart, changes );\n\n\t\t\t\t\t\tchanges.push( attributePart );\n\n\t\t\t\t\t\tinc.nodesToHandle = old.offset - inc.offset;\n\t\t\t\t\t\tinc.howMany = inc.nodesToHandle;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( old.type == 'attribute' ) {\n\t\t\t\t\t// There are only two conflicting scenarios possible here:\n\t\t\t\t\tif ( inc.offset >= old.offset && incEnd <= oldEnd ) {\n\t\t\t\t\t\t// `old` change includes `inc` change, or they are the same.\n\t\t\t\t\t\tinc.nodesToHandle = 0;\n\t\t\t\t\t\tinc.howMany = 0;\n\t\t\t\t\t\tinc.offset = 0;\n\t\t\t\t\t} else if ( inc.offset <= old.offset && incEnd >= oldEnd ) {\n\t\t\t\t\t\t// `inc` change includes `old` change.\n\t\t\t\t\t\told.howMany = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tinc.howMany = inc.nodesToHandle;\n\t\tdelete inc.nodesToHandle;\n\t}\n\n\t/**\n\t * Returns an object with a single insert change description.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} parent The element in which the change happened.\n\t * @param {Number} offset The offset at which change happened.\n\t * @param {String} name The name of the removed element or `'$text'` for a character.\n\t * @returns {Object} The diff item.\n\t */\n\t_getInsertDiff( parent, offset, name ) {\n\t\treturn {\n\t\t\ttype: 'insert',\n\t\t\tposition: Position._createAt( parent, offset ),\n\t\t\tname,\n\t\t\tlength: 1,\n\t\t\tchangeCount: this._changeCount++\n\t\t};\n\t}\n\n\t/**\n\t * Returns an object with a single remove change description.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} parent The element in which change happened.\n\t * @param {Number} offset The offset at which change happened.\n\t * @param {String} name The name of the removed element or `'$text'` for a character.\n\t * @returns {Object} The diff item.\n\t */\n\t_getRemoveDiff( parent, offset, name ) {\n\t\treturn {\n\t\t\ttype: 'remove',\n\t\t\tposition: Position._createAt( parent, offset ),\n\t\t\tname,\n\t\t\tlength: 1,\n\t\t\tchangeCount: this._changeCount++\n\t\t};\n\t}\n\n\t/**\n\t * Returns an array of objects where each one is a single attribute change description.\n\t *\n\t * @private\n\t * @param {module:engine/model/range~Range} range The range where the change happened.\n\t * @param {Map} oldAttributes A map, map iterator or compatible object that contains attributes before the change.\n\t * @param {Map} newAttributes A map, map iterator or compatible object that contains attributes after the change.\n\t * @returns {Array.<Object>} An array containing one or more diff items.\n\t */\n\t_getAttributesDiff( range, oldAttributes, newAttributes ) {\n\t\t// Results holder.\n\t\tconst diffs = [];\n\n\t\t// Clone new attributes as we will be performing changes on this object.\n\t\tnewAttributes = new Map( newAttributes );\n\n\t\t// Look through old attributes.\n\t\tfor ( const [ key, oldValue ] of oldAttributes ) {\n\t\t\t// Check what is the new value of the attribute (or if it was removed).\n\t\t\tconst newValue = newAttributes.has( key ) ? newAttributes.get( key ) : null;\n\n\t\t\t// If values are different (or attribute was removed)...\n\t\t\tif ( newValue !== oldValue ) {\n\t\t\t\t// Add diff item.\n\t\t\t\tdiffs.push( {\n\t\t\t\t\ttype: 'attribute',\n\t\t\t\t\tposition: range.start,\n\t\t\t\t\trange: range.clone(),\n\t\t\t\t\tlength: 1,\n\t\t\t\t\tattributeKey: key,\n\t\t\t\t\tattributeOldValue: oldValue,\n\t\t\t\t\tattributeNewValue: newValue,\n\t\t\t\t\tchangeCount: this._changeCount++\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Prevent returning two diff items for the same change.\n\t\t\tnewAttributes.delete( key );\n\t\t}\n\n\t\t// Look through new attributes that weren't handled above.\n\t\tfor ( const [ key, newValue ] of newAttributes ) {\n\t\t\t// Each of them is a new attribute. Add diff item.\n\t\t\tdiffs.push( {\n\t\t\t\ttype: 'attribute',\n\t\t\t\tposition: range.start,\n\t\t\t\trange: range.clone(),\n\t\t\t\tlength: 1,\n\t\t\t\tattributeKey: key,\n\t\t\t\tattributeOldValue: null,\n\t\t\t\tattributeNewValue: newValue,\n\t\t\t\tchangeCount: this._changeCount++\n\t\t\t} );\n\t\t}\n\n\t\treturn diffs;\n\t}\n\n\t/**\n\t * Checks whether given element or any of its parents is an element that is buffered as an inserted element.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} element Element to check.\n\t * @returns {Boolean}\n\t */\n\t_isInInsertedElement( element ) {\n\t\tconst parent = element.parent;\n\n\t\tif ( !parent ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst changes = this._changesInElement.get( parent );\n\t\tconst offset = element.startOffset;\n\n\t\tif ( changes ) {\n\t\t\tfor ( const change of changes ) {\n\t\t\t\tif ( change.type == 'insert' && offset >= change.offset && offset < change.offset + change.howMany ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this._isInInsertedElement( parent );\n\t}\n\n\t/**\n\t * Removes deeply all buffered changes that are registered in elements from range specified by `parent`, `offset`\n\t * and `howMany`.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} parent\n\t * @param {Number} offset\n\t * @param {Number} howMany\n\t */\n\t_removeAllNestedChanges( parent, offset, howMany ) {\n\t\tconst range = new Range( Position._createAt( parent, offset ), Position._createAt( parent, offset + howMany ) );\n\n\t\tfor ( const item of range.getItems( { shallow: true } ) ) {\n\t\t\tif ( item.is( 'element' ) ) {\n\t\t\t\tthis._elementSnapshots.delete( item );\n\t\t\t\tthis._changesInElement.delete( item );\n\n\t\t\t\tthis._removeAllNestedChanges( item, 0, item.maxOffset );\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Returns an array that is a copy of passed child list with the exception that text nodes are split to one or more\n// objects, each representing one character and attributes set on that character.\nfunction _getChildrenSnapshot( children ) {\n\tconst snapshot = [];\n\n\tfor ( const child of children ) {\n\t\tif ( child.is( 'text' ) ) {\n\t\t\tfor ( let i = 0; i < child.data.length; i++ ) {\n\t\t\t\tsnapshot.push( {\n\t\t\t\t\tname: '$text',\n\t\t\t\t\tattributes: new Map( child.getAttributes() )\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\t\t\tsnapshot.push( {\n\t\t\t\tname: child.name,\n\t\t\t\tattributes: new Map( child.getAttributes() )\n\t\t\t} );\n\t\t}\n\t}\n\n\treturn snapshot;\n}\n\n// Generates array of actions for given changes set.\n// It simulates what `diff` function does.\n// Generated actions are:\n// - 'e' for 'equal' - when item at that position did not change,\n// - 'i' for 'insert' - when item at that position was inserted,\n// - 'r' for 'remove' - when item at that position was removed,\n// - 'a' for 'attribute' - when item at that position has it attributes changed.\n//\n// Example (assume that uppercase letters have bold attribute, compare with function code):\n//\n// children before:\tfooBAR\n// children after:\tfoxybAR\n//\n// changes: type: remove, offset: 1, howMany: 1\n//\t\t\ttype: insert, offset: 2, howMany: 2\n//\t\t\ttype: attribute, offset: 4, howMany: 1\n//\n// expected actions: equal (f), remove (o), equal (o), insert (x), insert (y), attribute (b), equal (A), equal (R)\n//\n// steps taken by th script:\n//\n// 1. change = \"type: remove, offset: 1, howMany: 1\"; offset = 0; oldChildrenHandled = 0\n// 1.1 between this change and the beginning is one not-changed node, fill with one equal action, one old child has been handled\n// 1.2 this change removes one node, add one remove action\n// 1.3 change last visited `offset` to 1\n// 1.4 since an old child has been removed, one more old child has been handled\n// 1.5 actions at this point are: equal, remove\n//\n// 2. change = \"type: insert, offset: 2, howMany: 2\"; offset = 1; oldChildrenHandled = 2\n// 2.1 between this change and previous change is one not-changed node, add equal action, another one old children has been handled\n// 2.2 this change inserts two nodes, add two insert actions\n// 2.3 change last visited offset to the end of the inserted range, that is 4\n// 2.4 actions at this point are: equal, remove, equal, insert, insert\n//\n// 3. change = \"type: attribute, offset: 4, howMany: 1\"; offset = 4, oldChildrenHandled = 3\n// 3.1 between this change and previous change are no not-changed nodes\n// 3.2 this change changes one node, add one attribute action\n// 3.3 change last visited `offset` to the end of change range, that is 5\n// 3.4 since an old child has been changed, one more old child has been handled\n// 3.5 actions at this point are: equal, remove, equal, insert, insert, attribute\n//\n// 4. after loop oldChildrenHandled = 4, oldChildrenLength = 6 (fooBAR is 6 characters)\n// 4.1 fill up with two equal actions\n//\n// The result actions are: equal, remove, equal, insert, insert, attribute, equal, equal.\nfunction _generateActionsFromChanges( oldChildrenLength, changes ) {\n\tconst actions = [];\n\n\tlet offset = 0;\n\tlet oldChildrenHandled = 0;\n\n\t// Go through all buffered changes.\n\tfor ( const change of changes ) {\n\t\t// First, fill \"holes\" between changes with \"equal\" actions.\n\t\tif ( change.offset > offset ) {\n\t\t\tfor ( let i = 0; i < change.offset - offset; i++ ) {\n\t\t\t\tactions.push( 'e' );\n\t\t\t}\n\n\t\t\toldChildrenHandled += change.offset - offset;\n\t\t}\n\n\t\t// Then, fill up actions accordingly to change type.\n\t\tif ( change.type == 'insert' ) {\n\t\t\tfor ( let i = 0; i < change.howMany; i++ ) {\n\t\t\t\tactions.push( 'i' );\n\t\t\t}\n\n\t\t\t// The last handled offset is after inserted range.\n\t\t\toffset = change.offset + change.howMany;\n\t\t} else if ( change.type == 'remove' ) {\n\t\t\tfor ( let i = 0; i < change.howMany; i++ ) {\n\t\t\t\tactions.push( 'r' );\n\t\t\t}\n\n\t\t\t// The last handled offset is at the position where the nodes were removed.\n\t\t\toffset = change.offset;\n\t\t\t// We removed `howMany` old nodes, update `oldChildrenHandled`.\n\t\t\toldChildrenHandled += change.howMany;\n\t\t} else {\n\t\t\tactions.push( ...'a'.repeat( change.howMany ).split( '' ) );\n\n\t\t\t// The last handled offset is at the position after the changed range.\n\t\t\toffset = change.offset + change.howMany;\n\t\t\t// We changed `howMany` old nodes, update `oldChildrenHandled`.\n\t\t\toldChildrenHandled += change.howMany;\n\t\t}\n\t}\n\n\t// Fill \"equal\" actions at the end of actions set. Use `oldChildrenHandled` to see how many children\n\t// has not been changed / removed at the end of their parent.\n\tif ( oldChildrenHandled < oldChildrenLength ) {\n\t\tfor ( let i = 0; i < oldChildrenLength - oldChildrenHandled - offset; i++ ) {\n\t\t\tactions.push( 'e' );\n\t\t}\n\t}\n\n\treturn actions;\n}\n\n// Filter callback for Array.filter that filters out change entries that are in graveyard.\nfunction _changesInGraveyardFilter( entry ) {\n\tconst posInGy = entry.position && entry.position.root.rootName == '$graveyard';\n\tconst rangeInGy = entry.range && entry.range.root.rootName == '$graveyard';\n\n\treturn !posInGy && !rangeInGy;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/history\n */\n\n/**\n * `History` keeps the track of all the operations applied to the {@link module:engine/model/document~Document document}.\n */\nexport default class History {\n\t/**\n\t * Creates an empty History instance.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Operations added to the history.\n\t\t *\n\t\t * @protected\n\t\t * @member {Array.<module:engine/model/operation/operation~Operation>} module:engine/model/history~History#_operations\n\t\t */\n\t\tthis._operations = [];\n\n\t\t/**\n\t\t * Holds an information which {@link module:engine/model/operation/operation~Operation operation} undoes which\n\t\t * {@link module:engine/model/operation/operation~Operation operation}.\n\t\t *\n\t\t * Keys of the map are \"undoing operations\", that is operations that undone some other operations. For each key, the\n\t\t * value is an operation that has been undone by the \"undoing operation\".\n\t\t *\n\t\t * @private\n\t\t * @member {Map} module:engine/model/history~History#_undoPairs\n\t\t */\n\t\tthis._undoPairs = new Map();\n\n\t\t/**\n\t\t * Holds all undone operations.\n\t\t *\n\t\t * @private\n\t\t * @member {Set.<module:engine/model/operation/operation~Operation>} module:engine/model/history~History#_undoneOperations\n\t\t */\n\t\tthis._undoneOperations = new Set();\n\t}\n\n\t/**\n\t * Adds an operation to the history.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation Operation to add.\n\t */\n\taddOperation( operation ) {\n\t\tif ( this._operations.includes( operation ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._operations.push( operation );\n\t}\n\n\t/**\n\t * Returns operations added to the history.\n\t *\n\t * @param {Number} [from=0] Base version from which operations should be returned (inclusive). Defaults to `0`, which means\n\t * that operations from the first one will be returned.\n\t * @param {Number} [to=Number.POSITIVE_INFINITY] Base version up to which operations should be returned (exclusive).\n\t * Defaults to `Number.POSITIVE_INFINITY` which means that operations up to the last one will be returned.\n\t * @returns {Iterable.<module:engine/model/operation/operation~Operation>} Operations added to the history.\n\t */\n\tgetOperations( from = 0, to = Number.POSITIVE_INFINITY ) {\n\t\tif ( from < 0 ) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn this._operations.slice( from, to );\n\t}\n\n\t/**\n\t * Returns operation from the history that bases on given `baseVersion`.\n\t *\n\t * @param {Number} baseVersion Base version of the operation to get.\n\t * @returns {module:engine/model/operation/operation~Operation|null} Operation with given base version or `null` if\n\t * there is no such operation in history.\n\t */\n\tgetOperation( baseVersion ) {\n\t\treturn this._operations[ baseVersion ];\n\t}\n\n\t/**\n\t * Marks in history that one operation is an operation that is undoing the other operation. By marking operation this way,\n\t * history is keeping more context information about operations, which helps in operational transformation.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} undoneOperation Operation which is undone by `undoingOperation`.\n\t * @param {module:engine/model/operation/operation~Operation} undoingOperation Operation which undoes `undoneOperation`.\n\t */\n\tsetOperationAsUndone( undoneOperation, undoingOperation ) {\n\t\tthis._undoPairs.set( undoingOperation, undoneOperation );\n\t\tthis._undoneOperations.add( undoneOperation );\n\t}\n\n\t/**\n\t * Checks whether given `operation` is undoing any other operation.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation Operation to check.\n\t * @returns {Boolean} `true` if given `operation` is undoing any other operation, `false` otherwise.\n\t */\n\tisUndoingOperation( operation ) {\n\t\treturn this._undoPairs.has( operation );\n\t}\n\n\t/**\n\t * Checks whether given `operation` has been undone by any other operation.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation Operation to check.\n\t * @returns {Boolean} `true` if given `operation` has been undone any other operation, `false` otherwise.\n\t */\n\tisUndoneOperation( operation ) {\n\t\treturn this._undoneOperations.has( operation );\n\t}\n\n\t/**\n\t * For given `undoingOperation`, returns the operation which has been undone by it.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} undoingOperation\n\t * @returns {module:engine/model/operation/operation~Operation|undefined} Operation that has been undone by given\n\t * `undoingOperation` or `undefined` if given `undoingOperation` is not undoing any other operation.\n\t */\n\tgetUndoneOperation( undoingOperation ) {\n\t\treturn this._undoPairs.get( undoingOperation );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * Set of utils to handle unicode characters.\n *\n * @module utils/unicode\n */\n\n/**\n * Checks whether given `character` is a combining mark.\n *\n * @param {String} character Character to check.\n * @returns {Boolean}\n */\nexport function isCombiningMark( character ) {\n\treturn !!character && character.length == 1 && /[\\u0300-\\u036f\\u1ab0-\\u1aff\\u1dc0-\\u1dff\\u20d0-\\u20ff\\ufe20-\\ufe2f]/.test( character );\n}\n\n/**\n * Checks whether given `character` is a high half of surrogate pair.\n *\n * Using UTF-16 terminology, a surrogate pair denotes UTF-16 character using two UTF-8 characters. The surrogate pair\n * consist of high surrogate pair character followed by low surrogate pair character.\n *\n * @param {String} character Character to check.\n * @returns {Boolean}\n */\nexport function isHighSurrogateHalf( character ) {\n\treturn !!character && character.length == 1 && /[\\ud800-\\udbff]/.test( character );\n}\n\n/**\n * Checks whether given `character` is a low half of surrogate pair.\n *\n * Using UTF-16 terminology, a surrogate pair denotes UTF-16 character using two UTF-8 characters. The surrogate pair\n * consist of high surrogate pair character followed by low surrogate pair character.\n *\n * @param {String} character Character to check.\n * @returns {Boolean}\n */\nexport function isLowSurrogateHalf( character ) {\n\treturn !!character && character.length == 1 && /[\\udc00-\\udfff]/.test( character );\n}\n\n/**\n * Checks whether given offset in a string is inside a surrogate pair (between two surrogate halves).\n *\n * @param {String} string String to check.\n * @param {Number} offset Offset to check.\n * @returns {Boolean}\n */\nexport function isInsideSurrogatePair( string, offset ) {\n\treturn isHighSurrogateHalf( string.charAt( offset - 1 ) ) && isLowSurrogateHalf( string.charAt( offset ) );\n}\n\n/**\n * Checks whether given offset in a string is between base character and combining mark or between two combining marks.\n *\n * @param {String} string String to check.\n * @param {Number} offset Offset to check.\n * @returns {Boolean}\n */\nexport function isInsideCombinedSymbol( string, offset ) {\n\treturn isCombiningMark( string.charAt( offset ) );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/document\n */\n\nimport Differ from './differ';\nimport RootElement from './rootelement';\nimport History from './history';\nimport DocumentSelection from './documentselection';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport { isInsideSurrogatePair, isInsideCombinedSymbol } from '@ckeditor/ckeditor5-utils/src/unicode';\nimport { clone } from 'lodash-es';\n\nconst graveyardName = '$graveyard';\n\n/**\n * Data model's document. It contains the model's structure, its selection and the history of changes.\n *\n * Read more about working with the model in\n * {@glink framework/guides/architecture/editing-engine#model introduction to the the editing engine's architecture}.\n *\n * Usually, the document contains just one {@link module:engine/model/document~Document#roots root element}, so\n * you can retrieve it by just calling {@link module:engine/model/document~Document#getRoot} without specifying its name:\n *\n *\t\tmodel.document.getRoot(); // -> returns the main root\n *\n * However, the document may contain multiple roots – e.g. when the editor has multiple editable areas\n * (e.g. a title and a body of a message).\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class Document {\n\t/**\n\t * Creates an empty document instance with no {@link #roots} (other than\n\t * the {@link #graveyard graveyard root}).\n\t */\n\tconstructor( model ) {\n\t\t/**\n\t\t * The {@link module:engine/model/model~Model model} that the document is a part of.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/model~Model}\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * The document version. It starts from `0` and every operation increases the version number. It is used to ensure that\n\t\t * operations are applied on a proper document version.\n\t\t *\n\t\t * If the {@link module:engine/model/operation/operation~Operation#baseVersion base version} does not match the document version,\n\t\t * a {@link module:utils/ckeditorerror~CKEditorError model-document-applyOperation-wrong-version} error is thrown.\n\t\t *\n\t\t * @readonly\n\t\t * @type {Number}\n\t\t */\n\t\tthis.version = 0;\n\n\t\t/**\n\t\t * The document's history.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/history~History}\n\t\t */\n\t\tthis.history = new History( this );\n\n\t\t/**\n\t\t * The selection in this document.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/documentselection~DocumentSelection}\n\t\t */\n\t\tthis.selection = new DocumentSelection( this );\n\n\t\t/**\n\t\t * A list of roots that are owned and managed by this document. Use {@link #createRoot} and\n\t\t * {@link #getRoot} to manipulate it.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:utils/collection~Collection}\n\t\t */\n\t\tthis.roots = new Collection( { idProperty: 'rootName' } );\n\n\t\t/**\n\t\t * The model differ object. Its role is to buffer changes done on the model document and then calculate a diff of those changes.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:engine/model/differ~Differ}\n\t\t */\n\t\tthis.differ = new Differ( model.markers );\n\n\t\t/**\n\t\t * Post-fixer callbacks registered to the model document.\n\t\t *\n\t\t * @private\n\t\t * @type {Set.<Function>}\n\t\t */\n\t\tthis._postFixers = new Set();\n\n\t\t/**\n\t\t * A boolean indicates whether the selection has changed until\n\t\t *\n\t\t * @private\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis._hasSelectionChangedFromTheLastChangeBlock = false;\n\n\t\t// Graveyard tree root. Document always have a graveyard root, which stores removed nodes.\n\t\tthis.createRoot( '$root', graveyardName );\n\n\t\t// First, if the operation is a document operation check if it's base version is correct.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation && operation.baseVersion !== this.version ) {\n\t\t\t\t/**\n\t\t\t\t * Only operations with matching versions can be applied.\n\t\t\t\t *\n\t\t\t\t * @error document-applyOperation-wrong-version\n\t\t\t\t * @param {module:engine/model/operation/operation~Operation} operation\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'model-document-applyOperation-wrong-version: Only operations with matching versions can be applied.',\n\t\t\t\t\tthis,\n\t\t\t\t\t{ operation }\n\t\t\t\t);\n\t\t\t}\n\t\t}, { priority: 'highest' } );\n\n\t\t// Then, still before an operation is applied on model, buffer the change in differ.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation ) {\n\t\t\t\tthis.differ.bufferOperation( operation );\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\n\t\t// After the operation is applied, bump document's version and add the operation to the history.\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.isDocumentOperation ) {\n\t\t\t\tthis.version++;\n\t\t\t\tthis.history.addOperation( operation );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\n\t\t// Listen to selection changes. If selection changed, mark it.\n\t\tthis.listenTo( this.selection, 'change', () => {\n\t\t\tthis._hasSelectionChangedFromTheLastChangeBlock = true;\n\t\t} );\n\n\t\t// Buffer marker changes.\n\t\t// This is not covered in buffering operations because markers may change outside of them (when they\n\t\t// are modified using `model.markers` collection, not through `MarkerOperation`).\n\t\tthis.listenTo( model.markers, 'update', ( evt, marker, oldRange, newRange ) => {\n\t\t\t// Whenever marker is updated, buffer that change.\n\t\t\tthis.differ.bufferMarkerChange( marker.name, oldRange, newRange, marker.affectsData );\n\n\t\t\tif ( oldRange === null ) {\n\t\t\t\t// If this is a new marker, add a listener that will buffer change whenever marker changes.\n\t\t\t\tmarker.on( 'change', ( evt, oldRange ) => {\n\t\t\t\t\tthis.differ.bufferMarkerChange( marker.name, oldRange, marker.getRange(), marker.affectsData );\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * The graveyard tree root. A document always has a graveyard root that stores removed nodes.\n\t *\n\t * @readonly\n\t * @member {module:engine/model/rootelement~RootElement}\n\t */\n\tget graveyard() {\n\t\treturn this.getRoot( graveyardName );\n\t}\n\n\t/**\n\t * Creates a new root.\n\t *\n\t * @param {String} [elementName='$root'] The element name. Defaults to `'$root'` which also has some basic schema defined\n\t * (`$block`s are allowed inside the `$root`). Make sure to define a proper schema if you use a different name.\n\t * @param {String} [rootName='main'] A unique root name.\n\t * @returns {module:engine/model/rootelement~RootElement} The created root.\n\t */\n\tcreateRoot( elementName = '$root', rootName = 'main' ) {\n\t\tif ( this.roots.get( rootName ) ) {\n\t\t\t/**\n\t\t\t * A root with the specified name already exists.\n\t\t\t *\n\t\t\t * @error model-document-createRoot-name-exists\n\t\t\t * @param {module:engine/model/document~Document} doc\n\t\t\t * @param {String} name\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-document-createRoot-name-exists: Root with specified name already exists.',\n\t\t\t\tthis,\n\t\t\t\t{ name: rootName }\n\t\t\t);\n\t\t}\n\n\t\tconst root = new RootElement( this, elementName, rootName );\n\t\tthis.roots.add( root );\n\n\t\treturn root;\n\t}\n\n\t/**\n\t * Removes all event listeners set by the document instance.\n\t */\n\tdestroy() {\n\t\tthis.selection.destroy();\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Returns a root by its name.\n\t *\n\t * @param {String} [name='main'] A unique root name.\n\t * @returns {module:engine/model/rootelement~RootElement|null} The root registered under a given name or `null` when\n\t * there is no root with the given name.\n\t */\n\tgetRoot( name = 'main' ) {\n\t\treturn this.roots.get( name );\n\t}\n\n\t/**\n\t * Returns an array with names of all roots (without the {@link #graveyard}) added to the document.\n\t *\n\t * @returns {Array.<String>} Roots names.\n\t */\n\tgetRootNames() {\n\t\treturn Array.from( this.roots, root => root.rootName ).filter( name => name != graveyardName );\n\t}\n\n\t/**\n\t * Used to register a post-fixer callback. A post-fixer mechanism guarantees that the features\n\t * will operate on a correct model state.\n\t *\n\t * An execution of a feature may lead to an incorrect document tree state. The callbacks are used to fix the document tree after\n\t * it has changed. Post-fixers are fired just after all changes from the outermost change block were applied but\n\t * before the {@link module:engine/model/document~Document#event:change change event} is fired. If a post-fixer callback made\n\t * a change, it should return `true`. When this happens, all post-fixers are fired again to check if something else should\n\t * not be fixed in the new document tree state.\n\t *\n\t * As a parameter, a post-fixer callback receives a {@link module:engine/model/writer~Writer writer} instance connected with the\n\t * executed changes block. Thanks to that, all changes done by the callback will be added to the same\n\t * {@link module:engine/model/batch~Batch batch} (and undo step) as the original changes. This makes post-fixer changes transparent\n\t * for the user.\n\t *\n\t * An example of a post-fixer is a callback that checks if all the data were removed from the editor. If so, the\n\t * callback should add an empty paragraph so that the editor is never empty:\n\t *\n\t *\t\tdocument.registerPostFixer( writer => {\n\t *\t\t\tconst changes = document.differ.getChanges();\n\t *\n\t *\t\t\t// Check if the changes lead to an empty root in the editor.\n\t *\t\t\tfor ( const entry of changes ) {\n\t *\t\t\t\tif ( entry.type == 'remove' && entry.position.root.isEmpty ) {\n\t *\t\t\t\t\twriter.insertElement( 'paragraph', entry.position.root, 0 );\n\t *\n\t *\t\t\t\t\t// It is fine to return early, even if multiple roots would need to be fixed.\n\t *\t\t\t\t\t// All post-fixers will be fired again, so if there are more empty roots, those will be fixed, too.\n\t *\t\t\t\t\treturn true;\n\t *\t\t\t\t}\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * @param {Function} postFixer\n\t */\n\tregisterPostFixer( postFixer ) {\n\t\tthis._postFixers.add( postFixer );\n\t}\n\n\t/**\n\t * A custom `toJSON()` method to solve child-parent circular dependencies.\n\t *\n\t * @returns {Object} A clone of this object with the document property changed to a string.\n\t */\n\ttoJSON() {\n\t\tconst json = clone( this );\n\n\t\t// Due to circular references we need to remove parent reference.\n\t\tjson.selection = '[engine.model.DocumentSelection]';\n\t\tjson.model = '[engine.model.Model]';\n\n\t\treturn json;\n\t}\n\n\t/**\n\t * Check if there were any changes done on document, and if so, call post-fixers,\n\t * fire `change` event for features and conversion and then reset the differ.\n\t * Fire `change:data` event when at least one operation or buffered marker changes the data.\n\t *\n\t * @protected\n\t * @fires change\n\t * @fires change:data\n\t * @param {module:engine/model/writer~Writer} writer The writer on which post-fixers will be called.\n\t */\n\t_handleChangeBlock( writer ) {\n\t\tif ( this._hasDocumentChangedFromTheLastChangeBlock() ) {\n\t\t\tthis._callPostFixers( writer );\n\n\t\t\t// Refresh selection attributes according to the final position in the model after the change.\n\t\t\tthis.selection.refresh();\n\n\t\t\tif ( this.differ.hasDataChanges() ) {\n\t\t\t\tthis.fire( 'change:data', writer.batch );\n\t\t\t} else {\n\t\t\t\tthis.fire( 'change', writer.batch );\n\t\t\t}\n\n\t\t\t// Theoretically, it is not necessary to refresh selection after change event because\n\t\t\t// post-fixers are the last who should change the model, but just in case...\n\t\t\tthis.selection.refresh();\n\n\t\t\tthis.differ.reset();\n\t\t}\n\n\t\tthis._hasSelectionChangedFromTheLastChangeBlock = false;\n\t}\n\n\t/**\n\t * Returns whether there is a buffered change or if the selection has changed from the last\n\t * {@link module:engine/model/model~Model#enqueueChange `enqueueChange()` block}\n\t * or {@link module:engine/model/model~Model#change `change()` block}.\n\t *\n\t * @protected\n\t * @returns {Boolean} Returns `true` if document has changed from the last `change()` or `enqueueChange()` block.\n\t */\n\t_hasDocumentChangedFromTheLastChangeBlock() {\n\t\treturn !this.differ.isEmpty || this._hasSelectionChangedFromTheLastChangeBlock;\n\t}\n\n\t/**\n\t * Returns the default root for this document which is either the first root that was added to the document using\n\t * {@link #createRoot} or the {@link #graveyard graveyard root} if no other roots were created.\n\t *\n\t * @protected\n\t * @returns {module:engine/model/rootelement~RootElement} The default root for this document.\n\t */\n\t_getDefaultRoot() {\n\t\tfor ( const root of this.roots ) {\n\t\t\tif ( root !== this.graveyard ) {\n\t\t\t\treturn root;\n\t\t\t}\n\t\t}\n\n\t\treturn this.graveyard;\n\t}\n\n\t/**\n\t * Returns the default range for this selection. The default range is a collapsed range that starts and ends\n\t * at the beginning of this selection's document {@link #_getDefaultRoot default root}.\n\t *\n\t * @protected\n\t * @returns {module:engine/model/range~Range}\n\t */\n\t_getDefaultRange() {\n\t\tconst defaultRoot = this._getDefaultRoot();\n\t\tconst model = this.model;\n\t\tconst schema = model.schema;\n\n\t\t// Find the first position where the selection can be put.\n\t\tconst position = model.createPositionFromPath( defaultRoot, [ 0 ] );\n\t\tconst nearestRange = schema.getNearestSelectionRange( position );\n\n\t\t// If valid selection range is not found - return range collapsed at the beginning of the root.\n\t\treturn nearestRange || model.createRange( position );\n\t}\n\n\t/**\n\t * Checks whether a given {@link module:engine/model/range~Range range} is a valid range for\n\t * the {@link #selection document's selection}.\n\t *\n\t * @private\n\t * @param {module:engine/model/range~Range} range A range to check.\n\t * @returns {Boolean} `true` if `range` is valid, `false` otherwise.\n\t */\n\t_validateSelectionRange( range ) {\n\t\treturn validateTextNodePosition( range.start ) && validateTextNodePosition( range.end );\n\t}\n\n\t/**\n\t * Performs post-fixer loops. Executes post-fixer callbacks as long as none of them has done any changes to the model.\n\t *\n\t * @private\n\t * @param {module:engine/model/writer~Writer} writer The writer on which post-fixer callbacks will be called.\n\t */\n\t_callPostFixers( writer ) {\n\t\tlet wasFixed = false;\n\n\t\tdo {\n\t\t\tfor ( const callback of this._postFixers ) {\n\t\t\t\t// Ensure selection attributes are up to date before each post-fixer.\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-engine/issues/1673.\n\t\t\t\t//\n\t\t\t\t// It might be good to refresh the selection after each operation but at the moment it leads\n\t\t\t\t// to losing attributes for composition or and spell checking\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-typing/issues/188\n\t\t\t\tthis.selection.refresh();\n\n\t\t\t\twasFixed = callback( writer );\n\n\t\t\t\tif ( wasFixed ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} while ( wasFixed );\n\t}\n\n\t/**\n\t * Fired after each {@link module:engine/model/model~Model#enqueueChange `enqueueChange()` block} or the outermost\n\t * {@link module:engine/model/model~Model#change `change()` block} was executed and the document was changed\n\t * during that block's execution.\n\t *\n\t * The changes which this event will cover include:\n\t *\n\t * * document structure changes,\n\t * * selection changes,\n\t * * marker changes.\n\t *\n\t * If you want to be notified about all these changes, then simply listen to this event like this:\n\t *\n\t *\t\tmodel.document.on( 'change', () => {\n\t *\t\t\tconsole.log( 'The document has changed!' );\n\t *\t\t} );\n\t *\n\t * If, however, you only want to be notified about the data changes, then use the\n\t * {@link module:engine/model/document~Document#event:change:data change:data} event,\n\t * which is fired for document structure changes and marker changes (which affects the data).\n\t *\n\t *\t\tmodel.document.on( 'change:data', () => {\n\t *\t\t\tconsole.log( 'The data has changed!' );\n\t *\t\t} );\n\t *\n\t * @event change\n\t * @param {module:engine/model/batch~Batch} batch The batch that was used in the executed changes block.\n\t */\n\n\t/**\n\t * It is a narrower version of the {@link #event:change} event. It is fired for changes which\n\t * affect the editor data. This is:\n\t *\n\t * * document structure changes,\n\t * * marker changes (which affects the data).\n\t *\n\t * If you want to be notified about the data changes, then listen to this event:\n\t *\n\t *\t\tmodel.document.on( 'change:data', () => {\n\t *\t\t\tconsole.log( 'The data has changed!' );\n\t *\t\t} );\n\t *\n\t * If you would like to listen to all document changes, then check out the\n\t * {@link module:engine/model/document~Document#event:change change} event.\n\t *\n\t * @event change:data\n\t * @param {module:engine/model/batch~Batch} batch The batch that was used in the executed changes block.\n\t */\n}\n\nmix( Document, EmitterMixin );\n\n// Checks whether given range boundary position is valid for document selection, meaning that is not between\n// unicode surrogate pairs or base character and combining marks.\nfunction validateTextNodePosition( rangeBoundary ) {\n\tconst textNode = rangeBoundary.textNode;\n\n\tif ( textNode ) {\n\t\tconst data = textNode.data;\n\t\tconst offset = rangeBoundary.offset - textNode.startOffset;\n\n\t\treturn !isInsideSurrogatePair( data, offset ) && !isInsideCombinedSymbol( data, offset );\n\t}\n\n\treturn true;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/markercollection\n */\n\nimport LiveRange from './liverange';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * The collection of all {@link module:engine/model/markercollection~Marker markers} attached to the document.\n * It lets you {@link module:engine/model/markercollection~MarkerCollection#get get} markers or track them using\n * {@link module:engine/model/markercollection~MarkerCollection#event:update} event.\n *\n * To create, change or remove makers use {@link module:engine/model/writer~Writer model writers'} methods:\n * {@link module:engine/model/writer~Writer#addMarker} or {@link module:engine/model/writer~Writer#removeMarker}. Since\n * the writer is the only proper way to change the data model it is not possible to change markers directly using this\n * collection. All markers created by the writer will be automatically added to this collection.\n *\n * By default there is one marker collection available as {@link module:engine/model/model~Model#markers model property}.\n *\n * @see module:engine/model/markercollection~Marker\n */\nexport default class MarkerCollection {\n\t/**\n\t * Creates a markers collection.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * Stores {@link ~Marker markers} added to the collection.\n\t\t *\n\t\t * @private\n\t\t * @member {Map} #_markers\n\t\t */\n\t\tthis._markers = new Map();\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * Iterates over all {@link ~Marker markers} added to the collection.\n\t *\n\t * @returns {Iterable}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this._markers.values();\n\t}\n\n\t/**\n\t * Checks if marker with given `markerName` is in the collection.\n\t *\n\t * @param {String} markerName Marker name.\n\t * @returns {Boolean} `true` if marker with given `markerName` is in the collection, `false` otherwise.\n\t */\n\thas( markerName ) {\n\t\treturn this._markers.has( markerName );\n\t}\n\n\t/**\n\t * Returns {@link ~Marker marker} with given `markerName`.\n\t *\n\t * @param {String} markerName Name of marker to get.\n\t * @returns {module:engine/model/markercollection~Marker|null} Marker with given name or `null` if such marker was\n\t * not added to the collection.\n\t */\n\tget( markerName ) {\n\t\treturn this._markers.get( markerName ) || null;\n\t}\n\n\t/**\n\t * Creates and adds a {@link ~Marker marker} to the `MarkerCollection` with given name on given\n\t * {@link module:engine/model/range~Range range}.\n\t *\n\t * If `MarkerCollection` already had a marker with given name (or {@link ~Marker marker} was passed), the marker in\n\t * collection is updated and {@link module:engine/model/markercollection~MarkerCollection#event:update} event is fired\n\t * but only if there was a change (marker range or {@link module:engine/model/markercollection~Marker#managedUsingOperations}\n\t * flag has changed.\n\t *\n\t * @protected\n\t * @fires module:engine/model/markercollection~MarkerCollection#event:update\n\t * @param {String|module:engine/model/markercollection~Marker} markerOrName Name of marker to set or marker instance to update.\n\t * @param {module:engine/model/range~Range} range Marker range.\n\t * @param {Boolean} [managedUsingOperations=false] Specifies whether the marker is managed using operations.\n\t * @param {Boolean} [affectsData=false] Specifies whether the marker affects the data produced by the data pipeline\n\t * (is persisted in the editor's data).\n\t * @returns {module:engine/model/markercollection~Marker} `Marker` instance which was added or updated.\n\t */\n\t_set( markerOrName, range, managedUsingOperations = false, affectsData = false ) {\n\t\tconst markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;\n\t\tconst oldMarker = this._markers.get( markerName );\n\n\t\tif ( oldMarker ) {\n\t\t\tconst oldRange = oldMarker.getRange();\n\t\t\tlet hasChanged = false;\n\n\t\t\tif ( !oldRange.isEqual( range ) ) {\n\t\t\t\toldMarker._attachLiveRange( LiveRange.fromRange( range ) );\n\t\t\t\thasChanged = true;\n\t\t\t}\n\n\t\t\tif ( managedUsingOperations != oldMarker.managedUsingOperations ) {\n\t\t\t\toldMarker._managedUsingOperations = managedUsingOperations;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\n\t\t\tif ( typeof affectsData === 'boolean' && affectsData != oldMarker.affectsData ) {\n\t\t\t\toldMarker._affectsData = affectsData;\n\t\t\t\thasChanged = true;\n\t\t\t}\n\n\t\t\tif ( hasChanged ) {\n\t\t\t\tthis.fire( 'update:' + markerName, oldMarker, oldRange, range );\n\t\t\t}\n\n\t\t\treturn oldMarker;\n\t\t}\n\n\t\tconst liveRange = LiveRange.fromRange( range );\n\t\tconst marker = new Marker( markerName, liveRange, managedUsingOperations, affectsData );\n\n\t\tthis._markers.set( markerName, marker );\n\t\tthis.fire( 'update:' + markerName, marker, null, range );\n\n\t\treturn marker;\n\t}\n\n\t/**\n\t * Removes given {@link ~Marker marker} or a marker with given name from the `MarkerCollection`.\n\t *\n\t * @protected\n\t * @fires module:engine/model/markercollection~MarkerCollection#event:update\n\t * @param {String} markerOrName Marker or name of a marker to remove.\n\t * @returns {Boolean} `true` if marker was found and removed, `false` otherwise.\n\t */\n\t_remove( markerOrName ) {\n\t\tconst markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;\n\t\tconst oldMarker = this._markers.get( markerName );\n\n\t\tif ( oldMarker ) {\n\t\t\tthis._markers.delete( markerName );\n\t\t\tthis.fire( 'update:' + markerName, oldMarker, oldMarker.getRange(), null );\n\n\t\t\tthis._destroyMarker( oldMarker );\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Fires an {@link module:engine/model/markercollection~MarkerCollection#event:update} event for the given {@link ~Marker marker}\n\t * but does not change the marker. Useful to force {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast\n\t * conversion} for the marker.\n\t *\n\t * @protected\n\t * @fires module:engine/model/markercollection~MarkerCollection#event:update\n\t * @param {String} markerOrName Marker or name of a marker to refresh.\n\t */\n\t_refresh( markerOrName ) {\n\t\tconst markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;\n\t\tconst marker = this._markers.get( markerName );\n\n\t\tif ( !marker ) {\n\t\t\tthrow new CKEditorError( 'markercollection-refresh-marker-not-exists: Marker with provided name does not exists.', this );\n\t\t}\n\n\t\tconst range = marker.getRange();\n\n\t\tthis.fire( 'update:' + markerName, marker, range, range, marker.managedUsingOperations, marker.affectsData );\n\t}\n\n\t/**\n\t * Returns iterator that iterates over all markers, which ranges contain given {@link module:engine/model/position~Position position}.\n\t *\n\t * @param {module:engine/model/position~Position} position\n\t * @returns {Iterable.<module:engine/model/markercollection~Marker>}\n\t */\n\t* getMarkersAtPosition( position ) {\n\t\tfor ( const marker of this ) {\n\t\t\tif ( marker.getRange().containsPosition( position ) ) {\n\t\t\t\tyield marker;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns iterator that iterates over all markers, which intersects with given {@link module:engine/model/range~Range range}.\n\t *\n\t * @param {module:engine/model/range~Range} range\n\t * @returns {Iterable.<module:engine/model/markercollection~Marker>}\n\t */\n\t* getMarkersIntersectingRange( range ) {\n\t\tfor ( const marker of this ) {\n\t\t\tif ( marker.getRange().getIntersection( range ) !== null ) {\n\t\t\t\tyield marker;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys marker collection and all markers inside it.\n\t */\n\tdestroy() {\n\t\tfor ( const marker of this._markers.values() ) {\n\t\t\tthis._destroyMarker( marker );\n\t\t}\n\n\t\tthis._markers = null;\n\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Iterates over all markers that starts with given `prefix`.\n\t *\n\t *\t\tconst markerFooA = markersCollection.set( 'foo:a', rangeFooA );\n\t *\t\tconst markerFooB = markersCollection.set( 'foo:b', rangeFooB );\n\t *\t\tconst markerBarA = markersCollection.set( 'bar:a', rangeBarA );\n\t *\t\tconst markerFooBarA = markersCollection.set( 'foobar:a', rangeFooBarA );\n\t *\t\tArray.from( markersCollection.getMarkersGroup( 'foo' ) ); // [ markerFooA, markerFooB ]\n\t *\t\tArray.from( markersCollection.getMarkersGroup( 'a' ) ); // []\n\t *\n\t * @param prefix\n\t * @returns {Iterable.<module:engine/model/markercollection~Marker>}\n\t */\n\t* getMarkersGroup( prefix ) {\n\t\tfor ( const marker of this._markers.values() ) {\n\t\t\tif ( marker.name.startsWith( prefix + ':' ) ) {\n\t\t\t\tyield marker;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the marker.\n\t *\n\t * @private\n\t * @param {module:engine/model/markercollection~Marker} marker Marker to destroy.\n\t */\n\t_destroyMarker( marker ) {\n\t\tmarker.stopListening();\n\t\tmarker._detachLiveRange();\n\t}\n\n\t/**\n\t * Fired whenever marker is added, updated or removed from `MarkerCollection`.\n\t *\n\t * @event update\n\t * @param {module:engine/model/markercollection~Marker} marker Updated Marker.\n\t * @param {module:engine/model/range~Range|null} oldRange Marker range before the update. When is not defined it\n\t * means that marker is just added.\n\t * @param {module:engine/model/range~Range|null} newRange Marker range after update. When is not defined it\n\t * means that marker is just removed.\n\t */\n}\n\nmix( MarkerCollection, EmitterMixin );\n\n/**\n * `Marker` is a continuous parts of model (like a range), is named and represent some kind of information about marked\n * part of model document. In contrary to {@link module:engine/model/node~Node nodes}, which are building blocks of\n * model document tree, markers are not stored directly in document tree but in\n * {@link module:engine/model/model~Model#markers model markers' collection}. Still, they are document data, by giving\n * additional meaning to the part of a model document between marker start and marker end.\n *\n * In this sense, markers are similar to adding and converting attributes on nodes. The difference is that attribute is\n * connected with a given node (e.g. a character is bold no matter if it gets moved or content around it changes).\n * Markers on the other hand are continuous ranges and are characterized by their start and end position. This means that\n * any character in the marker is marked by the marker. For example, if a character is moved outside of marker it stops being\n * \"special\" and the marker is shrunk. Similarly, when a character is moved into the marker from other place in document\n * model, it starts being \"special\" and the marker is enlarged.\n *\n * Another upside of markers is that finding marked part of document is fast and easy. Using attributes to mark some nodes\n * and then trying to find that part of document would require traversing whole document tree. Marker gives instant access\n * to the range which it is marking at the moment.\n *\n * Markers are built from a name and a range.\n *\n * Range of the marker is updated automatically when document changes, using\n * {@link module:engine/model/liverange~LiveRange live range} mechanism.\n *\n * Name is used to group and identify markers. Names have to be unique, but markers can be grouped by\n * using common prefixes, separated with `:`, for example: `user:john` or `search:3`. That's useful in term of creating\n * namespaces for custom elements (e.g. comments, highlights). You can use this prefixes in\n * {@link module:engine/model/markercollection~MarkerCollection#event:update} listeners to listen on changes in a group of markers.\n * For instance: `model.markers.on( 'set:user', callback );` will be called whenever any `user:*` markers changes.\n *\n * There are two types of markers.\n *\n * 1. Markers managed directly, without using operations. They are added directly by {@link module:engine/model/writer~Writer}\n * to the {@link module:engine/model/markercollection~MarkerCollection} without any additional mechanism. They can be used\n * as bookmarks or visual markers. They are great for showing results of the find, or select link when the focus is in the input.\n *\n * 1. Markers managed using operations. These markers are also stored in {@link module:engine/model/markercollection~MarkerCollection}\n * but changes in these markers is managed the same way all other changes in the model structure - using operations.\n * Therefore, they are handled in the undo stack and synchronized between clients if the collaboration plugin is enabled.\n * This type of markers is useful for solutions like spell checking or comments.\n *\n * Both type of them should be added / updated by {@link module:engine/model/writer~Writer#addMarker}\n * and removed by {@link module:engine/model/writer~Writer#removeMarker} methods.\n *\n *\t\tmodel.change( ( writer ) => {\n * \t\t\tconst marker = writer.addMarker( name, { range, usingOperation: true } );\n *\n * \t\t\t// ...\n *\n * \t\t\twriter.removeMarker( marker );\n *\t\t} );\n *\n * See {@link module:engine/model/writer~Writer} to find more examples.\n *\n * Since markers need to track change in the document, for efficiency reasons, it is best to create and keep as little\n * markers as possible and remove them as soon as they are not needed anymore.\n *\n * Markers can be downcasted and upcasted.\n *\n * Markers downcast happens on {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:addMarker} and\n * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:removeMarker} events.\n * Use {@link module:engine/conversion/downcasthelpers downcast converters} or attach a custom converter to mentioned events.\n * For {@link module:engine/controller/datacontroller~DataController data pipeline}, marker should be downcasted to an element.\n * Then, it can be upcasted back to a marker. Again, use {@link module:engine/conversion/upcasthelpers upcast converters} or\n * attach a custom converter to {@link module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element}.\n *\n * `Marker` instances are created and destroyed only by {@link ~MarkerCollection MarkerCollection}.\n */\nclass Marker {\n\t/**\n\t * Creates a marker instance.\n\t *\n\t * @param {String} name Marker name.\n\t * @param {module:engine/model/liverange~LiveRange} liveRange Range marked by the marker.\n\t * @param {Boolean} managedUsingOperations Specifies whether the marker is managed using operations.\n\t * @param {Boolean} affectsData Specifies whether the marker affects the data produced by the data pipeline\n\t * (is persisted in the editor's data).\n\t */\n\tconstructor( name, liveRange, managedUsingOperations, affectsData ) {\n\t\t/**\n\t\t * Marker's name.\n\t\t *\n\t\t * @readonly\n\t\t * @type {String}\n\t\t */\n\t\tthis.name = name;\n\n\t\t/**\n\t\t * Range marked by the marker.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:engine/model/liverange~LiveRange}\n\t\t */\n\t\tthis._liveRange = this._attachLiveRange( liveRange );\n\n\t\t/**\n\t\t * Flag indicates if the marker is managed using operations or not.\n\t\t *\n\t\t * @private\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis._managedUsingOperations = managedUsingOperations;\n\n\t\t/**\n\t\t * Specifies whether the marker affects the data produced by the data pipeline\n\t\t * (is persisted in the editor's data).\n\t\t *\n\t\t * @private\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis._affectsData = affectsData;\n\t}\n\n\t/**\n\t * A value indicating if the marker is managed using operations.\n\t * See {@link ~Marker marker class description} to learn more about marker types.\n\t * See {@link module:engine/model/writer~Writer#addMarker}.\n\t *\n\t * @returns {Boolean}\n\t */\n\tget managedUsingOperations() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );\n\t\t}\n\n\t\treturn this._managedUsingOperations;\n\t}\n\n\t/**\n\t * A value indicating if the marker changes the data.\n\t *\n\t * @returns {Boolean}\n\t */\n\tget affectsData() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );\n\t\t}\n\n\t\treturn this._affectsData;\n\t}\n\n\t/**\n\t * Returns current marker start position.\n\t *\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tgetStart() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );\n\t\t}\n\n\t\treturn this._liveRange.start.clone();\n\t}\n\n\t/**\n\t * Returns current marker end position.\n\t *\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tgetEnd() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );\n\t\t}\n\n\t\treturn this._liveRange.end.clone();\n\t}\n\n\t/**\n\t * Returns a range that represents the current state of the marker.\n\t *\n\t * Keep in mind that returned value is a {@link module:engine/model/range~Range Range}, not a\n\t * {@link module:engine/model/liverange~LiveRange LiveRange}. This means that it is up-to-date and relevant only\n\t * until next model document change. Do not store values returned by this method. Instead, store {@link ~Marker#name}\n\t * and get `Marker` instance from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection} every\n\t * time there is a need to read marker properties. This will guarantee that the marker has not been removed and\n\t * that it's data is up-to-date.\n\t *\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tgetRange() {\n\t\tif ( !this._liveRange ) {\n\t\t\tthrow new CKEditorError( 'marker-destroyed: Cannot use a destroyed marker instance.', this );\n\t\t}\n\n\t\treturn this._liveRange.toRange();\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tmarker.is( 'marker' ); // -> true\n\t *\t\tmarker.is( 'model:marker' ); // -> true\n\t *\n\t *\t\tmarker.is( 'view:element' ); // -> false\n\t *\t\tmarker.is( 'documentSelection' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'marker' || type == 'model:marker';\n\t}\n\n\t/**\n\t * Binds new live range to the marker and detach the old one if is attached.\n\t *\n\t * @protected\n\t * @param {module:engine/model/liverange~LiveRange} liveRange Live range to attach\n\t * @returns {module:engine/model/liverange~LiveRange} Attached live range.\n\t */\n\t_attachLiveRange( liveRange ) {\n\t\tif ( this._liveRange ) {\n\t\t\tthis._detachLiveRange();\n\t\t}\n\n\t\t// Delegating does not work with namespaces. Alternatively, we could delegate all events (using `*`).\n\t\tliveRange.delegate( 'change:range' ).to( this );\n\t\tliveRange.delegate( 'change:content' ).to( this );\n\n\t\tthis._liveRange = liveRange;\n\n\t\treturn liveRange;\n\t}\n\n\t/**\n\t * Unbinds and destroys currently attached live range.\n\t *\n\t * @protected\n\t */\n\t_detachLiveRange() {\n\t\tthis._liveRange.stopDelegating( 'change:range', this );\n\t\tthis._liveRange.stopDelegating( 'change:content', this );\n\t\tthis._liveRange.detach();\n\t\tthis._liveRange = null;\n\t}\n\n\t/**\n\t * Fired whenever {@link ~Marker#_liveRange marker range} is changed due to changes on {@link module:engine/model/document~Document}.\n\t * This is a delegated {@link module:engine/model/liverange~LiveRange#event:change:range LiveRange change:range event}.\n\t *\n\t * When marker is removed from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection},\n\t * all event listeners listening to it should be removed. It is best to do it on\n\t * {@link module:engine/model/markercollection~MarkerCollection#event:update MarkerCollection update event}.\n\t *\n\t * @see module:engine/model/liverange~LiveRange#event:change:range\n\t * @event change:range\n\t * @param {module:engine/model/range~Range} oldRange\n\t * @param {Object} data\n\t */\n\n\t/**\n\t * Fired whenever change on {@link module:engine/model/document~Document} is done inside {@link ~Marker#_liveRange marker range}.\n\t * This is a delegated {@link module:engine/model/liverange~LiveRange#event:change:content LiveRange change:content event}.\n\t *\n\t * When marker is removed from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection},\n\t * all event listeners listening to it should be removed. It is best to do it on\n\t * {@link module:engine/model/markercollection~MarkerCollection#event:update MarkerCollection update event}.\n\t *\n\t * @see module:engine/model/liverange~LiveRange#event:change:content\n\t * @event change:content\n\t * @param {module:engine/model/range~Range} oldRange\n\t * @param {Object} data\n\t */\n}\n\nmix( Marker, EmitterMixin );\n\n/**\n * Cannot use a {@link module:engine/model/markercollection~MarkerCollection#destroy destroyed marker} instance.\n *\n * @error marker-destroyed\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/liveposition\n */\n\nimport Position from './position';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * `LivePosition` is a type of {@link module:engine/model/position~Position Position}\n * that updates itself as {@link module:engine/model/document~Document document}\n * is changed through operations. It may be used as a bookmark.\n *\n * **Note:** Contrary to {@link module:engine/model/position~Position}, `LivePosition` works only in roots that are\n * {@link module:engine/model/rootelement~RootElement}.\n * If {@link module:engine/model/documentfragment~DocumentFragment} is passed, error will be thrown.\n *\n * **Note:** Be very careful when dealing with `LivePosition`. Each `LivePosition` instance bind events that might\n * have to be unbound.\n * Use {@link module:engine/model/liveposition~LivePosition#detach} whenever you don't need `LivePosition` anymore.\n *\n * @extends module:engine/model/position~Position\n */\nexport default class LivePosition extends Position {\n\t/**\n\t * Creates a live position.\n\t *\n\t * @see module:engine/model/position~Position\n\t * @param {module:engine/model/rootelement~RootElement} root\n\t * @param {Array.<Number>} path\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness]\n\t */\n\tconstructor( root, path, stickiness = 'toNone' ) {\n\t\tsuper( root, path, stickiness );\n\n\t\tif ( !this.root.is( 'rootElement' ) ) {\n\t\t\t/**\n\t\t\t * LivePosition's root has to be an instance of RootElement.\n\t\t\t *\n\t\t\t * @error liveposition-root-not-rootelement\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'model-liveposition-root-not-rootelement: LivePosition\\'s root has to be an instance of RootElement.',\n\t\t\t\troot\n\t\t\t);\n\t\t}\n\n\t\tbindWithDocument.call( this );\n\t}\n\n\t/**\n\t * Unbinds all events previously bound by `LivePosition`. Use it whenever you don't need `LivePosition` instance\n\t * anymore (i.e. when leaving scope in which it was declared or before re-assigning variable that was\n\t * referring to it).\n\t */\n\tdetach() {\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Checks whether this object is of the given.\n\t *\n\t *\t\tlivePosition.is( 'position' ); // -> true\n\t *\t\tlivePosition.is( 'model:position' ); // -> true\n\t *\t\tlivePosition.is( 'liveposition' ); // -> true\n\t *\t\tlivePosition.is( 'model:livePosition' ); // -> true\n\t *\n\t *\t\tlivePosition.is( 'view:position' ); // -> false\n\t *\t\tlivePosition.is( 'documentSelection' ); // -> false\n\t *\n\t * {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.\n\t *\n\t * @param {String} type\n\t * @returns {Boolean}\n\t */\n\tis( type ) {\n\t\treturn type == 'livePosition' || type == 'model:livePosition' || super.is( type );\n\t}\n\n\t/**\n\t * Creates a {@link module:engine/model/position~Position position instance}, which is equal to this live position.\n\t *\n\t * @returns {module:engine/model/position~Position}\n\t */\n\ttoPosition() {\n\t\treturn new Position( this.root, this.path.slice(), this.stickiness );\n\t}\n\n\t/**\n\t * Creates a `LivePosition` instance that is equal to position.\n\t *\n\t * @param {module:engine/model/position~Position} position\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness]\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tstatic fromPosition( position, stickiness ) {\n\t\treturn new this( position.root, position.path.slice(), stickiness ? stickiness : position.stickiness );\n\t}\n\n\t/**\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liveposition~LivePosition._createAfter\n\t * @see module:engine/model/position~Position._createAfter\n\t * @param {module:engine/model/node~Node} node\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']\n\t * @returns {module:engine/model/liveposition~LivePosition}\n\t */\n\n\t/**\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liveposition~LivePosition._createBefore\n\t * @see module:engine/model/position~Position._createBefore\n\t * @param {module:engine/model/node~Node} node\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']\n\t * @returns {module:engine/model/liveposition~LivePosition}\n\t */\n\n\t/**\n\t * @static\n\t * @protected\n\t * @method module:engine/model/liveposition~LivePosition._createAt\n\t * @see module:engine/model/position~Position._createAt\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset]\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone']\n\t * @returns {module:engine/model/liveposition~LivePosition}\n\t */\n\n\t/**\n\t * Fired when `LivePosition` instance is changed due to changes on {@link module:engine/model/document~Document}.\n\t *\n\t * @event module:engine/model/liveposition~LivePosition#change\n\t * @param {module:engine/model/position~Position} oldPosition Position equal to this live position before it got changed.\n\t */\n}\n\n// Binds this `LivePosition` to the {@link module:engine/model/document~Document document} that owns\n// this position's {@link module:engine/model/position~Position#root root}.\n//\n// @private\nfunction bindWithDocument() {\n\tthis.listenTo(\n\t\tthis.root.document.model,\n\t\t'applyOperation',\n\t\t( event, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( !operation.isDocumentOperation ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttransform.call( this, operation );\n\t\t},\n\t\t{ priority: 'low' }\n\t);\n}\n\n// Updates this position accordingly to the updates applied to the model. Bases on change events.\n//\n// @private\n// @param {module:engine/model/operation/operation~Operation} operation Executed operation.\nfunction transform( operation ) {\n\tconst result = this.getTransformedByOperation( operation );\n\n\tif ( !this.isEqual( result ) ) {\n\t\tconst oldPosition = this.toPosition();\n\n\t\tthis.path = result.path;\n\t\tthis.root = result.root;\n\n\t\tthis.fire( 'change', oldPosition );\n\t}\n}\n\nmix( LivePosition, EmitterMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/utils/insertcontent\n */\n\nimport Position from '../position';\nimport LivePosition from '../liveposition';\nimport Element from '../element';\nimport Range from '../range';\nimport DocumentSelection from '../documentselection';\nimport Selection from '../selection';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Inserts content into the editor (specified selection) as one would expect the paste\n * functionality to work.\n *\n * If an instance of {@link module:engine/model/selection~Selection} is passed as `selectable` it will be modified\n * to the insertion selection (equal to a range to be selected after insertion).\n *\n * If `selectable` is not passed, the content will be inserted using the current selection of the model document.\n *\n * **Note:** Use {@link module:engine/model/model~Model#insertContent} instead of this function.\n * This function is only exposed to be reusable in algorithms which change the {@link module:engine/model/model~Model#insertContent}\n * method's behavior.\n *\n * @param {module:engine/model/model~Model} model The model in context of which the insertion\n * should be performed.\n * @param {module:engine/model/documentfragment~DocumentFragment|module:engine/model/item~Item} content The content to insert.\n * @param {module:engine/model/selection~Selectable} [selectable=model.document.selection]\n * Selection into which the content should be inserted.\n * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n * @returns {module:engine/model/range~Range} Range which contains all the performed changes. This is a range that, if removed,\n * would return the model to the state before the insertion. If no changes were preformed by `insertContent`, returns a range collapsed\n * at the insertion position.\n */\nexport default function insertContent( model, content, selectable, placeOrOffset ) {\n\treturn model.change( writer => {\n\t\tlet selection;\n\n\t\tif ( !selectable ) {\n\t\t\tselection = model.document.selection;\n\t\t} else if ( selectable instanceof Selection || selectable instanceof DocumentSelection ) {\n\t\t\tselection = selectable;\n\t\t} else {\n\t\t\tselection = writer.createSelection( selectable, placeOrOffset );\n\t\t}\n\n\t\tconst insertionPosition = selection.getFirstPosition();\n\n\t\tif ( !selection.isCollapsed ) {\n\t\t\tmodel.deleteContent( selection, { doNotAutoparagraph: true } );\n\t\t}\n\n\t\tconst insertion = new Insertion( model, writer, insertionPosition );\n\n\t\tlet nodesToInsert;\n\n\t\tif ( content.is( 'documentFragment' ) ) {\n\t\t\tnodesToInsert = content.getChildren();\n\t\t} else {\n\t\t\tnodesToInsert = [ content ];\n\t\t}\n\n\t\tinsertion.handleNodes( nodesToInsert, {\n\t\t\t// The set of children being inserted is the only set in this context\n\t\t\t// so it's the first and last (it's a hack ;)).\n\t\t\tisFirst: true,\n\t\t\tisLast: true\n\t\t} );\n\n\t\tconst newRange = insertion.getSelectionRange();\n\n\t\t/* istanbul ignore else */\n\t\tif ( newRange ) {\n\t\t\tif ( selection instanceof DocumentSelection ) {\n\t\t\t\twriter.setSelection( newRange );\n\t\t\t} else {\n\t\t\t\tselection.setTo( newRange );\n\t\t\t}\n\t\t} else {\n\t\t\t// We are not testing else because it's a safe check for unpredictable edge cases:\n\t\t\t// an insertion without proper range to select.\n\t\t\t//\n\t\t\t// @if CK_DEBUG // console.warn( 'Cannot determine a proper selection range after insertion.' );\n\t\t}\n\n\t\tconst affectedRange = insertion.getAffectedRange() || model.createRange( insertionPosition );\n\n\t\tinsertion.destroy();\n\n\t\treturn affectedRange;\n\t} );\n}\n\n/**\n * Utility class for performing content insertion.\n *\n * @private\n */\nclass Insertion {\n\tconstructor( model, writer, position ) {\n\t\t/**\n\t\t * The model in context of which the insertion should be performed.\n\t\t *\n\t\t * @member {module:engine/model~Model} #model\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * Batch to which operations will be added.\n\t\t *\n\t\t * @member {module:engine/controller/writer~Batch} #writer\n\t\t */\n\t\tthis.writer = writer;\n\n\t\t/**\n\t\t * The position at which (or near which) the next node will be inserted.\n\t\t *\n\t\t * @member {module:engine/model/position~Position} #position\n\t\t */\n\t\tthis.position = position;\n\n\t\t/**\n\t\t * Elements with which the inserted elements can be merged.\n\t\t *\n\t\t *\t\t<p>x^</p><p>y</p> + <p>z</p> (can merge to <p>x</p>)\n\t\t *\t\t<p>x</p><p>^y</p> + <p>z</p> (can merge to <p>y</p>)\n\t\t *\t\t<p>x^y</p> + <p>z</p> (can merge to <p>xy</p> which will be split during the action,\n\t\t *\t\t\t\t\t\t\t\tso both its pieces will be added to this set)\n\t\t *\n\t\t *\n\t\t * @member {Set} #canMergeWith\n\t\t */\n\t\tthis.canMergeWith = new Set( [ this.position.parent ] );\n\n\t\t/**\n\t\t * Schema of the model.\n\t\t *\n\t\t * @member {module:engine/model/schema~Schema} #schema\n\t\t */\n\t\tthis.schema = model.schema;\n\n\t\tthis._filterAttributesOf = [];\n\n\t\t/**\n\t\t * Beginning of the affected range. See {@link module:engine/model/utils/insertcontent~Insertion#getAffectedRange}.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/liveposition~LivePosition|null} #_affectedStart\n\t\t */\n\t\tthis._affectedStart = null;\n\n\t\t/**\n\t\t * End of the affected range. See {@link module:engine/model/utils/insertcontent~Insertion#getAffectedRange}.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/liveposition~LivePosition|null} #_affectedEnd\n\t\t */\n\t\tthis._affectedEnd = null;\n\t}\n\n\t/**\n\t * Handles insertion of a set of nodes.\n\t *\n\t * @param {Iterable.<module:engine/model/node~Node>} nodes Nodes to insert.\n\t * @param {Object} parentContext Context in which parent of these nodes was supposed to be inserted.\n\t * If the parent context is passed it means that the parent element was stripped (was not allowed).\n\t */\n\thandleNodes( nodes, parentContext ) {\n\t\tnodes = Array.from( nodes );\n\n\t\tfor ( let i = 0; i < nodes.length; i++ ) {\n\t\t\tconst node = nodes[ i ];\n\n\t\t\tthis._handleNode( node, {\n\t\t\t\tisFirst: i === 0 && parentContext.isFirst,\n\t\t\t\tisLast: ( i === ( nodes.length - 1 ) ) && parentContext.isLast\n\t\t\t} );\n\t\t}\n\n\t\t// TMP this will become a post-fixer.\n\t\tthis.schema.removeDisallowedAttributes( this._filterAttributesOf, this.writer );\n\t\tthis._filterAttributesOf = [];\n\t}\n\n\t/**\n\t * Returns range to be selected after insertion.\n\t * Returns `null` if there is no valid range to select after insertion.\n\t *\n\t * @returns {module:engine/model/range~Range|null}\n\t */\n\tgetSelectionRange() {\n\t\tif ( this.nodeToSelect ) {\n\t\t\treturn Range._createOn( this.nodeToSelect );\n\t\t}\n\n\t\treturn this.model.schema.getNearestSelectionRange( this.position );\n\t}\n\n\t/**\n\t * Returns a range which contains all the performed changes. This is a range that, if removed, would return the model to the state\n\t * before the insertion. Returns `null` if no changes were done.\n\t *\n\t * @returns {module:engine/model/range~Range|null}\n\t */\n\tgetAffectedRange() {\n\t\tif ( !this._affectedStart ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn new Range( this._affectedStart, this._affectedEnd );\n\t}\n\n\t/**\n\t * Destroys `Insertion` instance.\n\t */\n\tdestroy() {\n\t\tif ( this._affectedStart ) {\n\t\t\tthis._affectedStart.detach();\n\t\t}\n\n\t\tif ( this._affectedEnd ) {\n\t\t\tthis._affectedEnd.detach();\n\t\t}\n\t}\n\n\t/**\n\t * Handles insertion of a single node.\n\t *\n\t * @private\n\t * @param {module:engine/model/node~Node} node\n\t * @param {Object} context\n\t * @param {Boolean} context.isFirst Whether the given node is the first one in the content to be inserted.\n\t * @param {Boolean} context.isLast Whether the given node is the last one in the content to be inserted.\n\t */\n\t_handleNode( node, context ) {\n\t\t// Let's handle object in a special way.\n\t\t// * They should never be merged with other elements.\n\t\t// * If they are not allowed in any of the selection ancestors, they could be either autoparagraphed or totally removed.\n\t\tif ( this.schema.isObject( node ) ) {\n\t\t\tthis._handleObject( node, context );\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Try to find a place for the given node.\n\t\t// Split the position.parent's branch up to a point where the node can be inserted.\n\t\t// If it isn't allowed in the whole branch, then of course don't split anything.\n\t\tconst isAllowed = this._checkAndSplitToAllowedPosition( node, context );\n\n\t\tif ( !isAllowed ) {\n\t\t\tthis._handleDisallowedNode( node, context );\n\n\t\t\treturn;\n\t\t}\n\n\t\tthis._insert( node );\n\n\t\t// After the node was inserted we may try to merge it with its siblings.\n\t\t// This should happen only if it was the first and/or last of the nodes (so only with boundary nodes)\n\t\t// and only if the selection was in those elements initially.\n\t\t//\n\t\t// E.g.:\n\t\t// <p>x^</p> + <p>y</p> => <p>x</p><p>y</p> => <p>xy[]</p>\n\t\t// and:\n\t\t// <p>x^y</p> + <p>z</p> => <p>x</p>^<p>y</p> + <p>z</p> => <p>x</p><p>z</p><p>y</p> => <p>xz[]y</p>\n\t\t// but:\n\t\t// <p>x</p><p>^</p><p>z</p> + <p>y</p> => <p>x</p><p>y</p><p>z</p> (no merging)\n\t\t// <p>x</p>[<img>]<p>z</p> + <p>y</p> => <p>x</p><p>y</p><p>z</p> (no merging, note: after running deleteContents\n\t\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t it's exactly the same case as above)\n\t\tthis._mergeSiblingsOf( node, context );\n\t}\n\n\t/**\n\t * @private\n\t * @param {module:engine/model/element~Element} node The object element.\n\t * @param {Object} context\n\t */\n\t_handleObject( node, context ) {\n\t\t// Try finding it a place in the tree.\n\t\tif ( this._checkAndSplitToAllowedPosition( node ) ) {\n\t\t\tthis._insert( node );\n\t\t}\n\t\t// Try autoparagraphing.\n\t\telse {\n\t\t\tthis._tryAutoparagraphing( node, context );\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t * @param {module:engine/model/node~Node} node The disallowed node which needs to be handled.\n\t * @param {Object} context\n\t */\n\t_handleDisallowedNode( node, context ) {\n\t\t// If the node is an element, try inserting its children (strip the parent).\n\t\tif ( node.is( 'element' ) ) {\n\t\t\tthis.handleNodes( node.getChildren(), context );\n\t\t}\n\t\t// If text is not allowed, try autoparagraphing it.\n\t\telse {\n\t\t\tthis._tryAutoparagraphing( node, context );\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t * @param {module:engine/model/node~Node} node The node to insert.\n\t */\n\t_insert( node ) {\n\t\t/* istanbul ignore if */\n\t\tif ( !this.schema.checkChild( this.position, node ) ) {\n\t\t\t// Algorithm's correctness check. We should never end up here but it's good to know that we did.\n\t\t\t// Note that it would often be a silent issue if we insert node in a place where it's not allowed.\n\n\t\t\t/**\n\t\t\t * Given node cannot be inserted on the given position.\n\t\t\t *\n\t\t\t * @error insertcontent-wrong-position\n\t\t\t * @param {module:engine/model/node~Node} node Node to insert.\n\t\t\t * @param {module:engine/model/position~Position} position Position to insert the node at.\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'insertcontent-wrong-position: Given node cannot be inserted on the given position.',\n\t\t\t\tthis,\n\t\t\t\t{ node, position: this.position }\n\t\t\t);\n\t\t}\n\n\t\tconst livePos = LivePosition.fromPosition( this.position, 'toNext' );\n\n\t\tthis._setAffectedBoundaries( this.position );\n\t\tthis.writer.insert( node, this.position );\n\n\t\tthis.position = livePos.toPosition();\n\t\tlivePos.detach();\n\n\t\t// The last inserted object should be selected because we can't put a collapsed selection after it.\n\t\tif ( this.schema.isObject( node ) && !this.schema.checkChild( this.position, '$text' ) ) {\n\t\t\tthis.nodeToSelect = node;\n\t\t} else {\n\t\t\tthis.nodeToSelect = null;\n\t\t}\n\n\t\tthis._filterAttributesOf.push( node );\n\t}\n\n\t/**\n\t * Sets `_affectedStart` and `_affectedEnd` to the given `position`. Should be used before a change is done during insertion process to\n\t * mark the affected range.\n\t *\n\t * This method is used before inserting a node or splitting a parent node. `_affectedStart` and `_affectedEnd` are also changed\n\t * during merging, but the logic there is more complicated so it is left out of this function.\n\t *\n\t * @private\n\t * @param {module:engine/model/position~Position} position\n\t */\n\t_setAffectedBoundaries( position ) {\n\t\t// Set affected boundaries stickiness so that those position will \"expand\" when something is inserted in between them:\n\t\t// <paragraph>Foo][bar</paragraph> -> <paragraph>Foo]xx[bar</paragraph>\n\t\t// This is why it cannot be a range but two separate positions.\n\t\tif ( !this._affectedStart ) {\n\t\t\tthis._affectedStart = LivePosition.fromPosition( position, 'toPrevious' );\n\t\t}\n\n\t\t// If `_affectedEnd` is before the new boundary position, expand `_affectedEnd`. This can happen if first inserted node was\n\t\t// inserted into the parent but the next node is moved-out of that parent:\n\t\t// (1) <paragraph>Foo][</paragraph> -> <paragraph>Foo]xx[</paragraph>\n\t\t// (2) <paragraph>Foo]xx[</paragraph> -> <paragraph>Foo]xx</paragraph><widget></widget>[\n\t\tif ( !this._affectedEnd || this._affectedEnd.isBefore( position ) ) {\n\t\t\tif ( this._affectedEnd ) {\n\t\t\t\tthis._affectedEnd.detach();\n\t\t\t}\n\n\t\t\tthis._affectedEnd = LivePosition.fromPosition( position, 'toNext' );\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t * @param {module:engine/model/node~Node} node The node which could potentially be merged.\n\t * @param {Object} context\n\t */\n\t_mergeSiblingsOf( node, context ) {\n\t\tif ( !( node instanceof Element ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mergeLeft = this._canMergeLeft( node, context );\n\t\tconst mergeRight = this._canMergeRight( node, context );\n\t\tconst mergePosLeft = LivePosition._createBefore( node );\n\t\tmergePosLeft.stickiness = 'toNext';\n\t\tconst mergePosRight = LivePosition._createAfter( node );\n\t\tmergePosRight.stickiness = 'toNext';\n\n\t\tif ( mergeLeft ) {\n\t\t\tconst livePosition = LivePosition.fromPosition( this.position );\n\t\t\tlivePosition.stickiness = 'toNext';\n\n\t\t\t// If `_affectedStart` is sames as merge position, it means that the element \"marked\" by `_affectedStart` is going to be\n\t\t\t// removed and its contents will be moved. This won't transform `LivePosition` so `_affectedStart` needs to be moved\n\t\t\t// by hand to properly reflect affected range. (Due to `_affectedStart` and `_affectedEnd` stickiness, the \"range\" is\n\t\t\t// shown as `][`).\n\t\t\t//\n\t\t\t// Example - insert `<paragraph>Abc</paragraph><paragraph>Xyz</paragraph>` at the end of `<paragraph>Foo^</paragraph>`:\n\t\t\t//\n\t\t\t// <paragraph>Foo</paragraph><paragraph>Bar</paragraph> -->\n\t\t\t// <paragraph>Foo</paragraph>]<paragraph>Abc</paragraph><paragraph>Xyz</paragraph>[<paragraph>Bar</paragraph> -->\n\t\t\t// <paragraph>Foo]Abc</paragraph><paragraph>Xyz</paragraph>[<paragraph>Bar</paragraph>\n\t\t\t//\n\t\t\t// Note, that if we are here then something must have been inserted, so `_affectedStart` and `_affectedEnd` have to be set.\n\t\t\tif ( this._affectedStart.isEqual( mergePosLeft ) ) {\n\t\t\t\tthis._affectedStart.detach();\n\t\t\t\tthis._affectedStart = LivePosition._createAt( mergePosLeft.nodeBefore, 'end', 'toPrevious' );\n\t\t\t}\n\n\t\t\tthis.writer.merge( mergePosLeft );\n\n\t\t\t// If only one element (the merged one) is in the \"affected range\", also move the affected range end appropriately.\n\t\t\t//\n\t\t\t// Example - insert `<paragraph>Abc</paragraph>` at the of `<paragraph>Foo^</paragraph>`:\n\t\t\t//\n\t\t\t// <paragraph>Foo</paragraph><paragraph>Bar</paragraph> -->\n\t\t\t// <paragraph>Foo</paragraph>]<paragraph>Abc</paragraph>[<paragraph>Bar</paragraph> -->\n\t\t\t// <paragraph>Foo]Abc</paragraph>[<paragraph>Bar</paragraph> -->\n\t\t\t// <paragraph>Foo]Abc[</paragraph><paragraph>Bar</paragraph>\n\t\t\tif ( mergePosLeft.isEqual( this._affectedEnd ) && context.isLast ) {\n\t\t\t\tthis._affectedEnd.detach();\n\t\t\t\tthis._affectedEnd = LivePosition._createAt( mergePosLeft.nodeBefore, 'end', 'toNext' );\n\t\t\t}\n\n\t\t\tthis.position = livePosition.toPosition();\n\t\t\tlivePosition.detach();\n\t\t}\n\n\t\tif ( mergeRight ) {\n\t\t\t/* istanbul ignore if */\n\t\t\tif ( !this.position.isEqual( mergePosRight ) ) {\n\t\t\t\t// Algorithm's correctness check. We should never end up here but it's good to know that we did.\n\t\t\t\t// At this point the insertion position should be after the node we'll merge. If it isn't,\n\t\t\t\t// it should need to be secured as in the left merge case.\n\t\t\t\t/**\n\t\t\t\t * An internal error occured during merging insertion content with siblings.\n\t\t\t\t * The insertion position should equal to the merge position.\n\t\t\t\t *\n\t\t\t\t * @error insertcontent-invalid-insertion-position\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError( 'insertcontent-invalid-insertion-position', this );\n\t\t\t}\n\n\t\t\t// Move the position to the previous node, so it isn't moved to the graveyard on merge.\n\t\t\t// <p>x</p>[]<p>y</p> => <p>x[]</p><p>y</p>\n\t\t\tthis.position = Position._createAt( mergePosRight.nodeBefore, 'end' );\n\n\t\t\t// OK: <p>xx[]</p> + <p>yy</p> => <p>xx[]yy</p> (when sticks to previous)\n\t\t\t// NOK: <p>xx[]</p> + <p>yy</p> => <p>xxyy[]</p> (when sticks to next)\n\t\t\tconst livePosition = LivePosition.fromPosition( this.position, 'toPrevious' );\n\n\t\t\t// See comment above on moving `_affectedStart`.\n\t\t\tif ( this._affectedEnd.isEqual( mergePosRight ) ) {\n\t\t\t\tthis._affectedEnd.detach();\n\t\t\t\tthis._affectedEnd = LivePosition._createAt( mergePosRight.nodeBefore, 'end', 'toNext' );\n\t\t\t}\n\n\t\t\tthis.writer.merge( mergePosRight );\n\n\t\t\t// See comment above on moving `_affectedStart`.\n\t\t\tif ( mergePosRight.getShiftedBy( -1 ).isEqual( this._affectedStart ) && context.isFirst ) {\n\t\t\t\tthis._affectedStart.detach();\n\t\t\t\tthis._affectedStart = LivePosition._createAt( mergePosRight.nodeBefore, 0, 'toPrevious' );\n\t\t\t}\n\n\t\t\tthis.position = livePosition.toPosition();\n\t\t\tlivePosition.detach();\n\t\t}\n\n\t\tif ( mergeLeft || mergeRight ) {\n\t\t\t// After merge elements that were marked by _insert() to be filtered might be gone so\n\t\t\t// we need to mark the new container.\n\t\t\tthis._filterAttributesOf.push( this.position.parent );\n\t\t}\n\n\t\tmergePosLeft.detach();\n\t\tmergePosRight.detach();\n\t}\n\n\t/**\n\t * Checks whether specified node can be merged with previous sibling element.\n\t *\n\t * @private\n\t * @param {module:engine/model/node~Node} node The node which could potentially be merged.\n\t * @param {Object} context\n\t * @returns {Boolean}\n\t */\n\t_canMergeLeft( node, context ) {\n\t\tconst previousSibling = node.previousSibling;\n\n\t\treturn context.isFirst &&\n\t\t\t( previousSibling instanceof Element ) &&\n\t\t\tthis.canMergeWith.has( previousSibling ) &&\n\t\t\tthis.model.schema.checkMerge( previousSibling, node );\n\t}\n\n\t/**\n\t * Checks whether specified node can be merged with next sibling element.\n\t *\n\t * @private\n\t * @param {module:engine/model/node~Node} node The node which could potentially be merged.\n\t * @param {Object} context\n\t * @returns {Boolean}\n\t */\n\t_canMergeRight( node, context ) {\n\t\tconst nextSibling = node.nextSibling;\n\n\t\treturn context.isLast &&\n\t\t\t( nextSibling instanceof Element ) &&\n\t\t\tthis.canMergeWith.has( nextSibling ) &&\n\t\t\tthis.model.schema.checkMerge( node, nextSibling );\n\t}\n\n\t/**\n\t * Tries wrapping the node in a new paragraph and inserting it this way.\n\t *\n\t * @private\n\t * @param {module:engine/model/node~Node} node The node which needs to be autoparagraphed.\n\t * @param {Object} context\n\t */\n\t_tryAutoparagraphing( node, context ) {\n\t\tconst paragraph = this.writer.createElement( 'paragraph' );\n\n\t\t// Do not autoparagraph if the paragraph won't be allowed there,\n\t\t// cause that would lead to an infinite loop. The paragraph would be rejected in\n\t\t// the next _handleNode() call and we'd be here again.\n\t\tif ( this._getAllowedIn( paragraph, this.position.parent ) && this.schema.checkChild( paragraph, node ) ) {\n\t\t\tparagraph._appendChild( node );\n\t\t\tthis._handleNode( paragraph, context );\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t * @param {module:engine/model/node~Node} node\n\t * @returns {Boolean} Whether an allowed position was found.\n\t * `false` is returned if the node isn't allowed at any position up in the tree, `true` if was.\n\t */\n\t_checkAndSplitToAllowedPosition( node ) {\n\t\tconst allowedIn = this._getAllowedIn( node, this.position.parent );\n\n\t\tif ( !allowedIn ) {\n\t\t\treturn false;\n\t\t}\n\n\t\twhile ( allowedIn != this.position.parent ) {\n\t\t\t// If a parent which we'd need to leave is a limit element, break.\n\t\t\tif ( this.schema.isLimit( this.position.parent ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( this.position.isAtStart ) {\n\t\t\t\t// If insertion position is at the beginning of the parent, move it out instead of splitting.\n\t\t\t\t// <p>^Foo</p> -> ^<p>Foo</p>\n\t\t\t\tconst parent = this.position.parent;\n\n\t\t\t\tthis.position = this.writer.createPositionBefore( parent );\n\n\t\t\t\t// Special case – parent is empty (<p>^</p>).\n\t\t\t\t//\n\t\t\t\t// 1. parent.isEmpty\n\t\t\t\t// We can remove the element after moving insertion position out of it.\n\t\t\t\t//\n\t\t\t\t// 2. parent.parent === allowedIn\n\t\t\t\t// However parent should remain in place when allowed element is above limit element in document tree.\n\t\t\t\t// For example there shouldn't be allowed to remove empty paragraph from tableCell, when is pasted\n\t\t\t\t// content allowed in $root.\n\t\t\t\tif ( parent.isEmpty && parent.parent === allowedIn ) {\n\t\t\t\t\tthis.writer.remove( parent );\n\t\t\t\t}\n\t\t\t} else if ( this.position.isAtEnd ) {\n\t\t\t\t// If insertion position is at the end of the parent, move it out instead of splitting.\n\t\t\t\t// <p>Foo^</p> -> <p>Foo</p>^\n\t\t\t\tthis.position = this.writer.createPositionAfter( this.position.parent );\n\t\t\t} else {\n\t\t\t\tconst tempPos = this.writer.createPositionAfter( this.position.parent );\n\n\t\t\t\tthis._setAffectedBoundaries( this.position );\n\t\t\t\tthis.writer.split( this.position );\n\n\t\t\t\tthis.position = tempPos;\n\n\t\t\t\tthis.canMergeWith.add( this.position.nodeAfter );\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Gets the element in which the given node is allowed. It checks the passed element and all its ancestors.\n\t *\n\t * @private\n\t * @param {module:engine/model/node~Node} node The node to check.\n\t * @param {module:engine/model/element~Element} element The element in which the node's correctness should be checked.\n\t * @returns {module:engine/model/element~Element|null}\n\t */\n\t_getAllowedIn( node, element ) {\n\t\tif ( this.schema.checkChild( element, node ) ) {\n\t\t\treturn element;\n\t\t}\n\n\t\tif ( element.parent ) {\n\t\t\treturn this._getAllowedIn( node, element.parent );\n\t\t}\n\n\t\treturn null;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/utils/deletecontent\n */\n\nimport LivePosition from '../liveposition';\nimport Range from '../range';\nimport DocumentSelection from '../documentselection';\n\n/**\n * Deletes content of the selection and merge siblings. The resulting selection is always collapsed.\n *\n * **Note:** Use {@link module:engine/model/model~Model#deleteContent} instead of this function.\n * This function is only exposed to be reusable in algorithms\n * which change the {@link module:engine/model/model~Model#deleteContent}\n * method's behavior.\n *\n * @param {module:engine/model/model~Model} model The model in context of which the insertion\n * should be performed.\n * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n * Selection of which the content should be deleted.\n * @param {module:engine/model/batch~Batch} batch Batch to which the operations will be added.\n * @param {Object} [options]\n * @param {Boolean} [options.leaveUnmerged=false] Whether to merge elements after removing the content of the selection.\n *\n * For example `<heading>x[x</heading><paragraph>y]y</paragraph>` will become:\n *\n * * `<heading>x^y</heading>` with the option disabled (`leaveUnmerged == false`)\n * * `<heading>x^</heading><paragraph>y</paragraph>` with enabled (`leaveUnmerged == true`).\n *\n * Note: {@link module:engine/model/schema~Schema#isObject object} and {@link module:engine/model/schema~Schema#isLimit limit}\n * elements will not be merged.\n *\n * @param {Boolean} [options.doNotResetEntireContent=false] Whether to skip replacing the entire content with a\n * paragraph when the entire content was selected.\n *\n * For example `<heading>[x</heading><paragraph>y]</paragraph>` will become:\n *\n * * `<paragraph>^</paragraph>` with the option disabled (`doNotResetEntireContent == false`)\n * * `<heading>^</heading>` with enabled (`doNotResetEntireContent == true`).\n *\n * @param {Boolean} [options.doNotAutoparagraph=false] Whether to create a paragraph if after content deletion selection is moved\n * to a place where text cannot be inserted.\n *\n * For example `<paragraph>x</paragraph>[<image src=\"foo.jpg\"></image>]` will become:\n *\n * * `<paragraph>x</paragraph><paragraph>[]</paragraph>` with the option disabled (`doNotAutoparagraph == false`)\n * * `<paragraph>x[]</paragraph>` with the option enabled (`doNotAutoparagraph == true`).\n *\n * **Note:** if there is no valid position for the selection, the paragraph will always be created:\n *\n * `[<image src=\"foo.jpg\"></image>]` -> `<paragraph>[]</paragraph>`.\n */\nexport default function deleteContent( model, selection, options = {} ) {\n\tif ( selection.isCollapsed ) {\n\t\treturn;\n\t}\n\n\tconst selRange = selection.getFirstRange();\n\n\t// If the selection is already removed, don't do anything.\n\tif ( selRange.root.rootName == '$graveyard' ) {\n\t\treturn;\n\t}\n\n\tconst schema = model.schema;\n\n\tmodel.change( writer => {\n\t\t// 1. Replace the entire content with paragraph.\n\t\t// See: https://github.com/ckeditor/ckeditor5-engine/issues/1012#issuecomment-315017594.\n\t\tif ( !options.doNotResetEntireContent && shouldEntireContentBeReplacedWithParagraph( schema, selection ) ) {\n\t\t\treplaceEntireContentWithParagraph( writer, selection, schema );\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst startPos = selRange.start;\n\t\tconst endPos = LivePosition.fromPosition( selRange.end, 'toNext' );\n\n\t\t// 2. Remove the content if there is any.\n\t\tif ( !selRange.start.isTouching( selRange.end ) ) {\n\t\t\twriter.remove( selRange );\n\t\t}\n\n\t\t// 3. Merge elements in the right branch to the elements in the left branch.\n\t\t// The only reasonable (in terms of data and selection correctness) case in which we need to do that is:\n\t\t//\n\t\t// <heading type=1>Fo[</heading><paragraph>]ar</paragraph> => <heading type=1>Fo^ar</heading>\n\t\t//\n\t\t// However, the algorithm supports also merging deeper structures (up to the depth of the shallower branch),\n\t\t// as it's hard to imagine what should actually be the default behavior. Usually, specific features will\n\t\t// want to override that behavior anyway.\n\t\tif ( !options.leaveUnmerged ) {\n\t\t\tmergeBranches( writer, startPos, endPos );\n\n\t\t\t// TMP this will be replaced with a postfixer.\n\t\t\t// We need to check and strip disallowed attributes in all nested nodes because after merge\n\t\t\t// some attributes could end up in a path where are disallowed.\n\t\t\t//\n\t\t\t// e.g. bold is disallowed for <H1>\n\t\t\t// <h1>Fo{o</h1><p>b}a<b>r</b><p> -> <h1>Fo{}a<b>r</b><h1> -> <h1>Fo{}ar<h1>.\n\t\t\tschema.removeDisallowedAttributes( startPos.parent.getChildren(), writer );\n\t\t}\n\n\t\tcollapseSelectionAt( writer, selection, startPos );\n\n\t\t// 4. Add a paragraph to set selection in it.\n\t\t// Check if a text is allowed in the new container. If not, try to create a new paragraph (if it's allowed here).\n\t\tif ( shouldAutoparagraph( schema, startPos ) ) {\n\t\t\t// If auto-paragraphing is off, find the closest valid selection range and collapse the selection there.\n\t\t\t// If there is no valid selection range, create paragraph anyway and set selection there.\n\t\t\tconst validSelectionRange = schema.getNearestSelectionRange( startPos );\n\n\t\t\tif ( options.doNotAutoparagraph && validSelectionRange ) {\n\t\t\t\tcollapseSelectionAt( writer, selection, validSelectionRange );\n\t\t\t} else {\n\t\t\t\tinsertParagraph( writer, startPos, selection );\n\t\t\t}\n\t\t}\n\n\t\tendPos.detach();\n\t} );\n}\n\n// This function is a result of reaching the Ballmer's peak for just the right amount of time.\n// Even I had troubles documenting it after a while and after reading it again I couldn't believe that it really works.\nfunction mergeBranches( writer, startPos, endPos ) {\n\tconst startParent = startPos.parent;\n\tconst endParent = endPos.parent;\n\n\t// If both positions ended up in the same parent, then there's nothing more to merge:\n\t// <$root><p>x[]</p><p>{}y</p></$root> => <$root><p>xy</p>[]{}</$root>\n\tif ( startParent == endParent ) {\n\t\treturn;\n\t}\n\n\t// If one of the positions is a limit element, then there's nothing to merge because we don't want to cross the limit boundaries.\n\tif ( writer.model.schema.isLimit( startParent ) || writer.model.schema.isLimit( endParent ) ) {\n\t\treturn;\n\t}\n\n\t// Check if operations we'll need to do won't need to cross object or limit boundaries.\n\t// E.g., we can't merge endParent into startParent in this case:\n\t// <limit><startParent>x[]</startParent></limit><endParent>{}</endParent>\n\tif ( !checkCanBeMerged( startPos, endPos, writer.model.schema ) ) {\n\t\treturn;\n\t}\n\n\t// Remember next positions to merge. For example:\n\t// <a><b>x[]</b></a><c><d>{}y</d></c>\n\t// will become:\n\t// <a><b>xy</b>[]</a><c>{}</c>\n\tstartPos = writer.createPositionAfter( startParent );\n\tendPos = writer.createPositionBefore( endParent );\n\n\tif ( !endPos.isEqual( startPos ) ) {\n\t\t// In this case, before we merge, we need to move `endParent` to the `startPos`:\n\t\t// <a><b>x[]</b></a><c><d>{}y</d></c>\n\t\t// becomes:\n\t\t// <a><b>x</b>[]<d>y</d></a><c>{}</c>\n\t\twriter.insert( endParent, startPos );\n\t}\n\n\t// Merge two siblings:\n\t// <a>x</a>[]<b>y</b> -> <a>xy</a> (the usual case)\n\t// <a><b>x</b>[]<d>y</d></a><c></c> -> <a><b>xy</b>[]</a><c></c> (this is the \"move parent\" case shown above)\n\twriter.merge( startPos );\n\n\t// Remove empty end ancestors:\n\t// <a>fo[o</a><b><a><c>bar]</c></a></b>\n\t// becomes:\n\t// <a>fo[]</a><b><a>{}</a></b>\n\t// So we can remove <a> and <b>.\n\twhile ( endPos.parent.isEmpty ) {\n\t\tconst parentToRemove = endPos.parent;\n\n\t\tendPos = writer.createPositionBefore( parentToRemove );\n\n\t\twriter.remove( parentToRemove );\n\t}\n\n\t// Continue merging next level.\n\tmergeBranches( writer, startPos, endPos );\n}\n\nfunction shouldAutoparagraph( schema, position ) {\n\tconst isTextAllowed = schema.checkChild( position, '$text' );\n\tconst isParagraphAllowed = schema.checkChild( position, 'paragraph' );\n\n\treturn !isTextAllowed && isParagraphAllowed;\n}\n\n// Check if parents of two positions can be merged by checking if there are no limit/object\n// boundaries between those two positions.\n//\n// E.g. in <bQ><p>x[]</p></bQ><widget><caption>{}</caption></widget>\n// we'll check <p>, <bQ>, <widget> and <caption>.\n// Usually, widget and caption are marked as objects/limits in the schema, so in this case merging will be blocked.\nfunction checkCanBeMerged( leftPos, rightPos, schema ) {\n\tconst rangeToCheck = new Range( leftPos, rightPos );\n\n\tfor ( const value of rangeToCheck.getWalker() ) {\n\t\tif ( schema.isLimit( value.item ) ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nfunction insertParagraph( writer, position, selection ) {\n\tconst paragraph = writer.createElement( 'paragraph' );\n\n\twriter.insert( paragraph, position );\n\n\tcollapseSelectionAt( writer, selection, writer.createPositionAt( paragraph, 0 ) );\n}\n\nfunction replaceEntireContentWithParagraph( writer, selection ) {\n\tconst limitElement = writer.model.schema.getLimitElement( selection );\n\n\twriter.remove( writer.createRangeIn( limitElement ) );\n\tinsertParagraph( writer, writer.createPositionAt( limitElement, 0 ), selection );\n}\n\n// We want to replace the entire content with a paragraph when:\n// * the entire content is selected,\n// * selection contains at least two elements,\n// * whether the paragraph is allowed in schema in the common ancestor.\nfunction shouldEntireContentBeReplacedWithParagraph( schema, selection ) {\n\tconst limitElement = schema.getLimitElement( selection );\n\n\tif ( !selection.containsEntireContent( limitElement ) ) {\n\t\treturn false;\n\t}\n\n\tconst range = selection.getFirstRange();\n\n\tif ( range.start.parent == range.end.parent ) {\n\t\treturn false;\n\t}\n\n\treturn schema.checkChild( limitElement, 'paragraph' );\n}\n\n// Helper function that sets the selection. Depending whether given `selection` is a document selection or not,\n// uses a different method to set it.\nfunction collapseSelectionAt( writer, selection, positionOrRange ) {\n\tif ( selection instanceof DocumentSelection ) {\n\t\twriter.setSelection( positionOrRange );\n\t} else {\n\t\tselection.setTo( positionOrRange );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/utils/modifyselection\n */\n\nimport Position from '../position';\nimport TreeWalker from '../treewalker';\nimport Range from '../range';\nimport { isInsideSurrogatePair, isInsideCombinedSymbol } from '@ckeditor/ckeditor5-utils/src/unicode';\nimport DocumentSelection from '../documentselection';\n\nconst wordBoundaryCharacters = ' ,.?!:;\"-()';\n\n/**\n * Modifies the selection. Currently, the supported modifications are:\n *\n * * Extending. The selection focus is moved in the specified `options.direction` with a step specified in `options.unit`.\n * Possible values for `unit` are:\n * * `'character'` (default) - moves selection by one user-perceived character. In most cases this means moving by one\n * character in `String` sense. However, unicode also defines \"combing marks\". These are special symbols, that combines\n * with a symbol before it (\"base character\") to create one user-perceived character. For example, `q̣̇` is a normal\n * letter `q` with two \"combining marks\": upper dot (`Ux0307`) and lower dot (`Ux0323`). For most actions, i.e. extending\n * selection by one position, it is correct to include both \"base character\" and all of it's \"combining marks\". That is\n * why `'character'` value is most natural and common method of modifying selection.\n * * `'codePoint'` - moves selection by one unicode code point. In contrary to, `'character'` unit, this will insert\n * selection between \"base character\" and \"combining mark\", because \"combining marks\" have their own unicode code points.\n * However, for technical reasons, unicode code points with values above `UxFFFF` are represented in native `String` by\n * two characters, called \"surrogate pairs\". Halves of \"surrogate pairs\" have a meaning only when placed next to each other.\n * For example `𨭎` is represented in `String` by `\\uD862\\uDF4E`. Both `\\uD862` and `\\uDF4E` do not have any meaning\n * outside the pair (are rendered as ? when alone). Position between them would be incorrect. In this case, selection\n * extension will include whole \"surrogate pair\".\n * * `'word'` - moves selection by a whole word.\n *\n * **Note:** if you extend a forward selection in a backward direction you will in fact shrink it.\n *\n * **Note:** Use {@link module:engine/model/model~Model#modifySelection} instead of this function.\n * This function is only exposed to be reusable in algorithms\n * which change the {@link module:engine/model/model~Model#modifySelection}\n * method's behavior.\n *\n * @param {module:engine/model/model~Model} model The model in context of which\n * the selection modification should be performed.\n * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n * The selection to modify.\n * @param {Object} [options]\n * @param {'forward'|'backward'} [options.direction='forward'] The direction in which the selection should be modified.\n * @param {'character'|'codePoint'|'word'} [options.unit='character'] The unit by which selection should be modified.\n */\nexport default function modifySelection( model, selection, options = {} ) {\n\tconst schema = model.schema;\n\tconst isForward = options.direction != 'backward';\n\tconst unit = options.unit ? options.unit : 'character';\n\n\tconst focus = selection.focus;\n\n\tconst walker = new TreeWalker( {\n\t\tboundaries: getSearchRange( focus, isForward ),\n\t\tsingleCharacters: true,\n\t\tdirection: isForward ? 'forward' : 'backward'\n\t} );\n\n\tconst data = { walker, schema, isForward, unit };\n\n\tlet next;\n\n\twhile ( ( next = walker.next() ) ) {\n\t\tif ( next.done ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst position = tryExtendingTo( data, next.value );\n\n\t\tif ( position ) {\n\t\t\tif ( selection instanceof DocumentSelection ) {\n\t\t\t\tmodel.change( writer => {\n\t\t\t\t\twriter.setSelectionFocus( position );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tselection.setFocus( position );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n// Checks whether the selection can be extended to the the walker's next value (next position).\n// @param {{ walker, unit, isForward, schema }} data\n// @param {module:engine/view/treewalker~TreeWalkerValue} value\nfunction tryExtendingTo( data, value ) {\n\t// If found text, we can certainly put the focus in it. Let's just find a correct position\n\t// based on the unit.\n\tif ( value.type == 'text' ) {\n\t\tif ( data.unit === 'word' ) {\n\t\t\treturn getCorrectWordBreakPosition( data.walker, data.isForward );\n\t\t}\n\n\t\treturn getCorrectPosition( data.walker, data.unit, data.isForward );\n\t}\n\n\t// Entering an element.\n\tif ( value.type == ( data.isForward ? 'elementStart' : 'elementEnd' ) ) {\n\t\t// If it's an object, we can select it now.\n\t\tif ( data.schema.isObject( value.item ) ) {\n\t\t\treturn Position._createAt( value.item, data.isForward ? 'after' : 'before' );\n\t\t}\n\n\t\t// If text allowed on this position, extend to this place.\n\t\tif ( data.schema.checkChild( value.nextPosition, '$text' ) ) {\n\t\t\treturn value.nextPosition;\n\t\t}\n\t}\n\t// Leaving an element.\n\telse {\n\t\t// If leaving a limit element, stop.\n\t\tif ( data.schema.isLimit( value.item ) ) {\n\t\t\t// NOTE: Fast-forward the walker until the end.\n\t\t\tdata.walker.skip( () => true );\n\n\t\t\treturn;\n\t\t}\n\n\t\t// If text allowed on this position, extend to this place.\n\t\tif ( data.schema.checkChild( value.nextPosition, '$text' ) ) {\n\t\t\treturn value.nextPosition;\n\t\t}\n\t}\n}\n\n// Finds a correct position by walking in a text node and checking whether selection can be extended to given position\n// or should be extended further.\n//\n// @param {module:engine/model/treewalker~TreeWalker} walker\n// @param {String} unit The unit by which selection should be modified.\nfunction getCorrectPosition( walker, unit ) {\n\tconst textNode = walker.position.textNode;\n\n\tif ( textNode ) {\n\t\tconst data = textNode.data;\n\t\tlet offset = walker.position.offset - textNode.startOffset;\n\n\t\twhile ( isInsideSurrogatePair( data, offset ) || ( unit == 'character' && isInsideCombinedSymbol( data, offset ) ) ) {\n\t\t\twalker.next();\n\n\t\t\toffset = walker.position.offset - textNode.startOffset;\n\t\t}\n\t}\n\n\treturn walker.position;\n}\n\n// Finds a correct position of a word break by walking in a text node and checking whether selection can be extended to given position\n// or should be extended further.\n//\n// @param {module:engine/model/treewalker~TreeWalker} walker\n// @param {Boolean} isForward Is the direction in which the selection should be modified is forward.\nfunction getCorrectWordBreakPosition( walker, isForward ) {\n\tlet textNode = walker.position.textNode;\n\n\tif ( textNode ) {\n\t\tlet offset = walker.position.offset - textNode.startOffset;\n\n\t\twhile ( !isAtWordBoundary( textNode.data, offset, isForward ) && !isAtNodeBoundary( textNode, offset, isForward ) ) {\n\t\t\twalker.next();\n\n\t\t\t// Check of adjacent text nodes with different attributes (like BOLD).\n\t\t\t// Example : 'foofoo []bar<$text bold=\"true\">bar</$text> bazbaz'\n\t\t\t// should expand to : 'foofoo [bar<$text bold=\"true\">bar</$text>] bazbaz'.\n\t\t\tconst nextNode = isForward ? walker.position.nodeAfter : walker.position.nodeBefore;\n\n\t\t\t// Scan only text nodes. Ignore inline elements (like `<softBreak>`).\n\t\t\tif ( nextNode && nextNode.is( 'text' ) ) {\n\t\t\t\t// Check boundary char of an adjacent text node.\n\t\t\t\tconst boundaryChar = nextNode.data.charAt( isForward ? 0 : nextNode.data.length - 1 );\n\n\t\t\t\t// Go to the next node if the character at the boundary of that node belongs to the same word.\n\t\t\t\tif ( !wordBoundaryCharacters.includes( boundaryChar ) ) {\n\t\t\t\t\t// If adjacent text node belongs to the same word go to it & reset values.\n\t\t\t\t\twalker.next();\n\n\t\t\t\t\ttextNode = walker.position.textNode;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toffset = walker.position.offset - textNode.startOffset;\n\t\t}\n\t}\n\n\treturn walker.position;\n}\n\nfunction getSearchRange( start, isForward ) {\n\tconst root = start.root;\n\tconst searchEnd = Position._createAt( root, isForward ? 'end' : 0 );\n\n\tif ( isForward ) {\n\t\treturn new Range( start, searchEnd );\n\t} else {\n\t\treturn new Range( searchEnd, start );\n\t}\n}\n\n// Checks if selection is on word boundary.\n//\n// @param {String} data The text node value to investigate.\n// @param {Number} offset Position offset.\n// @param {Boolean} isForward Is the direction in which the selection should be modified is forward.\nfunction isAtWordBoundary( data, offset, isForward ) {\n\t// The offset to check depends on direction.\n\tconst offsetToCheck = offset + ( isForward ? 0 : -1 );\n\n\treturn wordBoundaryCharacters.includes( data.charAt( offsetToCheck ) );\n}\n\n// Checks if selection is on node boundary.\n//\n// @param {module:engine/model/text~Text} textNode The text node to investigate.\n// @param {Number} offset Position offset.\n// @param {Boolean} isForward Is the direction in which the selection should be modified is forward.\nfunction isAtNodeBoundary( textNode, offset, isForward ) {\n\treturn offset === ( isForward ? textNode.endOffset : 0 );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/utils/getselectedcontent\n */\n\n/**\n * Gets a clone of the selected content.\n *\n * For example, for the following selection:\n *\n * ```html\n * <p>x</p><quote><p>y</p><h>fir[st</h></quote><p>se]cond</p><p>z</p>\n * ```\n *\n * It will return a document fragment with such a content:\n *\n * ```html\n * <quote><h>st</h></quote><p>se</p>\n * ```\n *\n * @param {module:engine/model/model~Model} model The model in context of which\n * the selection modification should be performed.\n * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n * The selection of which content will be returned.\n * @returns {module:engine/model/documentfragment~DocumentFragment}\n */\nexport default function getSelectedContent( model, selection ) {\n\treturn model.change( writer => {\n\t\tconst frag = writer.createDocumentFragment();\n\t\tconst range = selection.getFirstRange();\n\n\t\tif ( !range || range.isCollapsed ) {\n\t\t\treturn frag;\n\t\t}\n\n\t\tconst root = range.start.root;\n\t\tconst commonPath = range.start.getCommonPath( range.end );\n\t\tconst commonParent = root.getNodeByPath( commonPath );\n\n\t\t// ## 1st step\n\t\t//\n\t\t// First, we'll clone a fragment represented by a minimal flat range\n\t\t// containing the original range to be cloned.\n\t\t// E.g. let's consider such a range:\n\t\t//\n\t\t// <p>x</p><quote><p>y</p><h>fir[st</h></quote><p>se]cond</p><p>z</p>\n\t\t//\n\t\t// A minimal flat range containing this one is:\n\t\t//\n\t\t// <p>x</p>[<quote><p>y</p><h>first</h></quote><p>second</p>]<p>z</p>\n\t\t//\n\t\t// We can easily clone this structure, preserving e.g. the <quote> element.\n\t\tlet flatSubtreeRange;\n\n\t\tif ( range.start.parent == range.end.parent ) {\n\t\t\t// The original range is flat, so take it.\n\t\t\tflatSubtreeRange = range;\n\t\t} else {\n\t\t\tflatSubtreeRange = writer.createRange(\n\t\t\t\twriter.createPositionAt( commonParent, range.start.path[ commonPath.length ] ),\n\t\t\t\twriter.createPositionAt( commonParent, range.end.path[ commonPath.length ] + 1 )\n\t\t\t);\n\t\t}\n\n\t\tconst howMany = flatSubtreeRange.end.offset - flatSubtreeRange.start.offset;\n\n\t\t// Clone the whole contents.\n\t\tfor ( const item of flatSubtreeRange.getItems( { shallow: true } ) ) {\n\t\t\tif ( item.is( 'textProxy' ) ) {\n\t\t\t\twriter.appendText( item.data, item.getAttributes(), frag );\n\t\t\t} else {\n\t\t\t\twriter.append( item._clone( true ), frag );\n\t\t\t}\n\t\t}\n\n\t\t// ## 2nd step\n\t\t//\n\t\t// If the original range wasn't flat, then we need to remove the excess nodes from the both ends of the cloned fragment.\n\t\t//\n\t\t// For example, for the range shown in the 1st step comment, we need to remove these pieces:\n\t\t//\n\t\t// <quote>[<p>y</p>]<h>[fir]st</h></quote><p>se[cond]</p>\n\t\t//\n\t\t// So this will be the final copied content:\n\t\t//\n\t\t// <quote><h>st</h></quote><p>se</p>\n\t\t//\n\t\t// In order to do that, we remove content from these two ranges:\n\t\t//\n\t\t// [<quote><p>y</p><h>fir]st</h></quote><p>se[cond</p>]\n\t\tif ( flatSubtreeRange != range ) {\n\t\t\t// Find the position of the original range in the cloned fragment.\n\t\t\tconst newRange = range._getTransformedByMove( flatSubtreeRange.start, writer.createPositionAt( frag, 0 ), howMany )[ 0 ];\n\n\t\t\tconst leftExcessRange = writer.createRange( writer.createPositionAt( frag, 0 ), newRange.start );\n\t\t\tconst rightExcessRange = writer.createRange( newRange.end, writer.createPositionAt( frag, 'end' ) );\n\n\t\t\tremoveRangeContent( rightExcessRange, writer );\n\t\t\tremoveRangeContent( leftExcessRange, writer );\n\t\t}\n\n\t\treturn frag;\n\t} );\n}\n\n// After https://github.com/ckeditor/ckeditor5-engine/issues/690 is fixed,\n// this function will, most likely, be able to rewritten using getMinimalFlatRanges().\nfunction removeRangeContent( range, writer ) {\n\tconst parentsToCheck = [];\n\n\tArray.from( range.getItems( { direction: 'backward' } ) )\n\t\t// We should better store ranges because text proxies will lose integrity\n\t\t// with the text nodes when we'll start removing content.\n\t\t.map( item => writer.createRangeOn( item ) )\n\t\t// Filter only these items which are fully contained in the passed range.\n\t\t//\n\t\t// E.g. for the following range: [<quote><p>y</p><h>fir]st</h>\n\t\t// the walker will return the entire <h> element, when only the \"fir\" item inside it is fully contained.\n\t\t.filter( itemRange => {\n\t\t\t// We should be able to use Range.containsRange, but https://github.com/ckeditor/ckeditor5-engine/issues/691.\n\t\t\tconst contained =\n\t\t\t\t( itemRange.start.isAfter( range.start ) || itemRange.start.isEqual( range.start ) ) &&\n\t\t\t\t( itemRange.end.isBefore( range.end ) || itemRange.end.isEqual( range.end ) );\n\n\t\t\treturn contained;\n\t\t} )\n\t\t.forEach( itemRange => {\n\t\t\tparentsToCheck.push( itemRange.start.parent );\n\n\t\t\twriter.remove( itemRange );\n\t\t} );\n\n\t// Remove ancestors of the removed items if they turned to be empty now\n\t// (their whole content was contained in the range).\n\tparentsToCheck.forEach( parentToCheck => {\n\t\tlet parent = parentToCheck;\n\n\t\twhile ( parent.parent && parent.isEmpty ) {\n\t\t\tconst removeRange = writer.createRangeOn( parent );\n\n\t\t\tparent = parent.parent;\n\n\t\t\twriter.remove( removeRange );\n\t\t}\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/utils/selection-post-fixer\n */\n\nimport Range from '../range';\nimport Position from '../position';\n\n/**\n * Injects selection post-fixer to the model.\n *\n * The role of the selection post-fixer is to ensure that the selection is in a correct place\n * after a {@link module:engine/model/model~Model#change `change()`} block was executed.\n *\n * The correct position means that:\n *\n * * All collapsed selection ranges are in a place where the {@link module:engine/model/schema~Schema}\n * allows a `$text`.\n * * None of the selection's non-collapsed ranges crosses a {@link module:engine/model/schema~Schema#isLimit limit element}\n * boundary (a range must be rooted within one limit element).\n * * Only {@link module:engine/model/schema~Schema#isObject object elements} can be selected from the outside\n * (e.g. `[<paragraph>foo</paragraph>]` is invalid). This rule applies independently to both selection ends, so this\n * selection is correct: `<paragraph>f[oo</paragraph><image></image>]`.\n *\n * If the position is not correct, the post-fixer will automatically correct it.\n *\n * ## Fixing a non-collapsed selection\n *\n * See as an example a selection that starts in a P1 element and ends inside the text of a TD element\n * (`[` and `]` are range boundaries and `(l)` denotes an element defined as `isLimit=true`):\n *\n *\t\troot\n *\t\t |- element P1\n *\t\t | |- \"foo\" root\n *\t\t |- element TABLE (l) P1 TABLE P2\n *\t\t | |- element TR (l) f o[o TR TR b a r\n *\t\t | | |- element TD (l) TD TD\n *\t\t | | |- \"aaa\" a]a a b b b\n *\t\t | |- element TR (l)\n *\t\t | | |- element TD (l) ||\n *\t\t | | |- \"bbb\" ||\n *\t\t |- element P2 VV\n *\t\t | |- \"bar\"\n *\t\t root\n *\t\t P1 TABLE] P2\n *\t\t f o[o TR TR b a r\n *\t\t TD TD\n *\t\t a a a b b b\n *\n * In the example above, the TABLE, TR and TD are defined as `isLimit=true` in the schema. The range which is not contained within\n * a single limit element must be expanded to select the outermost limit element. The range end is inside the text node of the TD element.\n * As the TD element is a child of the TR and TABLE elements, where both are defined as `isLimit=true` in the schema, the range must be\n * expanded to select the whole TABLE element.\n *\n * **Note** If the selection contains multiple ranges, the method returns a minimal set of ranges that are not intersecting after expanding\n * them to select `isLimit=true` elements.\n *\n * @param {module:engine/model/model~Model} model\n */\nexport function injectSelectionPostFixer( model ) {\n\tmodel.document.registerPostFixer( writer => selectionPostFixer( writer, model ) );\n}\n\n// The selection post-fixer.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/model~Model} model\nfunction selectionPostFixer( writer, model ) {\n\tconst selection = model.document.selection;\n\tconst schema = model.schema;\n\n\tconst ranges = [];\n\n\tlet wasFixed = false;\n\n\tfor ( const modelRange of selection.getRanges() ) {\n\t\t// Go through all ranges in selection and try fixing each of them.\n\t\t// Those ranges might overlap but will be corrected later.\n\t\tconst correctedRange = tryFixingRange( modelRange, schema );\n\n\t\tif ( correctedRange ) {\n\t\t\tranges.push( correctedRange );\n\t\t\twasFixed = true;\n\t\t} else {\n\t\t\tranges.push( modelRange );\n\t\t}\n\t}\n\n\t// If any of ranges were corrected update the selection.\n\tif ( wasFixed ) {\n\t\t// The above algorithm might create ranges that intersects each other when selection contains more then one range.\n\t\t// This is case happens mostly on Firefox which creates multiple ranges for selected table.\n\t\tlet fixedRanges = ranges;\n\n\t\t// Fixing selection with many ranges usually breaks the selection in Firefox. As only Firefox supports multiple selection ranges\n\t\t// we simply create one continuous range from fixed selection ranges (even if they are not adjacent).\n\t\tif ( ranges.length > 1 ) {\n\t\t\tconst selectionStart = ranges[ 0 ].start;\n\t\t\tconst selectionEnd = ranges[ ranges.length - 1 ].end;\n\n\t\t\tfixedRanges = [ new Range( selectionStart, selectionEnd ) ];\n\t\t}\n\n\t\twriter.setSelection( fixedRanges, { backward: selection.isBackward } );\n\t}\n}\n\n// Tries fixing a range if it's incorrect.\n//\n// @param {module:engine/model/range~Range} range\n// @param {module:engine/model/schema~Schema} schema\n// @returns {module:engine/model/range~Range|null} Returns fixed range or null if range is valid.\nfunction tryFixingRange( range, schema ) {\n\tif ( range.isCollapsed ) {\n\t\treturn tryFixingCollapsedRange( range, schema );\n\t}\n\n\treturn tryFixingNonCollapsedRage( range, schema );\n}\n\n// Tries to fix collapsed ranges.\n//\n// * Fixes situation when a range is in a place where $text is not allowed\n//\n// @param {module:engine/model/range~Range} range Collapsed range to fix.\n// @param {module:engine/model/schema~Schema} schema\n// @returns {module:engine/model/range~Range|null} Returns fixed range or null if range is valid.\nfunction tryFixingCollapsedRange( range, schema ) {\n\tconst originalPosition = range.start;\n\n\tconst nearestSelectionRange = schema.getNearestSelectionRange( originalPosition );\n\n\t// This might be null ie when editor data is empty.\n\t// In such cases there is no need to fix the selection range.\n\tif ( !nearestSelectionRange ) {\n\t\treturn null;\n\t}\n\n\tconst fixedPosition = nearestSelectionRange.start;\n\n\t// Fixed position is the same as original - no need to return corrected range.\n\tif ( originalPosition.isEqual( fixedPosition ) ) {\n\t\treturn null;\n\t}\n\n\t// Check single node selection (happens in tables).\n\tif ( fixedPosition.nodeAfter && schema.isLimit( fixedPosition.nodeAfter ) ) {\n\t\treturn new Range( fixedPosition, Position._createAfter( fixedPosition.nodeAfter ) );\n\t}\n\n\treturn new Range( fixedPosition );\n}\n\n// Tries to fix an expanded range.\n//\n// @param {module:engine/model/range~Range} range Expanded range to fix.\n// @param {module:engine/model/schema~Schema} schema\n// @returns {module:engine/model/range~Range|null} Returns fixed range or null if range is valid.\nfunction tryFixingNonCollapsedRage( range, schema ) {\n\tconst start = range.start;\n\tconst end = range.end;\n\n\tconst isTextAllowedOnStart = schema.checkChild( start, '$text' );\n\tconst isTextAllowedOnEnd = schema.checkChild( end, '$text' );\n\n\tconst startLimitElement = schema.getLimitElement( start );\n\tconst endLimitElement = schema.getLimitElement( end );\n\n\t// Ranges which both end are inside the same limit element (or root) might needs only minor fix.\n\tif ( startLimitElement === endLimitElement ) {\n\t\t// Range is valid when both position allows to place a text:\n\t\t// - <block>f[oobarba]z</block>\n\t\t// This would be \"fixed\" by a next check but as it will be the same it's better to return null so the selection stays the same.\n\t\tif ( isTextAllowedOnStart && isTextAllowedOnEnd ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Range that is on non-limit element (or is partially) must be fixed so it is placed inside the block around $text:\n\t\t// - [<block>foo</block>] -> <block>[foo]</block>\n\t\t// - [<block>foo]</block> -> <block>[foo]</block>\n\t\t// - <block>f[oo</block>] -> <block>f[oo]</block>\n\t\t// - [<block>foo</block><object></object>] -> <block>[foo</block><object></object>]\n\t\tif ( checkSelectionOnNonLimitElements( start, end, schema ) ) {\n\t\t\tconst isStartObject = start.nodeAfter && schema.isObject( start.nodeAfter );\n\t\t\tconst fixedStart = isStartObject ? null : schema.getNearestSelectionRange( start, 'forward' );\n\n\t\t\tconst isEndObject = end.nodeBefore && schema.isObject( end.nodeBefore );\n\t\t\tconst fixedEnd = isEndObject ? null : schema.getNearestSelectionRange( end, 'backward' );\n\n\t\t\t// The schema.getNearestSelectionRange might return null - if that happens use original position.\n\t\t\tconst rangeStart = fixedStart ? fixedStart.start : start;\n\t\t\tconst rangeEnd = fixedEnd ? fixedEnd.start : end;\n\n\t\t\treturn new Range( rangeStart, rangeEnd );\n\t\t}\n\t}\n\n\tconst isStartInLimit = startLimitElement && !startLimitElement.is( 'rootElement' );\n\tconst isEndInLimit = endLimitElement && !endLimitElement.is( 'rootElement' );\n\n\t// At this point we eliminated valid positions on text nodes so if one of range positions is placed inside a limit element\n\t// then the range crossed limit element boundaries and needs to be fixed.\n\tif ( isStartInLimit || isEndInLimit ) {\n\t\tconst bothInSameParent = ( start.nodeAfter && end.nodeBefore ) && start.nodeAfter.parent === end.nodeBefore.parent;\n\n\t\tconst expandStart = isStartInLimit && ( !bothInSameParent || !isInObject( start.nodeAfter, schema ) );\n\t\tconst expandEnd = isEndInLimit && ( !bothInSameParent || !isInObject( end.nodeBefore, schema ) );\n\n\t\t// Although we've already found limit element on start/end positions we must find the outer-most limit element.\n\t\t// as limit elements might be nested directly inside (ie table > tableRow > tableCell).\n\t\tlet fixedStart = start;\n\t\tlet fixedEnd = end;\n\n\t\tif ( expandStart ) {\n\t\t\tfixedStart = Position._createBefore( findOutermostLimitAncestor( startLimitElement, schema ) );\n\t\t}\n\n\t\tif ( expandEnd ) {\n\t\t\tfixedEnd = Position._createAfter( findOutermostLimitAncestor( endLimitElement, schema ) );\n\t\t}\n\n\t\treturn new Range( fixedStart, fixedEnd );\n\t}\n\n\t// Range was not fixed at this point so it is valid - ie it was placed around limit element already.\n\treturn null;\n}\n\n// Finds the outer-most ancestor.\n//\n// @param {module:engine/model/node~Node} startingNode\n// @param {module:engine/model/schema~Schema} schema\n// @param {String} expandToDirection Direction of expansion - either 'start' or 'end' of the range.\n// @returns {module:engine/model/node~Node}\nfunction findOutermostLimitAncestor( startingNode, schema ) {\n\tlet isLimitNode = startingNode;\n\tlet parent = isLimitNode;\n\n\t// Find outer most isLimit block as such blocks might be nested (ie. in tables).\n\twhile ( schema.isLimit( parent ) && parent.parent ) {\n\t\tisLimitNode = parent;\n\t\tparent = parent.parent;\n\t}\n\n\treturn isLimitNode;\n}\n\n// Checks whether any of range boundaries is placed around non-limit elements.\n//\n// @param {module:engine/model/position~Position} start\n// @param {module:engine/model/position~Position} end\n// @param {module:engine/model/schema~Schema} schema\n// @returns {Boolean}\nfunction checkSelectionOnNonLimitElements( start, end, schema ) {\n\tconst startIsOnBlock = ( start.nodeAfter && !schema.isLimit( start.nodeAfter ) ) || schema.checkChild( start, '$text' );\n\tconst endIsOnBlock = ( end.nodeBefore && !schema.isLimit( end.nodeBefore ) ) || schema.checkChild( end, '$text' );\n\n\t// We should fix such selection when one of those nodes needs fixing.\n\treturn startIsOnBlock || endIsOnBlock;\n}\n\n// Checks if node exists and if it's an object.\n//\n// @param {module:engine/model/node~Node} node\n// @param {module:engine/model/schema~Schema} schema\n// @returns {Boolean}\nfunction isInObject( node, schema ) {\n\treturn node && schema.isObject( node );\n}\n\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/model\n */\n\nimport Batch from './batch';\nimport Writer from './writer';\nimport Schema from './schema';\nimport Document from './document';\nimport MarkerCollection from './markercollection';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport ModelElement from './element';\nimport ModelRange from './range';\nimport ModelPosition from './position';\nimport ModelSelection from './selection';\n\nimport insertContent from './utils/insertcontent';\nimport deleteContent from './utils/deletecontent';\nimport modifySelection from './utils/modifyselection';\nimport getSelectedContent from './utils/getselectedcontent';\nimport { injectSelectionPostFixer } from './utils/selection-post-fixer';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Editor's data model. Read about the model in the\n * {@glink framework/guides/architecture/editing-engine engine architecture guide}.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class Model {\n\tconstructor() {\n\t\t/**\n\t\t * Model's marker collection.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/markercollection~MarkerCollection}\n\t\t */\n\t\tthis.markers = new MarkerCollection();\n\n\t\t/**\n\t\t * Model's document.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/document~Document}\n\t\t */\n\t\tthis.document = new Document( this );\n\n\t\t/**\n\t\t * Model's schema.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/schema~Schema}\n\t\t */\n\t\tthis.schema = new Schema();\n\n\t\t/**\n\t\t * All callbacks added by {@link module:engine/model/model~Model#change} or\n\t\t * {@link module:engine/model/model~Model#enqueueChange} methods waiting to be executed.\n\t\t *\n\t\t * @private\n\t\t * @type {Array.<Function>}\n\t\t */\n\t\tthis._pendingChanges = [];\n\n\t\t/**\n\t\t * The last created and currently used writer instance.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/writer~Writer}\n\t\t */\n\t\tthis._currentWriter = null;\n\n\t\t[ 'insertContent', 'deleteContent', 'modifySelection', 'getSelectedContent', 'applyOperation' ]\n\t\t\t.forEach( methodName => this.decorate( methodName ) );\n\n\t\t// Adding operation validation with `highest` priority, so it is called before any other feature would like\n\t\t// to do anything with the operation. If the operation has incorrect parameters it should throw on the earliest occasion.\n\t\tthis.on( 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\toperation._validate();\n\t\t}, { priority: 'highest' } );\n\n\t\t// Register some default abstract entities.\n\t\tthis.schema.register( '$root', {\n\t\t\tisLimit: true\n\t\t} );\n\t\tthis.schema.register( '$block', {\n\t\t\tallowIn: '$root',\n\t\t\tisBlock: true\n\t\t} );\n\t\tthis.schema.register( '$text', {\n\t\t\tallowIn: '$block',\n\t\t\tisInline: true\n\t\t} );\n\t\tthis.schema.register( '$clipboardHolder', {\n\t\t\tallowContentOf: '$root',\n\t\t\tisLimit: true\n\t\t} );\n\t\tthis.schema.extend( '$text', { allowIn: '$clipboardHolder' } );\n\n\t\t// An element needed by the `upcastElementToMarker` converter.\n\t\t// This element temporarily represents a marker boundary during the conversion process and is removed\n\t\t// at the end of the conversion. `UpcastDispatcher` or at least `Conversion` class looks like a\n\t\t// better place for this registration but both know nothing about `Schema`.\n\t\tthis.schema.register( '$marker' );\n\t\tthis.schema.addChildCheck( ( context, childDefinition ) => {\n\t\t\tif ( childDefinition.name === '$marker' ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} );\n\n\t\tinjectSelectionPostFixer( this );\n\t}\n\n\t/**\n\t * The `change()` method is the primary way of changing the model. You should use it to modify all document nodes\n\t * (including detached nodes – i.e. nodes not added to the {@link module:engine/model/model~Model#document model document}),\n\t * the {@link module:engine/model/document~Document#selection document's selection}, and\n\t * {@link module:engine/model/model~Model#markers model markers}.\n\t *\n\t *\t\tmodel.change( writer => {\n\t *\t\t\twriter.insertText( 'foo', paragraph, 'end' );\n\t *\t\t} );\n\t *\n\t * All changes inside the change block use the same {@link module:engine/model/batch~Batch} so they are combined\n\t * into a single undo step.\n\t *\n\t *\t\tmodel.change( writer => {\n\t *\t\t\twriter.insertText( 'foo', paragraph, 'end' ); // foo.\n\t *\n\t *\t\t\tmodel.change( writer => {\n\t *\t\t\t\twriter.insertText( 'bar', paragraph, 'end' ); // foobar.\n\t *\t\t\t} );\n\t *\n\t * \t\t\twriter.insertText( 'bom', paragraph, 'end' ); // foobarbom.\n\t *\t\t} );\n\t *\n\t * The callback of the `change()` block is executed synchronously.\n\t *\n\t * You can also return a value from the change block.\n\t *\n\t *\t\tconst img = model.change( writer => {\n\t *\t\t\treturn writer.createElement( 'img' );\n\t *\t\t} );\n\t *\n\t * @see #enqueueChange\n\t * @param {Function} callback Callback function which may modify the model.\n\t * @returns {*} Value returned by the callback.\n\t */\n\tchange( callback ) {\n\t\ttry {\n\t\t\tif ( this._pendingChanges.length === 0 ) {\n\t\t\t\t// If this is the outermost block, create a new batch and start `_runPendingChanges` execution flow.\n\t\t\t\tthis._pendingChanges.push( { batch: new Batch(), callback } );\n\n\t\t\t\treturn this._runPendingChanges()[ 0 ];\n\t\t\t} else {\n\t\t\t\t// If this is not the outermost block, just execute the callback.\n\t\t\t\treturn callback( this._currentWriter );\n\t\t\t}\n\t\t} catch ( err ) {\n\t\t\tCKEditorError.rethrowUnexpectedError( err, this );\n\t\t}\n\t}\n\n\t/**\n\t * The `enqueueChange()` method performs similar task as the {@link #change `change()` method}, with two major differences.\n\t *\n\t * First, the callback of `enqueueChange()` is executed when all other enqueued changes are done. It might be executed\n\t * immediately if it is not nested in any other change block, but if it is nested in another (enqueue)change block,\n\t * it will be delayed and executed after the outermost block.\n\t *\n\t *\t\tmodel.change( writer => {\n\t *\t\t\tconsole.log( 1 );\n\t *\n\t *\t\t\tmodel.enqueueChange( writer => {\n\t *\t\t\t\tconsole.log( 2 );\n\t *\t\t\t} );\n\t *\n\t * \t\t\tconsole.log( 3 );\n\t *\t\t} ); // Will log: 1, 3, 2.\n\t *\n\t * Second, it lets you define the {@link module:engine/model/batch~Batch} into which you want to add your changes.\n\t * By default, a new batch is created. In the sample above, `change` and `enqueueChange` blocks use a different\n\t * batch (and different {@link module:engine/model/writer~Writer} since each of them operates on the separate batch).\n\t *\n\t * When using the `enqueueChange()` block you can also add some changes to the batch you used before.\n\t *\n\t *\t\tmodel.enqueueChange( batch, writer => {\n\t *\t\t\twriter.insertText( 'foo', paragraph, 'end' );\n\t *\t\t} );\n\t *\n\t * The batch instance can be obtained from {@link module:engine/model/writer~Writer#batch the writer}.\n\t *\n\t * @param {module:engine/model/batch~Batch|'transparent'|'default'} batchOrType Batch or batch type should be used in the callback.\n\t * If not defined, a new batch will be created.\n\t * @param {Function} callback Callback function which may modify the model.\n\t */\n\tenqueueChange( batchOrType, callback ) {\n\t\ttry {\n\t\t\tif ( typeof batchOrType === 'string' ) {\n\t\t\t\tbatchOrType = new Batch( batchOrType );\n\t\t\t} else if ( typeof batchOrType == 'function' ) {\n\t\t\t\tcallback = batchOrType;\n\t\t\t\tbatchOrType = new Batch();\n\t\t\t}\n\n\t\t\tthis._pendingChanges.push( { batch: batchOrType, callback } );\n\n\t\t\tif ( this._pendingChanges.length == 1 ) {\n\t\t\t\tthis._runPendingChanges();\n\t\t\t}\n\t\t} catch ( err ) {\n\t\t\tCKEditorError.rethrowUnexpectedError( err, this );\n\t\t}\n\t}\n\n\t/**\n\t * {@link module:utils/observablemixin~ObservableMixin#decorate Decorated} function for applying\n\t * {@link module:engine/model/operation/operation~Operation operations} to the model.\n\t *\n\t * This is a low-level way of changing the model. It is exposed for very specific use cases (like the undo feature).\n\t * Normally, to modify the model, you will want to use {@link module:engine/model/writer~Writer `Writer`}.\n\t * See also {@glink framework/guides/architecture/editing-engine#changing-the-model Changing the model} section\n\t * of the {@glink framework/guides/architecture/editing-engine Editing architecture} guide.\n\t *\n\t * @param {module:engine/model/operation/operation~Operation} operation The operation to apply.\n\t */\n\tapplyOperation( operation ) {\n\t\toperation._execute();\n\t}\n\n\t/**\n\t * Inserts content at the position in the editor specified by the selection, as one would expect the paste\n\t * functionality to work.\n\t *\n\t * This is a high-level method. It takes the {@link #schema schema} into consideration when inserting\n\t * the content, clears the given selection's content before inserting nodes and moves the selection\n\t * to its target position at the end of the process.\n\t * It can split elements, merge them, wrap bare text nodes with paragraphs, etc. &mdash; just like the\n\t * pasting feature should do.\n\t *\n\t * For lower-level methods see {@link module:engine/model/writer~Writer `Writer`}.\n\t *\n\t * This method, unlike {@link module:engine/model/writer~Writer `Writer`}'s methods, does not have to be used\n\t * inside a {@link #change `change()` block}.\n\t *\n\t * # Conversion and schema\n\t *\n\t * Inserting elements and text nodes into the model is not enough to make CKEditor 5 render that content\n\t * to the user. CKEditor 5 implements a model-view-controller architecture and what `model.insertContent()` does\n\t * is only adding nodes to the model. Additionally, you need to define\n\t * {@glink framework/guides/architecture/editing-engine#conversion converters} between the model and view\n\t * and define those nodes in the {@glink framework/guides/architecture/editing-engine#schema schema}.\n\t *\n\t * So, while this method may seem similar to CKEditor 4 `editor.insertHtml()` (in fact, both methods\n\t * are used for paste-like content insertion), the CKEditor 5 method cannot be use to insert arbitrary HTML\n\t * unless converters are defined for all elements and attributes in that HTML.\n\t *\n\t * # Examples\n\t *\n\t * Using `insertContent()` with a manually created model structure:\n\t *\n\t *\t\t// Let's create a document fragment containing such content as:\n\t *\t\t//\n\t *\t\t// <paragrap>foo</paragraph>\n\t *\t\t// <blockQuote>\n\t *\t\t// <paragraph>bar</paragraph>\n\t *\t\t// </blockQuote>\n\t *\t\tconst docFrag = editor.model.change( writer => {\n\t *\t\t\tconst p1 = writer.createElement( 'paragraph' );\n\t *\t\t\tconst p2 = writer.createElement( 'paragraph' );\n\t *\t\t\tconst blockQuote = writer.createElement( 'blockQuote' );\n\t *\t\t\tconst docFrag = writer.createDocumentFragment();\n\t *\n\t *\t\t\twriter.append( p1, docFrag );\n\t *\t\t\twriter.append( blockQuote, docFrag );\n\t *\t\t\twriter.append( p2, blockQuote );\n\t *\t\t\twriter.insertText( 'foo', p1 );\n\t *\t\t\twriter.insertText( 'bar', p2 );\n\t *\n\t *\t\t\treturn docFrag;\n\t *\t\t} );\n\t *\n\t *\t\t// insertContent() does not have to be used in a change() block. It can, though,\n\t *\t\t// so this code could be moved to the callback defined above.\n\t *\t\teditor.model.insertContent( docFrag );\n\t *\n\t * Using `insertContent()` with an HTML string converted to a model document fragment (similar to the pasting mechanism):\n\t *\n\t *\t\t// You can create your own HtmlDataProcessor instance or use editor.data.processor\n\t *\t\t// if you have not overridden the default one (which is the HtmlDataProcessor instance).\n\t *\t\tconst htmlDP = new HtmlDataProcessor();\n\t *\n\t *\t\t// Convert an HTML string to a view document fragment:\n\t *\t\tconst viewFragment = htmlDP.toView( htmlString );\n\t *\n\t *\t\t// Convert the view document fragment to a model document fragment\n\t *\t\t// in the context of $root. This conversion takes the schema into\n\t *\t\t// account so if, for example, the view document fragment contained a bare text node,\n\t *\t\t// this text node cannot be a child of $root, so it will be automatically\n\t *\t\t// wrapped with a <paragraph>. You can define the context yourself (in the second parameter),\n\t *\t\t// and e.g. convert the content like it would happen in a <paragraph>.\n\t *\t\t// Note: The clipboard feature uses a custom context called $clipboardHolder\n\t *\t\t// which has a loosened schema.\n\t *\t\tconst modelFragment = editor.data.toModel( viewFragment );\n\t *\n\t *\t\teditor.model.insertContent( modelFragment );\n\t *\n\t * By default this method will use the document selection but it can also be used with a position, range or selection instance.\n\t *\n\t *\t\t// Insert text at the current document selection position.\n\t *\t\teditor.model.change( writer => {\n\t *\t\t\teditor.model.insertContent( writer.createText( 'x' ) );\n\t *\t\t} );\n\t *\n\t *\t\t// Insert text at a given position - the document selection will not be modified.\n\t *\t\teditor.model.change( writer => {\n\t *\t\t\teditor.model.insertContent( writer.createText( 'x' ), doc.getRoot(), 2 );\n\t *\n\t *\t\t\t// Which is a shorthand for:\n\t *\t\t\teditor.model.insertContent( writer.createText( 'x' ), writer.createPositionAt( doc.getRoot(), 2 ) );\n\t *\t\t} );\n\t *\n\t * If an instance of {@link module:engine/model/selection~Selection} is passed as `selectable`\n\t * it will be moved to the target position (where the document selection should be moved after the insertion).\n\t *\n\t *\t\teditor.model.change( writer => {\n\t *\t\t\t// Insert text replacing the given selection instance.\n\t *\t\t\tconst selection = writer.createSelection( paragraph, 'in' );\n\t *\n\t *\t\t\teditor.model.insertContent( writer.createText( 'x' ), selection );\n\t *\n\t *\t\t\t// insertContent() modifies the passed selection instance so it can be used to set the document selection.\n\t *\t\t\t// Note: This is not necessary when you passed the document selection to insertContent().\n\t *\t\t\twriter.setSelection( selection );\n\t *\t\t} );\n\t *\n\t * @fires insertContent\n\t * @param {module:engine/model/documentfragment~DocumentFragment|module:engine/model/item~Item} content The content to insert.\n\t * @param {module:engine/model/selection~Selectable} [selectable=model.document.selection]\n\t * The selection into which the content should be inserted. If not provided the current model document selection will be used.\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] To be used when a model item was passed as `selectable`.\n\t * This param defines a position in relation to that item.\n\t * @returns {module:engine/model/range~Range} Range which contains all the performed changes. This is a range that, if removed,\n\t * would return the model to the state before the insertion. If no changes were preformed by `insertContent`, returns a range collapsed\n\t * at the insertion position.\n\t */\n\tinsertContent( content, selectable, placeOrOffset ) {\n\t\treturn insertContent( this, content, selectable, placeOrOffset );\n\t}\n\n\t/**\n\t * Deletes content of the selection and merge siblings. The resulting selection is always collapsed.\n\t *\n\t * **Note:** For the sake of predictability, the resulting selection should always be collapsed.\n\t * In cases where a feature wants to modify deleting behavior so selection isn't collapsed\n\t * (e.g. a table feature may want to keep row selection after pressing <kbd>Backspace</kbd>),\n\t * then that behavior should be implemented in the view's listener. At the same time, the table feature\n\t * will need to modify this method's behavior too, e.g. to \"delete contents and then collapse\n\t * the selection inside the last selected cell\" or \"delete the row and collapse selection somewhere near\".\n\t * That needs to be done in order to ensure that other features which use `deleteContent()` will work well with tables.\n\t *\n\t * @fires deleteContent\n\t * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n\t * Selection of which the content should be deleted.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.leaveUnmerged=false] Whether to merge elements after removing the content of the selection.\n\t *\n\t * For example `<heading1>x[x</heading1><paragraph>y]y</paragraph>` will become:\n\t *\n\t * * `<heading1>x^y</heading1>` with the option disabled (`leaveUnmerged == false`)\n\t * * `<heading1>x^</heading1><paragraph>y</paragraph>` with enabled (`leaveUnmerged == true`).\n\t *\n\t * Note: {@link module:engine/model/schema~Schema#isObject object} and {@link module:engine/model/schema~Schema#isLimit limit}\n\t * elements will not be merged.\n\t *\n\t * @param {Boolean} [options.doNotResetEntireContent=false] Whether to skip replacing the entire content with a\n\t * paragraph when the entire content was selected.\n\t *\n\t * For example `<heading1>[x</heading1><paragraph>y]</paragraph>` will become:\n\t *\n\t * * `<paragraph>^</paragraph>` with the option disabled (`doNotResetEntireContent == false`)\n\t * * `<heading1>^</heading1>` with enabled (`doNotResetEntireContent == true`)\n\t *\n\t * @param {Boolean} [options.doNotAutoparagraph=false] Whether to create a paragraph if after content deletion selection is moved\n\t * to a place where text cannot be inserted.\n\t *\n\t * For example `<paragraph>x</paragraph>[<image src=\"foo.jpg\"></image>]` will become:\n\t *\n\t * * `<paragraph>x</paragraph><paragraph>[]</paragraph>` with the option disabled (`doNotAutoparagraph == false`)\n\t * * `<paragraph>x[]</paragraph>` with the option enabled (`doNotAutoparagraph == true`).\n\t *\n\t * **Note:** if there is no valid position for the selection, the paragraph will always be created:\n\t *\n\t * `[<image src=\"foo.jpg\"></image>]` -> `<paragraph>[]</paragraph>`.\n\t */\n\tdeleteContent( selection, options ) {\n\t\tdeleteContent( this, selection, options );\n\t}\n\n\t/**\n\t * Modifies the selection. Currently, the supported modifications are:\n\t *\n\t * * Extending. The selection focus is moved in the specified `options.direction` with a step specified in `options.unit`.\n\t * Possible values for `unit` are:\n\t * * `'character'` (default) - moves selection by one user-perceived character. In most cases this means moving by one\n\t * character in `String` sense. However, unicode also defines \"combing marks\". These are special symbols, that combines\n\t * with a symbol before it (\"base character\") to create one user-perceived character. For example, `q̣̇` is a normal\n\t * letter `q` with two \"combining marks\": upper dot (`Ux0307`) and lower dot (`Ux0323`). For most actions, i.e. extending\n\t * selection by one position, it is correct to include both \"base character\" and all of it's \"combining marks\". That is\n\t * why `'character'` value is most natural and common method of modifying selection.\n\t * * `'codePoint'` - moves selection by one unicode code point. In contrary to, `'character'` unit, this will insert\n\t * selection between \"base character\" and \"combining mark\", because \"combining marks\" have their own unicode code points.\n\t * However, for technical reasons, unicode code points with values above `UxFFFF` are represented in native `String` by\n\t * two characters, called \"surrogate pairs\". Halves of \"surrogate pairs\" have a meaning only when placed next to each other.\n\t * For example `𨭎` is represented in `String` by `\\uD862\\uDF4E`. Both `\\uD862` and `\\uDF4E` do not have any meaning\n\t * outside the pair (are rendered as ? when alone). Position between them would be incorrect. In this case, selection\n\t * extension will include whole \"surrogate pair\".\n\t * * `'word'` - moves selection by a whole word.\n\t *\n\t * **Note:** if you extend a forward selection in a backward direction you will in fact shrink it.\n\t *\n\t * @fires modifySelection\n\t * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n\t * The selection to modify.\n\t * @param {Object} [options]\n\t * @param {'forward'|'backward'} [options.direction='forward'] The direction in which the selection should be modified.\n\t * @param {'character'|'codePoint'|'word'} [options.unit='character'] The unit by which selection should be modified.\n\t */\n\tmodifySelection( selection, options ) {\n\t\tmodifySelection( this, selection, options );\n\t}\n\n\t/**\n\t * Gets a clone of the selected content.\n\t *\n\t * For example, for the following selection:\n\t *\n\t * ```html\n\t * <paragraph>x</paragraph>\n\t * <blockQuote>\n\t *\t<paragraph>y</paragraph>\n\t *\t<heading1>fir[st</heading1>\n\t * </blockQuote>\n\t * <paragraph>se]cond</paragraph>\n\t * <paragraph>z</paragraph>\n\t * ```\n\t *\n\t * It will return a document fragment with such a content:\n\t *\n\t * ```html\n\t * <blockQuote>\n\t *\t<heading1>st</heading1>\n\t * </blockQuote>\n\t * <paragraph>se</paragraph>\n\t * ```\n\t *\n\t * @fires getSelectedContent\n\t * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n\t * The selection of which content will be returned.\n\t * @returns {module:engine/model/documentfragment~DocumentFragment}\n\t */\n\tgetSelectedContent( selection ) {\n\t\treturn getSelectedContent( this, selection );\n\t}\n\n\t/**\n\t * Checks whether the given {@link module:engine/model/range~Range range} or\n\t * {@link module:engine/model/element~Element element} has any meaningful content.\n\t *\n\t * Meaningful content is:\n\t *\n\t * * any text node (`options.ignoreWhitespaces` allows controlling whether this text node must also contain\n\t * any non-whitespace characters),\n\t * * or any {@link module:engine/model/schema~Schema#isObject object element},\n\t * * or any {@link module:engine/model/markercollection~Marker marker} which\n\t * {@link module:engine/model/markercollection~Marker#_affectsData affects data}.\n\t *\n\t * This means that a range containing an empty `<paragraph></paragraph>` is not considered to have a meaningful content.\n\t * However, a range containing an `<image></image>` (which would normally be marked in the schema as an object element)\n\t * is considered non-empty.\n\t *\n\t * @param {module:engine/model/range~Range|module:engine/model/element~Element} rangeOrElement Range or element to check.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.ignoreWhitespaces] Whether text node with whitespaces only should be considered empty.\n\t * @returns {Boolean}\n\t */\n\thasContent( rangeOrElement, options ) {\n\t\tconst range = rangeOrElement instanceof ModelElement ? ModelRange._createIn( rangeOrElement ) : rangeOrElement;\n\n\t\tif ( range.isCollapsed ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if there are any markers which affects data in this given range.\n\t\tfor ( const intersectingMarker of this.markers.getMarkersIntersectingRange( range ) ) {\n\t\t\tif ( intersectingMarker.affectsData ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tconst { ignoreWhitespaces = false } = options || {};\n\n\t\tfor ( const item of range.getItems() ) {\n\t\t\tif ( item.is( 'textProxy' ) ) {\n\t\t\t\tif ( !ignoreWhitespaces ) {\n\t\t\t\t\treturn true;\n\t\t\t\t} else if ( item.data.search( /\\S/ ) !== -1 ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t} else if ( this.schema.isObject( item ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Creates a position from the given root and path in that root.\n\t *\n\t * Note: This method is also available as\n\t * {@link module:engine/model/writer~Writer#createPositionFromPath `Writer#createPositionFromPath()`}.\n\t *\n\t * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} root Root of the position.\n\t * @param {Array.<Number>} path Position path. See {@link module:engine/model/position~Position#path}.\n\t * @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.\n\t * See {@link module:engine/model/position~PositionStickiness}.\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tcreatePositionFromPath( root, path, stickiness ) {\n\t\treturn new ModelPosition( root, path, stickiness );\n\t}\n\n\t/**\n\t * Creates position at the given location. The location can be specified as:\n\t *\n\t * * a {@link module:engine/model/position~Position position},\n\t * * a parent element and offset in that element,\n\t * * a parent element and `'end'` (the position will be set at the end of that element),\n\t * * a {@link module:engine/model/item~Item model item} and `'before'` or `'after'`\n\t * (the position will be set before or after the given model item).\n\t *\n\t * This method is a shortcut to other factory methods such as:\n\t *\n\t * * {@link module:engine/model/model~Model#createPositionBefore `createPositionBefore()`},\n\t * * {@link module:engine/model/model~Model#createPositionAfter `createPositionAfter()`}.\n\t *\n\t * Note: This method is also available as\n\t * {@link module:engine/model/writer~Writer#createPositionAt `Writer#createPositionAt()`},\n\t *\n\t * @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/model/item~Item model item}.\n\t */\n\tcreatePositionAt( itemOrPosition, offset ) {\n\t\treturn ModelPosition._createAt( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Creates a new position after the given {@link module:engine/model/item~Item model item}.\n\t *\n\t * Note: This method is also available as\n\t * {@link module:engine/model/writer~Writer#createPositionAfter `Writer#createPositionAfter()`}.\n\t *\n\t * @param {module:engine/model/item~Item} item Item after which the position should be placed.\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tcreatePositionAfter( item ) {\n\t\treturn ModelPosition._createAfter( item );\n\t}\n\n\t/**\n\t * Creates a new position before the given {@link module:engine/model/item~Item model item}.\n\t *\n\t * Note: This method is also available as\n\t * {@link module:engine/model/writer~Writer#createPositionBefore `Writer#createPositionBefore()`}.\n\t *\n\t * @param {module:engine/model/item~Item} item Item before which the position should be placed.\n\t * @returns {module:engine/model/position~Position}\n\t */\n\tcreatePositionBefore( item ) {\n\t\treturn ModelPosition._createBefore( item );\n\t}\n\n\t/**\n\t * Creates a range spanning from the `start` position to the `end` position.\n\t *\n\t * Note: This method is also available as\n\t * {@link module:engine/model/writer~Writer#createRange `Writer#createRange()`}:\n\t *\n\t *\t\tmodel.change( writer => {\n\t *\t\t\tconst range = writer.createRange( start, end );\n\t *\t\t} );\n\t *\n\t * @param {module:engine/model/position~Position} start Start position.\n\t * @param {module:engine/model/position~Position} [end] End position. If not set, the range will be collapsed\n\t * to the `start` position.\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tcreateRange( start, end ) {\n\t\treturn new ModelRange( start, end );\n\t}\n\n\t/**\n\t * Creates a range inside the given element which starts before the first child of\n\t * that element and ends after the last child of that element.\n\t *\n\t * Note: This method is also available as\n\t * {@link module:engine/model/writer~Writer#createRangeIn `Writer#createRangeIn()`}:\n\t *\n\t *\t\tmodel.change( writer => {\n\t *\t\t\tconst range = writer.createRangeIn( paragraph );\n\t *\t\t} );\n\t *\n\t * @param {module:engine/model/element~Element} element Element which is a parent for the range.\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tcreateRangeIn( element ) {\n\t\treturn ModelRange._createIn( element );\n\t}\n\n\t/**\n\t * Creates a range that starts before the given {@link module:engine/model/item~Item model item} and ends after it.\n\t *\n\t * Note: This method is also available on `writer` instance as\n\t * {@link module:engine/model/writer~Writer#createRangeOn `Writer.createRangeOn()`}:\n\t *\n\t *\t\tmodel.change( writer => {\n\t *\t\t\tconst range = writer.createRangeOn( paragraph );\n\t *\t\t} );\n\t *\n\t * @param {module:engine/model/item~Item} item\n\t * @returns {module:engine/model/range~Range}\n\t */\n\tcreateRangeOn( item ) {\n\t\treturn ModelRange._createOn( item );\n\t}\n\n\t/**\n\t * Creates a new selection instance based on the given {@link module:engine/model/selection~Selectable selectable}\n\t * or creates an empty selection if no arguments were passed.\n\t *\n\t * Note: This method is also available as\n\t * {@link module:engine/model/writer~Writer#createSelection `Writer#createSelection()`}.\n\t *\n\t *\t\t// Creates empty selection without ranges.\n\t *\t\tconst selection = writer.createSelection();\n\t *\n\t *\t\t// Creates selection at the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tconst selection = writer.createSelection( range );\n\t *\n\t *\t\t// Creates selection at the given ranges\n\t *\t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];\n\t *\t\tconst selection = writer.createSelection( ranges );\n\t *\n\t *\t\t// Creates selection from the other selection.\n\t *\t\t// Note: It doesn't copies selection attributes.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tconst selection = writer.createSelection( otherSelection );\n\t *\n\t *\t\t// Creates selection from the given document selection.\n\t *\t\t// Note: It doesn't copies selection attributes.\n\t *\t\tconst documentSelection = model.document.selection;\n\t *\t\tconst selection = writer.createSelection( documentSelection );\n\t *\n\t *\t\t// Creates selection at the given position.\n\t *\t\tconst position = writer.createPositionFromPath( root, path );\n\t *\t\tconst selection = writer.createSelection( position );\n\t *\n\t *\t\t// Creates selection at the given offset in the given element.\n\t *\t\tconst paragraph = writer.createElement( 'paragraph' );\n\t *\t\tconst selection = writer.createSelection( paragraph, offset );\n\t *\n\t *\t\t// Creates a range inside an {@link module:engine/model/element~Element element} which starts before the\n\t *\t\t// first child of that element and ends after the last child of that element.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'in' );\n\t *\n\t *\t\t// Creates a range on an {@link module:engine/model/item~Item item} which starts before the item and ends\n\t *\t\t// just after the item.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'on' );\n\t *\n\t *\t\t// Additional options (`'backward'`) can be specified as the last argument.\n\t *\n\t *\t\t// Creates backward selection.\n\t *\t\tconst selection = writer.createSelection( range, { backward: true } );\n\t *\n\t * @param {module:engine/model/selection~Selectable} selectable\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Sets place or offset of the selection.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @returns {module:engine/model/selection~Selection}\n\t */\n\tcreateSelection( selectable, placeOrOffset, options ) {\n\t\treturn new ModelSelection( selectable, placeOrOffset, options );\n\t}\n\n\t/**\n\t * Creates a {@link module:engine/model/batch~Batch} instance.\n\t *\n\t * **Note:** In most cases creating a batch instance is not necessary as they are created when using:\n\t *\n\t * * {@link #change `change()`},\n\t * * {@link #enqueueChange `enqueueChange()`}.\n\t *\n\t * @param {'transparent'|'default'} [type='default'] The type of the batch.\n\t * @returns {module:engine/model/batch~Batch}\n\t */\n\tcreateBatch( type ) {\n\t\treturn new Batch( type );\n\t}\n\n\t/**\n\t * Removes all events listeners set by model instance and destroys {@link module:engine/model/document~Document}.\n\t */\n\tdestroy() {\n\t\tthis.document.destroy();\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Common part of {@link module:engine/model/model~Model#change} and {@link module:engine/model/model~Model#enqueueChange}\n\t * which calls callbacks and returns array of values returned by these callbacks.\n\t *\n\t * @private\n\t * @returns {Array.<*>} Array of values returned by callbacks.\n\t */\n\t_runPendingChanges() {\n\t\tconst ret = [];\n\n\t\tthis.fire( '_beforeChanges' );\n\n\t\twhile ( this._pendingChanges.length ) {\n\t\t\t// Create a new writer using batch instance created for this chain of changes.\n\t\t\tconst currentBatch = this._pendingChanges[ 0 ].batch;\n\t\t\tthis._currentWriter = new Writer( this, currentBatch );\n\n\t\t\t// Execute changes callback and gather the returned value.\n\t\t\tconst callbackReturnValue = this._pendingChanges[ 0 ].callback( this._currentWriter );\n\t\t\tret.push( callbackReturnValue );\n\n\t\t\tthis.document._handleChangeBlock( this._currentWriter );\n\n\t\t\tthis._pendingChanges.shift();\n\t\t\tthis._currentWriter = null;\n\t\t}\n\n\t\tthis.fire( '_afterChanges' );\n\n\t\treturn ret;\n\t}\n\n\t/**\n\t * Fired when entering the outermost {@link module:engine/model/model~Model#enqueueChange} or\n\t * {@link module:engine/model/model~Model#change} block.\n\t *\n\t * @protected\n\t * @event _beforeChanges\n\t */\n\n\t/**\n\t * Fired when leaving the outermost {@link module:engine/model/model~Model#enqueueChange} or\n\t * {@link module:engine/model/model~Model#change} block.\n\t *\n\t * @protected\n\t * @event _afterChanges\n\t */\n\n\t/**\n\t * Fired every time any {@link module:engine/model/operation/operation~Operation operation} is applied on the model\n\t * using {@link #applyOperation}.\n\t *\n\t * Note that this event is suitable only for very specific use-cases. Use it if you need to listen to every single operation\n\t * applied on the document. However, in most cases {@link module:engine/model/document~Document#event:change} should\n\t * be used.\n\t *\n\t * A few callbacks are already added to this event by engine internal classes:\n\t *\n\t * * with `highest` priority operation is validated,\n\t * * with `normal` priority operation is executed,\n\t * * with `low` priority the {@link module:engine/model/document~Document} updates its version,\n\t * * with `low` priority {@link module:engine/model/liveposition~LivePosition} and {@link module:engine/model/liverange~LiveRange}\n\t * update themselves.\n\t *\n\t * @event applyOperation\n\t * @param {Array} args Arguments of the `applyOperation` which is an array with a single element - applied\n\t * {@link module:engine/model/operation/operation~Operation operation}.\n\t */\n\n\t/**\n\t * Event fired when {@link #insertContent} method is called.\n\t *\n\t * The {@link #insertContent default action of that method} is implemented as a\n\t * listener to this event so it can be fully customized by the features.\n\t *\n\t * **Note** The `selectable` parameter for the {@link #insertContent} is optional. When `undefined` value is passed the method uses\n\t * `model.document.selection`.\n\t *\n\t * @event insertContent\n\t * @param {Array} args The arguments passed to the original method.\n\t */\n\n\t/**\n\t * Event fired when {@link #deleteContent} method is called.\n\t *\n\t * The {@link #deleteContent default action of that method} is implemented as a\n\t * listener to this event so it can be fully customized by the features.\n\t *\n\t * @event deleteContent\n\t * @param {Array} args The arguments passed to the original method.\n\t */\n\n\t/**\n\t * Event fired when {@link #modifySelection} method is called.\n\t *\n\t * The {@link #modifySelection default action of that method} is implemented as a\n\t * listener to this event so it can be fully customized by the features.\n\t *\n\t * @event modifySelection\n\t * @param {Array} args The arguments passed to the original method.\n\t */\n\n\t/**\n\t * Event fired when {@link #getSelectedContent} method is called.\n\t *\n\t * The {@link #getSelectedContent default action of that method} is implemented as a\n\t * listener to this event so it can be fully customized by the features.\n\t *\n\t * @event getSelectedContent\n\t * @param {Array} args The arguments passed to the original method.\n\t */\n}\n\nmix( Model, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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.<String|Number>} 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-2019, 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 core/editingkeystrokehandler\n */\n\nimport KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';\n\n/**\n * A keystroke handler for editor editing. Its instance is available\n * in {@link module:core/editor/editor~Editor#keystrokes} so plugins\n * can register their keystrokes.\n *\n * E.g. an undo plugin would do this:\n *\n *\t\teditor.keystrokes.set( 'Ctrl+Z', 'undo' );\n *\t\teditor.keystrokes.set( 'Ctrl+Shift+Z', 'redo' );\n *\t\teditor.keystrokes.set( 'Ctrl+Y', 'redo' );\n *\n * @extends module:utils/keystrokehandler~KeystrokeHandler\n */\nexport default class EditingKeystrokeHandler extends KeystrokeHandler {\n\t/**\n\t * Creates an instance of the keystroke handler.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor\n\t */\n\tconstructor( editor ) {\n\t\tsuper();\n\n\t\t/**\n\t\t * The editor instance.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/editor/editor~Editor}\n\t\t */\n\t\tthis.editor = editor;\n\t}\n\n\t/**\n\t * Registers a handler for the specified keystroke.\n\t *\n\t * The handler can be specified as a command name or a callback.\n\t *\n\t * @param {String|Array.<String|Number>} keystroke Keystroke defined in a format accepted by\n\t * the {@link module:utils/keyboard~parseKeystroke} function.\n\t * @param {Function|String} callback If a string is passed, then the keystroke will\n\t * {@link module:core/editor/editor~Editor#execute execute a command}.\n\t * If a function, then it will be called with the\n\t * {@link module:engine/view/observer/keyobserver~KeyEventData key event data} object and\n\t * a `cancel()` helper to both `preventDefault()` and `stopPropagation()` of the 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\tif ( typeof callback == 'string' ) {\n\t\t\tconst commandName = callback;\n\n\t\t\tcallback = ( evtData, cancel ) => {\n\t\t\t\tthis.editor.execute( commandName );\n\t\t\t\tcancel();\n\t\t\t};\n\t\t}\n\n\t\tsuper.set( keystroke, callback, options );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 core/editor/editor\n */\n\nimport Config from '@ckeditor/ckeditor5-utils/src/config';\nimport EditingController from '@ckeditor/ckeditor5-engine/src/controller/editingcontroller';\nimport PluginCollection from '../plugincollection';\nimport CommandCollection from '../commandcollection';\nimport Locale from '@ckeditor/ckeditor5-utils/src/locale';\nimport DataController from '@ckeditor/ckeditor5-engine/src/controller/datacontroller';\nimport Conversion from '@ckeditor/ckeditor5-engine/src/conversion/conversion';\nimport Model from '@ckeditor/ckeditor5-engine/src/model/model';\nimport EditingKeystrokeHandler from '../editingkeystrokehandler';\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Class representing a basic, generic editor.\n *\n * Check out the list of its subclasses to learn about specific editor implementations.\n *\n * All editor implementations (like {@link module:editor-classic/classiceditor~ClassicEditor} or\n * {@link module:editor-inline/inlineeditor~InlineEditor}) should extend this class. They can add their\n * own methods and properties.\n *\n * When you are implementing a plugin, then this editor represents the API\n * which your plugin can expect to get when using its {@link module:core/plugin~Plugin#editor} property.\n *\n * This API should be sufficient in order to implement the \"editing\" part of your feature\n * (schema definition, conversion, commands, keystrokes, etc.).\n * It does not define the editor UI, which is available only if the\n * the specific editor implements also the {@link module:core/editor/editorwithui~EditorWithUI} interface\n * (as most editor implementations do).\n *\n * @abstract\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class Editor {\n\t/**\n\t * Creates a new instance of the Editor class.\n\t *\n\t * Usually, not to be used directly. See the static {@link module:core/editor/editor~Editor.create `create()`} method.\n\t *\n\t * @param {Object} [config] The editor config.\n\t */\n\tconstructor( config ) {\n\t\tconst availablePlugins = this.constructor.builtinPlugins;\n\n\t\t/**\n\t\t * Holds all configurations specific to this editor instance.\n\t\t *\n\t\t *\t\teditor.config.get( 'image.toolbar' );\n\t\t *\t\t// -> [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ]\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/config~Config}\n\t\t */\n\t\tthis.config = new Config( config, this.constructor.defaultConfig );\n\n\t\tthis.config.define( 'plugins', availablePlugins );\n\n\t\t/**\n\t\t * The plugins loaded and in use by this editor instance.\n\t\t *\n\t\t *\t\teditor.plugins.get( 'Clipboard' ); // -> instance of the Clipboard plugin.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/plugincollection~PluginCollection}\n\t\t */\n\t\tthis.plugins = new PluginCollection( this, availablePlugins );\n\n\t\t/**\n\t\t * Commands registered to the editor.\n\t\t *\n\t\t * Use the shorthand {@link #execute `editor.execute()`} method to execute commands:\n\t\t *\n\t\t *\t\t// Execute the bold command:\n\t\t *\t\teditor.execute( 'bold' );\n\t\t *\n\t\t *\t\t// Check the state of the bold command:\n\t\t *\t\teditor.commands.get( 'bold' ).value;\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/commandcollection~CommandCollection}\n\t\t */\n\t\tthis.commands = new CommandCollection();\n\n\t\tconst languageConfig = this.config.get( 'language' ) || {};\n\n\t\t/**\n\t\t * @readonly\n\t\t * @member {module:utils/locale~Locale}\n\t\t */\n\t\tthis.locale = new Locale( {\n\t\t\tuiLanguage: typeof languageConfig === 'string' ? languageConfig : languageConfig.ui,\n\t\t\tcontentLanguage: this.config.get( 'language.content' )\n\t\t} );\n\n\t\t/**\n\t\t * Shorthand for {@link module:utils/locale~Locale#t}.\n\t\t *\n\t\t * @see module:utils/locale~Locale#t\n\t\t * @method #t\n\t\t */\n\t\tthis.t = this.locale.t;\n\n\t\t/**\n\t\t * Indicates the editor life-cycle state.\n\t\t *\n\t\t * The editor is in one of the following states:\n\t\t *\n\t\t * * `initializing` - during the editor initialization (before {@link module:core/editor/editor~Editor.create `Editor.create()`})\n\t\t * finished its job,\n\t\t * * `ready` - after the promise returned by the {@link module:core/editor/editor~Editor.create `Editor.create()`}\n\t\t * method is resolved,\n\t\t * * `destroyed` - once the {@link #destroy `editor.destroy()`} method was called.\n\t\t *\n\t\t * @observable\n\t\t * @member {'initializing'|'ready'|'destroyed'} #state\n\t\t */\n\t\tthis.set( 'state', 'initializing' );\n\t\tthis.once( 'ready', () => ( this.state = 'ready' ), { priority: 'high' } );\n\t\tthis.once( 'destroy', () => ( this.state = 'destroyed' ), { priority: 'high' } );\n\n\t\t/**\n\t\t * Defines whether this editor is in read-only mode.\n\t\t *\n\t\t * In read-only mode the editor {@link #commands commands} are disabled so it is not possible\n\t\t * to modify the document by using them. Also, the editable element(s) become non-editable.\n\t\t *\n\t\t * In order to make the editor read-only, you can set this value directly:\n\t\t *\n\t\t *\t\teditor.isReadOnly = true;\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isReadOnly\n\t\t */\n\t\tthis.set( 'isReadOnly', false );\n\n\t\t/**\n\t\t * The editor's model.\n\t\t *\n\t\t * The central point of the editor's abstract data model.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/model~Model}\n\t\t */\n\t\tthis.model = new Model();\n\n\t\t/**\n\t\t * The {@link module:engine/controller/datacontroller~DataController data controller}.\n\t\t * Used e.g. for setting and retrieving editor data.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/controller/datacontroller~DataController}\n\t\t */\n\t\tthis.data = new DataController( this.model );\n\n\t\t/**\n\t\t * The {@link module:engine/controller/editingcontroller~EditingController editing controller}.\n\t\t * Controls user input and rendering the content for editing.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/controller/editingcontroller~EditingController}\n\t\t */\n\t\tthis.editing = new EditingController( this.model );\n\t\tthis.editing.view.document.bind( 'isReadOnly' ).to( this );\n\n\t\t/**\n\t\t * Conversion manager through which you can register model to view and view to model converters.\n\t\t *\n\t\t * See {@link module:engine/conversion/conversion~Conversion}'s documentation to learn how to add converters.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/conversion/conversion~Conversion}\n\t\t */\n\t\tthis.conversion = new Conversion( [ this.editing.downcastDispatcher, this.data.downcastDispatcher ], this.data.upcastDispatcher );\n\t\tthis.conversion.addAlias( 'dataDowncast', this.data.downcastDispatcher );\n\t\tthis.conversion.addAlias( 'editingDowncast', this.editing.downcastDispatcher );\n\n\t\t/**\n\t\t * Instance of the {@link module:core/editingkeystrokehandler~EditingKeystrokeHandler}.\n\t\t *\n\t\t * It allows setting simple keystrokes:\n\t\t *\n\t\t *\t\t// Execute the bold command on Ctrl+E:\n\t\t *\t\teditor.keystrokes.set( 'Ctrl+E', 'bold' );\n\t\t *\n\t\t *\t\t// Execute your own callback:\n\t\t *\t\teditor.keystrokes.set( 'Ctrl+E', ( data, cancel ) => {\n\t\t *\t\t\tconsole.log( data.keyCode );\n\t\t *\n\t\t *\t\t\t// Prevent default (native) action and stop the underlying keydown event\n\t\t *\t\t\t// so no other editor feature will interfere.\n\t\t *\t\t\tcancel();\n\t\t *\t\t} );\n\t\t *\n\t\t * Note: Certain, typing oriented keystrokes (like <kbd>Backspace</kbd> or <kbd>Enter</kbd>) are handled\n\t\t * by low level mechanism and trying to listen to them via the keystroke handler will not work reliably.\n\t\t * To handle those specific keystrokes see the events fired by the\n\t\t * {@link module:engine/view/document~Document editing view document} (`editor.editing.view.document`).\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/editingkeystrokehandler~EditingKeystrokeHandler}\n\t\t */\n\t\tthis.keystrokes = new EditingKeystrokeHandler( this );\n\t\tthis.keystrokes.listenTo( this.editing.view.document );\n\t}\n\n\t/**\n\t * Loads and initializes plugins specified in the config.\n\t *\n\t * @returns {Promise.<module:core/plugin~LoadedPlugins>} A promise which resolves\n\t * once the initialization is completed providing an array of loaded plugins.\n\t */\n\tinitPlugins() {\n\t\tconst config = this.config;\n\t\tconst plugins = config.get( 'plugins' ) || [];\n\t\tconst removePlugins = config.get( 'removePlugins' ) || [];\n\t\tconst extraPlugins = config.get( 'extraPlugins' ) || [];\n\n\t\treturn this.plugins.init( plugins.concat( extraPlugins ), removePlugins );\n\t}\n\n\t/**\n\t * Destroys the editor instance, releasing all resources used by it.\n\t *\n\t * **Note** The editor cannot be destroyed during the initialization phase so if it is called\n\t * while the editor {@link #state is being initialized}, it will wait for the editor initialization before destroying it.\n\t *\n\t * @fires destroy\n\t * @returns {Promise} A promise that resolves once the editor instance is fully destroyed.\n\t */\n\tdestroy() {\n\t\tlet readyPromise = Promise.resolve();\n\n\t\tif ( this.state == 'initializing' ) {\n\t\t\treadyPromise = new Promise( resolve => this.once( 'ready', resolve ) );\n\t\t}\n\n\t\treturn readyPromise\n\t\t\t.then( () => {\n\t\t\t\tthis.fire( 'destroy' );\n\t\t\t\tthis.stopListening();\n\t\t\t\tthis.commands.destroy();\n\t\t\t} )\n\t\t\t.then( () => this.plugins.destroy() )\n\t\t\t.then( () => {\n\t\t\t\tthis.model.destroy();\n\t\t\t\tthis.data.destroy();\n\t\t\t\tthis.editing.destroy();\n\t\t\t\tthis.keystrokes.destroy();\n\t\t\t} );\n\t}\n\n\t/**\n\t * Executes specified command with given parameters.\n\t *\n\t * Shorthand for:\n\t *\n\t *\t\teditor.commands.get( commandName ).execute( ... );\n\t *\n\t * @param {String} commandName Name of command to execute.\n\t * @param {*} [...commandParams] Command parameters.\n\t */\n\texecute( ...args ) {\n\t\ttry {\n\t\t\tthis.commands.execute( ...args );\n\t\t} catch ( err ) {\n\t\t\tCKEditorError.rethrowUnexpectedError( err, this );\n\t\t}\n\t}\n\n\t/**\n\t * Creates and initializes a new editor instance.\n\t *\n\t * This is an abstract method. Every editor type needs to implement its own initialization logic.\n\t *\n\t * See the `create()` methods of the existing editor types to learn how to use them:\n\t *\n\t * * {@link module:editor-classic/classiceditor~ClassicEditor.create `ClassicEditor.create()`}\n\t * * {@link module:editor-balloon/ballooneditor~BalloonEditor.create `BalloonEditor.create()`}\n\t * * {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`}\n\t * * {@link module:editor-inline/inlineeditor~InlineEditor.create `InlineEditor.create()`}\n\t *\n\t * @abstract\n\t * @method module:core/editor/editor~Editor.create\n\t */\n}\n\nmix( Editor, ObservableMixin );\n\n/**\n * Fired when {@link module:engine/controller/datacontroller~DataController#event:ready data} and all additional\n * editor components are ready.\n *\n * Note: This event is most useful for plugin developers. When integrating the editor with your website or\n * application you do not have to listen to `editor#ready` because when the promise returned by the static\n * {@link module:core/editor/editor~Editor.create `Editor.create()`} event is resolved, the editor is already ready.\n * In fact, since the first moment when the editor instance is available to you is inside `then()`'s callback,\n * you cannot even add a listener to the `editor#ready` event.\n *\n * See also the {@link #state `editor.state`} property.\n *\n * @event ready\n */\n\n/**\n * Fired when this editor instance is destroyed. The editor at this point is not usable and this event should be used to\n * perform the clean-up in any plugin.\n *\n *\n * See also the {@link #state `editor.state`} property.\n *\n * @event destroy\n */\n\n/**\n * This error is thrown when a user tries to use a `<textarea>` element to create a non-classic editor in it.\n *\n * Textarea element represents a plain-text and cannot be used as a editable root element with included CKEditor5.\n * Content of an editor should be nicely present to the user and show him how it's going to looks like. Textarea element\n * doesn't support such behavior.\n *\n * Only {@glink builds/guides/overview#classic-editor Classic Editor} has implemented a special system, which\n * **replace** DOM element and load data from it\n * ({@link module:editor-classic/classiceditor~ClassicEditor.create more information}). All other editors\n * use an existing element, load data from it and make this element editable. Details about behaviour of each editor\n * might be found in an associated description of a `create` method of each editor.\n *\n * @error editor-wrong-element\n */\n\n/**\n * An array of plugins built into this editor class.\n * It is used in CKEditor 5 builds to provide a list of plugins which are later automatically initialized\n * during the editor initialization.\n *\n * They will be automatically initialized by the editor, unless listed in `config.removePlugins` and\n * unless `config.plugins` is passed.\n *\n *\t\t// Build some plugins into the editor class first.\n *\t\tClassicEditor.builtinPlugins = [ FooPlugin, BarPlugin ];\n *\n *\t\t// Normally, you need to define config.plugins, but since ClassicEditor.builtinPlugins was\n *\t\t// defined, now you can call create() without any configuration.\n *\t\tClassicEditor\n *\t\t\t.create( sourceElement )\n *\t\t\t.then( editor => {\n *\t\t\t\teditor.plugins.get( FooPlugin ); // -> instance of the Foo plugin\n *\t\t\t\teditor.plugins.get( BarPlugin ); // -> instance of the Bar plugin\n *\t\t\t} );\n *\n *\t\tClassicEditor\n *\t\t\t.create( sourceElement, {\n *\t\t\t\t// Don't initialize this plugins (note: it's defined by a string):\n *\t\t\t\tremovePlugins: [ 'Foo' ]\n *\t\t\t} )\n *\t\t\t.then( editor => {\n *\t\t\t\teditor.plugins.get( FooPlugin ); // -> undefined\n *\t\t\t\teditor.config.get( BarPlugin ); // -> instance of the Bar plugin\n *\t\t\t} );\n *\n *\t\tClassicEditor\n *\t\t\t.create( sourceElement, {\n *\t\t\t\t// Load only this plugin. Can also be define by a string if\n *\t\t\t\t// this plugin was built into the editor class.\n *\t\t\t\tplugins: [ FooPlugin ]\n *\t\t\t} )\n *\t\t\t.then( editor => {\n *\t\t\t\teditor.plugins.get( FooPlugin ); // -> instance of the Foo plugin\n *\t\t\t\teditor.config.get( BarPlugin ); // -> undefined\n *\t\t\t} );\n *\n * See also {@link module:core/editor/editor~Editor.defaultConfig}.\n *\n * @static\n * @member {Array.<Function>} module:core/editor/editor~Editor.builtinPlugins\n */\n\n/**\n * The default config which is built into the editor class.\n * It is used in CKEditor 5 builds to provide the default config options which are later used during editor initialization.\n *\n *\t\tClassicEditor.defaultConfig = {\n *\t\t\tfoo: 1,\n *\t\t\tbar: 2\n *\t\t};\n *\n *\t\tClassicEditor\n *\t\t\t.create( sourceElement )\n *\t\t\t.then( editor => {\n *\t\t\t\teditor.config.get( 'foo' ); // -> 1\n *\t\t\t\teditor.config.get( 'bar' ); // -> 2\n *\t\t\t} );\n *\n *\t\t// The default options can be overridden by the config passed to create().\n *\t\tClassicEditor\n *\t\t\t.create( sourceElement, { bar: 3 } )\n *\t\t\t.then( editor => {\n *\t\t\t\teditor.config.get( 'foo' ); // -> 1\n *\t\t\t\teditor.config.get( 'bar' ); // -> 3\n *\t\t\t} );\n *\n * See also {@link module:core/editor/editor~Editor.builtinPlugins}.\n *\n * @static\n * @member {Object} module:core/editor/editor~Editor.defaultConfig\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 core/editor/utils/dataapimixin\n */\n\n/**\n * Implementation of the {@link module:core/editor/utils/dataapimixin~DataApi}.\n *\n * @mixin DataApiMixin\n * @implements module:core/editor/utils/dataapimixin~DataApi\n */\nconst DataApiMixin = {\n\t/**\n\t * @inheritDoc\n\t */\n\tsetData( data ) {\n\t\tthis.data.set( data );\n\t},\n\n\t/**\n\t * @inheritDoc\n\t */\n\tgetData( options ) {\n\t\treturn this.data.get( options );\n\t}\n};\n\nexport default DataApiMixin;\n\n/**\n * Interface defining editor methods for setting and getting data to and from the editor's main root element\n * using the {@link module:core/editor/editor~Editor#data data pipeline}.\n *\n * This interface is not a part of the {@link module:core/editor/editor~Editor} class because one may want to implement\n * an editor with multiple root elements, in which case the methods for setting and getting data will need to be implemented\n * differently.\n *\n * @interface DataApi\n */\n\n/**\n * Sets the data in the editor.\n *\n *\t\teditor.setData( '<p>This is editor!</p>' );\n *\n * By default the editor accepts HTML. This can be controlled by injecting a different data processor.\n * See the {@glink features/markdown Markdown output} guide for more details.\n *\n * Note: Not only is the format of the data configurable, but the type of the `setData()`'s parameter does not\n * have to be a string either. You can e.g. accept an object or a DOM `DocumentFragment` if you consider this\n * the right format for you.\n *\n * @method #setData\n * @param {String} data Input data.\n */\n\n/**\n * Gets the data from the editor.\n *\n *\t\teditor.getData(); // -> '<p>This is editor!</p>'\n *\n * By default the editor outputs HTML. This can be controlled by injecting a different data processor.\n * See the {@glink features/markdown Markdown output} guide for more details.\n *\n * Note: Not only is the format of the data configurable, but the type of the `getData()`'s return value does not\n * have to be a string either. You can e.g. return an object or a DOM `DocumentFragment` if you consider this\n * the right format for you.\n *\n * @method #getData\n * @param {Object} [options]\n * @param {String} [options.rootName='main'] Root name.\n * @param {String} [options.trim='empty'] Whether returned data should be trimmed. This option is set to `'empty'` by default,\n * which means that whenever editor content is considered empty, an empty string is returned. To turn off trimming\n * use `'none'`. In such cases exact content will be returned (for example `'<p>&nbsp;</p>'` for an empty editor).\n * @returns {String} Output data.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/dataprocessor/basichtmlwriter\n */\n\n/* globals document */\n\n/**\n * Basic HTML writer. It uses the native `innerHTML` property for basic conversion\n * from a document fragment to an HTML string.\n *\n * @implements module:engine/dataprocessor/htmlwriter~HtmlWriter\n */\nexport default class BasicHtmlWriter {\n\t/**\n\t * Returns an HTML string created from the document fragment.\n\t *\n\t * @param {DocumentFragment} fragment\n\t * @returns {String}\n\t */\n\tgetHtml( fragment ) {\n\t\tconst doc = document.implementation.createHTMLDocument( '' );\n\t\tconst container = doc.createElement( 'div' );\n\t\tcontainer.appendChild( fragment );\n\n\t\treturn container.innerHTML;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/dataprocessor/htmldataprocessor\n */\n\n/* globals document, DOMParser */\n\nimport BasicHtmlWriter from './basichtmlwriter';\nimport DomConverter from '../view/domconverter';\n\n/**\n * The HTML data processor class.\n * This data processor implementation uses HTML as input and output data.\n *\n * @implements module:engine/dataprocessor/dataprocessor~DataProcessor\n */\nexport default class HtmlDataProcessor {\n\t/**\n\t * Creates a new instance of the HTML data processor class.\n\t */\n\tconstructor() {\n\t\t/**\n\t\t * A DOM parser instance used to parse an HTML string to an HTML document.\n\t\t *\n\t\t * @private\n\t\t * @member {DOMParser}\n\t\t */\n\t\tthis._domParser = new DOMParser();\n\n\t\t/**\n\t\t * A DOM converter used to convert DOM elements to view elements.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/view/domconverter~DomConverter}\n\t\t */\n\t\tthis._domConverter = new DomConverter( { blockFillerMode: 'nbsp' } );\n\n\t\t/**\n\t\t * A basic HTML writer instance used to convert DOM elements to an HTML string.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/dataprocessor/basichtmlwriter~BasicHtmlWriter}\n\t\t */\n\t\tthis._htmlWriter = new BasicHtmlWriter();\n\t}\n\n\t/**\n\t * Converts a provided {@link module:engine/view/documentfragment~DocumentFragment document fragment}\n\t * to data format &mdash; in this case to an HTML string.\n\t *\n\t * @param {module:engine/view/documentfragment~DocumentFragment} viewFragment\n\t * @returns {String} HTML string.\n\t */\n\ttoData( viewFragment ) {\n\t\t// Convert view DocumentFragment to DOM DocumentFragment.\n\t\tconst domFragment = this._domConverter.viewToDom( viewFragment, document );\n\n\t\t// Convert DOM DocumentFragment to HTML output.\n\t\treturn this._htmlWriter.getHtml( domFragment );\n\t}\n\n\t/**\n\t * Converts the provided HTML string to a view tree.\n\t *\n\t * @param {String} data An HTML string.\n\t * @returns {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment|null} A converted view element.\n\t */\n\ttoView( data ) {\n\t\t// Convert input HTML data to DOM DocumentFragment.\n\t\tconst domFragment = this._toDom( data );\n\n\t\t// Convert DOM DocumentFragment to view DocumentFragment.\n\t\treturn this._domConverter.domToView( domFragment );\n\t}\n\n\t/**\n\t * Converts an HTML string to its DOM representation. Returns a document fragment containing nodes parsed from\n\t * the provided data.\n\t *\n\t * @private\n\t * @param {String} data\n\t * @returns {DocumentFragment}\n\t */\n\t_toDom( data ) {\n\t\tconst document = this._domParser.parseFromString( data, 'text/html' );\n\t\tconst fragment = document.createDocumentFragment();\n\t\tconst nodes = document.body.childNodes;\n\n\t\twhile ( nodes.length > 0 ) {\n\t\t\tfragment.appendChild( nodes[ 0 ] );\n\t\t}\n\n\t\treturn fragment;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/componentfactory\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * A helper class implementing the UI component ({@link module:ui/view~View view}) factory.\n *\n * It allows functions producing specific UI components to be registered under their unique names\n * in the factory. A registered component can be then instantiated by providing its name.\n * Note that names are case insensitive.\n *\n *\t\t// The editor provides localization tools for the factory.\n *\t\tconst factory = new ComponentFactory( editor );\n *\n *\t\tfactory.add( 'foo', locale => new FooView( locale ) );\n *\t\tfactory.add( 'bar', locale => new BarView( locale ) );\n *\n *\t\t// An instance of FooView.\n *\t\tconst fooInstance = factory.create( 'foo' );\n *\n *\t\t// Names are case insensitive so this is also allowed:\n *\t\tconst barInstance = factory.create( 'Bar' );\n *\n * The {@link module:core/editor/editor~Editor#locale editor locale} is passed to the factory\n * function when {@link module:ui/componentfactory~ComponentFactory#create} is called.\n */\nexport default class ComponentFactory {\n\t/**\n\t * Creates an instance of the factory.\n\t *\n\t * @constructor\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t */\n\tconstructor( editor ) {\n\t\t/**\n\t\t * The editor instance that the factory belongs to.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/editor/editor~Editor}\n\t\t */\n\t\tthis.editor = editor;\n\n\t\t/**\n\t\t * Registered component factories.\n\t\t *\n\t\t * @private\n\t\t * @member {Map}\n\t\t */\n\t\tthis._components = new Map();\n\t}\n\n\t/**\n\t * Returns an iterator of registered component names. Names are returned in lower case.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\t* names() {\n\t\tfor ( const value of this._components.values() ) {\n\t\t\tyield value.originalName;\n\t\t}\n\t}\n\n\t/**\n\t * Registers a component factory function that will be used by the\n\t * {@link #create create} method and called with the\n\t * {@link module:core/editor/editor~Editor#locale editor locale} as an argument,\n\t * allowing localization of the {@link module:ui/view~View view}.\n\t *\n\t * @param {String} name The name of the component.\n\t * @param {Function} callback The callback that returns the component.\n\t */\n\tadd( name, callback ) {\n\t\tif ( this.has( name ) ) {\n\t\t\t/**\n\t\t\t * The item already exists in the component factory.\n\t\t\t *\n\t\t\t * @error componentfactory-item-exists\n\t\t\t * @param {String} name The name of the component.\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'componentfactory-item-exists: The item already exists in the component factory.',\n\t\t\t\tthis,\n\t\t\t\t{ name }\n\t\t\t);\n\t\t}\n\n\t\tthis._components.set( getNormalized( name ), { callback, originalName: name } );\n\t}\n\n\t/**\n\t * Creates an instance of a component registered in the factory under a specific name.\n\t *\n\t * When called, the {@link module:core/editor/editor~Editor#locale editor locale} is passed to\n\t * the previously {@link #add added} factory function, allowing localization of the\n\t * {@link module:ui/view~View view}.\n\t *\n\t * @param {String} name The name of the component.\n\t * @returns {module:ui/view~View} The instantiated component view.\n\t */\n\tcreate( name ) {\n\t\tif ( !this.has( name ) ) {\n\t\t\t/**\n\t\t\t * The required component is not registered in the component factory. Please make sure\n\t\t\t * the provided name is correct and the component has been correctly\n\t\t\t * {@link #add added} to the factory.\n\t\t\t *\n\t\t\t * @error componentfactory-item-missing\n\t\t\t * @param {String} name The name of the missing component.\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'componentfactory-item-missing: The required component is not registered in the factory.',\n\t\t\t\tthis,\n\t\t\t\t{ name }\n\t\t\t);\n\t\t}\n\n\t\treturn this._components.get( getNormalized( name ) ).callback( this.editor.locale );\n\t}\n\n\t/**\n\t * Checks if a component of a given name is registered in the factory.\n\t *\n\t * @param {String} name The name of the component.\n\t * @returns {Boolean}\n\t */\n\thas( name ) {\n\t\treturn this._components.has( getNormalized( name ) );\n\t}\n}\n\n//\n// Ensures that the component name used as the key in the internal map is in lower case.\n//\n// @private\n// @param {String} name\n// @returns {String}\nfunction getNormalized( name ) {\n\treturn String( name ).toLowerCase();\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 * @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}\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.<HTMLElement>}\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\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-2019, 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 core/editor/editorui\n */\n\n/* globals console */\n\nimport ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\n\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * A class providing the minimal interface that is required to successfully bootstrap any editor UI.\n *\n * @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class EditorUI {\n\t/**\n\t * Creates an instance of the editor UI class.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t */\n\tconstructor( editor ) {\n\t\t/**\n\t\t * The editor that the UI belongs to.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/editor/editor~Editor} #editor\n\t\t */\n\t\tthis.editor = editor;\n\n\t\t/**\n\t\t * An instance of the {@link module:ui/componentfactory~ComponentFactory}, a registry used by plugins\n\t\t * to register factories of specific UI components.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/componentfactory~ComponentFactory} #componentFactory\n\t\t */\n\t\tthis.componentFactory = new ComponentFactory( editor );\n\n\t\t/**\n\t\t * Stores the information about the editor UI focus and propagates it so various plugins and components\n\t\t * are unified as a focus group.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker} #focusTracker\n\t\t */\n\t\tthis.focusTracker = new FocusTracker();\n\n\t\t/**\n\t\t * Stores all editable elements used by the editor instance.\n\t\t *\n\t\t * @private\n\t\t * @member {Map.<String,HTMLElement>}\n\t\t */\n\t\tthis._editableElementsMap = new Map();\n\n\t\t// Informs UI components that should be refreshed after layout change.\n\t\tthis.listenTo( editor.editing.view.document, 'layoutChanged', () => this.update() );\n\t}\n\n\t/**\n\t * The main (outermost) DOM element of the editor UI.\n\t *\n\t * For example, in {@link module:editor-classic/classiceditor~ClassicEditor} it is a `<div>` which\n\t * wraps the editable element and the toolbar. In {@link module:editor-inline/inlineeditor~InlineEditor}\n\t * it is the editable element itself (as there is no other wrapper). However, in\n\t * {@link module:editor-decoupled/decouplededitor~DecoupledEditor} it is set to `null` because this editor does not\n\t * come with a single \"main\" HTML element (its editable element and toolbar are separate).\n\t *\n\t * This property can be understood as a shorthand for retrieving the element that a specific editor integration\n\t * considers to be its main DOM element.\n\t *\n\t * @readonly\n\t * @member {HTMLElement|null} #element\n\t */\n\tget element() {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Fires the {@link module:core/editor/editorui~EditorUI#event:update `update`} event.\n\t *\n\t * This method should be called when the editor UI (e.g. positions of its balloons) needs to be updated due to\n\t * some environmental change which CKEditor 5 is not aware of (e.g. resize of a container in which it is used).\n\t */\n\tupdate() {\n\t\tthis.fire( 'update' );\n\t}\n\n\t/**\n\t * Destroys the UI.\n\t */\n\tdestroy() {\n\t\tthis.stopListening();\n\n\t\tthis.focusTracker.destroy();\n\n\t\t// Clean–up the references to the CKEditor instance stored in the native editable DOM elements.\n\t\tfor ( const domElement of this._editableElementsMap.values() ) {\n\t\t\tdomElement.ckeditorInstance = null;\n\t\t}\n\n\t\tthis._editableElementsMap = new Map();\n\t}\n\n\t/**\n\t * Store the native DOM editable element used by the editor under\n\t * a unique name.\n\t *\n\t * @param {String} rootName The unique name of the editable element.\n\t * @param {HTMLElement} domElement The native DOM editable element.\n\t */\n\tsetEditableElement( rootName, domElement ) {\n\t\tthis._editableElementsMap.set( rootName, domElement );\n\n\t\t// Put a reference to the CKEditor instance in the editable native DOM element.\n\t\t// It helps 3rd–party software (browser extensions, other libraries) access and recognize\n\t\t// CKEditor 5 instances (editing roots) and use their API (there is no global editor\n\t\t// instance registry).\n\t\tif ( !domElement.ckeditorInstance ) {\n\t\t\tdomElement.ckeditorInstance = this.editor;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the editable editor element with the given name or null if editable does not exist.\n\t *\n\t * @param {String} [rootName=main] The editable name.\n\t * @returns {HTMLElement|undefined}\n\t */\n\tgetEditableElement( rootName = 'main' ) {\n\t\treturn this._editableElementsMap.get( rootName );\n\t}\n\n\t/**\n\t * Returns array of names of all editor editable elements.\n\t *\n\t * @returns {Iterable.<String>}\n\t */\n\tgetEditableElementsNames() {\n\t\treturn this._editableElementsMap.keys();\n\t}\n\n\t/**\n\t * Stores all editable elements used by the editor instance.\n\t *\n\t * @protected\n\t * @deprecated\n\t * @member {Map.<String,HTMLElement>}\n\t */\n\tget _editableElements() {\n\t\t/**\n\t\t * The {@link module:core/editor/editorui~EditorUI#_editableElements `EditorUI#_editableElements`} property has been\n\t\t * deprecated and will be removed in the near future. Please use {@link #setEditableElement `setEditableElement()`} and\n\t\t * {@link #getEditableElement `getEditableElement()`} methods instead.\n\t\t *\n\t\t * @error editor-ui-deprecated-editable-elements\n\t\t * @param {module:core/editor/editorui~EditorUI} editorUI Editor UI instance the deprecated property belongs to.\n\t\t */\n\t\tconsole.warn(\n\t\t\t'editor-ui-deprecated-editable-elements: ' +\n\t\t\t'The EditorUI#_editableElements property has been deprecated and will be removed in the near future.',\n\t\t\t{ editorUI: this } );\n\n\t\treturn this._editableElementsMap;\n\t}\n\n\t/**\n\t * Fired when the editor UI is ready.\n\t *\n\t * Fired before {@link module:engine/controller/datacontroller~DataController#event:ready}.\n\t *\n\t * @event ready\n\t */\n\n\t/**\n\t * Fired whenever the UI (all related components) should be refreshed.\n\t *\n\t * **Note:**: The event is fired after each {@link module:engine/view/document~Document#event:layoutChanged}.\n\t * It can also be fired manually via the {@link module:core/editor/editorui~EditorUI#update} method.\n\t *\n\t * @event update\n\t */\n}\n\nmix( EditorUI, EmitterMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/placeholder\n */\n\nimport '../../theme/placeholder.css';\n\n// Each document stores information about its placeholder elements and check functions.\nconst documentPlaceholders = new WeakMap();\n\n/**\n * A helper that enables a placeholder on the provided view element (also updates its visibility).\n * The placeholder is a CSS pseudo–element (with a text content) attached to the element.\n *\n * To change the placeholder text, simply call this method again with new options.\n *\n * To disable the placeholder, use {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} helper.\n *\n * @param {Object} [options] Configuration options of the placeholder.\n * @param {module:engine/view/view~View} options.view Editing view instance.\n * @param {module:engine/view/element~Element} options.element Element that will gain a placeholder.\n * See `options.isDirectHost` to learn more.\n * @param {String} options.text Placeholder text.\n * @param {Boolean} [options.isDirectHost=true] If set `false`, the placeholder will not be enabled directly\n * in the passed `element` but in one of its children (selected automatically, i.e. a first empty child element).\n * Useful when attaching placeholders to elements that can host other elements (not just text), for instance,\n * editable root elements.\n */\nexport function enablePlaceholder( options ) {\n\tconst { view, element, text, isDirectHost = true } = options;\n\tconst doc = view.document;\n\n\t// Use a single a single post fixer per—document to update all placeholders.\n\tif ( !documentPlaceholders.has( doc ) ) {\n\t\tdocumentPlaceholders.set( doc, new Map() );\n\n\t\t// If a post-fixer callback makes a change, it should return `true` so other post–fixers\n\t\t// can re–evaluate the document again.\n\t\tdoc.registerPostFixer( writer => updateDocumentPlaceholders( doc, writer ) );\n\t}\n\n\t// Store information about the element placeholder under its document.\n\tdocumentPlaceholders.get( doc ).set( element, {\n\t\ttext,\n\t\tisDirectHost\n\t} );\n\n\t// Update the placeholders right away.\n\tview.change( writer => updateDocumentPlaceholders( doc, writer ) );\n}\n\n/**\n * Disables the placeholder functionality from a given element.\n *\n * See {@link module:engine/view/placeholder~enablePlaceholder `enablePlaceholder()`} to learn more.\n *\n * @param {module:engine/view/view~View} view\n * @param {module:engine/view/element~Element} element\n */\nexport function disablePlaceholder( view, element ) {\n\tconst doc = element.document;\n\n\tview.change( writer => {\n\t\tif ( !documentPlaceholders.has( doc ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst placeholders = documentPlaceholders.get( doc );\n\t\tconst config = placeholders.get( element );\n\n\t\twriter.removeAttribute( 'data-placeholder', config.hostElement );\n\t\thidePlaceholder( writer, config.hostElement );\n\n\t\tplaceholders.delete( element );\n\t} );\n}\n\n/**\n * Shows a placeholder in the provided element by changing related attributes and CSS classes.\n *\n * **Note**: This helper will not update the placeholder visibility nor manage the\n * it in any way in the future. What it does is a one–time state change of an element. Use\n * {@link module:engine/view/placeholder~enablePlaceholder `enablePlaceholder()`} and\n * {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} for full\n * placeholder functionality.\n *\n * **Note**: This helper will blindly show the placeholder directly in the root editable element if\n * one is passed, which could result in a visual clash if the editable element has some children\n * (for instance, an empty paragraph). Use {@link module:engine/view/placeholder~enablePlaceholder `enablePlaceholder()`}\n * in that case or make sure the correct element is passed to the helper.\n *\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n * @param {module:engine/view/element~Element} element\n * @returns {Boolean} `true`, if any changes were made to the `element`.\n */\nexport function showPlaceholder( writer, element ) {\n\tif ( !element.hasClass( 'ck-placeholder' ) ) {\n\t\twriter.addClass( 'ck-placeholder', element );\n\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Hides a placeholder in the element by changing related attributes and CSS classes.\n *\n * **Note**: This helper will not update the placeholder visibility nor manage the\n * it in any way in the future. What it does is a one–time state change of an element. Use\n * {@link module:engine/view/placeholder~enablePlaceholder `enablePlaceholder()`} and\n * {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} for full\n * placeholder functionality.\n *\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n * @param {module:engine/view/element~Element} element\n * @returns {Boolean} `true`, if any changes were made to the `element`.\n */\nexport function hidePlaceholder( writer, element ) {\n\tif ( element.hasClass( 'ck-placeholder' ) ) {\n\t\twriter.removeClass( 'ck-placeholder', element );\n\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n/**\n * Checks if a placeholder should be displayed in the element.\n *\n * **Note**: This helper will blindly check the possibility of showing a placeholder directly in the\n * root editable element if one is passed, which may not be the expected result. If an element can\n * host other elements (not just text), most likely one of its children should be checked instead\n * because it will be the final host for the placeholder. Use\n * {@link module:engine/view/placeholder~enablePlaceholder `enablePlaceholder()`} in that case or make\n * sure the correct element is passed to the helper.\n *\n * @param {module:engine/view/element~Element} element\n * @returns {Boolean}\n */\nexport function needsPlaceholder( element ) {\n\tconst doc = element.document;\n\n\t// The element was removed from document.\n\tif ( !doc ) {\n\t\treturn false;\n\t}\n\n\t// The element is empty only as long as it contains nothing but uiElements.\n\tconst isEmptyish = !Array.from( element.getChildren() )\n\t\t.some( element => !element.is( 'uiElement' ) );\n\n\t// If the element is empty and the document is blurred.\n\tif ( !doc.isFocused && isEmptyish ) {\n\t\treturn true;\n\t}\n\n\tconst viewSelection = doc.selection;\n\tconst selectionAnchor = viewSelection.anchor;\n\n\t// If document is focused and the element is empty but the selection is not anchored inside it.\n\tif ( isEmptyish && selectionAnchor && selectionAnchor.parent !== element ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n// Updates all placeholders associated with a document in a post–fixer callback.\n//\n// @private\n// @param { module:engine/view/document~Document} doc\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @returns {Boolean} True if any changes were made to the view document.\nfunction updateDocumentPlaceholders( doc, writer ) {\n\tconst placeholders = documentPlaceholders.get( doc );\n\tlet wasViewModified = false;\n\n\tfor ( const [ element, config ] of placeholders ) {\n\t\tif ( updatePlaceholder( writer, element, config ) ) {\n\t\t\twasViewModified = true;\n\t\t}\n\t}\n\n\treturn wasViewModified;\n}\n\n// Updates a single placeholder in a post–fixer callback.\n//\n// @private\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @param {module:engine/view/element~Element} element\n// @param {Object} config Configuration of the placeholder\n// @param {String} config.text\n// @param {Boolean} config.isDirectHost\n// @returns {Boolean} True if any changes were made to the view document.\nfunction updatePlaceholder( writer, element, config ) {\n\tconst { text, isDirectHost } = config;\n\tconst hostElement = isDirectHost ? element : getChildPlaceholderHostSubstitute( element );\n\tlet wasViewModified = false;\n\n\t// When not a direct host, it could happen that there is no child element\n\t// capable of displaying a placeholder.\n\tif ( !hostElement ) {\n\t\treturn false;\n\t}\n\n\t// Cache the host element. It will be necessary for disablePlaceholder() to know\n\t// which element should have class and attribute removed because, depending on\n\t// the config.isDirectHost value, it could be the element or one of its descendants.\n\tconfig.hostElement = hostElement;\n\n\t// This may be necessary when updating the placeholder text to something else.\n\tif ( hostElement.getAttribute( 'data-placeholder' ) !== text ) {\n\t\twriter.setAttribute( 'data-placeholder', text, hostElement );\n\t\twasViewModified = true;\n\t}\n\n\tif ( needsPlaceholder( hostElement ) ) {\n\t\tif ( showPlaceholder( writer, hostElement ) ) {\n\t\t\twasViewModified = true;\n\t\t}\n\t} else if ( hidePlaceholder( writer, hostElement ) ) {\n\t\twasViewModified = true;\n\t}\n\n\treturn wasViewModified;\n}\n\n// Gets a child element capable of displaying a placeholder if a parent element can host more\n// than just text (for instance, when it is a root editable element). The child element\n// can then be used in other placeholder helpers as a substitute of its parent.\n//\n// @private\n// @param {module:engine/view/element~Element} parent\n// @returns {module:engine/view/element~Element|null}\nfunction getChildPlaceholderHostSubstitute( parent ) {\n\tif ( parent.childCount === 1 ) {\n\t\tconst firstChild = parent.getChild( 0 );\n\n\t\tif ( firstChild.is( 'element' ) && !firstChild.is( 'uiElement' ) ) {\n\t\t\treturn firstChild;\n\t\t}\n\t}\n\n\treturn null;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 editor-decoupled/decouplededitorui\n */\n\nimport EditorUI from '@ckeditor/ckeditor5-core/src/editor/editorui';\nimport enableToolbarKeyboardFocus from '@ckeditor/ckeditor5-ui/src/toolbar/enabletoolbarkeyboardfocus';\nimport normalizeToolbarConfig from '@ckeditor/ckeditor5-ui/src/toolbar/normalizetoolbarconfig';\nimport { enablePlaceholder } from '@ckeditor/ckeditor5-engine/src/view/placeholder';\n\n/**\n * The decoupled editor UI class.\n *\n * @extends module:core/editor/editorui~EditorUI\n */\nexport default class DecoupledEditorUI extends EditorUI {\n\t/**\n\t * Creates an instance of the decoupled editor UI class.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t * @param {module:ui/editorui/editoruiview~EditorUIView} view The view of the UI.\n\t */\n\tconstructor( editor, view ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The main (top–most) view of the editor UI.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/editorui/editoruiview~EditorUIView} #view\n\t\t */\n\t\tthis.view = view;\n\n\t\t/**\n\t\t * A normalized `config.toolbar` object.\n\t\t *\n\t\t * @type {Object}\n\t\t * @private\n\t\t */\n\t\tthis._toolbarConfig = normalizeToolbarConfig( editor.config.get( 'toolbar' ) );\n\t}\n\n\t/**\n\t * Initializes the UI.\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst view = this.view;\n\t\tconst editingView = editor.editing.view;\n\t\tconst editable = view.editable;\n\t\tconst editingRoot = editingView.document.getRoot();\n\n\t\t// The editable UI and editing root should share the same name. Then name is used\n\t\t// to recognize the particular editable, for instance in ARIA attributes.\n\t\tview.editable.name = editingRoot.rootName;\n\n\t\tview.render();\n\n\t\t// The editable UI element in DOM is available for sure only after the editor UI view has been rendered.\n\t\t// But it can be available earlier if a DOM element has been passed to DecoupledEditor.create().\n\t\tconst editableElement = editable.element;\n\n\t\t// Register the editable UI view in the editor. A single editor instance can aggregate multiple\n\t\t// editable areas (roots) but the decoupled editor has only one.\n\t\tthis.setEditableElement( editable.name, editableElement );\n\n\t\t// Let the global focus tracker know that the editable UI element is focusable and\n\t\t// belongs to the editor. From now on, the focus tracker will sustain the editor focus\n\t\t// as long as the editable is focused (e.g. the user is typing).\n\t\tthis.focusTracker.add( editableElement );\n\n\t\t// Let the editable UI element respond to the changes in the global editor focus\n\t\t// tracker. It has been added to the same tracker a few lines above but, in reality, there are\n\t\t// many focusable areas in the editor, like balloons, toolbars or dropdowns and as long\n\t\t// as they have focus, the editable should act like it is focused too (although technically\n\t\t// it isn't), e.g. by setting the proper CSS class, visually announcing focus to the user.\n\t\t// Doing otherwise will result in editable focus styles disappearing, once e.g. the\n\t\t// toolbar gets focused.\n\t\tview.editable.bind( 'isFocused' ).to( this.focusTracker );\n\n\t\t// Bind the editable UI element to the editing view, making it an end– and entry–point\n\t\t// of the editor's engine. This is where the engine meets the UI.\n\t\teditingView.attachDomRoot( editableElement );\n\n\t\tthis._initPlaceholder();\n\t\tthis._initToolbar();\n\t\tthis.fire( 'ready' );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tconst view = this.view;\n\t\tconst editingView = this.editor.editing.view;\n\n\t\teditingView.detachDomRoot( view.editable.name );\n\t\tview.destroy();\n\n\t\tsuper.destroy();\n\t}\n\n\t/**\n\t * Initializes the inline editor toolbar and its panel.\n\t *\n\t * @private\n\t */\n\t_initToolbar() {\n\t\tconst editor = this.editor;\n\t\tconst view = this.view;\n\t\tconst toolbar = view.toolbar;\n\n\t\ttoolbar.fillFromConfig( this._toolbarConfig.items, this.componentFactory );\n\n\t\tenableToolbarKeyboardFocus( {\n\t\t\torigin: editor.editing.view,\n\t\t\toriginFocusTracker: this.focusTracker,\n\t\t\toriginKeystrokeHandler: editor.keystrokes,\n\t\t\ttoolbar\n\t\t} );\n\t}\n\n\t/**\n\t * Enable the placeholder text on the editing root, if any was configured.\n\t *\n\t * @private\n\t */\n\t_initPlaceholder() {\n\t\tconst editor = this.editor;\n\t\tconst editingView = editor.editing.view;\n\t\tconst editingRoot = editingView.document.getRoot();\n\t\tconst sourceElement = editor.sourceElement;\n\n\t\tconst placeholderText = editor.config.get( 'placeholder' ) ||\n\t\t\tsourceElement && sourceElement.tagName.toLowerCase() === 'textarea' && sourceElement.getAttribute( 'placeholder' );\n\n\t\tif ( placeholderText ) {\n\t\t\tenablePlaceholder( {\n\t\t\t\tview: editingView,\n\t\t\t\telement: editingRoot,\n\t\t\t\ttext: placeholderText,\n\t\t\t\tisDirectHost: false\n\t\t\t} );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/toolbar/normalizetoolbarconfig\n */\n\n/**\n * Normalizes the toolbar configuration (`config.toolbar`), which:\n *\n * * may be defined as an `Array`:\n *\n * \t\ttoolbar: [ 'heading', 'bold', 'italic', 'link', ... ]\n *\n * * or an `Object`:\n *\n *\t\ttoolbar: {\n *\t\t\titems: [ 'heading', 'bold', 'italic', 'link', ... ],\n *\t\t\t...\n *\t\t}\n *\n * * or may not be defined at all (`undefined`)\n *\n * and returns it in the object form.\n *\n * @param {Array|Object|undefined} config The value of `config.toolbar`.\n * @returns {Object} A normalized toolbar config object.\n */\nexport default function normalizeToolbarConfig( config ) {\n\tif ( Array.isArray( config ) ) {\n\t\treturn {\n\t\t\titems: config\n\t\t};\n\t}\n\n\tif ( !config ) {\n\t\treturn {\n\t\t\titems: []\n\t\t};\n\t}\n\n\treturn Object.assign( {\n\t\titems: []\n\t}, config );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/toolbar/enabletoolbarkeyboardfocus\n */\n\n/**\n * Enables focus/blur toolbar navigation using `Alt+F10` and `Esc` keystrokes.\n *\n * @param {Object} options Options of the utility.\n * @param {*} options.origin A view to which the focus will return when `Esc` is pressed and\n * `options.toolbar` is focused.\n * @param {module:utils/keystrokehandler~KeystrokeHandler} options.originKeystrokeHandler A keystroke\n * handler to register `Alt+F10` keystroke.\n * @param {module:utils/focustracker~FocusTracker} options.originFocusTracker A focus tracker\n * for `options.origin`.\n * @param {module:ui/toolbar/toolbarview~ToolbarView} options.toolbar A toolbar which is to gain\n * focus when `Alt+F10` is pressed.\n * @param {Function} [options.beforeFocus] A callback executed before the `options.toolbar` gains focus\n * upon the `Alt+F10` keystroke.\n * @param {Function} [options.afterBlur] A callback executed after `options.toolbar` loses focus upon\n * `Esc` keystroke but before the focus goes back to `options.origin`.\n */\nexport default function enableToolbarKeyboardFocus( {\n\torigin,\n\toriginKeystrokeHandler,\n\toriginFocusTracker,\n\ttoolbar,\n\tbeforeFocus,\n\tafterBlur\n} ) {\n\t// Because toolbar items can get focus, the overall state of the toolbar must\n\t// also be tracked.\n\toriginFocusTracker.add( toolbar.element );\n\n\t// Focus the toolbar on the keystroke, if not already focused.\n\toriginKeystrokeHandler.set( 'Alt+F10', ( data, cancel ) => {\n\t\tif ( originFocusTracker.isFocused && !toolbar.focusTracker.isFocused ) {\n\t\t\tif ( beforeFocus ) {\n\t\t\t\tbeforeFocus();\n\t\t\t}\n\n\t\t\ttoolbar.focus();\n\n\t\t\tcancel();\n\t\t}\n\t} );\n\n\t// Blur the toolbar and bring the focus back to origin.\n\ttoolbar.keystrokes.set( 'Esc', ( data, cancel ) => {\n\t\tif ( toolbar.focusTracker.isFocused ) {\n\t\t\torigin.focus();\n\n\t\t\tif ( afterBlur ) {\n\t\t\t\tafterBlur();\n\t\t\t}\n\n\t\t\tcancel();\n\t\t}\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/viewcollection\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\n\n/**\n * Collects {@link module:ui/view~View} instances.\n *\n *\t\tconst parentView = new ParentView( locale );\n *\t\tconst collection = new ViewCollection( locale );\n *\n *\t\tcollection.setParent( parentView.element );\n *\n *\t\tconst viewA = new ChildView( locale );\n *\t\tconst viewB = new ChildView( locale );\n *\n * View collection renders and manages view {@link module:ui/view~View#element elements}:\n *\n *\t\tcollection.add( viewA );\n *\t\tcollection.add( viewB );\n *\n *\t\tconsole.log( parentView.element.firsChild ); // -> viewA.element\n *\t\tconsole.log( parentView.element.lastChild ); // -> viewB.element\n *\n * It {@link module:ui/viewcollection~ViewCollection#delegate propagates} DOM events too:\n *\n *\t\t// Delegate #click and #keydown events from viewA and viewB to the parentView.\n *\t\tcollection.delegate( 'click' ).to( parentView );\n *\n *\t\tparentView.on( 'click', ( evt ) => {\n *\t\t\tconsole.log( `${ evt.source } has been clicked.` );\n *\t\t} );\n *\n *\t\t// This event will be delegated to the parentView.\n *\t\tviewB.fire( 'click' );\n *\n * **Note**: A view collection can be used directly in the {@link module:ui/template~TemplateDefinition definition}\n * of a {@link module:ui/template~Template template}.\n *\n * @extends module:utils/collection~Collection\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class ViewCollection extends Collection {\n\t/**\n\t * Creates a new instance of the {@link module:ui/viewcollection~ViewCollection}.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The {@link module:core/editor/editor~Editor editor's locale} instance.\n\t */\n\tconstructor( locale ) {\n\t\tsuper( {\n\t\t\t// An #id Number attribute should be legal and not break the `ViewCollection` instance.\n\t\t\t// https://github.com/ckeditor/ckeditor5-ui/issues/93\n\t\t\tidProperty: 'viewUid'\n\t\t} );\n\n\t\t// Handle {@link module:ui/view~View#element} in DOM when a new view is added to the collection.\n\t\tthis.on( 'add', ( evt, view, index ) => {\n\t\t\tif ( !view.isRendered ) {\n\t\t\t\tview.render();\n\t\t\t}\n\n\t\t\tif ( view.element && this._parentElement ) {\n\t\t\t\tthis._parentElement.insertBefore( view.element, this._parentElement.children[ index ] );\n\t\t\t}\n\t\t} );\n\n\t\t// Handle {@link module:ui/view~View#element} in DOM when a view is removed from the collection.\n\t\tthis.on( 'remove', ( evt, view ) => {\n\t\t\tif ( view.element && this._parentElement ) {\n\t\t\t\tview.element.remove();\n\t\t\t}\n\t\t} );\n\n\t\t/**\n\t\t * The {@link module:core/editor/editor~Editor#locale editor's locale} instance.\n\t\t * See the view {@link module:ui/view~View#locale locale} property.\n\t\t *\n\t\t * @member {module:utils/locale~Locale}\n\t\t */\n\t\tthis.locale = locale;\n\n\t\t/**\n\t\t * A parent element within which child views are rendered and managed in DOM.\n\t\t *\n\t\t * @protected\n\t\t * @member {HTMLElement}\n\t\t */\n\t\tthis._parentElement = null;\n\t}\n\n\t/**\n\t * Destroys the view collection along with child views.\n\t * See the view {@link module:ui/view~View#destroy} method.\n\t */\n\tdestroy() {\n\t\tthis.map( view => view.destroy() );\n\t}\n\n\t/**\n\t * Sets the parent HTML element of this collection. When parent is set, {@link #add adding} and\n\t * {@link #remove removing} views in the collection synchronizes their\n\t * {@link module:ui/view~View#element elements} in the parent element.\n\t *\n\t * @param {HTMLElement} element A new parent element.\n\t */\n\tsetParent( elementOrDocFragment ) {\n\t\tthis._parentElement = elementOrDocFragment;\n\t}\n\n\t/**\n\t * Delegates selected events coming from within views in the collection to any\n\t * {@link module:utils/emittermixin~Emitter}.\n\t *\n\t * For the following views and collection:\n\t *\n\t *\t\tconst viewA = new View();\n\t *\t\tconst viewB = new View();\n\t *\t\tconst viewC = new View();\n\t *\n\t *\t\tconst views = parentView.createCollection();\n\t *\n\t *\t\tviews.delegate( 'eventX' ).to( viewB );\n\t *\t\tviews.delegate( 'eventX', 'eventY' ).to( viewC );\n\t *\n\t *\t\tviews.add( viewA );\n\t *\n\t * the `eventX` is delegated (fired by) `viewB` and `viewC` along with `customData`:\n\t *\n\t *\t\tviewA.fire( 'eventX', customData );\n\t *\n\t * and `eventY` is delegated (fired by) `viewC` along with `customData`:\n\t *\n\t *\t\tviewA.fire( 'eventY', customData );\n\t *\n\t * See {@link module:utils/emittermixin~Emitter#delegate}.\n\t *\n\t * @param {...String} events {@link module:ui/view~View} event names to be delegated to another\n\t * {@link module:utils/emittermixin~Emitter}.\n\t * @returns {Object}\n\t * @returns {Function} return.to A function which accepts the destination of\n\t * {@link module:utils/emittermixin~Emitter#delegate delegated} events.\n\t */\n\tdelegate( ...events ) {\n\t\tif ( !events.length || !isStringArray( events ) ) {\n\t\t\t/**\n\t\t\t * All event names must be strings.\n\t\t\t *\n\t\t\t * @error ui-viewcollection-delegate-wrong-events\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'ui-viewcollection-delegate-wrong-events: All event names must be strings.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\t/**\n\t\t\t * Selects destination for {@link module:utils/emittermixin~Emitter#delegate} events.\n\t\t\t *\n\t\t\t * @memberOf module:ui/viewcollection~ViewCollection#delegate\n\t\t\t * @function module:ui/viewcollection~ViewCollection#delegate.to\n\t\t\t * @param {module:utils/emittermixin~Emitter} dest An `Emitter` instance which is\n\t\t\t * the destination for delegated events.\n\t\t\t */\n\t\t\tto: dest => {\n\t\t\t\t// Activate delegating on existing views in this collection.\n\t\t\t\tfor ( const view of this ) {\n\t\t\t\t\tfor ( const evtName of events ) {\n\t\t\t\t\t\tview.delegate( evtName ).to( dest );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Activate delegating on future views in this collection.\n\t\t\t\tthis.on( 'add', ( evt, view ) => {\n\t\t\t\t\tfor ( const evtName of events ) {\n\t\t\t\t\t\tview.delegate( evtName ).to( dest );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\t// Deactivate delegating when view is removed from this collection.\n\t\t\t\tthis.on( 'remove', ( evt, view ) => {\n\t\t\t\t\tfor ( const evtName of events ) {\n\t\t\t\t\t\tview.stopDelegating( evtName, dest );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Removes a child view from the collection. If the {@link #setParent parent element} of the\n\t * collection has been set, the {@link module:ui/view~View#element element} of the view is also removed\n\t * in DOM, reflecting the order of the collection.\n\t *\n\t * See the {@link #add} method.\n\t *\n\t * @method #remove\n\t * @param {module:ui/view~View|Number|String} subject The view to remove, its id or index in the collection.\n\t * @returns {Object} The removed view.\n\t */\n}\n\n// Check if all entries of the array are of `String` type.\n//\n// @private\n// @param {Array} arr An array to be checked.\n// @returns {Boolean}\nfunction isStringArray( arr ) {\n\treturn arr.every( a => typeof a == 'string' );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/template\n */\n\n/* global document */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport View from './view';\nimport ViewCollection from './viewcollection';\nimport isNode from '@ckeditor/ckeditor5-utils/src/dom/isnode';\nimport { isObject, cloneDeepWith } from 'lodash-es';\n\nconst xhtmlNs = 'http://www.w3.org/1999/xhtml';\n\n/**\n * A basic Template class. It renders a DOM HTML element or text from a\n * {@link module:ui/template~TemplateDefinition definition} and supports element attributes, children,\n * bindings to {@link module:utils/observablemixin~Observable observables} and DOM event propagation.\n *\n * A simple template can look like this:\n *\n *\t\tconst bind = Template.bind( observable, emitter );\n *\n *\t\tnew Template( {\n *\t\t\ttag: 'p',\n *\t\t\tattributes: {\n *\t\t\t\tclass: 'foo',\n *\t\t\t\tstyle: {\n *\t\t\t\t\tbackgroundColor: 'yellow'\n *\t\t\t\t}\n *\t\t\t},\n *\t\t\ton: {\n *\t\t\t\tclick: bind.to( 'clicked' )\n *\t\t\t},\n *\t\t\tchildren: [\n *\t\t\t\t'A paragraph.'\n *\t\t\t]\n *\t\t} ).render();\n *\n * and it will render the following HTML element:\n *\n *\t\t<p class=\"foo\" style=\"background-color: yellow;\">A paragraph.</p>\n *\n * Additionally, the `observable` will always fire `clicked` upon clicking `<p>` in the DOM.\n *\n * See {@link module:ui/template~TemplateDefinition} to know more about templates and complex\n * template definitions.\n *\n* @mixes module:utils/emittermixin~EmitterMixin\n */\nexport default class Template {\n\t/**\n\t * Creates an instance of the {@link ~Template} class.\n\t *\n\t * @param {module:ui/template~TemplateDefinition} def The definition of the template.\n\t */\n\tconstructor( def ) {\n\t\tObject.assign( this, normalize( clone( def ) ) );\n\n\t\t/**\n\t\t * Indicates whether this particular Template instance has been\n\t\t * {@link #render rendered}.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis._isRendered = false;\n\n\t\t/**\n\t\t * The tag (`tagName`) of this template, e.g. `div`. It also indicates that the template\n\t\t * renders to an HTML element.\n\t\t *\n\t\t * @member {String} #tag\n\t\t */\n\n\t\t/**\n\t\t * The text of the template. It also indicates that the template renders to a DOM text node.\n\t\t *\n\t\t * @member {Array.<String|module:ui/template~TemplateValueSchema>} #text\n\t\t */\n\n\t\t/**\n\t\t * The attributes of the template, e.g. `{ id: [ 'ck-id' ] }`, corresponding with\n\t\t * the attributes of an HTML element.\n\t\t *\n\t\t * **Note**: This property only makes sense when {@link #tag} is defined.\n\t\t *\n\t\t * @member {Object} #attributes\n\t\t */\n\n\t\t/**\n\t\t * The children of the template. They can be either:\n\t\t * * independent instances of {@link ~Template} (sub–templates),\n\t\t * * native DOM Nodes.\n\t\t *\n\t\t * **Note**: This property only makes sense when {@link #tag} is defined.\n\t\t *\n\t\t * @member {Array.<module:ui/template~Template|Node>} #children\n\t\t */\n\n\t\t/**\n\t\t * The DOM event listeners of the template.\n\t\t *\n\t\t * @member {Object} #eventListeners\n\t\t */\n\n\t\t/**\n\t\t * The data used by the {@link #revert} method to restore a node to its original state.\n\t\t *\n\t\t * See: {@link #apply}.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/template~RenderData}\n\t\t */\n\t\tthis._revertData = null;\n\t}\n\n\t/**\n\t * Renders a DOM Node (an HTML element or text) out of the template.\n\t *\n\t *\t\tconst domNode = new Template( { ... } ).render();\n\t *\n\t * See: {@link #apply}.\n\t *\n\t * @returns {HTMLElement|Text}\n\t */\n\trender() {\n\t\tconst node = this._renderNode( {\n\t\t\tintoFragment: true\n\t\t} );\n\n\t\tthis._isRendered = true;\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Applies the template to an existing DOM Node, either HTML element or text.\n\t *\n\t * **Note:** No new DOM nodes will be created. Applying extends:\n\t *\n\t * {@link module:ui/template~TemplateDefinition attributes},\n\t * {@link module:ui/template~TemplateDefinition event listeners}, and\n\t * `textContent` of {@link module:ui/template~TemplateDefinition children} only.\n\t *\n\t * **Note:** Existing `class` and `style` attributes are extended when a template\n\t * is applied to an HTML element, while other attributes and `textContent` are overridden.\n\t *\n\t * **Note:** The process of applying a template can be easily reverted using the\n\t * {@link module:ui/template~Template#revert} method.\n\t *\n\t *\t\tconst element = document.createElement( 'div' );\n\t *\t\tconst observable = new Model( { divClass: 'my-div' } );\n\t *\t\tconst emitter = Object.create( EmitterMixin );\n\t *\t\tconst bind = Template.bind( observable, emitter );\n\t *\n\t *\t\tnew Template( {\n\t *\t\t\tattributes: {\n\t *\t\t\t\tid: 'first-div',\n\t *\t\t\t\tclass: bind.to( 'divClass' )\n\t *\t\t\t},\n\t *\t\t\ton: {\n\t *\t\t\t\tclick: bind( 'elementClicked' ) // Will be fired by the observable.\n\t *\t\t\t},\n\t *\t\t\tchildren: [\n\t *\t\t\t\t'Div text.'\n\t *\t\t\t]\n\t *\t\t} ).apply( element );\n\t *\n\t *\t\tconsole.log( element.outerHTML ); // -> '<div id=\"first-div\" class=\"my-div\"></div>'\n\t *\n\t * @see module:ui/template~Template#render\n\t * @see module:ui/template~Template#revert\n\t * @param {Node} node Root node for the template to apply.\n\t */\n\tapply( node ) {\n\t\tthis._revertData = getEmptyRevertData();\n\n\t\tthis._renderNode( {\n\t\t\tnode,\n\t\t\tisApplying: true,\n\t\t\trevertData: this._revertData\n\t\t} );\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Reverts a template {@link module:ui/template~Template#apply applied} to a DOM node.\n\t *\n\t * @param {Node} node The root node for the template to revert. In most of the cases, it is the\n\t * same node used by {@link module:ui/template~Template#apply}.\n\t */\n\trevert( node ) {\n\t\tif ( !this._revertData ) {\n\t\t\t/**\n\t\t\t * Attempting to revert a template which has not been applied yet.\n\t\t\t *\n\t\t\t * @error ui-template-revert-not-applied\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'ui-template-revert-not-applied: Attempting to revert a template which has not been applied yet.',\n\t\t\t\t[ this, node ]\n\t\t\t);\n\t\t}\n\n\t\tthis._revertTemplateFromNode( node, this._revertData );\n\t}\n\n\t/**\n\t * Returns an iterator which traverses the template in search of {@link module:ui/view~View}\n\t * instances and returns them one by one.\n\t *\n\t *\t\tconst viewFoo = new View();\n\t *\t\tconst viewBar = new View();\n\t *\t\tconst viewBaz = new View();\n\t *\t\tconst template = new Template( {\n\t *\t\t\ttag: 'div',\n\t *\t\t\tchildren: [\n\t *\t\t\t\tviewFoo,\n\t *\t\t\t\t{\n\t *\t\t\t\t\ttag: 'div',\n\t *\t\t\t\t\tchildren: [\n\t *\t\t\t\t\t\tviewBar\n\t *\t\t\t\t\t]\n\t *\t\t\t\t},\n\t *\t\t\t\tviewBaz\n\t *\t\t\t]\n\t *\t\t} );\n\t *\n\t *\t\t// Logs: viewFoo, viewBar, viewBaz\n\t *\t\tfor ( const view of template.getViews() ) {\n\t *\t\t\tconsole.log( view );\n\t *\t\t}\n\t *\n\t * @returns {Iterable.<module:ui/view~View>}\n\t */\n\t* getViews() {\n\t\tfunction* search( def ) {\n\t\t\tif ( def.children ) {\n\t\t\t\tfor ( const child of def.children ) {\n\t\t\t\t\tif ( isView( child ) ) {\n\t\t\t\t\t\tyield child;\n\t\t\t\t\t} else if ( isTemplate( child ) ) {\n\t\t\t\t\t\tyield* search( child );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tyield* search( this );\n\t}\n\n\t/**\n\t * An entry point to the interface which binds DOM nodes to\n\t * {@link module:utils/observablemixin~Observable observables}.\n\t * There are two types of bindings:\n\t *\n\t * * HTML element attributes or text `textContent` synchronized with attributes of an\n\t * {@link module:utils/observablemixin~Observable}. Learn more about {@link module:ui/template~BindChain#to}\n\t * and {@link module:ui/template~BindChain#if}.\n\t *\n\t *\t\tconst bind = Template.bind( observable, emitter );\n\t *\n\t *\t\tnew Template( {\n\t *\t\t\tattributes: {\n\t *\t\t\t\t// Binds the element \"class\" attribute to observable#classAttribute.\n\t *\t\t\t\tclass: bind.to( 'classAttribute' )\n\t *\t\t\t}\n\t *\t\t} ).render();\n\t *\n\t * * DOM events fired on HTML element propagated through\n\t * {@link module:utils/observablemixin~Observable}. Learn more about {@link module:ui/template~BindChain#to}.\n\t *\n\t *\t\tconst bind = Template.bind( observable, emitter );\n\t *\n\t *\t\tnew Template( {\n\t *\t\t\ton: {\n\t *\t\t\t\t// Will be fired by the observable.\n\t *\t\t\t\tclick: bind( 'elementClicked' )\n\t *\t\t\t}\n\t *\t\t} ).render();\n\t *\n\t * Also see {@link module:ui/view~View#bindTemplate}.\n\t *\n\t * @param {module:utils/observablemixin~Observable} observable An observable which provides boundable attributes.\n\t * @param {module:utils/emittermixin~Emitter} emitter An emitter that listens to observable attribute\n\t * changes or DOM Events (depending on the kind of the binding). Usually, a {@link module:ui/view~View} instance.\n\t * @returns {module:ui/template~BindChain}\n\t */\n\tstatic bind( observable, emitter ) {\n\t\treturn {\n\t\t\tto( eventNameOrFunctionOrAttribute, callback ) {\n\t\t\t\treturn new TemplateToBinding( {\n\t\t\t\t\teventNameOrFunction: eventNameOrFunctionOrAttribute,\n\t\t\t\t\tattribute: eventNameOrFunctionOrAttribute,\n\t\t\t\t\tobservable, emitter, callback\n\t\t\t\t} );\n\t\t\t},\n\n\t\t\tif( attribute, valueIfTrue, callback ) {\n\t\t\t\treturn new TemplateIfBinding( {\n\t\t\t\t\tobservable, emitter, attribute, valueIfTrue, callback\n\t\t\t\t} );\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Extends an existing {@link module:ui/template~Template} instance with some additional content\n\t * from another {@link module:ui/template~TemplateDefinition}.\n\t *\n\t *\t\tconst bind = Template.bind( observable, emitter );\n\t *\n\t *\t\tconst template = new Template( {\n\t *\t\t\ttag: 'p',\n\t *\t\t\tattributes: {\n\t *\t\t\t\tclass: 'a',\n\t *\t\t\t\tdata-x: bind.to( 'foo' )\n\t *\t\t\t},\n\t *\t\t\tchildren: [\n\t *\t\t\t\t{\n\t *\t\t\t\t\ttag: 'span',\n\t *\t\t\t\t\tattributes: {\n\t *\t\t\t\t\t\tclass: 'b'\n\t *\t\t\t\t\t},\n\t *\t\t\t\t\tchildren: [\n\t *\t\t\t\t\t\t'Span'\n\t *\t\t\t\t\t]\n\t *\t\t\t\t}\n\t *\t\t\t]\n\t *\t\t } );\n\t *\n\t *\t\t// Instance-level extension.\n\t *\t\tTemplate.extend( template, {\n\t *\t\t\tattributes: {\n\t *\t\t\t\tclass: 'b',\n\t *\t\t\t\tdata-x: bind.to( 'bar' )\n\t *\t\t\t},\n\t *\t\t\tchildren: [\n\t *\t\t\t\t{\n\t *\t\t\t\t\tattributes: {\n\t *\t\t\t\t\t\tclass: 'c'\n\t *\t\t\t\t\t}\n\t *\t\t\t\t}\n\t *\t\t\t]\n\t *\t\t} );\n\t *\n\t *\t\t// Child extension.\n\t *\t\tTemplate.extend( template.children[ 0 ], {\n\t *\t\t\tattributes: {\n\t *\t\t\t\tclass: 'd'\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * the `outerHTML` of `template.render()` is:\n\t *\n\t *\t\t<p class=\"a b\" data-x=\"{ observable.foo } { observable.bar }\">\n\t *\t\t\t<span class=\"b c d\">Span</span>\n\t *\t\t</p>\n\t *\n\t * @param {module:ui/template~Template} template An existing template instance to be extended.\n\t * @param {module:ui/template~TemplateDefinition} def Additional definition to be applied to a template.\n\t */\n\tstatic extend( template, def ) {\n\t\tif ( template._isRendered ) {\n\t\t\t/**\n\t\t\t * Extending a template after rendering may not work as expected. To make sure\n\t\t\t * the {@link module:ui/template~Template.extend extending} works for an element,\n\t\t\t * make sure it happens before {@link #render} is called.\n\t\t\t *\n\t\t\t * @error template-extend-render\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'template-extend-render: Attempting to extend a template which has already been rendered.',\n\t\t\t\t[ this, template ]\n\t\t\t);\n\t\t}\n\n\t\textendTemplate( template, normalize( clone( def ) ) );\n\t}\n\n\t/**\n\t * Renders a DOM Node (either an HTML element or text) out of the template.\n\t *\n\t * @protected\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t */\n\t_renderNode( data ) {\n\t\tlet isInvalid;\n\n\t\tif ( data.node ) {\n\t\t\t// When applying, a definition cannot have \"tag\" and \"text\" at the same time.\n\t\t\tisInvalid = this.tag && this.text;\n\t\t} else {\n\t\t\t// When rendering, a definition must have either \"tag\" or \"text\": XOR( this.tag, this.text ).\n\t\t\tisInvalid = this.tag ? this.text : !this.text;\n\t\t}\n\n\t\tif ( isInvalid ) {\n\t\t\t/**\n\t\t\t * Node definition cannot have the \"tag\" and \"text\" properties at the same time.\n\t\t\t * Node definition must have either \"tag\" or \"text\" when rendering a new Node.\n\t\t\t *\n\t\t\t * @error ui-template-wrong-syntax\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'ui-template-wrong-syntax: Node definition must have either \"tag\" or \"text\" when rendering a new Node.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tif ( this.text ) {\n\t\t\treturn this._renderText( data );\n\t\t} else {\n\t\t\treturn this._renderElement( data );\n\t\t}\n\t}\n\n\t/**\n\t * Renders an HTML element out of the template.\n\t *\n\t * @protected\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t */\n\t_renderElement( data ) {\n\t\tlet node = data.node;\n\n\t\tif ( !node ) {\n\t\t\tnode = data.node = document.createElementNS( this.ns || xhtmlNs, this.tag );\n\t\t}\n\n\t\tthis._renderAttributes( data );\n\t\tthis._renderElementChildren( data );\n\t\tthis._setUpListeners( data );\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Renders a text node out of {@link module:ui/template~Template#text}.\n\t *\n\t * @protected\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t */\n\t_renderText( data ) {\n\t\tlet node = data.node;\n\n\t\t// Save the original textContent to revert it in #revert().\n\t\tif ( node ) {\n\t\t\tdata.revertData.text = node.textContent;\n\t\t} else {\n\t\t\tnode = data.node = document.createTextNode( '' );\n\t\t}\n\n\t\t// Check if this Text Node is bound to Observable. Cases:\n\t\t//\n\t\t//\t\ttext: [ Template.bind( ... ).to( ... ) ]\n\t\t//\n\t\t//\t\ttext: [\n\t\t//\t\t\t'foo',\n\t\t//\t\t\tTemplate.bind( ... ).to( ... ),\n\t\t//\t\t\t...\n\t\t//\t\t]\n\t\t//\n\t\tif ( hasTemplateBinding( this.text ) ) {\n\t\t\tthis._bindToObservable( {\n\t\t\t\tschema: this.text,\n\t\t\t\tupdater: getTextUpdater( node ),\n\t\t\t\tdata\n\t\t\t} );\n\t\t}\n\t\t// Simply set text. Cases:\n\t\t//\n\t\t//\t\ttext: [ 'all', 'are', 'static' ]\n\t\t//\n\t\t//\t\ttext: [ 'foo' ]\n\t\t//\n\t\telse {\n\t\t\tnode.textContent = this.text.join( '' );\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Renders HTML element attributes out of {@link module:ui/template~Template#attributes}.\n\t *\n\t * @protected\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t */\n\t_renderAttributes( data ) {\n\t\tlet attrName, attrValue, domAttrValue, attrNs;\n\n\t\tif ( !this.attributes ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst node = data.node;\n\t\tconst revertData = data.revertData;\n\n\t\tfor ( attrName in this.attributes ) {\n\t\t\t// Current attribute value in DOM.\n\t\t\tdomAttrValue = node.getAttribute( attrName );\n\n\t\t\t// The value to be set.\n\t\t\tattrValue = this.attributes[ attrName ];\n\n\t\t\t// Save revert data.\n\t\t\tif ( revertData ) {\n\t\t\t\trevertData.attributes[ attrName ] = domAttrValue;\n\t\t\t}\n\n\t\t\t// Detect custom namespace:\n\t\t\t//\n\t\t\t//\t\tclass: {\n\t\t\t//\t\t\tns: 'abc',\n\t\t\t//\t\t\tvalue: Template.bind( ... ).to( ... )\n\t\t\t//\t\t}\n\t\t\t//\n\t\t\tattrNs = ( isObject( attrValue[ 0 ] ) && attrValue[ 0 ].ns ) ? attrValue[ 0 ].ns : null;\n\n\t\t\t// Activate binding if one is found. Cases:\n\t\t\t//\n\t\t\t//\t\tclass: [\n\t\t\t//\t\t\tTemplate.bind( ... ).to( ... )\n\t\t\t//\t\t]\n\t\t\t//\n\t\t\t//\t\tclass: [\n\t\t\t//\t\t\t'bar',\n\t\t\t//\t\t\tTemplate.bind( ... ).to( ... ),\n\t\t\t//\t\t\t'baz'\n\t\t\t//\t\t]\n\t\t\t//\n\t\t\t//\t\tclass: {\n\t\t\t//\t\t\tns: 'abc',\n\t\t\t//\t\t\tvalue: Template.bind( ... ).to( ... )\n\t\t\t//\t\t}\n\t\t\t//\n\t\t\tif ( hasTemplateBinding( attrValue ) ) {\n\t\t\t\t// Normalize attributes with additional data like namespace:\n\t\t\t\t//\n\t\t\t\t//\t\tclass: {\n\t\t\t\t//\t\t\tns: 'abc',\n\t\t\t\t//\t\t\tvalue: [ ... ]\n\t\t\t\t//\t\t}\n\t\t\t\t//\n\t\t\t\tconst valueToBind = attrNs ? attrValue[ 0 ].value : attrValue;\n\n\t\t\t\t// Extend the original value of attributes like \"style\" and \"class\",\n\t\t\t\t// don't override them.\n\t\t\t\tif ( revertData && shouldExtend( attrName ) ) {\n\t\t\t\t\tvalueToBind.unshift( domAttrValue );\n\t\t\t\t}\n\n\t\t\t\tthis._bindToObservable( {\n\t\t\t\t\tschema: valueToBind,\n\t\t\t\t\tupdater: getAttributeUpdater( node, attrName, attrNs ),\n\t\t\t\t\tdata\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Style attribute could be an Object so it needs to be parsed in a specific way.\n\t\t\t//\n\t\t\t//\t\tstyle: {\n\t\t\t//\t\t\twidth: '100px',\n\t\t\t//\t\t\theight: Template.bind( ... ).to( ... )\n\t\t\t//\t\t}\n\t\t\t//\n\t\t\telse if ( attrName == 'style' && typeof attrValue[ 0 ] !== 'string' ) {\n\t\t\t\tthis._renderStyleAttribute( attrValue[ 0 ], data );\n\t\t\t}\n\n\t\t\t// Otherwise simply set the static attribute:\n\t\t\t//\n\t\t\t//\t\tclass: [ 'foo' ]\n\t\t\t//\n\t\t\t//\t\tclass: [ 'all', 'are', 'static' ]\n\t\t\t//\n\t\t\t//\t\tclass: [\n\t\t\t//\t\t\t{\n\t\t\t//\t\t\t\tns: 'abc',\n\t\t\t//\t\t\t\tvalue: [ 'foo' ]\n\t\t\t//\t\t\t}\n\t\t\t//\t\t]\n\t\t\t//\n\t\t\telse {\n\t\t\t\t// Extend the original value of attributes like \"style\" and \"class\",\n\t\t\t\t// don't override them.\n\t\t\t\tif ( revertData && domAttrValue && shouldExtend( attrName ) ) {\n\t\t\t\t\tattrValue.unshift( domAttrValue );\n\t\t\t\t}\n\n\t\t\t\tattrValue = attrValue\n\t\t\t\t\t// Retrieve \"values\" from:\n\t\t\t\t\t//\n\t\t\t\t\t//\t\tclass: [\n\t\t\t\t\t//\t\t\t{\n\t\t\t\t\t//\t\t\t\tns: 'abc',\n\t\t\t\t\t//\t\t\t\tvalue: [ ... ]\n\t\t\t\t\t//\t\t\t}\n\t\t\t\t\t//\t\t]\n\t\t\t\t\t//\n\t\t\t\t\t.map( val => val ? ( val.value || val ) : val )\n\t\t\t\t\t// Flatten the array.\n\t\t\t\t\t.reduce( ( prev, next ) => prev.concat( next ), [] )\n\t\t\t\t\t// Convert into string.\n\t\t\t\t\t.reduce( arrayValueReducer, '' );\n\n\t\t\t\tif ( !isFalsy( attrValue ) ) {\n\t\t\t\t\tnode.setAttributeNS( attrNs, attrName, attrValue );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Renders the `style` attribute of an HTML element based on\n\t * {@link module:ui/template~Template#attributes}.\n\t *\n\t * A style attribute is an {Object} with static values:\n\t *\n\t *\t\tattributes: {\n\t *\t\t\tstyle: {\n\t *\t\t\t\tcolor: 'red'\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t * or values bound to {@link module:ui/model~Model} properties:\n\t *\n\t *\t\tattributes: {\n\t *\t\t\tstyle: {\n\t *\t\t\t\tcolor: bind.to( ... )\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t * Note: The `style` attribute is rendered without setting the namespace. It does not seem to be\n\t * needed.\n\t *\n\t * @private\n\t * @param {Object} styles Styles located in `attributes.style` of {@link module:ui/template~TemplateDefinition}.\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t */\n\t_renderStyleAttribute( styles, data ) {\n\t\tconst node = data.node;\n\n\t\tfor ( const styleName in styles ) {\n\t\t\tconst styleValue = styles[ styleName ];\n\n\t\t\t// Cases:\n\t\t\t//\n\t\t\t//\t\tstyle: {\n\t\t\t//\t\t\tcolor: bind.to( 'attribute' )\n\t\t\t//\t\t}\n\t\t\t//\n\t\t\tif ( hasTemplateBinding( styleValue ) ) {\n\t\t\t\tthis._bindToObservable( {\n\t\t\t\t\tschema: [ styleValue ],\n\t\t\t\t\tupdater: getStyleUpdater( node, styleName ),\n\t\t\t\t\tdata\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Cases:\n\t\t\t//\n\t\t\t//\t\tstyle: {\n\t\t\t//\t\t\tcolor: 'red'\n\t\t\t//\t\t}\n\t\t\t//\n\t\t\telse {\n\t\t\t\tnode.style[ styleName ] = styleValue;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Recursively renders HTML element's children from {@link module:ui/template~Template#children}.\n\t *\n\t * @protected\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t */\n\t_renderElementChildren( data ) {\n\t\tconst node = data.node;\n\t\tconst container = data.intoFragment ? document.createDocumentFragment() : node;\n\t\tconst isApplying = data.isApplying;\n\t\tlet childIndex = 0;\n\n\t\tfor ( const child of this.children ) {\n\t\t\tif ( isViewCollection( child ) ) {\n\t\t\t\tif ( !isApplying ) {\n\t\t\t\t\tchild.setParent( node );\n\n\t\t\t\t\t// Note: ViewCollection renders its children.\n\t\t\t\t\tfor ( const view of child ) {\n\t\t\t\t\t\tcontainer.appendChild( view.element );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( isView( child ) ) {\n\t\t\t\tif ( !isApplying ) {\n\t\t\t\t\tif ( !child.isRendered ) {\n\t\t\t\t\t\tchild.render();\n\t\t\t\t\t}\n\n\t\t\t\t\tcontainer.appendChild( child.element );\n\t\t\t\t}\n\t\t\t} else if ( isNode( child ) ) {\n\t\t\t\tcontainer.appendChild( child );\n\t\t\t} else {\n\t\t\t\tif ( isApplying ) {\n\t\t\t\t\tconst revertData = data.revertData;\n\t\t\t\t\tconst childRevertData = getEmptyRevertData();\n\n\t\t\t\t\trevertData.children.push( childRevertData );\n\n\t\t\t\t\tchild._renderNode( {\n\t\t\t\t\t\tnode: container.childNodes[ childIndex++ ],\n\t\t\t\t\t\tisApplying: true,\n\t\t\t\t\t\trevertData: childRevertData\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\tcontainer.appendChild( child.render() );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( data.intoFragment ) {\n\t\t\tnode.appendChild( container );\n\t\t}\n\t}\n\n\t/**\n\t * Activates `on` event listeners from the {@link module:ui/template~TemplateDefinition}\n\t * on an HTML element.\n\t *\n\t * @protected\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t */\n\t_setUpListeners( data ) {\n\t\tif ( !this.eventListeners ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( const key in this.eventListeners ) {\n\t\t\tconst revertBindings = this.eventListeners[ key ].map( schemaItem => {\n\t\t\t\tconst [ domEvtName, domSelector ] = key.split( '@' );\n\n\t\t\t\treturn schemaItem.activateDomEventListener( domEvtName, domSelector, data );\n\t\t\t} );\n\n\t\t\tif ( data.revertData ) {\n\t\t\t\tdata.revertData.bindings.push( revertBindings );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * For a given {@link module:ui/template~TemplateValueSchema} containing {@link module:ui/template~TemplateBinding}\n\t * activates the binding and sets its initial value.\n\t *\n\t * Note: {@link module:ui/template~TemplateValueSchema} can be for HTML element attributes or\n\t * text node `textContent`.\n\t *\n\t * @protected\n\t * @param {Object} options Binding options.\n\t * @param {module:ui/template~TemplateValueSchema} options.schema\n\t * @param {Function} options.updater A function which updates the DOM (like attribute or text).\n\t * @param {module:ui/template~RenderData} options.data Rendering data.\n\t */\n\t_bindToObservable( { schema, updater, data } ) {\n\t\tconst revertData = data.revertData;\n\n\t\t// Set initial values.\n\t\tsyncValueSchemaValue( schema, updater, data );\n\n\t\tconst revertBindings = schema\n\t\t\t// Filter \"falsy\" (false, undefined, null, '') value schema components out.\n\t\t\t.filter( item => !isFalsy( item ) )\n\t\t\t// Filter inactive bindings from schema, like static strings ('foo'), numbers (42), etc.\n\t\t\t.filter( item => item.observable )\n\t\t\t// Once only the actual binding are left, let the emitter listen to observable change:attribute event.\n\t\t\t// TODO: Reduce the number of listeners attached as many bindings may listen\n\t\t\t// to the same observable attribute.\n\t\t\t.map( templateBinding => templateBinding.activateAttributeListener( schema, updater, data ) );\n\n\t\tif ( revertData ) {\n\t\t\trevertData.bindings.push( revertBindings );\n\t\t}\n\t}\n\n\t/**\n\t * Reverts {@link module:ui/template~RenderData#revertData template data} from a node to\n\t * return it to the original state.\n\t *\n\t * @protected\n\t * @param {HTMLElement|Text} node A node to be reverted.\n\t * @param {Object} revertData An object that stores information about what changes have been made by\n\t * {@link #apply} to the node. See {@link module:ui/template~RenderData#revertData} for more information.\n\t */\n\t_revertTemplateFromNode( node, revertData ) {\n\t\tfor ( const binding of revertData.bindings ) {\n\t\t\t// Each binding may consist of several observable+observable#attribute.\n\t\t\t// like the following has 2:\n\t\t\t//\n\t\t\t//\t\tclass: [\n\t\t\t//\t\t\t'x',\n\t\t\t//\t\t\tbind.to( 'foo' ),\n\t\t\t//\t\t\t'y',\n\t\t\t//\t\t\tbind.to( 'bar' )\n\t\t\t//\t\t]\n\t\t\t//\n\t\t\tfor ( const revertBinding of binding ) {\n\t\t\t\trevertBinding();\n\t\t\t}\n\t\t}\n\n\t\tif ( revertData.text ) {\n\t\t\tnode.textContent = revertData.text;\n\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( const attrName in revertData.attributes ) {\n\t\t\tconst attrValue = revertData.attributes[ attrName ];\n\n\t\t\t// When the attribute has **not** been set before #apply().\n\t\t\tif ( attrValue === null ) {\n\t\t\t\tnode.removeAttribute( attrName );\n\t\t\t} else {\n\t\t\t\tnode.setAttribute( attrName, attrValue );\n\t\t\t}\n\t\t}\n\n\t\tfor ( let i = 0; i < revertData.children.length; ++i ) {\n\t\t\tthis._revertTemplateFromNode( node.childNodes[ i ], revertData.children[ i ] );\n\t\t}\n\t}\n}\n\nmix( Template, EmitterMixin );\n\n/**\n * Describes a binding created by the {@link module:ui/template~Template.bind} interface.\n *\n * @protected\n */\nexport class TemplateBinding {\n\t/**\n\t * Creates an instance of the {@link module:ui/template~TemplateBinding} class.\n\t *\n\t * @param {module:ui/template~TemplateDefinition} def The definition of the binding.\n\t */\n\tconstructor( def ) {\n\t\tObject.assign( this, def );\n\n\t\t/**\n\t\t * An observable instance of the binding. It either:\n\t\t *\n\t\t * * provides the attribute with the value,\n\t\t * * or passes the event when a corresponding DOM event is fired.\n\t\t *\n\t\t * @member {module:utils/observablemixin~ObservableMixin} module:ui/template~TemplateBinding#observable\n\t\t */\n\n\t\t/**\n\t\t * An {@link module:utils/emittermixin~Emitter} used by the binding to:\n\t\t *\n\t\t * * listen to the attribute change in the {@link module:ui/template~TemplateBinding#observable},\n\t\t * * or listen to the event in the DOM.\n\t\t *\n\t\t * @member {module:utils/emittermixin~EmitterMixin} module:ui/template~TemplateBinding#emitter\n\t\t */\n\n\t\t/**\n\t\t * The name of the {@link module:ui/template~TemplateBinding#observable observed attribute}.\n\t\t *\n\t\t * @member {String} module:ui/template~TemplateBinding#attribute\n\t\t */\n\n\t\t/**\n\t\t * A custom function to process the value of the {@link module:ui/template~TemplateBinding#attribute}.\n\t\t *\n\t\t * @member {Function} [module:ui/template~TemplateBinding#callback]\n\t\t */\n\t}\n\n\t/**\n\t * Returns the value of the binding. It is the value of the {@link module:ui/template~TemplateBinding#attribute} in\n\t * {@link module:ui/template~TemplateBinding#observable}. The value may be processed by the\n\t * {@link module:ui/template~TemplateBinding#callback}, if such has been passed to the binding.\n\t *\n\t * @param {Node} [node] A native DOM node, passed to the custom {@link module:ui/template~TemplateBinding#callback}.\n\t * @returns {*} The value of {@link module:ui/template~TemplateBinding#attribute} in\n\t * {@link module:ui/template~TemplateBinding#observable}.\n\t */\n\tgetValue( node ) {\n\t\tconst value = this.observable[ this.attribute ];\n\n\t\treturn this.callback ? this.callback( value, node ) : value;\n\t}\n\n\t/**\n\t * Activates the listener which waits for changes of the {@link module:ui/template~TemplateBinding#attribute} in\n\t * {@link module:ui/template~TemplateBinding#observable}, then updates the DOM with the aggregated\n\t * value of {@link module:ui/template~TemplateValueSchema}.\n\t *\n\t * @param {module:ui/template~TemplateValueSchema} schema A full schema to generate an attribute or text in the DOM.\n\t * @param {Function} updater A DOM updater function used to update the native DOM attribute or text.\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t * @returns {Function} A function to sever the listener binding.\n\t */\n\tactivateAttributeListener( schema, updater, data ) {\n\t\tconst callback = () => syncValueSchemaValue( schema, updater, data );\n\n\t\tthis.emitter.listenTo( this.observable, 'change:' + this.attribute, callback );\n\n\t\t// Allows revert of the listener.\n\t\treturn () => {\n\t\t\tthis.emitter.stopListening( this.observable, 'change:' + this.attribute, callback );\n\t\t};\n\t}\n}\n\n/**\n * Describes either:\n *\n * * a binding to an {@link module:utils/observablemixin~Observable},\n * * or a native DOM event binding.\n *\n * It is created by the {@link module:ui/template~BindChain#to} method.\n *\n * @protected\n */\nexport class TemplateToBinding extends TemplateBinding {\n\t/**\n\t * Activates the listener for the native DOM event, which when fired, is propagated by\n\t * the {@link module:ui/template~TemplateBinding#emitter}.\n\t *\n\t * @param {String} domEvtName The name of the native DOM event.\n\t * @param {String} domSelector The selector in the DOM to filter delegated events.\n\t * @param {module:ui/template~RenderData} data Rendering data.\n\t * @returns {Function} A function to sever the listener binding.\n\t */\n\tactivateDomEventListener( domEvtName, domSelector, data ) {\n\t\tconst callback = ( evt, domEvt ) => {\n\t\t\tif ( !domSelector || domEvt.target.matches( domSelector ) ) {\n\t\t\t\tif ( typeof this.eventNameOrFunction == 'function' ) {\n\t\t\t\t\tthis.eventNameOrFunction( domEvt );\n\t\t\t\t} else {\n\t\t\t\t\tthis.observable.fire( this.eventNameOrFunction, domEvt );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthis.emitter.listenTo( data.node, domEvtName, callback );\n\n\t\t// Allows revert of the listener.\n\t\treturn () => {\n\t\t\tthis.emitter.stopListening( data.node, domEvtName, callback );\n\t\t};\n\t}\n}\n\n/**\n * Describes a binding to {@link module:utils/observablemixin~ObservableMixin} created by the {@link module:ui/template~BindChain#if}\n * method.\n *\n * @protected\n */\nexport class TemplateIfBinding extends TemplateBinding {\n\t/**\n\t * @inheritDoc\n\t */\n\tgetValue( node ) {\n\t\tconst value = super.getValue( node );\n\n\t\treturn isFalsy( value ) ? false : ( this.valueIfTrue || true );\n\t}\n\n\t/**\n\t * The value of the DOM attribute or text to be set if the {@link module:ui/template~TemplateBinding#attribute} in\n\t * {@link module:ui/template~TemplateBinding#observable} is `true`.\n\t *\n\t * @member {String} [module:ui/template~TemplateIfBinding#valueIfTrue]\n\t */\n}\n\n// Checks whether given {@link module:ui/template~TemplateValueSchema} contains a\n// {@link module:ui/template~TemplateBinding}.\n//\n// @param {module:ui/template~TemplateValueSchema} schema\n// @returns {Boolean}\nfunction hasTemplateBinding( schema ) {\n\tif ( !schema ) {\n\t\treturn false;\n\t}\n\n\t// Normalize attributes with additional data like namespace:\n\t//\n\t//\t\tclass: {\n\t//\t\t\tns: 'abc',\n\t//\t\t\tvalue: [ ... ]\n\t//\t\t}\n\t//\n\tif ( schema.value ) {\n\t\tschema = schema.value;\n\t}\n\n\tif ( Array.isArray( schema ) ) {\n\t\treturn schema.some( hasTemplateBinding );\n\t} else if ( schema instanceof TemplateBinding ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n// Assembles the value using {@link module:ui/template~TemplateValueSchema} and stores it in a form of\n// an Array. Each entry of the Array corresponds to one of {@link module:ui/template~TemplateValueSchema}\n// items.\n//\n// @param {module:ui/template~TemplateValueSchema} schema\n// @param {Node} node DOM Node updated when {@link module:utils/observablemixin~ObservableMixin} changes.\n// @returns {Array}\nfunction getValueSchemaValue( schema, node ) {\n\treturn schema.map( schemaItem => {\n\t\t// Process {@link module:ui/template~TemplateBinding} bindings.\n\t\tif ( schemaItem instanceof TemplateBinding ) {\n\t\t\treturn schemaItem.getValue( node );\n\t\t}\n\n\t\t// All static values like strings, numbers, and \"falsy\" values (false, null, undefined, '', etc.) just pass.\n\t\treturn schemaItem;\n\t} );\n}\n\n// A function executed each time the bound Observable attribute changes, which updates the DOM with a value\n// constructed from {@link module:ui/template~TemplateValueSchema}.\n//\n// @param {module:ui/template~TemplateValueSchema} schema\n// @param {Function} updater A function which updates the DOM (like attribute or text).\n// @param {Node} node DOM Node updated when {@link module:utils/observablemixin~ObservableMixin} changes.\nfunction syncValueSchemaValue( schema, updater, { node } ) {\n\tlet value = getValueSchemaValue( schema, node );\n\n\t// Check if schema is a single Template.bind.if, like:\n\t//\n\t//\t\tclass: Template.bind.if( 'foo' )\n\t//\n\tif ( schema.length == 1 && schema[ 0 ] instanceof TemplateIfBinding ) {\n\t\tvalue = value[ 0 ];\n\t} else {\n\t\tvalue = value.reduce( arrayValueReducer, '' );\n\t}\n\n\tif ( isFalsy( value ) ) {\n\t\tupdater.remove();\n\t} else {\n\t\tupdater.set( value );\n\t}\n}\n\n// Returns an object consisting of `set` and `remove` functions, which\n// can be used in the context of DOM Node to set or reset `textContent`.\n// @see module:ui/view~View#_bindToObservable\n//\n// @param {Node} node DOM Node to be modified.\n// @returns {Object}\nfunction getTextUpdater( node ) {\n\treturn {\n\t\tset( value ) {\n\t\t\tnode.textContent = value;\n\t\t},\n\n\t\tremove() {\n\t\t\tnode.textContent = '';\n\t\t}\n\t};\n}\n\n// Returns an object consisting of `set` and `remove` functions, which\n// can be used in the context of DOM Node to set or reset an attribute.\n// @see module:ui/view~View#_bindToObservable\n//\n// @param {Node} node DOM Node to be modified.\n// @param {String} attrName Name of the attribute to be modified.\n// @param {String} [ns=null] Namespace to use.\n// @returns {Object}\nfunction getAttributeUpdater( el, attrName, ns ) {\n\treturn {\n\t\tset( value ) {\n\t\t\tel.setAttributeNS( ns, attrName, value );\n\t\t},\n\n\t\tremove() {\n\t\t\tel.removeAttributeNS( ns, attrName );\n\t\t}\n\t};\n}\n\n// Returns an object consisting of `set` and `remove` functions, which\n// can be used in the context of CSSStyleDeclaration to set or remove a style.\n// @see module:ui/view~View#_bindToObservable\n//\n// @param {Node} node DOM Node to be modified.\n// @param {String} styleName Name of the style to be modified.\n// @returns {Object}\nfunction getStyleUpdater( el, styleName ) {\n\treturn {\n\t\tset( value ) {\n\t\t\tel.style[ styleName ] = value;\n\t\t},\n\n\t\tremove() {\n\t\t\tel.style[ styleName ] = null;\n\t\t}\n\t};\n}\n\n// Clones definition of the template.\n//\n// @param {module:ui/template~TemplateDefinition} def\n// @returns {module:ui/template~TemplateDefinition}\nfunction clone( def ) {\n\tconst clone = cloneDeepWith( def, value => {\n\t\t// Don't clone the `Template.bind`* bindings because of the references to Observable\n\t\t// and DomEmitterMixin instances inside, which would also be traversed and cloned by greedy\n\t\t// cloneDeepWith algorithm. There's no point in cloning Observable/DomEmitterMixins\n\t\t// along with the definition.\n\t\t//\n\t\t// Don't clone Template instances if provided as a child. They're simply #render()ed\n\t\t// and nothing should interfere.\n\t\t//\n\t\t// Also don't clone View instances if provided as a child of the Template. The template\n\t\t// instance will be extracted from the View during the normalization and there's no need\n\t\t// to clone it.\n\t\tif ( value && ( value instanceof TemplateBinding || isTemplate( value ) || isView( value ) || isViewCollection( value ) ) ) {\n\t\t\treturn value;\n\t\t}\n\t} );\n\n\treturn clone;\n}\n\n// Normalizes given {@link module:ui/template~TemplateDefinition}.\n//\n// See:\n// * {@link normalizeAttributes}\n// * {@link normalizeListeners}\n// * {@link normalizePlainTextDefinition}\n// * {@link normalizeTextDefinition}\n//\n// @param {module:ui/template~TemplateDefinition} def\n// @returns {module:ui/template~TemplateDefinition} Normalized definition.\nfunction normalize( def ) {\n\tif ( typeof def == 'string' ) {\n\t\tdef = normalizePlainTextDefinition( def );\n\t} else if ( def.text ) {\n\t\tnormalizeTextDefinition( def );\n\t}\n\n\tif ( def.on ) {\n\t\tdef.eventListeners = normalizeListeners( def.on );\n\n\t\t// Template mixes EmitterMixin, so delete #on to avoid collision.\n\t\tdelete def.on;\n\t}\n\n\tif ( !def.text ) {\n\t\tif ( def.attributes ) {\n\t\t\tnormalizeAttributes( def.attributes );\n\t\t}\n\n\t\tconst children = [];\n\n\t\tif ( def.children ) {\n\t\t\tif ( isViewCollection( def.children ) ) {\n\t\t\t\tchildren.push( def.children );\n\t\t\t} else {\n\t\t\t\tfor ( const child of def.children ) {\n\t\t\t\t\tif ( isTemplate( child ) || isView( child ) || isNode( child ) ) {\n\t\t\t\t\t\tchildren.push( child );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchildren.push( new Template( child ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdef.children = children;\n\t}\n\n\treturn def;\n}\n\n// Normalizes \"attributes\" section of {@link module:ui/template~TemplateDefinition}.\n//\n//\t\tattributes: {\n//\t\t\ta: 'bar',\n//\t\t\tb: {@link module:ui/template~TemplateBinding},\n//\t\t\tc: {\n//\t\t\t\tvalue: 'bar'\n//\t\t\t}\n//\t\t}\n//\n// becomes\n//\n//\t\tattributes: {\n//\t\t\ta: [ 'bar' ],\n//\t\t\tb: [ {@link module:ui/template~TemplateBinding} ],\n//\t\t\tc: {\n//\t\t\t\tvalue: [ 'bar' ]\n//\t\t\t}\n//\t\t}\n//\n// @param {Object} attributes\nfunction normalizeAttributes( attributes ) {\n\tfor ( const a in attributes ) {\n\t\tif ( attributes[ a ].value ) {\n\t\t\tattributes[ a ].value = [].concat( attributes[ a ].value );\n\t\t}\n\n\t\tarrayify( attributes, a );\n\t}\n}\n\n// Normalizes \"on\" section of {@link module:ui/template~TemplateDefinition}.\n//\n//\t\ton: {\n//\t\t\ta: 'bar',\n//\t\t\tb: {@link module:ui/template~TemplateBinding},\n//\t\t\tc: [ {@link module:ui/template~TemplateBinding}, () => { ... } ]\n//\t\t}\n//\n// becomes\n//\n//\t\ton: {\n//\t\t\ta: [ 'bar' ],\n//\t\t\tb: [ {@link module:ui/template~TemplateBinding} ],\n//\t\t\tc: [ {@link module:ui/template~TemplateBinding}, () => { ... } ]\n//\t\t}\n//\n// @param {Object} listeners\n// @returns {Object} Object containing normalized listeners.\nfunction normalizeListeners( listeners ) {\n\tfor ( const l in listeners ) {\n\t\tarrayify( listeners, l );\n\t}\n\n\treturn listeners;\n}\n\n// Normalizes \"string\" {@link module:ui/template~TemplateDefinition}.\n//\n//\t\t\"foo\"\n//\n// becomes\n//\n//\t\t{ text: [ 'foo' ] },\n//\n// @param {String} def\n// @returns {module:ui/template~TemplateDefinition} Normalized template definition.\nfunction normalizePlainTextDefinition( def ) {\n\treturn {\n\t\ttext: [ def ]\n\t};\n}\n\n// Normalizes text {@link module:ui/template~TemplateDefinition}.\n//\n//\t\tchildren: [\n//\t\t\t{ text: 'def' },\n//\t\t\t{ text: {@link module:ui/template~TemplateBinding} }\n//\t\t]\n//\n// becomes\n//\n//\t\tchildren: [\n//\t\t\t{ text: [ 'def' ] },\n//\t\t\t{ text: [ {@link module:ui/template~TemplateBinding} ] }\n//\t\t]\n//\n// @param {module:ui/template~TemplateDefinition} def\nfunction normalizeTextDefinition( def ) {\n\tif ( !Array.isArray( def.text ) ) {\n\t\tdef.text = [ def.text ];\n\t}\n}\n\n// Wraps an entry in Object in an Array, if not already one.\n//\n//\t\t{\n//\t\t\tx: 'y',\n//\t\t\ta: [ 'b' ]\n//\t\t}\n//\n// becomes\n//\n//\t\t{\n//\t\t\tx: [ 'y' ],\n//\t\t\ta: [ 'b' ]\n//\t\t}\n//\n// @param {Object} obj\n// @param {String} key\nfunction arrayify( obj, key ) {\n\tif ( !Array.isArray( obj[ key ] ) ) {\n\t\tobj[ key ] = [ obj[ key ] ];\n\t}\n}\n\n// A helper which concatenates the value avoiding unwanted\n// leading white spaces.\n//\n// @param {String} prev\n// @param {String} cur\n// @returns {String}\nfunction arrayValueReducer( prev, cur ) {\n\tif ( isFalsy( cur ) ) {\n\t\treturn prev;\n\t} else if ( isFalsy( prev ) ) {\n\t\treturn cur;\n\t} else {\n\t\treturn `${ prev } ${ cur }`;\n\t}\n}\n\n// Extends one object defined in the following format:\n//\n//\t\t{\n//\t\t\tkey1: [Array1],\n//\t\t\tkey2: [Array2],\n//\t\t\t...\n//\t\t\tkeyN: [ArrayN]\n//\t\t}\n//\n// with another object of the same data format.\n//\n// @param {Object} obj Base object.\n// @param {Object} ext Object extending base.\n// @returns {String}\nfunction extendObjectValueArray( obj, ext ) {\n\tfor ( const a in ext ) {\n\t\tif ( obj[ a ] ) {\n\t\t\tobj[ a ].push( ...ext[ a ] );\n\t\t} else {\n\t\t\tobj[ a ] = ext[ a ];\n\t\t}\n\t}\n}\n\n// A helper for {@link module:ui/template~Template#extend}. Recursively extends {@link module:ui/template~Template} instance\n// with content from {@link module:ui/template~TemplateDefinition}. See {@link module:ui/template~Template#extend} to learn more.\n//\n// @param {module:ui/template~Template} def A template instance to be extended.\n// @param {module:ui/template~TemplateDefinition} def A definition which is to extend the template instance.\n// @param {Object} Error context.\nfunction extendTemplate( template, def ) {\n\tif ( def.attributes ) {\n\t\tif ( !template.attributes ) {\n\t\t\ttemplate.attributes = {};\n\t\t}\n\n\t\textendObjectValueArray( template.attributes, def.attributes );\n\t}\n\n\tif ( def.eventListeners ) {\n\t\tif ( !template.eventListeners ) {\n\t\t\ttemplate.eventListeners = {};\n\t\t}\n\n\t\textendObjectValueArray( template.eventListeners, def.eventListeners );\n\t}\n\n\tif ( def.text ) {\n\t\ttemplate.text.push( ...def.text );\n\t}\n\n\tif ( def.children && def.children.length ) {\n\t\tif ( template.children.length != def.children.length ) {\n\t\t\t/**\n\t\t\t * The number of children in extended definition does not match.\n\t\t\t *\n\t\t\t * @error ui-template-extend-children-mismatch\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'ui-template-extend-children-mismatch: The number of children in extended definition does not match.',\n\t\t\t\ttemplate\n\t\t\t);\n\t\t}\n\n\t\tlet childIndex = 0;\n\n\t\tfor ( const childDef of def.children ) {\n\t\t\textendTemplate( template.children[ childIndex++ ], childDef );\n\t\t}\n\t}\n}\n\n// Checks if value is \"falsy\".\n// Note: 0 (Number) is not \"falsy\" in this context.\n//\n// @private\n// @param {*} value Value to be checked.\nfunction isFalsy( value ) {\n\treturn !value && value !== 0;\n}\n\n// Checks if the item is an instance of {@link module:ui/view~View}\n//\n// @private\n// @param {*} value Value to be checked.\nfunction isView( item ) {\n\treturn item instanceof View;\n}\n\n// Checks if the item is an instance of {@link module:ui/template~Template}\n//\n// @private\n// @param {*} value Value to be checked.\nfunction isTemplate( item ) {\n\treturn item instanceof Template;\n}\n\n// Checks if the item is an instance of {@link module:ui/viewcollection~ViewCollection}\n//\n// @private\n// @param {*} value Value to be checked.\nfunction isViewCollection( item ) {\n\treturn item instanceof ViewCollection;\n}\n\n// Creates an empty skeleton for {@link module:ui/template~Template#revert}\n// data.\n//\n// @private\nfunction getEmptyRevertData() {\n\treturn {\n\t\tchildren: [],\n\t\tbindings: [],\n\t\tattributes: {}\n\t};\n}\n\n// Checks whether an attribute should be extended when\n// {@link module:ui/template~Template#apply} is called.\n//\n// @private\n// @param {String} attrName Attribute name to check.\nfunction shouldExtend( attrName ) {\n\treturn attrName == 'class' || attrName == 'style';\n}\n\n/**\n * A definition of the {@link module:ui/template~Template}. It describes what kind of\n * node a template will render (HTML element or text), attributes of an element, DOM event\n * listeners and children.\n *\n * Also see:\n * * {@link module:ui/template~TemplateValueSchema} to learn about HTML element attributes,\n * * {@link module:ui/template~TemplateListenerSchema} to learn about DOM event listeners.\n *\n * A sample definition on an HTML element can look like this:\n *\n *\t\tnew Template( {\n *\t\t\ttag: 'p',\n *\t\t\tchildren: [\n *\t\t\t\t{\n *\t\t\t\t\ttag: 'span',\n *\t\t\t\t\tattributes: { ... },\n *\t\t\t\t\tchildren: [ ... ],\n *\t\t\t\t},\n *\t\t\t\t{\n *\t\t\t\t\ttext: 'static–text'\n *\t\t\t\t},\n *\t\t\t\t'also-static–text',\n *\t\t\t],\n *\t\t\tattributes: {\n *\t\t\t\tclass: {@link module:ui/template~TemplateValueSchema},\n *\t\t\t\tid: {@link module:ui/template~TemplateValueSchema},\n *\t\t\t\tstyle: {@link module:ui/template~TemplateValueSchema}\n *\n *\t\t\t\t// ...\n *\t\t\t},\n *\t\t\ton: {\n *\t\t\t\t'click': {@link module:ui/template~TemplateListenerSchema}\n *\n *\t\t\t\t// Document.querySelector format is also accepted.\n *\t\t\t\t'keyup@a.some-class': {@link module:ui/template~TemplateListenerSchema}\n *\n *\t\t\t\t// ...\n *\t\t\t}\n *\t\t} );\n *\n * A {@link module:ui/view~View}, another {@link module:ui/template~Template} or a native DOM node\n * can also become a child of a template. When a view is passed, its {@link module:ui/view~View#element} is used:\n *\n *\t\tconst view = new SomeView();\n *\t\tconst childTemplate = new Template( { ... } );\n *\t\tconst childNode = document.createElement( 'b' );\n *\n *\t\tnew Template( {\n *\t\t\ttag: 'p',\n *\n *\t\t\tchildren: [\n *\t\t\t\t// view#element will be added as a child of this <p>.\n *\t\t\t\tview,\n *\n * \t\t\t\t// The output of childTemplate.render() will be added here.\n *\t\t\t\tchildTemplate,\n *\n *\t\t\t\t// Native DOM nodes are included directly in the rendered output.\n *\t\t\t\tchildNode\n *\t\t\t]\n *\t\t} );\n *\n * An entire {@link module:ui/viewcollection~ViewCollection} can be used as a child in the definition:\n *\n *\t\tconst collection = new ViewCollection();\n *\t\tcollection.add( someView );\n *\n *\t\tnew Template( {\n *\t\t\ttag: 'p',\n *\n *\t\t\tchildren: collection\n *\t\t} );\n *\n * @typedef module:ui/template~TemplateDefinition\n * @type Object\n *\n * @property {String} tag See the template {@link module:ui/template~Template#tag} property.\n *\n * @property {Array.<module:ui/template~TemplateDefinition>} [children]\n * See the template {@link module:ui/template~Template#children} property.\n *\n * @property {Object.<String, module:ui/template~TemplateValueSchema>} [attributes]\n * See the template {@link module:ui/template~Template#attributes} property.\n *\n * @property {String|module:ui/template~TemplateValueSchema|Array.<String|module:ui/template~TemplateValueSchema>} [text]\n * See the template {@link module:ui/template~Template#text} property.\n *\n * @property {Object.<String, module:ui/template~TemplateListenerSchema>} [on]\n * See the template {@link module:ui/template~Template#eventListeners} property.\n */\n\n/**\n * Describes a value of an HTML element attribute or `textContent`. It allows combining multiple\n * data sources like static values and {@link module:utils/observablemixin~Observable} attributes.\n *\n * Also see:\n * * {@link module:ui/template~TemplateDefinition} to learn where to use it,\n * * {@link module:ui/template~Template.bind} to learn how to configure\n * {@link module:utils/observablemixin~Observable} attribute bindings,\n * * {@link module:ui/template~Template#render} to learn how to render a template,\n * * {@link module:ui/template~BindChain#to `to()`} and {@link module:ui/template~BindChain#if `if()`}\n * methods to learn more about bindings.\n *\n * Attribute values can be described in many different ways:\n *\n *\t\t// Bind helper will create bindings to attributes of the observable.\n *\t\tconst bind = Template.bind( observable, emitter );\n *\n *\t\tnew Template( {\n *\t\t\ttag: 'p',\n *\t\t\tattributes: {\n *\t\t\t\t// A plain string schema.\n *\t\t\t\t'class': 'static-text',\n *\n *\t\t\t\t// An object schema, binds to the \"foo\" attribute of the\n *\t\t\t\t// observable and follows its value.\n *\t\t\t\t'class': bind.to( 'foo' ),\n *\n *\t\t\t\t// An array schema, combines the above.\n *\t\t\t\t'class': [\n *\t\t\t\t\t'static-text',\n *\t\t\t\t\tbind.to( 'bar', () => { ... } ),\n *\n * \t\t\t\t\t// Bindings can also be conditional.\n *\t\t\t\t\tbind.if( 'baz', 'class-when-baz-is-true' )\n *\t\t\t\t],\n *\n *\t\t\t\t// An array schema, with a custom namespace, e.g. useful for creating SVGs.\n *\t\t\t\t'class': {\n *\t\t\t\t\tns: 'http://ns.url',\n *\t\t\t\t\tvalue: [\n *\t\t\t\t\t\tbind.if( 'baz', 'value-when-true' ),\n *\t\t\t\t\t\t'static-text'\n *\t\t\t\t\t]\n *\t\t\t\t},\n *\n *\t\t\t\t// An object schema, specific for styles.\n *\t\t\t\tstyle: {\n *\t\t\t\t\tcolor: 'red',\n *\t\t\t\t\tbackgroundColor: bind.to( 'qux', () => { ... } )\n *\t\t\t\t}\n *\t\t\t}\n *\t\t} );\n *\n * Text nodes can also have complex values:\n *\n *\t\tconst bind = Template.bind( observable, emitter );\n *\n *\t\t// Will render a \"foo\" text node.\n *\t\tnew Template( {\n *\t\t\ttext: 'foo'\n *\t\t} );\n *\n *\t\t// Will render a \"static text: {observable.foo}\" text node.\n *\t\t// The text of the node will be updated as the \"foo\" attribute changes.\n *\t\tnew Template( {\n *\t\t\ttext: [\n *\t\t\t\t'static text: ',\n *\t\t\t\tbind.to( 'foo', () => { ... } )\n *\t\t\t]\n *\t\t} );\n *\n * @typedef module:ui/template~TemplateValueSchema\n * @type {Object|String|Array}\n */\n\n/**\n * Describes an event listener attached to an HTML element. Such listener can propagate DOM events\n * through an {@link module:utils/observablemixin~Observable} instance, execute custom callbacks\n * or both, if necessary.\n *\n * Also see:\n * * {@link module:ui/template~TemplateDefinition} to learn more about template definitions,\n * * {@link module:ui/template~BindChain#to `to()`} method to learn more about bindings.\n *\n * Check out different ways of attaching event listeners below:\n *\n *\t\t// Bind helper will propagate events through the observable.\n *\t\tconst bind = Template.bind( observable, emitter );\n *\n *\t\tnew Template( {\n *\t\t\ttag: 'p',\n *\t\t\ton: {\n *\t\t\t\t// An object schema. The observable will fire the \"clicked\" event upon DOM \"click\".\n *\t\t\t\tclick: bind.to( 'clicked' )\n *\n *\t\t\t\t// An object schema. It will work for \"click\" event on \"a.foo\" children only.\n *\t\t\t\t'click@a.foo': bind.to( 'clicked' )\n *\n *\t\t\t\t// An array schema, makes the observable propagate multiple events.\n *\t\t\t\tclick: [\n *\t\t\t\t\tbind.to( 'clicked' ),\n *\t\t\t\t\tbind.to( 'executed' )\n *\t\t\t\t],\n *\n *\t\t\t\t// An array schema with a custom callback.\n *\t\t\t\t'click@a.foo': {\n *\t\t\t\t\tbind.to( 'clicked' ),\n *\t\t\t\t\tbind.to( evt => {\n *\t\t\t\t\t\tconsole.log( `${ evt.target } has been clicked!` );\n *\t\t\t\t\t} }\n *\t\t\t\t}\n *\t\t\t}\n *\t\t} );\n *\n * @typedef module:ui/template~TemplateListenerSchema\n * @type {Object|String|Array}\n */\n\n/**\n * The return value of {@link ~Template.bind `Template.bind()`}. It provides `to()` and `if()`\n * methods to create the {@link module:utils/observablemixin~Observable observable} attribute and event bindings.\n *\n * @interface module:ui/template~BindChain\n */\n\n/**\n * Binds an {@link module:utils/observablemixin~Observable observable} to either:\n *\n * * an HTML element attribute or a text node `textContent`, so it remains in sync with the observable\n * attribute as it changes,\n * * or an HTML element DOM event, so the DOM events are propagated through an observable.\n *\n * Some common use cases of `to()` bindings are presented below:\n *\n *\t\tconst bind = Template.bind( observable, emitter );\n *\n *\t\tnew Template( {\n *\t\t\ttag: 'p',\n *\t\t\tattributes: {\n *\t\t\t\t// class=\"...\" attribute gets bound to `observable#a`\n *\t\t\t\tclass: bind.to( 'a' )\n *\t\t\t},\n *\t\t\tchildren: [\n *\t\t\t\t// <p>...</p> gets bound to observable#b; always `toUpperCase()`.\n *\t\t\t\t{\n *\t\t\t\t\ttext: bind.to( 'b', ( value, node ) => value.toUpperCase() )\n *\t\t\t\t}\n *\t\t\t],\n *\t\t\ton: {\n *\t\t\t\tclick: [\n *\t\t\t\t\t// An observable will fire \"clicked\" upon \"click\" in the DOM.\n *\t\t\t\t\tbind.to( 'clicked' ),\n *\n *\t\t\t\t\t// A custom callback will be executed upon \"click\" in the DOM.\n *\t\t\t\t\tbind.to( () => {\n *\t\t\t\t\t\t...\n *\t\t\t\t\t} )\n *\t\t\t\t]\n *\t\t\t}\n *\t\t} ).render();\n *\n * Learn more about using `to()` in the {@link module:ui/template~TemplateValueSchema} and\n * {@link module:ui/template~TemplateListenerSchema}.\n *\n * @method #to\n * @param {String|Function} eventNameOrFunctionOrAttribute An attribute name of\n * {@link module:utils/observablemixin~Observable} or a DOM event name or an event callback.\n * @param {Function} [callback] Allows for processing of the value. Accepts `Node` and `value` as arguments.\n * @returns {module:ui/template~TemplateBinding}\n */\n\n/**\n * Binds an {@link module:utils/observablemixin~Observable observable} to an HTML element attribute or a text\n * node `textContent` so it remains in sync with the observable attribute as it changes.\n *\n * Unlike {@link module:ui/template~BindChain#to}, it controls the presence of the attribute or `textContent`\n * depending on the \"falseness\" of an {@link module:utils/observablemixin~Observable} attribute.\n *\n *\t\tconst bind = Template.bind( observable, emitter );\n *\n *\t\tnew Template( {\n *\t\t\ttag: 'input',\n *\t\t\tattributes: {\n *\t\t\t\t// <input checked> when `observable#a` is not undefined/null/false/''\n *\t\t\t\t// <input> when `observable#a` is undefined/null/false\n *\t\t\t\tchecked: bind.if( 'a' )\n *\t\t\t},\n *\t\t\tchildren: [\n *\t\t\t\t{\n *\t\t\t\t\t// <input>\"b-is-not-set\"</input> when `observable#b` is undefined/null/false/''\n *\t\t\t\t\t// <input></input> when `observable#b` is not \"falsy\"\n *\t\t\t\t\ttext: bind.if( 'b', 'b-is-not-set', ( value, node ) => !value )\n *\t\t\t\t}\n *\t\t\t]\n *\t\t} ).render();\n *\n * Learn more about using `if()` in the {@link module:ui/template~TemplateValueSchema}.\n *\n * @method #if\n * @param {String} attribute An attribute name of {@link module:utils/observablemixin~Observable} used in the binding.\n * @param {String} [valueIfTrue] Value set when the {@link module:utils/observablemixin~Observable} attribute is not\n * undefined/null/false/'' (empty string).\n * @param {Function} [callback] Allows for processing of the value. Accepts `Node` and `value` as arguments.\n * @returns {module:ui/template~TemplateBinding}\n */\n\n/**\n * The {@link module:ui/template~Template#_renderNode} configuration.\n *\n * @private\n * @interface module:ui/template~RenderData\n */\n\n/**\n * Tells {@link module:ui/template~Template#_renderNode} to render\n * children into `DocumentFragment` first and then append the fragment\n * to the parent element. It is a speed optimization.\n *\n * @member {Boolean} #intoFragment\n */\n\n/**\n * A node which is being rendered.\n *\n * @member {HTMLElement|Text} #node\n */\n\n/**\n * Indicates whether the {@module:ui/template~RenderNodeOptions#node} has\n * been provided by {@module:ui/template~Template#apply}.\n *\n * @member {Boolean} #isApplying\n */\n\n/**\n * An object storing the data that helps {@module:ui/template~Template#revert}\n * bringing back an element to its initial state, i.e. before\n * {@module:ui/template~Template#apply} was called.\n *\n * @member {Object} #revertData\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/view\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport ViewCollection from './viewcollection';\nimport Template from './template';\nimport DomEmitterMixin from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';\n\nimport '../theme/globals/globals.css';\n\n/**\n * The basic view class, which represents an HTML element created out of a\n * {@link module:ui/view~View#template}. Views are building blocks of the user interface and handle\n * interaction\n *\n * Views {@link module:ui/view~View#registerChild aggregate} children in\n * {@link module:ui/view~View#createCollection collections} and manage the life cycle of DOM\n * listeners e.g. by handling rendering and destruction.\n *\n * See the {@link module:ui/template~TemplateDefinition} syntax to learn more about shaping view\n * elements, attributes and listeners.\n *\n *\t\tclass SampleView extends View {\n *\t\t\tconstructor( locale ) {\n *\t\t\t\tsuper( locale );\n *\n *\t\t\t\tconst bind = this.bindTemplate;\n *\n *\t\t\t\t// Views define their interface (state) using observable attributes.\n *\t\t\t\tthis.set( 'elementClass', 'bar' );\n *\n *\t\t\t\tthis.setTemplate( {\n *\t\t\t\t\ttag: 'p',\n *\n *\t\t\t\t\t// The element of the view can be defined with its children.\n *\t\t\t\t\tchildren: [\n *\t\t\t\t\t\t'Hello',\n *\t\t\t\t\t\t{\n *\t\t\t\t\t\t\ttag: 'b',\n *\t\t\t\t\t\t\tchildren: [ 'world!' ]\n *\t\t\t\t\t\t}\n *\t\t\t\t\t],\n *\t\t\t\t\tattributes: {\n *\t\t\t\t\t\tclass: [\n *\t\t\t\t\t\t\t'foo',\n *\n *\t\t\t\t\t\t\t// Observable attributes control the state of the view in DOM.\n *\t\t\t\t\t\t\tbind.to( 'elementClass' )\n *\t\t\t\t\t\t]\n *\t\t\t\t\t},\n *\t\t\t\t\ton: {\n *\t\t\t\t\t\t// Views listen to DOM events and propagate them.\n *\t\t\t\t\t\tclick: bind.to( 'clicked' )\n *\t\t\t\t\t}\n *\t\t\t\t} );\n *\t\t\t}\n *\t\t}\n *\n *\t\tconst view = new SampleView( locale );\n *\n *\t\tview.render();\n *\n *\t\t// Append <p class=\"foo bar\">Hello<b>world</b></p> to the <body>\n *\t\tdocument.body.appendChild( view.element );\n *\n *\t\t// Change the class attribute to <p class=\"foo baz\">Hello<b>world</b></p>\n *\t\tview.elementClass = 'baz';\n *\n *\t\t// Respond to the \"click\" event in DOM by executing a custom action.\n *\t\tview.on( 'clicked', () => {\n *\t\t\tconsole.log( 'The view has been clicked!' );\n *\t\t} );\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class View {\n\t/**\n\t * Creates an instance of the {@link module:ui/view~View} class.\n\t *\n\t * Also see {@link #render}.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The localization services instance.\n\t */\n\tconstructor( locale ) {\n\t\t/**\n\t\t * An HTML element of the view. `null` until {@link #render rendered}\n\t\t * from the {@link #template}.\n\t\t *\n\t\t *\t\tclass SampleView extends View {\n\t\t *\t\t\tconstructor() {\n\t\t *\t\t\t\tsuper();\n\t\t *\n\t\t *\t\t\t\t// A template instance the #element will be created from.\n\t\t *\t\t\t\tthis.setTemplate( {\n\t\t *\t\t\t\t\ttag: 'p'\n\t\t *\n\t\t *\t\t\t\t\t// ...\n\t\t *\t\t\t\t} );\n\t\t *\t\t\t}\n\t\t *\t\t}\n\t\t *\n\t\t *\t\tconst view = new SampleView();\n\t\t *\n\t\t *\t\t// Renders the #template.\n\t\t *\t\tview.render();\n\t\t *\n\t\t *\t\t// Append the HTML element of the view to <body>.\n\t\t *\t\tdocument.body.appendChild( view.element );\n\t\t *\n\t\t * **Note**: The element of the view can also be assigned directly:\n\t\t *\n\t\t *\t\tview.element = document.querySelector( '#my-container' );\n\t\t *\n\t\t * @member {HTMLElement}\n\t\t */\n\t\tthis.element = null;\n\n\t\t/**\n\t\t * Set `true` when the view has already been {@link module:ui/view~View#render rendered}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} #isRendered\n\t\t */\n\t\tthis.isRendered = false;\n\n\t\t/**\n\t\t * A set of tools to localize the user interface.\n\t\t *\n\t\t * Also see {@link module:core/editor/editor~Editor#locale}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/locale~Locale}\n\t\t */\n\t\tthis.locale = locale;\n\n\t\t/**\n\t\t * Shorthand for {@link module:utils/locale~Locale#t}.\n\t\t *\n\t\t * Note: If {@link #locale} instance hasn't been passed to the view this method may not\n\t\t * be available.\n\t\t *\n\t\t * @see module:utils/locale~Locale#t\n\t\t * @method\n\t\t */\n\t\tthis.t = locale && locale.t;\n\n\t\t/**\n\t\t * Collections registered with {@link #createCollection}.\n\t\t *\n\t\t * @protected\n\t\t * @member {Set.<module:ui/viewcollection~ViewCollection>}\n\t\t */\n\t\tthis._viewCollections = new Collection();\n\n\t\t/**\n\t\t * A collection of view instances, which have been added directly\n\t\t * into the {@link module:ui/template~Template#children}.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis._unboundChildren = this.createCollection();\n\n\t\t// Pass parent locale to its children.\n\t\tthis._viewCollections.on( 'add', ( evt, collection ) => {\n\t\t\tcollection.locale = locale;\n\t\t} );\n\n\t\t/**\n\t\t * Template of this view. It provides the {@link #element} representing\n\t\t * the view in DOM, which is {@link #render rendered}.\n\t\t *\n\t\t * @member {module:ui/template~Template} #template\n\t\t */\n\n\t\t/**\n\t\t * Cached {@link module:ui/template~BindChain bind chain} object created by the\n\t\t * {@link #template}. See {@link #bindTemplate}.\n\t\t *\n\t\t * @private\n\t\t * @member {Object} #_bindTemplate\n\t\t */\n\n\t\tthis.decorate( 'render' );\n\t}\n\n\t/**\n\t * Shorthand for {@link module:ui/template~Template.bind}, a binding\n\t * {@link module:ui/template~BindChain interface} pre–configured for the view instance.\n\t *\n\t * It provides {@link module:ui/template~BindChain#to `to()`} and\n\t * {@link module:ui/template~BindChain#if `if()`} methods that initialize bindings with\n\t * observable attributes and attach DOM listeners.\n\t *\n\t *\t\tclass SampleView extends View {\n\t *\t\t\tconstructor( locale ) {\n\t *\t\t\t\tsuper( locale );\n\t *\n\t *\t\t\t\tconst bind = this.bindTemplate;\n\t *\n\t *\t\t\t\t// These {@link module:utils/observablemixin~Observable observable} attributes will control\n\t *\t\t\t\t// the state of the view in DOM.\n\t *\t\t\t\tthis.set( {\n\t *\t\t\t\t\telementClass: 'foo',\n\t *\t\t\t\t \tisEnabled: true\n\t *\t\t\t\t } );\n\t *\n\t *\t\t\t\tthis.setTemplate( {\n\t *\t\t\t\t\ttag: 'p',\n\t *\n\t *\t\t\t\t\tattributes: {\n\t *\t\t\t\t\t\t// The class HTML attribute will follow elementClass\n\t *\t\t\t\t\t\t// and isEnabled view attributes.\n\t *\t\t\t\t\t\tclass: [\n\t *\t\t\t\t\t\t\tbind.to( 'elementClass' )\n\t *\t\t\t\t\t\t\tbind.if( 'isEnabled', 'present-when-enabled' )\n\t *\t\t\t\t\t\t]\n\t *\t\t\t\t\t},\n\t *\n\t *\t\t\t\t\ton: {\n\t *\t\t\t\t\t\t// The view will fire the \"clicked\" event upon clicking <p> in DOM.\n\t *\t\t\t\t\t\tclick: bind.to( 'clicked' )\n\t *\t\t\t\t\t}\n\t *\t\t\t\t} );\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t * @method #bindTemplate\n\t */\n\tget bindTemplate() {\n\t\tif ( this._bindTemplate ) {\n\t\t\treturn this._bindTemplate;\n\t\t}\n\n\t\treturn ( this._bindTemplate = Template.bind( this, this ) );\n\t}\n\n\t/**\n\t * Creates a new collection of views, which can be used as\n\t * {@link module:ui/template~Template#children} of this view.\n\t *\n\t *\t\tclass SampleView extends View {\n\t *\t\t\tconstructor( locale ) {\n\t *\t\t\t\tsuper( locale );\n\t *\n\t *\t\t\t\tthis.items = this.createCollection();\n \t *\n\t *\t\t\t\tthis.setTemplate( {\n\t *\t\t\t\t\ttag: 'p',\n\t *\n\t *\t\t\t\t\t// `items` collection will render here.\n\t *\t\t\t\t\tchildren: this.items\n\t *\t\t\t\t} );\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t *\t\tconst view = new SampleView( locale );\n\t *\t\tconst child = new ChildView( locale );\n\t *\n\t *\t\tview.render();\n\t *\n\t *\t\t// It will append <p></p> to the <body>.\n\t *\t\tdocument.body.appendChild( view.element );\n\t *\n\t *\t\t// From now on the child is nested under its parent, which is also reflected in DOM.\n\t *\t\t// <p><child#element></p>\n\t *\t\tview.items.add( child );\n\t *\n\t * @returns {module:ui/viewcollection~ViewCollection} A new collection of view instances.\n\t */\n\tcreateCollection() {\n\t\tconst collection = new ViewCollection();\n\n\t\tthis._viewCollections.add( collection );\n\n\t\treturn collection;\n\t}\n\n\t/**\n\t * Registers a new child view under the view instance. Once registered, a child\n\t * view is managed by its parent, including {@link #render rendering}\n\t * and {@link #destroy destruction}.\n\t *\n\t * To revert this, use {@link #deregisterChild}.\n\t *\n\t *\t\tclass SampleView extends View {\n\t *\t\t\tconstructor( locale ) {\n\t *\t\t\t\tsuper( locale );\n\t *\n\t *\t\t\t\tthis.childA = new SomeChildView( locale );\n\t *\t\t\t\tthis.childB = new SomeChildView( locale );\n\t *\n\t *\t\t\t\tthis.setTemplate( { tag: 'p' } );\n\t *\n\t *\t\t\t\t// Register the children.\n\t *\t\t\t\tthis.registerChild( [ this.childA, this.childB ] );\n\t *\t\t\t}\n\t *\n\t *\t\t\trender() {\n\t *\t\t\t\tsuper.render();\n\t *\n\t *\t\t\t\tthis.element.appendChild( this.childA.element );\n\t *\t\t\t\tthis.element.appendChild( this.childB.element );\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t *\t\tconst view = new SampleView( locale );\n\t *\n\t *\t\tview.render();\n\t *\n\t *\t\t// Will append <p><childA#element><b></b><childB#element></p>.\n\t *\t\tdocument.body.appendChild( view.element );\n\t *\n\t * **Note**: There's no need to add child views if they're already referenced in the\n\t * {@link #template}:\n\t *\n\t *\t\tclass SampleView extends View {\n\t *\t\t\tconstructor( locale ) {\n\t *\t\t\t\tsuper( locale );\n\t *\n\t *\t\t\t\tthis.childA = new SomeChildView( locale );\n\t *\t\t\t\tthis.childB = new SomeChildView( locale );\n\t *\n\t *\t\t\t\tthis.setTemplate( {\n\t *\t\t\t\t\ttag: 'p',\n\t *\n \t *\t\t\t\t\t// These children will be added automatically. There's no\n \t *\t\t\t\t\t// need to call {@link #registerChild} for any of them.\n\t *\t\t\t\t\tchildren: [ this.childA, this.childB ]\n\t *\t\t\t\t} );\n\t *\t\t\t}\n\t *\n\t *\t\t\t// ...\n\t *\t\t}\n\t *\n\t * @param {module:ui/view~View|Iterable.<module:ui/view~View>} children Children views to be registered.\n\t */\n\tregisterChild( children ) {\n\t\tif ( !isIterable( children ) ) {\n\t\t\tchildren = [ children ];\n\t\t}\n\n\t\tfor ( const child of children ) {\n\t\t\tthis._unboundChildren.add( child );\n\t\t}\n\t}\n\n\t/**\n\t * The opposite of {@link #registerChild}. Removes a child view from this view instance.\n\t * Once removed, the child is no longer managed by its parent, e.g. it can safely\n\t * become a child of another parent view.\n\t *\n\t * @see #registerChild\n\t * @param {module:ui/view~View|Iterable.<module:ui/view~View>} children Child views to be removed.\n\t */\n\tderegisterChild( children ) {\n\t\tif ( !isIterable( children ) ) {\n\t\t\tchildren = [ children ];\n\t\t}\n\n\t\tfor ( const child of children ) {\n\t\t\tthis._unboundChildren.remove( child );\n\t\t}\n\t}\n\n\t/**\n\t * Sets the {@link #template} of the view with with given definition.\n\t *\n\t * A shorthand for:\n\t *\n\t *\t\tview.setTemplate( definition );\n\t *\n\t * @param {module:ui/template~TemplateDefinition} definition Definition of view's template.\n\t */\n\tsetTemplate( definition ) {\n\t\tthis.template = new Template( definition );\n\t}\n\n\t/**\n\t * {@link module:ui/template~Template.extend Extends} the {@link #template} of the view with\n\t * with given definition.\n\t *\n\t * A shorthand for:\n\t *\n\t *\t\tTemplate.extend( view.template, definition );\n\t *\n\t * **Note**: Is requires the {@link #template} to be already set. See {@link #setTemplate}.\n\t *\n\t * @param {module:ui/template~TemplateDefinition} definition Definition which\n\t * extends the {@link #template}.\n\t */\n\textendTemplate( definition ) {\n\t\tTemplate.extend( this.template, definition );\n\t}\n\n\t/**\n\t * Recursively renders the view.\n\t *\n\t * Once the view is rendered:\n\t * * the {@link #element} becomes an HTML element out of {@link #template},\n\t * * the {@link #isRendered} flag is set `true`.\n\t *\n\t * **Note**: The children of the view:\n\t * * defined directly in the {@link #template}\n\t * * residing in collections created by the {@link #createCollection} method,\n\t * * and added by {@link #registerChild}\n\t * are also rendered in the process.\n\t *\n\t * In general, `render()` method is the right place to keep the code which refers to the\n\t * {@link #element} and should be executed at the very beginning of the view's life cycle.\n\t *\n\t * It is possible to {@link module:ui/template~Template.extend} the {@link #template} before\n\t * the view is rendered. To allow an early customization of the view (e.g. by its parent),\n\t * such references should be done in `render()`.\n\t *\n\t *\t\tclass SampleView extends View {\n\t *\t\t\tconstructor() {\n\t *\t\t\t\tthis.setTemplate( {\n\t *\t\t\t\t\t// ...\n\t *\t\t\t\t} );\n\t *\t\t\t},\n\t *\n\t *\t\t\trender() {\n\t *\t\t\t\t// View#element becomes available.\n\t *\t\t\t\tsuper.render();\n\t *\n\t *\t\t\t\t// The \"scroll\" listener depends on #element.\n\t *\t\t\t\tthis.listenTo( window, 'scroll', () => {\n\t *\t\t\t\t\t// A reference to #element would render the #template and make it non-extendable.\n\t *\t\t\t\t\tif ( window.scrollY > 0 ) {\n\t *\t\t\t\t\t\tthis.element.scrollLeft = 100;\n\t *\t\t\t\t\t} else {\n\t *\t\t\t\t\t\tthis.element.scrollLeft = 0;\n\t *\t\t\t\t\t}\n\t *\t\t\t\t} );\n\t *\t\t\t}\n\t *\t\t}\n\t *\n\t *\t\tconst view = new SampleView();\n\t *\n\t *\t\t// Let's customize the view before it gets rendered.\n\t *\t\tview.extendTemplate( {\n\t *\t\t\tattributes: {\n\t *\t\t\t\tclass: [\n\t *\t\t\t\t\t'additional-class'\n\t *\t\t\t\t]\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t *\t\t// Late rendering allows customization of the view.\n\t *\t\tview.render();\n\t */\n\trender() {\n\t\tif ( this.isRendered ) {\n\t\t\t/**\n\t\t\t * This View has already been rendered.\n\t\t\t *\n\t\t\t * @error ui-view-render-rendered\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'ui-view-render-already-rendered: This View has already been rendered.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\t// Render #element of the view.\n\t\tif ( this.template ) {\n\t\t\tthis.element = this.template.render();\n\n\t\t\t// Auto–register view children from #template.\n\t\t\tthis.registerChild( this.template.getViews() );\n\t\t}\n\n\t\tthis.isRendered = true;\n\t}\n\n\t/**\n\t * Recursively destroys the view instance and child views added by {@link #registerChild} and\n\t * residing in collections created by the {@link #createCollection}.\n\t *\n\t * Destruction disables all event listeners:\n\t * * created on the view, e.g. `view.on( 'event', () => {} )`,\n\t * * defined in the {@link #template} for DOM events.\n\t */\n\tdestroy() {\n\t\tthis.stopListening();\n\n\t\tthis._viewCollections.map( c => c.destroy() );\n\n\t\t// Template isn't obligatory for views.\n\t\tif ( this.template && this.template._revertData ) {\n\t\t\tthis.template.revert( this.element );\n\t\t}\n\t}\n\n\t/**\n\t * Event fired by the {@link #render} method. Actual rendering is executed as a listener to\n\t * this event with the default priority.\n\t *\n\t * See {@link module:utils/observablemixin~ObservableMixin#decorate} for more information and samples.\n\t *\n\t * @event render\n\t */\n}\n\nmix( View, DomEmitterMixin );\nmix( View, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/editorui/editoruiview\n */\n\n/* globals document */\n\nimport View from '../view';\nimport Template from '../template';\n\nimport '../../theme/components/editorui/editorui.css';\n\n/**\n * The editor UI view class. Base class for the editor main views.\n *\n * @extends module:ui/view~View\n */\nexport default class EditorUIView extends View {\n\t/**\n\t * Creates an instance of the editor UI view class.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The locale instance.\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * Collection of the child views, detached from the DOM\n\t\t * structure of the editor, like panels, icons etc.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection} #body\n\t\t */\n\t\tthis.body = this.createCollection();\n\n\t\t/**\n\t\t * The element holding elements of the 'body' region.\n\t\t *\n\t\t * @private\n\t\t * @member {HTMLElement} #_bodyCollectionContainer\n\t\t */\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tthis._renderBodyCollection();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tthis._bodyCollectionContainer.remove();\n\n\t\treturn super.destroy();\n\t}\n\n\t/**\n\t * Creates and appends to `<body>` the {@link #body} collection container.\n\t *\n\t * @private\n\t */\n\t_renderBodyCollection() {\n\t\tconst locale = this.locale;\n\t\tconst bodyElement = this._bodyCollectionContainer = new Template( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-reset_all',\n\t\t\t\t\t'ck-body',\n\t\t\t\t\t'ck-rounded-corners'\n\t\t\t\t],\n\t\t\t\tdir: locale.uiLanguageDirection,\n\t\t\t},\n\t\t\tchildren: this.body\n\t\t} ).render();\n\n\t\tdocument.body.appendChild( bodyElement );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/editableui/editableuiview\n */\n\nimport View from '../view';\n\n/**\n * The editable UI view class.\n *\n * @extends module:ui/view~View\n */\nexport default class EditableUIView extends View {\n\t/**\n\t * Creates an instance of EditableUIView class.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The locale instance.\n\t * @param {module:engine/view/view~View} editingView The editing view instance the editable is related to.\n\t * @param {HTMLElement} [editableElement] The editable element. If not specified, this view\n\t * should create it. Otherwise, the existing element should be used.\n\t */\n\tconstructor( locale, editingView, editableElement ) {\n\t\tsuper( locale );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-content',\n\t\t\t\t\t'ck-editor__editable',\n\t\t\t\t\t'ck-rounded-corners'\n\t\t\t\t],\n\t\t\t\tlang: locale.contentLanguage,\n\t\t\t\tdir: locale.contentLanguageDirection\n\t\t\t}\n\t\t} );\n\n\t\t/**\n\t\t * The name of the editable UI view.\n\t\t *\n\t\t * @member {String} #name\n\t\t */\n\t\tthis.name = null;\n\n\t\t/**\n\t\t * Controls whether the editable is focused, i.e. the user is typing in it.\n\t\t *\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 element which is the main editable element (usually the one with `contentEditable=\"true\"`).\n\t\t *\n\t\t * @private\n\t\t * @member {HTMLElement} #_editableElement\n\t\t */\n\t\tthis._editableElement = editableElement;\n\n\t\t/**\n\t\t * Whether an external {@link #_editableElement} was passed into the constructor, which also means\n\t\t * the view will not render its {@link #template}.\n\t\t *\n\t\t * @private\n\t\t * @member {Boolean} #_hasExternalElement\n\t\t */\n\t\tthis._hasExternalElement = !!this._editableElement;\n\n\t\t/**\n\t\t * The editing view instance the editable is related to. Editable uses the editing\n\t\t * view to dynamically modify its certain DOM attributes after {@link #render rendering}.\n\t\t *\n\t\t * **Note**: The DOM attributes are performed by the editing view and not UI\n\t\t * {@link module:ui/view~View#bindTemplate template bindings} because once rendered,\n\t\t * the editable DOM element must remain under the full control of the engine to work properly.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:engine/view/view~View} #isFocused\n\t\t */\n\t\tthis._editingView = editingView;\n\t}\n\n\t/**\n\t * Renders the view by either applying the {@link #template} to the existing\n\t * {@link #_editableElement} or assigning {@link #element} as {@link #_editableElement}.\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tif ( this._hasExternalElement ) {\n\t\t\tthis.template.apply( this.element = this._editableElement );\n\t\t} else {\n\t\t\tthis._editableElement = this.element;\n\t\t}\n\n\t\tthis.on( 'change:isFocused', () => this._updateIsFocusedClasses() );\n\t\tthis._updateIsFocusedClasses();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tif ( this._hasExternalElement ) {\n\t\t\tthis.template.revert( this._editableElement );\n\t\t}\n\n\t\tsuper.destroy();\n\t}\n\n\t/**\n\t * Updates the `ck-focused` and `ck-blurred` CSS classes on the {@link #element} according to\n\t * the {@link #isFocused} property value using the {@link #_editingView editing view} API.\n\t *\n\t * @private\n\t */\n\t_updateIsFocusedClasses() {\n\t\tconst editingView = this._editingView;\n\n\t\tif ( editingView.isRenderingInProgress ) {\n\t\t\tupdateAfterRender( this );\n\t\t} else {\n\t\t\tupdate( this );\n\t\t}\n\n\t\tfunction update( view ) {\n\t\t\teditingView.change( writer => {\n\t\t\t\tconst viewRoot = editingView.document.getRoot( view.name );\n\n\t\t\t\twriter.addClass( view.isFocused ? 'ck-focused' : 'ck-blurred', viewRoot );\n\t\t\t\twriter.removeClass( view.isFocused ? 'ck-blurred' : 'ck-focused', viewRoot );\n\t\t\t} );\n\t\t}\n\n\t\t// In a case of a multi-root editor, a callback will be attached more than once (one callback for each root).\n\t\t// While executing one callback the `isRenderingInProgress` observable is changing what causes executing another\n\t\t// callback and render is called inside the already pending render.\n\t\t// We need to be sure that callback is executed only when the value has changed from `true` to `false`.\n\t\t// See https://github.com/ckeditor/ckeditor5/issues/1676.\n\t\tfunction updateAfterRender( view ) {\n\t\t\teditingView.once( 'change:isRenderingInProgress', ( evt, name, value ) => {\n\t\t\t\tif ( !value ) {\n\t\t\t\t\tupdate( view );\n\t\t\t\t} else {\n\t\t\t\t\tupdateAfterRender( view );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module ui/editableui/inline/inlineeditableuiview\n */\nimport EditableUIView from '../../editableui/editableuiview';\n/**\n * The inline editable UI class implementing an inline {@link module:ui/editableui/editableuiview~EditableUIView}.\n *\n * @extends module:ui/editableui/editableuiview~EditableUIView\n */\nexport default class InlineEditableUIView extends EditableUIView {\n /**\n\t * Creates an instance of the InlineEditableUIView class.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The locale instance.\n\t * @param {module:engine/view/view~View} editingView The editing view instance the editable is related to.\n\t * @param {HTMLElement} [editableElement] The editable element. If not specified, the\n\t * {@link module:ui/editableui/editableuiview~EditableUIView}\n\t * will create it. Otherwise, the existing element will be used.\n\t */\n constructor(locale, editingView, editableElement) {\n super(locale, editingView, editableElement);\n this.extendTemplate({\n attributes: {\n role: 'textbox',\n class: 'ck-editor__editable_inline'\n }\n });\n }\n /**\n\t * @inheritDoc\n\t */\n render() {\n super.render();\n const editingView = this._editingView;\n const t = this.t;\n editingView.change(writer => {\n const viewRoot = editingView.document.getRoot(this.name);\n writer.setAttribute('aria-label', t('j', [this.name]), viewRoot);\n });\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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 ui/focuscycler\n */\n\nimport global from '@ckeditor/ckeditor5-utils/src/dom/global';\n\n/**\n * A utility class that helps cycling over focusable {@link module:ui/view~View views} in a\n * {@link module:ui/viewcollection~ViewCollection} when the focus is tracked by the\n * {@link module:utils/focustracker~FocusTracker} instance. It helps implementing keyboard\n * navigation in HTML forms, toolbars, lists and the like.\n *\n * To work properly it requires:\n * * a collection of focusable (HTML `tabindex` attribute) views that implement the `focus()` method,\n * * an associated focus tracker to determine which view is focused.\n *\n * A simple cycler setup can look like this:\n *\n *\t\tconst focusables = new ViewCollection();\n *\t\tconst focusTracker = new FocusTracker();\n *\n *\t\t// Add focusable views to the focus tracker.\n *\t\tfocusTracker.add( ... );\n *\n * Then, the cycler can be used manually:\n *\n *\t\tconst cycler = new FocusCycler( { focusables, focusTracker } );\n *\n *\t\t// Will focus the first focusable view in #focusables.\n *\t\tcycler.focusFirst();\n *\n *\t\t// Will log the next focusable item in #focusables.\n *\t\tconsole.log( cycler.next );\n *\n * Alternatively, it can work side by side with the {@link module:utils/keystrokehandler~KeystrokeHandler}:\n *\n *\t\tconst keystrokeHandler = new KeystrokeHandler();\n *\n *\t\t// Activate the keystroke handler.\n *\t\tkeystrokeHandler.listenTo( sourceOfEvents );\n *\n *\t\tconst cycler = new FocusCycler( {\n *\t\t\tfocusables, focusTracker, keystrokeHandler,\n *\t\t\tactions: {\n *\t\t\t\t// When arrowup of arrowleft is detected by the #keystrokeHandler,\n *\t\t\t\t// focusPrevious() will be called on the cycler.\n *\t\t\t\tfocusPrevious: [ 'arrowup', 'arrowleft' ],\n *\t\t\t}\n *\t\t} );\n */\nexport default class FocusCycler {\n\t/**\n\t * Creates an instance of the focus cycler utility.\n\t *\n\t * @param {Object} options Configuration options.\n\t * @param {module:utils/collection~Collection|Object} options.focusables\n\t * @param {module:utils/focustracker~FocusTracker} options.focusTracker\n\t * @param {module:utils/keystrokehandler~KeystrokeHandler} [options.keystrokeHandler]\n\t * @param {Object} [options.actions]\n\t */\n\tconstructor( options ) {\n\t\tObject.assign( this, options );\n\n\t\t/**\n\t\t * A {@link module:ui/view~View view} collection that the cycler operates on.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/collection~Collection} #focusables\n\t\t */\n\n\t\t/**\n\t\t * A focus tracker instance that the cycler uses to determine the current focus\n\t\t * state in {@link #focusables}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker} #focusTracker\n\t\t */\n\n\t\t/**\n\t\t * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}\n\t\t * which can respond to certain keystrokes and cycle the focus.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler} #keystrokeHandler\n\t\t */\n\n\t\t/**\n\t\t * Actions that the cycler can take when a keystroke is pressed. Requires\n\t\t * `options.keystrokeHandler` to be passed and working. When an action is\n\t\t * performed, `preventDefault` and `stopPropagation` will be called on the event\n\t\t * the keystroke fired in the DOM.\n\t\t *\n\t\t *\t\tactions: {\n\t\t *\t\t\t// Will call #focusPrevious() when arrowleft or arrowup is pressed.\n\t\t *\t\t\tfocusPrevious: [ 'arrowleft', 'arrowup' ],\n\t\t *\n\t\t *\t\t\t// Will call #focusNext() when arrowdown is pressed.\n\t\t *\t\t\tfocusNext: 'arrowdown'\n\t\t *\t\t}\n\t\t *\n\t\t * @readonly\n\t\t * @member {Object} #actions\n\t\t */\n\n\t\tif ( options.actions && options.keystrokeHandler ) {\n\t\t\tfor ( const methodName in options.actions ) {\n\t\t\t\tlet actions = options.actions[ methodName ];\n\n\t\t\t\tif ( typeof actions == 'string' ) {\n\t\t\t\t\tactions = [ actions ];\n\t\t\t\t}\n\n\t\t\t\tfor ( const keystroke of actions ) {\n\t\t\t\t\toptions.keystrokeHandler.set( keystroke, ( data, cancel ) => {\n\t\t\t\t\t\tthis[ methodName ]();\n\t\t\t\t\t\tcancel();\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns the first focusable view in {@link #focusables}.\n\t * Returns `null` if there is none.\n\t *\n\t * @readonly\n\t * @member {module:ui/view~View|null} #first\n\t */\n\tget first() {\n\t\treturn this.focusables.find( isFocusable ) || null;\n\t}\n\n\t/**\n\t * Returns the last focusable view in {@link #focusables}.\n\t * Returns `null` if there is none.\n\t *\n\t * @readonly\n\t * @member {module:ui/view~View|null} #last\n\t */\n\tget last() {\n\t\treturn this.focusables.filter( isFocusable ).slice( -1 )[ 0 ] || null;\n\t}\n\n\t/**\n\t * Returns the next focusable view in {@link #focusables} based on {@link #current}.\n\t * Returns `null` if there is none.\n\t *\n\t * @readonly\n\t * @member {module:ui/view~View|null} #next\n\t */\n\tget next() {\n\t\treturn this._getFocusableItem( 1 );\n\t}\n\n\t/**\n\t * Returns the previous focusable view in {@link #focusables} based on {@link #current}.\n\t * Returns `null` if there is none.\n\t *\n\t * @readonly\n\t * @member {module:ui/view~View|null} #previous\n\t */\n\tget previous() {\n\t\treturn this._getFocusableItem( -1 );\n\t}\n\n\t/**\n\t * An index of the view in the {@link #focusables} which is focused according\n\t * to {@link #focusTracker}. Returns `null` when there is no such view.\n\t *\n\t * @readonly\n\t * @member {Number|null} #current\n\t */\n\tget current() {\n\t\tlet index = null;\n\n\t\t// There's no focused view in the focusables.\n\t\tif ( this.focusTracker.focusedElement === null ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tthis.focusables.find( ( view, viewIndex ) => {\n\t\t\tconst focused = view.element === this.focusTracker.focusedElement;\n\n\t\t\tif ( focused ) {\n\t\t\t\tindex = viewIndex;\n\t\t\t}\n\n\t\t\treturn focused;\n\t\t} );\n\n\t\treturn index;\n\t}\n\n\t/**\n\t * Focuses the {@link #first} item in {@link #focusables}.\n\t */\n\tfocusFirst() {\n\t\tthis._focus( this.first );\n\t}\n\n\t/**\n\t * Focuses the {@link #last} item in {@link #focusables}.\n\t */\n\tfocusLast() {\n\t\tthis._focus( this.last );\n\t}\n\n\t/**\n\t * Focuses the {@link #next} item in {@link #focusables}.\n\t */\n\tfocusNext() {\n\t\tthis._focus( this.next );\n\t}\n\n\t/**\n\t * Focuses the {@link #previous} item in {@link #focusables}.\n\t */\n\tfocusPrevious() {\n\t\tthis._focus( this.previous );\n\t}\n\n\t/**\n\t * Focuses the given view if it exists.\n\t *\n\t * @protected\n\t * @param {module:ui/view~View} view\n\t */\n\t_focus( view ) {\n\t\tif ( view ) {\n\t\t\tview.focus();\n\t\t}\n\t}\n\n\t/**\n\t * Returns the next or previous focusable view in {@link #focusables} with respect\n\t * to {@link #current}.\n\t *\n\t * @protected\n\t * @param {Number} step Either `1` for checking forward from {@link #current} or\n\t * `-1` for checking backwards.\n\t * @returns {module:ui/view~View|null}\n\t */\n\t_getFocusableItem( step ) {\n\t\t// Cache for speed.\n\t\tconst current = this.current;\n\t\tconst collectionLength = this.focusables.length;\n\n\t\tif ( !collectionLength ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Start from the beginning if no view is focused.\n\t\t// https://github.com/ckeditor/ckeditor5-ui/issues/206\n\t\tif ( current === null ) {\n\t\t\treturn this[ step === 1 ? 'first' : 'last' ];\n\t\t}\n\n\t\t// Cycle in both directions.\n\t\tlet index = ( current + collectionLength + step ) % collectionLength;\n\n\t\tdo {\n\t\t\tconst view = this.focusables.get( index );\n\n\t\t\t// TODO: Check if view is visible.\n\t\t\tif ( isFocusable( view ) ) {\n\t\t\t\treturn view;\n\t\t\t}\n\n\t\t\t// Cycle in both directions.\n\t\t\tindex = ( index + collectionLength + step ) % collectionLength;\n\t\t} while ( index !== current );\n\n\t\treturn null;\n\t}\n}\n\n// Checks whether a view is focusable.\n//\n// @private\n// @param {module:ui/view~View} view A view to be checked.\n// @returns {Boolean}\nfunction isFocusable( view ) {\n\treturn !!( view.focus && global.window.getComputedStyle( view.element ).display != 'none' );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/toolbar/toolbarseparatorview\n */\n\nimport View from '../view';\n\n/**\n * The toolbar separator view class.\n *\n * @extends module:ui/view~View\n */\nexport default class ToolbarSeparatorView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'span',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-toolbar__separator'\n\t\t\t\t]\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/getresizeobserver\n */\n\n/* globals setTimeout, clearTimeout */\n\nimport mix from '../mix';\nimport global from './global';\nimport Rect from './rect';\nimport DomEmitterMixin from './emittermixin';\n\nconst RESIZE_CHECK_INTERVAL = 100;\n\n/**\n * Returns an instance of [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).\n * In browsers that support the `ResizeObserver` API, the native observer instance is returned.\n * In other browsers, a polyfilled instance is returned instead with a compatible API.\n *\n * [Learn more](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) about the native API.\n *\n * @param {Function} callback A function called when any observed element was resized. Refer to the\n * native [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) API to\n * learn more.\n * @returns {module:utils/dom/getresizeobserver~ResizeObserver} An observer instance.\n */\nexport default function getResizeObserver( callback ) {\n\t// TODO: One day, the `ResizeObserver` API will be supported in all modern web browsers.\n\t// When it happens, this module will no longer make sense and should be removed and\n\t// the native implementation should be used across the project to save bytes.\n\t// Check out https://caniuse.com/#feat=resizeobserver.\n\tif ( typeof global.window.ResizeObserver === 'function' ) {\n\t\treturn new global.window.ResizeObserver( callback );\n\t} else {\n\t\treturn new ResizeObserverPolyfill( callback );\n\t}\n}\n\n/**\n * A polyfill class for the native [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).\n *\n * @private\n * @mixes module:utils/domemittermixin~DomEmitterMixin\n */\nclass ResizeObserverPolyfill {\n\t/**\n\t * Creates an instance of the {@link module:utils/dom/getresizeobserver~ResizeObserverPolyfill} class.\n\t *\n\t * It synchronously reacts to resize of the window to check if observed elements' geometry changed.\n\t *\n\t * Additionally, the polyfilled observer uses a timeout to check if observed elements' geometry has changed\n\t * in some other way (dynamic layouts, scrollbars showing up, etc.), so its response can also be asynchronous.\n\t *\n\t * @param {Function} callback A function called when any observed element was resized. Refer to the\n\t * native [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) API to\n\t * learn more.\n\t */\n\tconstructor( callback ) {\n\t\t/**\n\t\t * A function called when any observed {@link #_elements element} was resized.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {Function}\n\t\t */\n\t\tthis._callback = callback;\n\n\t\t/**\n\t\t * DOM elements currently observed by the observer instance.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {Set}\n\t\t */\n\t\tthis._elements = new Set();\n\n\t\t/**\n\t\t * Cached DOM {@link #_elements elements} bounding rects to compare to upon the next check.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {Map.<HTMLElement,module:utils/dom/rect~Rect>}\n\t\t */\n\t\tthis._previousRects = new Map();\n\n\t\t/**\n\t\t * An UID of the current timeout upon which the observed elements rects\n\t\t * will be compared to the {@link #_previousRects previous rects} from the past.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {Map.<HTMLElement,module:utils/dom/rect~Rect>}\n\t\t */\n\t\tthis._periodicCheckTimeout = null;\n\t}\n\n\t/**\n\t * Starts observing a DOM element.\n\t *\n\t * Learn more in the\n\t * [native method documentation](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/observe).\n\t *\n\t * @param {HTMLElement} element\n\t */\n\tobserve( element ) {\n\t\tthis._elements.add( element );\n\n\t\tif ( this._elements.size === 1 ) {\n\t\t\tthis._startPeriodicCheck();\n\t\t}\n\t}\n\n\t/**\n\t * Stops observing a DOM element.\n\t *\n\t * Learn more in the\n\t * [native method documentation](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/unobserve).\n\t *\n\t * @param {HTMLElement} element\n\t */\n\tunobserve( element ) {\n\t\tthis._elements.delete( element );\n\t\tthis._previousRects.delete( element );\n\n\t\tif ( !this._elements.size ) {\n\t\t\tthis._stopPeriodicCheck();\n\t\t}\n\t}\n\n\t/**\n\t * Stops observing all observed DOM elements.\n\t *\n\t * Learn more in the\n\t * [native method documentation](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/disconnect).\n\t *\n\t * @param {HTMLElement} element\n\t */\n\tdisconnect() {\n\t\tthis._elements.forEach( element => this.unobserve( element ) );\n\t}\n\n\t/**\n\t * When called, the observer calls the {@link #_callback resize callback} for all observed\n\t * {@link #_elements elements} but also starts checking periodically for changes in the elements' geometry.\n\t * If some are detected, {@link #_callback resize callback} is called for relevant elements that were resized.\n\t *\n\t * @protected\n\t */\n\t_startPeriodicCheck() {\n\t\tconst periodicCheck = () => {\n\t\t\tthis._checkElementRectsAndExecuteCallback();\n\t\t\tthis._periodicCheckTimeout = setTimeout( periodicCheck, RESIZE_CHECK_INTERVAL );\n\t\t};\n\n\t\tthis.listenTo( global.window, 'resize', () => {\n\t\t\tthis._checkElementRectsAndExecuteCallback();\n\t\t} );\n\n\t\tperiodicCheck();\n\t}\n\n\t/**\n\t * Stops checking for changes in all observed {@link #_elements elements} geometry.\n\t *\n\t * @protected\n\t */\n\t_stopPeriodicCheck() {\n\t\tclearTimeout( this._periodicCheckTimeout );\n\t\tthis.stopListening();\n\t\tthis._previousRects.clear();\n\t}\n\n\t/**\n\t * Checks if the geometry of any of the {@link #_elements element} has changed. If so, executes\n\t * the {@link #_callback resize callback} with element geometry data.\n\t *\n\t * @protected\n\t */\n\t_checkElementRectsAndExecuteCallback() {\n\t\tconst entries = [];\n\n\t\tfor ( const element of this._elements ) {\n\t\t\tif ( this._hasRectChanged( element ) ) {\n\t\t\t\tentries.push( {\n\t\t\t\t\ttarget: element,\n\t\t\t\t\tcontentRect: this._previousRects.get( element )\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\tif ( entries.length ) {\n\t\t\tthis._callback( entries );\n\t\t}\n\t}\n\n\t/**\n\t * Compares the DOM element geometry to the {@link #_previousRects cached geometry} from the past.\n\t * Returns `true` if geometry has changed or the element is checked for the first time.\n\t *\n\t * @protected\n\t * @param {HTMLElement} element\n\t * @returns {Boolean}\n\t */\n\t_hasRectChanged( element ) {\n\t\tif ( !element.ownerDocument.body.contains( element ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst currentRect = new Rect( element );\n\t\tconst previousRect = this._previousRects.get( element );\n\n\t\t// The first check should always yield true despite no Previous rect to compare to.\n\t\t// The native ResizeObserver does that and... that makes sense. Sort of.\n\t\tconst hasChanged = !previousRect || !previousRect.isEqual( currentRect );\n\n\t\tthis._previousRects.set( element, currentRect );\n\n\t\treturn hasChanged;\n\t}\n}\n\nmix( ResizeObserverPolyfill, DomEmitterMixin );\n\n/**\n * A resize observer object (either native or {@link module:utils/dom/getresizeobserver~getResizeObserver polyfilled})\n * offering the [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) API.\n *\n * @typedef {Function} module:utils/dom/getresizeobserver~ResizeObserver\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/dropdown/dropdownpanelview\n */\n\nimport View from '../view';\n\n/**\n * The dropdown panel view class.\n *\n * See {@link module:ui/dropdown/dropdownview~DropdownView} to learn about the common usage.\n *\n * @extends module:ui/view~View\n */\nexport default class DropdownPanelView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\t/**\n\t\t * Controls whether the panel is visible.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isVisible\n\t\t */\n\t\tthis.set( 'isVisible', false );\n\n\t\t/**\n\t\t * The position of the panel, relative to the parent.\n\t\t *\n\t\t * This property is reflected in the CSS class set to {@link #element} that controls\n\t\t * the position of the panel.\n\t\t *\n\t\t * @observable\n\t\t * @default 'se'\n\t\t * @member {'se'|'sw'|'ne'|'nw'} #position\n\t\t */\n\t\tthis.set( 'position', 'se' );\n\n\t\t/**\n\t\t * Collection of the child views in this panel.\n\t\t *\n\t\t * A common child type is the {@link module:ui/list/listview~ListView} and {@link module:ui/toolbar/toolbarview~ToolbarView}.\n\t\t * See {@link module:ui/dropdown/utils~addListToDropdown} and\n\t\t * {@link module:ui/dropdown/utils~addToolbarToDropdown} to learn more about child views of dropdowns.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis.children = this.createCollection();\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-reset',\n\t\t\t\t\t'ck-dropdown__panel',\n\t\t\t\t\tbind.to( 'position', value => `ck-dropdown__panel_${ value }` ),\n\t\t\t\t\tbind.if( 'isVisible', 'ck-dropdown__panel-visible' )\n\t\t\t\t]\n\t\t\t},\n\n\t\t\tchildren: this.children,\n\n\t\t\ton: {\n\t\t\t\t// Drag and drop in the panel should not break the selection in the editor.\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-ui/issues/228\n\t\t\t\tselectstart: bind.to( evt => evt.preventDefault() )\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Focuses the view element or first item in view collection on opening dropdown's panel.\n\t *\n\t * See also {@link module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable}.\n\t */\n\tfocus() {\n\t\tif ( this.children.length ) {\n\t\t\tthis.children.first.focus();\n\t\t}\n\t}\n\n\t/**\n\t * Focuses the view element or last item in view collection on opening dropdown's panel.\n\t *\n\t * See also {@link module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable}.\n\t */\n\tfocusLast() {\n\t\tif ( this.children.length ) {\n\t\t\tconst lastChild = this.children.last;\n\n\t\t\tif ( typeof lastChild.focusLast === 'function' ) {\n\t\t\t\tlastChild.focusLast();\n\t\t\t} else {\n\t\t\t\tlastChild.focus();\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/position\n */\n\nimport global from './global';\nimport Rect from './rect';\nimport getPositionedAncestor from './getpositionedancestor';\nimport getBorderWidths from './getborderwidths';\nimport { isFunction } from 'lodash-es';\n\n/**\n * Calculates the `position: absolute` coordinates of a given element so it can be positioned with respect to the\n * target in the visually most efficient way, taking various restrictions like viewport or limiter geometry\n * into consideration.\n *\n *\t\t// The element which is to be positioned.\n *\t\tconst element = document.body.querySelector( '#toolbar' );\n *\n *\t\t// A target to which the element is positioned relatively.\n *\t\tconst target = document.body.querySelector( '#container' );\n *\n *\t\t// Finding the optimal coordinates for the positioning.\n *\t\tconst { left, top, name } = getOptimalPosition( {\n *\t\t\telement: element,\n *\t\t\ttarget: target,\n *\n * \t\t\t// The algorithm will chose among these positions to meet the requirements such\n * \t\t\t// as \"limiter\" element or \"fitInViewport\", set below. The positions are considered\n * \t\t\t// in the order of the array.\n *\t\t\tpositions: [\n *\t\t\t\t//\n *\t\t\t \t//\t[ Target ]\n *\t\t\t\t//\t+-----------------+\n *\t\t\t\t//\t| Element |\n *\t\t\t\t//\t+-----------------+\n *\t\t\t\t//\n *\t\t\t\ttargetRect => ( {\n *\t\t\t\t\ttop: targetRect.bottom,\n *\t\t\t\t\tleft: targetRect.left,\n *\t\t\t\t\tname: 'mySouthEastPosition'\n *\t\t\t\t} ),\n *\n *\t\t\t\t//\n *\t\t\t\t//\t+-----------------+\n *\t\t\t\t//\t| Element |\n *\t\t\t\t//\t+-----------------+\n *\t\t\t\t//\t[ Target ]\n *\t\t\t\t//\n *\t\t\t\t( targetRect, elementRect ) => ( {\n *\t\t\t\t\ttop: targetRect.top - elementRect.height,\n *\t\t\t\t\tleft: targetRect.left,\n *\t\t\t\t\tname: 'myNorthEastPosition'\n *\t\t\t\t} )\n *\t\t\t],\n *\n *\t\t\t// Find a position such guarantees the element remains within visible boundaries of <body>.\n *\t\t\tlimiter: document.body,\n *\n *\t\t\t// Find a position such guarantees the element remains within visible boundaries of the browser viewport.\n *\t\t\tfitInViewport: true\n *\t\t} );\n *\n *\t\t// The best position which fits into document.body and the viewport. May be useful\n *\t\t// to set proper class on the `element`.\n *\t\tconsole.log( name ); // -> \"myNorthEastPosition\"\n *\n *\t\t// Using the absolute coordinates which has been found to position the element\n *\t\t// as in the diagram depicting the \"myNorthEastPosition\" position.\n *\t\telement.style.top = top;\n *\t\telement.style.left = left;\n *\n * @param {module:utils/dom/position~Options} options Positioning options object.\n * @returns {module:utils/dom/position~Position}\n */\nexport function getOptimalPosition( { element, target, positions, limiter, fitInViewport } ) {\n\t// If the {@link module:utils/dom/position~Options#target} is a function, use what it returns.\n\t// https://github.com/ckeditor/ckeditor5-utils/issues/157\n\tif ( isFunction( target ) ) {\n\t\ttarget = target();\n\t}\n\n\t// If the {@link module:utils/dom/position~Options#limiter} is a function, use what it returns.\n\t// https://github.com/ckeditor/ckeditor5-ui/issues/260\n\tif ( isFunction( limiter ) ) {\n\t\tlimiter = limiter();\n\t}\n\n\tconst positionedElementAncestor = getPositionedAncestor( element.parentElement );\n\tconst elementRect = new Rect( element );\n\tconst targetRect = new Rect( target );\n\n\tlet bestPosition;\n\tlet name;\n\n\t// If there are no limits, just grab the very first position and be done with that drama.\n\tif ( !limiter && !fitInViewport ) {\n\t\t[ name, bestPosition ] = getPosition( positions[ 0 ], targetRect, elementRect );\n\t} else {\n\t\tconst limiterRect = limiter && new Rect( limiter ).getVisible();\n\t\tconst viewportRect = fitInViewport && new Rect( global.window );\n\n\t\t[ name, bestPosition ] =\n\t\t\tgetBestPosition( positions, targetRect, elementRect, limiterRect, viewportRect ) ||\n\t\t\t// If there's no best position found, i.e. when all intersections have no area because\n\t\t\t// rects have no width or height, then just use the first available position.\n\t\t\tgetPosition( positions[ 0 ], targetRect, elementRect );\n\t}\n\n\tlet { left, top } = getAbsoluteRectCoordinates( bestPosition );\n\n\tif ( positionedElementAncestor ) {\n\t\tconst ancestorPosition = getAbsoluteRectCoordinates( new Rect( positionedElementAncestor ) );\n\t\tconst ancestorBorderWidths = getBorderWidths( positionedElementAncestor );\n\n\t\t// (https://github.com/ckeditor/ckeditor5-ui-default/issues/126)\n\t\t// If there's some positioned ancestor of the panel, then its `Rect` must be taken into\n\t\t// consideration. `Rect` is always relative to the viewport while `position: absolute` works\n\t\t// with respect to that positioned ancestor.\n\t\tleft -= ancestorPosition.left;\n\t\ttop -= ancestorPosition.top;\n\n\t\t// (https://github.com/ckeditor/ckeditor5-utils/issues/139)\n\t\t// If there's some positioned ancestor of the panel, not only its position must be taken into\n\t\t// consideration (see above) but also its internal scrolls. Scroll have an impact here because `Rect`\n\t\t// is relative to the viewport (it doesn't care about scrolling), while `position: absolute`\n\t\t// must compensate that scrolling.\n\t\tleft += positionedElementAncestor.scrollLeft;\n\t\ttop += positionedElementAncestor.scrollTop;\n\n\t\t// (https://github.com/ckeditor/ckeditor5-utils/issues/139)\n\t\t// If there's some positioned ancestor of the panel, then its `Rect` includes its CSS `borderWidth`\n\t\t// while `position: absolute` positioning does not consider it.\n\t\t// E.g. `{ position: absolute, top: 0, left: 0 }` means upper left corner of the element,\n\t\t// not upper-left corner of its border.\n\t\tleft -= ancestorBorderWidths.left;\n\t\ttop -= ancestorBorderWidths.top;\n\t}\n\n\treturn { left, top, name };\n}\n\n// For given position function, returns a corresponding `Rect` instance.\n//\n// @private\n// @param {Function} position A function returning {@link module:utils/dom/position~Position}.\n// @param {utils/dom/rect~Rect} targetRect A rect of the target.\n// @param {utils/dom/rect~Rect} elementRect A rect of positioned element.\n// @returns {Array} An array containing position name and its Rect.\nfunction getPosition( position, targetRect, elementRect ) {\n\tconst { left, top, name } = position( targetRect, elementRect );\n\n\treturn [ name, elementRect.clone().moveTo( left, top ) ];\n}\n\n// For a given array of positioning functions, returns such that provides the best\n// fit of the `elementRect` into the `limiterRect` and `viewportRect`.\n//\n// @private\n// @param {module:utils/dom/position~Options#positions} positions Functions returning\n// {@link module:utils/dom/position~Position} to be checked, in the order of preference.\n// @param {utils/dom/rect~Rect} targetRect A rect of the {@link module:utils/dom/position~Options#target}.\n// @param {utils/dom/rect~Rect} elementRect A rect of positioned {@link module:utils/dom/position~Options#element}.\n// @param {utils/dom/rect~Rect} limiterRect A rect of the {@link module:utils/dom/position~Options#limiter}.\n// @param {utils/dom/rect~Rect} viewportRect A rect of the viewport.\n// @returns {Array} An array containing the name of the position and it's rect.\nfunction getBestPosition( positions, targetRect, elementRect, limiterRect, viewportRect ) {\n\tlet maxLimiterIntersectArea = 0;\n\tlet maxViewportIntersectArea = 0;\n\tlet bestPositionRect;\n\tlet bestPositionName;\n\n\t// This is when element is fully visible.\n\tconst elementRectArea = elementRect.getArea();\n\n\tpositions.some( position => {\n\t\tconst [ positionName, positionRect ] = getPosition( position, targetRect, elementRect );\n\t\tlet limiterIntersectArea;\n\t\tlet viewportIntersectArea;\n\n\t\tif ( limiterRect ) {\n\t\t\tif ( viewportRect ) {\n\t\t\t\t// Consider only the part of the limiter which is visible in the viewport. So the limiter is getting limited.\n\t\t\t\tconst limiterViewportIntersectRect = limiterRect.getIntersection( viewportRect );\n\n\t\t\t\tif ( limiterViewportIntersectRect ) {\n\t\t\t\t\t// If the limiter is within the viewport, then check the intersection between that part of the\n\t\t\t\t\t// limiter and actual position.\n\t\t\t\t\tlimiterIntersectArea = limiterViewportIntersectRect.getIntersectionArea( positionRect );\n\t\t\t\t} else {\n\t\t\t\t\tlimiterIntersectArea = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlimiterIntersectArea = limiterRect.getIntersectionArea( positionRect );\n\t\t\t}\n\t\t}\n\n\t\tif ( viewportRect ) {\n\t\t\tviewportIntersectArea = viewportRect.getIntersectionArea( positionRect );\n\t\t}\n\n\t\t// The only criterion: intersection with the viewport.\n\t\tif ( viewportRect && !limiterRect ) {\n\t\t\tif ( viewportIntersectArea > maxViewportIntersectArea ) {\n\t\t\t\tsetBestPosition();\n\t\t\t}\n\t\t}\n\t\t// The only criterion: intersection with the limiter.\n\t\telse if ( !viewportRect && limiterRect ) {\n\t\t\tif ( limiterIntersectArea > maxLimiterIntersectArea ) {\n\t\t\t\tsetBestPosition();\n\t\t\t}\n\t\t}\n\t\t// Two criteria: intersection with the viewport and the limiter visible in the viewport.\n\t\telse {\n\t\t\tif ( viewportIntersectArea > maxViewportIntersectArea && limiterIntersectArea >= maxLimiterIntersectArea ) {\n\t\t\t\tsetBestPosition();\n\t\t\t} else if ( viewportIntersectArea >= maxViewportIntersectArea && limiterIntersectArea > maxLimiterIntersectArea ) {\n\t\t\t\tsetBestPosition();\n\t\t\t}\n\t\t}\n\n\t\tfunction setBestPosition() {\n\t\t\tmaxViewportIntersectArea = viewportIntersectArea;\n\t\t\tmaxLimiterIntersectArea = limiterIntersectArea;\n\t\t\tbestPositionRect = positionRect;\n\t\t\tbestPositionName = positionName;\n\t\t}\n\n\t\t// If a such position is found that element is fully container by the limiter then, obviously,\n\t\t// there will be no better one, so finishing.\n\t\treturn limiterIntersectArea === elementRectArea;\n\t} );\n\n\treturn bestPositionRect ? [ bestPositionName, bestPositionRect ] : null;\n}\n\n// DOMRect (also Rect) works in a scroll–independent geometry but `position: absolute` doesn't.\n// This function converts Rect to `position: absolute` coordinates.\n//\n// @private\n// @param {utils/dom/rect~Rect} rect A rect to be converted.\n// @returns {Object} Object containing `left` and `top` properties, in absolute coordinates.\nfunction getAbsoluteRectCoordinates( { left, top } ) {\n\tconst { scrollX, scrollY } = global.window;\n\n\treturn {\n\t\tleft: left + scrollX,\n\t\ttop: top + scrollY,\n\t};\n}\n\n/**\n * The `getOptimalPosition` helper options.\n *\n * @interface module:utils/dom/position~Options\n */\n\n/**\n * Element that is to be positioned.\n *\n * @member {HTMLElement} #element\n */\n\n/**\n * Target with respect to which the `element` is to be positioned.\n *\n * @member {HTMLElement|Range|ClientRect|Rect|Function} #target\n */\n\n/**\n * An array of functions which return {@link module:utils/dom/position~Position} relative\n * to the `target`, in the order of preference.\n *\n * @member {Array.<Function>} #positions\n */\n\n/**\n * When set, the algorithm will chose position which fits the most in the\n * limiter's bounding rect.\n *\n * @member {HTMLElement|Range|ClientRect|Rect|Function} #limiter\n */\n\n/**\n * When set, the algorithm will chose such a position which fits `element`\n * the most inside visible viewport.\n *\n * @member {Boolean} #fitInViewport\n */\n\n/**\n * An object describing a position in `position: absolute` coordinate\n * system, along with position name.\n *\n * @typedef {Object} module:utils/dom/position~Position\n *\n * @property {Number} top Top position offset.\n * @property {Number} left Left position offset.\n * @property {String} name Name of the position.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/getpositionedancestor\n */\n\nimport global from './global';\n\n/**\n * For a given element, returns the nearest ancestor element which CSS position is not \"static\".\n *\n * @param {HTMLElement} element The native DOM element to be checked.\n * @returns {HTMLElement|null}\n */\nexport default function getPositionedAncestor( element ) {\n\twhile ( element && element.tagName.toLowerCase() != 'html' ) {\n\t\tif ( global.window.getComputedStyle( element ).position != 'static' ) {\n\t\t\treturn element;\n\t\t}\n\n\t\telement = element.parentElement;\n\t}\n\n\treturn null;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/dropdown/dropdownview\n */\n\nimport View from '../view';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\nimport KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';\n\nimport '../../theme/components/dropdown/dropdown.css';\n\nimport { getOptimalPosition } from '@ckeditor/ckeditor5-utils/src/dom/position';\n\n/**\n * The dropdown view class. It manages the dropdown button and dropdown panel.\n *\n * In most cases, the easiest way to create a dropdown is by using the {@link module:ui/dropdown/utils~createDropdown}\n * util:\n *\n *\t\tconst dropdown = createDropdown( locale );\n *\n *\t\t// Configure dropdown's button properties:\n *\t\tdropdown.buttonView.set( {\n *\t\t\tlabel: 'A dropdown',\n *\t\t\twithText: true\n *\t\t} );\n *\n *\t\tdropdown.render();\n *\n *\t\tdropdown.panelView.element.textContent = 'Content of the panel';\n *\n *\t\t// Will render a dropdown with a panel containing a \"Content of the panel\" text.\n *\t\tdocument.body.appendChild( dropdown.element );\n *\n * If you want to add a richer content to the dropdown panel, you can use the {@link module:ui/dropdown/utils~addListToDropdown}\n * and {@link module:ui/dropdown/utils~addToolbarToDropdown} helpers. See more examples in\n * {@link module:ui/dropdown/utils~createDropdown} documentation.\n *\n * If you want to create a completely custom dropdown, then you can compose it manually:\n *\n *\t\tconst button = new DropdownButtonView( locale );\n *\t\tconst panel = new DropdownPanelView( locale );\n *\t\tconst dropdown = new DropdownView( locale, button, panel );\n *\n *\t\tbutton.set( {\n *\t\t\tlabel: 'A dropdown',\n *\t\t\twithText: true\n *\t\t} );\n *\n *\t\tdropdown.render();\n *\n *\t\tpanel.element.textContent = 'Content of the panel';\n *\n *\t\t// Will render a dropdown with a panel containing a \"Content of the panel\" text.\n *\t\tdocument.body.appendChild( dropdown.element );\n *\n * However, dropdown created this way will contain little behavior. You will need to implement handlers for actions\n * such as {@link module:ui/bindings/clickoutsidehandler~clickOutsideHandler clicking outside an open dropdown}\n * (which should close it) and support for arrow keys inside the panel. Therefore, unless you really know what\n * you do and you really need to do it, it is recommended to use the {@link module:ui/dropdown/utils~createDropdown} helper.\n *\n * @extends module:ui/view~View\n */\nexport default class DropdownView extends View {\n\t/**\n\t * Creates an instance of the dropdown.\n\t *\n\t * Also see {@link #render}.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The localization services instance.\n\t * @param {module:ui/dropdown/button/dropdownbutton~DropdownButton} buttonView\n\t * @param {module:ui/dropdown/dropdownpanelview~DropdownPanelView} panelView\n\t */\n\tconstructor( locale, buttonView, panelView ) {\n\t\tsuper( locale );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\t/**\n\t\t * Button of the dropdown view. Clicking the button opens the {@link #panelView}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/button/buttonview~ButtonView} #buttonView\n\t\t */\n\t\tthis.buttonView = buttonView;\n\n\t\t/**\n\t\t * Panel of the dropdown. It opens when the {@link #buttonView} is\n\t\t * {@link module:ui/button/buttonview~ButtonView#event:execute executed} (i.e. clicked).\n\t\t *\n\t\t * Child views can be added to the panel's `children` collection:\n\t\t *\n\t\t *\t\tdropdown.panelView.children.add( childView );\n\t\t *\n\t\t * See {@link module:ui/dropdown/dropdownpanelview~DropdownPanelView#children} and\n\t\t * {@link module:ui/viewcollection~ViewCollection#add}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/dropdown/dropdownpanelview~DropdownPanelView} #panelView\n\t\t */\n\t\tthis.panelView = panelView;\n\n\t\t/**\n\t\t * Controls whether the dropdown view is open, i.e. shows or hides the {@link #panelView panel}.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isOpen\n\t\t */\n\t\tthis.set( 'isOpen', false );\n\n\t\t/**\n\t\t * Controls whether the dropdown is enabled, i.e. it can be clicked and execute an action.\n\t\t *\n\t\t * See {@link module:ui/button/buttonview~ButtonView#isEnabled}.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isEnabled\n\t\t */\n\t\tthis.set( 'isEnabled', true );\n\n\t\t/**\n\t\t * (Optional) The additional CSS class set on the dropdown {@link #element}.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #class\n\t\t */\n\t\tthis.set( 'class' );\n\n\t\t/**\n\t\t * The position of the panel, relative to the dropdown.\n\t\t *\n\t\t * **Note**: When `'auto'`, the panel will use one of the remaining positions to stay\n\t\t * in the viewport, visible to the user. The positions correspond directly to\n\t\t * {@link module:ui/dropdown/dropdownview~DropdownView.defaultPanelPositions default panel positions}.\n\t\t *\n\t\t * **Note**: This value has an impact on the\n\t\t * {@link module:ui/dropdown/dropdownpanelview~DropdownPanelView#position} property\n\t\t * each time the panel becomes {@link #isOpen open}.\n\t\t *\n\t\t * @observable\n\t\t * @default 'auto'\n\t\t * @member {'auto'|'se'|'sw'|'ne'|'nw'} #panelPosition\n\t\t */\n\t\tthis.set( 'panelPosition', 'auto' );\n\n\t\t/**\n\t\t * Tracks information about DOM focus in the dropdown.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n\t\tthis.focusTracker = new FocusTracker();\n\n\t\t/**\n\t\t * Instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}. It manages\n\t\t * keystrokes of the dropdown:\n\t\t *\n\t\t * * <kbd>▼</kbd> opens the dropdown,\n\t\t * * <kbd>◀</kbd> and <kbd>Esc</kbd> closes the dropdown.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler}\n\t\t */\n\t\tthis.keystrokes = new KeystrokeHandler();\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-dropdown',\n\t\t\t\t\tbind.to( 'class' ),\n\t\t\t\t\tbind.if( 'isEnabled', 'ck-disabled', value => !value )\n\t\t\t\t]\n\t\t\t},\n\n\t\t\tchildren: [\n\t\t\t\tbuttonView,\n\t\t\t\tpanelView\n\t\t\t]\n\t\t} );\n\n\t\tbuttonView.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck-dropdown__button',\n\t\t\t\t]\n\t\t\t}\n\t\t} );\n\n\t\t/**\n\t\t * A child {@link module:ui/list/listview~ListView list view} of the dropdown located\n\t\t * in its {@link module:ui/dropdown/dropdownview~DropdownView#panelView panel}.\n\t\t *\n\t\t * **Note**: Only supported when dropdown has list view added using {@link module:ui/dropdown/utils~addListToDropdown}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/list/listview~ListView} #listView\n\t\t */\n\n\t\t/**\n\t\t * A child toolbar of the dropdown located in the\n\t\t * {@link module:ui/dropdown/dropdownview~DropdownView#panelView panel}.\n\t\t *\n\t\t * **Note**: Only supported when dropdown has list view added using {@link module:ui/dropdown/utils~addToolbarToDropdown}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/toolbar/toolbarview~ToolbarView} #toolbarView\n\t\t */\n\n\t\t/**\n\t\t * Fired when the toolbar button or list item is executed.\n\t\t *\n\t\t * For {@link #listView} It fires when a child of some {@link module:ui/list/listitemview~ListItemView}\n\t\t * fired `execute`.\n\t\t *\n\t\t * For {@link #toolbarView} It fires when one of the buttons has been\n\t\t * {@link module:ui/button/buttonview~ButtonView#event:execute executed}.\n\t\t *\n\t\t * **Note**: Only supported when dropdown has list view added using {@link module:ui/dropdown/utils~addListToDropdown}\n\t\t * or {@link module:ui/dropdown/utils~addToolbarToDropdown}.\n\t\t *\n\t\t * @event execute\n\t\t */\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\t// Toggle the dropdown when its button has been clicked.\n\t\tthis.listenTo( this.buttonView, 'open', () => {\n\t\t\tthis.isOpen = !this.isOpen;\n\t\t} );\n\n\t\t// Toggle the visibility of the panel when the dropdown becomes open.\n\t\tthis.panelView.bind( 'isVisible' ).to( this, 'isOpen' );\n\n\t\t// Let the dropdown control the position of the panel. The position must\n\t\t// be updated every time the dropdown is open.\n\t\tthis.on( 'change:isOpen', () => {\n\t\t\tif ( !this.isOpen ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If \"auto\", find the best position of the panel to fit into the viewport.\n\t\t\t// Otherwise, simply assign the static position.\n\t\t\tif ( this.panelPosition === 'auto' ) {\n\t\t\t\tthis.panelView.position = DropdownView._getOptimalPosition( {\n\t\t\t\t\telement: this.panelView.element,\n\t\t\t\t\ttarget: this.buttonView.element,\n\t\t\t\t\tfitInViewport: true,\n\t\t\t\t\tpositions: this._panelPositions\n\t\t\t\t} ).name;\n\t\t\t} else {\n\t\t\t\tthis.panelView.position = this.panelPosition;\n\t\t\t}\n\t\t} );\n\n\t\t// Listen for keystrokes coming from within #element.\n\t\tthis.keystrokes.listenTo( this.element );\n\n\t\t// Register #element in the focus tracker.\n\t\tthis.focusTracker.add( this.element );\n\n\t\tconst closeDropdown = ( data, cancel ) => {\n\t\t\tif ( this.isOpen ) {\n\t\t\t\tthis.buttonView.focus();\n\t\t\t\tthis.isOpen = false;\n\t\t\t\tcancel();\n\t\t\t}\n\t\t};\n\n\t\t// Open the dropdown panel using the arrow down key, just like with return or space.\n\t\tthis.keystrokes.set( 'arrowdown', ( data, cancel ) => {\n\t\t\t// Don't open if the dropdown is disabled or already open.\n\t\t\tif ( this.buttonView.isEnabled && !this.isOpen ) {\n\t\t\t\tthis.isOpen = true;\n\t\t\t\tcancel();\n\t\t\t}\n\t\t} );\n\n\t\t// Block the right arrow key (until nested dropdowns are implemented).\n\t\tthis.keystrokes.set( 'arrowright', ( data, cancel ) => {\n\t\t\tif ( this.isOpen ) {\n\t\t\t\tcancel();\n\t\t\t}\n\t\t} );\n\n\t\t// Close the dropdown using the arrow left/escape key.\n\t\tthis.keystrokes.set( 'arrowleft', closeDropdown );\n\t\tthis.keystrokes.set( 'esc', closeDropdown );\n\t}\n\n\t/**\n\t * Focuses the {@link #buttonView}.\n\t */\n\tfocus() {\n\t\tthis.buttonView.focus();\n\t}\n\n\t/**\n\t * Returns {@link #panelView panel} positions to be used by the\n\t * {@link module:utils/dom/position~getOptimalPosition `getOptimalPosition()`}\n\t * utility considering the direction of the language the UI of the editor is displayed in.\n\t *\n\t * @type {module:utils/dom/position~Options#positions}\n\t * @private\n\t */\n\tget _panelPositions() {\n\t\tconst { southEast, southWest, northEast, northWest } = DropdownView.defaultPanelPositions;\n\n\t\tif ( this.locale.uiLanguageDirection === 'ltr' ) {\n\t\t\treturn [ southEast, southWest, northEast, northWest ];\n\t\t} else {\n\t\t\treturn [ southWest, southEast, northWest, northEast ];\n\t\t}\n\t}\n}\n\n/**\n * A set of positioning functions used by the dropdown view to determine\n * the optimal position (i.e. fitting into the browser viewport) of its\n * {@link module:ui/dropdown/dropdownview~DropdownView#panelView panel} when\n * {@link module:ui/dropdown/dropdownview~DropdownView#panelPosition} is set to 'auto'`.\n *\n * The available positioning functions are as follow:\n *\n * **South**\n *\n * * `southEast`\n *\n *\t\t[ Button ]\n *\t\t+-----------------+\n *\t\t| Panel |\n *\t\t+-----------------+\n *\n * * `southWest`\n *\n *\t\t [ Button ]\n *\t\t+-----------------+\n *\t\t| Panel |\n *\t\t+-----------------+\n *\n * **North**\n *\n * * `northEast`\n *\n *\t\t+-----------------+\n *\t\t| Panel |\n *\t\t+-----------------+\n *\t\t[ Button ]\n *\n * * `northWest`\n *\n *\t\t+-----------------+\n *\t\t| Panel |\n *\t\t+-----------------+\n *\t\t [ Button ]\n *\n * Positioning functions are compatible with {@link module:utils/dom/position~Position}.\n *\n * The name that position function returns will be reflected in dropdown panel's class that\n * controls its placement. See {@link module:ui/dropdown/dropdownview~DropdownView#panelPosition}\n * to learn more.\n *\n * @member {Object} module:ui/dropdown/dropdownview~DropdownView.defaultPanelPositions\n */\nDropdownView.defaultPanelPositions = {\n\tsouthEast: buttonRect => {\n\t\treturn {\n\t\t\ttop: buttonRect.bottom,\n\t\t\tleft: buttonRect.left,\n\t\t\tname: 'se'\n\t\t};\n\t},\n\tsouthWest: ( buttonRect, panelRect ) => {\n\t\treturn {\n\t\t\ttop: buttonRect.bottom,\n\t\t\tleft: buttonRect.left - panelRect.width + buttonRect.width,\n\t\t\tname: 'sw'\n\t\t};\n\t},\n\tnorthEast: ( buttonRect, panelRect ) => {\n\t\treturn {\n\t\t\ttop: buttonRect.top - panelRect.height,\n\t\t\tleft: buttonRect.left,\n\t\t\tname: 'ne'\n\t\t};\n\t},\n\tnorthWest: ( buttonRect, panelRect ) => {\n\t\treturn {\n\t\t\ttop: buttonRect.bottom - panelRect.height,\n\t\t\tleft: buttonRect.left - panelRect.width + buttonRect.width,\n\t\t\tname: 'nw'\n\t\t};\n\t}\n};\n\n/**\n * A function used to calculate the optimal position for the dropdown panel.\n *\n * @protected\n * @member {Function} module:ui/dropdown/dropdownview~DropdownView._getOptimalPosition\n */\nDropdownView._getOptimalPosition = getOptimalPosition;\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* global DOMParser */\n\n/**\n * @module ui/icon/iconview\n */\n\nimport View from '../view';\n\nimport '../../theme/components/icon/icon.css';\n\n/**\n * The icon view class.\n *\n * @extends module:ui/view~View\n */\nexport default class IconView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\tconst bind = this.bindTemplate;\n\n\t\t/**\n\t\t * The SVG source of the icon.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #content\n\t\t */\n\t\tthis.set( 'content', '' );\n\n\t\t/**\n\t\t * This attribute specifies the boundaries to which the\n\t\t * icon content should stretch.\n\t\t *\n\t\t * @observable\n\t\t * @default '0 0 20 20'\n\t\t * @member {String} #viewBox\n\t\t */\n\t\tthis.set( 'viewBox', '0 0 20 20' );\n\n\t\t/**\n\t\t * The fill color of the child `path.ck-icon__fill`.\n\t\t *\n\t\t * @observable\n\t\t * @default ''\n\t\t * @member {String} #fillColor\n\t\t */\n\t\tthis.set( 'fillColor', '' );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'svg',\n\t\t\tns: 'http://www.w3.org/2000/svg',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-icon'\n\t\t\t\t],\n\t\t\t\tviewBox: bind.to( 'viewBox' )\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tthis._updateXMLContent();\n\t\tthis._colorFillPaths();\n\n\t\t// This is a hack for lack of innerHTML binding.\n\t\t// See: https://github.com/ckeditor/ckeditor5-ui/issues/99.\n\t\tthis.on( 'change:content', () => {\n\t\t\tthis._updateXMLContent();\n\t\t\tthis._colorFillPaths();\n\t\t} );\n\n\t\tthis.on( 'change:fillColor', () => {\n\t\t\tthis._colorFillPaths();\n\t\t} );\n\t}\n\n\t/**\n\t * Updates the {@link #element} with the value of {@link #content}.\n\t *\n\t * @private\n\t */\n\t_updateXMLContent() {\n\t\tif ( this.content ) {\n\t\t\tconst parsed = new DOMParser().parseFromString( this.content.trim(), 'image/svg+xml' );\n\t\t\tconst svg = parsed.querySelector( 'svg' );\n\t\t\tconst viewBox = svg.getAttribute( 'viewBox' );\n\n\t\t\tif ( viewBox ) {\n\t\t\t\tthis.viewBox = viewBox;\n\t\t\t}\n\n\t\t\tthis.element.innerHTML = '';\n\n\t\t\twhile ( svg.childNodes.length > 0 ) {\n\t\t\t\tthis.element.appendChild( svg.childNodes[ 0 ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Fills all child `path.ck-icon__fill` with the `#fillColor`.\n\t *\n\t * @private\n\t */\n\t_colorFillPaths() {\n\t\tif ( this.fillColor ) {\n\t\t\tthis.element.querySelectorAll( '.ck-icon__fill' ).forEach( path => {\n\t\t\t\tpath.style.fill = this.fillColor;\n\t\t\t} );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/tooltip/tooltipview\n */\n\nimport View from '../view';\n\nimport '../../theme/components/tooltip/tooltip.css';\n\n/**\n * The tooltip view class.\n *\n * @extends module:ui/view~View\n */\nexport default class TooltipView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * The text of the tooltip visible to the user.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #text\n\t\t */\n\t\tthis.set( 'text', '' );\n\n\t\t/**\n\t\t * The position of the tooltip (south or north).\n\t\t *\n\t\t *\t\t+-----------+\n\t\t *\t\t| north |\n\t\t *\t\t+-----------+\n\t\t *\t\t V\n\t\t *\t\t [element]\n\t\t *\n\t\t *\t\t [element]\n\t\t *\t\t ^\n\t\t *\t\t+-----------+\n\t\t *\t\t| south |\n\t\t *\t\t+-----------+\n\t\t *\n\t\t * @observable\n\t\t * @default 's'\n\t\t * @member {'s'|'n'} #position\n\t\t */\n\t\tthis.set( 'position', 's' );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'span',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-tooltip',\n\t\t\t\t\tbind.to( 'position', position => 'ck-tooltip_' + position ),\n\t\t\t\t\tbind.if( 'text', 'ck-hidden', value => !value.trim() )\n\t\t\t\t]\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'span',\n\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tclass: [\n\t\t\t\t\t\t\t'ck',\n\t\t\t\t\t\t\t'ck-tooltip__text'\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\n\t\t\t\t\tchildren: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: bind.to( 'text' ),\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/button/buttonview\n */\n\nimport View from '../view';\nimport IconView from '../icon/iconview';\nimport TooltipView from '../tooltip/tooltipview';\n\nimport uid from '@ckeditor/ckeditor5-utils/src/uid';\nimport { getEnvKeystrokeText } from '@ckeditor/ckeditor5-utils/src/keyboard';\n\nimport '../../theme/components/button/button.css';\n\n/**\n * The button view class.\n *\n *\t\tconst view = new ButtonView();\n *\n *\t\tview.set( {\n *\t\t\tlabel: 'A button',\n *\t\t\tkeystroke: 'Ctrl+B',\n *\t\t\ttooltip: true,\n *\t\t\twithText: true\n *\t\t} );\n *\n *\t\tview.render();\n *\n *\t\tdocument.body.append( view.element );\n *\n * @extends module:ui/view~View\n * @implements module:ui/button/button~Button\n */\nexport default class ButtonView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tconst bind = this.bindTemplate;\n\t\tconst ariaLabelUid = uid();\n\n\t\t// Implement the Button interface.\n\t\tthis.set( 'class' );\n\t\tthis.set( 'labelStyle' );\n\t\tthis.set( 'icon' );\n\t\tthis.set( 'isEnabled', true );\n\t\tthis.set( 'isOn', false );\n\t\tthis.set( 'isVisible', true );\n\t\tthis.set( 'isToggleable', false );\n\t\tthis.set( 'keystroke' );\n\t\tthis.set( 'label' );\n\t\tthis.set( 'tabindex', -1 );\n\t\tthis.set( 'tooltip' );\n\t\tthis.set( 'tooltipPosition', 's' );\n\t\tthis.set( 'type', 'button' );\n\t\tthis.set( 'withText', false );\n\n\t\t/**\n\t\t * Collection of the child views inside of the button {@link #element}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis.children = this.createCollection();\n\n\t\t/**\n\t\t * Tooltip of the button view. It is configurable using the {@link #tooltip tooltip attribute}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/tooltip/tooltipview~TooltipView} #tooltipView\n\t\t */\n\t\tthis.tooltipView = this._createTooltipView();\n\n\t\t/**\n\t\t * Label of the button view. It is configurable using the {@link #label label attribute}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/view~View} #labelView\n\t\t */\n\t\tthis.labelView = this._createLabelView( ariaLabelUid );\n\n\t\t/**\n\t\t * The icon view of the button. Will be added to {@link #children} when the\n\t\t * {@link #icon icon attribute} is defined.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/icon/iconview~IconView} #iconView\n\t\t */\n\t\tthis.iconView = new IconView();\n\n\t\tthis.iconView.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: 'ck-button__icon'\n\t\t\t}\n\t\t} );\n\n\t\t/**\n\t\t * Tooltip of the button bound to the template.\n\t\t *\n\t\t * @see #tooltip\n\t\t * @see #_getTooltipString\n\t\t * @private\n\t\t * @observable\n\t\t * @member {Boolean} #_tooltipString\n\t\t */\n\t\tthis.bind( '_tooltipString' ).to(\n\t\t\tthis, 'tooltip',\n\t\t\tthis, 'label',\n\t\t\tthis, 'keystroke',\n\t\t\tthis._getTooltipString.bind( this )\n\t\t);\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'button',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-button',\n\t\t\t\t\tbind.to( 'class' ),\n\t\t\t\t\tbind.if( 'isEnabled', 'ck-disabled', value => !value ),\n\t\t\t\t\tbind.if( 'isVisible', 'ck-hidden', value => !value ),\n\t\t\t\t\tbind.to( 'isOn', value => value ? 'ck-on' : 'ck-off' ),\n\t\t\t\t\tbind.if( 'withText', 'ck-button_with-text' )\n\t\t\t\t],\n\t\t\t\ttype: bind.to( 'type', value => value ? value : 'button' ),\n\t\t\t\ttabindex: bind.to( 'tabindex' ),\n\t\t\t\t'aria-labelledby': `ck-editor__aria-label_${ ariaLabelUid }`,\n\t\t\t\t'aria-disabled': bind.if( 'isEnabled', true, value => !value ),\n\t\t\t\t'aria-pressed': bind.to( 'isOn', value => this.isToggleable ? String( value ) : false )\n\t\t\t},\n\n\t\t\tchildren: this.children,\n\n\t\t\ton: {\n\t\t\t\tmousedown: bind.to( evt => {\n\t\t\t\t\tevt.preventDefault();\n\t\t\t\t} ),\n\n\t\t\t\tclick: bind.to( evt => {\n\t\t\t\t\t// We can't make the button disabled using the disabled attribute, because it won't be focusable.\n\t\t\t\t\t// Though, shouldn't this condition be moved to the button controller?\n\t\t\t\t\tif ( this.isEnabled ) {\n\t\t\t\t\t\tthis.fire( 'execute' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Prevent the default when button is disabled, to block e.g.\n\t\t\t\t\t\t// automatic form submitting. See ckeditor/ckeditor5-link#74.\n\t\t\t\t\t\tevt.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tif ( this.icon ) {\n\t\t\tthis.iconView.bind( 'content' ).to( this, 'icon' );\n\t\t\tthis.children.add( this.iconView );\n\t\t}\n\n\t\tthis.children.add( this.tooltipView );\n\t\tthis.children.add( this.labelView );\n\t}\n\n\t/**\n\t * Focuses the {@link #element} of the button.\n\t */\n\tfocus() {\n\t\tthis.element.focus();\n\t}\n\n\t/**\n\t * Creates a {@link module:ui/tooltip/tooltipview~TooltipView} instance and binds it with button\n\t * attributes.\n\t *\n\t * @private\n\t * @returns {module:ui/tooltip/tooltipview~TooltipView}\n\t */\n\t_createTooltipView() {\n\t\tconst tooltipView = new TooltipView();\n\n\t\ttooltipView.bind( 'text' ).to( this, '_tooltipString' );\n\t\ttooltipView.bind( 'position' ).to( this, 'tooltipPosition' );\n\n\t\treturn tooltipView;\n\t}\n\n\t/**\n\t * Creates a label view instance and binds it with button attributes.\n\t *\n\t * @private\n\t * @param {String} ariaLabelUid The aria label UID.\n\t * @returns {module:ui/view~View}\n\t */\n\t_createLabelView( ariaLabelUid ) {\n\t\tconst labelView = new View();\n\t\tconst bind = this.bindTemplate;\n\n\t\tlabelView.setTemplate( {\n\t\t\ttag: 'span',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-button__label'\n\t\t\t\t],\n\t\t\t\tstyle: bind.to( 'labelStyle' ),\n\t\t\t\tid: `ck-editor__aria-label_${ ariaLabelUid }`,\n\t\t\t},\n\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttext: this.bindTemplate.to( 'label' )\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\n\t\treturn labelView;\n\t}\n\n\t/**\n\t * Gets the text for the {@link #tooltipView} from the combination of\n\t * {@link #tooltip}, {@link #label} and {@link #keystroke} attributes.\n\t *\n\t * @private\n\t * @see #tooltip\n\t * @see #_tooltipString\n\t * @param {Boolean|String|Function} tooltip Button tooltip.\n\t * @param {String} label Button label.\n\t * @param {String} keystroke Button keystroke.\n\t * @returns {String}\n\t */\n\t_getTooltipString( tooltip, label, keystroke ) {\n\t\tif ( tooltip ) {\n\t\t\tif ( typeof tooltip == 'string' ) {\n\t\t\t\treturn tooltip;\n\t\t\t} else {\n\t\t\t\tif ( keystroke ) {\n\t\t\t\t\tkeystroke = getEnvKeystrokeText( keystroke );\n\t\t\t\t}\n\n\t\t\t\tif ( tooltip instanceof Function ) {\n\t\t\t\t\treturn tooltip( label, keystroke );\n\t\t\t\t} else {\n\t\t\t\t\treturn `${ label }${ keystroke ? ` (${ keystroke })` : '' }`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn '';\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 10 10\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M.941 4.523a.75.75 0 1 1 1.06-1.06l3.006 3.005 3.005-3.005a.75.75 0 1 1 1.06 1.06l-3.549 3.55a.75.75 0 0 1-1.168-.136L.941 4.523z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, 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 ui/dropdown/button/dropdownbuttonview\n */\n\nimport ButtonView from '../../button/buttonview';\n\nimport dropdownArrowIcon from '../../../theme/icons/dropdown-arrow.svg';\nimport IconView from '../../icon/iconview';\n\n/**\n * The default dropdown button view class.\n *\n *\t\tconst view = new DropdownButtonView();\n *\n *\t\tview.set( {\n *\t\t\tlabel: 'A button',\n *\t\t\tkeystroke: 'Ctrl+B',\n *\t\t\ttooltip: true\n *\t\t} );\n *\n *\t\tview.render();\n *\n *\t\tdocument.body.append( view.element );\n *\n * Also see the {@link module:ui/dropdown/utils~createDropdown `createDropdown()` util}.\n *\n * @implements module:ui/dropdown/button/dropdownbutton~DropdownButton\n * @extends module:ui/button/buttonview~ButtonView\n */\nexport default class DropdownButtonView extends ButtonView {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * An icon that displays arrow to indicate a dropdown button.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/icon/iconview~IconView}\n\t\t */\n\t\tthis.arrowView = this._createArrowView();\n\n\t\tthis.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\t'aria-haspopup': true\n\t\t\t}\n\t\t} );\n\n\t\t// The DropdownButton interface expects the open event upon which will open the dropdown.\n\t\tthis.delegate( 'execute' ).to( this, 'open' );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tthis.children.add( this.arrowView );\n\t}\n\n\t/**\n\t * Creates a {@link module:ui/icon/iconview~IconView} instance as {@link #arrowView}.\n\t *\n\t * @private\n\t * @returns {module:ui/icon/iconview~IconView}\n\t */\n\t_createArrowView() {\n\t\tconst arrowView = new IconView();\n\n\t\tarrowView.content = dropdownArrowIcon;\n\n\t\tarrowView.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: 'ck-dropdown__arrow'\n\t\t\t}\n\t\t} );\n\n\t\treturn arrowView;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/list/listview\n */\n\nimport View from '../view';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\nimport FocusCycler from '../focuscycler';\nimport KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';\n\nimport '../../theme/components/list/list.css';\n\n/**\n * The list view class.\n *\n * @extends module:ui/view~View\n * @implements module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable\n */\nexport default class ListView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor() {\n\t\tsuper();\n\n\t\t/**\n\t\t * Collection of the child list views.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis.items = this.createCollection();\n\n\t\t/**\n\t\t * Tracks information about DOM focus in the list.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n\t\tthis.focusTracker = new FocusTracker();\n\n\t\t/**\n\t\t * Instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler}\n\t\t */\n\t\tthis.keystrokes = new KeystrokeHandler();\n\n\t\t/**\n\t\t * Helps cycling over focusable {@link #items} in the list.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/focuscycler~FocusCycler}\n\t\t */\n\t\tthis._focusCycler = new FocusCycler( {\n\t\t\tfocusables: this.items,\n\t\t\tfocusTracker: this.focusTracker,\n\t\t\tkeystrokeHandler: this.keystrokes,\n\t\t\tactions: {\n\t\t\t\t// Navigate list items backwards using the arrowup key.\n\t\t\t\tfocusPrevious: 'arrowup',\n\n\t\t\t\t// Navigate toolbar items forwards using the arrowdown key.\n\t\t\t\tfocusNext: 'arrowdown',\n\t\t\t}\n\t\t} );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'ul',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-reset',\n\t\t\t\t\t'ck-list'\n\t\t\t\t]\n\t\t\t},\n\n\t\t\tchildren: this.items\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\t// Items added before rendering should be known to the #focusTracker.\n\t\tfor ( const item of this.items ) {\n\t\t\tthis.focusTracker.add( item.element );\n\t\t}\n\n\t\tthis.items.on( 'add', ( evt, item ) => {\n\t\t\tthis.focusTracker.add( item.element );\n\t\t} );\n\n\t\tthis.items.on( 'remove', ( evt, item ) => {\n\t\t\tthis.focusTracker.remove( item.element );\n\t\t} );\n\n\t\t// Start listening for the keystrokes coming from #element.\n\t\tthis.keystrokes.listenTo( this.element );\n\t}\n\n\t/**\n\t * Focuses the first focusable in {@link #items}.\n\t */\n\tfocus() {\n\t\tthis._focusCycler.focusFirst();\n\t}\n\n\t/**\n\t * Focuses the last focusable in {@link #items}.\n\t */\n\tfocusLast() {\n\t\tthis._focusCycler.focusLast();\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/list/listitemview\n */\n\nimport View from '../view';\n\n/**\n * The list item view class.\n *\n * @extends module:ui/view~View\n */\nexport default class ListItemView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * Collection of the child views inside of the list item {@link #element}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis.children = this.createCollection();\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'li',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-list__item'\n\t\t\t\t]\n\t\t\t},\n\n\t\t\tchildren: this.children\n\t\t} );\n\t}\n\n\t/**\n\t * Focuses the list item.\n\t */\n\tfocus() {\n\t\tthis.children.first.focus();\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/list/listseparatorview\n */\n\nimport View from '../view';\n\n/**\n * The list separator view class.\n *\n * @extends module:ui/view~View\n */\nexport default class ListSeparatorView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'li',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-list__separator'\n\t\t\t\t]\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/button/switchbuttonview\n */\n\nimport View from '../view';\nimport ButtonView from './buttonview';\n\nimport '../../theme/components/button/switchbutton.css';\n\n/**\n * The switch button view class.\n *\n *\t\tconst view = new SwitchButtonView();\n *\n *\t\tview.set( {\n *\t\t\twithText: true,\n *\t\t\tlabel: 'Switch me!'\n *\t\t} );\n *\n *\t\tview.render();\n *\n *\t\tdocument.body.append( view.element );\n *\n * @extends module:ui/button/buttonview~ButtonView\n */\nexport default class SwitchButtonView extends ButtonView {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tthis.isToggleable = true;\n\n\t\t/**\n\t\t * The toggle switch of the button.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/view~View} #toggleSwitchView\n\t\t */\n\t\tthis.toggleSwitchView = this._createToggleView();\n\n\t\tthis.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: 'ck-switchbutton'\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tthis.children.add( this.toggleSwitchView );\n\t}\n\n\t/**\n\t * Creates a toggle child view.\n\t *\n\t * @private\n\t * @returns {module:ui/view~View}\n\t */\n\t_createToggleView() {\n\t\tconst toggleSwitchView = new View();\n\n\t\ttoggleSwitchView.setTemplate( {\n\t\t\ttag: 'span',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-button__toggle'\n\t\t\t\t],\n\t\t\t},\n\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'span',\n\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tclass: [\n\t\t\t\t\t\t\t'ck',\n\t\t\t\t\t\t\t'ck-button__toggle__inner'\n\t\t\t\t\t\t],\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\n\t\treturn toggleSwitchView;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/bindings/clickoutsidehandler\n */\n\n/* global document */\n\n/**\n * Handles clicking **outside** of a specified set of elements, then fires an action.\n *\n * **Note**: Actually, the action is executed upon `mousedown`, not `click`. It prevents\n * certain issues when the user keeps holding the mouse button and the UI cannot react\n * properly.\n *\n * @param {Object} options Configuration options.\n * @param {module:utils/dom/emittermixin~Emitter} options.emitter The emitter to which this behavior\n * should be added.\n * @param {Function} options.activator Function returning a `Boolean`, to determine whether the handler is active.\n * @param {Array.<HTMLElement>} options.contextElements HTML elements that determine the scope of the\n * handler. Clicking any of them or their descendants will **not** fire the callback.\n * @param {Function} options.callback An action executed by the handler.\n */\nexport default function clickOutsideHandler( { emitter, activator, callback, contextElements } ) {\n\temitter.listenTo( document, 'mousedown', ( evt, { target } ) => {\n\t\tif ( !activator() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( const contextElement of contextElements ) {\n\t\t\tif ( contextElement.contains( target ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tcallback();\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module ui/dropdown/utils\n */\nimport DropdownPanelView from './dropdownpanelview';\nimport DropdownView from './dropdownview';\nimport DropdownButtonView from './button/dropdownbuttonview';\nimport ToolbarView from '../toolbar/toolbarview';\nimport ListView from '../list/listview';\nimport ListItemView from '../list/listitemview';\nimport ListSeparatorView from '../list/listseparatorview';\nimport ButtonView from '../button/buttonview';\nimport SwitchButtonView from '../button/switchbuttonview';\nimport clickOutsideHandler from '../bindings/clickoutsidehandler';\nimport '../../theme/components/dropdown/toolbardropdown.css';\nimport '../../theme/components/dropdown/listdropdown.css';\n/**\n * A helper for creating dropdowns. It creates an instance of a {@link module:ui/dropdown/dropdownview~DropdownView dropdown},\n * with a {@link module:ui/dropdown/button/dropdownbutton~DropdownButton button},\n * {@link module:ui/dropdown/dropdownpanelview~DropdownPanelView panel} and all standard dropdown's behaviors.\n *\n * # Creating dropdowns\n *\n * By default, the default {@link module:ui/dropdown/button/dropdownbuttonview~DropdownButtonView} class is used as\n * definition of the button:\n *\n *\t\tconst dropdown = createDropdown( model );\n *\n *\t\t// Configure dropdown's button properties:\n *\t\tdropdown.buttonView.set( {\n *\t\t\tlabel: 'A dropdown',\n *\t\t\twithText: true\n *\t\t} );\n *\n *\t\tdropdown.render();\n *\n *\t\t// Will render a dropdown labeled \"A dropdown\" with an empty panel.\n *\t\tdocument.body.appendChild( dropdown.element );\n *\n * You can also provide other button views (they need to implement the\n * {@link module:ui/dropdown/button/dropdownbutton~DropdownButton} interface). For instance, you can use\n * {@link module:ui/dropdown/button/splitbuttonview~SplitButtonView} to create a dropdown with a split button.\n *\n *\t\tconst dropdown = createDropdown( model, SplitButtonView );\n *\n *\t\t// Configure dropdown's button properties:\n *\t\tdropdown.buttonView.set( {\n *\t\t\tlabel: 'A dropdown',\n *\t\t\twithText: true\n *\t\t} );\n *\n *\t\tdropdown.buttonView.on( 'execute', () => {\n *\t\t\t// Add the behavior of the \"action part\" of the split button.\n *\t\t\t// Split button consists of the \"action part\" and \"arrow part\".\n *\t\t\t// The arrow opens the dropdown while the action part can have some other behavior.\n * \t\t} );\n *\n *\t\tdropdown.render();\n *\n *\t\t// Will render a dropdown labeled \"A dropdown\" with an empty panel.\n *\t\tdocument.body.appendChild( dropdown.element );\n *\n * # Adding content to the dropdown's panel\n *\n * The content of the panel can be inserted directly into the `dropdown.panelView.element`:\n *\n *\t\tdropdown.panelView.element.textContent = 'Content of the panel';\n *\n * However, most of the time you will want to add there either a {@link module:ui/list/listview~ListView list of options}\n * or a list of buttons (i.e. a {@link module:ui/toolbar/toolbarview~ToolbarView toolbar}).\n * To simplify the task, you can use, respectively, {@link module:ui/dropdown/utils~addListToDropdown} or\n * {@link module:ui/dropdown/utils~addToolbarToDropdown} utils.\n *\n * @param {module:utils/locale~Locale} locale The locale instance.\n * @param {Function} ButtonClass The dropdown button view class. Needs to implement the\n * {@link module:ui/dropdown/button/dropdownbutton~DropdownButton} interface.\n * @returns {module:ui/dropdown/dropdownview~DropdownView} The dropdown view instance.\n */\nexport function createDropdown(locale, ButtonClass = DropdownButtonView) {\n const buttonView = new ButtonClass(locale);\n const panelView = new DropdownPanelView(locale);\n const dropdownView = new DropdownView(locale, buttonView, panelView);\n buttonView.bind('isEnabled').to(dropdownView);\n if (buttonView instanceof DropdownButtonView) {\n buttonView.bind('isOn').to(dropdownView, 'isOpen');\n } else {\n buttonView.arrowView.bind('isOn').to(dropdownView, 'isOpen');\n }\n addDefaultBehavior(dropdownView);\n return dropdownView;\n}\n/**\n * Adds an instance of {@link module:ui/toolbar/toolbarview~ToolbarView} to a dropdown.\n *\n *\t\tconst buttons = [];\n *\n *\t\t// Either create a new ButtonView instance or create existing.\n *\t\tbuttons.push( new ButtonView() );\n *\t\tbuttons.push( editor.ui.componentFactory.get( 'someButton' ) );\n *\n *\t\tconst dropdown = createDropdown( locale );\n *\n *\t\taddToolbarToDropdown( dropdown, buttons );\n *\n *\t\tdropdown.toolbarView.isVertical = true;\n *\n *\t\t// Will render a vertical button dropdown labeled \"A button dropdown\"\n *\t\t// with a button group in the panel containing two buttons.\n *\t\tdropdown.render()\n *\t\tdocument.body.appendChild( dropdown.element );\n *\n * See {@link module:ui/dropdown/utils~createDropdown} and {@link module:ui/toolbar/toolbarview~ToolbarView}.\n *\n * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdown instance to which `ToolbarView` will be added.\n * @param {Iterable.<module:ui/button/buttonview~ButtonView>} buttons\n */\nexport function addToolbarToDropdown(dropdownView, buttons) {\n const locale = dropdownView.locale;\n const t = locale.t;\n const toolbarView = dropdownView.toolbarView = new ToolbarView(locale);\n toolbarView.set('ariaLabel', t('h'));\n dropdownView.extendTemplate({ attributes: { class: ['ck-toolbar-dropdown'] } });\n buttons.map(view => toolbarView.items.add(view));\n dropdownView.panelView.children.add(toolbarView);\n toolbarView.items.delegate('execute').to(dropdownView);\n}\n/**\n * Adds an instance of {@link module:ui/list/listview~ListView} to a dropdown.\n *\n *\t\tconst items = new Collection();\n *\n *\t\titems.add( {\n *\t\t\ttype: 'button',\n *\t\t\tmodel: new Model( {\n *\t\t\t\twithText: true,\n *\t\t\t\tlabel: 'First item',\n *\t\t\t\tlabelStyle: 'color: red'\n *\t\t\t} )\n *\t\t} );\n *\n *\t\titems.add( {\n *\t\t\t type: 'button',\n *\t\t\t model: new Model( {\n *\t\t\t\twithText: true,\n *\t\t\t\tlabel: 'Second item',\n *\t\t\t\tlabelStyle: 'color: green',\n *\t\t\t\tclass: 'foo'\n *\t\t\t} )\n *\t\t} );\n *\n *\t\tconst dropdown = createDropdown( locale );\n *\n *\t\taddListToDropdown( dropdown, items );\n *\n *\t\t// Will render a dropdown with a list in the panel containing two items.\n *\t\tdropdown.render()\n *\t\tdocument.body.appendChild( dropdown.element );\n *\n * The `items` collection passed to this methods controls the presence and attributes of respective\n * {@link module:ui/list/listitemview~ListItemView list items}.\n *\n *\n * See {@link module:ui/dropdown/utils~createDropdown} and {@link module:list/list~List}.\n *\n * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdown instance to which `ListVIew` will be added.\n * @param {Iterable.<module:ui/dropdown/utils~ListDropdownItemDefinition>} items\n * A collection of the list item definitions to populate the list.\n */\nexport function addListToDropdown(dropdownView, items) {\n const locale = dropdownView.locale;\n const listView = dropdownView.listView = new ListView(locale);\n listView.items.bindTo(items).using(({type, model}) => {\n if (type === 'separator') {\n return new ListSeparatorView(locale);\n } else if (type === 'button' || type === 'switchbutton') {\n const listItemView = new ListItemView(locale);\n let buttonView;\n if (type === 'button') {\n buttonView = new ButtonView(locale);\n } else {\n buttonView = new SwitchButtonView(locale);\n }\n // Bind all model properties to the button view.\n buttonView.bind(...Object.keys(model)).to(model);\n buttonView.delegate('execute').to(listItemView);\n listItemView.children.add(buttonView);\n return listItemView;\n }\n });\n dropdownView.panelView.children.add(listView);\n listView.items.delegate('execute').to(dropdownView);\n}\n// Add a set of default behaviors to dropdown view.\n//\n// @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView\nfunction addDefaultBehavior(dropdownView) {\n closeDropdownOnBlur(dropdownView);\n closeDropdownOnExecute(dropdownView);\n focusDropdownContentsOnArrows(dropdownView);\n}\n// Adds a behavior to a dropdownView that closes opened dropdown when user clicks outside the dropdown.\n//\n// @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView\nfunction closeDropdownOnBlur(dropdownView) {\n dropdownView.on('render', () => {\n clickOutsideHandler({\n emitter: dropdownView,\n activator: () => dropdownView.isOpen,\n callback: () => {\n dropdownView.isOpen = false;\n },\n contextElements: [dropdownView.element]\n });\n });\n}\n// Adds a behavior to a dropdownView that closes the dropdown view on \"execute\" event.\n//\n// @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView\nfunction closeDropdownOnExecute(dropdownView) {\n // Close the dropdown when one of the list items has been executed.\n dropdownView.on('execute', evt => {\n // Toggling a switch button view should not close the dropdown.\n if (evt.source instanceof SwitchButtonView) {\n return;\n }\n dropdownView.isOpen = false;\n });\n}\n// Adds a behavior to a dropdownView that focuses the dropdown's panel view contents on keystrokes.\n//\n// @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView\nfunction focusDropdownContentsOnArrows(dropdownView) {\n // If the dropdown panel is already open, the arrow down key should focus the first child of the #panelView.\n dropdownView.keystrokes.set('arrowdown', (data, cancel) => {\n if (dropdownView.isOpen) {\n dropdownView.panelView.focus();\n cancel();\n }\n });\n // If the dropdown panel is already open, the arrow up key should focus the last child of the #panelView.\n dropdownView.keystrokes.set('arrowup', (data, cancel) => {\n if (dropdownView.isOpen) {\n dropdownView.panelView.focusLast();\n cancel();\n }\n });\n} /**\n * A definition of the list item used by the {@link module:ui/dropdown/utils~addListToDropdown}\n * utility.\n *\n * @typedef {Object} module:ui/dropdown/utils~ListDropdownItemDefinition\n *\n * @property {String} type Either `'separator'`, `'button'` or `'switchbutton'`.\n * @property {module:ui/model~Model} [model] Model of the item (when **not** `'separator'`).\n * Its properties fuel the newly created list item (or its children, depending on the `type`).\n */","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><circle cx=\\\"9.5\\\" cy=\\\"4.5\\\" r=\\\"1.5\\\"/><circle cx=\\\"9.5\\\" cy=\\\"10.5\\\" r=\\\"1.5\\\"/><circle cx=\\\"9.5\\\" cy=\\\"16.5\\\" r=\\\"1.5\\\"/></svg>\\n\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module ui/toolbar/toolbarview\n */\n/* globals console */\nimport View from '../view';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\nimport FocusCycler from '../focuscycler';\nimport KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';\nimport ToolbarSeparatorView from './toolbarseparatorview';\nimport getResizeObserver from '@ckeditor/ckeditor5-utils/src/dom/getresizeobserver';\nimport preventDefault from '../bindings/preventdefault.js';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\nimport global from '@ckeditor/ckeditor5-utils/src/dom/global';\nimport {\n createDropdown,\n addToolbarToDropdown\n} from '../dropdown/utils';\nimport { attachLinkToDocumentation } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport verticalDotsIcon from '@ckeditor/ckeditor5-core/theme/icons/three-vertical-dots.svg';\nimport '../../theme/components/toolbar/toolbar.css';\n/**\n * The toolbar view class.\n *\n * @extends module:ui/view~View\n * @implements module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable\n */\nexport default class ToolbarView extends View {\n /**\n\t * Creates an instance of the {@link module:ui/toolbar/toolbarview~ToolbarView} class.\n\t *\n\t * Also see {@link #render}.\n\t *\n\t * @param {module:utils/locale~Locale} locale The localization services instance.\n\t * @param {module:ui/toolbar/toolbarview~ToolbarOptions} [options] Configuration options of the toolbar.\n\t */\n constructor(locale, options) {\n super(locale);\n const bind = this.bindTemplate;\n const t = this.t;\n /**\n\t\t * A reference to the options object passed to the constructor.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/toolbar/toolbarview~ToolbarOptions}\n\t\t */\n this.options = options || {};\n /**\n\t\t * Label used by assistive technologies to describe this toolbar element.\n\t\t *\n\t\t * @default 'Editor toolbar'\n\t\t * @member {String} #ariaLabel\n\t\t */\n this.set('ariaLabel', t('al'));\n /**\n\t\t * A collection of toolbar items (buttons, dropdowns, etc.).\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.items = this.createCollection();\n /**\n\t\t * Tracks information about the DOM focus in the toolbar.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n this.focusTracker = new FocusTracker();\n /**\n\t\t * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}\n\t\t * to handle keyboard navigation in the toolbar.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler}\n\t\t */\n this.keystrokes = new KeystrokeHandler();\n /**\n\t\t * An additional CSS class added to the {@link #element}.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #class\n\t\t */\n this.set('class');\n /**\n\t\t * A (child) view containing {@link #items toolbar items}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/toolbar/toolbarview~ItemsView}\n\t\t */\n this.itemsView = new ItemsView(locale);\n /**\n\t\t * A top–level collection aggregating building blocks of the toolbar.\n\t\t *\n\t\t *\t┌───────────────── ToolbarView ─────────────────┐\n\t\t *\t| ┌──────────────── #children ────────────────┐ |\n\t\t *\t| | ┌──────────── #itemsView ───────────┐ | |\n\t\t *\t| | | [ item1 ] [ item2 ] ... [ itemN ] | | |\n\t\t *\t| | └──────────────────────────────────-┘ | |\n\t\t *\t| └───────────────────────────────────────────┘ |\n\t\t *\t└───────────────────────────────────────────────┘\n\t\t *\n\t\t * By default, it contains the {@link #itemsView} but it can be extended with additional\n\t\t * UI elements when necessary.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.children = this.createCollection();\n this.children.add(this.itemsView);\n /**\n\t\t * A collection of {@link #items} that take part in the focus cycling\n\t\t * (i.e. navigation using the keyboard). Usually, it contains a subset of {@link #items} with\n\t\t * some optional UI elements that also belong to the toolbar and should be focusable\n\t\t * by the user.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.focusables = this.createCollection();\n /**\n\t\t * Controls the orientation of toolbar items. Only available when\n\t\t * {@link module:ui/toolbar/toolbarview~ToolbarOptions#shouldGroupWhenFull dynamic items grouping}\n\t\t * is **disabled**.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isVertical\n\t\t */\n /**\n\t\t * Helps cycling over {@link #focusables focusable items} in the toolbar.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/focuscycler~FocusCycler}\n\t\t */\n this._focusCycler = new FocusCycler({\n focusables: this.focusables,\n focusTracker: this.focusTracker,\n keystrokeHandler: this.keystrokes,\n actions: {\n // Navigate toolbar items backwards using the arrow[left,up] keys.\n focusPrevious: [\n 'arrowleft',\n 'arrowup'\n ],\n // Navigate toolbar items forwards using the arrow[right,down] keys.\n focusNext: [\n 'arrowright',\n 'arrowdown'\n ]\n }\n });\n this.setTemplate({\n tag: 'div',\n attributes: {\n class: [\n 'ck',\n 'ck-toolbar',\n bind.to('class')\n ],\n role: 'toolbar',\n 'aria-label': bind.to('ariaLabel')\n },\n children: this.children,\n on: {\n // https://github.com/ckeditor/ckeditor5-ui/issues/206\n mousedown: preventDefault(this)\n }\n });\n /**\n\t\t * An instance of the active toolbar behavior that shapes its look and functionality.\n\t\t *\n\t\t * See {@link module:ui/toolbar/toolbarview~ToolbarBehavior} to learn more.\n\t\t *\n\t\t * @protected\n\t\t * @readonly\n\t\t * @member {module:ui/toolbar/toolbarview~ToolbarBehavior}\n\t\t */\n this._behavior = this.options.shouldGroupWhenFull ? new DynamicGrouping(this) : new StaticLayout(this);\n }\n /**\n\t * @inheritDoc\n\t */\n render() {\n super.render();\n // Children added before rendering should be known to the #focusTracker.\n for (const item of this.items) {\n this.focusTracker.add(item.element);\n }\n this.items.on('add', (evt, item) => {\n this.focusTracker.add(item.element);\n });\n this.items.on('remove', (evt, item) => {\n this.focusTracker.remove(item.element);\n });\n // Start listening for the keystrokes coming from #element.\n this.keystrokes.listenTo(this.element);\n this._behavior.render(this);\n }\n /**\n\t * @inheritDoc\n\t */\n destroy() {\n this._behavior.destroy();\n return super.destroy();\n }\n /**\n\t * Focuses the first focusable in {@link #focusables}.\n\t */\n focus() {\n this._focusCycler.focusFirst();\n }\n /**\n\t * Focuses the last focusable in {@link #focusables}.\n\t */\n focusLast() {\n this._focusCycler.focusLast();\n }\n /**\n\t * A utility that expands the plain toolbar configuration into\n\t * {@link module:ui/toolbar/toolbarview~ToolbarView#items} using a given component factory.\n\t *\n\t * @param {Array.<String>} config The toolbar items configuration.\n\t * @param {module:ui/componentfactory~ComponentFactory} factory A factory producing toolbar items.\n\t */\n fillFromConfig(config, factory) {\n config.map(name => {\n if (name == '|') {\n this.items.add(new ToolbarSeparatorView());\n } else if (factory.has(name)) {\n this.items.add(factory.create(name));\n } else {\n /**\n\t\t\t\t * There was a problem processing the configuration of the toolbar. The item with the given\n\t\t\t\t * name does not exist so it was omitted when rendering the toolbar.\n\t\t\t\t *\n\t\t\t\t * This warning usually shows up when the {@link module:core/plugin~Plugin} which is supposed\n\t\t\t\t * to provide a toolbar item has not been loaded or there is a typo in the configuration.\n\t\t\t\t *\n\t\t\t\t * Make sure the plugin responsible for this toolbar item is loaded and the toolbar configuration\n\t\t\t\t * is correct, e.g. {@link module:basic-styles/bold~Bold} is loaded for the `'bold'` toolbar item.\n\t\t\t\t *\n\t\t\t\t * You can use the following snippet to retrieve all available toolbar items:\n\t\t\t\t *\n\t\t\t\t *\t\tArray.from( editor.ui.componentFactory.names() );\n\t\t\t\t *\n\t\t\t\t * @error toolbarview-item-unavailable\n\t\t\t\t * @param {String} name The name of the component.\n\t\t\t\t */\n console.warn(attachLinkToDocumentation('toolbarview-item-unavailable: The requested toolbar item is unavailable.'), { name });\n }\n });\n }\n}\n/**\n * An inner block of the {@link module:ui/toolbar/toolbarview~ToolbarView} hosting its\n * {@link module:ui/toolbar/toolbarview~ToolbarView#items}.\n *\n * @private\n * @extends module:ui/view~View\n */\nclass ItemsView extends View {\n /**\n\t * @inheritDoc\n\t */\n constructor(locale) {\n super(locale);\n /**\n\t\t * A collection of items (buttons, dropdowns, etc.).\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.children = this.createCollection();\n this.setTemplate({\n tag: 'div',\n attributes: {\n class: [\n 'ck',\n 'ck-toolbar__items'\n ]\n },\n children: this.children\n });\n }\n}\n/**\n * A toolbar behavior that makes it static and unresponsive to the changes of the environment.\n * At the same time, it also makes it possible to display a toolbar with a vertical layout\n * using the {@link module:ui/toolbar/toolbarview~ToolbarView#isVertical} property.\n *\n * @private\n * @implements module:ui/toolbar/toolbarview~ToolbarBehavior\n */\nclass StaticLayout {\n /**\n\t * Creates an instance of the {@link module:ui/toolbar/toolbarview~StaticLayout} toolbar\n\t * behavior.\n\t *\n\t * @param {module:ui/toolbar/toolbarview~ToolbarView} view An instance of the toolbar that this behavior\n\t * is added to.\n\t */\n constructor(view) {\n const bind = view.bindTemplate;\n // Static toolbar can be vertical when needed.\n view.set('isVertical', false);\n // 1:1 pass–through binding, all ToolbarView#items are visible.\n view.itemsView.children.bindTo(view.items).using(item => item);\n // 1:1 pass–through binding, all ToolbarView#items are focusable.\n view.focusables.bindTo(view.items).using(item => item);\n view.extendTemplate({\n attributes: {\n class: [// When vertical, the toolbar has an additional CSS class.\n bind.if('isVertical', 'ck-toolbar_vertical')]\n }\n });\n }\n /**\n\t * @inheritDoc\n\t */\n render() {\n }\n /**\n\t * @inheritDoc\n\t */\n destroy() {\n }\n}\n/**\n * A toolbar behavior that makes the items respond to changes in the geometry.\n *\n * In a nutshell, it groups {@link module:ui/toolbar/toolbarview~ToolbarView#items}\n * that do not fit visually into a single row of the toolbar (due to limited space).\n * Items that do not fit are aggregated in a dropdown displayed at the end of the toolbar.\n *\n *\t┌──────────────────────────────────────── ToolbarView ──────────────────────────────────────────┐\n *\t| ┌─────────────────────────────────────── #children ─────────────────────────────────────────┐ |\n *\t| | ┌─────── #itemsView ────────┐ ┌──────────────────────┐ ┌── #groupedItemsDropdown ───┐ | |\n *\t| | | #ungroupedItems | | ToolbarSeparatorView | | #groupedItems | | |\n *\t| | └──────────────────────────-┘ └──────────────────────┘ └────────────────────────────┘ | |\n *\t| | \\---------- only when toolbar items overflow --------/ | |\n *\t| └───────────────────────────────────────────────────────────────────────────────────────────┘ |\n *\t└───────────────────────────────────────────────────────────────────────────────────────────────┘\n *\n * @private\n * @implements module:ui/toolbar/toolbarview~ToolbarBehavior\n */\nclass DynamicGrouping {\n /**\n\t * Creates an instance of the {@link module:ui/toolbar/toolbarview~DynamicGrouping} toolbar\n\t * behavior.\n\t *\n\t * @param {module:ui/toolbar/toolbarview~ToolbarView} view An instance of the toolbar that this behavior\n\t * is added to.\n\t */\n constructor(view) {\n /**\n\t\t * A collection of toolbar children.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.viewChildren = view.children;\n /**\n\t\t * A collection of focusable toolbar elements.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.viewFocusables = view.focusables;\n /**\n\t\t * A view containing toolbar items.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/toolbar/toolbarview~ItemsView}\n\t\t */\n this.viewItemsView = view.itemsView;\n /**\n\t\t * Toolbar focus tracker.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n this.viewFocusTracker = view.focusTracker;\n /**\n\t\t * Toolbar locale.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/locale~Locale}\n\t\t */\n this.viewLocale = view.locale;\n /**\n\t\t * Toolbar element.\n\t\t *\n\t\t * @readonly\n\t\t * @member {HTMLElement} #viewElement\n\t\t */\n /**\n\t\t * A subset of toolbar {@link module:ui/toolbar/toolbarview~ToolbarView#items}.\n\t\t * Aggregates items that fit into a single row of the toolbar and were not {@link #groupedItems grouped}\n\t\t * into a {@link #groupedItemsDropdown dropdown}. Items of this collection are displayed in the\n\t\t * {@link module:ui/toolbar/toolbarview~ToolbarView#itemsView}.\n\t\t *\n\t\t * When none of the {@link module:ui/toolbar/toolbarview~ToolbarView#items} were grouped, it\n\t\t * matches the {@link module:ui/toolbar/toolbarview~ToolbarView#items} collection in size and order.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.ungroupedItems = view.createCollection();\n /**\n\t\t * A subset of toolbar {@link module:ui/toolbar/toolbarview~ToolbarView#items}.\n\t\t * A collection of the toolbar items that do not fit into a single row of the toolbar.\n\t\t * Grouped items are displayed in a dedicated {@link #groupedItemsDropdown dropdown}.\n\t\t *\n\t\t * When none of the {@link module:ui/toolbar/toolbarview~ToolbarView#items} were grouped,\n\t\t * this collection is empty.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.groupedItems = view.createCollection();\n /**\n\t\t * The dropdown that aggregates {@link #groupedItems grouped items} that do not fit into a single\n\t\t * row of the toolbar. It is displayed on demand as the last of\n\t\t * {@link module:ui/toolbar/toolbarview~ToolbarView#children toolbar children} and offers another\n\t\t * (nested) toolbar which displays items that would normally overflow.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/dropdown/dropdownview~DropdownView}\n\t\t */\n this.groupedItemsDropdown = this._createGroupedItemsDropdown();\n /**\n\t\t * An instance of the resize observer that helps dynamically determine the geometry of the toolbar\n\t\t * and manage items that do not fit into a single row.\n\t\t *\n\t\t * **Note:** Created in {@link #_enableGroupingOnResize}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/dom/getresizeobserver~ResizeObserver}\n\t\t */\n this.resizeObserver = null;\n /**\n\t\t * A cached value of the horizontal padding style used by {@link #_updateGrouping}\n\t\t * to manage the {@link module:ui/toolbar/toolbarview~ToolbarView#items} that do not fit into\n\t\t * a single toolbar line. This value can be reused between updates because it is unlikely that\n\t\t * the padding will change and re–using `Window.getComputedStyle()` is expensive.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t */\n this.cachedPadding = null;\n // Only those items that were not grouped are visible to the user.\n view.itemsView.children.bindTo(this.ungroupedItems).using(item => item);\n // Make sure all #items visible in the main space of the toolbar are \"focuscycleable\".\n this.ungroupedItems.on('add', this._updateFocusCycleableItems.bind(this));\n this.ungroupedItems.on('remove', this._updateFocusCycleableItems.bind(this));\n // Make sure the #groupedItemsDropdown is also included in cycling when it appears.\n view.children.on('add', this._updateFocusCycleableItems.bind(this));\n view.children.on('remove', this._updateFocusCycleableItems.bind(this));\n // ToolbarView#items is dynamic. When an item is added, it should be automatically\n // represented in either grouped or ungrouped items at the right index.\n // In other words #items == concat( #ungroupedItems, #groupedItems )\n // (in length and order).\n view.items.on('add', (evt, item, index) => {\n if (index > this.ungroupedItems.length) {\n this.groupedItems.add(item, index - this.ungroupedItems.length);\n } else {\n this.ungroupedItems.add(item, index);\n }\n // When a new ungrouped item joins in and lands in #ungroupedItems, there's a chance it causes\n // the toolbar to overflow.\n this._updateGrouping();\n });\n // When an item is removed from ToolbarView#items, it should be automatically\n // removed from either grouped or ungrouped items.\n view.items.on('remove', (evt, item, index) => {\n if (index > this.ungroupedItems.length) {\n this.groupedItems.remove(item);\n } else {\n this.ungroupedItems.remove(item);\n }\n // Whether removed from grouped or ungrouped items, there is a chance\n // some new space is available and we could do some ungrouping.\n this._updateGrouping();\n });\n view.extendTemplate({\n attributes: {\n class: [// To group items dynamically, the toolbar needs a dedicated CSS class.\n 'ck-toolbar_grouping']\n }\n });\n }\n /**\n\t * Enables dynamic items grouping based on the dimensions of the toolbar.\n\t *\n\t * @param {module:ui/toolbar/toolbarview~ToolbarView} view An instance of the toolbar that this behavior\n\t * is added to.\n\t */\n render(view) {\n this.viewElement = view.element;\n this._enableGroupingOnResize();\n }\n /**\n\t * Cleans up the internals used by this behavior.\n\t */\n destroy() {\n // The dropdown may not be in ToolbarView#children at the moment of toolbar destruction\n // so let's make sure it's actually destroyed along with the toolbar.\n this.groupedItemsDropdown.destroy();\n this.resizeObserver.disconnect();\n }\n /**\n\t * When called, it will check if any of the {@link #ungroupedItems} do not fit into a single row of the toolbar,\n\t * and it will move them to the {@link #groupedItems} when it happens.\n\t *\n\t * At the same time, it will also check if there is enough space in the toolbar for the first of the\n\t * {@link #groupedItems} to be returned back to {@link #ungroupedItems} and still fit into a single row\n\t * without the toolbar wrapping.\n\t *\n\t * @protected\n\t */\n _updateGrouping() {\n // Do no grouping–related geometry analysis when the toolbar is detached from visible DOM,\n // for instance before #render(), or after render but without a parent or a parent detached\n // from DOM. DOMRects won't work anyway and there will be tons of warning in the console and\n // nothing else.\n if (!this.viewElement.ownerDocument.body.contains(this.viewElement)) {\n return;\n }\n let wereItemsGrouped;\n // Group #items as long as some wrap to the next row. This will happen, for instance,\n // when the toolbar is getting narrow and there is not enough space to display all items in\n // a single row.\n while (this._areItemsOverflowing) {\n this._groupLastItem();\n wereItemsGrouped = true;\n }\n // If none were grouped now but there were some items already grouped before,\n // then, what the hell, maybe let's see if some of them can be ungrouped. This happens when,\n // for instance, the toolbar is stretching and there's more space in it than before.\n if (!wereItemsGrouped && this.groupedItems.length) {\n // Ungroup items as long as none are overflowing or there are none to ungroup left.\n while (this.groupedItems.length && !this._areItemsOverflowing) {\n this._ungroupFirstItem();\n }\n // If the ungrouping ended up with some item wrapping to the next row,\n // put it back to the group toolbar (\"undo the last ungroup\"). We don't know whether\n // an item will wrap or not until we ungroup it (that's a DOM/CSS thing) so this\n // clean–up is vital for the algorithm.\n if (this._areItemsOverflowing) {\n this._groupLastItem();\n }\n }\n }\n /**\n\t * Returns `true` when {@link module:ui/toolbar/toolbarview~ToolbarView#element} children visually overflow,\n\t * for instance if the toolbar is narrower than its members. Returns `false` otherwise.\n\t *\n\t * @private\n\t * @type {Boolean}\n\t */\n get _areItemsOverflowing() {\n // An empty toolbar cannot overflow.\n if (!this.ungroupedItems.length) {\n return false;\n }\n const element = this.viewElement;\n const uiLanguageDirection = this.viewLocale.uiLanguageDirection;\n const lastChildRect = new Rect(element.lastChild);\n const toolbarRect = new Rect(element);\n if (!this.cachedPadding) {\n const computedStyle = global.window.getComputedStyle(element);\n const paddingProperty = uiLanguageDirection === 'ltr' ? 'paddingRight' : 'paddingLeft';\n // parseInt() is essential because of quirky floating point numbers logic and DOM.\n // If the padding turned out too big because of that, the grouped items dropdown would\n // always look (from the Rect perspective) like it overflows (while it's not).\n this.cachedPadding = Number.parseInt(computedStyle[paddingProperty]);\n }\n if (uiLanguageDirection === 'ltr') {\n return lastChildRect.right > toolbarRect.right - this.cachedPadding;\n } else {\n return lastChildRect.left < toolbarRect.left + this.cachedPadding;\n }\n }\n /**\n\t * Enables the functionality that prevents {@link #ungroupedItems} from overflowing (wrapping to the next row)\n\t * upon resize when there is little space available. Instead, the toolbar items are moved to the\n\t * {@link #groupedItems} collection and displayed in a dropdown at the end of the row (which has its own nested toolbar).\n\t *\n\t * When called, the toolbar will automatically analyze the location of its {@link #ungroupedItems} and \"group\"\n\t * them in the dropdown if necessary. It will also observe the browser window for size changes in\n\t * the future and respond to them by grouping more items or reverting already grouped back, depending\n\t * on the visual space available.\n\t *\n\t * @private\n\t */\n _enableGroupingOnResize() {\n let previousWidth;\n // TODO: Consider debounce.\n this.resizeObserver = getResizeObserver(([entry]) => {\n if (!previousWidth || previousWidth !== entry.contentRect.width) {\n this._updateGrouping();\n previousWidth = entry.contentRect.width;\n }\n });\n this.resizeObserver.observe(this.viewElement);\n this._updateGrouping();\n }\n /**\n\t * When called, it will remove the last item from {@link #ungroupedItems} and move it back\n\t * to the {@link #groupedItems} collection.\n\t *\n\t * The opposite of {@link #_ungroupFirstItem}.\n\t *\n\t * @private\n\t */\n _groupLastItem() {\n if (!this.groupedItems.length) {\n this.viewChildren.add(new ToolbarSeparatorView());\n this.viewChildren.add(this.groupedItemsDropdown);\n this.viewFocusTracker.add(this.groupedItemsDropdown.element);\n }\n this.groupedItems.add(this.ungroupedItems.remove(this.ungroupedItems.last), 0);\n }\n /**\n\t * Moves the very first item belonging to {@link #groupedItems} back\n\t * to the {@link #ungroupedItems} collection.\n\t *\n\t * The opposite of {@link #_groupLastItem}.\n\t *\n\t * @private\n\t */\n _ungroupFirstItem() {\n this.ungroupedItems.add(this.groupedItems.remove(this.groupedItems.first));\n if (!this.groupedItems.length) {\n this.viewChildren.remove(this.groupedItemsDropdown);\n this.viewChildren.remove(this.viewChildren.last);\n this.viewFocusTracker.remove(this.groupedItemsDropdown.element);\n }\n }\n /**\n\t * Creates the {@link #groupedItemsDropdown} that hosts the members of the {@link #groupedItems}\n\t * collection when there is not enough space in the toolbar to display all items in a single row.\n\t *\n\t * @private\n\t * @returns {module:ui/dropdown/dropdownview~DropdownView}\n\t */\n _createGroupedItemsDropdown() {\n const locale = this.viewLocale;\n const t = locale.t;\n const dropdown = createDropdown(locale);\n dropdown.class = 'ck-toolbar__grouped-dropdown';\n // Make sure the dropdown never sticks out to the left/right. It should be under the main toolbar.\n // (https://github.com/ckeditor/ckeditor5/issues/5608)\n dropdown.panelPosition = locale.uiLanguageDirection === 'ltr' ? 'sw' : 'se';\n addToolbarToDropdown(dropdown, []);\n dropdown.buttonView.set({\n label: t('am'),\n tooltip: true,\n icon: verticalDotsIcon\n });\n // 1:1 pass–through binding.\n dropdown.toolbarView.items.bindTo(this.groupedItems).using(item => item);\n return dropdown;\n }\n /**\n\t * Updates the {@link module:ui/toolbar/toolbarview~ToolbarView#focusables focus–cycleable items}\n\t * collection so it represents the up–to–date state of the UI from the perspective of the user.\n\t *\n\t * For instance, the {@link #groupedItemsDropdown} can show up and hide but when it is visible,\n\t * it must be subject to focus cycling in the toolbar.\n\t *\n\t * See the {@link module:ui/toolbar/toolbarview~ToolbarView#focusables collection} documentation\n\t * to learn more about the purpose of this method.\n\t *\n\t * @private\n\t */\n _updateFocusCycleableItems() {\n this.viewFocusables.clear();\n this.ungroupedItems.map(item => {\n this.viewFocusables.add(item);\n });\n if (this.groupedItems.length) {\n this.viewFocusables.add(this.groupedItemsDropdown);\n }\n }\n} /**\n * Options passed to the {@link module:ui/toolbar/toolbarview~ToolbarView#constructor} of the toolbar.\n *\n * @interface module:ui/toolbar/toolbarview~ToolbarOptions\n */\n /**\n * When set to `true`, the toolbar will automatically group {@link module:ui/toolbar/toolbarview~ToolbarView#items} that\n * would normally wrap to the next line when there is not enough space to display them in a single row, for\n * instance, if the parent container of the toolbar is narrow.\n *\n * @member {Boolean} module:ui/toolbar/toolbarview~ToolbarOptions#shouldGroupWhenFull\n */\n /**\n * A class interface defining the behavior of the {@link module:ui/toolbar/toolbarview~ToolbarView}.\n *\n * Toolbar behaviors extend its look and functionality and have an impact on the\n * {@link module:ui/toolbar/toolbarview~ToolbarView#element} template or\n * {@link module:ui/toolbar/toolbarview~ToolbarView#render rendering}. They can be enabled\n * conditionally, e.g. depending on the configuration of the toolbar.\n *\n * @private\n * @interface module:ui/toolbar/toolbarview~ToolbarBehavior\n */\n /**\n * Creates a new toolbar behavior instance.\n *\n * The instance is created in the {@link module:ui/toolbar/toolbarview~ToolbarView#constructor} of the toolbar.\n * This is the right place to extend the {@link module:ui/toolbar/toolbarview~ToolbarView#template} of\n * the toolbar, define extra toolbar properties, etc.\n *\n * @method #constructor\n * @param {module:ui/toolbar/toolbarview~ToolbarView} view An instance of the toolbar that this behavior is added to.\n */\n /**\n * A method called after the toolbar has been {@link module:ui/toolbar/toolbarview~ToolbarView#render rendered}.\n * It can be used to, for example, customize the behavior of the toolbar when its {@link module:ui/toolbar/toolbarview~ToolbarView#element}\n * is available.\n *\n * @readonly\n * @member {Function} #render\n * @param {module:ui/toolbar/toolbarview~ToolbarView} view An instance of the toolbar being rendered.\n */\n /**\n * A method called after the toolbar has been {@link module:ui/toolbar/toolbarview~ToolbarView#destroy destroyed}.\n * It allows cleaning up after the toolbar behavior, for instance, this is the right place to detach\n * event listeners, free up references, etc.\n *\n * @readonly\n * @member {Function} #destroy\n */","/**\n * @license Copyright (c) 2003-2019, 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 ui/bindings/preventdefault\n */\n\n/**\n * A helper which executes a native `Event.preventDefault()` if the target of an event equals the\n * {@link module:ui/view~View#element element of the view}. It shortens the definition of a\n * {@link module:ui/view~View#template template}.\n *\n *\t\t// In a class extending View.\n *\t\timport preventDefault from '@ckeditor/ckeditor5-ui/src/bindings/preventdefault';\n *\n *\t\t// ...\n *\n *\t\tthis.setTemplate( {\n *\t\t\ttag: 'div',\n *\n *\t\t\ton: {\n *\t\t\t\t// Prevent the default mousedown action on this view.\n *\t\t\t\tmousedown: preventDefault( this )\n *\t\t\t}\n *\t\t} );\n *\n * @param {module:ui/view~View} view View instance that defines the template.\n * @returns {module:ui/template~TemplateToBinding}\n */\nexport default function preventDefault( view ) {\n\treturn view.bindTemplate.to( evt => {\n\t\tif ( evt.target === view.element ) {\n\t\t\tevt.preventDefault();\n\t\t}\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 editor-decoupled/decouplededitoruiview\n */\n\nimport EditorUIView from '@ckeditor/ckeditor5-ui/src/editorui/editoruiview';\nimport InlineEditableUIView from '@ckeditor/ckeditor5-ui/src/editableui/inline/inlineeditableuiview';\nimport ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';\n\n/**\n * The decoupled editor UI view. It is a virtual view providing an inline\n * {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#editable} and a\n * {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#toolbar}, but without any\n * specific arrangement of the components in the DOM.\n *\n * See {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`}\n * to learn more about this view.\n *\n * @extends module:ui/editorui/editoruiview~EditorUIView\n */\nexport default class DecoupledEditorUIView extends EditorUIView {\n\t/**\n\t * Creates an instance of the decoupled editor UI view.\n\t *\n\t * @param {module:utils/locale~Locale} locale The {@link module:core/editor/editor~Editor#locale} instance.\n\t * @param {module:engine/view/view~View} editingView The editing view instance this view is related to.\n\t * @param {HTMLElement} [editableElement] The editable element. If not specified, it will be automatically created by\n\t * {@link module:ui/editableui/editableuiview~EditableUIView}. Otherwise, the given element will be used.\n\t */\n\tconstructor( locale, editingView, editableElement ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * The main toolbar of the decoupled editor UI.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/toolbar/toolbarview~ToolbarView}\n\t\t */\n\t\tthis.toolbar = new ToolbarView( locale, {\n\t\t\tshouldGroupWhenFull: true\n\t\t} );\n\n\t\t/**\n\t\t * The editable of the decoupled editor UI.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/editableui/inline/inlineeditableuiview~InlineEditableUIView}\n\t\t */\n\t\tthis.editable = new InlineEditableUIView( locale, editingView, editableElement );\n\n\t\t// This toolbar may be placed anywhere in the page so things like font size need to be reset in it.\n\t\t// Because of the above, make sure the toolbar supports rounded corners.\n\t\t// Also, make sure the toolbar has the proper dir attribute because its ancestor may not have one\n\t\t// and some toolbar item styles depend on this attribute.\n\t\tthis.toolbar.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck-reset_all',\n\t\t\t\t\t'ck-rounded-corners'\n\t\t\t\t],\n\t\t\t\tdir: locale.uiLanguageDirection\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tthis.registerChild( [ this.toolbar, this.editable ] );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 editor-decoupled/decouplededitor\n */\n\nimport Editor from '@ckeditor/ckeditor5-core/src/editor/editor';\nimport DataApiMixin from '@ckeditor/ckeditor5-core/src/editor/utils/dataapimixin';\nimport HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';\nimport DecoupledEditorUI from './decouplededitorui';\nimport DecoupledEditorUIView from './decouplededitoruiview';\nimport getDataFromElement from '@ckeditor/ckeditor5-utils/src/dom/getdatafromelement';\nimport setDataInElement from '@ckeditor/ckeditor5-utils/src/dom/setdatainelement';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport { isElement } from 'lodash-es';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport secureSourceElement from '@ckeditor/ckeditor5-core/src/editor/utils/securesourceelement';\n\n/**\n * The {@glink builds/guides/overview#document-editor decoupled editor} implementation.\n * It provides an inline editable and a toolbar. However, unlike other editors,\n * it does not render these components anywhere in the DOM unless configured.\n *\n * This type of an editor is dedicated to integrations which require a customized UI with an open\n * structure, allowing developers to specify the exact location of the interface.\n *\n * See the document editor {@glink examples/builds/document-editor demo} to learn about possible use cases\n * for the decoupled editor.\n *\n * In order to create a decoupled editor instance, use the static\n * {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`} method.\n *\n * # Decoupled editor and document editor build\n *\n * The decoupled editor can be used directly from source (if you installed the\n * [`@ckeditor/ckeditor5-editor-decoupled`](https://www.npmjs.com/package/@ckeditor/ckeditor5-editor-decoupled) package)\n * but it is also available in the {@glink builds/guides/overview#document-editor document editor build}.\n *\n * {@glink builds/guides/overview Builds} are ready-to-use editors with plugins bundled in. When using the editor from\n * source you need to take care of loading all plugins by yourself\n * (through the {@link module:core/editor/editorconfig~EditorConfig#plugins `config.plugins`} option).\n * Using the editor from source gives much better flexibility and allows for easier customization.\n *\n * Read more about initializing the editor from source or as a build in\n * {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`}.\n *\n * @mixes module:core/editor/utils/dataapimixin~DataApiMixin\n * @implements module:core/editor/editorwithui~EditorWithUI\n * @extends module:core/editor/editor~Editor\n */\nexport default class DecoupledEditor extends Editor {\n\t/**\n\t * Creates an instance of the decoupled editor.\n\t *\n\t * **Note:** Do not use the constructor to create editor instances. Use the static\n\t * {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`} method instead.\n\t *\n\t * @protected\n\t * @param {HTMLElement|String} sourceElementOrData The DOM element that will be the source for the created editor\n\t * (on which the editor will be initialized) or initial data for the editor. For more information see\n\t * {@link module:editor-balloon/ballooneditor~BalloonEditor.create `BalloonEditor.create()`}.\n\t * @param {module:core/editor/editorconfig~EditorConfig} config The editor configuration.\n\t */\n\tconstructor( sourceElementOrData, config ) {\n\t\tsuper( config );\n\n\t\tif ( isElement( sourceElementOrData ) ) {\n\t\t\tthis.sourceElement = sourceElementOrData;\n\t\t\tsecureSourceElement( this );\n\t\t}\n\n\t\tthis.data.processor = new HtmlDataProcessor();\n\n\t\tthis.model.document.createRoot();\n\n\t\tconst view = new DecoupledEditorUIView( this.locale, this.editing.view, this.sourceElement );\n\t\tthis.ui = new DecoupledEditorUI( this, view );\n\t}\n\n\t/**\n\t * Destroys the editor instance, releasing all resources used by it.\n\t *\n\t * **Note**: The decoupled editor does not remove the toolbar and editable when destroyed. You can\n\t * do that yourself in the destruction chain:\n\t *\n\t *\t\teditor.destroy()\n\t *\t\t\t.then( () => {\n\t *\t\t\t\t// Remove the toolbar from DOM.\n\t *\t\t\t\teditor.ui.view.toolbar.element.remove();\n\t *\n\t *\t\t\t\t// Remove the editable from DOM.\n\t *\t\t\t\teditor.ui.view.editable.element.remove();\n\t *\n\t *\t\t\t\tconsole.log( 'Editor was destroyed' );\n\t *\t\t\t} );\n\t *\n\t * @returns {Promise}\n\t */\n\tdestroy() {\n\t\t// Cache the data, then destroy.\n\t\t// It's safe to assume that the model->view conversion will not work after super.destroy().\n\t\tconst data = this.getData();\n\n\t\tthis.ui.destroy();\n\n\t\treturn super.destroy()\n\t\t\t.then( () => {\n\t\t\t\tif ( this.sourceElement ) {\n\t\t\t\t\tsetDataInElement( this.sourceElement, data );\n\t\t\t\t}\n\t\t\t} );\n\t}\n\n\t/**\n\t * Creates a new decoupled editor instance.\n\t *\n\t * Remember that `DecoupledEditor` does not append the toolbar element to your web page so you have to do it manually after the editor\n\t * has been initialized.\n\t *\n\t * There are two ways how the editor can be initialized.\n\t *\n\t * # Using an existing DOM element (and loading data from it)\n\t *\n\t * You can initialize the editor using an existing DOM element:\n\t *\n\t *\t\tDecoupledEditor\n\t *\t\t\t.create( document.querySelector( '#editor' ) )\n\t *\t\t\t.then( editor => {\n\t *\t\t\t\tconsole.log( 'Editor was initialized', editor );\n\t *\n\t *\t\t\t\t// Append the toolbar to the <body> element.\n\t *\t\t\t\tdocument.body.appendChild( editor.ui.view.toolbar.element );\n\t *\t\t\t} )\n\t *\t\t\t.catch( err => {\n\t *\t\t\t\tconsole.error( err.stack );\n\t *\t\t\t} );\n\t *\n\t * The element's content will be used as the editor data and the element will become the editable element.\n\t *\n\t * # Creating a detached editor\n\t *\n\t * Alternatively, you can initialize the editor by passing the initial data directly as a string.\n\t * In this case, you will have to manually append both the toolbar element and the editable element to your web page.\n\t *\n\t *\t\tDecoupledEditor\n\t *\t\t\t.create( '<p>Hello world!</p>' )\n\t *\t\t\t.then( editor => {\n\t *\t\t\t\tconsole.log( 'Editor was initialized', editor );\n\t *\n\t *\t\t\t\t// Append the toolbar to the <body> element.\n\t *\t\t\t\tdocument.body.appendChild( editor.ui.view.toolbar.element );\n\t *\n\t *\t\t\t\t// Initial data was provided so the editor UI element needs to be added manually to the DOM.\n\t *\t\t\t\tdocument.body.appendChild( editor.ui.getEditableElement() );\n\t *\t\t\t} )\n\t *\t\t\t.catch( err => {\n\t *\t\t\t\tconsole.error( err.stack );\n\t *\t\t\t} );\n\t *\n\t * This lets you dynamically append the editor to your web page whenever it is convenient for you. You may use this method if your\n\t * web page content is generated on the client side and the DOM structure is not ready at the moment when you initialize the editor.\n\t *\n\t * # Using an existing DOM element (and data provided in `config.initialData`)\n\t *\n\t * You can also mix these two ways by providing a DOM element to be used and passing the initial data through the configuration:\n\t *\n\t *\t\tDecoupledEditor\n\t *\t\t\t.create( document.querySelector( '#editor' ), {\n\t *\t\t\t\tinitialData: '<h2>Initial data</h2><p>Foo bar.</p>'\n\t *\t\t\t} )\n\t *\t\t\t.then( editor => {\n\t *\t\t\t\tconsole.log( 'Editor was initialized', editor );\n\t *\n\t *\t\t\t\t// Append the toolbar to the <body> element.\n\t *\t\t\t\tdocument.body.appendChild( editor.ui.view.toolbar.element );\n\t *\t\t\t} )\n\t *\t\t\t.catch( err => {\n\t *\t\t\t\tconsole.error( err.stack );\n\t *\t\t\t} );\n\t *\n\t * This method can be used to initialize the editor on an existing element with the specified content in case if your integration\n\t * makes it difficult to set the content of the source element.\n\t *\n\t * Note that an error will be thrown if you pass the initial data both as the first parameter and also in the configuration.\n\t *\n\t * # Configuring the editor\n\t *\n\t * See the {@link module:core/editor/editorconfig~EditorConfig editor configuration documentation} to learn more about\n\t * customizing plugins, toolbar and more.\n\t *\n\t * # Using the editor from source\n\t *\n\t * The code samples listed in the previous sections of this documentation assume that you are using an\n\t * {@glink builds/guides/overview editor build} (for example – `@ckeditor/ckeditor5-build-decoupled`).\n\t *\n\t * If you want to use the decoupled editor from source (`@ckeditor/ckeditor5-editor-decoupled/src/decouplededitor`),\n\t * you need to define the list of\n\t * {@link module:core/editor/editorconfig~EditorConfig#plugins plugins to be initialized} and\n\t * {@link module:core/editor/editorconfig~EditorConfig#toolbar toolbar items}. Read more about using the editor from\n\t * source in the {@glink builds/guides/integration/advanced-setup \"Advanced setup\" guide}.\n\t *\n\t * @param {HTMLElement|String} sourceElementOrData The DOM element that will be the source for the created editor\n\t * or the editor's initial data.\n\t *\n\t * If a DOM element is passed, its content will be automatically loaded to the editor upon initialization.\n\t * Moreover, the editor data will be set back to the original element once the editor is destroyed.\n\t *\n\t * If the initial data is passed, a detached editor will be created. In this case you need to insert it into the DOM manually.\n\t * It is available via\n\t * {@link module:editor-decoupled/decouplededitorui~DecoupledEditorUI#getEditableElement `editor.ui.getEditableElement()`}.\n\t *\n\t * @param {module:core/editor/editorconfig~EditorConfig} [config] The editor configuration.\n\t * @returns {Promise} A promise resolved once the editor is ready. The promise resolves with the created editor instance.\n\t */\n\tstatic create( sourceElementOrData, config = {} ) {\n\t\treturn new Promise( resolve => {\n\t\t\tconst isHTMLElement = isElement( sourceElementOrData );\n\n\t\t\tif ( isHTMLElement && sourceElementOrData.tagName === 'TEXTAREA' ) {\n\t\t\t\t// Documented in core/editor/editor.js\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'editor-wrong-element: This type of editor cannot be initialized inside <textarea> element.', null );\n\t\t\t}\n\n\t\t\tconst editor = new this( sourceElementOrData, config );\n\n\t\t\tresolve(\n\t\t\t\teditor.initPlugins()\n\t\t\t\t\t.then( () => {\n\t\t\t\t\t\teditor.ui.init();\n\t\t\t\t\t} )\n\t\t\t\t\t.then( () => {\n\t\t\t\t\t\tif ( !isHTMLElement && config.initialData ) {\n\t\t\t\t\t\t\t// Documented in core/editor/editorconfig.jdoc.\n\t\t\t\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t\t\t\t'editor-create-initial-data: ' +\n\t\t\t\t\t\t\t\t'The config.initialData option cannot be used together with initial data passed in Editor.create().',\n\t\t\t\t\t\t\t\tnull\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst initialData = config.initialData || getInitialData( sourceElementOrData );\n\n\t\t\t\t\t\treturn editor.data.init( initialData );\n\t\t\t\t\t} )\n\t\t\t\t\t.then( () => editor.fire( 'ready' ) )\n\t\t\t\t\t.then( () => editor )\n\t\t\t);\n\t\t} );\n\t}\n}\n\nmix( DecoupledEditor, DataApiMixin );\n\nfunction getInitialData( sourceElementOrData ) {\n\treturn isElement( sourceElementOrData ) ? getDataFromElement( sourceElementOrData ) : sourceElementOrData;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * @module core/editor/utils/securesourceelement\n */\n\n/**\n * Marks the source element on which the editor was initialized. This prevents other editor instances from using this element.\n *\n * Running multiple editor instances on the same source element causes various issues and it is\n * crucial this helper is called as soon as the source element is known to prevent collisions.\n *\n * @param {module:core/editor/editor~Editor} editor Editor instance.\n */\nexport default function secureSourceElement( editor ) {\n\tconst sourceElement = editor.sourceElement;\n\n\t// If the editor was initialized without specifying an element, we don't need to secure anything.\n\tif ( !sourceElement ) {\n\t\treturn;\n\t}\n\n\tif ( sourceElement.ckeditorInstance ) {\n\t\t/**\n\t\t * A DOM element used to create the editor (e.g.\n\t\t * {@link module:editor-inline/inlineeditor~InlineEditor.create `InlineEditor.create()`})\n\t\t * has already been used to create another editor instance. Make sure each editor is\n\t\t * created with an unique DOM element.\n\t\t *\n\t\t * @error editor-source-element-already-used\n\t\t * @param {HTMLElement} element DOM element that caused the collision.\n\t\t */\n\t\tthrow new CKEditorError(\n\t\t\t'editor-source-element-already-used: ' +\n\t\t\t'The DOM element cannot be used to create multiple editor instances.',\n\t\t\teditor\n\t\t);\n\t}\n\n\tsourceElement.ckeditorInstance = editor;\n\n\teditor.once( 'destroy', () => {\n\t\tdelete sourceElement.ckeditorInstance;\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/setdatainelement\n */\n\n/* globals HTMLTextAreaElement */\n\n/**\n * Sets data in a given element.\n *\n * @param {HTMLElement} el The element in which the data will be set.\n * @param {String} data The data string.\n */\nexport default function setDataInElement( el, data ) {\n\tif ( el instanceof HTMLTextAreaElement ) {\n\t\tel.value = data;\n\t}\n\n\tel.innerHTML = data;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* globals HTMLTextAreaElement */\n\n/**\n * @module utils/dom/getdatafromelement\n */\n\n/**\n * Gets data from a given source element.\n *\n * @param {HTMLElement} el The element from which the data will be retrieved.\n * @returns {String} The data string.\n */\nexport default function getDataFromElement( el ) {\n\tif ( el instanceof HTMLTextAreaElement ) {\n\t\treturn el.value;\n\t}\n\n\treturn el.innerHTML;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 core/plugin\n */\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * The base class for CKEditor plugin classes.\n *\n * @implements module:core/plugin~PluginInterface\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\t/**\n\t\t * The editor instance.\n\t\t *\n\t\t * Note that most editors implement the {@link module:core/editor/editorwithui~EditorWithUI} interface in addition\n\t\t * to the base {@link module:core/editor/editor~Editor} interface. However, editors with an external UI\n\t\t * (i.e. Bootstrap-based) or a headless editor may not implement the {@link module:core/editor/editorwithui~EditorWithUI}\n\t\t * interface.\n\t\t *\n\t\t * Because of above, to make plugins more universal, it is recommended to split features into:\n\t\t * - The \"editing\" part that only uses the {@link module:core/editor/editor~Editor} interface.\n\t\t * - The \"UI\" part that uses both the {@link module:core/editor/editor~Editor} interface and\n\t\t * the {@link module:core/editor/editorwithui~EditorWithUI} interface.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/editor/editor~Editor} #editor\n\t\t */\n\t\tthis.editor = editor;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tthis.stopListening();\n\t}\n}\n\nmix( Plugin, ObservableMixin );\n\n/**\n * The base interface for CKEditor plugins.\n *\n * In its minimal form a plugin can be a simple function that accepts {@link module:core/editor/editor~Editor the editor}\n * as a parameter:\n *\n *\t\t// A simple plugin that enables a data processor.\n *\t\tfunction MyPlugin( editor ) {\n *\t\t\teditor.data.processor = new MyDataProcessor();\n *\t\t}\n *\n * In most cases however, you will want to inherit from the {@link module:core/plugin~Plugin} class which implements the\n * {@link module:utils/observablemixin~ObservableMixin} and is, therefore, more convenient:\n *\n *\t\tclass MyPlugin extends Plugin {\n *\t\t\tinit() {\n *\t\t\t\t// `listenTo()` and `editor` are available thanks to `Plugin`.\n *\t\t\t\t// By using `listenTo()` you will ensure that the listener is removed when\n *\t\t\t\t// the plugin is destroyed.\n *\t\t\t\tthis.listenTo( this.editor.data, 'ready', () => {\n *\t\t\t\t\t// Do something when the data is ready.\n *\t\t\t\t} );\n *\t\t\t}\n *\t\t}\n *\n * The plugin can also implement methods (e.g. {@link module:core/plugin~PluginInterface#init `init()`} or\n * {@link module:core/plugin~PluginInterface#destroy `destroy()`}) which, when present, will be used to properly\n * initialize and destroy the plugin.\n *\n * **Note:** When defined as a plain function, the plugin acts as a constructor and will be\n * called in parallel with other plugins' {@link module:core/plugin~PluginInterface#constructor constructors}.\n * This means the code of that plugin will be executed **before** {@link module:core/plugin~PluginInterface#init `init()`} and\n * {@link module:core/plugin~PluginInterface#afterInit `afterInit()`} methods of other plugins and, for instance,\n * you cannot use it to extend other plugins' {@glink framework/guides/architecture/editing-engine#schema schema}\n * rules as they are defined later on during the `init()` stage.\n *\n * @interface PluginInterface\n */\n\n/**\n * Creates a new plugin instance. This is the first step of the plugin initialization.\n * See also {@link #init} and {@link #afterInit}.\n *\n * A plugin is always instantiated after its {@link module:core/plugin~PluginInterface.requires dependencies} and the\n * {@link #init} and {@link #afterInit} methods are called in the same order.\n *\n * Usually, you will want to put your plugin's initialization code in the {@link #init} method.\n * The constructor can be understood as \"before init\" and used in special cases, just like\n * {@link #afterInit} serves the special \"after init\" scenarios (e.g.the code which depends on other\n * plugins, but which does not {@link module:core/plugin~PluginInterface.requires explicitly require} them).\n *\n * @method #constructor\n * @param {module:core/editor/editor~Editor} editor\n */\n\n/**\n * An array of plugins required by this plugin.\n *\n * To keep the plugin class definition tight it is recommended to define this property as a static getter:\n *\n *\t\timport Image from './image.js';\n *\n *\t\texport default class ImageCaption {\n *\t\t\tstatic get requires() {\n *\t\t\t\treturn [ Image ];\n *\t\t\t}\n *\t\t}\n *\n * @static\n * @readonly\n * @member {Array.<Function>|undefined} module:core/plugin~PluginInterface.requires\n */\n\n/**\n * An optional name of the plugin. If set, the plugin will be available in\n * {@link module:core/plugincollection~PluginCollection#get} by its\n * name and its constructor. If not, then only by its constructor.\n *\n * The name should reflect the constructor name.\n *\n * To keep the plugin class definition tight it is recommended to define this property as a static getter:\n *\n *\t\texport default class ImageCaption {\n *\t\t\tstatic get pluginName() {\n *\t\t\t\treturn 'ImageCaption';\n *\t\t\t}\n *\t\t}\n *\n * Note: The native `Function.name` property could not be used to keep the plugin name because\n * it will be mangled during code minification.\n *\n * Naming a plugin is necessary to enable removing it through the\n * {@link module:core/editor/editorconfig~EditorConfig#removePlugins `config.removePlugins`} option.\n *\n * @static\n * @readonly\n * @member {String|undefined} module:core/plugin~PluginInterface.pluginName\n */\n\n/**\n * The second stage (after plugin {@link #constructor}) of plugin initialization.\n * Unlike the plugin constructor this method can be asynchronous.\n *\n * A plugin's `init()` method is called after its {@link module:core/plugin~PluginInterface.requires dependencies} are initialized,\n * so in the same order as constructors of these plugins.\n *\n * **Note:** This method is optional. A plugin instance does not need to have it defined.\n *\n * @method #init\n * @returns {null|Promise}\n */\n\n/**\n * The third (and last) stage of plugin initialization. See also {@link #constructor} and {@link #init}.\n *\n * **Note:** This method is optional. A plugin instance does not need to have it defined.\n *\n * @method #afterInit\n * @returns {null|Promise}\n */\n\n/**\n * Destroys the plugin.\n *\n * **Note:** This method is optional. A plugin instance does not need to have it defined.\n *\n * @method #destroy\n * @returns {null|Promise}\n */\n\n/**\n * Array of loaded plugins.\n *\n * @typedef {Array.<module:core/plugin~PluginInterface>} module:core/plugin~LoadedPlugins\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 widget/highlightstack\n */\n\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Class used to handle correct order of highlights on elements.\n *\n * When different highlights are applied to same element correct order should be preserved:\n *\n * * highlight with highest priority should be applied,\n * * if two highlights have same priority - sort by CSS class provided in\n * {@link module:engine/conversion/downcasthelpers~HighlightDescriptor}.\n *\n * This way, highlight will be applied with the same rules it is applied on texts.\n */\nexport default class HighlightStack {\n\t/**\n\t * Creates class instance.\n\t */\n\tconstructor() {\n\t\tthis._stack = [];\n\t}\n\n\t/**\n\t * Adds highlight descriptor to the stack.\n\t *\n\t * @fires change:top\n\t * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n\t */\n\tadd( descriptor, writer ) {\n\t\tconst stack = this._stack;\n\n\t\t// Save top descriptor and insert new one. If top is changed - fire event.\n\t\tconst oldTop = stack[ 0 ];\n\t\tthis._insertDescriptor( descriptor );\n\t\tconst newTop = stack[ 0 ];\n\n\t\t// When new object is at the top and stores different information.\n\t\tif ( oldTop !== newTop && !compareDescriptors( oldTop, newTop ) ) {\n\t\t\tthis.fire( 'change:top', {\n\t\t\t\toldDescriptor: oldTop,\n\t\t\t\tnewDescriptor: newTop,\n\t\t\t\twriter\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Removes highlight descriptor from the stack.\n\t *\n\t * @fires change:top\n\t * @param {String} id Id of the descriptor to remove.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n\t */\n\tremove( id, writer ) {\n\t\tconst stack = this._stack;\n\n\t\tconst oldTop = stack[ 0 ];\n\t\tthis._removeDescriptor( id );\n\t\tconst newTop = stack[ 0 ];\n\n\t\t// When new object is at the top and stores different information.\n\t\tif ( oldTop !== newTop && !compareDescriptors( oldTop, newTop ) ) {\n\t\t\tthis.fire( 'change:top', {\n\t\t\t\toldDescriptor: oldTop,\n\t\t\t\tnewDescriptor: newTop,\n\t\t\t\twriter\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Inserts given descriptor in correct place in the stack. It also takes care about updating information when\n\t * descriptor with same id is already present.\n\t *\n\t * @private\n\t * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor\n\t */\n\t_insertDescriptor( descriptor ) {\n\t\tconst stack = this._stack;\n\t\tconst index = stack.findIndex( item => item.id === descriptor.id );\n\n\t\t// Inserting exact same descriptor - do nothing.\n\t\tif ( compareDescriptors( descriptor, stack[ index ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If descriptor with same id but with different information is on the stack - remove it.\n\t\tif ( index > -1 ) {\n\t\t\tstack.splice( index, 1 );\n\t\t}\n\n\t\t// Find correct place to insert descriptor in the stack.\n\t\t// It have different information (for example priority) so it must be re-inserted in correct place.\n\t\tlet i = 0;\n\n\t\twhile ( stack[ i ] && shouldABeBeforeB( stack[ i ], descriptor ) ) {\n\t\t\ti++;\n\t\t}\n\n\t\tstack.splice( i, 0, descriptor );\n\t}\n\n\t/**\n\t * Removes descriptor with given id from the stack.\n\t *\n\t * @private\n\t * @param {String} id Descriptor's id.\n\t */\n\t_removeDescriptor( id ) {\n\t\tconst stack = this._stack;\n\t\tconst index = stack.findIndex( item => item.id === id );\n\n\t\t// If descriptor with same id is on the list - remove it.\n\t\tif ( index > -1 ) {\n\t\t\tstack.splice( index, 1 );\n\t\t}\n\t}\n}\n\nmix( HighlightStack, EmitterMixin );\n\n// Compares two descriptors by checking their priority and class list.\n//\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} a\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} b\n// @returns {Boolean} Returns true if both descriptors are defined and have same priority and classes.\nfunction compareDescriptors( a, b ) {\n\treturn a && b && a.priority == b.priority && classesToString( a.classes ) == classesToString( b.classes );\n}\n\n// Checks whenever first descriptor should be placed in the stack before second one.\n//\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} a\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} b\n// @returns {Boolean}\nfunction shouldABeBeforeB( a, b ) {\n\tif ( a.priority > b.priority ) {\n\t\treturn true;\n\t} else if ( a.priority < b.priority ) {\n\t\treturn false;\n\t}\n\n\t// When priorities are equal and names are different - use classes to compare.\n\treturn classesToString( a.classes ) > classesToString( b.classes );\n}\n\n// Converts CSS classes passed with {@link module:engine/conversion/downcasthelpers~HighlightDescriptor} to\n// sorted string.\n//\n// @param {String|Array<String>} descriptor\n// @returns {String}\nfunction classesToString( classes ) {\n\treturn Array.isArray( classes ) ? classes.sort().join( ',' ) : classes;\n}\n\n/**\n * Fired when top element on {@link module:widget/highlightstack~HighlightStack} has been changed\n *\n * @event change:top\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} [data.newDescriptor] New highlight\n * descriptor. It will be `undefined` when last descriptor is removed from the stack.\n * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} [data.oldDescriptor] Old highlight\n * descriptor. It will be `undefined` when first descriptor is added to the stack.\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that can be used to modify element.\n */\n","export default \"<svg viewBox=\\\"0 0 16 16\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M4 0v1H1v3H0V.5A.5.5 0 0 1 .5 0H4zm8 0h3.5a.5.5 0 0 1 .5.5V4h-1V1h-3V0zM4 16H.5a.5.5 0 0 1-.5-.5V12h1v3h3v1zm8 0v-1h3v-3h1v3.5a.5.5 0 0 1-.5.5H12z\\\"/><path fill-opacity=\\\".256\\\" d=\\\"M1 1h14v14H1z\\\"/><g class=\\\"ck-icon__selected-indicator\\\"><path d=\\\"M7 0h2v1H7V0zM0 7h1v2H0V7zm15 0h1v2h-1V7zm-8 8h2v1H7v-1z\\\"/><path fill-opacity=\\\".254\\\" d=\\\"M1 1h14v14H1z\\\"/></g></svg>\"","/**\n * @license Copyright (c) 2003-2019, 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 widget/utils\n */\n\nimport HighlightStack from './highlightstack';\nimport IconView from '@ckeditor/ckeditor5-ui/src/icon/iconview';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\nimport dragHandleIcon from '../theme/icons/drag-handle.svg';\n\n/**\n * CSS class added to each widget element.\n *\n * @const {String}\n */\nexport const WIDGET_CLASS_NAME = 'ck-widget';\n\n/**\n * CSS class added to currently selected widget element.\n *\n * @const {String}\n */\nexport const WIDGET_SELECTED_CLASS_NAME = 'ck-widget_selected';\n\n/**\n * Returns `true` if given {@link module:engine/view/node~Node} is an {@link module:engine/view/element~Element} and a widget.\n *\n * @param {module:engine/view/node~Node} node\n * @returns {Boolean}\n */\nexport function isWidget( node ) {\n\tif ( !node.is( 'element' ) ) {\n\t\treturn false;\n\t}\n\n\treturn !!node.getCustomProperty( 'widget' );\n}\n\n/* eslint-disable max-len */\n/**\n * Converts the given {@link module:engine/view/element~Element} to a widget in the following way:\n *\n * * sets the `contenteditable` attribute to `\"true\"`,\n * * adds the `ck-widget` CSS class,\n * * adds a custom {@link module:engine/view/element~Element#getFillerOffset `getFillerOffset()`} method returning `null`,\n * * adds a custom property allowing to recognize widget elements by using {@link ~isWidget `isWidget()`},\n * * implements the {@link ~setHighlightHandling view highlight on widgets}.\n *\n * This function needs to be used in conjunction with\n * {@link module:engine/conversion/downcasthelpers~DowncastHelpers downcast conversion helpers}\n * like {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.\n * Moreover, typically you will want to use `toWidget()` only for `editingDowncast`, while keeping the `dataDowncast` clean.\n *\n * For example, in order to convert a `<widget>` model element to `<div class=\"widget\">` in the view, you can define\n * such converters:\n *\n *\t\teditor.conversion.for( 'editingDowncast' )\n *\t\t\t.elementToElement( {\n *\t\t\t\tmodel: 'widget',\n *\t\t\t\tview: ( modelItem, writer ) => {\n *\t\t\t\t\tconst div = writer.createContainerElement( 'div', { class: 'widget' } );\n *\n *\t\t\t\t\treturn toWidget( div, writer, { label: 'some widget' } );\n *\t\t\t\t}\n *\t\t\t} );\n *\n *\t\teditor.conversion.for( 'dataDowncast' )\n *\t\t\t.elementToElement( {\n *\t\t\t\tmodel: 'widget',\n *\t\t\t\tview: ( modelItem, writer ) => {\n *\t\t\t\t\treturn writer.createContainerElement( 'div', { class: 'widget' } );\n *\t\t\t\t}\n *\t\t\t} );\n *\n * See the full source code of the widget (with a nested editable) schema definition and converters in\n * [this sample](https://github.com/ckeditor/ckeditor5-widget/blob/master/tests/manual/widget-with-nestededitable.js).\n *\n * @param {module:engine/view/element~Element} element\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n * @param {Object} [options={}]\n * @param {String|Function} [options.label] Element's label provided to the {@link ~setLabel} function. It can be passed as\n * a plain string or a function returning a string. It represents the widget for assistive technologies (like screen readers).\n * @param {Boolean} [options.hasSelectionHandle=false] If `true`, the widget will have a selection handle added.\n * @returns {module:engine/view/element~Element} Returns the same element.\n */\n/* eslint-enable max-len */\nexport function toWidget( element, writer, options = {} ) {\n\t// The selection on Edge behaves better when the whole editor contents is in a single contenteditable element.\n\t// https://github.com/ckeditor/ckeditor5/issues/1079\n\tif ( !env.isEdge ) {\n\t\twriter.setAttribute( 'contenteditable', 'false', element );\n\t}\n\n\twriter.addClass( WIDGET_CLASS_NAME, element );\n\twriter.setCustomProperty( 'widget', true, element );\n\telement.getFillerOffset = getFillerOffset;\n\n\tif ( options.label ) {\n\t\tsetLabel( element, options.label, writer );\n\t}\n\n\tif ( options.hasSelectionHandle ) {\n\t\taddSelectionHandle( element, writer );\n\t}\n\n\tsetHighlightHandling(\n\t\telement,\n\t\twriter,\n\t\t( element, descriptor, writer ) => writer.addClass( normalizeToArray( descriptor.classes ), element ),\n\t\t( element, descriptor, writer ) => writer.removeClass( normalizeToArray( descriptor.classes ), element )\n\t);\n\n\treturn element;\n\n\t// Normalizes CSS class in descriptor that can be provided in form of an array or a string.\n\tfunction normalizeToArray( classes ) {\n\t\treturn Array.isArray( classes ) ? classes : [ classes ];\n\t}\n}\n\n/**\n * Sets highlight handling methods. Uses {@link module:widget/highlightstack~HighlightStack} to\n * properly determine which highlight descriptor should be used at given time.\n *\n * @param {module:engine/view/element~Element} element\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n * @param {Function} add\n * @param {Function} remove\n */\nexport function setHighlightHandling( element, writer, add, remove ) {\n\tconst stack = new HighlightStack();\n\n\tstack.on( 'change:top', ( evt, data ) => {\n\t\tif ( data.oldDescriptor ) {\n\t\t\tremove( element, data.oldDescriptor, data.writer );\n\t\t}\n\n\t\tif ( data.newDescriptor ) {\n\t\t\tadd( element, data.newDescriptor, data.writer );\n\t\t}\n\t} );\n\n\twriter.setCustomProperty( 'addHighlight', ( element, descriptor, writer ) => stack.add( descriptor, writer ), element );\n\twriter.setCustomProperty( 'removeHighlight', ( element, id, writer ) => stack.remove( id, writer ), element );\n}\n\n/**\n * Sets label for given element.\n * It can be passed as a plain string or a function returning a string. Function will be called each time label is retrieved by\n * {@link ~getLabel `getLabel()`}.\n *\n * @param {module:engine/view/element~Element} element\n * @param {String|Function} labelOrCreator\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n */\nexport function setLabel( element, labelOrCreator, writer ) {\n\twriter.setCustomProperty( 'widgetLabel', labelOrCreator, element );\n}\n\n/**\n * Returns the label of the provided element.\n *\n * @param {module:engine/view/element~Element} element\n * @returns {String}\n */\nexport function getLabel( element ) {\n\tconst labelCreator = element.getCustomProperty( 'widgetLabel' );\n\n\tif ( !labelCreator ) {\n\t\treturn '';\n\t}\n\n\treturn typeof labelCreator == 'function' ? labelCreator() : labelCreator;\n}\n\n/**\n * Adds functionality to the provided {@link module:engine/view/editableelement~EditableElement} to act as a widget's editable:\n *\n * * sets the `contenteditable` attribute to `true` when {@link module:engine/view/editableelement~EditableElement#isReadOnly} is `false`,\n * otherwise sets it to `false`,\n * * adds the `ck-editor__editable` and `ck-editor__nested-editable` CSS classes,\n * * adds the `ck-editor__nested-editable_focused` CSS class when the editable is focused and removes it when it is blurred.\n *\n * Similarly to {@link ~toWidget `toWidget()`} this function should be used in `dataDowncast` only and it is usually\n * used together with {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.\n *\n * For example, in order to convert a `<nested>` model element to `<div class=\"nested\">` in the view, you can define\n * such converters:\n *\n *\t\teditor.conversion.for( 'editingDowncast' )\n *\t\t\t.elementToElement( {\n *\t\t\t\tmodel: 'nested',\n *\t\t\t\tview: ( modelItem, writer ) => {\n *\t\t\t\t\tconst div = writer.createEditableElement( 'div', { class: 'nested' } );\n *\n *\t\t\t\t\treturn toWidgetEditable( nested, writer );\n *\t\t\t\t}\n *\t\t\t} );\n *\n *\t\teditor.conversion.for( 'dataDowncast' )\n *\t\t\t.elementToElement( {\n *\t\t\t\tmodel: 'nested',\n *\t\t\t\tview: ( modelItem, writer ) => {\n *\t\t\t\t\treturn writer.createContainerElement( 'div', { class: 'nested' } );\n *\t\t\t\t}\n *\t\t\t} );\n *\n * See the full source code of the widget (with nested editable) schema definition and converters in\n * [this sample](https://github.com/ckeditor/ckeditor5-widget/blob/master/tests/manual/widget-with-nestededitable.js).\n *\n * @param {module:engine/view/editableelement~EditableElement} editable\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n * @returns {module:engine/view/editableelement~EditableElement} Returns the same element that was provided in the `editable` parameter\n */\nexport function toWidgetEditable( editable, writer ) {\n\twriter.addClass( [ 'ck-editor__editable', 'ck-editor__nested-editable' ], editable );\n\n\t// The selection on Edge behaves better when the whole editor contents is in a single contentedible element.\n\t// https://github.com/ckeditor/ckeditor5/issues/1079\n\tif ( !env.isEdge ) {\n\t\t// Set initial contenteditable value.\n\t\twriter.setAttribute( 'contenteditable', editable.isReadOnly ? 'false' : 'true', editable );\n\n\t\t// Bind the contenteditable property to element#isReadOnly.\n\t\teditable.on( 'change:isReadOnly', ( evt, property, is ) => {\n\t\t\twriter.setAttribute( 'contenteditable', is ? 'false' : 'true', editable );\n\t\t} );\n\t}\n\n\teditable.on( 'change:isFocused', ( evt, property, is ) => {\n\t\tif ( is ) {\n\t\t\twriter.addClass( 'ck-editor__nested-editable_focused', editable );\n\t\t} else {\n\t\t\twriter.removeClass( 'ck-editor__nested-editable_focused', editable );\n\t\t}\n\t} );\n\n\treturn editable;\n}\n\n/**\n * Returns a model position which is optimal (in terms of UX) for inserting a widget block.\n *\n * For instance, if a selection is in the middle of a paragraph, the position before this paragraph\n * will be returned so that it is not split. If the selection is at the end of a paragraph,\n * the position after this paragraph will be returned.\n *\n * Note: If the selection is placed in an empty block, that block will be returned. If that position\n * is then passed to {@link module:engine/model/model~Model#insertContent},\n * the block will be fully replaced by the image.\n *\n * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n * The selection based on which the insertion position should be calculated.\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {module:engine/model/position~Position} The optimal position.\n */\nexport function findOptimalInsertionPosition( selection, model ) {\n\tconst selectedElement = selection.getSelectedElement();\n\n\tif ( selectedElement && model.schema.isBlock( selectedElement ) ) {\n\t\treturn model.createPositionAfter( selectedElement );\n\t}\n\n\tconst firstBlock = selection.getSelectedBlocks().next().value;\n\n\tif ( firstBlock ) {\n\t\t// If inserting into an empty block – return position in that block. It will get\n\t\t// replaced with the image by insertContent(). #42.\n\t\tif ( firstBlock.isEmpty ) {\n\t\t\treturn model.createPositionAt( firstBlock, 0 );\n\t\t}\n\n\t\tconst positionAfter = model.createPositionAfter( firstBlock );\n\n\t\t// If selection is at the end of the block - return position after the block.\n\t\tif ( selection.focus.isTouching( positionAfter ) ) {\n\t\t\treturn positionAfter;\n\t\t}\n\n\t\t// Otherwise return position before the block.\n\t\treturn model.createPositionBefore( firstBlock );\n\t}\n\n\treturn selection.focus;\n}\n\n/**\n * A util to be used in order to map view positions to correct model positions when implementing a widget\n * which renders non-empty view element for an empty model element.\n *\n * For example:\n *\n *\t\t// Model:\n *\t\t<placeholder type=\"name\"></placeholder>\n *\n *\t\t// View:\n *\t\t<span class=\"placeholder\">name</span>\n *\n * In such case, view positions inside `<span>` cannot be correct mapped to the model (because the model element is empty).\n * To handle mapping positions inside `<span class=\"placeholder\">` to the model use this util as follows:\n *\n *\t\teditor.editing.mapper.on(\n *\t\t\t'viewToModelPosition',\n *\t\t\tviewToModelPositionOutsideModelElement( model, viewElement => viewElement.hasClass( 'placeholder' ) )\n *\t\t);\n *\n * The callback will try to map the view offset of selection to an expected model position.\n *\n * 1. When the position is at the end (or in the middle) of the inline widget:\n *\n *\t\t// View:\n *\t\t<p>foo <span class=\"placeholder\">name|</span> bar</p>\n *\n *\t\t// Model:\n *\t\t<paragraph>foo <placeholder type=\"name\"></placeholder>| bar</paragraph>\n *\n * 2. When the position is at the beginning of the inline widget:\n *\n *\t\t// View:\n *\t\t<p>foo <span class=\"placeholder\">|name</span> bar</p>\n *\n *\t\t// Model:\n *\t\t<paragraph>foo |<placeholder type=\"name\"></placeholder> bar</paragraph>\n *\n * @param {module:engine/model/model~Model} model Model instance on which the callback operates.\n * @param {Function} viewElementMatcher Function that is passed a view element and should return `true` if the custom mapping\n * should be applied to the given view element.\n * @return {Function}\n */\nexport function viewToModelPositionOutsideModelElement( model, viewElementMatcher ) {\n\treturn ( evt, data ) => {\n\t\tconst { mapper, viewPosition } = data;\n\n\t\tconst viewParent = mapper.findMappedViewAncestor( viewPosition );\n\n\t\tif ( !viewElementMatcher( viewParent ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelParent = mapper.toModelElement( viewParent );\n\n\t\tdata.modelPosition = model.createPositionAt( modelParent, viewPosition.isAtStart ? 'before' : 'after' );\n\t};\n}\n\n// Default filler offset function applied to all widget elements.\n//\n// @returns {null}\nfunction getFillerOffset() {\n\treturn null;\n}\n\n// Adds a drag handle to the widget.\n//\n// @param {module:engine/view/containerelement~ContainerElement}\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\nfunction addSelectionHandle( widgetElement, writer ) {\n\tconst selectionHandle = writer.createUIElement( 'div', { class: 'ck ck-widget__selection-handle' }, function( domDocument ) {\n\t\tconst domElement = this.toDomElement( domDocument );\n\n\t\t// Use the IconView from the ui library.\n\t\tconst icon = new IconView();\n\t\ticon.set( 'content', dragHandleIcon );\n\n\t\t// Render the icon view right away to append its #element to the selectionHandle DOM element.\n\t\ticon.render();\n\n\t\tdomElement.appendChild( icon.element );\n\n\t\treturn domElement;\n\t} );\n\n\t// Append the selection handle into the widget wrapper.\n\twriter.insert( writer.createPositionAt( widgetElement, 0 ), selectionHandle );\n\twriter.addClass( [ 'ck-widget_with-selection-handle' ], widgetElement );\n}\n","import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport { toWidget } from '@ckeditor/ckeditor5-widget/src/utils';\nimport ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';\n\nexport default class OPMacroTocPlugin extends Plugin {\n\n\tstatic get pluginName() {\n\t\treturn 'OPMacroToc';\n\t}\n\n\tstatic get buttonName() {\n\t\treturn 'insertToc';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst conversion = editor.conversion;\n\n\t\t// Schema.\n\t\tmodel.schema.register( 'op-macro-toc', {\n\t\t\tallowWhere: '$block',\n\t\t\tisBlock: true,\n\t\t isLimit: true\n\t\t});\n\n\t\tconversion.for( 'upcast' )\n\t\t\t.elementToElement( {\n\t\t\t\tview: {\n\t\t\t\t\tname: 'macro',\n\t\t\t\t\tclasses: 'toc'\n\t\t\t\t},\n\t\t\t\tmodel: 'op-macro-toc'\n\t\t\t} );\n\n\n\t\tconversion.for( 'editingDowncast' ).elementToElement( {\n\t\t\tmodel: 'op-macro-toc',\n\t\t\tview: (modelElement, viewWriter) => {\n\t\t\t\treturn toWidget(this.createTocViewElement(viewWriter), viewWriter, { label: this.label } )\n\t\t\t}\n\t } );\n\n\t\tconversion.for('dataDowncast').elementToElement({\n\t\t\tmodel: 'op-macro-toc',\n\t\t\tview: (modelElement, viewWriter) => {\n\t\t\t\treturn this.createTocDataElement(viewWriter)\n\t\t\t}\n\t\t});\n\n\t\teditor.ui.componentFactory.add( OPMacroTocPlugin.buttonName, locale => {\n\t\t\tconst view = new ButtonView( locale );\n\n\t\t\tview.set( {\n\t\t\t\tlabel: this.label,\n\t\t\t\twithText: true,\n\t\t\t} );\n\n\t\t\t// Callback executed once the image is clicked.\n\t\t\tview.on( 'execute', () => {\n\t\t\t\teditor.model.change( writer => {\n\t\t\t\t\tconst tocElement = writer.createElement( 'op-macro-toc', {});\n\n\t\t\t\t\t// Insert the image in the current selection location.\n\t\t\t\t\teditor.model.insertContent( tocElement, editor.model.document.selection );\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\treturn view;\n\t\t} );\n\t}\n\n\tget label() {\n\t\treturn window.I18n.t('js.editor.macro.toc');\n\t}\n\n\tcreateTocViewElement(writer) {\n\t\tconst placeholder = writer.createText( this.label );\n\t\tconst container = writer.createContainerElement( 'div', { class: 'macro -toc' } );\n\n\t\twriter.insert( writer.createPositionAt( container, 0 ), placeholder );\n\t\treturn container;\n\t}\n\n\tcreateTocDataElement(writer) {\n\t\treturn writer.createContainerElement('macro', { class: 'toc' } );\n\t}\n\n}\n","const embeddedTableSymbol = Symbol( 'isOPEmbeddedTable' );\nimport {toWidget, isWidget} from '@ckeditor/ckeditor5-widget/src/utils';\n\nexport function toEmbeddedTableWidget( viewElement, writer, label ) {\n\twriter.setCustomProperty( embeddedTableSymbol, true, viewElement );\n\treturn toWidget( viewElement, writer, { label: 'your label here' } );\n}\n\n\nexport function isEmbeddedTableWidget( viewElement ) {\n\treturn !!viewElement.getCustomProperty( embeddedTableSymbol ) && isWidget( viewElement );\n}\n\n\nexport function isEmbeddedTableWidgetSelected( selection ) {\n\tconst viewElement = selection.getSelectedElement();\n\n\treturn !!( viewElement && isEmbeddedTableWidget( viewElement ) );\n}\n","export function getOP(editor) {\n\treturn _.get(editor.config, '_config.openProject');\n}\n\nexport function getOPService(editor, name) {\n\treturn getPluginContext(editor).services[name];\n}\n\nexport function getPluginContext(editor) {\n\treturn _.get(editor.config, '_config.openProject.pluginContext');\n}\n\nexport function getOPResource(editor) {\n\treturn _.get(editor.config, '_config.openProject.context.resource');\n}\n\nexport function getOPPreviewContext(editor) {\n\treturn _.get(editor.config, '_config.openProject.context.previewContext');\n}\n\nexport function getOPPath(editor, pathName) {\n\treturn getOPService(editor,'pathHelperService');\n\n}\n","import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport {toEmbeddedTableWidget} from './utils';\nimport ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';\nimport {getPluginContext} from '../op-context/op-context';\n\nexport default class EmbeddedTableEditing extends Plugin {\n\n\tstatic get pluginName() {\n\t\treturn 'EmbeddedTableEditing';\n\t}\n\n\tstatic get buttonName() {\n\t\treturn 'insertEmbeddedTable';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst conversion = editor.conversion;\n\t\tconst pluginContext = getPluginContext(editor);\n\n\t\tthis.text = {\n\t\t\tbutton: window.I18n.t('js.editor.macro.embedded_table.button'),\n\t\t\tmacro_text: window.I18n.t('js.editor.macro.embedded_table.text'),\n\t\t};\n\n\t\t// Schema.\n\t\tmodel.schema.register( 'op-macro-embedded-table', {\n\t\t\tallowWhere: '$block',\n\t\t\tallowAttributes: ['opEmbeddedTableQuery'],\n\t\t\tisBlock: true,\n\t\t\tisObject: true\n\t\t});\n\n\t\tconversion.for( 'upcast' )\n\t\t\t.elementToElement( {\n\t\t\t\tview: {\n\t\t\t\t\tname: 'macro',\n\t\t\t\t\tclasses: 'embedded-table',\n\t\t\t\t},\n\t\t\t\tmodel: ( viewElement, modelWriter ) => {\n\t\t\t\t\tconst queryProps = viewElement.getAttribute( 'data-query-props' );\n\t\t\t\t\treturn modelWriter.createElement(\n\t\t\t\t\t\t'op-macro-embedded-table',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\topEmbeddedTableQuery: queryProps ? JSON.parse(queryProps) : {}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\n\n\t\tconversion.for( 'editingDowncast' ).elementToElement( {\n\t\t\tmodel: 'op-macro-embedded-table',\n\t\t\tview: (modelElement, viewWriter) => {\n\t\t\t\treturn toEmbeddedTableWidget(this.createEmbeddedTableView(viewWriter), viewWriter, { label: this.label } )\n\t\t\t}\n\t } );\n\n\t\tconversion.for('dataDowncast').elementToElement({\n\t\t\tmodel: 'op-macro-embedded-table',\n\t\t\tview: (modelElement, viewWriter) => {\n\t\t\t\treturn this.createEmbeddedTableDataElement(modelElement, viewWriter)\n\t\t\t}\n\t\t});\n\n\t\teditor.ui.componentFactory.add( EmbeddedTableEditing.buttonName, locale => {\n\t\t\tconst view = new ButtonView( locale );\n\n\t\t\tview.set( {\n\t\t\t\tlabel: this.text.button,\n\t\t\t\twithText: true\n\t\t\t} );\n\n\t\t\t// Callback executed once the widget is clicked.\n\t\t\tview.on( 'execute', () => pluginContext.runInZone(() => {\n\t\t\t\tconst externalQueryConfiguration = pluginContext.services.externalQueryConfiguration;\n\t\t\t\tconst currentQuery = {}; // Initial query currently empty, we may want to provide context here.\n\n\t\t\t\texternalQueryConfiguration.show(\n\t\t\t\t\tcurrentQuery,\n\t\t\t\t\t(newQuery) => editor.model.change(writer => {\n\t\t\t\t\t\tconst element = writer.createElement( 'op-macro-embedded-table', { opEmbeddedTableQuery: newQuery });\n\n\t\t\t\t\t\t// Insert the widget in the current selection location.\n\t\t\t\t\t\teditor.model.insertContent( element, editor.model.document.selection );\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t} ) );\n\n\t\t\treturn view;\n\t\t} );\n\t}\n\n\tcreateEmbeddedTableView(writer) {\n\t\tconst placeholder = writer.createText( this.text.macro_text );\n\t\tconst container = writer.createContainerElement( 'div', { class: 'macro -embedded-table' } );\n\n\t\twriter.insert( writer.createPositionAt( container, 0 ), placeholder );\n\t\treturn container;\n\n\t\t// The following doesnt work when removing the widget...\n\t\t// let that = this;\n\t\t// return writer.createUIElement( 'div', { class: 'macro -embedded-table' }, function(containerDocument) {\n\t\t// \tconst containerElement = this.toDomElement(containerDocument);\n\t\t// \tcontainerElement.innerHTML = imageIcon + '<div class=\"macro--description\">' + that.text.macro_text + '</div>';\n\n\t\t// \treturn containerElement;\n\t\t// } );\n\t}\n\n\tcreateEmbeddedTableDataElement(modelElement, writer) {\n\t\tconst queryProps = modelElement.getAttribute('opEmbeddedTableQuery') || {};\n\t\tconst element = writer.createContainerElement(\n\t\t\t'macro',\n\t\t\t{\n\t\t\t\t'class': 'embedded-table',\n\t\t\t\t'data-query-props': JSON.stringify(queryProps)\n\t\t\t}\n\t\t);\n\n\t\treturn element;\n\t}\n\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/mouseobserver\n */\n\nimport DomEventObserver from './domeventobserver';\n\n/**\n * Mouse events observer.\n *\n * Note that this observer is not available by default. To make it available it needs to be added to\n * {@link module:engine/view/view~View} by {@link module:engine/view/view~View#addObserver} method.\n *\n * @extends module:engine/view/observer/domeventobserver~DomEventObserver\n */\nexport default class MouseObserver extends DomEventObserver {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tthis.domEventType = 'mousedown';\n\t}\n\n\tonDomEvent( domEvent ) {\n\t\tthis.fire( domEvent.type, domEvent );\n\t}\n}\n\n/**\n * Fired when mouse button is pressed down on one of the editables.\n *\n * Introduced by {@link module:engine/view/observer/mouseobserver~MouseObserver}.\n *\n * Note that this event is not available by default. To make it available {@link module:engine/view/observer/mouseobserver~MouseObserver}\n * needs to be added to {@link module:engine/view/view~View} by a {@link module:engine/view/view~View#addObserver} method.\n *\n * @see module:engine/view/observer/mouseobserver~MouseObserver\n * @event module:engine/view/document~Document#event:mousedown\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 widget/widget\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport MouseObserver from '@ckeditor/ckeditor5-engine/src/view/observer/mouseobserver';\nimport { getLabel, isWidget, WIDGET_SELECTED_CLASS_NAME } from './utils';\nimport { getCode, keyCodes, parseKeystroke } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\nimport '../theme/widget.css';\n\nconst selectAllKeystrokeCode = parseKeystroke( 'Ctrl+A' );\n\n/**\n * The widget plugin. It enables base support for widgets.\n *\n * See {@glink api/widget package page} for more details and documentation.\n *\n * This plugin enables multiple behaviors required by widgets:\n *\n * * The model to view selection converter for the editing pipeline (it handles widget custom selection rendering).\n * If a converted selection wraps around a widget element, that selection is marked as\n * {@link module:engine/view/selection~Selection#isFake fake}. Additionally, the `ck-widget_selected` CSS class\n * is added to indicate that widget has been selected.\n * * The mouse and keyboard events handling on and around widget elements.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Widget extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Widget';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst view = this.editor.editing.view;\n\t\tconst viewDocument = view.document;\n\n\t\t/**\n\t\t * Holds previously selected widgets.\n\t\t *\n\t\t * @private\n\t\t * @type {Set.<module:engine/view/element~Element>}\n\t\t */\n\t\tthis._previouslySelected = new Set();\n\n\t\t// Model to view selection converter.\n\t\t// Converts selection placed over widget element to fake selection\n\t\tthis.editor.editing.downcastDispatcher.on( 'selection', ( evt, data, conversionApi ) => {\n\t\t\t// Remove selected class from previously selected widgets.\n\t\t\tthis._clearPreviouslySelectedWidgets( conversionApi.writer );\n\n\t\t\tconst viewWriter = conversionApi.writer;\n\t\t\tconst viewSelection = viewWriter.document.selection;\n\t\t\tconst selectedElement = viewSelection.getSelectedElement();\n\t\t\tlet lastMarked = null;\n\n\t\t\tfor ( const range of viewSelection.getRanges() ) {\n\t\t\t\tfor ( const value of range ) {\n\t\t\t\t\tconst node = value.item;\n\n\t\t\t\t\t// Do not mark nested widgets in selected one. See: #57.\n\t\t\t\t\tif ( isWidget( node ) && !isChild( node, lastMarked ) ) {\n\t\t\t\t\t\tviewWriter.addClass( WIDGET_SELECTED_CLASS_NAME, node );\n\n\t\t\t\t\t\tthis._previouslySelected.add( node );\n\t\t\t\t\t\tlastMarked = node;\n\n\t\t\t\t\t\t// Check if widget is a single element selected.\n\t\t\t\t\t\tif ( node == selectedElement ) {\n\t\t\t\t\t\t\tviewWriter.setSelection( viewSelection.getRanges(), { fake: true, label: getLabel( selectedElement ) } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\n\t\t// If mouse down is pressed on widget - create selection over whole widget.\n\t\tview.addObserver( MouseObserver );\n\t\tthis.listenTo( viewDocument, 'mousedown', ( ...args ) => this._onMousedown( ...args ) );\n\n\t\t// Handle custom keydown behaviour.\n\t\tthis.listenTo( viewDocument, 'keydown', ( ...args ) => this._onKeydown( ...args ), { priority: 'high' } );\n\n\t\t// Handle custom delete behaviour.\n\t\tthis.listenTo( viewDocument, 'delete', ( evt, data ) => {\n\t\t\tif ( this._handleDelete( data.direction == 'forward' ) ) {\n\t\t\t\tdata.preventDefault();\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\t}\n\n\t/**\n\t * Handles {@link module:engine/view/document~Document#event:mousedown mousedown} events on widget elements.\n\t *\n\t * @private\n\t * @param {module:utils/eventinfo~EventInfo} eventInfo\n\t * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData\n\t */\n\t_onMousedown( eventInfo, domEventData ) {\n\t\tconst editor = this.editor;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\t\tlet element = domEventData.target;\n\n\t\t// Do nothing for single or double click inside nested editable.\n\t\tif ( isInsideNestedEditable( element ) ) {\n\t\t\t// But at least triple click inside nested editable causes broken selection in Safari.\n\t\t\t// For such event, we select the entire nested editable element.\n\t\t\t// See: https://github.com/ckeditor/ckeditor5/issues/1463.\n\t\t\tif ( env.isSafari && domEventData.domEvent.detail >= 3 ) {\n\t\t\t\tconst mapper = editor.editing.mapper;\n\t\t\t\tconst modelElement = mapper.toModelElement( element );\n\n\t\t\t\tthis.editor.model.change( writer => {\n\t\t\t\t\tdomEventData.preventDefault();\n\t\t\t\t\twriter.setSelection( modelElement, 'in' );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// If target is not a widget element - check if one of the ancestors is.\n\t\tif ( !isWidget( element ) ) {\n\t\t\telement = element.findAncestor( isWidget );\n\n\t\t\tif ( !element ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tdomEventData.preventDefault();\n\n\t\t// Focus editor if is not focused already.\n\t\tif ( !viewDocument.isFocused ) {\n\t\t\tview.focus();\n\t\t}\n\n\t\t// Create model selection over widget.\n\t\tconst modelElement = editor.editing.mapper.toModelElement( element );\n\n\t\tthis._setSelectionOverElement( modelElement );\n\t}\n\n\t/**\n\t * Handles {@link module:engine/view/document~Document#event:keydown keydown} events.\n\t *\n\t * @private\n\t * @param {module:utils/eventinfo~EventInfo} eventInfo\n\t * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData\n\t */\n\t_onKeydown( eventInfo, domEventData ) {\n\t\tconst keyCode = domEventData.keyCode;\n\t\tconst isLtrContent = this.editor.locale.contentLanguageDirection === 'ltr';\n\t\tconst isForward = keyCode == keyCodes.arrowdown || keyCode == keyCodes[ isLtrContent ? 'arrowright' : 'arrowleft' ];\n\t\tlet wasHandled = false;\n\n\t\t// Checks if the keys were handled and then prevents the default event behaviour and stops\n\t\t// the propagation.\n\t\tif ( isArrowKeyCode( keyCode ) ) {\n\t\t\twasHandled = this._handleArrowKeys( isForward );\n\t\t} else if ( isSelectAllKeyCode( domEventData ) ) {\n\t\t\twasHandled = this._selectAllNestedEditableContent() || this._selectAllContent();\n\t\t} else if ( keyCode === keyCodes.enter ) {\n\t\t\twasHandled = this._handleEnterKey( domEventData.shiftKey );\n\t\t}\n\n\t\tif ( wasHandled ) {\n\t\t\tdomEventData.preventDefault();\n\t\t\teventInfo.stop();\n\t\t}\n\t}\n\n\t/**\n\t * Handles delete keys: backspace and delete.\n\t *\n\t * @private\n\t * @param {Boolean} isForward Set to true if delete was performed in forward direction.\n\t * @returns {Boolean|undefined} Returns `true` if keys were handled correctly.\n\t */\n\t_handleDelete( isForward ) {\n\t\t// Do nothing when the read only mode is enabled.\n\t\tif ( this.editor.isReadOnly ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelDocument = this.editor.model.document;\n\t\tconst modelSelection = modelDocument.selection;\n\n\t\t// Do nothing on non-collapsed selection.\n\t\tif ( !modelSelection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst objectElement = this._getObjectElementNextToSelection( isForward );\n\n\t\tif ( objectElement ) {\n\t\t\tthis.editor.model.change( writer => {\n\t\t\t\tlet previousNode = modelSelection.anchor.parent;\n\n\t\t\t\t// Remove previous element if empty.\n\t\t\t\twhile ( previousNode.isEmpty ) {\n\t\t\t\t\tconst nodeToRemove = previousNode;\n\t\t\t\t\tpreviousNode = nodeToRemove.parent;\n\n\t\t\t\t\twriter.remove( nodeToRemove );\n\t\t\t\t}\n\n\t\t\t\tthis._setSelectionOverElement( objectElement );\n\t\t\t} );\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * Handles arrow keys.\n\t *\n\t * @private\n\t * @param {Boolean} isForward Set to true if arrow key should be handled in forward direction.\n\t * @returns {Boolean|undefined} Returns `true` if keys were handled correctly.\n\t */\n\t_handleArrowKeys( isForward ) {\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\t\tconst modelDocument = model.document;\n\t\tconst modelSelection = modelDocument.selection;\n\t\tconst objectElement = modelSelection.getSelectedElement();\n\n\t\t// If object element is selected.\n\t\tif ( objectElement && schema.isObject( objectElement ) ) {\n\t\t\tconst position = isForward ? modelSelection.getLastPosition() : modelSelection.getFirstPosition();\n\t\t\tconst newRange = schema.getNearestSelectionRange( position, isForward ? 'forward' : 'backward' );\n\n\t\t\tif ( newRange ) {\n\t\t\t\tmodel.change( writer => {\n\t\t\t\t\twriter.setSelection( newRange );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\t// If selection is next to object element.\n\t\t// Return if not collapsed.\n\t\tif ( !modelSelection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst objectElement2 = this._getObjectElementNextToSelection( isForward );\n\n\t\tif ( !!objectElement2 && schema.isObject( objectElement2 ) ) {\n\t\t\tthis._setSelectionOverElement( objectElement2 );\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * Handles the enter key, giving users and access to positions in the editable directly before\n\t * (<kbd>Shift</kbd>+<kbd>Enter</kbd>) or after (<kbd>Enter</kbd>) the selected widget.\n\t * It improves the UX, mainly when the widget is the first or last child of the root editable\n\t * and there's no other way to type after or before it.\n\t *\n\t * @private\n\t * @param {Boolean} isBackwards Set to true if the new paragraph is to be inserted before\n\t * the selected widget (<kbd>Shift</kbd>+<kbd>Enter</kbd>).\n\t * @returns {Boolean|undefined} Returns `true` if keys were handled correctly.\n\t */\n\t_handleEnterKey( isBackwards ) {\n\t\tconst model = this.editor.model;\n\t\tconst modelSelection = model.document.selection;\n\t\tconst selectedElement = modelSelection.getSelectedElement();\n\n\t\tif ( shouldInsertParagraph( selectedElement, model.schema ) ) {\n\t\t\tmodel.change( writer => {\n\t\t\t\tlet position = writer.createPositionAt( selectedElement, isBackwards ? 'before' : 'after' );\n\t\t\t\tconst paragraph = writer.createElement( 'paragraph' );\n\n\t\t\t\t// Split the parent when inside a block element.\n\t\t\t\t// https://github.com/ckeditor/ckeditor5/issues/1529\n\t\t\t\tif ( model.schema.isBlock( selectedElement.parent ) ) {\n\t\t\t\t\tconst paragraphLimit = model.schema.findAllowedParent( position, paragraph );\n\n\t\t\t\t\tposition = writer.split( position, paragraphLimit ).position;\n\t\t\t\t}\n\n\t\t\t\twriter.insert( paragraph, position );\n\t\t\t\twriter.setSelection( paragraph, 'in' );\n\t\t\t} );\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * Extends the {@link module:engine/model/selection~Selection document's selection} to span the entire\n\t * content of the nested editable if already anchored in one.\n\t *\n\t * See: {@link module:engine/model/schema~Schema#getLimitElement}.\n\t *\n\t * @private\n\t */\n\t_selectAllNestedEditableContent() {\n\t\tconst model = this.editor.model;\n\t\tconst documentSelection = model.document.selection;\n\t\tconst limitElement = model.schema.getLimitElement( documentSelection );\n\n\t\tif ( documentSelection.getFirstRange().root == limitElement ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tmodel.change( writer => {\n\t\t\twriter.setSelection( writer.createRangeIn( limitElement ) );\n\t\t} );\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Handles <kbd>CTRL + A</kbd> when widget is selected.\n\t *\n\t * @private\n\t * @returns {Boolean} Returns true if widget was selected and selecting all was handled by this method.\n\t */\n\t_selectAllContent() {\n\t\tconst model = this.editor.model;\n\t\tconst editing = this.editor.editing;\n\t\tconst view = editing.view;\n\t\tconst viewDocument = view.document;\n\t\tconst viewSelection = viewDocument.selection;\n\n\t\tconst selectedElement = viewSelection.getSelectedElement();\n\n\t\t// Only widget is selected.\n\t\t// https://github.com/ckeditor/ckeditor5-widget/issues/23\n\t\tif ( selectedElement && isWidget( selectedElement ) ) {\n\t\t\tconst widgetParent = editing.mapper.toModelElement( selectedElement.parent );\n\n\t\t\tmodel.change( writer => {\n\t\t\t\twriter.setSelection( writer.createRangeIn( widgetParent ) );\n\t\t\t} );\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Sets {@link module:engine/model/selection~Selection document's selection} over given element.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} element\n\t */\n\t_setSelectionOverElement( element ) {\n\t\tthis.editor.model.change( writer => {\n\t\t\twriter.setSelection( writer.createRangeOn( element ) );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks if {@link module:engine/model/element~Element element} placed next to the current\n\t * {@link module:engine/model/selection~Selection model selection} exists and is marked in\n\t * {@link module:engine/model/schema~Schema schema} as `object`.\n\t *\n\t * @private\n\t * @param {Boolean} forward Direction of checking.\n\t * @returns {module:engine/model/element~Element|null}\n\t */\n\t_getObjectElementNextToSelection( forward ) {\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\t\tconst modelSelection = model.document.selection;\n\n\t\t// Clone current selection to use it as a probe. We must leave default selection as it is so it can return\n\t\t// to its current state after undo.\n\t\tconst probe = model.createSelection( modelSelection );\n\t\tmodel.modifySelection( probe, { direction: forward ? 'forward' : 'backward' } );\n\t\tconst objectElement = forward ? probe.focus.nodeBefore : probe.focus.nodeAfter;\n\n\t\tif ( !!objectElement && schema.isObject( objectElement ) ) {\n\t\t\treturn objectElement;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Removes CSS class from previously selected widgets.\n\t *\n\t * @private\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n\t */\n\t_clearPreviouslySelectedWidgets( writer ) {\n\t\tfor ( const widget of this._previouslySelected ) {\n\t\t\twriter.removeClass( WIDGET_SELECTED_CLASS_NAME, widget );\n\t\t}\n\n\t\tthis._previouslySelected.clear();\n\t}\n}\n\n// Returns 'true' if provided key code represents one of the arrow keys.\n//\n// @param {Number} keyCode\n// @returns {Boolean}\nfunction 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// Returns 'true' if provided (DOM) key event data corresponds with the Ctrl+A keystroke.\n//\n// @param {module:engine/view/observer/keyobserver~KeyEventData} domEventData\n// @returns {Boolean}\nfunction isSelectAllKeyCode( domEventData ) {\n\treturn getCode( domEventData ) == selectAllKeystrokeCode;\n}\n\n// Returns `true` when element is a nested editable or is placed inside one.\n//\n// @param {module:engine/view/element~Element}\n// @returns {Boolean}\nfunction isInsideNestedEditable( element ) {\n\twhile ( element ) {\n\t\tif ( element.is( 'editableElement' ) && !element.is( 'rootElement' ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Click on nested widget should select it.\n\t\tif ( isWidget( element ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\telement = element.parent;\n\t}\n\n\treturn false;\n}\n\n// Checks whether the specified `element` is a child of the `parent` element.\n//\n// @param {module:engine/view/element~Element} element An element to check.\n// @param {module:engine/view/element~Element|null} parent A parent for the element.\n// @returns {Boolean}\nfunction isChild( element, parent ) {\n\tif ( !parent ) {\n\t\treturn false;\n\t}\n\n\treturn Array.from( element.getAncestors() ).includes( parent );\n}\n\n// Checks if enter key should insert paragraph. This should be done only on elements of type object (excluding inline objects).\n//\n// @param {module:engine/model/element~Element} element And element to check.\n// @param {module:engine/model/schema~Schema} schema\nfunction shouldInsertParagraph( element, schema ) {\n\treturn element && schema.isObject( element ) && !schema.isInline( element );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/tounit\n */\n\n/**\n * Returns a helper function, which adds a desired trailing\n * `unit` to the passed value.\n *\n * @param {String} unit An unit like \"px\" or \"em\".\n * @returns {module:utils/dom/tounit~helper}\n */\nexport default function toUnit( unit ) {\n\t/**\n\t * A function, which adds a pre–defined trailing `unit`\n\t * to the passed `value`.\n\t *\n\t * @function helper\n \t * @param {*} value A value to be given the unit.\n \t * @returns {String} A value with the trailing unit.\n\t */\n\treturn value => value + unit;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md.\n */\n\n/**\n * @module ui/panel/balloon/balloonpanelview\n */\n\nimport View from '../../view';\nimport { getOptimalPosition } from '@ckeditor/ckeditor5-utils/src/dom/position';\nimport isRange from '@ckeditor/ckeditor5-utils/src/dom/isrange';\nimport toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit';\nimport global from '@ckeditor/ckeditor5-utils/src/dom/global';\nimport { isElement } from 'lodash-es';\n\nimport '../../../theme/components/panel/balloonpanel.css';\n\nconst toPx = toUnit( 'px' );\nconst defaultLimiterElement = global.document.body;\n\n/**\n * The balloon panel view class.\n *\n * A floating container which can\n * {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#pin pin} to any\n * {@link module:utils/dom/position~Options#target target} in the DOM and remain in that position\n * e.g. when the web page is scrolled.\n *\n * The balloon panel can be used to display contextual, non-blocking UI like forms, toolbars and\n * the like in its {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#content} view\n * collection.\n *\n * There is a number of {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}\n * that the balloon can use, automatically switching from one to another when the viewport space becomes\n * scarce to keep the balloon visible to the user as long as it is possible. The balloon will also\n * accept any custom position set provided by the user compatible with the\n * {@link module:utils/dom/position~Options options}.\n *\n *\t\tconst panel = new BalloonPanelView( locale );\n *\t\tconst childView = new ChildView();\n *\t\tconst positions = BalloonPanelView.defaultPositions;\n *\n *\t\tpanel.render();\n *\n *\t\t// Add a child view to the panel's content collection.\n *\t\tpanel.content.add( childView );\n *\n *\t\t// Start pinning the panel to an element with the \"target\" id DOM.\n *\t\t// The balloon will remain pinned until unpin() is called.\n *\t\tpanel.pin( {\n *\t\t\ttarget: document.querySelector( '#target' ),\n *\t\t\tpositions: [\n *\t\t\t\tpositions.northArrowSouth,\n *\t\t\t\tpositions.southArrowNorth\n *\t\t\t]\n *\t\t} );\n *\n * @extends module:ui/view~View\n */\nexport default class BalloonPanelView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\t/**\n\t\t * The absolute top position of the balloon panel in pixels.\n\t\t *\n\t\t * @observable\n\t\t * @default 0\n\t\t * @member {Number} #top\n\t\t */\n\t\tthis.set( 'top', 0 );\n\n\t\t/**\n\t\t * The absolute left position of the balloon panel in pixels.\n\t\t *\n\t\t * @observable\n\t\t * @default 0\n\t\t * @member {Number} #left\n\t\t */\n\t\tthis.set( 'left', 0 );\n\n\t\t/**\n\t\t * The balloon panel's current position. The position name is reflected in the CSS class set\n\t\t * to the balloon, i.e. `.ck-balloon-panel_arrow_nw` for the \"arrow_nw\" position. The class\n\t\t * controls the minor aspects of the balloon's visual appearance like the placement\n\t\t * of an {@link #withArrow arrow}. To support a new position, an additional CSS must be created.\n\t\t *\n\t\t * Default position names correspond with\n\t\t * {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.\n\t\t *\n\t\t * See the {@link #attachTo} and {@link #pin} methods to learn about custom balloon positions.\n\t\t *\n\t\t * @observable\n\t\t * @default 'arrow_nw'\n\t\t * @member {'arrow_nw'|'arrow_ne'|'arrow_sw'|'arrow_se'} #position\n\t\t */\n\t\tthis.set( 'position', 'arrow_nw' );\n\n\t\t/**\n\t\t * Controls whether the balloon panel is visible or not.\n\t\t *\n\t\t * @observable\n\t\t * @default false\n\t\t * @member {Boolean} #isVisible\n\t\t */\n\t\tthis.set( 'isVisible', false );\n\n\t\t/**\n\t\t * Controls whether the balloon panel has an arrow. The presence of the arrow\n\t\t * is reflected in the `ck-balloon-panel_with-arrow` CSS class.\n\t\t *\n\t\t * @observable\n\t\t * @default true\n\t\t * @member {Boolean} #withArrow\n\t\t */\n\t\tthis.set( 'withArrow', true );\n\n\t\t/**\n\t\t * An additional CSS class added to the {@link #element}.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #class\n\t\t */\n\t\tthis.set( 'class' );\n\n\t\t/**\n\t\t * A callback that starts pinning the panel when {@link #isVisible} gets\n\t\t * `true`. Used by {@link #pin}.\n\t\t *\n\t\t * @private\n\t\t * @member {Function} #_pinWhenIsVisibleCallback\n\t\t */\n\n\t\t/**\n\t\t * A collection of the child views that creates the balloon panel contents.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis.content = this.createCollection();\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-balloon-panel',\n\t\t\t\t\tbind.to( 'position', value => `ck-balloon-panel_${ value }` ),\n\t\t\t\t\tbind.if( 'isVisible', 'ck-balloon-panel_visible' ),\n\t\t\t\t\tbind.if( 'withArrow', 'ck-balloon-panel_with-arrow' ),\n\t\t\t\t\tbind.to( 'class' )\n\t\t\t\t],\n\n\t\t\t\tstyle: {\n\t\t\t\t\ttop: bind.to( 'top', toPx ),\n\t\t\t\t\tleft: bind.to( 'left', toPx )\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tchildren: this.content\n\t\t} );\n\t}\n\n\t/**\n\t * Shows the panel.\n\t *\n\t * See {@link #isVisible}.\n\t */\n\tshow() {\n\t\tthis.isVisible = true;\n\t}\n\n\t/**\n\t * Hides the panel.\n\t *\n\t * See {@link #isVisible}.\n\t */\n\thide() {\n\t\tthis.isVisible = false;\n\t}\n\n\t/**\n\t * Attaches the panel to a specified {@link module:utils/dom/position~Options#target} with a\n\t * smart positioning heuristics that chooses from available positions to make sure the panel\n\t * is visible to the user i.e. within the limits of the viewport.\n\t *\n\t * This method accepts configuration {@link module:utils/dom/position~Options options}\n\t * to set the `target`, optional `limiter` and `positions` the balloon should choose from.\n\t *\n\t *\t\tconst panel = new BalloonPanelView( locale );\n\t *\t\tconst positions = BalloonPanelView.defaultPositions;\n\t *\n\t *\t\tpanel.render();\n\t *\n\t *\t\t// Attach the panel to an element with the \"target\" id DOM.\n\t *\t\tpanel.attachTo( {\n\t *\t\t\ttarget: document.querySelector( '#target' ),\n\t *\t\t\tpositions: [\n\t *\t\t\t\tpositions.northArrowSouth,\n\t *\t\t\t\tpositions.southArrowNorth\n\t *\t\t\t]\n\t *\t\t} );\n\t *\n\t * **Note**: Attaching the panel will also automatically {@link #show} it.\n\t *\n\t * **Note**: An attached panel will not follow its target when the window is scrolled or resized.\n\t * See the {@link #pin} method for a more permanent positioning strategy.\n\t *\n\t * @param {module:utils/dom/position~Options} options Positioning options compatible with\n\t * {@link module:utils/dom/position~getOptimalPosition}. Default `positions` array is\n\t * {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.\n\t */\n\tattachTo( options ) {\n\t\tthis.show();\n\n\t\tconst defaultPositions = BalloonPanelView.defaultPositions;\n\t\tconst positionOptions = Object.assign( {}, {\n\t\t\telement: this.element,\n\t\t\tpositions: [\n\t\t\t\tdefaultPositions.southArrowNorth,\n\t\t\t\tdefaultPositions.southArrowNorthWest,\n\t\t\t\tdefaultPositions.southArrowNorthEast,\n\t\t\t\tdefaultPositions.northArrowSouth,\n\t\t\t\tdefaultPositions.northArrowSouthWest,\n\t\t\t\tdefaultPositions.northArrowSouthEast\n\t\t\t],\n\t\t\tlimiter: defaultLimiterElement,\n\t\t\tfitInViewport: true\n\t\t}, options );\n\n\t\tconst optimalPosition = BalloonPanelView._getOptimalPosition( positionOptions );\n\n\t\t// Usually browsers make some problems with super accurate values like 104.345px\n\t\t// so it is better to use int values.\n\t\tconst left = parseInt( optimalPosition.left );\n\t\tconst top = parseInt( optimalPosition.top );\n\t\tconst position = optimalPosition.name;\n\n\t\tObject.assign( this, { top, left, position } );\n\t}\n\n\t/**\n\t * Works the same way as the {@link #attachTo} method except that the position of the panel is\n\t * continuously updated when:\n\t *\n\t * * any ancestor of the {@link module:utils/dom/position~Options#target}\n\t * or {@link module:utils/dom/position~Options#limiter} is scrolled,\n\t * * the browser window gets resized or scrolled.\n\t *\n\t * Thanks to that, the panel always sticks to the {@link module:utils/dom/position~Options#target}\n\t * and is immune to the changing environment.\n\t *\n\t *\t\tconst panel = new BalloonPanelView( locale );\n\t *\t\tconst positions = BalloonPanelView.defaultPositions;\n\t *\n\t *\t\tpanel.render();\n\t *\n\t *\t\t// Pin the panel to an element with the \"target\" id DOM.\n\t *\t\tpanel.pin( {\n\t *\t\t\ttarget: document.querySelector( '#target' ),\n\t *\t\t\tpositions: [\n\t *\t\t\t\tpositions.northArrowSouth,\n\t *\t\t\t\tpositions.southArrowNorth\n\t *\t\t\t]\n\t *\t\t} );\n\t *\n\t * To leave the pinned state, use the {@link #unpin} method.\n\t *\n\t * **Note**: Pinning the panel will also automatically {@link #show} it.\n\t *\n\t * @param {module:utils/dom/position~Options} options Positioning options compatible with\n\t * {@link module:utils/dom/position~getOptimalPosition}. Default `positions` array is\n\t * {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}.\n\t */\n\tpin( options ) {\n\t\tthis.unpin();\n\n\t\tthis._pinWhenIsVisibleCallback = () => {\n\t\t\tif ( this.isVisible ) {\n\t\t\t\tthis._startPinning( options );\n\t\t\t} else {\n\t\t\t\tthis._stopPinning();\n\t\t\t}\n\t\t};\n\n\t\tthis._startPinning( options );\n\n\t\t// Control the state of the listeners depending on whether the panel is visible\n\t\t// or not.\n\t\t// TODO: Use on() (https://github.com/ckeditor/ckeditor5-utils/issues/144).\n\t\tthis.listenTo( this, 'change:isVisible', this._pinWhenIsVisibleCallback );\n\t}\n\n\t/**\n\t * Stops pinning the panel, as set up by {@link #pin}.\n\t */\n\tunpin() {\n\t\tif ( this._pinWhenIsVisibleCallback ) {\n\t\t\t// Deactivate listeners attached by pin().\n\t\t\tthis._stopPinning();\n\n\t\t\t// Deactivate the panel pin() control logic.\n\t\t\t// TODO: Use off() (https://github.com/ckeditor/ckeditor5-utils/issues/144).\n\t\t\tthis.stopListening( this, 'change:isVisible', this._pinWhenIsVisibleCallback );\n\n\t\t\tthis._pinWhenIsVisibleCallback = null;\n\n\t\t\tthis.hide();\n\t\t}\n\t}\n\n\t/**\n\t * Starts managing the pinned state of the panel. See {@link #pin}.\n\t *\n\t * @private\n\t * @param {module:utils/dom/position~Options} options Positioning options compatible with\n\t * {@link module:utils/dom/position~getOptimalPosition}.\n\t */\n\t_startPinning( options ) {\n\t\tthis.attachTo( options );\n\n\t\tconst targetElement = getDomElement( options.target );\n\t\tconst limiterElement = options.limiter ? getDomElement( options.limiter ) : defaultLimiterElement;\n\n\t\t// Then we need to listen on scroll event of eny element in the document.\n\t\tthis.listenTo( global.document, 'scroll', ( evt, domEvt ) => {\n\t\t\tconst scrollTarget = domEvt.target;\n\n\t\t\t// The position needs to be updated if the positioning target is within the scrolled element.\n\t\t\tconst isWithinScrollTarget = targetElement && scrollTarget.contains( targetElement );\n\n\t\t\t// The position needs to be updated if the positioning limiter is within the scrolled element.\n\t\t\tconst isLimiterWithinScrollTarget = limiterElement && scrollTarget.contains( limiterElement );\n\n\t\t\t// The positioning target and/or limiter can be a Rect, object etc..\n\t\t\t// There's no way to optimize the listener then.\n\t\t\tif ( isWithinScrollTarget || isLimiterWithinScrollTarget || !targetElement || !limiterElement ) {\n\t\t\t\tthis.attachTo( options );\n\t\t\t}\n\t\t}, { useCapture: true } );\n\n\t\t// We need to listen on window resize event and update position.\n\t\tthis.listenTo( global.window, 'resize', () => {\n\t\t\tthis.attachTo( options );\n\t\t} );\n\t}\n\n\t/**\n\t * Stops managing the pinned state of the panel. See {@link #pin}.\n\t *\n\t * @private\n\t */\n\t_stopPinning() {\n\t\tthis.stopListening( global.document, 'scroll' );\n\t\tthis.stopListening( global.window, 'resize' );\n\t}\n}\n\n// Returns the DOM element for given object or null, if there is none,\n// e.g. when the passed object is a Rect instance or so.\n//\n// @private\n// @param {*} object\n// @returns {HTMLElement|null}\nfunction getDomElement( object ) {\n\tif ( isElement( object ) ) {\n\t\treturn object;\n\t}\n\n\tif ( isRange( object ) ) {\n\t\treturn object.commonAncestorContainer;\n\t}\n\n\tif ( typeof object == 'function' ) {\n\t\treturn getDomElement( object() );\n\t}\n\n\treturn null;\n}\n\n/**\n * A horizontal offset of the arrow tip from the edge of the balloon. Controlled by CSS.\n *\n *\t\t +-----|---------...\n *\t\t | |\n *\t\t | |\n *\t\t | |\n *\t\t | |\n *\t\t +--+ | +------...\n *\t\t \\ | /\n *\t\t \\|/\n *\t >|-----|<---------------- horizontal offset\n *\n * @default 30\n * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowHorizontalOffset\n */\nBalloonPanelView.arrowHorizontalOffset = 25;\n\n/**\n * A vertical offset of the arrow from the edge of the balloon. Controlled by CSS.\n *\n *\t\t +-------------...\n *\t\t |\n *\t\t |\n *\t\t | /-- vertical offset\n *\t\t | V\n *\t\t +--+ +-----... ---------\n *\t\t \\ / |\n *\t\t \\/ |\n *\t\t-------------------------------\n *\t\t ^\n *\n * @default 15\n * @member {Number} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.arrowVerticalOffset\n */\nBalloonPanelView.arrowVerticalOffset = 10;\n\n/**\n * Function used to calculate the optimal position for the balloon.\n *\n * @protected\n * @member {Function} module:ui/panel/balloon/balloonpanelview~BalloonPanelView._getOptimalPosition\n */\nBalloonPanelView._getOptimalPosition = getOptimalPosition;\n\n/**\n * A default set of positioning functions used by the balloon panel view\n * when attaching using the {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#attachTo} method.\n *\n * The available positioning functions are as follows:\n *\n * **North**\n *\n * * `northArrowSouth`\n *\n * \t\t+-----------------+\n * \t\t| Balloon |\n * \t\t+-----------------+\n * \t\t V\n * \t\t [ Target ]\n *\n * * `northArrowSouthEast`\n *\n * \t\t+-----------------+\n * \t\t| Balloon |\n * \t\t+-----------------+\n * \t\t V\n * \t\t [ Target ]\n *\n * * `northArrowSouthWest`\n *\n * \t\t +-----------------+\n * \t\t | Balloon |\n * \t\t +-----------------+\n * \t\t V\n * \t\t[ Target ]\n *\n * **North west**\n *\n * * `northWestArrowSouth`\n *\n * \t\t+-----------------+\n * \t\t| Balloon |\n * \t\t+-----------------+\n * \t\t V\n * \t\t [ Target ]\n *\n * * `northWestArrowSouthWest`\n *\n * \t\t+-----------------+\n * \t\t| Balloon |\n * \t\t+-----------------+\n * \t\t V\n * \t\t [ Target ]\n *\n * * `northWestArrowSouthEast`\n *\n * \t\t+-----------------+\n * \t\t| Balloon |\n * \t\t+-----------------+\n * \t\t V\n * \t\t [ Target ]\n *\n * **North east**\n *\n * * `northEastArrowSouth`\n *\n * \t\t+-----------------+\n * \t\t| Balloon |\n * \t\t+-----------------+\n * \t\t V\n * \t\t[ Target ]\n *\n * * `northEastArrowSouthEast`\n *\n * \t\t+-----------------+\n * \t\t| Balloon |\n * \t\t+-----------------+\n * \t\t V\n * \t\t [ Target ]\n *\n * * `northEastArrowSouthWest`\n *\n * \t\t +-----------------+\n * \t\t | Balloon |\n * \t\t +-----------------+\n * \t\t V\n * \t\t[ Target ]\n *\n * **South**\n *\n * * `southArrowNorth`\n *\n *\t\t [ Target ]\n *\t\t ^\n *\t\t+-----------------+\n *\t\t| Balloon |\n *\t\t+-----------------+\n *\n * * `southArrowNorthEast`\n *\n *\t\t [ Target ]\n *\t\t ^\n *\t\t+-----------------+\n *\t\t| Balloon |\n *\t\t+-----------------+\n *\n * * `southArrowNorthWest`\n *\n *\t\t[ Target ]\n *\t\t ^\n *\t\t +-----------------+\n *\t\t | Balloon |\n *\t\t +-----------------+\n *\n * **South west**\n *\n * * `southWestArrowNorth`\n *\n *\t\t [ Target ]\n *\t\t ^\n *\t\t+-----------------+\n *\t\t| Balloon |\n *\t\t+-----------------+\n *\n * * `southWestArrowNorthWest`\n *\n *\t\t [ Target ]\n *\t\t ^\n *\t\t+-----------------+\n *\t\t| Balloon |\n *\t\t+-----------------+\n *\n * * `southWestArrowNorthEast`\n *\n *\t\t [ Target ]\n *\t\t ^\n *\t\t+-----------------+\n *\t\t| Balloon |\n *\t\t+-----------------+\n *\n * **South east**\n *\n * * `southEastArrowNorth`\n *\n *\t\t[ Target ]\n *\t\t ^\n *\t\t+-----------------+\n *\t\t| Balloon |\n *\t\t+-----------------+\n *\n * * `southEastArrowNorthEast`\n *\n *\t\t [ Target ]\n *\t\t ^\n *\t\t+-----------------+\n *\t\t| Balloon |\n *\t\t+-----------------+\n *\n * * `southEastArrowNorthWest`\n *\n *\t\t[ Target ]\n *\t\t ^\n *\t\t +-----------------+\n *\t\t | Balloon |\n *\t\t +-----------------+\n *\n * See {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView#attachTo}.\n *\n * Positioning functions must be compatible with {@link module:utils/dom/position~Position}.\n *\n * The name that the position function returns will be reflected in the balloon panel's class that\n * controls the placement of the \"arrow\". See {@link #position} to learn more.\n *\n * @member {Object} module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions\n */\nBalloonPanelView.defaultPositions = {\n\t// ------- North\n\n\tnorthArrowSouth: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,\n\t\tname: 'arrow_s'\n\t} ),\n\n\tnorthArrowSouthEast: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left + targetRect.width / 2 - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_se'\n\t} ),\n\n\tnorthArrowSouthWest: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left + targetRect.width / 2 - BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_sw'\n\t} ),\n\n\t// ------- North west\n\n\tnorthWestArrowSouth: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left - balloonRect.width / 2,\n\t\tname: 'arrow_s'\n\t} ),\n\n\tnorthWestArrowSouthWest: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left - BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_sw'\n\t} ),\n\n\tnorthWestArrowSouthEast: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_se'\n\t} ),\n\n\t// ------- North east\n\n\tnorthEastArrowSouth: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.right - balloonRect.width / 2,\n\t\tname: 'arrow_s'\n\t} ),\n\n\tnorthEastArrowSouthEast: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.right - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_se'\n\t} ),\n\n\tnorthEastArrowSouthWest: ( targetRect, balloonRect ) => ( {\n\t\ttop: getNorthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.right - BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_sw'\n\t} ),\n\n\t// ------- South\n\n\tsouthArrowNorth: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,\n\t\tname: 'arrow_n'\n\t} ),\n\n\tsouthArrowNorthEast: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left + targetRect.width / 2 - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_ne'\n\t} ),\n\n\tsouthArrowNorthWest: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left + targetRect.width / 2 - BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_nw'\n\t} ),\n\n\t// ------- South west\n\n\tsouthWestArrowNorth: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left - balloonRect.width / 2,\n\t\tname: 'arrow_n'\n\t} ),\n\n\tsouthWestArrowNorthWest: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left - BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_nw'\n\t} ),\n\n\tsouthWestArrowNorthEast: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.left - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_ne'\n\t} ),\n\n\t// ------- South east\n\n\tsouthEastArrowNorth: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.right - balloonRect.width / 2,\n\t\tname: 'arrow_n'\n\t} ),\n\n\tsouthEastArrowNorthEast: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.right - balloonRect.width + BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_ne'\n\t} ),\n\n\tsouthEastArrowNorthWest: ( targetRect, balloonRect ) => ( {\n\t\ttop: getSouthTop( targetRect, balloonRect ),\n\t\tleft: targetRect.right - BalloonPanelView.arrowHorizontalOffset,\n\t\tname: 'arrow_nw'\n\t} ),\n};\n\n// Returns the top coordinate for positions starting with `north*`.\n//\n// @private\n// @param {utils/dom/rect~Rect} targetRect A rect of the target.\n// @param {utils/dom/rect~Rect} elementRect A rect of the balloon.\n// @returns {Number}\nfunction getNorthTop( targetRect, balloonRect ) {\n\treturn targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset;\n}\n\n// Returns the top coordinate for positions starting with `south*`.\n//\n// @private\n// @param {utils/dom/rect~Rect} targetRect A rect of the target.\n// @param {utils/dom/rect~Rect} elementRect A rect of the balloon.\n// @returns {Number}\nfunction getSouthTop( targetRect ) {\n\treturn targetRect.bottom + BalloonPanelView.arrowVerticalOffset;\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M11.463 5.187a.888.888 0 1 1 1.254 1.255L9.16 10l3.557 3.557a.888.888 0 1 1-1.254 1.255L7.26 10.61a.888.888 0 0 1 .16-1.382l4.043-4.042z\\\" /></svg>\\n\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M8.537 14.813a.888.888 0 1 1-1.254-1.255L10.84 10 7.283 6.442a.888.888 0 1 1 1.254-1.255L12.74 9.39a.888.888 0 0 1-.16 1.382l-4.043 4.042z\\\"/></svg>\\n\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module ui/panel/balloon/contextualballoon\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport BalloonPanelView from './balloonpanelview';\nimport View from '../../view';\nimport ButtonView from '../../button/buttonview';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\nimport toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\nimport prevIcon from '../../../theme/icons/previous-arrow.svg';\nimport nextIcon from '../../../theme/icons/next-arrow.svg';\nimport '../../../theme/components/panel/balloonrotator.css';\nimport '../../../theme/components/panel/fakepanel.css';\nconst toPx = toUnit('px');\n/**\n * Provides the common contextual balloon for the editor.\n *\n * The role of this plugin is to unify the contextual balloons logic, simplify views management and help\n * avoid the unnecessary complexity of handling multiple {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView}\n * instances in the editor.\n *\n * This plugin allows for creating single or multiple panel stacks.\n *\n * Each stack may have multiple views, with the one on the top being visible. When the visible view is removed from the stack,\n * the previous view becomes visible.\n *\n * It might be useful to implement nested navigation in a balloon. For instance, a toolbar view may contain a link button.\n * When you click it, a link view (which lets you set the URL) is created and put on top of the toolbar view, so the link panel\n * is displayed. When you finish editing the link and close (remove) the link view, the toolbar view is visible again.\n *\n * However, there are cases when there are multiple independent balloons to be displayed, for instance, if the selection\n * is inside two inline comments at the same time. For such cases, you can create two independent panel stacks.\n * The contextual balloon plugin will create a navigation bar to let the users switch between these panel stacks using the \"Next\"\n * and \"Previous\" buttons.\n *\n * If there are no views in the current stack, the balloon panel will try to switch to the next stack. If there are no\n * panels in any stack, the balloon panel will be hidden.\n *\n * **Note**: To force the balloon panel to show only one view, even if there are other stacks, use the `singleViewMode=true` option\n * when {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon#add adding} a view to a panel.\n *\n * From the implementation point of view, the contextual ballon plugin is reusing a single\n * {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView} instance to display multiple contextual balloon\n * panels in the editor. It also creates a special {@link module:ui/panel/balloon/contextualballoon~RotatorView rotator view},\n * used to manage multiple panel stacks. Rotator view is a child of the balloon panel view and the parent of the specific\n * view you want to display. If there is more than one panel stack to be displayed, the rotator view will add a\n * navigation bar. If there is only one stack, the rotator view is transparent (it does not add any UI elements).\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ContextualBalloon extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'ContextualBalloon';\n }\n /**\n\t * @inheritDoc\n\t */\n constructor(editor) {\n super(editor);\n /**\n\t\t * The {@link module:utils/dom/position~Options#limiter position limiter}\n\t\t * for the {@link #view balloon}, used when no `limiter` has been passed into {@link #add}\n\t\t * or {@link #updatePosition}.\n\t\t *\n\t\t * By default, a function that obtains the farthest DOM\n\t\t * {@link module:engine/view/rooteditableelement~RootEditableElement}\n\t\t * of the {@link module:engine/view/document~Document#selection}.\n\t\t *\n\t\t * @member {module:utils/dom/position~Options#limiter} #positionLimiter\n\t\t */\n this.positionLimiter = () => {\n const view = this.editor.editing.view;\n const viewDocument = view.document;\n const editableElement = viewDocument.selection.editableElement;\n if (editableElement) {\n return view.domConverter.mapViewToDom(editableElement.root);\n }\n return null;\n };\n /**\n\t\t * The currently visible view or `null` when there are no views in any stack.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {module:ui/view~View|null} #visibleView\n\t\t */\n this.set('visibleView', null);\n /**\n\t\t * The common balloon panel view.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/panel/balloon/balloonpanelview~BalloonPanelView} #view\n\t\t */\n this.view = new BalloonPanelView(editor.locale);\n editor.ui.view.body.add(this.view);\n editor.ui.focusTracker.add(this.view.element);\n /**\n\t\t * The map of views and their stacks.\n\t\t *\n\t\t * @private\n\t\t * @type {Map.<module:ui/view~View,Set>}\n\t\t */\n this._viewToStack = new Map();\n /**\n\t\t * The map of IDs and stacks.\n\t\t *\n\t\t * @private\n\t\t * @type {Map.<String,Set>}\n\t\t */\n this._idToStack = new Map();\n /**\n\t\t * A total number of all stacks in the balloon.\n\t\t *\n\t\t * @private\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #_numberOfStacks\n\t\t */\n this.set('_numberOfStacks', 0);\n /**\n\t\t * A flag that controls the single view mode.\n\t\t *\n\t\t * @private\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Boolean} #_singleViewMode\n\t\t */\n this.set('_singleViewMode', false);\n /**\n\t\t * Rotator view embedded in the contextual balloon.\n\t\t * Displays the currently visible view in the balloon and provides navigation for switching stacks.\n\t\t *\n\t\t * @private\n\t\t * @type {module:ui/panel/balloon/contextualballoon~RotatorView}\n\t\t */\n this._rotatorView = this._createRotatorView();\n /**\n\t\t * Displays fake panels under the balloon panel view when multiple stacks are added to the balloon.\n\t\t *\n\t\t * @private\n\t\t * @type {module:ui/view~View}\n\t\t */\n this._fakePanelsView = this._createFakePanelsView();\n }\n /**\n\t * Returns `true` when the given view is in one of the stacks. Otherwise returns `false`.\n\t *\n\t * @param {module:ui/view~View} view\n\t * @returns {Boolean}\n\t */\n hasView(view) {\n return Array.from(this._viewToStack.keys()).includes(view);\n }\n /**\n\t * Adds a new view to the stack and makes it visible if the current stack is visible\n\t * or it is the first view in the balloon.\n\t *\n\t * @param {Object} data The configuration of the view.\n\t * @param {String} [data.stackId='main'] The ID of the stack that the view is added to.\n\t * @param {module:ui/view~View} [data.view] The content of the balloon.\n\t * @param {module:utils/dom/position~Options} [data.position] Positioning options.\n\t * @param {String} [data.balloonClassName] An additional CSS class added to the {@link #view balloon} when visible.\n\t * @param {Boolean} [data.withArrow=true] Whether the {@link #view balloon} should be rendered with an arrow.\n\t * @param {Boolean} [data.singleViewMode=false] Whether the view should be the only visible view even if other stacks were added.\n\t */\n add(data) {\n if (this.hasView(data.view)) {\n /**\n\t\t\t * Trying to add configuration of the same view more than once.\n\t\t\t *\n\t\t\t * @error contextualballoon-add-view-exist\n\t\t\t */\n throw new CKEditorError('contextualballoon-add-view-exist: Cannot add configuration of the same view twice.', [\n this,\n data\n ]);\n }\n const stackId = data.stackId || 'main';\n // If new stack is added, creates it and show view from this stack.\n if (!this._idToStack.has(stackId)) {\n this._idToStack.set(stackId, new Map([[\n data.view,\n data\n ]]));\n this._viewToStack.set(data.view, this._idToStack.get(stackId));\n this._numberOfStacks = this._idToStack.size;\n if (!this._visibleStack || data.singleViewMode) {\n this.showStack(stackId);\n }\n return;\n }\n const stack = this._idToStack.get(stackId);\n if (data.singleViewMode) {\n this.showStack(stackId);\n }\n // Add new view to the stack.\n stack.set(data.view, data);\n this._viewToStack.set(data.view, stack);\n // And display it if is added to the currently visible stack.\n if (stack === this._visibleStack) {\n this._showView(data);\n }\n }\n /**\n\t * Removes the given view from the stack. If the removed view was visible,\n\t * the view preceding it in the stack will become visible instead.\n\t * When there is no view in the stack, the next stack will be displayed.\n\t * When there are no more stacks, the balloon will hide.\n\t *\n\t * @param {module:ui/view~View} view A view to be removed from the balloon.\n\t */\n remove(view) {\n if (!this.hasView(view)) {\n /**\n\t\t\t * Trying to remove the configuration of the view not defined in the stack.\n\t\t\t *\n\t\t\t * @error contextualballoon-remove-view-not-exist\n\t\t\t */\n throw new CKEditorError('contextualballoon-remove-view-not-exist: Cannot remove the configuration of a non-existent view.', [\n this,\n view\n ]);\n }\n const stack = this._viewToStack.get(view);\n if (this._singleViewMode && this.visibleView === view) {\n this._singleViewMode = false;\n }\n // When visible view will be removed we need to show a preceding view or next stack\n // if a view is the only view in the stack.\n if (this.visibleView === view) {\n if (stack.size === 1) {\n if (this._idToStack.size > 1) {\n this._showNextStack();\n } else {\n this.view.hide();\n this.visibleView = null;\n this._rotatorView.hideView();\n }\n } else {\n this._showView(Array.from(stack.values())[stack.size - 2]);\n }\n }\n if (stack.size === 1) {\n this._idToStack.delete(this._getStackId(stack));\n this._numberOfStacks = this._idToStack.size;\n } else {\n stack.delete(view);\n }\n this._viewToStack.delete(view);\n }\n /**\n\t * Updates the position of the balloon using the position data of the first visible view in the stack.\n\t * When new position data is given, the position data of the currently visible view will be updated.\n\t *\n\t * @param {module:utils/dom/position~Options} [position] position options.\n\t */\n updatePosition(position) {\n if (position) {\n this._visibleStack.get(this.visibleView).position = position;\n }\n this.view.pin(this._getBalloonPosition());\n this._fakePanelsView.updatePosition();\n }\n /**\n\t * Shows the last view from the stack of a given ID.\n\t *\n\t * @param {String} id\n\t */\n showStack(id) {\n this.visibleStack = id;\n const stack = this._idToStack.get(id);\n if (!stack) {\n /**\n\t\t\t * Trying to show a stack that does not exist.\n\t\t\t *\n\t\t\t * @error contextualballoon-showstack-stack-not-exist\n\t\t\t */\n throw new CKEditorError('contextualballoon-showstack-stack-not-exist: Cannot show a stack that does not exist.', this);\n }\n if (this._visibleStack === stack) {\n return;\n }\n this._showView(Array.from(stack.values()).pop());\n }\n /**\n\t * Returns the stack of the currently visible view.\n\t *\n\t * @private\n\t * @type {Set}\n\t */\n get _visibleStack() {\n return this._viewToStack.get(this.visibleView);\n }\n /**\n\t * Returns the ID of the given stack.\n\t *\n\t * @private\n\t * @param {Set} stack\n\t * @returns {String}\n\t */\n _getStackId(stack) {\n const entry = Array.from(this._idToStack.entries()).find(entry => entry[1] === stack);\n return entry[0];\n }\n /**\n\t * Shows the last view from the next stack.\n\t *\n\t * @private\n\t */\n _showNextStack() {\n const stacks = Array.from(this._idToStack.values());\n let nextIndex = stacks.indexOf(this._visibleStack) + 1;\n if (!stacks[nextIndex]) {\n nextIndex = 0;\n }\n this.showStack(this._getStackId(stacks[nextIndex]));\n }\n /**\n\t * Shows the last view from the previous stack.\n\t *\n\t * @private\n\t */\n _showPrevStack() {\n const stacks = Array.from(this._idToStack.values());\n let nextIndex = stacks.indexOf(this._visibleStack) - 1;\n if (!stacks[nextIndex]) {\n nextIndex = stacks.length - 1;\n }\n this.showStack(this._getStackId(stacks[nextIndex]));\n }\n /**\n\t * Creates a rotator view.\n\t *\n\t * @private\n\t * @returns {module:ui/panel/balloon/contextualballoon~RotatorView}\n\t */\n _createRotatorView() {\n const view = new RotatorView(this.editor.locale);\n const t = this.editor.locale.t;\n this.view.content.add(view);\n // Hide navigation when there is only a one stack & not in single view mode.\n view.bind('isNavigationVisible').to(this, '_numberOfStacks', this, '_singleViewMode', (value, isSingleViewMode) => {\n return !isSingleViewMode && value > 1;\n });\n // Update balloon position after toggling navigation.\n view.on('change:isNavigationVisible', () => this.updatePosition(), { priority: 'low' });\n // Update stacks counter value.\n view.bind('counter').to(this, 'visibleView', this, '_numberOfStacks', (visibleView, numberOfStacks) => {\n if (numberOfStacks < 2) {\n return '';\n }\n const current = Array.from(this._idToStack.values()).indexOf(this._visibleStack) + 1;\n return t('ar', [\n current,\n numberOfStacks\n ]);\n });\n view.buttonNextView.on('execute', () => {\n // When current view has a focus then move focus to the editable before removing it,\n // otherwise editor will lost focus.\n if (view.focusTracker.isFocused) {\n this.editor.editing.view.focus();\n }\n this._showNextStack();\n });\n view.buttonPrevView.on('execute', () => {\n // When current view has a focus then move focus to the editable before removing it,\n // otherwise editor will lost focus.\n if (view.focusTracker.isFocused) {\n this.editor.editing.view.focus();\n }\n this._showPrevStack();\n });\n return view;\n }\n /**\n\t * @returns {module:ui/view~View}\n\t */\n _createFakePanelsView() {\n const view = new FakePanelsView(this.editor.locale, this.view);\n view.bind('numberOfPanels').to(this, '_numberOfStacks', this, '_singleViewMode', (number, isSingleViewMode) => {\n const showPanels = !isSingleViewMode && number >= 2;\n return showPanels ? Math.min(number - 1, 2) : 0;\n });\n view.listenTo(this.view, 'change:top', () => view.updatePosition());\n view.listenTo(this.view, 'change:left', () => view.updatePosition());\n this.editor.ui.view.body.add(view);\n return view;\n }\n /**\n\t * Sets the view as the content of the balloon and attaches the balloon using position\n\t * options of the first view.\n\t *\n\t * @private\n\t * @param {Object} data Configuration.\n\t * @param {module:ui/view~View} [data.view] The view to show in the balloon.\n\t * @param {String} [data.balloonClassName=''] Additional class name which will be added to the {@link #view balloon}.\n\t * @param {Boolean} [data.withArrow=true] Whether the {@link #view balloon} should be rendered with an arrow.\n\t */\n _showView({view, balloonClassName = '', withArrow = true, singleViewMode = false}) {\n this.view.class = balloonClassName;\n this.view.withArrow = withArrow;\n this._rotatorView.showView(view);\n this.visibleView = view;\n this.view.pin(this._getBalloonPosition());\n this._fakePanelsView.updatePosition();\n if (singleViewMode) {\n this._singleViewMode = true;\n }\n }\n /**\n\t * Returns position options of the last view in the stack.\n\t * This keeps the balloon in the same position when the view is changed.\n\t *\n\t * @private\n\t * @returns {module:utils/dom/position~Options}\n\t */\n _getBalloonPosition() {\n let position = Array.from(this._visibleStack.values()).pop().position;\n // Use the default limiter if none has been specified.\n if (position && !position.limiter) {\n // Don't modify the original options object.\n position = Object.assign({}, position, { limiter: this.positionLimiter });\n }\n return position;\n }\n}\n/**\n * Rotator view is a helper class for the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon ContextualBalloon}.\n * It is used for displaying the last view from the current stack and providing navigation buttons for switching stacks.\n * See the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon ContextualBalloon} documentation to learn more.\n *\n * @extends module:ui/view~View\n */\nclass RotatorView extends View {\n /**\n\t * @inheritDoc\n\t */\n constructor(locale) {\n super(locale);\n const t = locale.t;\n const bind = this.bindTemplate;\n /**\n\t\t * Defines whether navigation is visible or not.\n\t\t *\n\t\t * @member {Boolean} #isNavigationVisible\n\t\t */\n this.set('isNavigationVisible', true);\n /**\n\t\t * Used for checking if a view is focused or not.\n\t\t *\n\t\t * @type {module:utils/focustracker~FocusTracker}\n\t\t */\n this.focusTracker = new FocusTracker();\n /**\n\t\t * Navigation button for switching the stack to the previous one.\n\t\t *\n\t\t * @type {module:ui/button/buttonview~ButtonView}\n\t\t */\n this.buttonPrevView = this._createButtonView(t('as'), prevIcon);\n /**\n\t\t * Navigation button for switching the stack to the next one.\n\t\t *\n\t\t * @type {module:ui/button/buttonview~ButtonView}\n\t\t */\n this.buttonNextView = this._createButtonView(t('at'), nextIcon);\n /**\n\t\t * A collection of the child views that creates the rotator content.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.content = this.createCollection();\n this.setTemplate({\n tag: 'div',\n attributes: {\n class: [\n 'ck',\n 'ck-balloon-rotator'\n ],\n 'z-index': '-1'\n },\n children: [\n {\n tag: 'div',\n attributes: {\n class: [\n 'ck-balloon-rotator__navigation',\n bind.to('isNavigationVisible', value => value ? '' : 'ck-hidden')\n ]\n },\n children: [\n this.buttonPrevView,\n {\n tag: 'span',\n attributes: { class: ['ck-balloon-rotator__counter'] },\n children: [{ text: bind.to('counter') }]\n },\n this.buttonNextView\n ]\n },\n {\n tag: 'div',\n attributes: { class: 'ck-balloon-rotator__content' },\n children: this.content\n }\n ]\n });\n }\n /**\n\t * @inheritDoc\n\t */\n render() {\n super.render();\n this.focusTracker.add(this.element);\n }\n /**\n\t * Shows a given view.\n\t *\n\t * @param {module:ui/view~View} view The view to show.\n\t */\n showView(view) {\n this.hideView();\n this.content.add(view);\n }\n /**\n\t * Hides the currently displayed view.\n\t */\n hideView() {\n this.content.clear();\n }\n /**\n\t * Creates a navigation button view.\n\t *\n\t * @private\n\t * @param {String} label The button label.\n\t * @param {String} icon The button icon.\n\t * @returns {module:ui/button/buttonview~ButtonView}\n\t */\n _createButtonView(label, icon) {\n const view = new ButtonView(this.locale);\n view.set({\n label,\n icon,\n tooltip: true\n });\n return view;\n }\n}\n// Displays additional layers under the balloon when multiple stacks are added to the balloon.\n//\n// @private\n// @extends module:ui/view~View\nclass FakePanelsView extends View {\n // @inheritDoc\n constructor(locale, balloonPanelView) {\n super(locale);\n const bind = this.bindTemplate;\n // Fake panels top offset.\n //\n // @observable\n // @member {Number} #top\n this.set('top', 0);\n // Fake panels left offset.\n //\n // @observable\n // @member {Number} #left\n this.set('left', 0);\n // Fake panels height.\n //\n // @observable\n // @member {Number} #height\n this.set('height', 0);\n // Fake panels width.\n //\n // @observable\n // @member {Number} #width\n this.set('width', 0);\n // Number of rendered fake panels.\n //\n // @observable\n // @member {Number} #numberOfPanels\n this.set('numberOfPanels', 0);\n // Collection of the child views which creates fake panel content.\n //\n // @readonly\n // @type {module:ui/viewcollection~ViewCollection}\n this.content = this.createCollection();\n // Context.\n //\n // @private\n // @type {module:ui/panel/balloon/balloonpanelview~BalloonPanelView}\n this._balloonPanelView = balloonPanelView;\n this.setTemplate({\n tag: 'div',\n attributes: {\n class: [\n 'ck-fake-panel',\n bind.to('numberOfPanels', number => number ? '' : 'ck-hidden')\n ],\n style: {\n top: bind.to('top', toPx),\n left: bind.to('left', toPx),\n width: bind.to('width', toPx),\n height: bind.to('height', toPx)\n }\n },\n children: this.content\n });\n this.on('change:numberOfPanels', (evt, name, next, prev) => {\n if (next > prev) {\n this._addPanels(next - prev);\n } else {\n this._removePanels(prev - next);\n }\n this.updatePosition();\n });\n }\n // @private\n // @param {Number} number\n _addPanels(number) {\n while (number--) {\n const view = new View();\n view.setTemplate({ tag: 'div' });\n this.content.add(view);\n this.registerChild(view);\n }\n }\n // @private\n // @param {Number} number\n _removePanels(number) {\n while (number--) {\n const view = this.content.last;\n this.content.remove(view);\n this.deregisterChild(view);\n view.destroy();\n }\n }\n // Updates coordinates of fake panels.\n updatePosition() {\n if (this.numberOfPanels) {\n const {top, left} = this._balloonPanelView;\n const {width, height} = new Rect(this._balloonPanelView.element);\n Object.assign(this, {\n top,\n left,\n width,\n height\n });\n }\n }\n}","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 20 20\\\" width=\\\"20\\\" height=\\\"20\\\"><path d=\\\"M1.586 18.227l.398-2.753.398-2.753 2.355 2.388 2.355 2.355-2.753.365zM14.954 8.01l-7.099 7.065-.763-.796 7.065-7.066-1.592-1.559L5.5 12.721l-.763-.796 7.065-7.066-.796-.796-7.861 7.862 4.71 4.71 7.861-7.828zm3.25-1.56c.398-.397.398-1.094-.033-1.525L15.02 1.775c-.431-.432-1.128-.465-1.526-.034l-.1.1-1.525 1.493 4.71 4.71 1.526-1.493-.033-.033c.033-.033.099-.033.132-.066z\\\"/></svg>\\n\"","import imageIcon from '../icons/edit.svg';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nexport function createToolbarEditButton(editor, name, callback) {\n\t// Add editing button\n\teditor.ui.componentFactory.add( name, locale => {\n\t\tconst view = new ButtonView( locale );\n\n\t\tview.set( {\n\t\t\tlabel: I18n.t('js.button_edit'),\n\t\t\ticon: imageIcon,\n\t\t\ttooltip: true\n\t\t} );\n\n\t\t// Callback executed once the widget is clicked.\n\t\tview.on( 'execute', () => {\n\n\t\t\tconst widget = editor.model.document.selection.getSelectedElement();\n\n\t\t\tif (!widget) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcallback(widget);\n\t\t} );\n\n\t\treturn view;\n\t} );\n}\n","import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';\nimport BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';\n\nconst balloonClassName = 'ck-toolbar-container';\n\nexport function createEditToolbar(\n\t// Plugin instance\n\tplugin,\n\t// Editor instance\n\teditor,\n\t// Configuration namespace in op-ckeditor.js\n\tconfig_namespace,\n\t// Callback to check if widget is selected\n\tisWidgetSelected\n) {\n\n\tconst toolbarConfig = editor.config.get( config_namespace + '.toolbar' );\n\n\t// Don't add the toolbar if there is no configuration.\n\tif ( !toolbarConfig || !toolbarConfig.length ) {\n\t\treturn;\n\t}\n\n\tconst _balloon = editor.plugins.get( 'ContextualBalloon' );\n\tconst _toolbar = new ToolbarView( editor.locale );\n\n\tfunction _checkIsVisible() {\n\t\tif ( !editor.ui.focusTracker.isFocused ) {\n\t\t\t_hideToolbar();\n\t\t} else {\n\t\t\tif ( isWidgetSelected(editor.editing.view.document.selection ) ) {\n\t\t\t\t_showToolbar();\n\t\t\t} else {\n\t\t\t\t_hideToolbar();\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction _showToolbar() {\n\t\tif ( _isVisible() ) {\n\t\t\trepositionContextualBalloon( editor, isWidgetSelected );\n\t\t} else if ( !_balloon.hasView( _toolbar ) ) {\n\t\t\t_balloon.add( {\n\t\t\t\tview: _toolbar,\n\t\t\t\tposition: getBalloonPositionData( editor ),\n\t\t\t\tballoonClassName\n\t\t\t} );\n\t\t}\n\t}\n\n\tfunction _hideToolbar() {\n\t\tif ( !_isVisible() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t_balloon.remove( _toolbar );\n\t}\n\n\tfunction _isVisible() {\n\t\treturn _balloon.visibleView == _toolbar;\n\t}\n\n\t// Add buttons to the toolbar.\n\t_toolbar.fillFromConfig( toolbarConfig, editor.ui.componentFactory );\n\n\t// Show balloon panel each time the widget is selected.\n\t// TODO: This has changed in master with https://github.com/ckeditor/ckeditor5-image/pull/215\n\tplugin.listenTo( editor.editing.view, 'render', _checkIsVisible);\n\n\t// UI#update is not fired after focus is back in editor, we need to check if balloon panel should be visible.\n\tplugin.listenTo( editor.ui.focusTracker, 'change:isFocused', _checkIsVisible, { priority: 'low' } );\n}\n\n\n/**\n * A helper utility that positions the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} instance\n * with respect to the element in the editor content, if one is selected.\n *\n * @param {module:core/editor/editor~Editor} editor The editor instance.\n */\nfunction repositionContextualBalloon( editor, selectionCallback ) {\n\tconst balloon = editor.plugins.get( 'ContextualBalloon' );\n\n\tif ( selectionCallback( editor.editing.view.document.selection ) ) {\n\t\tconst position = getBalloonPositionData( editor );\n\n\t\tballoon.updatePosition( position );\n\t}\n}\n\n\n/**\n * Returns the positioning options that control the geometry of the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} with respect\n * to the selected element in the editor content.\n *\n * @param {module:core/editor/editor~Editor} editor The editor instance.\n * @returns {module:utils/dom/position~Options}\n */\nfunction getBalloonPositionData( editor ) {\n\tconst editingView = editor.editing.view;\n\tconst defaultPositions = BalloonPanelView.defaultPositions;\n\n\treturn {\n\t\ttarget: editingView.domConverter.viewToDom( editingView.document.selection.getSelectedElement() ),\n\t\tpositions: [\n\t\t\tdefaultPositions.northArrowSouth,\n\t\t\tdefaultPositions.northArrowSouthWest,\n\t\t\tdefaultPositions.northArrowSouthEast,\n\t\t\tdefaultPositions.southArrowNorth,\n\t\t\tdefaultPositions.southArrowNorthWest,\n\t\t\tdefaultPositions.southArrowNorthEast\n\t\t]\n\t};\n}\n","import Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\n\nimport {isEmbeddedTableWidgetSelected} from './utils';\nimport {createToolbarEditButton} from '../../helpers/create-toolbar-edit-button';\nimport {createEditToolbar} from '../../helpers/create-toolbar';\nimport {getPluginContext} from '../op-context/op-context';\n\n\nconst balloonClassName = 'ck-toolbar-container';\n\nexport default class EmbeddedTableToolbar extends Plugin {\n\tstatic get requires() {\n\t\treturn [ ContextualBalloon ];\n\t}\n\n\tstatic get pluginName() {\n\t\treturn 'EmbeddedTableToolbar';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = this.editor.model;\n\t\tconst pluginContext = getPluginContext(editor);\n\n\t\t// Add editing button\n\t\tcreateToolbarEditButton( editor, 'opEditEmbeddedTableQuery', widget => {\n\t\t\tconst externalQueryConfiguration = pluginContext.services.externalQueryConfiguration;\n\t\t\tconst currentQuery = widget.getAttribute('opEmbeddedTableQuery') || {};\n\n\t\t\tpluginContext.runInZone(() => {\n\t\t\t\texternalQueryConfiguration.show(\n\t\t\t\t\tcurrentQuery,\n\t\t\t\t\t(newQuery) => model.change(writer => {\n\t\t\t\t\t\twriter.setAttribute( 'opEmbeddedTableQuery', newQuery, widget );\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t});\n\t\t} );\n\t}\n\n\tafterInit() {\n\t\t// Add actual toolbar\n\t\tcreateEditToolbar(\n\t\t\tthis,\n\t\t\tthis.editor,\n\t\t\t'OPMacroEmbeddedTable',\n\t\t\tisEmbeddedTableWidgetSelected\n\t\t);\n\t}\n}\n","const wpButtonMacroSymbol = Symbol( 'isWpButtonMacroSymbol' );\nimport {toWidget, isWidget} from '@ckeditor/ckeditor5-widget/src/utils';\n\nexport function toWpButtonMacroWidget( viewElement, writer, label ) {\n\twriter.setCustomProperty( wpButtonMacroSymbol, true, viewElement );\n\treturn toWidget( viewElement, writer, { label: label });\n}\n\n\nexport function isWpButtonMacroWidget( viewElement ) {\n\treturn !!viewElement.getCustomProperty( wpButtonMacroSymbol ) && isWidget( viewElement );\n}\n\n\nexport function isWpButtonMacroWidgetSelected( selection ) {\n\tconst viewElement = selection.getSelectedElement();\n\n\treturn !!( viewElement && isWpButtonMacroWidget( viewElement ) );\n}\n","import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport {toWpButtonMacroWidget} from './utils';\nimport {getPluginContext} from '../op-context/op-context';\n\nexport default class OPMacroWpButtonEditing extends Plugin {\n\n\tstatic get pluginName() {\n\t\treturn 'OPMacroWpButtonEditing';\n\t}\n\n\tstatic get buttonName() {\n\t\treturn 'insertWorkPackageButton';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst conversion = editor.conversion;\n\t\tconst pluginContext = getPluginContext(editor);\n\n\t\t// Schema.\n\t\tmodel.schema.register( 'op-macro-wp-button', {\n\t\t\tallowWhere: ['$block'],\n\t\t\tallowAttributes: ['type', 'classes'],\n\t\t\tisBlock: true,\n\t\t isLimit: true\n\t\t});\n\n\t\tconversion.for( 'upcast' )\n\t\t\t.elementToElement( {\n\t\t\t\tview: {\n\t\t\t\t\tname: 'macro',\n\t\t\t\t\tclasses: 'create_work_package_link'\n\t\t\t\t},\n\t\t\t\tmodel: ( viewElement, modelWriter ) => {\n\t\t\t\t\tconst type = viewElement.getAttribute( 'data-type' ) || '';\n\t\t\t\t\tconst classes = viewElement.getAttribute( 'data-classes' ) || '';\n\n\t\t\t\t\treturn modelWriter.createElement(\n\t\t\t\t\t\t'op-macro-wp-button',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: type,\n\t\t\t\t\t\t\tclasses: classes\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\n\n\t\tconversion.for( 'editingDowncast' ).elementToElement( {\n\t\t\tmodel: 'op-macro-wp-button',\n\t\t\tview: (modelElement, writer) => {\n\t\t\t\treturn this.createMacroViewElement(modelElement, writer);\n\t\t\t}\n\t } );\n\n\t\tconversion.for('dataDowncast').elementToElement({\n\t\t\tmodel: 'op-macro-wp-button',\n\t\t\tview: (modelElement, writer) => {\n\t\t\t\tconst element = writer.createContainerElement(\n\t\t\t\t\t'macro',\n\t\t\t\t\t{\n\t\t\t\t\t\t'class': 'create_work_package_link',\n\t\t\t\t\t\t'data-type': modelElement.getAttribute('type') || '',\n\t\t\t\t\t\t'data-classes': modelElement.getAttribute('classes') || '',\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\treturn element;\n\t\t\t}\n\t\t});\n\n\t\teditor.ui.componentFactory.add( OPMacroWpButtonEditing.buttonName, locale => {\n\t\t\tconst view = new ButtonView( locale );\n\n\t\t\tview.set( {\n\t\t\t\tlabel: window.I18n.t('js.editor.macro.work_package_button.button'),\n\t\t\t\twithText: true\n\t\t\t} );\n\n\t\t\t// Callback executed once the image is clicked.\n\t\t\tview.on( 'execute', () => {\n\t\t\t\tconst macroService = pluginContext.services.macros;\n\n\t\t\t\tmacroService\n\t\t\t\t\t.configureWorkPackageButton()\n\t\t\t\t\t.then((result) => editor.model.change(writer => {\n\t\t\t\t\t\tconst element = writer.createElement( 'op-macro-wp-button', {});\n\t\t\t\t\t\twriter.setAttribute( 'type', result.type, element );\n\t\t\t\t\t\twriter.setAttribute( 'classes', result.classes, element );\n\n\t\t\t\t\t\teditor.model.insertContent( element, editor.model.document.selection );\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t} );\n\n\t\t\treturn view;\n\t\t} );\n\t}\n\n\tmacroLabel(type) {\n\t\tif (type) {\n\t\t\treturn window.I18n.t('js.editor.macro.work_package_button.with_type', { typename: type });\n\t\t} else {\n\t\t\treturn window.I18n.t('js.editor.macro.work_package_button.without_type');\n\t\t}\n\t}\n\n\tcreateMacroViewElement(modelElement, writer) {\n\t\tconst type = modelElement.getAttribute('type');\n\t\tconst classes = modelElement.getAttribute('classes') || '';\n\t\tconst label = this.macroLabel(); // TODO: Pass type, it is not updated on coming back from the modal..\n\t\tconst placeholder = writer.createText( label );\n\t\tconst container = writer.createContainerElement( 'span', { class: 'macro -create_work_package_link ' + classes } );\n\n\t\twriter.insert( writer.createPositionAt( container, 0 ), placeholder );\n\t\treturn toWpButtonMacroWidget(container, writer, { label: label } )\n\t}\n}\n","import Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\n\nimport {isWpButtonMacroWidgetSelected} from './utils';\nimport {createToolbarEditButton} from '../../helpers/create-toolbar-edit-button';\nimport {createEditToolbar} from '../../helpers/create-toolbar';\nimport {getPluginContext} from '../op-context/op-context';\n\n\nconst balloonClassName = 'ck-toolbar-container';\n\nexport default class OPMacroWpButtonToolbar extends Plugin {\n\tstatic get requires() {\n\t\treturn [ ContextualBalloon ];\n\t}\n\n\tstatic get pluginName() {\n\t\treturn 'OPMacroWpButtonToolbar';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = this.editor.model;\n\t\tconst pluginContext = getPluginContext(editor);\n\n\t\t// Add editing button\n\t\tcreateToolbarEditButton( editor, 'opEditWpMacroButton', widget => {\n\t\t\tconst macroService = pluginContext.services.macros;\n\t\t\tconst type = widget.getAttribute('type');\n\t\t\tconst classes = widget.getAttribute('classes');\n\n\t\t\tmacroService\n\t\t\t\t.configureWorkPackageButton(type, classes)\n\t\t\t\t.then((result) => editor.model.change(writer => {\n\t\t\t\t\twriter.setAttribute( 'classes', result.classes, widget );\n\t\t\t\t\twriter.setAttribute( 'type', result.type, widget );\n\t\t\t\t})\n\t\t\t);\n\t\t} );\n\t}\n\n\tafterInit() {\n\t\t// Add actual toolbar\n\t\tcreateEditToolbar(\n\t\t\tthis,\n\t\t\tthis.editor,\n\t\t\t'OPMacroWpButton',\n\t\t\tisWpButtonMacroWidgetSelected\n\t\t);\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 core/pendingactions\n */\n\nimport Plugin from './plugin';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * The list of pending editor actions.\n *\n * This plugin should be used to synchronise plugins that execute long-lasting actions\n * (e.g. file upload) with the editor integration. It gives the developer who integrates the editor\n * an easy way to check if there are any actions pending whenever such information is needed.\n * All plugins that register a pending action also provide a message about the action that is ongoing\n * which can be displayed to the user. This lets them decide if they want to interrupt the action or wait.\n *\n * Adding and updating a pending action:\n *\n * \t\tconst pendingActions = editor.plugins.get( 'PendingActions' );\n * \t\tconst action = pendingActions.add( 'Upload in progress: 0%.' );\n *\n *\t\t// You can update the message:\n * \t\taction.message = 'Upload in progress: 10%.';\n *\n * Removing a pending action:\n *\n * \t\tconst pendingActions = editor.plugins.get( 'PendingActions' );\n * \t\tconst action = pendingActions.add( 'Unsaved changes.' );\n *\n * \t\tpendingActions.remove( action );\n *\n * Getting pending actions:\n *\n * \t\tconst pendingActions = editor.plugins.get( 'PendingActions' );\n *\n * \t\tconst action1 = pendingActions.add( 'Action 1' );\n * \t\tconst action2 = pendingActions.add( 'Action 2' );\n *\n * \t\tpendingActions.first; // Returns action1\n * \t\tArray.from( pendingActions ); // Returns [ action1, action2 ]\n *\n * This plugin is used by features like {@link module:upload/filerepository~FileRepository} to register their ongoing actions\n * and by features like {@link module:autosave/autosave~Autosave} to detect whether there are any ongoing actions.\n * Read more about saving the data in the {@glink builds/guides/integration/saving-data Saving and getting data} guide.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class PendingActions extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'PendingActions';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\t/**\n\t\t * Defines whether there is any registered pending action.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Boolean} #hasAny\n\t\t */\n\t\tthis.set( 'hasAny', false );\n\n\t\t/**\n\t\t * A list of pending actions.\n\t\t *\n\t\t * @private\n\t\t * @type {module:utils/collection~Collection}\n\t\t */\n\t\tthis._actions = new Collection( { idProperty: '_id' } );\n\t\tthis._actions.delegate( 'add', 'remove' ).to( this );\n\t}\n\n\t/**\n\t * Adds an action to the list of pending actions.\n\t *\n\t * This method returns an action object with an observable message property.\n\t * The action object can be later used in the {@link #remove} method. It also allows you to change the message.\n\t *\n\t * @param {String} message The action message.\n\t * @returns {Object} An observable object that represents a pending action.\n\t */\n\tadd( message ) {\n\t\tif ( typeof message !== 'string' ) {\n\t\t\t/**\n\t\t\t * The message must be a string.\n\t\t\t *\n\t\t\t * @error pendingactions-add-invalid-message\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'pendingactions-add-invalid-message: The message must be a string.', this );\n\t\t}\n\n\t\tconst action = Object.create( ObservableMixin );\n\n\t\taction.set( 'message', message );\n\t\tthis._actions.add( action );\n\t\tthis.hasAny = true;\n\n\t\treturn action;\n\t}\n\n\t/**\n\t * Removes an action from the list of pending actions.\n\t *\n\t * @param {Object} action An action object.\n\t */\n\tremove( action ) {\n\t\tthis._actions.remove( action );\n\t\tthis.hasAny = !!this._actions.length;\n\t}\n\n\t/**\n\t * Returns the first action from the list or null when list is empty\n\t *\n\t * returns {Object|null} The pending action object.\n\t */\n\tget first() {\n\t\treturn this._actions.get( 0 );\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * @returns {Iterable.<*>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this._actions[ Symbol.iterator ]();\n\t}\n\n\t/**\n\t * Fired when an action is added to the list.\n\t *\n\t * @event add\n\t * @param {Object} action The added action.\n\t */\n\n\t/**\n\t * Fired when an action is removed from the list.\n\t *\n\t * @event remove\n\t * @param {Object} action The removed action.\n\t */\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 upload/filereader\n */\n\n/* globals window */\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Wrapper over the native `FileReader`.\n */\nexport default class FileReader {\n\t/**\n\t * Creates an instance of the FileReader.\n\t */\n\tconstructor() {\n\t\tconst reader = new window.FileReader();\n\n\t\t/**\n\t\t * Instance of native FileReader.\n\t\t *\n\t\t * @private\n\t\t * @member {FileReader} #_reader\n\t\t */\n\t\tthis._reader = reader;\n\n\t\tthis._data = undefined;\n\n\t\t/**\n\t\t * Number of bytes loaded.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #loaded\n\t\t */\n\t\tthis.set( 'loaded', 0 );\n\n\t\treader.onprogress = evt => {\n\t\t\tthis.loaded = evt.loaded;\n\t\t};\n\t}\n\n\t/**\n\t * Returns error that occurred during file reading.\n\t *\n\t * @returns {Error}\n\t */\n\tget error() {\n\t\treturn this._reader.error;\n\t}\n\n\t/**\n\t * Holds the data of an already loaded file. The file must be first loaded\n\t * by using {@link module:upload/filereader~FileReader#read `read()`}.\n\t *\n\t * @type {File|undefined}\n\t */\n\tget data() {\n\t\treturn this._data;\n\t}\n\n\t/**\n\t * Reads the provided file.\n\t *\n\t * @param {File} file Native File object.\n\t * @returns {Promise.<String>} Returns a promise that will be resolved with file's content.\n\t * The promise will be rejected in case of an error or when the reading process is aborted.\n\t */\n\tread( file ) {\n\t\tconst reader = this._reader;\n\t\tthis.total = file.size;\n\n\t\treturn new Promise( ( resolve, reject ) => {\n\t\t\treader.onload = () => {\n\t\t\t\tconst result = reader.result;\n\n\t\t\t\tthis._data = result;\n\n\t\t\t\tresolve( result );\n\t\t\t};\n\n\t\t\treader.onerror = () => {\n\t\t\t\treject( 'error' );\n\t\t\t};\n\n\t\t\treader.onabort = () => {\n\t\t\t\treject( 'aborted' );\n\t\t\t};\n\n\t\t\tthis._reader.readAsDataURL( file );\n\t\t} );\n\t}\n\n\t/**\n\t * Aborts file reader.\n\t */\n\tabort() {\n\t\tthis._reader.abort();\n\t}\n}\n\nmix( FileReader, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module upload/filerepository\n */\n/* globals console */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport PendingActions from '@ckeditor/ckeditor5-core/src/pendingactions';\nimport CKEditorError, { attachLinkToDocumentation } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport FileReader from './filereader.js';\nimport uid from '@ckeditor/ckeditor5-utils/src/uid.js';\n/**\n * File repository plugin. A central point for managing file upload.\n *\n * To use it, first you need an upload adapter. Upload adapter's job is to handle communication with the server\n * (sending the file and handling server's response). You can use one of the existing plugins introducing upload adapters\n * (e.g. {@link module:easy-image/cloudservicesuploadadapter~CloudServicesUploadAdapter} or\n * {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter}) or write your own one – see\n * the {@glink framework/guides/deep-dive/upload-adapter \"Custom image upload adapter\" deep dive guide}.\n *\n * Then, you can use {@link module:upload/filerepository~FileRepository#createLoader `createLoader()`} and the returned\n * {@link module:upload/filerepository~FileLoader} instance to load and upload files.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class FileRepository extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'FileRepository';\n }\n /**\n\t * @inheritDoc\n\t */\n static get requires() {\n return [PendingActions];\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n /**\n\t\t * Collection of loaders associated with this repository.\n\t\t *\n\t\t * @member {module:utils/collection~Collection} #loaders\n\t\t */\n this.loaders = new Collection();\n // Keeps upload in a sync with pending actions.\n this.loaders.on('add', () => this._updatePendingAction());\n this.loaders.on('remove', () => this._updatePendingAction());\n /**\n\t\t * Loaders mappings used to retrieve loaders references.\n\t\t *\n\t\t * @private\n\t\t * @member {Map<File|Promise, FileLoader>} #_loadersMap\n\t\t */\n this._loadersMap = new Map();\n /**\n\t\t * Reference to a pending action registered in a {@link module:core/pendingactions~PendingActions} plugin\n\t\t * while upload is in progress. When there is no upload then value is `null`.\n\t\t *\n\t\t * @private\n\t\t * @member {Object} #_pendingAction\n\t\t */\n this._pendingAction = null;\n /**\n\t\t * A factory function which should be defined before using `FileRepository`.\n\t\t *\n\t\t * It should return a new instance of {@link module:upload/filerepository~UploadAdapter} that will be used to upload files.\n\t\t * {@link module:upload/filerepository~FileLoader} instance associated with the adapter\n\t\t * will be passed to that function.\n\t\t *\n\t\t * For more information and example see {@link module:upload/filerepository~UploadAdapter}.\n\t\t *\n\t\t * @member {Function} #createUploadAdapter\n\t\t */\n /**\n\t\t * Number of bytes uploaded.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #uploaded\n\t\t */\n this.set('uploaded', 0);\n /**\n\t\t * Number of total bytes to upload.\n\t\t *\n\t\t * It might be different than the file size because of headers and additional data.\n\t\t * It contains `null` if value is not available yet, so it's better to use {@link #uploadedPercent} to monitor\n\t\t * the progress.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number|null} #uploadTotal\n\t\t */\n this.set('uploadTotal', null);\n /**\n\t\t * Upload progress in percents.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #uploadedPercent\n\t\t */\n this.bind('uploadedPercent').to(this, 'uploaded', this, 'uploadTotal', (uploaded, total) => {\n return total ? uploaded / total * 100 : 0;\n });\n }\n /**\n\t * Returns the loader associated with specified file or promise.\n\t *\n\t * To get loader by id use `fileRepository.loaders.get( id )`.\n\t *\n\t * @param {File|Promise.<File>} fileOrPromise Native file or promise handle.\n\t * @returns {module:upload/filerepository~FileLoader|null}\n\t */\n getLoader(fileOrPromise) {\n return this._loadersMap.get(fileOrPromise) || null;\n }\n /**\n\t * Creates a loader instance for the given file.\n\t *\n\t * Requires {@link #createUploadAdapter} factory to be defined.\n\t *\n\t * @param {File|Promise.<File>} fileOrPromise Native File object or native Promise object which resolves to a File.\n\t * @returns {module:upload/filerepository~FileLoader|null}\n\t */\n createLoader(fileOrPromise) {\n if (!this.createUploadAdapter) {\n /**\n\t\t\t * You need to enable an upload adapter in order to be able to upload files.\n\t\t\t *\n\t\t\t * This warning shows up when {@link module:upload/filerepository~FileRepository} is being used\n\t\t\t * without {@link #createUploadAdapter definining an upload adapter}.\n\t\t\t *\n\t\t\t * **If you see this warning when using one of the {@glink builds/index CKEditor 5 Builds}**\n\t\t\t * it means that you did not configure any of the upload adapters available by default in those builds.\n\t\t\t *\n\t\t\t * See the {@glink features/image-upload/image-upload comprehensive \"Image upload overview\"} to learn which upload\n\t\t\t * adapters are available in the builds and how to configure them.\n\t\t\t *\n\t\t\t * **If you see this warning when using a custom build** there is a chance that you enabled\n\t\t\t * a feature like {@link module:image/imageupload~ImageUpload},\n\t\t\t * or {@link module:image/imageupload/imageuploadui~ImageUploadUI} but you did not enable any upload adapter.\n\t\t\t * You can choose one of the existing upload adapters listed in the\n\t\t\t * {@glink features/image-upload/image-upload \"Image upload overview\"}.\n\t\t\t *\n\t\t\t * You can also implement your {@glink framework/guides/deep-dive/upload-adapter own image upload adapter}.\n\t\t\t *\n\t\t\t * @error filerepository-no-upload-adapter\n\t\t\t */\n console.warn(attachLinkToDocumentation('filerepository-no-upload-adapter: Upload adapter is not defined.'));\n return null;\n }\n const loader = new FileLoader(Promise.resolve(fileOrPromise), this.createUploadAdapter);\n this.loaders.add(loader);\n this._loadersMap.set(fileOrPromise, loader);\n // Store also file => loader mapping so loader can be retrieved by file instance returned upon Promise resolution.\n if (fileOrPromise instanceof Promise) {\n loader.file.then(file => {\n this._loadersMap.set(file, loader);\n }) // Every then() must have a catch().\n // File loader state (and rejections) are handled in read() and upload().\n // Also, see the \"does not swallow the file promise rejection\" test.\n.catch(() => {\n });\n }\n loader.on('change:uploaded', () => {\n let aggregatedUploaded = 0;\n for (const loader of this.loaders) {\n aggregatedUploaded += loader.uploaded;\n }\n this.uploaded = aggregatedUploaded;\n });\n loader.on('change:uploadTotal', () => {\n let aggregatedTotal = 0;\n for (const loader of this.loaders) {\n if (loader.uploadTotal) {\n aggregatedTotal += loader.uploadTotal;\n }\n }\n this.uploadTotal = aggregatedTotal;\n });\n return loader;\n }\n /**\n\t * Destroys the given loader.\n\t *\n\t * @param {File|Promise|module:upload/filerepository~FileLoader} fileOrPromiseOrLoader File or Promise associated\n\t * with that loader or loader itself.\n\t */\n destroyLoader(fileOrPromiseOrLoader) {\n const loader = fileOrPromiseOrLoader instanceof FileLoader ? fileOrPromiseOrLoader : this.getLoader(fileOrPromiseOrLoader);\n loader._destroy();\n this.loaders.remove(loader);\n this._loadersMap.forEach((value, key) => {\n if (value === loader) {\n this._loadersMap.delete(key);\n }\n });\n }\n /**\n\t * Registers or deregisters pending action bound with upload progress.\n\t *\n\t * @private\n\t */\n _updatePendingAction() {\n const pendingActions = this.editor.plugins.get(PendingActions);\n if (this.loaders.length) {\n if (!this._pendingAction) {\n const t = this.editor.t;\n const getMessage = value => `${ t('i') } ${ parseInt(value) }%.`;\n this._pendingAction = pendingActions.add(getMessage(this.uploadedPercent));\n this._pendingAction.bind('message').to(this, 'uploadedPercent', getMessage);\n }\n } else {\n pendingActions.remove(this._pendingAction);\n this._pendingAction = null;\n }\n }\n}\nmix(FileRepository, ObservableMixin);\n/**\n * File loader class.\n *\n * It is used to control the process of reading the file and uploading it using the specified upload adapter.\n */\nclass FileLoader {\n /**\n\t * Creates a new instance of `FileLoader`.\n\t *\n\t * @param {Promise.<File>} filePromise A promise which resolves to a file instance.\n\t * @param {Function} uploadAdapterCreator The function which returns {@link module:upload/filerepository~UploadAdapter} instance.\n\t */\n constructor(filePromise, uploadAdapterCreator) {\n /**\n\t\t * Unique id of FileLoader instance.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t */\n this.id = uid();\n /**\n\t\t * Additional wrapper over the initial file promise passed to this loader.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:upload/filerepository~FilePromiseWrapper}\n\t\t */\n this._filePromiseWrapper = this._createFilePromiseWrapper(filePromise);\n /**\n\t\t * Adapter instance associated with this file loader.\n\t\t *\n\t\t * @private\n\t\t * @member {module:upload/filerepository~UploadAdapter}\n\t\t */\n this._adapter = uploadAdapterCreator(this);\n /**\n\t\t * FileReader used by FileLoader.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:upload/filereader~FileReader}\n\t\t */\n this._reader = new FileReader();\n /**\n\t\t * Current status of FileLoader. It can be one of the following:\n\t\t *\n\t\t * * 'idle',\n\t\t * * 'reading',\n\t\t * * 'uploading',\n\t\t * * 'aborted',\n\t\t * * 'error'.\n\t\t *\n\t\t * When reading status can change in a following way:\n\t\t *\n\t\t * `idle` -> `reading` -> `idle`\n\t\t * `idle` -> `reading -> `aborted`\n\t\t * `idle` -> `reading -> `error`\n\t\t *\n\t\t * When uploading status can change in a following way:\n\t\t *\n\t\t * `idle` -> `uploading` -> `idle`\n\t\t * `idle` -> `uploading` -> `aborted`\n\t\t * `idle` -> `uploading` -> `error`\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {String} #status\n\t\t */\n this.set('status', 'idle');\n /**\n\t\t * Number of bytes uploaded.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #uploaded\n\t\t */\n this.set('uploaded', 0);\n /**\n\t\t * Number of total bytes to upload.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number|null} #uploadTotal\n\t\t */\n this.set('uploadTotal', null);\n /**\n\t\t * Upload progress in percents.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #uploadedPercent\n\t\t */\n this.bind('uploadedPercent').to(this, 'uploaded', this, 'uploadTotal', (uploaded, total) => {\n return total ? uploaded / total * 100 : 0;\n });\n /**\n\t\t * Response of the upload.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Object|null} #uploadResponse\n\t\t */\n this.set('uploadResponse', null);\n }\n /**\n\t * A `Promise` which resolves to a `File` instance associated with this file loader.\n\t *\n\t * @type {Promise.<File|null>}\n\t */\n get file() {\n if (!this._filePromiseWrapper) {\n // Loader was destroyed, return promise which resolves to null.\n return Promise.resolve(null);\n } else {\n // The `this._filePromiseWrapper.promise` is chained and not simply returned to handle a case when:\n //\n //\t\t* The `loader.file.then( ... )` is called by external code (returned promise is pending).\n //\t\t* Then `loader._destroy()` is called (call is synchronous) which destroys the `loader`.\n //\t\t* Promise returned by the first `loader.file.then( ... )` call is resolved.\n //\n // Returning `this._filePromiseWrapper.promise` will still resolve to a `File` instance so there\n // is an additional check needed in the chain to see if `loader` was destroyed in the meantime.\n return this._filePromiseWrapper.promise.then(file => this._filePromiseWrapper ? file : null);\n }\n }\n /**\n\t * Returns the file data. To read its data, you need for first load the file\n\t * by using the {@link module:upload/filerepository~FileLoader#read `read()`} method.\n\t *\n\t * @type {File|undefined}\n\t */\n get data() {\n return this._reader.data;\n }\n /**\n\t * Reads file using {@link module:upload/filereader~FileReader}.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `filerepository-read-wrong-status` when status\n\t * is different than `idle`.\n\t *\n\t * Example usage:\n\t *\n\t *\tfileLoader.read()\n\t *\t\t.then( data => { ... } )\n\t *\t\t.catch( err => {\n\t *\t\t\tif ( err === 'aborted' ) {\n\t *\t\t\t\tconsole.log( 'Reading aborted.' );\n\t *\t\t\t} else {\n\t *\t\t\t\tconsole.log( 'Reading error.', err );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * @returns {Promise.<String>} Returns promise that will be resolved with read data. Promise will be rejected if error\n\t * occurs or if read process is aborted.\n\t */\n read() {\n if (this.status != 'idle') {\n throw new CKEditorError('filerepository-read-wrong-status: You cannot call read if the status is different than idle.', this);\n }\n this.status = 'reading';\n return this.file.then(file => this._reader.read(file)).then(data => {\n // Edge case: reader was aborted after file was read - double check for proper status.\n if (this.status !== 'reading') {\n throw this.status;\n }\n this.status = 'idle';\n return data;\n }).catch(err => {\n if (err === 'aborted') {\n this.status = 'aborted';\n throw 'aborted';\n }\n this.status = 'error';\n throw this._reader.error ? this._reader.error : err;\n });\n }\n /**\n\t * Reads file using the provided {@link module:upload/filerepository~UploadAdapter}.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `filerepository-upload-wrong-status` when status\n\t * is different than `idle`.\n\t * Example usage:\n\t *\n\t *\tfileLoader.upload()\n\t *\t\t.then( data => { ... } )\n\t *\t\t.catch( e => {\n\t *\t\t\tif ( e === 'aborted' ) {\n\t *\t\t\t\tconsole.log( 'Uploading aborted.' );\n\t *\t\t\t} else {\n\t *\t\t\t\tconsole.log( 'Uploading error.', e );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * @returns {Promise.<Object>} Returns promise that will be resolved with response data. Promise will be rejected if error\n\t * occurs or if read process is aborted.\n\t */\n upload() {\n if (this.status != 'idle') {\n throw new CKEditorError('filerepository-upload-wrong-status: You cannot call upload if the status is different than idle.', this);\n }\n this.status = 'uploading';\n return this.file.then(() => this._adapter.upload()).then(data => {\n this.uploadResponse = data;\n this.status = 'idle';\n return data;\n }).catch(err => {\n if (this.status === 'aborted') {\n throw 'aborted';\n }\n this.status = 'error';\n throw err;\n });\n }\n /**\n\t * Aborts loading process.\n\t */\n abort() {\n const status = this.status;\n this.status = 'aborted';\n if (!this._filePromiseWrapper.isFulfilled) {\n // Edge case: file loader is aborted before read() is called\n // so it might happen that no one handled the rejection of this promise.\n // See https://github.com/ckeditor/ckeditor5-upload/pull/100\n this._filePromiseWrapper.promise.catch(() => {\n });\n this._filePromiseWrapper.rejecter('aborted');\n } else if (status == 'reading') {\n this._reader.abort();\n } else if (status == 'uploading' && this._adapter.abort) {\n this._adapter.abort();\n }\n this._destroy();\n }\n /**\n\t * Performs cleanup.\n\t *\n\t * @private\n\t */\n _destroy() {\n this._filePromiseWrapper = undefined;\n this._reader = undefined;\n this._adapter = undefined;\n this.uploadResponse = undefined;\n }\n /**\n\t * Wraps a given file promise into another promise giving additional\n\t * control (resolving, rejecting, checking if fulfilled) over it.\n\t *\n\t * @private\n\t * @param filePromise The initial file promise to be wrapped.\n\t * @returns {module:upload/filerepository~FilePromiseWrapper}\n\t */\n _createFilePromiseWrapper(filePromise) {\n const wrapper = {};\n wrapper.promise = new Promise((resolve, reject) => {\n wrapper.rejecter = reject;\n wrapper.isFulfilled = false;\n filePromise.then(file => {\n wrapper.isFulfilled = true;\n resolve(file);\n }).catch(err => {\n wrapper.isFulfilled = true;\n reject(err);\n });\n });\n return wrapper;\n }\n}\nmix(FileLoader, ObservableMixin); /**\n * Upload adapter interface used by the {@link module:upload/filerepository~FileRepository file repository}\n * to handle file upload. An upload adapter is a bridge between the editor and server that handles file uploads.\n * It should contain a logic necessary to initiate an upload process and monitor its progress.\n *\n * Learn how to develop your own upload adapter for CKEditor 5 in the\n * {@glink framework/guides/deep-dive/upload-adapter \"Custom upload adapter\" guide}.\n *\n * @interface UploadAdapter\n */\n /**\n * Executes the upload process.\n * This method should return a promise that will resolve when data will be uploaded to server. Promise should be\n * resolved with an object containing information about uploaded file:\n *\n *\t\t{\n *\t\t\tdefault: 'http://server/default-size.image.png'\n *\t\t}\n *\n * Additionally, other image sizes can be provided:\n *\n *\t\t{\n *\t\t\tdefault: 'http://server/default-size.image.png',\n *\t\t\t'160': 'http://server/size-160.image.png',\n *\t\t\t'500': 'http://server/size-500.image.png',\n *\t\t\t'1000': 'http://server/size-1000.image.png',\n *\t\t\t'1052': 'http://server/default-size.image.png'\n *\t\t}\n *\n * NOTE: When returning multiple images, the widest returned one should equal the default one. It is essential to\n * correctly set `width` attribute of the image. See this discussion:\n * https://github.com/ckeditor/ckeditor5-easy-image/issues/4 for more information.\n *\n * Take a look at {@link module:upload/filerepository~UploadAdapter example Adapter implementation} and\n * {@link module:upload/filerepository~FileRepository#createUploadAdapter createUploadAdapter method}.\n *\n * @method module:upload/filerepository~UploadAdapter#upload\n * @returns {Promise.<Object>} Promise that should be resolved when data is uploaded.\n */\n /**\n * Aborts the upload process.\n * After aborting it should reject promise returned from {@link #upload upload()}.\n *\n * Take a look at {@link module:upload/filerepository~UploadAdapter example Adapter implementation} and\n * {@link module:upload/filerepository~FileRepository#createUploadAdapter createUploadAdapter method}.\n *\n * @method module:upload/filerepository~UploadAdapter#abort\n */\n /**\n * Object returned by {@link module:upload/filerepository~FileLoader#_createFilePromiseWrapper} method\n * to add more control over the initial file promise passed to {@link module:upload/filerepository~FileLoader}.\n *\n * @protected\n * @typedef {Object} module:upload/filerepository~FilePromiseWrapper\n * @property {Promise.<File>} promise Wrapper promise which can be chained for further processing.\n * @property {Function} rejecter Rejects the promise when called.\n * @property {Boolean} isFulfilled Whether original promise is already fulfilled.\n */","export default class OpUploadResourceAdapter {\n constructor(loader, resource, editor) {\n this.loader = loader;\n this.resource = resource;\n this.editor = editor;\n }\n\n upload() {\n\t\tconst resource = this.resource;\n if (!(resource && resource.uploadAttachments)) {\n\t\t\tconst resourceContext = resource ? resource.name : 'Missing context';\n console.warn(`uploadAttachments not present on context: ${resourceContext}`);\n return Promise.reject(\"You're not allowed to upload attachments on this resource.\");\n\t\t}\n\n\t\treturn this.loader.file\n\t\t\t.then(file => {\n\t\t\treturn resource\n\t\t\t\t.uploadAttachments([file])\n\t\t\t\t.then((result) => {\n\t\t\t\t\tthis.editor.model.fire('op:attachment-added', result);\n\n\t\t\t\t\treturn this.buildResponse(result[0])\n\t\t\t\t}).catch((error) => {\n\t\t\t\t\tconsole.error(\"Failed upload %O\", error);\n\t\t\t\t});\n\t\t})\n\n\t}\n\n\tbuildResponse(result) {\n\t\treturn { default: result.uploadUrl };\n\t}\n\n abort() {\n\t\treturn false;\n }\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 upload/ui/filedialogbuttonview\n */\n\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport View from '@ckeditor/ckeditor5-ui/src/view';\n\n/**\n * The file dialog button view.\n *\n * This component provides a button that opens the native file selection dialog.\n * It can be used to implement the UI of a file upload feature.\n *\n *\t\tconst view = new FileDialogButtonView( locale );\n *\n *\t\tview.set( {\n *\t\t\tacceptedType: 'image/*',\n *\t\t\tallowMultipleFiles: true\n *\t\t} );\n *\n *\t\tview.buttonView.set( {\n *\t\t\tlabel: t( 'Insert image' ),\n *\t\t\ticon: imageIcon,\n *\t\t\ttooltip: true\n *\t\t} );\n *\n *\t\tview.on( 'done', ( evt, files ) => {\n *\t\t\tfor ( const file of Array.from( files ) ) {\n *\t\t\t\tconsole.log( 'Selected file', file );\n *\t\t\t}\n *\t\t} );\n *\n * @extends module:ui/view~View\n */\nexport default class FileDialogButtonView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * The button view of the component.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n\t\tthis.buttonView = new ButtonView( locale );\n\n\t\t/**\n\t\t * A hidden `<input>` view used to execute file dialog.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:upload/ui/filedialogbuttonview~FileInputView}\n\t\t */\n\t\tthis._fileInputView = new FileInputView( locale );\n\n\t\t/**\n\t\t * Accepted file types. Can be provided in form of file extensions, media type or one of:\n\t\t * * `audio/*`,\n\t\t * * `video/*`,\n\t\t * * `image/*`.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #acceptedType\n\t\t */\n\t\tthis._fileInputView.bind( 'acceptedType' ).to( this );\n\n\t\t/**\n\t\t * Indicates if multiple files can be selected. Defaults to `true`.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #allowMultipleFiles\n\t\t */\n\t\tthis._fileInputView.bind( 'allowMultipleFiles' ).to( this );\n\n\t\t/**\n\t\t * Fired when file dialog is closed with file selected.\n\t\t *\n\t\t *\t\tview.on( 'done', ( evt, files ) => {\n\t\t *\t\t\tfor ( const file of files ) {\n\t\t *\t\t\t\tconsole.log( 'Selected file', file );\n\t\t *\t\t\t}\n\t\t *\t\t}\n\t\t *\n\t\t * @event done\n\t\t * @param {Array.<File>} files Array of selected files.\n\t\t */\n\t\tthis._fileInputView.delegate( 'done' ).to( this );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'span',\n\t\t\tattributes: {\n\t\t\t\tclass: 'ck-file-dialog-button',\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\tthis.buttonView,\n\t\t\t\tthis._fileInputView\n\t\t\t]\n\t\t} );\n\n\t\tthis.buttonView.on( 'execute', () => {\n\t\t\tthis._fileInputView.open();\n\t\t} );\n\t}\n\n\t/**\n\t * Focuses the {@link #buttonView}.\n\t */\n\tfocus() {\n\t\tthis.buttonView.focus();\n\t}\n}\n\n/**\n * The hidden file input view class.\n *\n * @private\n * @extends module:ui/view~View\n */\nclass FileInputView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * Accepted file types. Can be provided in form of file extensions, media type or one of:\n\t\t * * `audio/*`,\n\t\t * * `video/*`,\n\t\t * * `image/*`.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #acceptedType\n\t\t */\n\t\tthis.set( 'acceptedType' );\n\n\t\t/**\n\t\t * Indicates if multiple files can be selected. Defaults to `false`.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #allowMultipleFiles\n\t\t */\n\t\tthis.set( 'allowMultipleFiles', false );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'input',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck-hidden'\n\t\t\t\t],\n\t\t\t\ttype: 'file',\n\t\t\t\ttabindex: '-1',\n\t\t\t\taccept: bind.to( 'acceptedType' ),\n\t\t\t\tmultiple: bind.to( 'allowMultipleFiles' )\n\t\t\t},\n\n\t\t\ton: {\n\t\t\t\t// Removing from code coverage since we cannot programmatically set input element files.\n\t\t\t\tchange: bind.to( /* istanbul ignore next */ () => {\n\t\t\t\t\tif ( this.element && this.element.files && this.element.files.length ) {\n\t\t\t\t\t\tthis.fire( 'done', this.element.files );\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.element.value = '';\n\t\t\t\t} )\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Opens file dialog.\n\t */\n\topen() {\n\t\tthis.element.click();\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M6.91 10.54c.26-.23.64-.21.88.03l3.36 3.14 2.23-2.06a.64.64 0 0 1 .87 0l2.52 2.97V4.5H3.2v10.12l3.71-4.08zm10.27-7.51c.6 0 1.09.47 1.09 1.05v11.84c0 .59-.49 1.06-1.09 1.06H2.79c-.6 0-1.09-.47-1.09-1.06V4.08c0-.58.49-1.05 1.1-1.05h14.38zm-5.22 5.56a1.96 1.96 0 1 1 3.4-1.96 1.96 1.96 0 0 1-3.4 1.96z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, 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 image/imageupload/utils\n */\n\n/* global fetch, File */\n\n/**\n * Creates a regular expression used to test for image files.\n *\n *\t\tconst imageType = createImageTypeRegExp( [ 'png', 'jpeg', 'svg+xml', 'vnd.microsoft.icon' ] );\n *\n *\t\tconsole.log( 'is supported image', imageType.test( file.type ) );\n *\n * @param {Array.<String>} types\n * @returns {RegExp}\n */\nexport function createImageTypeRegExp( types ) {\n\t// Sanitize the MIME type name which may include: \"+\", \"-\" or \".\".\n\tconst regExpSafeNames = types.map( type => type.replace( '+', '\\\\+' ) );\n\n\treturn new RegExp( `^image\\\\/(${ regExpSafeNames.join( '|' ) })$` );\n}\n\n/**\n * Creates a promise that fetches the image local source (Base64 or blob) and resolves with a `File` object.\n *\n * @param {module:engine/view/element~Element} image Image whose source to fetch.\n * @returns {Promise.<File>} A promise which resolves when an image source is fetched and converted to a `File` instance.\n * It resolves with a `File` object. If there were any errors during file processing, the promise will be rejected.\n */\nexport function fetchLocalImage( image ) {\n\treturn new Promise( ( resolve, reject ) => {\n\t\tconst imageSrc = image.getAttribute( 'src' );\n\n\t\t// Fetch works asynchronously and so does not block browser UI when processing data.\n\t\tfetch( imageSrc )\n\t\t\t.then( resource => resource.blob() )\n\t\t\t.then( blob => {\n\t\t\t\tconst mimeType = getImageMimeType( blob, imageSrc );\n\t\t\t\tconst ext = mimeType.replace( 'image/', '' );\n\t\t\t\tconst filename = `image.${ ext }`;\n\t\t\t\tconst file = createFileFromBlob( blob, filename, mimeType );\n\n\t\t\t\tfile ? resolve( file ) : reject();\n\t\t\t} )\n\t\t\t.catch( reject );\n\t} );\n}\n\n/**\n * Checks whether a given node is an image element with a local source (Base64 or blob).\n *\n * @param {module:engine/view/node~Node} node The node to check.\n * @returns {Boolean}\n */\nexport function isLocalImage( node ) {\n\tif ( !node.is( 'element', 'img' ) || !node.getAttribute( 'src' ) ) {\n\t\treturn false;\n\t}\n\n\treturn node.getAttribute( 'src' ).match( /^data:image\\/\\w+;base64,/g ) ||\n\t\tnode.getAttribute( 'src' ).match( /^blob:/g );\n}\n\n// Extracts an image type based on its blob representation or its source.\n//\n// @param {String} src Image `src` attribute value.\n// @param {Blob} blob Image blob representation.\n// @returns {String}\nfunction getImageMimeType( blob, src ) {\n\tif ( blob.type ) {\n\t\treturn blob.type;\n\t} else if ( src.match( /data:(image\\/\\w+);base64/ ) ) {\n\t\treturn src.match( /data:(image\\/\\w+);base64/ )[ 1 ].toLowerCase();\n\t} else {\n\t\t// Fallback to 'jpeg' as common extension.\n\t\treturn 'image/jpeg';\n\t}\n}\n\n// Creates a `File` instance from the given `Blob` instance using the specified file name.\n//\n// @param {Blob} blob The `Blob` instance from which the file will be created.\n// @param {String} filename The file name used during the file creation.\n// @param {String} mimeType The file MIME type.\n// @returns {File|null} The `File` instance created from the given blob or `null` if `File API` is not available.\nfunction createFileFromBlob( blob, filename, mimeType ) {\n\ttry {\n\t\treturn new File( [ blob ], filename, { type: mimeType } );\n\t} catch ( err ) {\n\t\t// Edge does not support `File` constructor ATM, see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9551546/.\n\t\t// However, the `File` function is present (so cannot be checked with `!window.File` or `typeof File === 'function'`), but\n\t\t// calling it with `new File( ... )` throws an error. This try-catch prevents that. Also when the function will\n\t\t// be implemented correctly in Edge the code will start working without any changes (see #247).\n\t\treturn null;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module image/imageupload/imageuploadui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport FileDialogButtonView from '@ckeditor/ckeditor5-upload/src/ui/filedialogbuttonview';\nimport imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';\nimport { createImageTypeRegExp } from './utils';\n/**\n * The image upload button plugin.\n *\n * For a detailed overview, check the {@glink features/image-upload/image-upload Image upload feature} documentation.\n *\n * Adds the `'imageUpload'` button to the {@link module:ui/componentfactory~ComponentFactory UI component factory}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageUploadUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const t = editor.t;\n // Setup `imageUpload` button.\n editor.ui.componentFactory.add('imageUpload', locale => {\n const view = new FileDialogButtonView(locale);\n const command = editor.commands.get('imageUpload');\n const imageTypes = editor.config.get('image.upload.types');\n const imageTypesRegExp = createImageTypeRegExp(imageTypes);\n view.set({\n acceptedType: imageTypes.map(type => `image/${ type }`).join(','),\n allowMultipleFiles: true\n });\n view.buttonView.set({\n label: t('bj'),\n icon: imageIcon,\n tooltip: true\n });\n view.buttonView.bind('isEnabled').to(command);\n view.on('done', (evt, files) => {\n const imagesToUpload = Array.from(files).filter(file => imageTypesRegExp.test(file.type));\n if (imagesToUpload.length) {\n editor.execute('imageUpload', { file: imagesToUpload });\n }\n });\n return view;\n });\n }\n}","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 700 250\\\"><rect rx=\\\"4\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, 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 image/imageupload/imageuploadprogress\n */\n\n/* globals setTimeout */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';\nimport uploadingPlaceholder from '../../theme/icons/image_placeholder.svg';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\nimport '../../theme/imageuploadprogress.css';\nimport '../../theme/imageuploadicon.css';\nimport '../../theme/imageuploadloader.css';\n\n/**\n * The image upload progress plugin.\n * It shows a placeholder when the image is read from the disk and a progress bar while the image is uploading.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageUploadProgress extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The image placeholder that is displayed before real image data can be accessed.\n\t\t *\n\t\t * @protected\n\t\t * @member {String} #placeholder\n\t\t */\n\t\tthis.placeholder = 'data:image/svg+xml;utf8,' + encodeURIComponent( uploadingPlaceholder );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Upload status change - update image's view according to that status.\n\t\teditor.editing.downcastDispatcher.on( 'attribute:uploadStatus:image', ( ...args ) => this.uploadStatusChange( ...args ) );\n\t}\n\n\t/**\n\t * This method is called each time the image `uploadStatus` attribute is changed.\n\t *\n\t * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n\t * @param {Object} data Additional information about the change.\n\t * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n\t */\n\tuploadStatusChange( evt, data, conversionApi ) {\n\t\tconst editor = this.editor;\n\t\tconst modelImage = data.item;\n\t\tconst uploadId = modelImage.getAttribute( 'uploadId' );\n\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst fileRepository = editor.plugins.get( FileRepository );\n\t\tconst status = uploadId ? data.attributeNewValue : null;\n\t\tconst placeholder = this.placeholder;\n\t\tconst viewFigure = editor.editing.mapper.toViewElement( modelImage );\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\tif ( status == 'reading' ) {\n\t\t\t// Start \"appearing\" effect and show placeholder with infinite progress bar on the top\n\t\t\t// while image is read from disk.\n\t\t\t_startAppearEffect( viewFigure, viewWriter );\n\t\t\t_showPlaceholder( placeholder, viewFigure, viewWriter );\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Show progress bar on the top of the image when image is uploading.\n\t\tif ( status == 'uploading' ) {\n\t\t\tconst loader = fileRepository.loaders.get( uploadId );\n\n\t\t\t// Start appear effect if needed - see https://github.com/ckeditor/ckeditor5-image/issues/191.\n\t\t\t_startAppearEffect( viewFigure, viewWriter );\n\n\t\t\tif ( !loader ) {\n\t\t\t\t// There is no loader associated with uploadId - this means that image came from external changes.\n\t\t\t\t// In such cases we still want to show the placeholder until image is fully uploaded.\n\t\t\t\t// Show placeholder if needed - see https://github.com/ckeditor/ckeditor5-image/issues/191.\n\t\t\t\t_showPlaceholder( placeholder, viewFigure, viewWriter );\n\t\t\t} else {\n\t\t\t\t// Hide placeholder and initialize progress bar showing upload progress.\n\t\t\t\t_hidePlaceholder( viewFigure, viewWriter );\n\t\t\t\t_showProgressBar( viewFigure, viewWriter, loader, editor.editing.view );\n\t\t\t\t_displayLocalImage( viewFigure, viewWriter, loader );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Because in Edge there is no way to show fancy animation of completeIcon we need to skip it.\n\t\tif ( status == 'complete' && fileRepository.loaders.get( uploadId ) && !env.isEdge ) {\n\t\t\t_showCompleteIcon( viewFigure, viewWriter, editor.editing.view );\n\t\t}\n\n\t\t// Clean up.\n\t\t_hideProgressBar( viewFigure, viewWriter );\n\t\t_hidePlaceholder( viewFigure, viewWriter );\n\t\t_stopAppearEffect( viewFigure, viewWriter );\n\t}\n}\n\n// Adds ck-appear class to the image figure if one is not already applied.\n//\n// @param {module:engine/view/containerelement~ContainerElement} viewFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\nfunction _startAppearEffect( viewFigure, writer ) {\n\tif ( !viewFigure.hasClass( 'ck-appear' ) ) {\n\t\twriter.addClass( 'ck-appear', viewFigure );\n\t}\n}\n\n// Removes ck-appear class to the image figure if one is not already removed.\n//\n// @param {module:engine/view/containerelement~ContainerElement} viewFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\nfunction _stopAppearEffect( viewFigure, writer ) {\n\twriter.removeClass( 'ck-appear', viewFigure );\n}\n\n// Shows placeholder together with infinite progress bar on given image figure.\n//\n// @param {String} Data-uri with a svg placeholder.\n// @param {module:engine/view/containerelement~ContainerElement} viewFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\nfunction _showPlaceholder( placeholder, viewFigure, writer ) {\n\tif ( !viewFigure.hasClass( 'ck-image-upload-placeholder' ) ) {\n\t\twriter.addClass( 'ck-image-upload-placeholder', viewFigure );\n\t}\n\n\tconst viewImg = viewFigure.getChild( 0 );\n\n\tif ( viewImg.getAttribute( 'src' ) !== placeholder ) {\n\t\twriter.setAttribute( 'src', placeholder, viewImg );\n\t}\n\n\tif ( !_getUIElement( viewFigure, 'placeholder' ) ) {\n\t\twriter.insert( writer.createPositionAfter( viewImg ), _createPlaceholder( writer ) );\n\t}\n}\n\n// Removes placeholder together with infinite progress bar on given image figure.\n//\n// @param {module:engine/view/containerelement~ContainerElement} viewFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\nfunction _hidePlaceholder( viewFigure, writer ) {\n\tif ( viewFigure.hasClass( 'ck-image-upload-placeholder' ) ) {\n\t\twriter.removeClass( 'ck-image-upload-placeholder', viewFigure );\n\t}\n\n\t_removeUIElement( viewFigure, writer, 'placeholder' );\n}\n\n// Shows progress bar displaying upload progress.\n// Attaches it to the file loader to update when upload percentace is changed.\n//\n// @param {module:engine/view/containerelement~ContainerElement} viewFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @param {module:upload/filerepository~FileLoader} loader\n// @param {module:engine/view/view~View} view\nfunction _showProgressBar( viewFigure, writer, loader, view ) {\n\tconst progressBar = _createProgressBar( writer );\n\twriter.insert( writer.createPositionAt( viewFigure, 'end' ), progressBar );\n\n\t// Update progress bar width when uploadedPercent is changed.\n\tloader.on( 'change:uploadedPercent', ( evt, name, value ) => {\n\t\tview.change( writer => {\n\t\t\twriter.setStyle( 'width', value + '%', progressBar );\n\t\t} );\n\t} );\n}\n\n// Hides upload progress bar.\n//\n// @param {module:engine/view/containerelement~ContainerElement} viewFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\nfunction _hideProgressBar( viewFigure, writer ) {\n\t_removeUIElement( viewFigure, writer, 'progressBar' );\n}\n\n// Shows complete icon and hides after a certain amount of time.\n//\n// @param {module:engine/view/containerelement~ContainerElement} viewFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @param {module:engine/view/view~View} view\nfunction _showCompleteIcon( viewFigure, writer, view ) {\n\tconst completeIcon = writer.createUIElement( 'div', { class: 'ck-image-upload-complete-icon' } );\n\n\twriter.insert( writer.createPositionAt( viewFigure, 'end' ), completeIcon );\n\n\tsetTimeout( () => {\n\t\tview.change( writer => writer.remove( writer.createRangeOn( completeIcon ) ) );\n\t}, 3000 );\n}\n\n// Create progress bar element using {@link module:engine/view/uielement~UIElement}.\n//\n// @private\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @returns {module:engine/view/uielement~UIElement}\nfunction _createProgressBar( writer ) {\n\tconst progressBar = writer.createUIElement( 'div', { class: 'ck-progress-bar' } );\n\n\twriter.setCustomProperty( 'progressBar', true, progressBar );\n\n\treturn progressBar;\n}\n\n// Create placeholder element using {@link module:engine/view/uielement~UIElement}.\n//\n// @private\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @returns {module:engine/view/uielement~UIElement}\nfunction _createPlaceholder( writer ) {\n\tconst placeholder = writer.createUIElement( 'div', { class: 'ck-upload-placeholder-loader' } );\n\n\twriter.setCustomProperty( 'placeholder', true, placeholder );\n\n\treturn placeholder;\n}\n\n// Returns {@link module:engine/view/uielement~UIElement} of given unique property from image figure element.\n// Returns `undefined` if element is not found.\n//\n// @private\n// @param {module:engine/view/element~Element} imageFigure\n// @param {String} uniqueProperty\n// @returns {module:engine/view/uielement~UIElement|undefined}\nfunction _getUIElement( imageFigure, uniqueProperty ) {\n\tfor ( const child of imageFigure.getChildren() ) {\n\t\tif ( child.getCustomProperty( uniqueProperty ) ) {\n\t\t\treturn child;\n\t\t}\n\t}\n}\n\n// Removes {@link module:engine/view/uielement~UIElement} of given unique property from image figure element.\n//\n// @private\n// @param {module:engine/view/element~Element} imageFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @param {String} uniqueProperty\nfunction _removeUIElement( viewFigure, writer, uniqueProperty ) {\n\tconst element = _getUIElement( viewFigure, uniqueProperty );\n\n\tif ( element ) {\n\t\twriter.remove( writer.createRangeOn( element ) );\n\t}\n}\n\n// Displays local data from file loader.\n//\n// @param {module:engine/view/element~Element} imageFigure\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @param {module:upload/filerepository~FileLoader} loader\nfunction _displayLocalImage( viewFigure, writer, loader ) {\n\tif ( loader.data ) {\n\t\tconst viewImg = viewFigure.getChild( 0 );\n\n\t\twriter.setAttribute( 'src', loader.data, viewImg );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/notification/notification\n */\n\n/* globals window */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\n/**\n * The Notification plugin.\n *\n * This plugin sends a few types of notifications: `success`, `info` and `warning`. The notifications need to be\n * handled and displayed by a plugin responsible for showing the UI of the notifications. Using this plugin for dispatching\n * notifications makes it possible to switch the notifications UI.\n *\n * Note that every unhandled and not stopped `warning` notification will be displayed as a system alert.\n * See {@link module:ui/notification/notification~Notification#showWarning}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Notification extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Notification';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\t// Each unhandled and not stopped `show:warning` event is displayed as a system alert.\n\t\tthis.on( 'show:warning', ( evt, data ) => {\n\t\t\twindow.alert( data.message ); // eslint-disable-line no-alert\n\t\t}, { priority: 'lowest' } );\n\t}\n\n\t/**\n\t * Shows a success notification.\n\t *\n\t * By default, it fires the {@link #event:show:success `show:success` event} with the given `data`. The event namespace can be extended\n\t * using the `data.namespace` option. For example:\n\t *\n\t * \t\tshowSuccess( 'Image is uploaded.', {\n\t * \t\t\tnamespace: 'upload:image'\n\t * \t\t} );\n\t *\n\t * will fire the `show:success:upload:image` event.\n\t *\n\t * You can provide the title of the notification:\n\t *\n\t *\t\tshowSuccess( 'Image is uploaded.', {\n\t *\t\t\ttitle: 'Image upload success'\n\t *\t\t} );\n\t *\n\t * @param {String} message The content of the notification.\n\t * @param {Object} [data={}] Additional data.\n\t * @param {String} [data.namespace] Additional event namespace.\n\t * @param {String} [data.title] The title of the notification.\n\t */\n\tshowSuccess( message, data = {} ) {\n\t\tthis._showNotification( {\n\t\t\tmessage,\n\t\t\ttype: 'success',\n\t\t\tnamespace: data.namespace,\n\t\t\ttitle: data.title\n\t\t} );\n\t}\n\n\t/**\n\t * Shows an information notification.\n\t *\n\t * By default, it fires the {@link #event:show:info `show:info` event} with the given `data`. The event namespace can be extended\n\t * using the `data.namespace` option. For example:\n\t *\n\t * \t\tshowInfo( 'Editor is offline.', {\n\t * \t\t\tnamespace: 'editor:status'\n\t * \t\t} );\n\t *\n\t * will fire the `show:info:editor:status` event.\n\t *\n\t * You can provide the title of the notification:\n\t *\n\t *\t\tshowInfo( 'Editor is offline.', {\n\t *\t\t\ttitle: 'Network information'\n\t *\t\t} );\n\t *\n\t * @param {String} message The content of the notification.\n\t * @param {Object} [data={}] Additional data.\n\t * @param {String} [data.namespace] Additional event namespace.\n\t * @param {String} [data.title] The title of the notification.\n\t */\n\tshowInfo( message, data = {} ) {\n\t\tthis._showNotification( {\n\t\t\tmessage,\n\t\t\ttype: 'info',\n\t\t\tnamespace: data.namespace,\n\t\t\ttitle: data.title\n\t\t} );\n\t}\n\n\t/**\n\t * Shows a warning notification.\n\t *\n\t * By default, it fires the {@link #event:show:warning `show:warning` event}\n\t * with the given `data`. The event namespace can be extended using the `data.namespace` option. For example:\n\t *\n\t * \t\tshowWarning( 'Image upload error.', {\n\t * \t\t\tnamespace: 'upload:image'\n\t * \t\t} );\n\t *\n\t * will fire the `show:warning:upload:image` event.\n\t *\n\t * You can provide the title of the notification:\n\t *\n\t *\t\tshowWarning( 'Image upload error.', {\n\t *\t\t\ttitle: 'Upload failed'\n\t *\t\t} );\n\t *\n\t * Note that each unhandled and not stopped `warning` notification will be displayed as a system alert.\n\t * The plugin responsible for displaying warnings should `stop()` the event to prevent displaying it as an alert:\n\t *\n\t * \t\tnotifications.on( 'show:warning', ( evt, data ) => {\n\t * \t\t\t// Do something with the data.\n\t *\n\t * \t\t\t// Stop this event to prevent displaying it as an alert.\n\t * \t\t\tevt.stop();\n\t * \t\t} );\n\t *\n\t * You can attach many listeners to the same event and `stop()` this event in a listener with a low priority:\n\t *\n\t * \t\tnotifications.on( 'show:warning', ( evt, data ) => {\n\t * \t\t\t// Show the warning in the UI, but do not stop it.\n\t * \t\t} );\n\t *\n\t * \t\tnotifications.on( 'show:warning', ( evt, data ) => {\n\t * \t\t\t// Log the warning to some error tracker.\n\t *\n\t * \t\t\t// Stop this event to prevent displaying it as an alert.\n\t * \t\t\tevt.stop();\n\t * \t\t}, { priority: 'low' } );\n\t *\n\t * @param {String} message The content of the notification.\n\t * @param {Object} [data={}] Additional data.\n\t * @param {String} [data.namespace] Additional event namespace.\n\t * @param {String} [data.title] The title of the notification.\n\t */\n\tshowWarning( message, data = {} ) {\n\t\tthis._showNotification( {\n\t\t\tmessage,\n\t\t\ttype: 'warning',\n\t\t\tnamespace: data.namespace,\n\t\t\ttitle: data.title\n\t\t} );\n\t}\n\n\t/**\n\t * Fires the `show` event with the specified type, namespace and message.\n\t *\n\t * @private\n\t * @param {Object} data The message data.\n\t * @param {String} data.message The content of the notification.\n\t * @param {'success'|'info'|'warning'} data.type The type of the message.\n\t * @param {String} [data.namespace] Additional event namespace.\n\t * @param {String} [data.title=''] The title of the notification.\n\t */\n\t_showNotification( data ) {\n\t\tconst event = `show:${ data.type }` + ( data.namespace ? `:${ data.namespace }` : '' );\n\n\t\tthis.fire( event, {\n\t\t\tmessage: data.message,\n\t\t\ttype: data.type,\n\t\t\ttitle: data.title || ''\n\t\t} );\n\t}\n\n\t/**\n\t * Fired when one of the `showSuccess()`, `showInfo()`, `showWarning()` methods is called.\n\t *\n\t * @event show\n\t * @param {Object} data The notification data.\n\t * @param {String} data.message The content of the notification.\n\t * @param {String} data.title The title of the notification.\n\t * @param {'success'|'info'|'warning'} data.type The type of the notification.\n\t */\n\n\t/**\n\t * Fired when the `showSuccess()` method is called.\n\t *\n\t * @event show:success\n\t * @param {Object} data The notification data.\n\t * @param {String} data.message The content of the notification.\n\t * @param {String} data.title The title of the notification.\n\t * @param {'success'} data.type The type of the notification.\n\t */\n\n\t/**\n\t * Fired when the `showInfo()` method is called.\n\t *\n\t * @event show:info\n\t * @param {Object} data The notification data.\n\t * @param {String} data.message The content of the notification.\n\t * @param {String} data.title The title of the notification.\n\t * @param {'info'} data.type The type of the notification.\n\t */\n\n\t/**\n\t * Fired when the `showWarning()` method is called.\n\t *\n\t * When this event is not handled or stopped by `event.stop()`, the `data.message` of this event will\n\t * be automatically displayed as a system alert.\n\t *\n\t * @event show:warning\n\t * @param {Object} data The notification data.\n\t * @param {String} data.message The content of the notification.\n\t * @param {String} data.title The title of the notification.\n\t * @param {'warning'} data.type The type of the notification.\n\t */\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 clipboard/datatransfer\n */\n\n/**\n * Facade over the native [`DataTransfer`](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer) object.\n */\nexport default class DataTransfer {\n\tconstructor( nativeDataTransfer ) {\n\t\t/**\n\t\t * The array of files created from the native `DataTransfer#files` or `DataTransfer#items`.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Array.<File>} #files\n\t\t */\n\t\tthis.files = getFiles( nativeDataTransfer );\n\n\t\t/**\n\t\t * The native DataTransfer object.\n\t\t *\n\t\t * @private\n\t\t * @member {DataTransfer} #_native\n\t\t */\n\t\tthis._native = nativeDataTransfer;\n\t}\n\n\t/**\n\t * Returns an array of available native content types.\n\t *\n\t * @returns {Array.<String>}\n\t */\n\tget types() {\n\t\treturn this._native.types;\n\t}\n\n\t/**\n\t * Gets data from the data transfer by its mime type.\n\t *\n\t *\t\tdataTransfer.getData( 'text/plain' );\n\t *\n\t * @param {String} type The mime type. E.g. `text/html` or `text/plain`.\n\t * @returns {String}\n\t */\n\tgetData( type ) {\n\t\treturn this._native.getData( type );\n\t}\n\n\t/**\n\t * Sets data in the data transfer.\n\t *\n\t * @param {String} type The mime type. E.g. `text/html` or `text/plain`.\n\t * @param {String} data\n\t */\n\tsetData( type, data ) {\n\t\tthis._native.setData( type, data );\n\t}\n}\n\nfunction getFiles( nativeDataTransfer ) {\n\t// DataTransfer.files and items are Array-like and might not have an iterable interface.\n\tconst files = nativeDataTransfer.files ? Array.from( nativeDataTransfer.files ) : [];\n\tconst items = nativeDataTransfer.items ? Array.from( nativeDataTransfer.items ) : [];\n\n\tif ( files.length ) {\n\t\treturn files;\n\t}\n\t// Chrome have empty DataTransfer.files, but let get files through the items interface.\n\treturn items\n\t\t.filter( item => item.kind === 'file' )\n\t\t.map( item => item.getAsFile() );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 clipboard/clipboardobserver\n */\n\nimport DomEventObserver from '@ckeditor/ckeditor5-engine/src/view/observer/domeventobserver';\nimport EventInfo from '@ckeditor/ckeditor5-utils/src/eventinfo';\nimport DataTransfer from './datatransfer';\n\n/**\n * Clipboard events observer.\n *\n * Fires the following events:\n *\n * * {@link module:engine/view/document~Document#event:clipboardInput}\n * * {@link module:engine/view/document~Document#event:dragover}\n * * {@link module:engine/view/document~Document#event:drop}\n * * {@link module:engine/view/document~Document#event:paste}\n * * {@link module:engine/view/document~Document#event:copy}\n * * {@link module:engine/view/document~Document#event:cut}\n *\n * Note that this observer is not available by default (it is not added by the engine).\n * To make it available it needs to be added to {@link module:engine/view/document~Document} by\n * the {@link module:engine/view/view~View#addObserver `View#addObserver()`} method. You can also load the\n * {@link module:clipboard/clipboard~Clipboard} plugin which adds this observer automatically (because it uses it).\n *\n * @extends module:engine/view/observer/domeventobserver~DomEventObserver\n */\nexport default class ClipboardObserver extends DomEventObserver {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tconst viewDocument = this.document;\n\n\t\tthis.domEventType = [ 'paste', 'copy', 'cut', 'drop', 'dragover' ];\n\n\t\tthis.listenTo( viewDocument, 'paste', handleInput, { priority: 'low' } );\n\t\tthis.listenTo( viewDocument, 'drop', handleInput, { priority: 'low' } );\n\n\t\tfunction handleInput( evt, data ) {\n\t\t\tdata.preventDefault();\n\n\t\t\tconst targetRanges = data.dropRange ? [ data.dropRange ] : Array.from( viewDocument.selection.getRanges() );\n\n\t\t\tconst eventInfo = new EventInfo( viewDocument, 'clipboardInput' );\n\n\t\t\tviewDocument.fire( eventInfo, {\n\t\t\t\tdataTransfer: data.dataTransfer,\n\t\t\t\ttargetRanges\n\t\t\t} );\n\n\t\t\t// If CKEditor handled the input, do not bubble the original event any further.\n\t\t\t// This helps external integrations recognize that fact and act accordingly.\n\t\t\t// https://github.com/ckeditor/ckeditor5-upload/issues/92\n\t\t\tif ( eventInfo.stop.called ) {\n\t\t\t\tdata.stopPropagation();\n\t\t\t}\n\t\t}\n\t}\n\n\tonDomEvent( domEvent ) {\n\t\tconst evtData = {\n\t\t\tdataTransfer: new DataTransfer( domEvent.clipboardData ? domEvent.clipboardData : domEvent.dataTransfer )\n\t\t};\n\n\t\tif ( domEvent.type == 'drop' ) {\n\t\t\tevtData.dropRange = getDropViewRange( this.view, domEvent );\n\t\t}\n\n\t\tthis.fire( domEvent.type, domEvent, evtData );\n\t}\n}\n\nfunction getDropViewRange( view, domEvent ) {\n\tconst domDoc = domEvent.target.ownerDocument;\n\tconst x = domEvent.clientX;\n\tconst y = domEvent.clientY;\n\tlet domRange;\n\n\t// Webkit & Blink.\n\tif ( domDoc.caretRangeFromPoint && domDoc.caretRangeFromPoint( x, y ) ) {\n\t\tdomRange = domDoc.caretRangeFromPoint( x, y );\n\t}\n\t// FF.\n\telse if ( domEvent.rangeParent ) {\n\t\tdomRange = domDoc.createRange();\n\t\tdomRange.setStart( domEvent.rangeParent, domEvent.rangeOffset );\n\t\tdomRange.collapse( true );\n\t}\n\n\tif ( domRange ) {\n\t\treturn view.domConverter.domRangeToView( domRange );\n\t} else {\n\t\treturn view.document.selection.getFirstRange();\n\t}\n}\n\n/**\n * Fired as a continuation of {@link #event:paste} and {@link #event:drop} events.\n *\n * It is a part of the {@glink framework/guides/deep-dive/clipboard#input-pipeline \"clipboard input pipeline\"}.\n *\n * Fired with a `dataTransfer` which comes from the clipboard and which content should be processed\n * and inserted into the editor.\n *\n * Note that this event is not available by default. To make it available {@link module:clipboard/clipboardobserver~ClipboardObserver}\n * needs to be added to {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.\n * It's done by the {@link module:clipboard/clipboard~Clipboard} feature. If it's not loaded, it must be done manually.\n *\n * @see module:clipboard/clipboardobserver~ClipboardObserver\n * @see module:clipboard/clipboard~Clipboard\n * @event module:engine/view/document~Document#event:clipboardInput\n * @param {Object} data Event data.\n * @param {module:clipboard/datatransfer~DataTransfer} data.dataTransfer Data transfer instance.\n * @param {Array.<module:engine/view/range~Range>} data.targetRanges Ranges which are the target of the operation\n * (usually – into which the content should be inserted).\n * If clipboard input was triggered by a paste operation, then these are the selection ranges. If by a drop operation,\n * then it's the drop position (which can be different than the selection at the moment of drop).\n */\n\n/**\n * Fired when user drags content over one of the editables.\n *\n * Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.\n *\n * Note that this event is not available by default. To make it available {@link module:clipboard/clipboardobserver~ClipboardObserver}\n * needs to be added to {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.\n * It's done by the {@link module:clipboard/clipboard~Clipboard} feature. If it's not loaded, it must be done manually.\n *\n * @see module:engine/view/document~Document#event:clipboardInput\n * @event module:engine/view/document~Document#event:dragover\n * @param {module:clipboard/clipboardobserver~ClipboardEventData} data Event data.\n */\n\n/**\n * Fired when user dropped content into one of the editables.\n *\n * Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.\n *\n * Note that this event is not available by default. To make it available {@link module:clipboard/clipboardobserver~ClipboardObserver}\n * needs to be added to {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.\n * It's done by the {@link module:clipboard/clipboard~Clipboard} feature. If it's not loaded, it must be done manually.\n *\n * @see module:engine/view/document~Document#event:clipboardInput\n * @event module:engine/view/document~Document#event:drop\n * @param {module:clipboard/clipboardobserver~ClipboardEventData} data Event data.\n * @param {module:engine/view/range~Range} dropRange The position into which the content is dropped.\n */\n\n/**\n * Fired when user pasted content into one of the editables.\n *\n * Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.\n *\n * Note that this event is not available by default. To make it available {@link module:clipboard/clipboardobserver~ClipboardObserver}\n * needs to be added to {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.\n * It's done by the {@link module:clipboard/clipboard~Clipboard} feature. If it's not loaded, it must be done manually.\n *\n * @see module:engine/view/document~Document#event:clipboardInput\n * @event module:engine/view/document~Document#event:paste\n * @param {module:clipboard/clipboardobserver~ClipboardEventData} data Event data.\n */\n\n/**\n * Fired when user copied content from one of the editables.\n *\n * Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.\n *\n * Note that this event is not available by default. To make it available {@link module:clipboard/clipboardobserver~ClipboardObserver}\n * needs to be added to {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.\n * It's done by the {@link module:clipboard/clipboard~Clipboard} feature. If it's not loaded, it must be done manually.\n *\n * @see module:clipboard/clipboardobserver~ClipboardObserver\n * @event module:engine/view/document~Document#event:copy\n * @param {module:clipboard/clipboardobserver~ClipboardEventData} data Event data.\n */\n\n/**\n * Fired when user cut content from one of the editables.\n *\n * Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.\n *\n * Note that this event is not available by default. To make it available {@link module:clipboard/clipboardobserver~ClipboardObserver}\n * needs to be added to {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.\n * It's done by the {@link module:clipboard/clipboard~Clipboard} feature. If it's not loaded, it must be done manually.\n *\n * @see module:clipboard/clipboardobserver~ClipboardObserver\n * @event module:engine/view/document~Document#event:cut\n * @param {module:clipboard/clipboardobserver~ClipboardEventData} data Event data.\n */\n\n/**\n * The value of the {@link module:engine/view/document~Document#event:paste},\n * {@link module:engine/view/document~Document#event:copy} and {@link module:engine/view/document~Document#event:cut} events.\n *\n * In order to access clipboard data use `dataTransfer` property.\n *\n * @class module:clipboard/clipboardobserver~ClipboardEventData\n * @extends module:engine/view/observer/domeventdata~DomEventData\n */\n\n/**\n * Data transfer instance.\n *\n * @readonly\n * @member {module:clipboard/datatransfer~DataTransfer} module:clipboard/clipboardobserver~ClipboardEventData#dataTransfer\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 clipboard/utils/viewtoplaintext\n */\n\n// Elements which should not have empty-line padding.\n// Most `view.ContainerElement` want to be separate by new-line, but some are creating one structure\n// together (like `<li>`) so it is better to separate them by only one \"\\n\".\nconst smallPaddingElements = [ 'figcaption', 'li' ];\n\n/**\n * Converts {@link module:engine/view/item~Item view item} and all of its children to plain text.\n *\n * @param {module:engine/view/item~Item} viewItem View item to convert.\n * @returns {String} Plain text representation of `viewItem`.\n */\nexport default function viewToPlainText( viewItem ) {\n\tlet text = '';\n\n\tif ( viewItem.is( 'text' ) || viewItem.is( 'textProxy' ) ) {\n\t\t// If item is `Text` or `TextProxy` simple take its text data.\n\t\ttext = viewItem.data;\n\t} else if ( viewItem.is( 'img' ) && viewItem.hasAttribute( 'alt' ) ) {\n\t\t// Special case for images - use alt attribute if it is provided.\n\t\ttext = viewItem.getAttribute( 'alt' );\n\t} else {\n\t\t// Other elements are document fragments, attribute elements or container elements.\n\t\t// They don't have their own text value, so convert their children.\n\t\tlet prev = null;\n\n\t\tfor ( const child of viewItem.getChildren() ) {\n\t\t\tconst childText = viewToPlainText( child );\n\n\t\t\t// Separate container element children with one or more new-line characters.\n\t\t\tif ( prev && ( prev.is( 'containerElement' ) || child.is( 'containerElement' ) ) ) {\n\t\t\t\tif ( smallPaddingElements.includes( prev.name ) || smallPaddingElements.includes( child.name ) ) {\n\t\t\t\t\ttext += '\\n';\n\t\t\t\t} else {\n\t\t\t\t\ttext += '\\n\\n';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttext += childText;\n\t\t\tprev = child;\n\t\t}\n\t}\n\n\treturn text;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 clipboard/clipboard\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport ClipboardObserver from './clipboardobserver';\n\nimport plainTextToHtml from './utils/plaintexttohtml';\nimport normalizeClipboardHtml from './utils/normalizeclipboarddata';\nimport viewToPlainText from './utils/viewtoplaintext.js';\n\nimport HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';\n\n/**\n * The clipboard feature. It is responsible for intercepting the `paste` and `drop` events and\n * passing the pasted content through the clipboard pipeline in order to insert it into the editor's content.\n * It also handles the `cut` and `copy` events to fill the native clipboard with serialized editor's data.\n *\n * Read more about the clipboard integration in {@glink framework/guides/deep-dive/clipboard \"Clipboard\" deep dive} guide.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Clipboard extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Clipboard';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst modelDocument = editor.model.document;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\n\t\t/**\n\t\t * Data processor used to convert pasted HTML to a view structure.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/dataprocessor/htmldataprocessor~HtmlDataProcessor} #_htmlDataProcessor\n\t\t */\n\t\tthis._htmlDataProcessor = new HtmlDataProcessor();\n\n\t\tview.addObserver( ClipboardObserver );\n\n\t\t// The clipboard paste pipeline.\n\n\t\t// Pasting and dropping is disabled when editor is read-only.\n\t\t// See: https://github.com/ckeditor/ckeditor5-clipboard/issues/26.\n\t\tthis.listenTo( viewDocument, 'clipboardInput', evt => {\n\t\t\tif ( editor.isReadOnly ) {\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t}, { priority: 'highest' } );\n\n\t\tthis.listenTo( viewDocument, 'clipboardInput', ( evt, data ) => {\n\t\t\tconst dataTransfer = data.dataTransfer;\n\t\t\tlet content = '';\n\n\t\t\tif ( dataTransfer.getData( 'text/html' ) ) {\n\t\t\t\tcontent = normalizeClipboardHtml( dataTransfer.getData( 'text/html' ) );\n\t\t\t} else if ( dataTransfer.getData( 'text/plain' ) ) {\n\t\t\t\tcontent = plainTextToHtml( dataTransfer.getData( 'text/plain' ) );\n\t\t\t}\n\n\t\t\tcontent = this._htmlDataProcessor.toView( content );\n\n\t\t\tthis.fire( 'inputTransformation', { content, dataTransfer } );\n\n\t\t\tview.scrollToTheSelection();\n\t\t}, { priority: 'low' } );\n\n\t\tthis.listenTo( this, 'inputTransformation', ( evt, data ) => {\n\t\t\tif ( !data.content.isEmpty ) {\n\t\t\t\tconst dataController = this.editor.data;\n\t\t\t\tconst model = this.editor.model;\n\n\t\t\t\t// Convert the pasted content to a model document fragment.\n\t\t\t\t// Conversion is contextual, but in this case we need an \"all allowed\" context and for that\n\t\t\t\t// we use the $clipboardHolder item.\n\t\t\t\tconst modelFragment = dataController.toModel( data.content, '$clipboardHolder' );\n\n\t\t\t\tif ( modelFragment.childCount == 0 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tmodel.insertContent( modelFragment );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\n\t\t// The clipboard copy/cut pipeline.\n\n\t\tfunction onCopyCut( evt, data ) {\n\t\t\tconst dataTransfer = data.dataTransfer;\n\n\t\t\tdata.preventDefault();\n\n\t\t\tconst content = editor.data.toView( editor.model.getSelectedContent( modelDocument.selection ) );\n\n\t\t\tviewDocument.fire( 'clipboardOutput', { dataTransfer, content, method: evt.name } );\n\t\t}\n\n\t\tthis.listenTo( viewDocument, 'copy', onCopyCut, { priority: 'low' } );\n\t\tthis.listenTo( viewDocument, 'cut', ( evt, data ) => {\n\t\t\t// Cutting is disabled when editor is read-only.\n\t\t\t// See: https://github.com/ckeditor/ckeditor5-clipboard/issues/26.\n\t\t\tif ( editor.isReadOnly ) {\n\t\t\t\tdata.preventDefault();\n\t\t\t} else {\n\t\t\t\tonCopyCut( evt, data );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\n\t\tthis.listenTo( viewDocument, 'clipboardOutput', ( evt, data ) => {\n\t\t\tif ( !data.content.isEmpty ) {\n\t\t\t\tdata.dataTransfer.setData( 'text/html', this._htmlDataProcessor.toData( data.content ) );\n\t\t\t\tdata.dataTransfer.setData( 'text/plain', viewToPlainText( data.content ) );\n\t\t\t}\n\n\t\t\tif ( data.method == 'cut' ) {\n\t\t\t\teditor.model.deleteContent( modelDocument.selection );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\t}\n}\n\n/**\n * Fired with a `content` and `dataTransfer` objects. The `content` which comes from the clipboard (was pasted or dropped)\n * should be processed in order to be inserted into the editor. The `dataTransfer` object is available\n * in case the transformation functions needs access to a raw clipboard data.\n *\n * It is a part of the {@glink framework/guides/deep-dive/clipboard#input-pipeline \"clipboard input pipeline\"}.\n *\n * @see module:clipboard/clipboardobserver~ClipboardObserver\n * @see module:clipboard/clipboard~Clipboard\n * @event module:clipboard/clipboard~Clipboard#event:inputTransformation\n * @param {Object} data Event data.\n * @param {module:engine/view/documentfragment~DocumentFragment} data.content Event data. Content to be inserted into the editor.\n * It can be modified by the event listeners. Read more about the clipboard pipelines in\n * {@glink framework/guides/deep-dive/clipboard \"Clipboard\" deep dive}.\n * @param {module:clipboard/datatransfer~DataTransfer} data.dataTransfer Data transfer instance.\n */\n\n/**\n * Fired on {@link module:engine/view/document~Document#event:copy} and {@link module:engine/view/document~Document#event:cut}\n * with a copy of selected content. The content can be processed before it ends up in the clipboard.\n *\n * It is a part of the {@glink framework/guides/deep-dive/clipboard#output-pipeline \"clipboard output pipeline\"}.\n *\n * @see module:clipboard/clipboardobserver~ClipboardObserver\n * @see module:clipboard/clipboard~Clipboard\n * @event module:engine/view/document~Document#event:clipboardOutput\n * @param {module:clipboard/clipboard~ClipboardOutputEventData} data Event data.\n */\n\n/**\n * The value of the {@link module:engine/view/document~Document#event:clipboardOutput} event.\n *\n * @class module:clipboard/clipboard~ClipboardOutputEventData\n */\n\n/**\n * Data transfer instance.\n *\n * @readonly\n * @member {module:clipboard/datatransfer~DataTransfer} module:clipboard/clipboard~ClipboardOutputEventData#dataTransfer\n */\n\n/**\n * Content to be put into the clipboard. It can be modified by the event listeners.\n * Read more about the clipboard pipelines in {@glink framework/guides/deep-dive/clipboard \"Clipboard\" deep dive}.\n *\n * @member {module:engine/view/documentfragment~DocumentFragment} module:clipboard/clipboard~ClipboardOutputEventData#content\n */\n\n/**\n * Whether the event was triggered by copy or cut operation.\n *\n * @member {'copy'|'cut'} module:clipboard/clipboard~ClipboardOutputEventData#method\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 clipboard/utils/normalizeclipboarddata\n */\n\n/**\n * Removes some popular browser quirks out of the clipboard data (HTML).\n *\n * @param {String} data The HTML data to normalize.\n * @returns {String} Normalized HTML.\n */\nexport default function normalizeClipboardData( data ) {\n\treturn data\n\t\t.replace( /<span(?: class=\"Apple-converted-space\"|)>(\\s+)<\\/span>/g, ( fullMatch, spaces ) => {\n\t\t\t// Handle the most popular and problematic case when even a single space becomes an nbsp;.\n\t\t\t// Decode those to normal spaces. Read more in https://github.com/ckeditor/ckeditor5-clipboard/issues/2.\n\t\t\tif ( spaces.length == 1 ) {\n\t\t\t\treturn ' ';\n\t\t\t}\n\n\t\t\treturn spaces;\n\t\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 clipboard/utils/plaintexttohtml\n */\n\n/**\n * Converts plain text to its HTML-ized version.\n *\n * @param {String} text The plain text to convert.\n * @returns {String} HTML generated from the plain text.\n */\nexport default function plainTextToHtml( text ) {\n\ttext = text\n\t\t// Encode <>.\n\t\t.replace( /</g, '&lt;' )\n\t\t.replace( />/g, '&gt;' )\n\t\t// Creates paragraphs for every line breaks.\n\t\t.replace( /\\n/g, '</p><p>' )\n\t\t// Preserve trailing spaces (only the first and last one – the rest is handled below).\n\t\t.replace( /^\\s/, '&nbsp;' )\n\t\t.replace( /\\s$/, '&nbsp;' )\n\t\t// Preserve other subsequent spaces now.\n\t\t.replace( /\\s\\s/g, ' &nbsp;' );\n\n\tif ( text.indexOf( '</p><p>' ) > -1 ) {\n\t\t// If we created paragraphs above, add the trailing ones.\n\t\ttext = `<p>${ text }</p>`;\n\t}\n\n\t// TODO:\n\t// * What about '\\nfoo' vs ' foo'?\n\n\treturn text;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 module:engine/view/upcastwriter\n */\n\nimport DocumentFragment from './documentfragment';\nimport Element from './element';\nimport Text from './text';\nimport { isPlainObject } from 'lodash-es';\nimport Position from './position';\nimport Range from './range';\nimport Selection from './selection';\n\n/**\n * View upcast writer. It provides a set of methods used to manipulate non-semantic view trees.\n *\n * It should be used only while working on a non-semantic view\n * (e.g. a view created from HTML string on paste).\n * To manipulate a view which was or is being downcasted from the the model use the\n * {@link module:engine/view/downcastwriter~DowncastWriter downcast writer}.\n *\n * Read more about changing the view in the {@glink framework/guides/architecture/editing-engine#changing-the-view Changing the view}\n * section of the {@glink framework/guides/architecture/editing-engine Editing engine architecture} guide.\n *\n * Unlike `DowncastWriter`, which is available in the {@link module:engine/view/view~View#change `View#change()`} block,\n * `UpcastWriter` can be created wherever you need it:\n *\n *\t\tconst writer = new UpcastWriter();\n *\t\tconst text = writer.createText( 'foo!' );\n *\n *\t\twriter.appendChild( text, someViewElement );\n */\nexport default class UpcastWriter {\n\t/**\n\t * Creates a new {@link module:engine/view/documentfragment~DocumentFragment} instance.\n\t *\n\t * @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]\n\t * A list of nodes to be inserted into the created document fragment.\n\t * @returns {module:engine/view/documentfragment~DocumentFragment} The created document fragment.\n\t */\n\tcreateDocumentFragment( children ) {\n\t\treturn new DocumentFragment( children );\n\t}\n\n\t/**\n\t * Creates a new {@link module:engine/view/element~Element} instance.\n\t *\n\t * Attributes can be passed in various formats:\n\t *\n\t *\t\tupcastWriter.createElement( 'div', { class: 'editor', contentEditable: 'true' } ); // object\n\t *\t\tupcastWriter.createElement( 'div', [ [ 'class', 'editor' ], [ 'contentEditable', 'true' ] ] ); // map-like iterator\n\t *\t\tupcastWriter.createElement( 'div', mapOfAttributes ); // map\n\t *\n\t * @param {String} name Node name.\n\t * @param {Object|Iterable} [attrs] Collection of attributes.\n\t * @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]\n\t * A list of nodes to be inserted into created element.\n\t * @returns {module:engine/view/element~Element} Created element.\n\t */\n\tcreateElement( name, attrs, children ) {\n\t\treturn new Element( name, attrs, children );\n\t}\n\n\t/**\n\t * Creates a new {@link module:engine/view/text~Text} instance.\n\t *\n\t * @param {String} data The text's data.\n\t * @returns {module:engine/view/text~Text} The created text node.\n\t */\n\tcreateText( data ) {\n\t\treturn new Text( data );\n\t}\n\n\t/**\n\t * Clones the provided element.\n\t *\n\t * @see module:engine/view/element~Element#_clone\n\t * @param {module:engine/view/element~Element} element Element to be cloned.\n\t * @param {Boolean} [deep=false] If set to `true` clones element and all its children recursively. When set to `false`,\n\t * element will be cloned without any children.\n\t * @returns {module:engine/view/element~Element} Clone of this element.\n\t */\n\tclone( element, deep = false ) {\n\t\treturn element._clone( deep );\n\t}\n\n\t/**\n\t * Appends a child node or a list of child nodes at the end of this node\n\t * and sets the parent of these nodes to this element.\n\t *\n\t * @see module:engine/view/element~Element#_appendChild\n\t * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.\n\t * @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} element Element\n\t * to which items will be appended.\n\t * @fires module:engine/view/node~Node#event:change\n\t * @returns {Number} Number of appended nodes.\n\t */\n\tappendChild( items, element ) {\n\t\treturn element._appendChild( items );\n\t}\n\n\t/**\n\t * Inserts a child node or a list of child nodes on the given index and sets the parent of these nodes to\n\t * this element.\n\t *\n\t * @see module:engine/view/element~Element#_insertChild\n\t * @param {Number} index Offset at which nodes should be inserted.\n\t * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.\n\t * @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} element Element\n\t * to which items will be inserted.\n\t * @fires module:engine/view/node~Node#event:change\n\t * @returns {Number} Number of inserted nodes.\n\t */\n\tinsertChild( index, items, element ) {\n\t\treturn element._insertChild( index, items );\n\t}\n\n\t/**\n\t * Removes the given number of child nodes starting at the given index and set the parent of these nodes to `null`.\n\t *\n\t * @see module:engine/view/element~Element#_removeChildren\n\t * @param {Number} index Offset from which nodes will be removed.\n\t * @param {Number} howMany Number of nodes to remove.\n\t * @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} element Element\n\t * which children will be removed.\n\t * @fires module:engine/view/node~Node#event:change\n\t * @returns {Array.<module:engine/view/node~Node>} The array containing removed nodes.\n\t */\n\tremoveChildren( index, howMany, element ) {\n\t\treturn element._removeChildren( index, howMany );\n\t}\n\n\t/**\n\t * Removes given element from the view structure. Will not have effect on detached elements.\n\t *\n\t * @param {module:engine/view/element~Element} element Element which will be removed.\n\t * @returns {Array.<module:engine/view/node~Node>} The array containing removed nodes.\n\t */\n\tremove( element ) {\n\t\tconst parent = element.parent;\n\n\t\tif ( parent ) {\n\t\t\treturn this.removeChildren( parent.getChildIndex( element ), 1, parent );\n\t\t}\n\n\t\treturn [];\n\t}\n\n\t/**\n\t * Replaces given element with the new one in the view structure. Will not have effect on detached elements.\n\t *\n\t * @param {module:engine/view/element~Element} oldElement Element which will be replaced.\n\t * @param {module:engine/view/element~Element} newElement Element which will be inserted in the place of the old element.\n\t * @returns {Boolean} Whether old element was successfully replaced.\n\t */\n\treplace( oldElement, newElement ) {\n\t\tconst parent = oldElement.parent;\n\n\t\tif ( parent ) {\n\t\t\tconst index = parent.getChildIndex( oldElement );\n\n\t\t\tthis.removeChildren( index, 1, parent );\n\t\t\tthis.insertChild( index, newElement, parent );\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Removes given element from view structure and places its children in its position.\n\t * It does nothing if element has no parent.\n\t *\n\t * @param {module:engine/view/element~Element} element Element to unwrap.\n\t */\n\tunwrapElement( element ) {\n\t\tconst parent = element.parent;\n\n\t\tif ( parent ) {\n\t\t\tconst index = parent.getChildIndex( element );\n\n\t\t\tthis.remove( element );\n\t\t\tthis.insertChild( index, element.getChildren(), parent );\n\t\t}\n\t}\n\n\t/**\n\t * Renames element by creating a copy of a given element but with its name changed and then moving contents of the\n\t * old element to the new one.\n\t *\n\t * Since this function creates a new element and removes the given one, the new element is returned to keep reference.\n\t *\n\t * @param {String} newName New element name.\n\t * @param {module:engine/view/element~Element} element Element to be renamed.\n\t * @returns {module:engine/view/element~Element|null} New element or null if the old element\n\t * was not replaced (happens for detached elements).\n\t */\n\trename( newName, element ) {\n\t\tconst newElement = new Element( newName, element.getAttributes(), element.getChildren() );\n\n\t\treturn this.replace( element, newElement ) ? newElement : null;\n\t}\n\n\t/**\n\t * Adds or overwrites element's attribute with a specified key and value.\n\t *\n\t *\t\twriter.setAttribute( linkElement, 'href', 'http://ckeditor.com' );\n\t *\n\t * @see module:engine/view/element~Element#_setAttribute\n\t * @param {String} key Attribute key.\n\t * @param {String} value Attribute value.\n\t * @param {module:engine/view/element~Element} element Element for which attribute will be set.\n\t */\n\tsetAttribute( key, value, element ) {\n\t\telement._setAttribute( key, value );\n\t}\n\n\t/**\n\t * Removes attribute from the element.\n\t *\n\t *\t\twriter.removeAttribute( linkElement, 'href' );\n\t *\n\t * @see module:engine/view/element~Element#_removeAttribute\n\t * @param {String} key Attribute key.\n\t * @param {module:engine/view/element~Element} element Element from which attribute will be removed.\n\t */\n\tremoveAttribute( key, element ) {\n\t\telement._removeAttribute( key );\n\t}\n\n\t/**\n\t * Adds specified class to the element.\n\t *\n\t *\t\twriter.addClass( linkElement, 'foo' );\n\t *\t\twriter.addClass( linkElement, [ 'foo', 'bar' ] );\n\t *\n\t * @see module:engine/view/element~Element#_addClass\n\t * @param {Array.<String>|String} className Single class name or array of class names which will be added.\n\t * @param {module:engine/view/element~Element} element Element for which class will be added.\n\t */\n\taddClass( className, element ) {\n\t\telement._addClass( className );\n\t}\n\n\t/**\n\t * Removes specified class from the element.\n\t *\n\t *\t\twriter.removeClass( linkElement, 'foo' );\n\t *\t\twriter.removeClass( linkElement, [ 'foo', 'bar' ] );\n\t *\n\t * @see module:engine/view/element~Element#_removeClass\n\t * @param {Array.<String>|String} className Single class name or array of class names which will be removed.\n\t * @param {module:engine/view/element~Element} element Element from which class will be removed.\n\t */\n\tremoveClass( className, element ) {\n\t\telement._removeClass( className );\n\t}\n\n\t/**\n\t * Adds style to the element.\n\t *\n\t *\t\twriter.setStyle( element, 'color', 'red' );\n\t *\t\twriter.setStyle( element, {\n\t *\t\t\tcolor: 'red',\n\t *\t\t\tposition: 'fixed'\n\t *\t\t} );\n\t *\n\t * @see module:engine/view/element~Element#_setStyle\n\t * @param {String|Object} property Property name or object with key - value pairs.\n\t * @param {String} [value] Value to set. This parameter is ignored if object is provided as the first parameter.\n\t * @param {module:engine/view/element~Element} element Element for which style will be added.\n\t */\n\tsetStyle( property, value, element ) {\n\t\tif ( isPlainObject( property ) && element === undefined ) {\n\t\t\telement = value;\n\t\t}\n\t\telement._setStyle( property, value );\n\t}\n\n\t/**\n\t * Removes specified style from the element.\n\t *\n\t *\t\twriter.removeStyle( element, 'color' ); // Removes 'color' style.\n\t *\t\twriter.removeStyle( element, [ 'color', 'border-top' ] ); // Removes both 'color' and 'border-top' styles.\n\t *\n\t * @see module:engine/view/element~Element#_removeStyle\n\t * @param {Array.<String>|String} property Style property name or names to be removed.\n\t * @param {module:engine/view/element~Element} element Element from which style will be removed.\n\t */\n\tremoveStyle( property, element ) {\n\t\telement._removeStyle( property );\n\t}\n\n\t/**\n\t * Sets a custom property on element. Unlike attributes, custom properties are not rendered to the DOM,\n\t * so they can be used to add special data to elements.\n\t *\n\t * @see module:engine/view/element~Element#_setCustomProperty\n\t * @param {String|Symbol} key Custom property name/key.\n\t * @param {*} value Custom property value to be stored.\n\t * @param {module:engine/view/element~Element} element Element for which custom property will be set.\n\t */\n\tsetCustomProperty( key, value, element ) {\n\t\telement._setCustomProperty( key, value );\n\t}\n\n\t/**\n\t * Removes a custom property stored under the given key.\n\t *\n\t * @see module:engine/view/element~Element#_removeCustomProperty\n\t * @param {String|Symbol} key Name/key of the custom property to be removed.\n\t * @param {module:engine/view/element~Element} element Element from which the custom property will be removed.\n\t * @returns {Boolean} Returns true if property was removed.\n\t */\n\tremoveCustomProperty( key, element ) {\n\t\treturn element._removeCustomProperty( key );\n\t}\n\n\t/**\n\t * Creates position at the given location. The location can be specified as:\n\t *\n\t * * a {@link module:engine/view/position~Position position},\n\t * * parent element and offset (offset defaults to `0`),\n\t * * parent element and `'end'` (sets position at the end of that element),\n\t * * {@link module:engine/view/item~Item view item} and `'before'` or `'after'` (sets position before or after given view item).\n\t *\n\t * This method is a shortcut to other constructors such as:\n\t *\n\t * * {@link #createPositionBefore},\n\t * * {@link #createPositionAfter},\n\t *\n\t * @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition\n\t * @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when\n\t * first parameter is a {@link module:engine/view/item~Item view item}.\n\t */\n\tcreatePositionAt( itemOrPosition, offset ) {\n\t\treturn Position._createAt( itemOrPosition, offset );\n\t}\n\n\t/**\n\t * Creates a new position after given view item.\n\t *\n\t * @param {module:engine/view/item~Item} item View item after which the position should be located.\n\t * @returns {module:engine/view/position~Position}\n\t */\n\tcreatePositionAfter( item ) {\n\t\treturn Position._createAfter( item );\n\t}\n\n\t/**\n\t * Creates a new position before given view item.\n\t *\n\t * @param {module:engine/view/item~Item} item View item before which the position should be located.\n\t * @returns {module:engine/view/position~Position}\n\t */\n\tcreatePositionBefore( item ) {\n\t\treturn Position._createBefore( item );\n\t}\n\n\t/**\n\t * Creates a range spanning from `start` position to `end` position.\n\t *\n\t * **Note:** This factory method creates it's own {@link module:engine/view/position~Position} instances basing on passed values.\n\t *\n\t * @param {module:engine/view/position~Position} start Start position.\n\t * @param {module:engine/view/position~Position} [end] End position. If not set, range will be collapsed at `start` position.\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRange( start, end ) {\n\t\treturn new Range( start, end );\n\t}\n\n\t/**\n\t * Creates a range that starts before given {@link module:engine/view/item~Item view item} and ends after it.\n\t *\n\t * @param {module:engine/view/item~Item} item\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRangeOn( item ) {\n\t\treturn Range._createOn( item );\n\t}\n\n\t/**\n\t * Creates a range inside an {@link module:engine/view/element~Element element} which starts before the first child of\n\t * that element and ends after the last child of that element.\n\t *\n\t * @param {module:engine/view/element~Element} element Element which is a parent for the range.\n\t * @returns {module:engine/view/range~Range}\n\t */\n\tcreateRangeIn( element ) {\n\t\treturn Range._createIn( element );\n\t}\n\n\t/**\n\t * Creates a new {@link module:engine/view/selection~Selection} instance.\n\t *\n\t * \t\t// Creates empty selection without ranges.\n\t *\t\tconst selection = writer.createSelection();\n\t *\n\t *\t\t// Creates selection at the given range.\n\t *\t\tconst range = writer.createRange( start, end );\n\t *\t\tconst selection = writer.createSelection( range );\n\t *\n\t *\t\t// Creates selection at the given ranges\n\t * \t\tconst ranges = [ writer.createRange( start1, end2 ), writer.createRange( star2, end2 ) ];\n\t *\t\tconst selection = writer.createSelection( ranges );\n\t *\n\t *\t\t// Creates selection from the other selection.\n\t *\t\tconst otherSelection = writer.createSelection();\n\t *\t\tconst selection = writer.createSelection( otherSelection );\n\t *\n\t *\t\t// Creates selection from the document selection.\n\t *\t\tconst selection = writer.createSelection( editor.editing.view.document.selection );\n\t *\n\t * \t\t// Creates selection at the given position.\n\t *\t\tconst position = writer.createPositionFromPath( root, path );\n\t *\t\tconst selection = writer.createSelection( position );\n\t *\n\t *\t\t// Creates collapsed selection at the position of given item and offset.\n\t *\t\tconst paragraph = writer.createContainerElement( 'paragraph' );\n\t *\t\tconst selection = writer.createSelection( paragraph, offset );\n\t *\n\t *\t\t// Creates a range inside an {@link module:engine/view/element~Element element} which starts before the\n\t *\t\t// first child of that element and ends after the last child of that element.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'in' );\n\t *\n\t *\t\t// Creates a range on an {@link module:engine/view/item~Item item} which starts before the item and ends\n\t *\t\t// just after the item.\n\t *\t\tconst selection = writer.createSelection( paragraph, 'on' );\n\t *\n\t * `Selection`'s constructor allow passing additional options (`backward`, `fake` and `label`) as the last argument.\n\t *\n\t *\t\t// Creates backward selection.\n\t *\t\tconst selection = writer.createSelection( range, { backward: true } );\n\t *\n\t * Fake selection does not render as browser native selection over selected elements and is hidden to the user.\n\t * This way, no native selection UI artifacts are displayed to the user and selection over elements can be\n\t * represented in other way, for example by applying proper CSS class.\n\t *\n\t * Additionally fake's selection label can be provided. It will be used to describe fake selection in DOM\n\t * (and be properly handled by screen readers).\n\t *\n\t *\t\t// Creates fake selection with label.\n\t *\t\tconst selection = writer.createSelection( range, { fake: true, label: 'foo' } );\n\t *\n\t * @param {module:engine/view/selection~Selectable} [selectable=null]\n\t * @param {Number|'before'|'end'|'after'|'on'|'in'} [placeOrOffset] Offset or place when selectable is an `Item`.\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.backward] Sets this selection instance to be backward.\n\t * @param {Boolean} [options.fake] Sets this selection instance to be marked as `fake`.\n\t * @param {String} [options.label] Label for the fake selection.\n\t * @returns {module:engine/view/selection~Selection}\n\t */\n\tcreateSelection( selectable, placeOrOffset, options ) {\n\t\treturn new Selection( selectable, placeOrOffset, options );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 core/command\n */\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * The base class for CKEditor commands.\n *\n * Commands are the main way to manipulate editor contents and state. They are mostly used by UI elements (or by other\n * commands) to make changes in the model. Commands are available in every part of code that has access to\n * the {@link module:core/editor/editor~Editor editor} instance.\n *\n * Instances of registered commands can be retrieved from {@link module:core/editor/editor~Editor#commands `editor.commands`}.\n * The easiest way to execute a command is through {@link module:core/editor/editor~Editor#execute `editor.execute()`}.\n *\n * By default commands are disabled when the editor is in {@link module:core/editor/editor~Editor#isReadOnly read-only} mode.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class Command {\n\t/**\n\t * Creates a new `Command` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor Editor on which this command will be used.\n\t */\n\tconstructor( editor ) {\n\t\t/**\n\t\t * The editor on which this command will be used.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/editor/editor~Editor}\n\t\t */\n\t\tthis.editor = editor;\n\n\t\t/**\n\t\t * The value of the command. A concrete command class should define what it represents for it.\n\t\t *\n\t\t * For example, the `'bold'` command's value indicates whether the selection starts in a bolded text.\n\t\t * And the value of the `'link'` command may be an object with links details.\n\t\t *\n\t\t * It is possible for a command to have no value (e.g. for stateless actions such as `'imageUpload'`).\n\t\t *\n\t\t * A concrete command class should control this value by overriding the {@link #refresh `refresh()`} method.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member #value\n\t\t */\n\t\tthis.set( 'value', undefined );\n\n\t\t/**\n\t\t * Flag indicating whether a command is enabled or disabled.\n\t\t * A disabled command will do nothing when executed.\n\t\t *\n\t\t * A concrete command class should control this value by overriding the {@link #refresh `refresh()`} method.\n\t\t *\n\t\t * It is possible to disable a command from \"outside\". For instance, in your integration you may want to disable\n\t\t * a certain set of commands for the time being. To do that, you can use the fact that `isEnabled` is observable\n\t\t * and it fires the `set:isEnabled` event every time anyone tries to modify its value:\n\t\t *\n\t\t *\t\tfunction disableCommand( cmd ) {\n\t\t *\t\t\tcmd.on( 'set:isEnabled', forceDisable, { priority: 'highest' } );\n\t\t *\n\t\t *\t\t\tcmd.isEnabled = false;\n\t\t *\n\t\t *\t\t\t// Make it possible to enable the command again.\n\t\t *\t\t\treturn () => {\n\t\t *\t\t\t\tcmd.off( 'set:isEnabled', forceDisable );\n\t\t *\t\t\t\tcmd.refresh();\n\t\t *\t\t\t};\n\t\t *\n\t\t *\t\t\tfunction forceDisable( evt ) {\n\t\t *\t\t\t\tevt.return = false;\n\t\t *\t\t\t\tevt.stop();\n\t\t *\t\t\t}\n\t\t *\t\t}\n\t\t *\n\t\t *\t\t// Usage:\n\t\t *\n\t\t *\t\t// Disabling the command.\n\t\t *\t\tconst enableBold = disableCommand( editor.commands.get( 'bold' ) );\n\t\t *\n\t\t *\t\t// Enabling the command again.\n\t\t *\t\tenableBold();\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #isEnabled\n\t\t */\n\t\tthis.set( 'isEnabled', false );\n\n\t\t/**\n\t\t * Holds identifiers for {@link #forceDisabled} mechanism.\n\t\t *\n\t\t * @type {Set.<String>}\n\t\t * @private\n\t\t */\n\t\tthis._disableStack = new Set();\n\n\t\tthis.decorate( 'execute' );\n\n\t\t// By default every command is refreshed when changes are applied to the model.\n\t\tthis.listenTo( this.editor.model.document, 'change', () => {\n\t\t\tthis.refresh();\n\t\t} );\n\n\t\tthis.on( 'execute', evt => {\n\t\t\tif ( !this.isEnabled ) {\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\n\t\t// By default commands are disabled when the editor is in read-only mode.\n\t\tthis.listenTo( editor, 'change:isReadOnly', ( evt, name, value ) => {\n\t\t\tif ( value ) {\n\t\t\t\tthis.forceDisabled( 'readOnlyMode' );\n\t\t\t} else {\n\t\t\t\tthis.clearForceDisabled( 'readOnlyMode' );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Refreshes the command. The command should update its {@link #isEnabled} and {@link #value} properties\n\t * in this method.\n\t *\n\t * This method is automatically called when\n\t * {@link module:engine/model/document~Document#event:change any changes are applied to the document}.\n\t */\n\trefresh() {\n\t\tthis.isEnabled = true;\n\t}\n\n\t/**\n\t * Disables the command.\n\t *\n\t * Command may be disabled by multiple features or algorithms (at once). When disabling a command, unique id should be passed\n\t * (e.g. feature name). The same identifier should be used when {@link #clearForceDisabled enabling back} the command.\n\t * The command becomes enabled only after all features {@link #clearForceDisabled enabled it back}.\n\t *\n\t * Disabling and enabling a command:\n\t *\n\t *\t\tcommand.isEnabled; // -> true\n\t *\t\tcommand.forceDisabled( 'MyFeature' );\n\t *\t\tcommand.isEnabled; // -> false\n\t *\t\tcommand.clearForceDisabled( 'MyFeature' );\n\t *\t\tcommand.isEnabled; // -> true\n\t *\n\t * Command disabled by multiple features:\n\t *\n\t *\t\tcommand.forceDisabled( 'MyFeature' );\n\t *\t\tcommand.forceDisabled( 'OtherFeature' );\n\t *\t\tcommand.clearForceDisabled( 'MyFeature' );\n\t *\t\tcommand.isEnabled; // -> false\n\t *\t\tcommand.clearForceDisabled( 'OtherFeature' );\n\t *\t\tcommand.isEnabled; // -> true\n\t *\n\t * Multiple disabling with the same identifier is redundant:\n\t *\n\t *\t\tcommand.forceDisabled( 'MyFeature' );\n\t *\t\tcommand.forceDisabled( 'MyFeature' );\n\t *\t\tcommand.clearForceDisabled( 'MyFeature' );\n\t *\t\tcommand.isEnabled; // -> true\n\t *\n\t * **Note:** some commands or algorithms may have more complex logic when it comes to enabling or disabling certain commands,\n\t * so the command might be still disabled after {@link #clearForceDisabled} was used.\n\t *\n\t * @param {String} id Unique identifier for disabling. Use the same id when {@link #clearForceDisabled enabling back} the command.\n\t */\n\tforceDisabled( id ) {\n\t\tthis._disableStack.add( id );\n\n\t\tif ( this._disableStack.size == 1 ) {\n\t\t\tthis.on( 'set:isEnabled', forceDisable, { priority: 'highest' } );\n\t\t\tthis.isEnabled = false;\n\t\t}\n\t}\n\n\t/**\n\t * Clears forced disable previously set through {@link #clearForceDisabled}. See {@link #clearForceDisabled}.\n\t *\n\t * @param {String} id Unique identifier, equal to the one passed in {@link #forceDisabled} call.\n\t */\n\tclearForceDisabled( id ) {\n\t\tthis._disableStack.delete( id );\n\n\t\tif ( this._disableStack.size == 0 ) {\n\t\t\tthis.off( 'set:isEnabled', forceDisable );\n\t\t\tthis.refresh();\n\t\t}\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * A command may accept parameters. They will be passed from {@link module:core/editor/editor~Editor#execute `editor.execute()`}\n\t * to the command.\n\t *\n\t * The `execute()` method will automatically abort when the command is disabled ({@link #isEnabled} is `false`).\n\t * This behavior is implemented by a high priority listener to the {@link #event:execute} event.\n\t *\n\t * In order to see how to disable a command from \"outside\" see the {@link #isEnabled} documentation.\n\t *\n\t * @fires execute\n\t */\n\texecute() {}\n\n\t/**\n\t * Destroys the command.\n\t */\n\tdestroy() {\n\t\tthis.stopListening();\n\t}\n\n\t/**\n\t * Event fired by the {@link #execute} method. The command action is a listener to this event so it's\n\t * possible to change/cancel the behavior of the command by listening to this event.\n\t *\n\t * See {@link module:utils/observablemixin~ObservableMixin#decorate} for more information and samples.\n\t *\n\t * **Note:** This event is fired even if command is disabled. However, it is automatically blocked\n\t * by a high priority listener in order to prevent command execution.\n\t *\n\t * @event execute\n\t */\n}\n\nmix( Command, ObservableMixin );\n\n// Helper function that forces command to be disabled.\nfunction forceDisable( evt ) {\n\tevt.return = false;\n\tevt.stop();\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 image/image/utils\n */\n\nimport { findOptimalInsertionPosition, isWidget, toWidget } from '@ckeditor/ckeditor5-widget/src/utils';\n\n/**\n * Converts a given {@link module:engine/view/element~Element} to an image widget:\n * * Adds a {@link module:engine/view/element~Element#_setCustomProperty custom property} allowing to recognize the image widget element.\n * * Calls the {@link module:widget/utils~toWidget} function with the proper element's label creator.\n *\n * @param {module:engine/view/element~Element} viewElement\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer An instance of the view writer.\n * @param {String} label The element's label. It will be concatenated with the image `alt` attribute if one is present.\n * @returns {module:engine/view/element~Element}\n */\nexport function toImageWidget( viewElement, writer, label ) {\n\twriter.setCustomProperty( 'image', true, viewElement );\n\n\treturn toWidget( viewElement, writer, { label: labelCreator } );\n\n\tfunction labelCreator() {\n\t\tconst imgElement = viewElement.getChild( 0 );\n\t\tconst altText = imgElement.getAttribute( 'alt' );\n\n\t\treturn altText ? `${ altText } ${ label }` : label;\n\t}\n}\n\n/**\n * Checks if a given view element is an image widget.\n *\n * @param {module:engine/view/element~Element} viewElement\n * @returns {Boolean}\n */\nexport function isImageWidget( viewElement ) {\n\treturn !!viewElement.getCustomProperty( 'image' ) && isWidget( viewElement );\n}\n\n/**\n * Returns an image widget editing view element if one is selected.\n *\n * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection} selection\n * @returns {module:engine/view/element~Element|null}\n */\nexport function getSelectedImageWidget( selection ) {\n\tconst viewElement = selection.getSelectedElement();\n\n\tif ( viewElement && isImageWidget( viewElement ) ) {\n\t\treturn viewElement;\n\t}\n\n\treturn null;\n}\n\n/**\n * Checks if the provided model element is an `image`.\n *\n * @param {module:engine/model/element~Element} modelElement\n * @returns {Boolean}\n */\nexport function isImage( modelElement ) {\n\treturn !!modelElement && modelElement.is( 'image' );\n}\n\n/**\n * Handles inserting single file. This method unifies image insertion using {@link module:widget/utils~findOptimalInsertionPosition} method.\n *\n *\t\tmodel.change( writer => {\n *\t\t\tinsertImage( writer, model, { src: 'path/to/image.jpg' } );\n *\t\t} );\n *\n * @param {module:engine/model/writer~Writer} writer\n * @param {module:engine/model/model~Model} model\n * @param {Object} [attributes={}] Attributes of inserted image\n */\nexport function insertImage( writer, model, attributes = {} ) {\n\tconst imageElement = writer.createElement( 'image', attributes );\n\n\tconst insertAtSelection = findOptimalInsertionPosition( model.document.selection, model );\n\n\tmodel.insertContent( imageElement, insertAtSelection );\n\n\t// Inserting an image might've failed due to schema regulations.\n\tif ( imageElement.parent ) {\n\t\twriter.setSelection( imageElement, 'on' );\n\t}\n}\n\n/**\n * Checks if image can be inserted at current model selection.\n *\n * @param {module:engine/model/model~Model} model\n * @returns {Boolean}\n */\nexport function isImageAllowed( model ) {\n\tconst schema = model.schema;\n\tconst selection = model.document.selection;\n\n\treturn isImageAllowedInParent( selection, schema, model ) &&\n\t\t!checkSelectionOnObject( selection, schema ) &&\n\t\tisInOtherImage( selection );\n}\n\n// Checks if image is allowed by schema in optimal insertion parent.\n//\n// @returns {Boolean}\nfunction isImageAllowedInParent( selection, schema, model ) {\n\tconst parent = getInsertImageParent( selection, model );\n\n\treturn schema.checkChild( parent, 'image' );\n}\n\n// Check if selection is on object.\n//\n// @returns {Boolean}\nfunction checkSelectionOnObject( selection, schema ) {\n\tconst selectedElement = selection.getSelectedElement();\n\n\treturn selectedElement && schema.isObject( selectedElement );\n}\n\n// Checks if selection is placed in other image (ie. in caption).\nfunction isInOtherImage( selection ) {\n\treturn [ ...selection.focus.getAncestors() ].every( ancestor => !ancestor.is( 'image' ) );\n}\n\n// Returns a node that will be used to insert image with `model.insertContent` to check if image can be placed there.\nfunction getInsertImageParent( selection, model ) {\n\tconst insertAt = findOptimalInsertionPosition( selection, model );\n\n\tconst parent = insertAt.parent;\n\n\tif ( parent.isEmpty && !parent.is( '$root' ) ) {\n\t\treturn parent.parent;\n\t}\n\n\treturn parent;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nimport FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { insertImage, isImageAllowed } from '../image/utils';\n\n/**\n * @module image/imageupload/imageuploadcommand\n */\n\n/**\n * The image upload command.\n *\n * The command is registered by the {@link module:image/imageupload/imageuploadediting~ImageUploadEditing} plugin as `'imageUpload'`.\n *\n * In order to upload an image at the current selection position\n * (according to the {@link module:widget/utils~findOptimalInsertionPosition} algorithm),\n * execute the command and pass the native image file instance:\n *\n *\t\tthis.listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => {\n *\t\t\t// Assuming that only images were pasted:\n *\t\t\tconst images = Array.from( data.dataTransfer.files );\n *\n *\t\t\t// Upload the first image:\n *\t\t\teditor.execute( 'imageUpload', { file: images[ 0 ] } );\n *\t\t} );\n *\n * It is also possible to insert multiple images at once:\n *\n *\t\teditor.execute( 'imageUpload', {\n *\t\t\tfile: [\n *\t\t\t\tfile1,\n *\t\t\t\tfile2\n *\t\t\t]\n *\t\t} );\n *\n * @extends module:core/command~Command\n */\nexport default class ImageUploadCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.isEnabled = isImageAllowed( this.editor.model );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @fires execute\n\t * @param {Object} options Options for the executed command.\n\t * @param {File|Array.<File>} options.file The image file or an array of image files to upload.\n\t */\n\texecute( options ) {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\n\t\tconst fileRepository = editor.plugins.get( FileRepository );\n\n\t\tmodel.change( writer => {\n\t\t\tconst filesToUpload = Array.isArray( options.file ) ? options.file : [ options.file ];\n\n\t\t\tfor ( const file of filesToUpload ) {\n\t\t\t\tuploadImage( writer, model, fileRepository, file );\n\t\t\t}\n\t\t} );\n\t}\n}\n\n// Handles uploading single file.\n//\n// @param {module:engine/model/writer~writer} writer\n// @param {module:engine/model/model~Model} model\n// @param {File} file\nfunction uploadImage( writer, model, fileRepository, file ) {\n\tconst loader = fileRepository.createLoader( file );\n\n\t// Do not throw when upload adapter is not set. FileRepository will log an error anyway.\n\tif ( !loader ) {\n\t\treturn;\n\t}\n\n\tinsertImage( writer, model, { uploadId: loader.id } );\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module image/imageupload/imageuploadediting\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';\nimport Notification from '@ckeditor/ckeditor5-ui/src/notification/notification';\nimport Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';\nimport UpcastWriter from '@ckeditor/ckeditor5-engine/src/view/upcastwriter';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\nimport ImageUploadCommand from '../../src/imageupload/imageuploadcommand';\nimport {\n fetchLocalImage,\n isLocalImage\n} from '../../src/imageupload/utils';\nimport { createImageTypeRegExp } from './utils';\n/**\n * The editing part of the image upload feature. It registers the `'imageUpload'` command.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageUploadEditing extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get requires() {\n return [\n FileRepository,\n Notification,\n Clipboard\n ];\n }\n static get pluginName() {\n return 'ImageUploadEditing';\n }\n /**\n\t * @inheritDoc\n\t */\n constructor(editor) {\n super(editor);\n editor.config.define('image', {\n upload: {\n types: [\n 'jpeg',\n 'png',\n 'gif',\n 'bmp',\n 'webp',\n 'tiff'\n ]\n }\n });\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const doc = editor.model.document;\n const schema = editor.model.schema;\n const conversion = editor.conversion;\n const fileRepository = editor.plugins.get(FileRepository);\n const imageTypes = createImageTypeRegExp(editor.config.get('image.upload.types'));\n // Setup schema to allow uploadId and uploadStatus for images.\n schema.extend('image', {\n allowAttributes: [\n 'uploadId',\n 'uploadStatus'\n ]\n });\n // Register imageUpload command.\n editor.commands.add('imageUpload', new ImageUploadCommand(editor));\n // Register upcast converter for uploadId.\n conversion.for('upcast').attributeToAttribute({\n view: {\n name: 'img',\n key: 'uploadId'\n },\n model: 'uploadId'\n });\n // Handle pasted images.\n // For every image file, a new file loader is created and a placeholder image is\n // inserted into the content. Then, those images are uploaded once they appear in the model\n // (see Document#change listener below).\n this.listenTo(editor.editing.view.document, 'clipboardInput', (evt, data) => {\n // Skip if non empty HTML data is included.\n // https://github.com/ckeditor/ckeditor5-upload/issues/68\n if (isHtmlIncluded(data.dataTransfer)) {\n return;\n }\n const images = Array.from(data.dataTransfer.files).filter(file => {\n // See https://github.com/ckeditor/ckeditor5-image/pull/254.\n if (!file) {\n return false;\n }\n return imageTypes.test(file.type);\n });\n const ranges = data.targetRanges.map(viewRange => editor.editing.mapper.toModelRange(viewRange));\n editor.model.change(writer => {\n // Set selection to paste target.\n writer.setSelection(ranges);\n if (images.length) {\n evt.stop();\n // Upload images after the selection has changed in order to ensure the command's state is refreshed.\n editor.model.enqueueChange('default', () => {\n editor.execute('imageUpload', { file: images });\n });\n }\n });\n });\n // Handle HTML pasted with images with base64 or blob sources.\n // For every image file, a new file loader is created and a placeholder image is\n // inserted into the content. Then, those images are uploaded once they appear in the model\n // (see Document#change listener below).\n this.listenTo(editor.plugins.get(Clipboard), 'inputTransformation', (evt, data) => {\n const fetchableImages = Array.from(editor.editing.view.createRangeIn(data.content)).filter(value => isLocalImage(value.item) && !value.item.getAttribute('uploadProcessed')).map(value => {\n return {\n promise: fetchLocalImage(value.item),\n imageElement: value.item\n };\n });\n if (!fetchableImages.length) {\n return;\n }\n const writer = new UpcastWriter();\n for (const fetchableImage of fetchableImages) {\n // Set attribute marking that the image was processed already.\n writer.setAttribute('uploadProcessed', true, fetchableImage.imageElement);\n const loader = fileRepository.createLoader(fetchableImage.promise);\n if (loader) {\n writer.setAttribute('src', '', fetchableImage.imageElement);\n writer.setAttribute('uploadId', loader.id, fetchableImage.imageElement);\n }\n }\n });\n // Prevents from the browser redirecting to the dropped image.\n editor.editing.view.document.on('dragover', (evt, data) => {\n data.preventDefault();\n });\n // Upload placeholder images that appeared in the model.\n doc.on('change', () => {\n const changes = doc.differ.getChanges({ includeChangesInGraveyard: true });\n for (const entry of changes) {\n if (entry.type == 'insert' && entry.name != '$text') {\n const item = entry.position.nodeAfter;\n const isInGraveyard = entry.position.root.rootName == '$graveyard';\n for (const image of getImagesFromChangeItem(editor, item)) {\n // Check if the image element still has upload id.\n const uploadId = image.getAttribute('uploadId');\n if (!uploadId) {\n continue;\n }\n // Check if the image is loaded on this client.\n const loader = fileRepository.loaders.get(uploadId);\n if (!loader) {\n continue;\n }\n if (isInGraveyard) {\n // If the image was inserted to the graveyard - abort the loading process.\n loader.abort();\n } else if (loader.status == 'idle') {\n // If the image was inserted into content and has not been loaded yet, start loading it.\n this._readAndUpload(loader, image);\n }\n }\n }\n }\n });\n }\n /**\n\t * Reads and uploads an image.\n\t *\n\t * The image is read from the disk and as a Base64-encoded string it is set temporarily to\n\t * `image[src]`. When the image is successfully uploaded, the temporary data is replaced with the target\n\t * image's URL (the URL to the uploaded image on the server).\n\t *\n\t * @protected\n\t * @param {module:upload/filerepository~FileLoader} loader\n\t * @param {module:engine/model/element~Element} imageElement\n\t * @returns {Promise}\n\t */\n _readAndUpload(loader, imageElement) {\n const editor = this.editor;\n const model = editor.model;\n const t = editor.locale.t;\n const fileRepository = editor.plugins.get(FileRepository);\n const notification = editor.plugins.get(Notification);\n model.enqueueChange('transparent', writer => {\n writer.setAttribute('uploadStatus', 'reading', imageElement);\n });\n return loader.read().then(() => {\n const promise = loader.upload();\n // Force re–paint in Safari. Without it, the image will display with a wrong size.\n // https://github.com/ckeditor/ckeditor5/issues/1975\n /* istanbul ignore next */\n if (env.isSafari) {\n const viewFigure = editor.editing.mapper.toViewElement(imageElement);\n const viewImg = viewFigure.getChild(0);\n editor.editing.view.once('render', () => {\n // Early returns just to be safe. There might be some code ran\n // in between the outer scope and this callback.\n if (!viewImg.parent) {\n return;\n }\n const domFigure = editor.editing.view.domConverter.mapViewToDom(viewImg.parent);\n if (!domFigure) {\n return;\n }\n const originalDisplay = domFigure.style.display;\n domFigure.style.display = 'none';\n // Make sure this line will never be removed during minification for having \"no effect\".\n domFigure._ckHack = domFigure.offsetHeight;\n domFigure.style.display = originalDisplay;\n });\n }\n model.enqueueChange('transparent', writer => {\n writer.setAttribute('uploadStatus', 'uploading', imageElement);\n });\n return promise;\n }).then(data => {\n model.enqueueChange('transparent', writer => {\n writer.setAttributes({\n uploadStatus: 'complete',\n src: data.default\n }, imageElement);\n this._parseAndSetSrcsetAttributeOnImage(data, imageElement, writer);\n });\n clean();\n }).catch(error => {\n // If status is not 'error' nor 'aborted' - throw error because it means that something else went wrong,\n // it might be generic error and it would be real pain to find what is going on.\n if (loader.status !== 'error' && loader.status !== 'aborted') {\n throw error;\n }\n // Might be 'aborted'.\n if (loader.status == 'error' && error) {\n notification.showWarning(error, {\n title: t('aq'),\n namespace: 'upload'\n });\n }\n clean();\n // Permanently remove image from insertion batch.\n model.enqueueChange('transparent', writer => {\n writer.remove(imageElement);\n });\n });\n function clean() {\n model.enqueueChange('transparent', writer => {\n writer.removeAttribute('uploadId', imageElement);\n writer.removeAttribute('uploadStatus', imageElement);\n });\n fileRepository.destroyLoader(loader);\n }\n }\n /**\n\t * Creates the `srcset` attribute based on a given file upload response and sets it as an attribute to a specific image element.\n\t *\n\t * @protected\n\t * @param {Object} data Data object from which `srcset` will be created.\n\t * @param {module:engine/model/element~Element} image The image element on which the `srcset` attribute will be set.\n\t * @param {module:engine/model/writer~Writer} writer\n\t */\n _parseAndSetSrcsetAttributeOnImage(data, image, writer) {\n // Srcset attribute for responsive images support.\n let maxWidth = 0;\n const srcsetAttribute = Object.keys(data) // Filter out keys that are not integers.\n.filter(key => {\n const width = parseInt(key, 10);\n if (!isNaN(width)) {\n maxWidth = Math.max(maxWidth, width);\n return true;\n }\n }) // Convert each key to srcset entry.\n.map(key => `${ data[key] } ${ key }w`) // Join all entries.\n.join(', ');\n if (srcsetAttribute != '') {\n writer.setAttribute('srcset', {\n data: srcsetAttribute,\n width: maxWidth\n }, image);\n }\n }\n}\n// Returns `true` if non-empty `text/html` is included in the data transfer.\n//\n// @param {module:clipboard/datatransfer~DataTransfer} dataTransfer\n// @returns {Boolean}\nexport function isHtmlIncluded(dataTransfer) {\n return Array.from(dataTransfer.types).includes('text/html') && dataTransfer.getData('text/html') !== '';\n}\nfunction getImagesFromChangeItem(editor, item) {\n return Array.from(editor.model.createRangeOn(item)).filter(value => value.item.is('image')).map(value => value.item);\n}","/**\n * @license Copyright (c) 2003-2019, 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 image/imageupload\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ImageUploadUI from './imageupload/imageuploadui';\nimport ImageUploadProgress from './imageupload/imageuploadprogress';\nimport ImageUploadEditing from './imageupload/imageuploadediting';\n\n/**\n * The image upload plugin.\n *\n * For a detailed overview, check the {@glink features/image-upload/image-upload image upload feature} documentation.\n *\n * This plugin does not do anything directly, but it loads a set of specific plugins to enable image uploading:\n *\n * * {@link module:image/imageupload/imageuploadediting~ImageUploadEditing},\n * * {@link module:image/imageupload/imageuploadui~ImageUploadUI},\n * * {@link module:image/imageupload/imageuploadprogress~ImageUploadProgress}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageUpload extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ImageUpload';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ImageUploadEditing, ImageUploadUI, ImageUploadProgress ];\n\t}\n}\n\n/**\n * Image upload configuration.\n *\n * @member {module:image/imageupload~ImageUploadConfig} module:image/image~ImageConfig#upload\n */\n\n/**\n * The configuration of the image upload feature. Used by the image upload feature in the `@ckeditor/ckeditor5-image` package.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n * \t\t\t\timage: {\n * \t\t\t\t\tupload: ... // Image upload feature options.\n * \t\t\t\t}\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.\n *\n * @interface module:image/imageupload~ImageUploadConfig\n */\n\n/**\n * The list of accepted image types.\n *\n * The accepted types of images can be customized to allow only certain types of images:\n *\n *\t\t// Allow only JPEG and PNG images:\n *\t\tconst imageUploadConfig = {\n *\t\t\ttypes: [ 'png', 'jpeg' ]\n *\t\t};\n *\n * The type string should match [one of the sub-types](https://www.iana.org/assignments/media-types/media-types.xhtml#image)\n * of the image MIME type. E.g. for the `image/jpeg` MIME type, add `'jpeg'` to your image upload configuration.\n *\n * **Note:** This setting only restricts some image types to be selected and uploaded through the CKEditor UI and commands. Image type\n * recognition and filtering should also be implemented on the server which accepts image uploads.\n *\n * @member {Array.<String>} module:image/imageupload~ImageUploadConfig#types\n * @default [ 'jpeg', 'png', 'gif', 'bmp', 'webp', 'tiff' ]\n */\n","const childPagesMacroSymbol = Symbol( 'isWpButtonMacroSymbol' );\nimport {toWidget, isWidget} from '@ckeditor/ckeditor5-widget/src/utils';\n\nexport function toChildPagesMacroWidget( viewElement, writer, label ) {\n\twriter.setCustomProperty( childPagesMacroSymbol, true, viewElement );\n\treturn toWidget( viewElement, writer, { label: label });\n}\n\n\nexport function isChildPagesMacroWidget( viewElement ) {\n\treturn !!viewElement.getCustomProperty( childPagesMacroSymbol ) && isWidget( viewElement );\n}\n\n\nexport function isChildPagesMacroWidgetSelected( selection ) {\n\tconst viewElement = selection.getSelectedElement();\n\n\treturn !!( viewElement && isChildPagesMacroWidget( viewElement ) );\n}\n","import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';\nimport ViewRange from '@ckeditor/ckeditor5-engine/src/view/range';\n\nimport {toChildPagesMacroWidget} from './utils';\n\nexport default class OPChildPagesEditing extends Plugin {\n\n\tstatic get pluginName() {\n\t\treturn 'OPChildPagesEditing';\n\t}\n\n\tstatic get buttonName(){\n\t\treturn \"insertChildPages\";\n\t}\n\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst conversion = editor.conversion;\n\n\t\t// Schema.\n\t\tmodel.schema.register( 'op-macro-child-pages', {\n\t\t\tallowWhere: ['$block'],\n\t\t\tallowAttributes: ['page'],\n\t\t\tisBlock: true,\n\t\t\tisLimit: true\n\t\t});\n\n\t\tconversion.for( 'upcast' )\n\t\t\t.elementToElement( {\n\t\t\t\tview: {\n\t\t\t\t\tname: 'macro',\n\t\t\t\t\tclasses: 'child_pages'\n\t\t\t\t},\n\t\t\t\tmodel: ( viewElement, modelWriter ) => {\n\t\t\t\t\tconst page = viewElement.getAttribute( 'data-page' ) || '';\n\t\t\t\t\tconst includeParent = viewElement.getAttribute( 'data-include-parent' ) == 'true';\n\n\t\t\t\t\treturn modelWriter.createElement(\n\t\t\t\t\t\t'op-macro-child-pages',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpage: page,\n\t\t\t\t\t\t\tincludeParent: includeParent\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\n\n\t\tconversion.for( 'editingDowncast' )\n\t\t\t.elementToElement({\n\t\t\t\tmodel: 'op-macro-child-pages',\n\t\t\t\tview: (modelElement, writer) => {\n\t\t\t\t\treturn this.createMacroViewElement(modelElement, writer);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.add(dispatcher => dispatcher.on( 'attribute:page', this.modelAttributeToView.bind(this)))\n\t\t\t.add(dispatcher => dispatcher.on( 'attribute:includeParent', this.modelAttributeToView.bind(this)));\n\n\t\tconversion.for('dataDowncast').elementToElement({\n\t\t\tmodel: 'op-macro-child-pages',\n\t\t\tview: (modelElement, writer) => {\n\t\t\t\tconst element = writer.createContainerElement(\n\t\t\t\t\t'macro',\n\t\t\t\t\t{\n\t\t\t\t\t\t'class': 'child_pages',\n\t\t\t\t\t\t'data-page': modelElement.getAttribute('page') || '',\n\t\t\t\t\t\t'data-include-parent': modelElement.getAttribute('includeParent') || ''\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\treturn element;\n\t\t\t}\n\t\t});\n\n\t\teditor.ui.componentFactory.add( OPChildPagesEditing.buttonName, locale => {\n\t\t\tconst view = new ButtonView( locale );\n\n\t\t\tview.set( {\n\t\t\t\tlabel: window.I18n.t('js.editor.macro.child_pages.button'),\n\t\t\t\twithText: true\n\t\t\t} );\n\n\t\t\t// Callback executed once the image is clicked.\n\t\t\tview.on( 'execute', () => {\n\t\t\t\teditor.model.change(writer => {\n\t\t\t\t\tconst element = writer.createElement( 'op-macro-child-pages', {});\n\n\t\t\t\t\teditor.model.insertContent( element, editor.model.document.selection );\n\t\t\t\t});\n\t\t\t} );\n\n\t\t\treturn view;\n\t\t} );\n\t}\n\n\tmodelAttributeToView( evt, data, conversionApi ) {\n\t\tconst modelElement = data.item;\n\t\tif (!modelElement.is('op-macro-child-pages')) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Mark element as consumed by conversion.\n\t\tconversionApi.consumable.consume(data.item, evt.name);\n\n\t\t// Get mapped view element to update.\n\t\tconst viewElement = conversionApi.mapper.toViewElement(modelElement);\n\n\t\t// Remove current <div> element contents.\n\t\tconversionApi.writer.remove(conversionApi.writer.createRangeIn(viewElement));\n\n\t\t// Set current content\n\t\tthis.setPlaceholderContent(conversionApi.writer, modelElement, viewElement);\n\t}\n\n\tmacroLabel() {\n\t\treturn window.I18n.t('js.editor.macro.child_pages.text');\n\t}\n\n\tpageLabel(page) {\n\t\tif (page && page.length > 0) {\n\t\t\treturn page\n\t\t} else {\n\t\t\treturn window.I18n.t('js.editor.macro.child_pages.this_page');\n\t\t}\n\t}\n\n\tincludeParentText(includeParent) {\n\t\tif (includeParent) {\n\t\t\treturn ` (${window.I18n.t('js.editor.macro.child_pages.include_parent')})`;\n\t\t} else {\n\t\t\treturn '';\n\t\t}\n\t}\n\n\tcreateMacroViewElement(modelElement, writer) {\n\t\tconst placeholderContainer = writer.createContainerElement( 'div', { class: 'macro -child_pages' } );\n\n\t\tthis.setPlaceholderContent( writer, modelElement, placeholderContainer );\n\n\t\treturn toChildPagesMacroWidget(placeholderContainer, writer, { label: this.macroLabel() } )\n\t}\n\n\tsetPlaceholderContent(writer, modelElement, placeholderContainer ) {\n\t\tconst page = modelElement.getAttribute('page');\n\t\tconst includeParent = modelElement.getAttribute('includeParent');\n\t\tconst macroLabel = this.macroLabel();\n\t\tconst pageLabel = this.pageLabel(page);\n\t\tconst pageLabelContainer = writer.createContainerElement( 'span', { class: 'macro-value' } );\n\t\tlet placeholderContent = [ writer.createText( `${macroLabel} ` ) ];\n\t\twriter.insert( writer.createPositionAt( pageLabelContainer, 0 ), writer.createText( `${pageLabel}` ) )\n\t\tplaceholderContent.push( pageLabelContainer );\n\t\tplaceholderContent.push( writer.createText( this.includeParentText(includeParent) ));\n\n\t\twriter.insert( writer.createPositionAt( placeholderContainer, 0 ), placeholderContent );\n\t}\n}\n","import Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\n\nimport {isChildPagesMacroWidgetSelected} from './utils';\nimport {createToolbarEditButton} from '../../helpers/create-toolbar-edit-button';\nimport {createEditToolbar} from '../../helpers/create-toolbar';\nimport {getPluginContext} from '../op-context/op-context';\n\n\nconst balloonClassName = 'ck-toolbar-container';\n\nexport default class OPChildPagesToolbar extends Plugin {\n\tstatic get requires() {\n\t\treturn [ ContextualBalloon ];\n\t}\n\n\tstatic get pluginName() {\n\t\treturn 'OPChildPagesToolbar';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = this.editor.model;\n\t\tconst pluginContext = getPluginContext(editor);\n\n\t\t// Add editing button\n\t\tcreateToolbarEditButton( editor, 'opEditChildPagesMacroButton', widget => {\n\t\t\tconst macroService = pluginContext.services.macros;\n\t\t\tconst pageAttribute = widget.getAttribute('page');\n\t\t\tconst includeParent = widget.getAttribute('includeParent');\n\t\t\tconst page = (pageAttribute && pageAttribute.length > 0) ? pageAttribute : '';\n\t\t\tmacroService\n\t\t\t\t.configureChildPages(page, includeParent)\n\t\t\t\t.then((macroConf) => model.change(writer => {\n\t\t\t\t\t\twriter.setAttribute( 'page', macroConf.page, widget );\n\t\t\t\t\t\twriter.setAttribute( 'includeParent', macroConf.includeParent, widget );\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t} );\n\t}\n\n\tafterInit() {\n\t\t// Add actual toolbar\n\t\tcreateEditToolbar(\n\t\t\tthis,\n\t\t\tthis.editor,\n\t\t\t'OPChildPages',\n\t\t\tisChildPagesMacroWidgetSelected\n\t\t);\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 enter/utils\n */\n\n/**\n * Returns attributes that should be preserved on the enter key.\n *\n * Filtering is realized based on `copyOnEnter` attribute property. Read more about attribute properties\n * {@link module:engine/model/schema~Schema#setAttributeProperties here}.\n *\n * @param {module:engine/model/schema~Schema} schema\n * @param {Iterable.<*>} allAttributes attributes to filter.\n * @returns {Iterable.<*>}\n */\nexport function* getCopyOnEnterAttributes( schema, allAttributes ) {\n\tfor ( const attribute of allAttributes ) {\n\t\tif ( attribute && schema.getAttributeProperties( attribute[ 0 ] ).copyOnEnter ) {\n\t\t\tyield attribute;\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 enter/entercommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { getCopyOnEnterAttributes } from './utils';\n\n/**\n * Enter command. It is used by the {@link module:enter/enter~Enter Enter feature} to handle the <kbd>Enter</kbd> key.\n *\n * @extends module:core/command~Command\n */\nexport default class EnterCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tmodel.change( writer => {\n\t\t\tenterBlock( this.editor.model, writer, doc.selection, model.schema );\n\t\t\tthis.fire( 'afterExecute', { writer } );\n\t\t} );\n\t}\n}\n\n// Creates a new block in the way that the <kbd>Enter</kbd> key is expected to work.\n//\n// @param {module:engine/model~Model} model\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n// Selection on which the action should be performed.\n// @param {module:engine/model/schema~Schema} schema\nfunction enterBlock( model, writer, selection, schema ) {\n\tconst isSelectionEmpty = selection.isCollapsed;\n\tconst range = selection.getFirstRange();\n\tconst startElement = range.start.parent;\n\tconst endElement = range.end.parent;\n\n\t// Don't touch the roots and other limit elements.\n\tif ( schema.isLimit( startElement ) || schema.isLimit( endElement ) ) {\n\t\t// Delete the selected content but only if inside a single limit element.\n\t\t// Abort, when crossing limit elements boundary (e.g. <limit1>x[x</limit1>donttouchme<limit2>y]y</limit2>).\n\t\t// This is an edge case and it's hard to tell what should actually happen because such a selection\n\t\t// is not entirely valid.\n\t\tif ( !isSelectionEmpty && startElement == endElement ) {\n\t\t\tmodel.deleteContent( selection );\n\t\t}\n\n\t\treturn;\n\t}\n\n\tif ( isSelectionEmpty ) {\n\t\tconst attributesToCopy = getCopyOnEnterAttributes( writer.model.schema, selection.getAttributes() );\n\t\tsplitBlock( writer, range.start );\n\t\twriter.setSelectionAttribute( attributesToCopy );\n\t} else {\n\t\tconst leaveUnmerged = !( range.start.isAtStart && range.end.isAtEnd );\n\t\tconst isContainedWithinOneElement = ( startElement == endElement );\n\n\t\tmodel.deleteContent( selection, { leaveUnmerged } );\n\n\t\tif ( leaveUnmerged ) {\n\t\t\t// Partially selected elements.\n\t\t\t//\n\t\t\t// <h>x[xx]x</h>\t\t-> <h>x^x</h>\t\t\t-> <h>x</h><h>^x</h>\n\t\t\tif ( isContainedWithinOneElement ) {\n\t\t\t\tsplitBlock( writer, selection.focus );\n\t\t\t}\n\t\t\t// Selection over multiple elements.\n\t\t\t//\n\t\t\t// <h>x[x</h><p>y]y<p>\t-> <h>x^</h><p>y</p>\t-> <h>x</h><p>^y</p>\n\t\t\telse {\n\t\t\t\twriter.setSelection( endElement, 0 );\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction splitBlock( writer, splitPos ) {\n\twriter.split( splitPos );\n\twriter.setSelection( splitPos.parent.nextSibling, 0 );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 enter/enterobserver\n */\n\nimport Observer from '@ckeditor/ckeditor5-engine/src/view/observer/observer';\nimport DomEventData from '@ckeditor/ckeditor5-engine/src/view/observer/domeventdata';\nimport { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';\n\n/**\n * Enter observer introduces the {@link module:engine/view/document~Document#event:enter} event.\n *\n * @extends module:engine/view/observer/observer~Observer\n */\nexport default class EnterObserver extends Observer {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tconst doc = this.document;\n\n\t\tdoc.on( 'keydown', ( evt, data ) => {\n\t\t\tif ( this.isEnabled && data.keyCode == keyCodes.enter ) {\n\t\t\t\t// Save the event object to check later if it was stopped or not.\n\t\t\t\tlet event;\n\t\t\t\tdoc.once( 'enter', evt => ( event = evt ), { priority: 'highest' } );\n\n\t\t\t\tdoc.fire( 'enter', new DomEventData( doc, data.domEvent, {\n\t\t\t\t\tisSoft: data.shiftKey\n\t\t\t\t} ) );\n\n\t\t\t\t// Stop `keydown` event if `enter` event was stopped.\n\t\t\t\t// https://github.com/ckeditor/ckeditor5/issues/753\n\t\t\t\tif ( event && event.stop.called ) {\n\t\t\t\t\tevt.stop();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tobserve() {}\n}\n\n/**\n * Event fired when the user presses the <kbd>Enter</kbd> key.\n *\n * Note: This event is fired by the {@link module:enter/enterobserver~EnterObserver observer}\n * (usually registered by the {@link module:enter/enter~Enter Enter feature} and\n * {@link module:enter/shiftenter~ShiftEnter ShiftEnter feature}).\n *\n * @event module:engine/view/document~Document#event:enter\n * @param {module:engine/view/observer/domeventdata~DomEventData} data\n * @param {Boolean} data.isSoft Whether it's a soft enter (<kbd>Shift</kbd>+<kbd>Enter</kbd>) or hard enter (<kbd>Enter</kbd>).\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 enter/enter\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport EnterCommand from './entercommand';\nimport EnterObserver from './enterobserver';\n\n/**\n * This plugin handles the <kbd>Enter</kbd> key (hard line break) in the editor.\n *\n * See also the {@link module:enter/shiftenter~ShiftEnter} plugin.\n *\n * For more information about this feature see the {@glink api/enter package page}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Enter extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Enter';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\n\t\tview.addObserver( EnterObserver );\n\n\t\teditor.commands.add( 'enter', new EnterCommand( editor ) );\n\n\t\tthis.listenTo( viewDocument, 'enter', ( evt, data ) => {\n\t\t\tdata.preventDefault();\n\n\t\t\t// The soft enter key is handled by the ShiftEnter plugin.\n\t\t\tif ( data.isSoft ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\teditor.execute( 'enter' );\n\t\t\tview.scrollToTheSelection();\n\t\t}, { priority: 'low' } );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 enter/shiftentercommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { getCopyOnEnterAttributes } from './utils';\n\n/**\n * ShiftEnter command. It is used by the {@link module:enter/shiftenter~ShiftEnter ShiftEnter feature} to handle\n * the <kbd>Shift</kbd>+<kbd>Enter</kbd> keystroke.\n *\n * @extends module:core/command~Command\n */\nexport default class ShiftEnterCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tmodel.change( writer => {\n\t\t\tsoftBreakAction( model, writer, doc.selection );\n\t\t\tthis.fire( 'afterExecute', { writer } );\n\t\t} );\n\t}\n\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tthis.isEnabled = isEnabled( model.schema, doc.selection );\n\t}\n}\n\n// Checks whether the ShiftEnter command should be enabled in the specified selection.\n//\n// @param {module:engine/model/schema~Schema} schema\n// @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\nfunction isEnabled( schema, selection ) {\n\t// At this moment it is okay to support single range selections only.\n\t// But in the future we may need to change that.\n\tif ( selection.rangeCount > 1 ) {\n\t\treturn false;\n\t}\n\n\tconst anchorPos = selection.anchor;\n\n\t// Check whether the break element can be inserted in the current selection anchor.\n\tif ( !anchorPos || !schema.checkChild( anchorPos, 'softBreak' ) ) {\n\t\treturn false;\n\t}\n\n\tconst range = selection.getFirstRange();\n\tconst startElement = range.start.parent;\n\tconst endElement = range.end.parent;\n\n\t// Do not modify the content if selection is cross-limit elements.\n\tif ( ( isInsideLimitElement( startElement, schema ) || isInsideLimitElement( endElement, schema ) ) && startElement !== endElement ) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n// Creates a break in the way that the <kbd>Shift</kbd>+<kbd>Enter</kbd> keystroke is expected to work.\n//\n// @param {module:engine/model~Model} model\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n// Selection on which the action should be performed.\nfunction softBreakAction( model, writer, selection ) {\n\tconst isSelectionEmpty = selection.isCollapsed;\n\tconst range = selection.getFirstRange();\n\tconst startElement = range.start.parent;\n\tconst endElement = range.end.parent;\n\tconst isContainedWithinOneElement = ( startElement == endElement );\n\n\tif ( isSelectionEmpty ) {\n\t\tconst attributesToCopy = getCopyOnEnterAttributes( model.schema, selection.getAttributes() );\n\t\tinsertBreak( writer, range.end );\n\n\t\twriter.removeSelectionAttribute( selection.getAttributeKeys() );\n\t\twriter.setSelectionAttribute( attributesToCopy );\n\t} else {\n\t\tconst leaveUnmerged = !( range.start.isAtStart && range.end.isAtEnd );\n\t\tmodel.deleteContent( selection, { leaveUnmerged } );\n\n\t\t// Selection within one element:\n\t\t//\n\t\t// <h>x[xx]x</h>\t\t-> <h>x^x</h>\t\t\t-> <h>x<br>^x</h>\n\t\tif ( isContainedWithinOneElement ) {\n\t\t\tinsertBreak( writer, selection.focus );\n\t\t}\n\t\t// Selection over multiple elements.\n\t\t//\n\t\t// <h>x[x</h><p>y]y<p>\t-> <h>x^</h><p>y</p>\t-> <h>x</h><p>^y</p>\n\t\t//\n\t\t// We chose not to insert a line break in this case because:\n\t\t//\n\t\t// * it's not a very common scenario,\n\t\t// * it actually surprised me when I saw the \"expected behavior\" in real life.\n\t\t//\n\t\t// It's ok if the user will need to be more specific where they want the <br> to be inserted.\n\t\telse {\n\t\t\t// Move the selection to the 2nd element (last step of the example above).\n\t\t\tif ( leaveUnmerged ) {\n\t\t\t\twriter.setSelection( endElement, 0 );\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction insertBreak( writer, position ) {\n\tconst breakLineElement = writer.createElement( 'softBreak' );\n\n\twriter.insert( breakLineElement, position );\n\twriter.setSelection( breakLineElement, 'after' );\n}\n\n// Checks whether the specified `element` is a child of the limit element.\n//\n// Checking whether the `<p>` element is inside a limit element:\n// - <$root><p>Text.</p></$root> => false\n// - <$root><limitElement><p>Text</p></limitElement></$root> => true\n//\n// @param {module:engine/model/element~Element} element\n// @param {module:engine/schema~Schema} schema\n// @returns {Boolean}\nfunction isInsideLimitElement( element, schema ) {\n\t// `$root` is a limit element but in this case is an invalid element.\n\tif ( element.is( 'rootElement' ) ) {\n\t\treturn false;\n\t}\n\n\treturn schema.isLimit( element ) || isInsideLimitElement( element.parent, schema );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 enter/shiftenter\n */\n\nimport ShiftEnterCommand from './shiftentercommand';\nimport EnterObserver from './enterobserver';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\n/**\n * This plugin handles the <kbd>Shift</kbd>+<kbd>Enter</kbd> keystroke (soft line break) in the editor.\n *\n * See also the {@link module:enter/enter~Enter} plugin.\n *\n * For more information about this feature see the {@glink api/enter package page}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ShiftEnter extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ShiftEnter';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst schema = editor.model.schema;\n\t\tconst conversion = editor.conversion;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\n\t\t// Configure the schema.\n\t\tschema.register( 'softBreak', {\n\t\t\tallowWhere: '$text',\n\t\t\tisInline: true\n\t\t} );\n\n\t\t// Configure converters.\n\t\tconversion.for( 'upcast' )\n\t\t\t.elementToElement( {\n\t\t\t\tmodel: 'softBreak',\n\t\t\t\tview: 'br'\n\t\t\t} );\n\n\t\tconversion.for( 'downcast' )\n\t\t\t.elementToElement( {\n\t\t\t\tmodel: 'softBreak',\n\t\t\t\tview: ( modelElement, viewWriter ) => viewWriter.createEmptyElement( 'br' )\n\t\t\t} );\n\n\t\tview.addObserver( EnterObserver );\n\n\t\teditor.commands.add( 'shiftEnter', new ShiftEnterCommand( editor ) );\n\n\t\tthis.listenTo( viewDocument, 'enter', ( evt, data ) => {\n\t\t\tdata.preventDefault();\n\n\t\t\t// The hard enter key is handled by the Enter plugin.\n\t\t\tif ( !data.isSoft ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\teditor.execute( 'shiftEnter' );\n\t\t\tview.scrollToTheSelection();\n\t\t}, { priority: 'low' } );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/utils/changebuffer\n */\n\n/**\n * Change buffer allows to group atomic changes (like characters that have been typed) into\n * {@link module:engine/model/batch~Batch batches}.\n *\n * Batches represent single undo steps, hence changes added to one single batch are undone together.\n *\n * The buffer has a configurable limit of atomic changes that it can accommodate. After the limit was\n * exceeded (see {@link ~ChangeBuffer#input}), a new batch is created in {@link ~ChangeBuffer#batch}.\n *\n * To use the change buffer you need to let it know about the number of changes that were added to the batch:\n *\n *\t\tconst buffer = new ChangeBuffer( model, LIMIT );\n *\n *\t\t// Later on in your feature:\n *\t\tbuffer.batch.insert( pos, insertedCharacters );\n *\t\tbuffer.input( insertedCharacters.length );\n *\n */\nexport default class ChangeBuffer {\n\t/**\n\t * Creates a new instance of the change buffer.\n\t *\n\t * @param {module:engine/model/model~Model} model\n\t * @param {Number} [limit=20] The maximum number of atomic changes which can be contained in one batch.\n\t */\n\tconstructor( model, limit = 20 ) {\n\t\t/**\n\t\t * The model instance.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/model~Model} #model\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * The number of atomic changes in the buffer. Once it exceeds the {@link #limit},\n\t\t * the {@link #batch batch} is set to a new one.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #size\n\t\t */\n\t\tthis.size = 0;\n\n\t\t/**\n\t\t * The maximum number of atomic changes which can be contained in one batch.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #limit\n\t\t */\n\t\tthis.limit = limit;\n\n\t\t/**\n\t\t * Whether the buffer is locked. A locked buffer cannot be reset unless it gets unlocked.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} #isLocked\n\t\t */\n\t\tthis.isLocked = false;\n\n\t\t// The function to be called in order to notify the buffer about batches which appeared in the document.\n\t\t// The callback will check whether it is a new batch and in that case the buffer will be flushed.\n\t\t//\n\t\t// The reason why the buffer needs to be flushed whenever a new batch appears is that the changes added afterwards\n\t\t// should be added to a new batch. For instance, when the user types, then inserts an image, and then types again,\n\t\t// the characters typed after inserting the image should be added to a different batch than the characters typed before.\n\t\tthis._changeCallback = ( evt, batch ) => {\n\t\t\tif ( batch.type != 'transparent' && batch !== this._batch ) {\n\t\t\t\tthis._reset( true );\n\t\t\t}\n\t\t};\n\n\t\tthis._selectionChangeCallback = () => {\n\t\t\tthis._reset();\n\t\t};\n\n\t\tthis.model.document.on( 'change', this._changeCallback );\n\n\t\tthis.model.document.selection.on( 'change:range', this._selectionChangeCallback );\n\t\tthis.model.document.selection.on( 'change:attribute', this._selectionChangeCallback );\n\n\t\t/**\n\t\t * The current batch instance.\n\t\t *\n\t\t * @private\n\t\t * @member #_batch\n\t\t */\n\n\t\t/**\n\t\t * The callback to document the change event which later needs to be removed.\n\t\t *\n\t\t * @private\n\t\t * @member #_changeCallback\n\t\t */\n\n\t\t/**\n\t\t * The callback to document selection `change:attribute` and `change:range` events which resets the buffer.\n\t\t *\n\t\t * @private\n\t\t * @member #_selectionChangeCallback\n\t\t */\n\t}\n\n\t/**\n\t * The current batch to which a feature should add its operations. Once the {@link #size}\n\t * is reached or exceeds the {@link #limit}, the batch is set to a new instance and the size is reset.\n\t *\n\t * @type {module:engine/model/batch~Batch}\n\t */\n\tget batch() {\n\t\tif ( !this._batch ) {\n\t\t\tthis._batch = this.model.createBatch();\n\t\t}\n\n\t\treturn this._batch;\n\t}\n\n\t/**\n\t * The input number of changes into the buffer. Once the {@link #size} is\n\t * reached or exceeds the {@link #limit}, the batch is set to a new instance and the size is reset.\n\t *\n\t * @param {Number} changeCount The number of atomic changes to input.\n\t */\n\tinput( changeCount ) {\n\t\tthis.size += changeCount;\n\n\t\tif ( this.size >= this.limit ) {\n\t\t\tthis._reset( true );\n\t\t}\n\t}\n\n\t/**\n\t * Locks the buffer.\n\t */\n\tlock() {\n\t\tthis.isLocked = true;\n\t}\n\n\t/**\n\t * Unlocks the buffer.\n\t */\n\tunlock() {\n\t\tthis.isLocked = false;\n\t}\n\n\t/**\n\t * Destroys the buffer.\n\t */\n\tdestroy() {\n\t\tthis.model.document.off( 'change', this._changeCallback );\n\t\tthis.model.document.selection.off( 'change:range', this._selectionChangeCallback );\n\t\tthis.model.document.selection.off( 'change:attribute', this._selectionChangeCallback );\n\t}\n\n\t/**\n\t * Resets the change buffer.\n\t *\n\t * @private\n\t * @param {Boolean} [ignoreLock] Whether internal lock {@link #isLocked} should be ignored.\n\t */\n\t_reset( ignoreLock ) {\n\t\tif ( !this.isLocked || ignoreLock ) {\n\t\t\tthis._batch = null;\n\t\t\tthis.size = 0;\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/inputcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\nimport ChangeBuffer from './utils/changebuffer';\n\n/**\n * The input command. Used by the {@link module:typing/input~Input input feature} to handle typing.\n *\n * @extends module:core/command~Command\n */\nexport default class InputCommand extends Command {\n\t/**\n\t * Creates an instance of the command.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor\n\t * @param {Number} undoStepSize The maximum number of atomic changes\n\t * which can be contained in one batch in the command buffer.\n\t */\n\tconstructor( editor, undoStepSize ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * Typing's change buffer used to group subsequent changes into batches.\n\t\t *\n\t\t * @readonly\n\t\t * @private\n\t\t * @member {module:typing/utils/changebuffer~ChangeBuffer} #_buffer\n\t\t */\n\t\tthis._buffer = new ChangeBuffer( editor.model, undoStepSize );\n\n\t\t/**\n\t\t * Stores batches created by the input command. The batches are used to differentiate input batches from other batches using\n\t\t * {@link module:typing/input~Input#isInput} method.\n\t\t *\n\t\t * @type {WeakSet<module:engine/model/batch~Batch>}\n\t\t * @protected\n\t\t */\n\t\tthis._batches = new WeakSet();\n\t}\n\n\t/**\n\t * The current change buffer.\n\t *\n\t * @type {module:typing/utils/changebuffer~ChangeBuffer}\n\t */\n\tget buffer() {\n\t\treturn this._buffer;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\tthis._buffer.destroy();\n\t}\n\n\t/**\n\t * Executes the input command. It replaces the content within the given range with the given text.\n\t * Replacing is a two step process, first the content within the range is removed and then the new text is inserted\n\t * at the beginning of the range (which after the removal is a collapsed range).\n\t *\n\t * @fires execute\n\t * @param {Object} [options] The command options.\n\t * @param {String} [options.text=''] The text to be inserted.\n\t * @param {module:engine/model/range~Range} [options.range] The range in which the text is inserted. Defaults\n\t * to the first range in the current selection.\n\t * @param {module:engine/model/range~Range} [options.resultRange] The range where the selection\n\t * should be placed after the insertion. If not specified, the selection will be placed right after\n\t * the inserted text.\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst text = options.text || '';\n\t\tconst textInsertions = text.length;\n\t\tconst range = options.range || doc.selection.getFirstRange();\n\t\tconst resultRange = options.resultRange;\n\n\t\tmodel.enqueueChange( this._buffer.batch, writer => {\n\t\t\tconst isCollapsedRange = range.isCollapsed;\n\n\t\t\tthis._buffer.lock();\n\n\t\t\tmodel.deleteContent( model.createSelection( range ) );\n\n\t\t\tif ( text ) {\n\t\t\t\tmodel.insertContent( writer.createText( text, doc.selection.getAttributes() ), range.start );\n\t\t\t}\n\n\t\t\tif ( resultRange ) {\n\t\t\t\twriter.setSelection( resultRange );\n\t\t\t} else if ( isCollapsedRange ) {\n\t\t\t\t// If range was collapsed just shift the selection by the number of inserted characters.\n\t\t\t\twriter.setSelection( range.start.getShiftedBy( textInsertions ) );\n\t\t\t}\n\n\t\t\tthis._buffer.unlock();\n\n\t\t\tthis._buffer.input( textInsertions );\n\n\t\t\t// Store the batch as an 'input' batch for the Input.isInput( batch ) check.\n\t\t\tthis._batches.add( this._buffer.batch );\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/utils/injectunsafekeystrokeshandling\n */\n\nimport { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\n/**\n * Handles keystrokes which are unsafe for typing. This handler's logic is explained\n * in https://github.com/ckeditor/ckeditor5-typing/issues/83#issuecomment-398690251.\n *\n * @param {module:core/editor/editor~Editor} editor The editor instance.\n */\nexport default function injectUnsafeKeystrokesHandling( editor ) {\n\tlet latestCompositionSelection = null;\n\n\tconst model = editor.model;\n\tconst view = editor.editing.view;\n\tconst inputCommand = editor.commands.get( 'input' );\n\n\t// For Android, we want to handle keystrokes on `beforeinput` to be sure that code in `DeleteObserver` already had a chance to be fired.\n\tif ( env.isAndroid ) {\n\t\tview.document.on( 'beforeinput', ( evt, evtData ) => handleUnsafeKeystroke( evtData ), { priority: 'lowest' } );\n\t} else {\n\t\tview.document.on( 'keydown', ( evt, evtData ) => handleUnsafeKeystroke( evtData ), { priority: 'lowest' } );\n\t}\n\n\tview.document.on( 'compositionstart', handleCompositionStart, { priority: 'lowest' } );\n\n\tview.document.on( 'compositionend', () => {\n\t\tlatestCompositionSelection = model.createSelection( model.document.selection );\n\t}, { priority: 'lowest' } );\n\n\t// Handles the keydown event. We need to guess whether such keystroke is going to result\n\t// in typing. If so, then before character insertion happens, any selected content needs\n\t// to be deleted. Otherwise the default browser deletion mechanism would be\n\t// triggered, resulting in:\n\t//\n\t// * Hundreds of mutations which could not be handled.\n\t// * But most importantly, loss of control over how the content is being deleted.\n\t//\n\t// The method is used in a low-priority listener, hence allowing other listeners (e.g. delete or enter features)\n\t// to handle the event.\n\t//\n\t// @param {module:engine/view/observer/keyobserver~KeyEventData} evtData\n\tfunction handleUnsafeKeystroke( evtData ) {\n\t\tconst doc = model.document;\n\t\tconst isComposing = view.document.isComposing;\n\t\tconst isSelectionUnchanged = latestCompositionSelection && latestCompositionSelection.isEqual( doc.selection );\n\n\t\t// Reset stored composition selection.\n\t\tlatestCompositionSelection = null;\n\n\t\t// By relying on the state of the input command we allow disabling the entire input easily\n\t\t// by just disabling the input command. We could’ve used here the delete command but that\n\t\t// would mean requiring the delete feature which would block loading one without the other.\n\t\t// We could also check the editor.isReadOnly property, but that wouldn't allow to block\n\t\t// the input without blocking other features.\n\t\tif ( !inputCommand.isEnabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( isSafeKeystroke( evtData ) || doc.selection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If during composition, deletion should be prevented as it may remove composed sequence (#83).\n\t\tif ( isComposing && evtData.keyCode === 229 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there is a `keydown` event fired with '229' keycode it might be related\n\t\t// to recent composition. Check if selection is the same as upon ending recent composition,\n\t\t// if so do not remove selected content as it will remove composed sequence (#83).\n\t\tif ( !isComposing && evtData.keyCode === 229 && isSelectionUnchanged ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdeleteSelectionContent();\n\t}\n\n\t// Handles the `compositionstart` event. It is used only in special cases to remove the contents\n\t// of a non-collapsed selection so composition itself does not result in complex mutations.\n\t//\n\t// The special case mentioned above is a situation in which the `keydown` event is fired after\n\t// `compositionstart` event. In such cases {@link #handleKeydown} cannot clear current selection\n\t// contents (because it is too late and will break the composition) so the composition handler takes care of it.\n\tfunction handleCompositionStart() {\n\t\tconst doc = model.document;\n\t\tconst isFlatSelection = doc.selection.rangeCount === 1 ? doc.selection.getFirstRange().isFlat : true;\n\n\t\t// If on `compositionstart` there is a non-collapsed selection which start and end have different parents\n\t\t// it means the `handleKeydown()` method did not remove its contents. It happens usually because\n\t\t// of different order of events (`compositionstart` before `keydown` - in Safari). In such cases\n\t\t// we need to remove selection contents on composition start (#83).\n\t\tif ( doc.selection.isCollapsed || isFlatSelection ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdeleteSelectionContent();\n\t}\n\n\tfunction deleteSelectionContent() {\n\t\tconst buffer = inputCommand.buffer;\n\n\t\tbuffer.lock();\n\n\t\tmodel.enqueueChange( buffer.batch, () => {\n\t\t\tmodel.deleteContent( model.document.selection );\n\t\t} );\n\n\t\tbuffer.unlock();\n\t}\n}\n\nconst safeKeycodes = [\n\tgetCode( 'arrowUp' ),\n\tgetCode( 'arrowRight' ),\n\tgetCode( 'arrowDown' ),\n\tgetCode( 'arrowLeft' ),\n\t9, // Tab\n\t16, // Shift\n\t17, // Ctrl\n\t18, // Alt\n\t19, // Pause\n\t20, // CapsLock\n\t27, // Escape\n\t33, // PageUp\n\t34, // PageDown\n\t35, // Home\n\t36, // End,\n\t45, // Insert,\n\t91, // Windows,\n\t93, // Menu key,\n\t144, // NumLock\n\t145, // ScrollLock,\n\t173, // Mute/Unmute\n\t174, // Volume up\n\t175, // Volume down,\n\t176, // Next song,\n\t177, // Previous song,\n\t178, // Stop,\n\t179, // Play/Pause,\n\t255 // Display brightness (increase and decrease)\n];\n\n// Function keys.\nfor ( let code = 112; code <= 135; code++ ) {\n\tsafeKeycodes.push( code );\n}\n\n// Returns `true` if a keystroke should not cause any content change caused by \"typing\".\n//\n// Note: This implementation is very simple and will need to be refined with time.\n//\n// @private\n// @param {engine.view.observer.keyObserver.KeyEventData} keyData\n// @returns {Boolean}\nfunction isSafeKeystroke( keyData ) {\n\t// Keystrokes which contain Ctrl don't represent typing.\n\tif ( keyData.ctrlKey ) {\n\t\treturn true;\n\t}\n\n\treturn safeKeycodes.includes( keyData.keyCode );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/utils/utils\n */\n\nimport diff from '@ckeditor/ckeditor5-utils/src/diff';\nimport diffToChanges from '@ckeditor/ckeditor5-utils/src/difftochanges';\n\n/**\n * Returns true if container children have mutated or more than a single text node was changed.\n *\n * @private\n * @param {Array.<module:engine/view/observer/mutationobserver~MutatedText|\n * module:engine/view/observer/mutationobserver~MutatedChildren>} mutations\n * @returns {Boolean}\n */\nexport function containerChildrenMutated( mutations ) {\n\tif ( mutations.length == 0 ) {\n\t\treturn false;\n\t}\n\n\t// Check if there is any mutation of `children` type or any mutation that changes more than one text node.\n\tfor ( const mutation of mutations ) {\n\t\tif ( mutation.type === 'children' && !getSingleTextNodeChange( mutation ) ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Returns change made to a single text node.\n *\n * @private\n * @param {module:engine/view/observer/mutationobserver~MutatedText|\n * module:engine/view/observer/mutationobserver~MutatedChildren} mutation\n * @returns {Object|undefined} Change object (see {@link module:utils/difftochanges~diffToChanges} output)\n * or undefined if more than a single text node was changed.\n */\nexport function getSingleTextNodeChange( mutation ) {\n\t// One new node.\n\tif ( mutation.newChildren.length - mutation.oldChildren.length != 1 ) {\n\t\treturn;\n\t}\n\n\t// Which is text.\n\tconst diffResult = diff( mutation.oldChildren, mutation.newChildren, compareChildNodes );\n\tconst changes = diffToChanges( diffResult, mutation.newChildren );\n\n\t// In case of [ delete, insert, insert ] the previous check will not exit.\n\tif ( changes.length > 1 ) {\n\t\treturn;\n\t}\n\n\tconst change = changes[ 0 ];\n\n\t// Which is text.\n\tif ( !( !!change.values[ 0 ] && change.values[ 0 ].is( 'text' ) ) ) {\n\t\treturn;\n\t}\n\n\treturn change;\n}\n\n/**\n * Checks whether two view nodes are identical, which means they are the same object\n * or contain exactly same data (in case of text nodes).\n *\n * @private\n * @param {module:engine/view/node~Node} oldChild\n * @param {module:engine/view/node~Node} newChild\n * @returns {Boolean}\n */\nexport function compareChildNodes( oldChild, newChild ) {\n\tif ( !!oldChild && oldChild.is( 'text' ) && !!newChild && newChild.is( 'text' ) ) {\n\t\treturn oldChild.data === newChild.data;\n\t} else {\n\t\treturn oldChild === newChild;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/difftochanges\n */\n\n/**\n * Creates a set of changes which need to be applied to the input in order to transform\n * it into the output. This function can be used with strings or arrays.\n *\n *\t\tconst input = Array.from( 'abc' );\n *\t\tconst output = Array.from( 'xaby' );\n *\t\tconst changes = diffToChanges( diff( input, output ), output );\n *\n *\t\tchanges.forEach( change => {\n *\t\t\tif ( change.type == 'insert' ) {\n *\t\t\t\tinput.splice( change.index, 0, ...change.values );\n *\t\t\t} else if ( change.type == 'delete' ) {\n *\t\t\t\tinput.splice( change.index, change.howMany );\n *\t\t\t}\n *\t\t} );\n *\n *\t\tinput.join( '' ) == output.join( '' ); // -> true\n *\n * @param {Array.<'equal'|'insert'|'delete'>} diff Result of {@link module:utils/diff~diff}.\n * @param {String|Array} output The string or array which was passed as diff's output.\n * @returns {Array.<Object>} Set of changes (insert or delete) which need to be applied to the input\n * in order to transform it into the output.\n */\nexport default function diffToChanges( diff, output ) {\n\tconst changes = [];\n\tlet index = 0;\n\tlet lastOperation;\n\n\tdiff.forEach( change => {\n\t\tif ( change == 'equal' ) {\n\t\t\tpushLast();\n\n\t\t\tindex++;\n\t\t} else if ( change == 'insert' ) {\n\t\t\tif ( isContinuationOf( 'insert' ) ) {\n\t\t\t\tlastOperation.values.push( output[ index ] );\n\t\t\t} else {\n\t\t\t\tpushLast();\n\n\t\t\t\tlastOperation = {\n\t\t\t\t\ttype: 'insert',\n\t\t\t\t\tindex,\n\t\t\t\t\tvalues: [ output[ index ] ]\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tindex++;\n\t\t} else /* if ( change == 'delete' ) */ {\n\t\t\tif ( isContinuationOf( 'delete' ) ) {\n\t\t\t\tlastOperation.howMany++;\n\t\t\t} else {\n\t\t\t\tpushLast();\n\n\t\t\t\tlastOperation = {\n\t\t\t\t\ttype: 'delete',\n\t\t\t\t\tindex,\n\t\t\t\t\thowMany: 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t} );\n\n\tpushLast();\n\n\treturn changes;\n\n\tfunction pushLast() {\n\t\tif ( lastOperation ) {\n\t\t\tchanges.push( lastOperation );\n\t\t\tlastOperation = null;\n\t\t}\n\t}\n\n\tfunction isContinuationOf( expected ) {\n\t\treturn lastOperation && lastOperation.type == expected;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/utils/injecttypingmutationshandling\n */\n\nimport diff from '@ckeditor/ckeditor5-utils/src/diff';\nimport DomConverter from '@ckeditor/ckeditor5-engine/src/view/domconverter';\n\nimport { getSingleTextNodeChange, containerChildrenMutated } from './utils';\n\n/**\n * Handles mutations caused by normal typing.\n *\n * @param {module:core/editor/editor~Editor} editor The editor instance.\n */\nexport default function injectTypingMutationsHandling( editor ) {\n\teditor.editing.view.document.on( 'mutations', ( evt, mutations, viewSelection ) => {\n\t\tnew MutationHandler( editor ).handle( mutations, viewSelection );\n\t} );\n}\n\n/**\n * Helper class for translating DOM mutations into model changes.\n *\n * @private\n */\nclass MutationHandler {\n\t/**\n\t * Creates an instance of the mutation handler.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor\n\t */\n\tconstructor( editor ) {\n\t\t/**\n\t\t * Editor instance for which mutations are handled.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:core/editor/editor~Editor} #editor\n\t\t */\n\t\tthis.editor = editor;\n\n\t\t/**\n\t\t * The editing controller.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/controller/editingcontroller~EditingController} #editing\n\t\t */\n\t\tthis.editing = this.editor.editing;\n\t}\n\n\t/**\n\t * Handles given mutations.\n\t *\n\t * @param {Array.<module:engine/view/observer/mutationobserver~MutatedText|\n\t * module:engine/view/observer/mutationobserver~MutatedChildren>} mutations\n\t * @param {module:engine/view/selection~Selection|null} viewSelection\n\t */\n\thandle( mutations, viewSelection ) {\n\t\tif ( containerChildrenMutated( mutations ) ) {\n\t\t\tthis._handleContainerChildrenMutations( mutations, viewSelection );\n\t\t} else {\n\t\t\tfor ( const mutation of mutations ) {\n\t\t\t\t// Fortunately it will never be both.\n\t\t\t\tthis._handleTextMutation( mutation, viewSelection );\n\t\t\t\tthis._handleTextNodeInsertion( mutation );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Handles situations when container's children mutated during input. This can happen when\n\t * the browser is trying to \"fix\" DOM in certain situations. For example, when the user starts to type\n\t * in `<p><a href=\"\"><i>Link{}</i></a></p>`, the browser might change the order of elements\n\t * to `<p><i><a href=\"\">Link</a>x{}</i></p>`. A similar situation happens when the spell checker\n\t * replaces a word wrapped with `<strong>` with a word wrapped with a `<b>` element.\n\t *\n\t * To handle such situations, the common DOM ancestor of all mutations is converted to the model representation\n\t * and then compared with the current model to calculate the proper text change.\n\t *\n\t * Note: Single text node insertion is handled in {@link #_handleTextNodeInsertion} and text node mutation is handled\n\t * in {@link #_handleTextMutation}).\n\t *\n\t * @private\n\t * @param {Array.<module:engine/view/observer/mutationobserver~MutatedText|\n\t * module:engine/view/observer/mutationobserver~MutatedChildren>} mutations\n\t * @param {module:engine/view/selection~Selection|null} viewSelection\n\t */\n\t_handleContainerChildrenMutations( mutations, viewSelection ) {\n\t\t// Get common ancestor of all mutations.\n\t\tconst mutationsCommonAncestor = getMutationsContainer( mutations );\n\n\t\t// Quit if there is no common ancestor.\n\t\tif ( !mutationsCommonAncestor ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst domConverter = this.editor.editing.view.domConverter;\n\n\t\t// Get common ancestor in DOM.\n\t\tconst domMutationCommonAncestor = domConverter.mapViewToDom( mutationsCommonAncestor );\n\n\t\t// Create fresh DomConverter so it will not use existing mapping and convert current DOM to model.\n\t\t// This wouldn't be needed if DomConverter would allow to create fresh view without checking any mappings.\n\t\tconst freshDomConverter = new DomConverter();\n\t\tconst modelFromCurrentDom = this.editor.data.toModel(\n\t\t\tfreshDomConverter.domToView( domMutationCommonAncestor )\n\t\t).getChild( 0 );\n\n\t\t// Current model.\n\t\tconst currentModel = this.editor.editing.mapper.toModelElement( mutationsCommonAncestor );\n\n\t\t// If common ancestor is not mapped, do not do anything. It probably is a parent of another view element.\n\t\t// That means that we would need to diff model elements (see `if` below). Better return early instead of\n\t\t// trying to get a reasonable model ancestor. It will fell into the `if` below anyway.\n\t\t// This situation happens for example for lists. If `<ul>` is a common ancestor, `currentModel` is `undefined`\n\t\t// because `<ul>` is not mapped (`<li>`s are).\n\t\t// See https://github.com/ckeditor/ckeditor5/issues/718.\n\t\tif ( !currentModel ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get children from both ancestors.\n\t\tconst modelFromDomChildren = Array.from( modelFromCurrentDom.getChildren() );\n\t\tconst currentModelChildren = Array.from( currentModel.getChildren() );\n\n\t\t// Remove the last `<softBreak>` from the end of `modelFromDomChildren` if there is no `<softBreak>` in current model.\n\t\t// If the described scenario happened, it means that this is a bogus `<br />` added by a browser.\n\t\tconst lastDomChild = modelFromDomChildren[ modelFromDomChildren.length - 1 ];\n\t\tconst lastCurrentChild = currentModelChildren[ currentModelChildren.length - 1 ];\n\n\t\tif ( lastDomChild && lastDomChild.is( 'softBreak' ) && lastCurrentChild && !lastCurrentChild.is( 'softBreak' ) ) {\n\t\t\tmodelFromDomChildren.pop();\n\t\t}\n\n\t\tconst schema = this.editor.model.schema;\n\n\t\t// Skip situations when common ancestor has any container elements.\n\t\tif ( !isSafeForTextMutation( modelFromDomChildren, schema ) || !isSafeForTextMutation( currentModelChildren, schema ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Replace &nbsp; inserted by the browser with normal space. See comment in `_handleTextMutation`.\n\t\t// Replace non-texts with any character. This is potentially dangerous but passes in manual tests. The thing is\n\t\t// that we need to take care of proper indexes so we cannot simply remove non-text elements from the content.\n\t\t// By inserting a character we keep all the real texts on their indexes.\n\t\tconst newText = modelFromDomChildren.map( item => item.is( 'text' ) ? item.data : '@' ).join( '' ).replace( /\\u00A0/g, ' ' );\n\t\tconst oldText = currentModelChildren.map( item => item.is( 'text' ) ? item.data : '@' ).join( '' ).replace( /\\u00A0/g, ' ' );\n\n\t\t// Do nothing if mutations created same text.\n\t\tif ( oldText === newText ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst diffResult = diff( oldText, newText );\n\n\t\tconst { firstChangeAt, insertions, deletions } = calculateChanges( diffResult );\n\n\t\t// Try setting new model selection according to passed view selection.\n\t\tlet modelSelectionRange = null;\n\n\t\tif ( viewSelection ) {\n\t\t\tmodelSelectionRange = this.editing.mapper.toModelRange( viewSelection.getFirstRange() );\n\t\t}\n\n\t\tconst insertText = newText.substr( firstChangeAt, insertions );\n\t\tconst removeRange = this.editor.model.createRange(\n\t\t\tthis.editor.model.createPositionAt( currentModel, firstChangeAt ),\n\t\t\tthis.editor.model.createPositionAt( currentModel, firstChangeAt + deletions )\n\t\t);\n\n\t\tthis.editor.execute( 'input', {\n\t\t\ttext: insertText,\n\t\t\trange: removeRange,\n\t\t\tresultRange: modelSelectionRange\n\t\t} );\n\t}\n\n\t/**\n\t * @private\n\t */\n\t_handleTextMutation( mutation, viewSelection ) {\n\t\tif ( mutation.type != 'text' ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Replace &nbsp; inserted by the browser with normal space.\n\t\t// We want only normal spaces in the model and in the view. Renderer and DOM Converter will be then responsible\n\t\t// for rendering consecutive spaces using &nbsp;, but the model and the view has to be clear.\n\t\t// Other feature may introduce inserting non-breakable space on specific key stroke (for example shift + space).\n\t\t// However then it will be handled outside of mutations, like enter key is.\n\t\t// The replacing is here because it has to be done before `diff` and `diffToChanges` functions, as they\n\t\t// take `newText` and compare it to (cleaned up) view.\n\t\t// It could also be done in mutation observer too, however if any outside plugin would like to\n\t\t// introduce additional events for mutations, they would get already cleaned up version (this may be good or not).\n\t\tconst newText = mutation.newText.replace( /\\u00A0/g, ' ' );\n\t\t// To have correct `diffResult`, we also compare view node text data with &nbsp; replaced by space.\n\t\tconst oldText = mutation.oldText.replace( /\\u00A0/g, ' ' );\n\n\t\t// Do nothing if mutations created same text.\n\t\tif ( oldText === newText ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst diffResult = diff( oldText, newText );\n\n\t\tconst { firstChangeAt, insertions, deletions } = calculateChanges( diffResult );\n\n\t\t// Try setting new model selection according to passed view selection.\n\t\tlet modelSelectionRange = null;\n\n\t\tif ( viewSelection ) {\n\t\t\tmodelSelectionRange = this.editing.mapper.toModelRange( viewSelection.getFirstRange() );\n\t\t}\n\n\t\t// Get the position in view and model where the changes will happen.\n\t\tconst viewPos = this.editing.view.createPositionAt( mutation.node, firstChangeAt );\n\t\tconst modelPos = this.editing.mapper.toModelPosition( viewPos );\n\t\tconst removeRange = this.editor.model.createRange( modelPos, modelPos.getShiftedBy( deletions ) );\n\t\tconst insertText = newText.substr( firstChangeAt, insertions );\n\n\t\tthis.editor.execute( 'input', {\n\t\t\ttext: insertText,\n\t\t\trange: removeRange,\n\t\t\tresultRange: modelSelectionRange\n\t\t} );\n\t}\n\n\t/**\n\t * @private\n\t */\n\t_handleTextNodeInsertion( mutation ) {\n\t\tif ( mutation.type != 'children' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst change = getSingleTextNodeChange( mutation );\n\t\tconst viewPos = this.editing.view.createPositionAt( mutation.node, change.index );\n\t\tconst modelPos = this.editing.mapper.toModelPosition( viewPos );\n\t\tconst insertedText = change.values[ 0 ].data;\n\n\t\tthis.editor.execute( 'input', {\n\t\t\t// Replace &nbsp; inserted by the browser with normal space.\n\t\t\t// See comment in `_handleTextMutation`.\n\t\t\t// In this case we don't need to do this before `diff` because we diff whole nodes.\n\t\t\t// Just change &nbsp; in case there are some.\n\t\t\ttext: insertedText.replace( /\\u00A0/g, ' ' ),\n\t\t\trange: this.editor.model.createRange( modelPos )\n\t\t} );\n\t}\n}\n\n// Returns first common ancestor of all mutations that is either {@link module:engine/view/containerelement~ContainerElement}\n// or {@link module:engine/view/rootelement~RootElement}.\n//\n// @private\n// @param {Array.<module:engine/view/observer/mutationobserver~MutatedText|\n// module:engine/view/observer/mutationobserver~MutatedChildren>} mutations\n// @returns {module:engine/view/containerelement~ContainerElement|engine/view/rootelement~RootElement|undefined}\nfunction getMutationsContainer( mutations ) {\n\tconst lca = mutations\n\t\t.map( mutation => mutation.node )\n\t\t.reduce( ( commonAncestor, node ) => {\n\t\t\treturn commonAncestor.getCommonAncestor( node, { includeSelf: true } );\n\t\t} );\n\n\tif ( !lca ) {\n\t\treturn;\n\t}\n\n\t// We need to look for container and root elements only, so check all LCA's\n\t// ancestors (starting from itself).\n\treturn lca.getAncestors( { includeSelf: true, parentFirst: true } )\n\t\t.find( element => element.is( 'containerElement' ) || element.is( 'rootElement' ) );\n}\n\n// Returns true if provided array contains content that won't be problematic during diffing and text mutation handling.\n//\n// @param {Array.<module:engine/model/node~Node>} children\n// @param {module:engine/model/schema~Schema} schema\n// @returns {Boolean}\nfunction isSafeForTextMutation( children, schema ) {\n\treturn children.every( child => schema.isInline( child ) );\n}\n\n// Calculates first change index and number of characters that should be inserted and deleted starting from that index.\n//\n// @private\n// @param diffResult\n// @returns {{insertions: number, deletions: number, firstChangeAt: *}}\nfunction calculateChanges( diffResult ) {\n\t// Index where the first change happens. Used to set the position from which nodes will be removed and where will be inserted.\n\tlet firstChangeAt = null;\n\t// Index where the last change happens. Used to properly count how many characters have to be removed and inserted.\n\tlet lastChangeAt = null;\n\n\t// Get `firstChangeAt` and `lastChangeAt`.\n\tfor ( let i = 0; i < diffResult.length; i++ ) {\n\t\tconst change = diffResult[ i ];\n\n\t\tif ( change != 'equal' ) {\n\t\t\tfirstChangeAt = firstChangeAt === null ? i : firstChangeAt;\n\t\t\tlastChangeAt = i;\n\t\t}\n\t}\n\n\t// How many characters, starting from `firstChangeAt`, should be removed.\n\tlet deletions = 0;\n\t// How many characters, starting from `firstChangeAt`, should be inserted.\n\tlet insertions = 0;\n\n\tfor ( let i = firstChangeAt; i <= lastChangeAt; i++ ) {\n\t\t// If there is no change (equal) or delete, the character is existing in `oldText`. We count it for removing.\n\t\tif ( diffResult[ i ] != 'insert' ) {\n\t\t\tdeletions++;\n\t\t}\n\n\t\t// If there is no change (equal) or insert, the character is existing in `newText`. We count it for inserting.\n\t\tif ( diffResult[ i ] != 'delete' ) {\n\t\t\tinsertions++;\n\t\t}\n\t}\n\n\treturn { insertions, deletions, firstChangeAt };\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/input\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport InputCommand from './inputcommand';\n\nimport injectUnsafeKeystrokesHandling from './utils/injectunsafekeystrokeshandling';\nimport injectTypingMutationsHandling from './utils/injecttypingmutationshandling';\n\n/**\n * Handles text input coming from the keyboard or other input methods.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Input extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Input';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// TODO The above default configuration value should be defined using editor.config.define() once it's fixed.\n\t\tconst inputCommand = new InputCommand( editor, editor.config.get( 'typing.undoStep' ) || 20 );\n\n\t\teditor.commands.add( 'input', inputCommand );\n\n\t\tinjectUnsafeKeystrokesHandling( editor );\n\t\tinjectTypingMutationsHandling( editor );\n\t}\n\n\t/**\n\t * Checks batch if it is a result of user input - e.g. typing.\n\t *\n\t *\t\tconst input = editor.plugins.get( 'Input' );\n\t *\n\t *\t\teditor.model.document.on( 'change:data', ( evt, batch ) => {\n\t *\t\t\tif ( input.isTyping( batch ) ) {\n\t *\t\t\t\tconsole.log( 'The user typed something...' );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * **Note:** This method checks if the batch was created using {@link module:typing/inputcommand~InputCommand 'input'}\n\t * command as typing changes coming from user input are inserted to the document using that command.\n\t *\n\t * @param {module:engine/model/batch~Batch} batch A batch to check.\n\t * @returns {Boolean}\n\t */\n\tisInput( batch ) {\n\t\tconst inputCommand = this.editor.commands.get( 'input' );\n\n\t\treturn inputCommand._batches.has( batch );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/deletecommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport count from '@ckeditor/ckeditor5-utils/src/count';\n\nimport ChangeBuffer from './utils/changebuffer';\n\n/**\n * The delete command. Used by the {@link module:typing/delete~Delete delete feature} to handle the <kbd>Delete</kbd> and\n * <kbd>Backspace</kbd> keys.\n *\n * @extends module:core/command~Command\n */\nexport default class DeleteCommand extends Command {\n\t/**\n\t * Creates an instance of the command.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor\n\t * @param {'forward'|'backward'} direction The directionality of the delete describing in what direction it\n\t * should consume the content when the selection is collapsed.\n\t */\n\tconstructor( editor, direction ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The directionality of the delete describing in what direction it should\n\t\t * consume the content when the selection is collapsed.\n\t\t *\n\t\t * @readonly\n\t\t * @member {'forward'|'backward'} #direction\n\t\t */\n\t\tthis.direction = direction;\n\n\t\t/**\n\t\t * Delete's change buffer used to group subsequent changes into batches.\n\t\t *\n\t\t * @readonly\n\t\t * @private\n\t\t * @member {typing.ChangeBuffer} #buffer\n\t\t */\n\t\tthis._buffer = new ChangeBuffer( editor.model, editor.config.get( 'typing.undoStep' ) );\n\t}\n\n\t/**\n\t * The current change buffer.\n\t *\n\t * @type {module:typing/utils/changebuffer~ChangeBuffer}\n\t */\n\tget buffer() {\n\t\treturn this._buffer;\n\t}\n\n\t/**\n\t * Executes the delete command. Depending on whether the selection is collapsed or not, deletes its content\n\t * or a piece of content in the {@link #direction defined direction}.\n\t *\n\t * @fires execute\n\t * @param {Object} [options] The command options.\n\t * @param {'character'} [options.unit='character'] See {@link module:engine/model/utils/modifyselection~modifySelection}'s options.\n\t * @param {Number} [options.sequence=1] A number describing which subsequent delete event it is without the key being released.\n\t * See the {@link module:engine/view/document~Document#event:delete} event data.\n\t * @param {module:engine/model/selection~Selection} [options.selection] Selection to remove. If not set, current model selection\n\t * will be used.\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tmodel.enqueueChange( this._buffer.batch, writer => {\n\t\t\tthis._buffer.lock();\n\n\t\t\tconst selection = writer.createSelection( options.selection || doc.selection );\n\n\t\t\t// Do not replace the whole selected content if selection was collapsed.\n\t\t\t// This prevents such situation:\n\t\t\t//\n\t\t\t// <h1></h1><p>[]</p>\t--> <h1>[</h1><p>]</p> \t\t--> <p></p>\n\t\t\t// starting content\t\t--> after `modifySelection`\t--> after `deleteContent`.\n\t\t\tconst doNotResetEntireContent = selection.isCollapsed;\n\n\t\t\t// Try to extend the selection in the specified direction.\n\t\t\tif ( selection.isCollapsed ) {\n\t\t\t\tmodel.modifySelection( selection, { direction: this.direction, unit: options.unit } );\n\t\t\t}\n\n\t\t\t// Check if deleting in an empty editor. See #61.\n\t\t\tif ( this._shouldEntireContentBeReplacedWithParagraph( options.sequence || 1 ) ) {\n\t\t\t\tthis._replaceEntireContentWithParagraph( writer );\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If selection is still collapsed, then there's nothing to delete.\n\t\t\tif ( selection.isCollapsed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet changeCount = 0;\n\n\t\t\tselection.getFirstRange().getMinimalFlatRanges().forEach( range => {\n\t\t\t\tchangeCount += count(\n\t\t\t\t\trange.getWalker( { singleCharacters: true, ignoreElementEnd: true, shallow: true } )\n\t\t\t\t);\n\t\t\t} );\n\n\t\t\tmodel.deleteContent( selection, { doNotResetEntireContent } );\n\t\t\tthis._buffer.input( changeCount );\n\n\t\t\twriter.setSelection( selection );\n\n\t\t\tthis._buffer.unlock();\n\t\t} );\n\t}\n\n\t/**\n\t * If the user keeps <kbd>Backspace</kbd> or <kbd>Delete</kbd> key pressed, the content of the current\n\t * editable will be cleared. However, this will not yet lead to resetting the remaining block to a paragraph\n\t * (which happens e.g. when the user does <kbd>Ctrl</kbd> + <kbd>A</kbd>, <kbd>Backspace</kbd>).\n\t *\n\t * But, if the user pressed the key in an empty editable for the first time,\n\t * we want to replace the entire content with a paragraph if:\n\t *\n\t * * the current limit element is empty,\n\t * * the paragraph is allowed in the limit element,\n\t * * the limit doesn't already have a paragraph inside.\n\t *\n\t * See https://github.com/ckeditor/ckeditor5-typing/issues/61.\n\t *\n\t * @private\n\t * @param {Number} sequence A number describing which subsequent delete event it is without the key being released.\n\t * @returns {Boolean}\n\t */\n\t_shouldEntireContentBeReplacedWithParagraph( sequence ) {\n\t\t// Does nothing if user pressed and held the \"Backspace\" or \"Delete\" key.\n\t\tif ( sequence > 1 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst selection = doc.selection;\n\t\tconst limitElement = model.schema.getLimitElement( selection );\n\n\t\t// If a collapsed selection contains the whole content it means that the content is empty\n\t\t// (from the user perspective).\n\t\tconst limitElementIsEmpty = selection.isCollapsed && selection.containsEntireContent( limitElement );\n\n\t\tif ( !limitElementIsEmpty ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( !model.schema.checkChild( limitElement, 'paragraph' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst limitElementFirstChild = limitElement.getChild( 0 );\n\n\t\t// Does nothing if the limit element already contains only a paragraph.\n\t\t// We ignore the case when paragraph might have some inline elements (<p><inlineWidget>[]</inlineWidget></p>)\n\t\t// because we don't support such cases yet and it's unclear whether inlineWidget shouldn't be a limit itself.\n\t\tif ( limitElementFirstChild && limitElementFirstChild.name === 'paragraph' ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * The entire content is replaced with the paragraph. Selection is moved inside the paragraph.\n\t *\n\t * @private\n\t */\n\t_replaceEntireContentWithParagraph( writer ) {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst selection = doc.selection;\n\t\tconst limitElement = model.schema.getLimitElement( selection );\n\t\tconst paragraph = writer.createElement( 'paragraph' );\n\n\t\twriter.remove( writer.createRangeIn( limitElement ) );\n\t\twriter.insert( paragraph, limitElement );\n\n\t\twriter.setSelection( paragraph, 0 );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/deleteobserver\n */\n\nimport Observer from '@ckeditor/ckeditor5-engine/src/view/observer/observer';\nimport DomEventData from '@ckeditor/ckeditor5-engine/src/view/observer/domeventdata';\nimport { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\n/**\n * Delete observer introduces the {@link module:engine/view/document~Document#event:delete} event.\n *\n * @extends module:engine/view/observer/observer~Observer\n */\nexport default class DeleteObserver extends Observer {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tconst document = view.document;\n\t\tlet sequence = 0;\n\n\t\tdocument.on( 'keyup', ( evt, data ) => {\n\t\t\tif ( data.keyCode == keyCodes.delete || data.keyCode == keyCodes.backspace ) {\n\t\t\t\tsequence = 0;\n\t\t\t}\n\t\t} );\n\n\t\tdocument.on( 'keydown', ( evt, data ) => {\n\t\t\tconst deleteData = {};\n\n\t\t\tif ( data.keyCode == keyCodes.delete ) {\n\t\t\t\tdeleteData.direction = 'forward';\n\t\t\t\tdeleteData.unit = 'character';\n\t\t\t} else if ( data.keyCode == keyCodes.backspace ) {\n\t\t\t\tdeleteData.direction = 'backward';\n\t\t\t\tdeleteData.unit = 'codePoint';\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst hasWordModifier = env.isMac ? data.altKey : data.ctrlKey;\n\t\t\tdeleteData.unit = hasWordModifier ? 'word' : deleteData.unit;\n\t\t\tdeleteData.sequence = ++sequence;\n\n\t\t\tfireViewDeleteEvent( evt, data.domEvent, deleteData );\n\t\t} );\n\n\t\t// `beforeinput` is handled only for Android devices. Desktop Chrome and iOS are skipped because they are working fine now.\n\t\tif ( env.isAndroid ) {\n\t\t\tdocument.on( 'beforeinput', ( evt, data ) => {\n\t\t\t\t// If event type is other than `deleteContentBackward` then this is not deleting.\n\t\t\t\tif ( data.domEvent.inputType != 'deleteContentBackward' ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst deleteData = {\n\t\t\t\t\tunit: 'codepoint',\n\t\t\t\t\tdirection: 'backward',\n\t\t\t\t\tsequence: 1\n\t\t\t\t};\n\n\t\t\t\t// Android IMEs may change the DOM selection on `beforeinput` event so that the selection contains all the text\n\t\t\t\t// that the IME wants to remove. We will pass this information to `delete` event so proper part of the content is removed.\n\t\t\t\t//\n\t\t\t\t// Sometimes it is only expanding by a one character (in case of collapsed selection). In this case we don't need to\n\t\t\t\t// set a different selection to remove, it will work just fine.\n\t\t\t\tconst domSelection = data.domTarget.ownerDocument.defaultView.getSelection();\n\n\t\t\t\tif ( domSelection.anchorNode == domSelection.focusNode && domSelection.anchorOffset + 1 != domSelection.focusOffset ) {\n\t\t\t\t\tdeleteData.selectionToRemove = view.domConverter.domSelectionToView( domSelection );\n\t\t\t\t}\n\n\t\t\t\tfireViewDeleteEvent( evt, data.domEvent, deleteData );\n\t\t\t} );\n\t\t}\n\n\t\tfunction fireViewDeleteEvent( originalEvent, domEvent, deleteData ) {\n\t\t\t// Save the event object to check later if it was stopped or not.\n\t\t\tlet event;\n\t\t\tdocument.once( 'delete', evt => ( event = evt ), { priority: Number.POSITIVE_INFINITY } );\n\n\t\t\tdocument.fire( 'delete', new DomEventData( document, domEvent, deleteData ) );\n\n\t\t\t// Stop the original event if `delete` event was stopped.\n\t\t\t// https://github.com/ckeditor/ckeditor5/issues/753\n\t\t\tif ( event && event.stop.called ) {\n\t\t\t\toriginalEvent.stop();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tobserve() {}\n}\n\n/**\n * Event fired when the user tries to delete content (e.g. presses <kbd>Delete</kbd> or <kbd>Backspace</kbd>).\n *\n * Note: This event is fired by the {@link module:typing/deleteobserver~DeleteObserver observer}\n * (usually registered by the {@link module:typing/delete~Delete delete feature}).\n *\n * @event module:engine/view/document~Document#event:delete\n * @param {module:engine/view/observer/domeventdata~DomEventData} data\n * @param {'forward'|'delete'} data.direction The direction in which the deletion should happen.\n * @param {'character'|'word'} data.unit The \"amount\" of content that should be deleted.\n * @param {Number} data.sequence A number describing which subsequent delete event it is without the key being released.\n * If it's 2 or more it means that the key was pressed and hold.\n * @param {module:engine/view/selection~Selection} [data.selectionToRemove] View selection which content should be removed. If not set,\n * current selection should be used.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/delete\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport DeleteCommand from './deletecommand';\nimport DeleteObserver from './deleteobserver';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\n/**\n * The delete and backspace feature. Handles the <kbd>Delete</kbd> and <kbd>Backspace</kbd> keys in the editor.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Delete extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Delete';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\n\t\tview.addObserver( DeleteObserver );\n\n\t\teditor.commands.add( 'forwardDelete', new DeleteCommand( editor, 'forward' ) );\n\t\teditor.commands.add( 'delete', new DeleteCommand( editor, 'backward' ) );\n\n\t\tthis.listenTo( viewDocument, 'delete', ( evt, data ) => {\n\t\t\tconst deleteCommandParams = { unit: data.unit, sequence: data.sequence };\n\n\t\t\t// If a specific (view) selection to remove was set, convert it to a model selection and set as a parameter for `DeleteCommand`.\n\t\t\tif ( data.selectionToRemove ) {\n\t\t\t\tconst modelSelection = editor.model.createSelection();\n\t\t\t\tconst ranges = [];\n\n\t\t\t\tfor ( const viewRange of data.selectionToRemove.getRanges() ) {\n\t\t\t\t\tranges.push( editor.editing.mapper.toModelRange( viewRange ) );\n\t\t\t\t}\n\n\t\t\t\tmodelSelection.setTo( ranges );\n\n\t\t\t\tdeleteCommandParams.selection = modelSelection;\n\t\t\t}\n\n\t\t\teditor.execute( data.direction == 'forward' ? 'forwardDelete' : 'delete', deleteCommandParams );\n\n\t\t\tdata.preventDefault();\n\n\t\t\tview.scrollToTheSelection();\n\t\t} );\n\n\t\t// Android IMEs have a quirk - they change DOM selection after the input changes were performed by the browser.\n\t\t// This happens on `keyup` event. Android doesn't know anything about our deletion and selection handling. Even if the selection\n\t\t// was changed during input events, IME remembers the position where the selection \"should\" be placed and moves it there.\n\t\t//\n\t\t// To prevent incorrect selection, we save the selection after deleting here and then re-set it on `keyup`. This has to be done\n\t\t// on DOM selection level, because on `keyup` the model selection is still the same as it was just after deletion, so it\n\t\t// wouldn't be changed and the fix would do nothing.\n\t\t//\n\t\tif ( env.isAndroid ) {\n\t\t\tlet domSelectionAfterDeletion = null;\n\n\t\t\tthis.listenTo( viewDocument, 'delete', ( evt, data ) => {\n\t\t\t\tconst domSelection = data.domTarget.ownerDocument.defaultView.getSelection();\n\n\t\t\t\tdomSelectionAfterDeletion = {\n\t\t\t\t\tanchorNode: domSelection.anchorNode,\n\t\t\t\t\tanchorOffset: domSelection.anchorOffset,\n\t\t\t\t\tfocusNode: domSelection.focusNode,\n\t\t\t\t\tfocusOffset: domSelection.focusOffset\n\t\t\t\t};\n\t\t\t}, { priority: 'lowest' } );\n\n\t\t\tthis.listenTo( viewDocument, 'keyup', ( evt, data ) => {\n\t\t\t\tif ( domSelectionAfterDeletion ) {\n\t\t\t\t\tconst domSelection = data.domTarget.ownerDocument.defaultView.getSelection();\n\n\t\t\t\t\tdomSelection.collapse( domSelectionAfterDeletion.anchorNode, domSelectionAfterDeletion.anchorOffset );\n\t\t\t\t\tdomSelection.extend( domSelectionAfterDeletion.focusNode, domSelectionAfterDeletion.focusOffset );\n\n\t\t\t\t\tdomSelectionAfterDeletion = null;\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/typing\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport Input from './input';\nimport Delete from './delete';\n\n/**\n * The typing feature. It handles typing.\n *\n * This is a \"glue\" plugin which loads the {@link module:typing/input~Input} and {@link module:typing/delete~Delete}\n * plugins.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Typing extends Plugin {\n\tstatic get requires() {\n\t\treturn [ Input, Delete ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Typing';\n\t}\n}\n\n/**\n * The configuration of the typing features. Used by the features from the `@ckeditor/ckeditor5-typing` package.\n *\n * Read more in {@link module:typing/typing~TypingConfig}.\n *\n * @member {module:typing/typing~TypingConfig} module:core/editor/editorconfig~EditorConfig#typing\n */\n\n/**\n * The configuration of the typing features. Used by the typing features in `@ckeditor/ckeditor5-typing` package.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n * \t\t\t\ttyping: ... // Typing feature options.\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.\n *\n * @interface TypingConfig\n */\n\n/**\n * The granularity of undo/redo for typing and deleting. The value `20` means (more or less) that a new undo step\n * is created every 20 characters are inserted or deleted.\n *\n * @member {Number} [module:typing/typing~TypingConfig#undoStep=20]\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/model/operation/nooperation\n */\n\nimport Operation from './operation';\n\n/**\n * Operation which is doing nothing (\"empty operation\", \"do-nothing operation\", \"noop\"). This is an operation,\n * which when executed does not change the tree model. It still has some parameters defined for transformation purposes.\n *\n * In most cases this operation is a result of transforming operations. When transformation returns\n * {@link module:engine/model/operation/nooperation~NoOperation} it means that changes done by the transformed operation\n * have already been applied.\n *\n * @extends module:engine/model/operation/operation~Operation\n */\nexport default class NoOperation extends Operation {\n\tget type() {\n\t\treturn 'noop';\n\t}\n\n\t/**\n\t * Creates and returns an operation that has the same parameters as this operation.\n\t *\n\t * @returns {module:engine/model/operation/nooperation~NoOperation} Clone of this operation.\n\t */\n\tclone() {\n\t\treturn new NoOperation( this.baseVersion );\n\t}\n\n\t/**\n\t * See {@link module:engine/model/operation/operation~Operation#getReversed `Operation#getReversed()`}.\n\t *\n\t * @returns {module:engine/model/operation/nooperation~NoOperation}\n\t */\n\tgetReversed() {\n\t\treturn new NoOperation( this.baseVersion + 1 );\n\t}\n\n\t_execute() {\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get className() {\n\t\treturn 'NoOperation';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nimport InsertOperation from './insertoperation';\nimport AttributeOperation from './attributeoperation';\nimport RenameOperation from './renameoperation';\nimport MarkerOperation from './markeroperation';\nimport MoveOperation from './moveoperation';\nimport RootAttributeOperation from './rootattributeoperation';\nimport MergeOperation from './mergeoperation';\nimport SplitOperation from './splitoperation';\nimport NoOperation from './nooperation';\nimport Range from '../range';\nimport Position from '../position';\n\nimport compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';\n\nconst transformations = new Map();\n\n/**\n * @module engine/model/operation/transform\n */\n\n/**\n * Sets a transformation function to be be used to transform instances of class `OperationA` by instances of class `OperationB`.\n *\n * The `transformationFunction` is passed three parameters:\n *\n * * `a` - operation to be transformed, an instance of `OperationA`,\n * * `b` - operation to be transformed by, an instance of `OperationB`,\n * * {@link module:engine/model/operation/transform~TransformationContext `context`} - object with additional information about\n * transformation context.\n *\n * The `transformationFunction` should return transformation result, which is an array with one or multiple\n * {@link module:engine/model/operation/operation~Operation operation} instances.\n *\n * @protected\n * @param {Function} OperationA\n * @param {Function} OperationB\n * @param {Function} transformationFunction Function to use for transforming.\n */\nfunction setTransformation( OperationA, OperationB, transformationFunction ) {\n\tlet aGroup = transformations.get( OperationA );\n\n\tif ( !aGroup ) {\n\t\taGroup = new Map();\n\t\ttransformations.set( OperationA, aGroup );\n\t}\n\n\taGroup.set( OperationB, transformationFunction );\n}\n\n/**\n * Returns a previously set transformation function for transforming an instance of `OperationA` by an instance of `OperationB`.\n *\n * If no transformation was set for given pair of operations, {@link module:engine/model/operation/transform~noUpdateTransformation}\n * is returned. This means that if no transformation was set, the `OperationA` instance will not change when transformed\n * by the `OperationB` instance.\n *\n * @private\n * @param {Function} OperationA\n * @param {Function} OperationB\n * @returns {Function} Function set to transform an instance of `OperationA` by an instance of `OperationB`.\n */\nfunction getTransformation( OperationA, OperationB ) {\n\tconst aGroup = transformations.get( OperationA );\n\n\tif ( aGroup && aGroup.has( OperationB ) ) {\n\t\treturn aGroup.get( OperationB );\n\t}\n\n\treturn noUpdateTransformation;\n}\n\n/**\n * A transformation function that only clones operation to transform, without changing it.\n *\n * @private\n * @param {module:engine/model/operation/operation~Operation} a Operation to transform.\n * @returns {Array.<module:engine/model/operation/operation~Operation>}\n */\nfunction noUpdateTransformation( a ) {\n\treturn [ a ];\n}\n\n/**\n * Transforms operation `a` by operation `b`.\n *\n * @param {module:engine/model/operation/operation~Operation} a Operation to be transformed.\n * @param {module:engine/model/operation/operation~Operation} b Operation to transform by.\n * @param {module:engine/model/operation/transform~TransformationContext} context Transformation context for this transformation.\n * @returns {Array.<module:engine/model/operation/operation~Operation>} Transformation result.\n */\nexport function transform( a, b, context = {} ) {\n\tconst transformationFunction = getTransformation( a.constructor, b.constructor );\n\n\ttry {\n\t\ta = a.clone();\n\n\t\treturn transformationFunction( a, b, context );\n\t} catch ( e ) {\n\t\t// @if CK_DEBUG // console.warn( 'Error during operation transformation!', e.message );\n\t\t// @if CK_DEBUG // console.warn( 'Transformed operation', a );\n\t\t// @if CK_DEBUG // console.warn( 'Operation transformed by', b );\n\t\t// @if CK_DEBUG // console.warn( 'context.aIsStrong', context.aIsStrong );\n\t\t// @if CK_DEBUG // console.warn( 'context.aWasUndone', context.aWasUndone );\n\t\t// @if CK_DEBUG // console.warn( 'context.bWasUndone', context.bWasUndone );\n\t\t// @if CK_DEBUG // console.warn( 'context.abRelation', context.abRelation );\n\t\t// @if CK_DEBUG // console.warn( 'context.baRelation', context.baRelation );\n\n\t\tthrow e;\n\t}\n}\n\n/**\n * Performs a transformation of two sets of operations - `operationsA` and `operationsB`. The transformation is two-way -\n * both transformed `operationsA` and transformed `operationsB` are returned.\n *\n * Note, that the first operation in each set should base on the same document state (\n * {@link module:engine/model/document~Document#version document version}).\n *\n * It is assumed that `operationsA` are \"more important\" during conflict resolution between two operations.\n *\n * New copies of both passed arrays and operations inside them are returned. Passed arguments are not altered.\n *\n * Base versions of the transformed operations sets are updated accordingly. For example, assume that base versions are `4`\n * and there are `3` operations in `operationsA` and `5` operations in `operationsB`. Then:\n *\n * * transformed `operationsA` will start from base version `9` (`4` base version + `5` operations B),\n * * transformed `operationsB` will start from base version `7` (`4` base version + `3` operations A).\n *\n * If no operation was broken into two during transformation, then both sets will end up with an operation that bases on version `11`:\n *\n * * transformed `operationsA` start from `9` and there are `3` of them, so the last will have `baseVersion` equal to `11`,\n * * transformed `operationsB` start from `7` and there are `5` of them, so the last will have `baseVersion` equal to `11`.\n *\n * @param {Array.<module:engine/model/operation/operation~Operation>} operationsA\n * @param {Array.<module:engine/model/operation/operation~Operation>} operationsB\n * @param {Object} options Additional transformation options.\n * @param {module:engine/model/document~Document|null} options.document Document which the operations change.\n * @param {Boolean} [options.useRelations=false] Whether during transformation relations should be used (used during undo for\n * better conflict resolution).\n * @param {Boolean} [options.padWithNoOps=false] Whether additional {@link module:engine/model/operation/nooperation~NoOperation}s\n * should be added to the transformation results to force the same last base version for both transformed sets (in case\n * if some operations got broken into multiple operations during transformation).\n * @returns {Object} Transformation result.\n * @returns {Array.<module:engine/model/operation/operation~Operation>} return.operationsA Transformed `operationsA`.\n * @returns {Array.<module:engine/model/operation/operation~Operation>} return.operationsB Transformed `operationsB`.\n * @returns {Map} return.originalOperations A map that links transformed operations to original operations. The keys are the transformed\n * operations and the values are the original operations from the input (`operationsA` and `operationsB`).\n */\nexport function transformSets( operationsA, operationsB, options ) {\n\t// Create new arrays so the originally passed arguments are not changed.\n\t// No need to clone operations, they are cloned as they are transformed.\n\toperationsA = operationsA.slice();\n\toperationsB = operationsB.slice();\n\n\tconst contextFactory = new ContextFactory( options.document, options.useRelations, options.forceWeakRemove );\n\tcontextFactory.setOriginalOperations( operationsA );\n\tcontextFactory.setOriginalOperations( operationsB );\n\n\tconst originalOperations = contextFactory.originalOperations;\n\n\t// If one of sets is empty there is simply nothing to transform, so return sets as they are.\n\tif ( operationsA.length == 0 || operationsB.length == 0 ) {\n\t\treturn { operationsA, operationsB, originalOperations };\n\t}\n\t//\n\t// Following is a description of transformation process:\n\t//\n\t// There are `operationsA` and `operationsB` to be transformed, both by both.\n\t//\n\t// So, suppose we have sets of two operations each: `operationsA` = `[ a1, a2 ]`, `operationsB` = `[ b1, b2 ]`.\n\t//\n\t// Remember, that we can only transform operations that base on the same context. We assert that `a1` and `b1` base on\n\t// the same context and we transform them. Then, we get `a1'` and `b1'`. `a2` bases on a context with `a1` -- `a2`\n\t// is an operation that followed `a1`. Similarly, `b2` bases on a context with `b1`.\n\t//\n\t// However, since `a1'` is a result of transformation by `b1`, `a1'` now also has a context with `b1`. This means that\n\t// we can safely transform `a1'` by `b2`. As we finish transforming `a1`, we also transformed all `operationsB`.\n\t// All `operationsB` also have context including `a1`. Now, we can properly transform `a2` by those operations.\n\t//\n\t// The transformation process can be visualized on a transformation diagram (\"diamond diagram\"):\n\t//\n\t// [the initial state]\n\t// [common for a1 and b1]\n\t//\n\t// *\n\t// / \\\n\t// / \\\n\t// b1 a1\n\t// / \\\n\t// / \\\n\t// * *\n\t// / \\ / \\\n\t// / \\ / \\\n\t// b2 a1' b1' a2\n\t// / \\ / \\\n\t// / \\ / \\\n\t// * * *\n\t// \\ / \\ /\n\t// \\ / \\ /\n\t// a1'' b2' a2' b1''\n\t// \\ / \\ /\n\t// \\ / \\ /\n\t// * *\n\t// \\ /\n\t// \\ /\n\t// a2'' b2''\n\t// \\ /\n\t// \\ /\n\t// *\n\t//\n\t// [the final state]\n\t//\n\t// The final state can be reached from the initial state by applying `a1`, `a2`, `b1''` and `b2''`, as well as by\n\t// applying `b1`, `b2`, `a1''`, `a2''`. Note how the operations get to a proper common state before each pair is\n\t// transformed.\n\t//\n\t// Another thing to consider is that an operation during transformation can be broken into multiple operations.\n\t// Suppose that `a1` * `b1` = `[ a11', a12' ]` (instead of `a1'` that we considered previously).\n\t//\n\t// In that case, we leave `a12'` for later and we continue transforming `a11'` until it is transformed by all `operationsB`\n\t// (in our case it is just `b2`). At this point, `b1` is transformed by \"whole\" `a1`, while `b2` is only transformed\n\t// by `a11'`. Similarly, `a12'` is only transformed by `b1`. This leads to a conclusion that we need to start transforming `a12'`\n\t// from the moment just after it was broken. So, `a12'` is transformed by `b2`. Now, \"the whole\" `a1` is transformed\n\t// by `operationsB`, while all `operationsB` are transformed by \"the whole\" `a1`. This means that we can continue with\n\t// following `operationsA` (in our case it is just `a2`).\n\t//\n\t// Of course, also `operationsB` can be broken. However, since we focus on transforming operation `a` to the end,\n\t// the only thing to do is to store both pieces of operation `b`, so that the next transformed operation `a` will\n\t// be transformed by both of them.\n\t//\n\t// *\n\t// / \\\n\t// / \\\n\t// / \\\n\t// b1 a1\n\t// / \\\n\t// / \\\n\t// / \\\n\t// * *\n\t// / \\ / \\\n\t// / a11' / \\\n\t// / \\ / \\\n\t// b2 * b1' a2\n\t// / / \\ / \\\n\t// / / a12' / \\\n\t// / / \\ / \\\n\t// * b2' * *\n\t// \\ / / \\ /\n\t// a11'' / b21'' \\ /\n\t// \\ / / \\ /\n\t// * * a2' b1''\n\t// \\ / \\ \\ /\n\t// a12'' b22''\\ \\ /\n\t// \\ / \\ \\ /\n\t// * a2'' *\n\t// \\ \\ /\n\t// \\ \\ b21'''\n\t// \\ \\ /\n\t// a2''' *\n\t// \\ /\n\t// \\ b22'''\n\t// \\ /\n\t// *\n\t//\n\t// Note, how `a1` is broken and transformed into `a11'` and `a12'`, while `b2'` got broken and transformed into `b21''` and `b22''`.\n\t//\n\t// Having all that on mind, here is an outline for the transformation process algorithm:\n\t//\n\t// 1. We have `operationsA` and `operationsB` array, which we dynamically update as the transformation process goes.\n\t//\n\t// 2. We take next (or first) operation from `operationsA` and check from which operation `b` we need to start transforming it.\n\t// All original `operationsA` are set to be transformed starting from the first operation `b`.\n\t//\n\t// 3. We take operations from `operationsB`, one by one, starting from the correct one, and transform operation `a`\n\t// by operation `b` (and vice versa). We update `operationsA` and `operationsB` by replacing the original operations\n\t// with the transformation results.\n\t//\n\t// 4. If operation is broken into multiple operations, we save all the new operations in the place of the\n\t// original operation.\n\t//\n\t// 5. Additionally, if operation `a` was broken, for the \"new\" operation, we remember from which operation `b` it should\n\t// be transformed by.\n\t//\n\t// 6. We continue transforming \"current\" operation `a` until it is transformed by all `operationsB`. Then, go to 2.\n\t// unless the last operation `a` was transformed.\n\t//\n\t// The actual implementation of the above algorithm is slightly different, as only one loop (while) is used.\n\t// The difference is that we have \"current\" `a` operation to transform and we store the index of the next `b` operation\n\t// to transform by. Each loop operates on two indexes then: index pointing to currently processed `a` operation and\n\t// index pointing to next `b` operation. Each loop is just one `a * b` + `b * a` transformation. After each loop\n\t// operation `b` index is updated. If all `b` operations were visited for the current `a` operation, we change\n\t// current `a` operation index to the next one.\n\t//\n\n\t// For each operation `a`, keeps information what is the index in `operationsB` from which the transformation should start.\n\tconst nextTransformIndex = new WeakMap();\n\n\t// For all the original `operationsA`, set that they should be transformed starting from the first of `operationsB`.\n\tfor ( const op of operationsA ) {\n\t\tnextTransformIndex.set( op, 0 );\n\t}\n\n\t// Additional data that is used for some postprocessing after the main transformation process is done.\n\tconst data = {\n\t\tnextBaseVersionA: operationsA[ operationsA.length - 1 ].baseVersion + 1,\n\t\tnextBaseVersionB: operationsB[ operationsB.length - 1 ].baseVersion + 1,\n\t\toriginalOperationsACount: operationsA.length,\n\t\toriginalOperationsBCount: operationsB.length\n\t};\n\n\t// Index of currently transformed operation `a`.\n\tlet i = 0;\n\n\t// While not all `operationsA` are transformed...\n\twhile ( i < operationsA.length ) {\n\t\t// Get \"current\" operation `a`.\n\t\tconst opA = operationsA[ i ];\n\n\t\t// For the \"current\" operation `a`, get the index of the next operation `b` to transform by.\n\t\tconst indexB = nextTransformIndex.get( opA );\n\n\t\t// If operation `a` was already transformed by every operation `b`, change \"current\" operation `a` to the next one.\n\t\tif ( indexB == operationsB.length ) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst opB = operationsB[ indexB ];\n\n\t\t// Transform `a` by `b` and `b` by `a`.\n\t\tconst newOpsA = transform( opA, opB, contextFactory.getContext( opA, opB, true ) );\n\t\tconst newOpsB = transform( opB, opA, contextFactory.getContext( opB, opA, false ) );\n\t\t// As a result we get one or more `newOpsA` and one or more `newOpsB` operations.\n\n\t\t// Update contextual information about operations.\n\t\tcontextFactory.updateRelation( opA, opB );\n\n\t\tcontextFactory.setOriginalOperations( newOpsA, opA );\n\t\tcontextFactory.setOriginalOperations( newOpsB, opB );\n\n\t\t// For new `a` operations, update their index of the next operation `b` to transform them by.\n\t\t//\n\t\t// This is needed even if there was only one result (`a` was not broken) because that information is used\n\t\t// at the beginning of this loop every time.\n\t\tfor ( const newOpA of newOpsA ) {\n\t\t\t// Acknowledge, that operation `b` also might be broken into multiple operations.\n\t\t\t//\n\t\t\t// This is why we raise `indexB` not just by 1. If `newOpsB` are multiple operations, they will be\n\t\t\t// spliced in the place of `opB`. So we need to change `transformBy` accordingly, so that an operation won't\n\t\t\t// be transformed by the same operation (part of it) again.\n\t\t\tnextTransformIndex.set( newOpA, indexB + newOpsB.length );\n\t\t}\n\n\t\t// Update `operationsA` and `operationsB` with the transformed versions.\n\t\toperationsA.splice( i, 1, ...newOpsA );\n\t\toperationsB.splice( indexB, 1, ...newOpsB );\n\t}\n\n\tif ( options.padWithNoOps ) {\n\t\t// If no-operations padding is enabled, count how many extra `a` and `b` operations were generated.\n\t\tconst brokenOperationsACount = operationsA.length - data.originalOperationsACount;\n\t\tconst brokenOperationsBCount = operationsB.length - data.originalOperationsBCount;\n\n\t\t// Then, if that number is not the same, pad `operationsA` or `operationsB` with correct number of no-ops so\n\t\t// that the base versions are equalled.\n\t\t//\n\t\t// Note that only one array will be updated, as only one of those subtractions can be greater than zero.\n\t\tpadWithNoOps( operationsA, brokenOperationsBCount - brokenOperationsACount );\n\t\tpadWithNoOps( operationsB, brokenOperationsACount - brokenOperationsBCount );\n\t}\n\n\t// Finally, update base versions of transformed operations.\n\tupdateBaseVersions( operationsA, data.nextBaseVersionB );\n\tupdateBaseVersions( operationsB, data.nextBaseVersionA );\n\n\treturn { operationsA, operationsB, originalOperations };\n}\n\n// Gathers additional data about operations processed during transformation. Can be used to obtain contextual information\n// about two operations that are about to be transformed. This contextual information can be used for better conflict resolution.\nclass ContextFactory {\n\t// Creates `ContextFactory` instance.\n\t//\n\t// @param {module:engine/model/document~Document} document Document which the operations change.\n\t// @param {Boolean} useRelations Whether during transformation relations should be used (used during undo for\n\t// better conflict resolution).\n\t// @param {Boolean} [forceWeakRemove=false] If set to `false`, remove operation will be always stronger than move operation,\n\t// so the removed nodes won't end up back in the document root. When set to `true`, context data will be used.\n\tconstructor( document, useRelations, forceWeakRemove = false ) {\n\t\t// For each operation that is created during transformation process, we keep a reference to the original operation\n\t\t// which it comes from. The original operation works as a kind of \"identifier\". Every contextual information\n\t\t// gathered during transformation that we want to save for given operation, is actually saved for the original operation.\n\t\t// This way no matter if operation `a` is cloned, then transformed, even breaks, we still have access to the previously\n\t\t// gathered data through original operation reference.\n\t\tthis.originalOperations = new Map();\n\n\t\t// `model.History` instance which information about undone operations will be taken from.\n\t\tthis._history = document.history;\n\n\t\t// Whether additional context should be used.\n\t\tthis._useRelations = useRelations;\n\n\t\tthis._forceWeakRemove = !!forceWeakRemove;\n\n\t\t// Relations is a double-map structure (maps in map) where for two operations we store how those operations were related\n\t\t// to each other. Those relations are evaluated during transformation process. For every transformated pair of operations\n\t\t// we keep relations between them.\n\t\tthis._relations = new Map();\n\t}\n\n\t// Sets \"original operation\" for given operations.\n\t//\n\t// During transformation process, operations are cloned, then changed, then processed again, sometimes broken into two\n\t// or multiple operations. When gathering additional data it is important that all operations can be somehow linked\n\t// so a cloned and transformed \"version\" still kept track of the data assigned earlier to it.\n\t//\n\t// The original operation object will be used as such an universal linking id. Throughout the transformation process\n\t// all cloned operations will refer to \"the original operation\" when storing and reading additional data.\n\t//\n\t// If `takeFrom` is not set, each operation from `operations` array will be assigned itself as \"the original operation\".\n\t// This should be used as an initialization step.\n\t//\n\t// If `takeFrom` is set, each operation from `operations` will be assigned the same original operation as assigned\n\t// for `takeFrom` operation. This should be used to update original operations. It should be used in a way that\n\t// `operations` are the result of `takeFrom` transformation to ensure proper \"original operation propagation\".\n\t//\n\t// @param {Array.<module:engine/model/operation/operation~Operation>} operations\n\t// @param {module:engine/model/operation/operation~Operation|null} [takeFrom=null]\n\tsetOriginalOperations( operations, takeFrom = null ) {\n\t\tconst originalOperation = takeFrom ? this.originalOperations.get( takeFrom ) : null;\n\n\t\tfor ( const operation of operations ) {\n\t\t\tthis.originalOperations.set( operation, originalOperation || operation );\n\t\t}\n\t}\n\n\t// Saves a relation between operations `opA` and `opB`.\n\t//\n\t// Relations are then later used to help solve conflicts when operations are transformed.\n\t//\n\t// @param {module:engine/model/operation/operation~Operation} opA\n\t// @param {module:engine/model/operation/operation~Operation} opB\n\tupdateRelation( opA, opB ) {\n\t\t// The use of relations is described in a bigger detail in transformation functions.\n\t\t//\n\t\t// In brief, this function, for specified pairs of operation types, checks how positions defined in those operations relate.\n\t\t// Then those relations are saved. For example, for two move operations, it is saved if one of those operations target\n\t\t// position is before the other operation source position. This kind of information gives contextual information when\n\t\t// transformation is used during undo. Similar checks are done for other pairs of operations.\n\t\t//\n\t\tswitch ( opA.constructor ) {\n\t\t\tcase MoveOperation: {\n\t\t\t\tswitch ( opB.constructor ) {\n\t\t\t\t\tcase MergeOperation: {\n\t\t\t\t\t\tif ( opA.targetPosition.isEqual( opB.sourcePosition ) || opB.movedRange.containsPosition( opA.targetPosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'insertAtSource' );\n\t\t\t\t\t\t} else if ( opA.targetPosition.isEqual( opB.deletionPosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'insertBetween' );\n\t\t\t\t\t\t} else if ( opA.targetPosition.isAfter( opB.sourcePosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'moveTargetAfter' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase MoveOperation: {\n\t\t\t\t\t\tif ( opA.targetPosition.isEqual( opB.sourcePosition ) || opA.targetPosition.isBefore( opB.sourcePosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'insertBefore' );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'insertAfter' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase SplitOperation: {\n\t\t\t\tswitch ( opB.constructor ) {\n\t\t\t\t\tcase MergeOperation: {\n\t\t\t\t\t\tif ( opA.splitPosition.isBefore( opB.sourcePosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'splitBefore' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase MoveOperation: {\n\t\t\t\t\t\tif ( opA.splitPosition.isEqual( opB.sourcePosition ) || opA.splitPosition.isBefore( opB.sourcePosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'splitBefore' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MergeOperation: {\n\t\t\t\tswitch ( opB.constructor ) {\n\t\t\t\t\tcase MergeOperation: {\n\t\t\t\t\t\tif ( !opA.targetPosition.isEqual( opB.sourcePosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'mergeTargetNotMoved' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( opA.sourcePosition.isEqual( opB.targetPosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'mergeSourceNotMoved' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( opA.sourcePosition.isEqual( opB.sourcePosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'mergeSameElement' );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase SplitOperation: {\n\t\t\t\t\t\tif ( opA.sourcePosition.isEqual( opB.splitPosition ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, 'splitAtSource' );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarkerOperation: {\n\t\t\t\tconst markerRange = opA.newRange;\n\n\t\t\t\tif ( !markerRange ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tswitch ( opB.constructor ) {\n\t\t\t\t\tcase MoveOperation: {\n\t\t\t\t\t\tconst movedRange = Range._createFromPositionAndShift( opB.sourcePosition, opB.howMany );\n\n\t\t\t\t\t\tconst affectedLeft = movedRange.containsPosition( markerRange.start ) ||\n\t\t\t\t\t\t\tmovedRange.start.isEqual( markerRange.start );\n\n\t\t\t\t\t\tconst affectedRight = movedRange.containsPosition( markerRange.end ) ||\n\t\t\t\t\t\t\tmovedRange.end.isEqual( markerRange.end );\n\n\t\t\t\t\t\tif ( ( affectedLeft || affectedRight ) && !movedRange.containsRange( markerRange ) ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, {\n\t\t\t\t\t\t\t\tside: affectedLeft ? 'left' : 'right',\n\t\t\t\t\t\t\t\tpath: affectedLeft ? markerRange.start.path.slice() : markerRange.end.path.slice()\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase MergeOperation: {\n\t\t\t\t\t\tconst wasInLeftElement = markerRange.start.isEqual( opB.targetPosition );\n\t\t\t\t\t\tconst wasStartBeforeMergedElement = markerRange.start.isEqual( opB.deletionPosition );\n\t\t\t\t\t\tconst wasEndBeforeMergedElement = markerRange.end.isEqual( opB.deletionPosition );\n\t\t\t\t\t\tconst wasInRightElement = markerRange.end.isEqual( opB.sourcePosition );\n\n\t\t\t\t\t\tif ( wasInLeftElement || wasStartBeforeMergedElement || wasEndBeforeMergedElement || wasInRightElement ) {\n\t\t\t\t\t\t\tthis._setRelation( opA, opB, {\n\t\t\t\t\t\t\t\twasInLeftElement,\n\t\t\t\t\t\t\t\twasStartBeforeMergedElement,\n\t\t\t\t\t\t\t\twasEndBeforeMergedElement,\n\t\t\t\t\t\t\t\twasInRightElement\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Evaluates and returns contextual information about two given operations `opA` and `opB` which are about to be transformed.\n\t//\n\t// @param {module:engine/model/operation/operation~Operation} opA\n\t// @param {module:engine/model/operation/operation~Operation} opB\n\t// @returns {module:engine/model/operation/transform~TransformationContext}\n\tgetContext( opA, opB, aIsStrong ) {\n\t\treturn {\n\t\t\taIsStrong,\n\t\t\taWasUndone: this._wasUndone( opA ),\n\t\t\tbWasUndone: this._wasUndone( opB ),\n\t\t\tabRelation: this._useRelations ? this._getRelation( opA, opB ) : null,\n\t\t\tbaRelation: this._useRelations ? this._getRelation( opB, opA ) : null,\n\t\t\tforceWeakRemove: this._forceWeakRemove\n\t\t};\n\t}\n\n\t// Returns whether given operation `op` has already been undone.\n\t//\n\t// Information whether an operation was undone gives more context when making a decision when two operations are in conflict.\n\t//\n\t// @param {module:engine/model/operation/operation~Operation} op\n\t// @returns {Boolean}\n\t_wasUndone( op ) {\n\t\t// For `op`, get its original operation. After all, if `op` is a clone (or even transformed clone) of another\n\t\t// operation, literally `op` couldn't be undone. It was just generated. If anything, it was the operation it origins\n\t\t// from which was undone. So get that original operation.\n\t\tconst originalOp = this.originalOperations.get( op );\n\n\t\t// And check with the document if the original operation was undone.\n\t\treturn originalOp.wasUndone || this._history.isUndoneOperation( originalOp );\n\t}\n\n\t// Returns a relation between `opA` and an operation which is undone by `opB`. This can be `String` value if a relation\n\t// was set earlier or `null` if there was no relation between those operations.\n\t//\n\t// This is a little tricky to understand, so let's compare it to `ContextFactory#_wasUndone`.\n\t//\n\t// When `wasUndone( opB )` is used, we check if the `opB` has already been undone. It is obvious, that the\n\t// undoing operation must happen after the undone operation. So, essentially, we have `opB`, we take document history,\n\t// we look forward in the future and ask if in that future `opB` was undone.\n\t//\n\t// Relations is a backward process to `wasUndone()`.\n\t//\n\t// Long story short - using relations is asking what happened in the past. Looking back. This time we have an undoing\n\t// operation `opB` which has undone some other operation. When there is a transformation `opA` x `opB` and there is\n\t// a conflict to solve and `opB` is an undoing operation, we can look back in the history and see what was a relation\n\t// between `opA` and the operation which `opB` undone. Basing on that relation from the past, we can now make\n\t// a better decision when resolving a conflict between two operations, because we know more about the context of\n\t// those two operations.\n\t//\n\t// This is why this function does not return a relation directly between `opA` and `opB` because we need to look\n\t// back to search for a meaningful contextual information.\n\t//\n\t// @param {module:engine/model/operation/operation~Operation} opA\n\t// @param {module:engine/model/operation/operation~Operation} opB\n\t// @returns {String|null}\n\t_getRelation( opA, opB ) {\n\t\t// Get the original operation. Similarly as in `wasUndone()` it is used as an universal identifier for stored data.\n\t\tconst origB = this.originalOperations.get( opB );\n\t\tconst undoneB = this._history.getUndoneOperation( origB );\n\n\t\t// If `opB` is not undoing any operation, there is no relation.\n\t\tif ( !undoneB ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst origA = this.originalOperations.get( opA );\n\t\tconst relationsA = this._relations.get( origA );\n\n\t\t// Get all relations for `opA`, and check if there is a relation with `opB`-undone-counterpart. If so, return it.\n\t\tif ( relationsA ) {\n\t\t\treturn relationsA.get( undoneB ) || null;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// Helper function for `ContextFactory#updateRelations`.\n\t//\n\t// @private\n\t// @param {module:engine/model/operation/operation~Operation} opA\n\t// @param {module:engine/model/operation/operation~Operation} opB\n\t// @param {String} relation\n\t_setRelation( opA, opB, relation ) {\n\t\t// As always, setting is for original operations, not the clones/transformed operations.\n\t\tconst origA = this.originalOperations.get( opA );\n\t\tconst origB = this.originalOperations.get( opB );\n\n\t\tlet relationsA = this._relations.get( origA );\n\n\t\tif ( !relationsA ) {\n\t\t\trelationsA = new Map();\n\t\t\tthis._relations.set( origA, relationsA );\n\t\t}\n\n\t\trelationsA.set( origB, relation );\n\t}\n}\n\n/**\n * Holds additional contextual information about a transformed pair of operations (`a` and `b`). Those information\n * can be used for better conflict resolving.\n *\n * @typedef {Object} module:engine/model/operation/transform~TransformationContext\n *\n * @property {Boolean} aIsStrong Whether `a` is strong operation in this transformation, or weak.\n * @property {Boolean} aWasUndone Whether `a` operation was undone.\n * @property {Boolean} bWasUndone Whether `b` operation was undone.\n * @property {String|null} abRelation The relation between `a` operation and an operation undone by `b` operation.\n * @property {String|null} baRelation The relation between `b` operation and an operation undone by `a` operation.\n */\n\n/**\n * An utility function that updates {@link module:engine/model/operation/operation~Operation#baseVersion base versions}\n * of passed operations.\n *\n * The function simply sets `baseVersion` as a base version of the first passed operation and then increments it for\n * each following operation in `operations`.\n *\n * @private\n * @param {Array.<module:engine/model/operation/operation~Operation>} operations Operations to update.\n * @param {Number} baseVersion Base version to set for the first operation in `operations`.\n */\nfunction updateBaseVersions( operations, baseVersion ) {\n\tfor ( const operation of operations ) {\n\t\toperation.baseVersion = baseVersion++;\n\t}\n}\n\n/**\n * Adds `howMany` instances of {@link module:engine/model/operation/nooperation~NoOperation} to `operations` set.\n *\n * @private\n * @param {Array.<module:engine/model/operation/operation~Operation>} operations\n * @param {Number} howMany\n */\nfunction padWithNoOps( operations, howMany ) {\n\tfor ( let i = 0; i < howMany; i++ ) {\n\t\toperations.push( new NoOperation( 0 ) );\n\t}\n}\n\n// -----------------------\n\nsetTransformation( AttributeOperation, AttributeOperation, ( a, b, context ) => {\n\tif ( a.key === b.key ) {\n\t\t// If operations attributes are in conflict, check if their ranges intersect and manage them properly.\n\n\t\t// First, we want to apply change to the part of a range that has not been changed by the other operation.\n\t\tconst operations = a.range.getDifference( b.range ).map( range => {\n\t\t\treturn new AttributeOperation( range, a.key, a.oldValue, a.newValue, 0 );\n\t\t} );\n\n\t\t// Then we take care of the common part of ranges.\n\t\tconst common = a.range.getIntersection( b.range );\n\n\t\tif ( common ) {\n\t\t\t// If this operation is more important, we also want to apply change to the part of the\n\t\t\t// original range that has already been changed by the other operation. Since that range\n\t\t\t// got changed we also have to update `oldValue`.\n\t\t\tif ( context.aIsStrong ) {\n\t\t\t\toperations.push( new AttributeOperation( common, b.key, b.newValue, a.newValue, 0 ) );\n\t\t\t}\n\t\t}\n\n\t\tif ( operations.length == 0 ) {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t}\n\n\t\treturn operations;\n\t} else {\n\t\t// If operations don't conflict, simply return an array containing just a clone of this operation.\n\t\treturn [ a ];\n\t}\n} );\n\nsetTransformation( AttributeOperation, InsertOperation, ( a, b ) => {\n\t// Case 1:\n\t//\n\t// The attribute operation range includes the position where nodes were inserted.\n\t// There are two possible scenarios: the inserted nodes were text and they should receive attributes or\n\t// the inserted nodes were elements and they should not receive attributes.\n\t//\n\tif ( a.range.start.hasSameParentAs( b.position ) && a.range.containsPosition( b.position ) ) {\n\t\t// If new nodes should not receive attributes, two separated ranges will be returned.\n\t\t// Otherwise, one expanded range will be returned.\n\t\tconst range = a.range._getTransformedByInsertion( b.position, b.howMany, !b.shouldReceiveAttributes );\n\t\tconst result = range.map( r => {\n\t\t\treturn new AttributeOperation( r, a.key, a.oldValue, a.newValue, a.baseVersion );\n\t\t} );\n\n\t\tif ( b.shouldReceiveAttributes ) {\n\t\t\t// `AttributeOperation#range` includes some newly inserted text.\n\t\t\t// The operation should also change the attribute of that text. An example:\n\t\t\t//\n\t\t\t// Bold should be applied on the following range:\n\t\t\t// <p>Fo[zb]ar</p>\n\t\t\t//\n\t\t\t// In meantime, new text is typed:\n\t\t\t// <p>Fozxxbar</p>\n\t\t\t//\n\t\t\t// Bold should be applied also on the new text:\n\t\t\t// <p>Fo[zxxb]ar</p>\n\t\t\t// <p>Fo<$text bold=\"true\">zxxb</$text>ar</p>\n\t\t\t//\n\t\t\t// There is a special case to consider here to consider.\n\t\t\t//\n\t\t\t// Consider setting an attribute with multiple possible values, for example `highlight`. The inserted text might\n\t\t\t// have already an attribute value applied and the `oldValue` property of the attribute operation might be wrong:\n\t\t\t//\n\t\t\t// Attribute `highlight=\"yellow\"` should be applied on the following range:\n\t\t\t// <p>Fo[zb]ar<p>\n\t\t\t//\n\t\t\t// In meantime, character `x` with `highlight=\"red\"` is typed:\n\t\t\t// <p>Fo[z<$text highlight=\"red\">x</$text>b]ar</p>\n\t\t\t//\n\t\t\t// In this case we cannot simply apply operation changing the attribute value from `null` to `\"yellow\"` for the whole range\n\t\t\t// because that would lead to an exception (`oldValue` is incorrect for `x`).\n\t\t\t//\n\t\t\t// We also cannot break the original range as this would mess up a scenario when there are multiple following\n\t\t\t// insert operations, because then only the first inserted character is included in those ranges:\n\t\t\t// <p>Fo[z][x][b]ar</p> --> <p>Fo[z][x]x[b]ar</p> --> <p>Fo[z][x]xx[b]ar</p>\n\t\t\t//\n\t\t\t// So, the attribute range needs be expanded, no matter what attributes are set on the inserted nodes:\n\t\t\t//\n\t\t\t// <p>Fo[z<$text highlight=\"red\">x</$text>b]ar</p> <--- Change from `null` to `yellow`, throwing an exception.\n\t\t\t//\n\t\t\t// But before that operation would be applied, we will add an additional attribute operation that will change\n\t\t\t// attributes on the inserted nodes in a way which would make the original operation correct:\n\t\t\t//\n\t\t\t// <p>Fo[z{<$text highlight=\"red\">}x</$text>b]ar</p> <--- Change range `{}` from `red` to `null`.\n\t\t\t// <p>Fo[zxb]ar</p> <--- Now change from `null` to `yellow` is completely fine.\n\t\t\t//\n\n\t\t\t// Generate complementary attribute operation. Be sure to add it before the original operation.\n\t\t\tconst op = _getComplementaryAttributeOperations( b, a.key, a.oldValue );\n\n\t\t\tif ( op ) {\n\t\t\t\tresult.unshift( op );\n\t\t\t}\n\t\t}\n\n\t\t// If nodes should not receive new attribute, we are done here.\n\t\treturn result;\n\t}\n\n\t// If insert operation is not expanding the attribute operation range, simply transform the range.\n\ta.range = a.range._getTransformedByInsertion( b.position, b.howMany, false )[ 0 ];\n\n\treturn [ a ];\n} );\n\n/**\n * Helper function for `AttributeOperation` x `InsertOperation` (and reverse) transformation.\n *\n * For given `insertOperation` it checks the inserted node if it has an attribute `key` set to a value different\n * than `newValue`. If so, it generates an `AttributeOperation` which changes the value of `key` attribute to `newValue`.\n *\n * @private\n * @param {module:engine/model/operation/insertoperation~InsertOperation} insertOperation\n * @param {String} key\n * @param {*} newValue\n * @returns {module:engine/model/operation/attributeoperation~AttributeOperation|null}\n */\nfunction _getComplementaryAttributeOperations( insertOperation, key, newValue ) {\n\tconst nodes = insertOperation.nodes;\n\n\t// At the beginning we store the attribute value from the first node.\n\tconst insertValue = nodes.getNode( 0 ).getAttribute( key );\n\n\tif ( insertValue == newValue ) {\n\t\treturn null;\n\t}\n\n\tconst range = new Range( insertOperation.position, insertOperation.position.getShiftedBy( insertOperation.howMany ) );\n\n\treturn new AttributeOperation( range, key, insertValue, newValue, 0 );\n}\n\nsetTransformation( AttributeOperation, MergeOperation, ( a, b ) => {\n\tconst ranges = [];\n\n\t// Case 1:\n\t//\n\t// Attribute change on the merged element. In this case, the merged element was moved to the graveyard.\n\t// An additional attribute operation that will change the (re)moved element needs to be generated.\n\t//\n\tif ( a.range.start.hasSameParentAs( b.deletionPosition ) ) {\n\t\tif ( a.range.containsPosition( b.deletionPosition ) || a.range.start.isEqual( b.deletionPosition ) ) {\n\t\t\tranges.push( Range._createFromPositionAndShift( b.graveyardPosition, 1 ) );\n\t\t}\n\t}\n\n\tconst range = a.range._getTransformedByMergeOperation( b );\n\n\t// Do not add empty (collapsed) ranges to the result. `range` may be collapsed if it contained only the merged element.\n\tif ( !range.isCollapsed ) {\n\t\tranges.push( range );\n\t}\n\n\t// Create `AttributeOperation`s out of the ranges.\n\treturn ranges.map( range => {\n\t\treturn new AttributeOperation( range, a.key, a.oldValue, a.newValue, a.baseVersion );\n\t} );\n} );\n\nsetTransformation( AttributeOperation, MoveOperation, ( a, b ) => {\n\tconst ranges = _breakRangeByMoveOperation( a.range, b );\n\n\t// Create `AttributeOperation`s out of the ranges.\n\treturn ranges.map( range => new AttributeOperation( range, a.key, a.oldValue, a.newValue, a.baseVersion ) );\n} );\n\n// Helper function for `AttributeOperation` x `MoveOperation` transformation.\n//\n// Takes the passed `range` and transforms it by move operation `moveOp` in a specific way. Only top-level nodes of `range`\n// are considered to be in the range. If move operation moves nodes deep from inside of the range, those nodes won't\n// be included in the result. In other words, top-level nodes of the ranges from the result are exactly the same as\n// top-level nodes of the original `range`.\n//\n// This is important for `AttributeOperation` because, for its range, it changes only the top-level nodes. So we need to\n// track only how those nodes have been affected by `MoveOperation`.\n//\n// @private\n// @param {module:engine/model/range~Range} range\n// @param {module:engine/model/operation/moveoperation~MoveOperation} moveOp\n// @returns {Array.<module:engine/model/range~Range>}\nfunction _breakRangeByMoveOperation( range, moveOp ) {\n\tconst moveRange = Range._createFromPositionAndShift( moveOp.sourcePosition, moveOp.howMany );\n\n\t// We are transforming `range` (original range) by `moveRange` (range moved by move operation). As usual when it comes to\n\t// transforming a ranges, we may have a common part of the ranges and we may have a difference part (zero to two ranges).\n\tlet common = null;\n\tlet difference = [];\n\n\t// Let's compare the ranges.\n\tif ( moveRange.containsRange( range, true ) ) {\n\t\t// If the whole original range is moved, treat it whole as a common part. There's also no difference part.\n\t\tcommon = range;\n\t} else if ( range.start.hasSameParentAs( moveRange.start ) ) {\n\t\t// If the ranges are \"on the same level\" (in the same parent) then move operation may move exactly those nodes\n\t\t// that are changed by the attribute operation. In this case we get common part and difference part in the usual way.\n\t\tdifference = range.getDifference( moveRange );\n\t\tcommon = range.getIntersection( moveRange );\n\t} else {\n\t\t// In any other situation we assume that original range is different than move range, that is that move operation\n\t\t// moves other nodes that attribute operation change. Even if the moved range is deep inside in the original range.\n\t\t//\n\t\t// Note that this is different than in `.getIntersection` (we would get a common part in that case) and different\n\t\t// than `.getDifference` (we would get two ranges).\n\t\tdifference = [ range ];\n\t}\n\n\tconst result = [];\n\n\t// The default behaviour of `_getTransformedByMove` might get wrong results for difference part, though, so\n\t// we do it by hand.\n\tfor ( let diff of difference ) {\n\t\t// First, transform the range by removing moved nodes. Since this is a difference, this is safe, `null` won't be returned\n\t\t// as the range is different than the moved range.\n\t\tdiff = diff._getTransformedByDeletion( moveOp.sourcePosition, moveOp.howMany );\n\n\t\t// Transform also `targetPosition`.\n\t\tconst targetPosition = moveOp.getMovedRangeStart();\n\n\t\t// Spread the range only if moved nodes are inserted only between the top-level nodes of the `diff` range.\n\t\tconst spread = diff.start.hasSameParentAs( targetPosition );\n\n\t\t// Transform by insertion of moved nodes.\n\t\tdiff = diff._getTransformedByInsertion( targetPosition, moveOp.howMany, spread );\n\n\t\tresult.push( ...diff );\n\t}\n\n\t// Common part can be simply transformed by the move operation. This is because move operation will not target to\n\t// that common part (the operation would have to target inside its own moved range).\n\tif ( common ) {\n\t\tresult.push(\n\t\t\tcommon._getTransformedByMove( moveOp.sourcePosition, moveOp.targetPosition, moveOp.howMany, false )[ 0 ]\n\t\t);\n\t}\n\n\treturn result;\n}\n\nsetTransformation( AttributeOperation, SplitOperation, ( a, b ) => {\n\t// Case 1:\n\t//\n\t// Split node is the last node in `AttributeOperation#range`.\n\t// `AttributeOperation#range` needs to be expanded to include the new (split) node.\n\t//\n\t// Attribute `type` to be changed to `numbered` but the `listItem` is split.\n\t// <listItem type=\"bulleted\">foobar</listItem>\n\t//\n\t// After split:\n\t// <listItem type=\"bulleted\">foo</listItem><listItem type=\"bulleted\">bar</listItem>\n\t//\n\t// After attribute change:\n\t// <listItem type=\"numbered\">foo</listItem><listItem type=\"numbered\">foo</listItem>\n\t//\n\tif ( a.range.end.isEqual( b.insertionPosition ) ) {\n\t\tif ( !b.graveyardPosition ) {\n\t\t\ta.range.end.offset++;\n\t\t}\n\n\t\treturn [ a ];\n\t}\n\n\t// Case 2:\n\t//\n\t// Split position is inside `AttributeOperation#range`, at the same level, so the nodes to change are\n\t// not going to make a flat range.\n\t//\n\t// Content with range-to-change and split position:\n\t// <p>Fo[zb^a]r</p>\n\t//\n\t// After split:\n\t// <p>Fozb</p><p>ar</p>\n\t//\n\t// Make two separate ranges containing all nodes to change:\n\t// <p>Fo[zb]</p><p>[a]r</p>\n\t//\n\tif ( a.range.start.hasSameParentAs( b.splitPosition ) && a.range.containsPosition( b.splitPosition ) ) {\n\t\tconst secondPart = a.clone();\n\n\t\tsecondPart.range = new Range(\n\t\t\tb.moveTargetPosition.clone(),\n\t\t\ta.range.end._getCombined( b.splitPosition, b.moveTargetPosition )\n\t\t);\n\n\t\ta.range.end = b.splitPosition.clone();\n\t\ta.range.end.stickiness = 'toPrevious';\n\n\t\treturn [ a, secondPart ];\n\t}\n\n\t// The default case.\n\t//\n\ta.range = a.range._getTransformedBySplitOperation( b );\n\n\treturn [ a ];\n} );\n\nsetTransformation( InsertOperation, AttributeOperation, ( a, b ) => {\n\tconst result = [ a ];\n\n\t// Case 1:\n\t//\n\t// The attribute operation range includes the position where nodes were inserted.\n\t// There are two possible scenarios: the inserted nodes were text and they should receive attributes or\n\t// the inserted nodes were elements and they should not receive attributes.\n\t//\n\t// This is a mirror scenario to the one described in `AttributeOperation` x `InsertOperation` transformation,\n\t// although this case is a little less complicated. In this case we simply need to change attributes of the\n\t// inserted nodes and that's it.\n\t//\n\tif ( a.shouldReceiveAttributes && a.position.hasSameParentAs( b.range.start ) && b.range.containsPosition( a.position ) ) {\n\t\tconst op = _getComplementaryAttributeOperations( a, b.key, b.newValue );\n\n\t\tif ( op ) {\n\t\t\tresult.push( op );\n\t\t}\n\t}\n\n\t// The default case is: do nothing.\n\t// `AttributeOperation` does not change the model tree structure so `InsertOperation` does not need to be changed.\n\t//\n\treturn result;\n} );\n\nsetTransformation( InsertOperation, InsertOperation, ( a, b, context ) => {\n\t// Case 1:\n\t//\n\t// Two insert operations insert nodes at the same position. Since they are the same, it needs to be decided\n\t// what will be the order of inserted nodes. However, there is no additional information to help in that\n\t// decision. Also, when `b` will be transformed by `a`, the same order must be maintained.\n\t//\n\t// To achieve that, we will check if the operation is strong.\n\t// If it is, it won't get transformed. If it is not, it will be moved.\n\t//\n\tif ( a.position.isEqual( b.position ) && context.aIsStrong ) {\n\t\treturn [ a ];\n\t}\n\n\t// The default case.\n\t//\n\ta.position = a.position._getTransformedByInsertOperation( b );\n\n\treturn [ a ];\n} );\n\nsetTransformation( InsertOperation, MoveOperation, ( a, b ) => {\n\t// The default case.\n\t//\n\ta.position = a.position._getTransformedByMoveOperation( b );\n\n\treturn [ a ];\n} );\n\nsetTransformation( InsertOperation, SplitOperation, ( a, b ) => {\n\t// The default case.\n\t//\n\ta.position = a.position._getTransformedBySplitOperation( b );\n\n\treturn [ a ];\n} );\n\nsetTransformation( InsertOperation, MergeOperation, ( a, b ) => {\n\ta.position = a.position._getTransformedByMergeOperation( b );\n\n\treturn [ a ];\n} );\n\n// -----------------------\n\nsetTransformation( MarkerOperation, InsertOperation, ( a, b ) => {\n\tif ( a.oldRange ) {\n\t\ta.oldRange = a.oldRange._getTransformedByInsertOperation( b )[ 0 ];\n\t}\n\n\tif ( a.newRange ) {\n\t\ta.newRange = a.newRange._getTransformedByInsertOperation( b )[ 0 ];\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( MarkerOperation, MarkerOperation, ( a, b, context ) => {\n\tif ( a.name == b.name ) {\n\t\tif ( context.aIsStrong ) {\n\t\t\ta.oldRange = b.newRange ? b.newRange.clone() : null;\n\t\t} else {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t}\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( MarkerOperation, MergeOperation, ( a, b ) => {\n\tif ( a.oldRange ) {\n\t\ta.oldRange = a.oldRange._getTransformedByMergeOperation( b );\n\t}\n\n\tif ( a.newRange ) {\n\t\ta.newRange = a.newRange._getTransformedByMergeOperation( b );\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( MarkerOperation, MoveOperation, ( a, b, context ) => {\n\tif ( a.oldRange ) {\n\t\ta.oldRange = Range._createFromRanges( a.oldRange._getTransformedByMoveOperation( b ) );\n\t}\n\n\tif ( a.newRange ) {\n\t\tif ( context.abRelation ) {\n\t\t\tconst aNewRange = Range._createFromRanges( a.newRange._getTransformedByMoveOperation( b ) );\n\n\t\t\tif ( context.abRelation.side == 'left' && b.targetPosition.isEqual( a.newRange.start ) ) {\n\t\t\t\ta.newRange.start.path = context.abRelation.path;\n\t\t\t\ta.newRange.end = aNewRange.end;\n\n\t\t\t\treturn [ a ];\n\t\t\t} else if ( context.abRelation.side == 'right' && b.targetPosition.isEqual( a.newRange.end ) ) {\n\t\t\t\ta.newRange.start = aNewRange.start;\n\t\t\t\ta.newRange.end.path = context.abRelation.path;\n\n\t\t\t\treturn [ a ];\n\t\t\t}\n\t\t}\n\n\t\ta.newRange = Range._createFromRanges( a.newRange._getTransformedByMoveOperation( b ) );\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( MarkerOperation, SplitOperation, ( a, b, context ) => {\n\tif ( a.oldRange ) {\n\t\ta.oldRange = a.oldRange._getTransformedBySplitOperation( b );\n\t}\n\n\tif ( a.newRange ) {\n\t\tif ( context.abRelation ) {\n\t\t\tconst aNewRange = a.newRange._getTransformedBySplitOperation( b );\n\n\t\t\tif ( a.newRange.start.isEqual( b.splitPosition ) && context.abRelation.wasStartBeforeMergedElement ) {\n\t\t\t\ta.newRange.start = Position._createAt( b.insertionPosition );\n\t\t\t} else if ( a.newRange.start.isEqual( b.splitPosition ) && !context.abRelation.wasInLeftElement ) {\n\t\t\t\ta.newRange.start = Position._createAt( b.moveTargetPosition );\n\t\t\t}\n\n\t\t\tif ( a.newRange.end.isEqual( b.splitPosition ) && context.abRelation.wasInRightElement ) {\n\t\t\t\ta.newRange.end = Position._createAt( b.moveTargetPosition );\n\t\t\t} else if ( a.newRange.end.isEqual( b.splitPosition ) && context.abRelation.wasEndBeforeMergedElement ) {\n\t\t\t\ta.newRange.end = Position._createAt( b.insertionPosition );\n\t\t\t} else {\n\t\t\t\ta.newRange.end = aNewRange.end;\n\t\t\t}\n\n\t\t\treturn [ a ];\n\t\t}\n\n\t\ta.newRange = a.newRange._getTransformedBySplitOperation( b );\n\t}\n\n\treturn [ a ];\n} );\n\n// -----------------------\n\nsetTransformation( MergeOperation, InsertOperation, ( a, b ) => {\n\tif ( a.sourcePosition.hasSameParentAs( b.position ) ) {\n\t\ta.howMany += b.howMany;\n\t}\n\n\ta.sourcePosition = a.sourcePosition._getTransformedByInsertOperation( b );\n\ta.targetPosition = a.targetPosition._getTransformedByInsertOperation( b );\n\n\treturn [ a ];\n} );\n\nsetTransformation( MergeOperation, MergeOperation, ( a, b, context ) => {\n\t// Case 1:\n\t//\n\t// Same merge operations.\n\t//\n\t// Both operations have same source and target positions. So the element already got merged and there is\n\t// theoretically nothing to do.\n\t//\n\tif ( a.sourcePosition.isEqual( b.sourcePosition ) && a.targetPosition.isEqual( b.targetPosition ) ) {\n\t\t// There are two ways that we can provide a do-nothing operation.\n\t\t//\n\t\t// First is simply a NoOperation instance. We will use it if `b` operation was not undone.\n\t\t//\n\t\t// Second is a merge operation that has the source operation in the merged element - in the graveyard -\n\t\t// same target position and `howMany` equal to `0`. So it is basically merging an empty element from graveyard\n\t\t// which is almost the same as NoOperation.\n\t\t//\n\t\t// This way the merge operation can be later transformed by split operation\n\t\t// to provide correct undo. This will be used if `b` operation was undone (only then it is correct).\n\t\t//\n\t\tif ( !context.bWasUndone ) {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t} else {\n\t\t\tconst path = b.graveyardPosition.path.slice();\n\t\t\tpath.push( 0 );\n\n\t\t\ta.sourcePosition = new Position( b.graveyardPosition.root, path );\n\t\t\ta.howMany = 0;\n\n\t\t\treturn [ a ];\n\t\t}\n\t}\n\n\t// Case 2:\n\t//\n\t// Same merge source position but different target position.\n\t//\n\t// This can happen during collaboration. For example, if one client merged a paragraph to the previous paragraph\n\t// and the other person removed that paragraph and merged the same paragraph to something before:\n\t//\n\t// Client A:\n\t// <p>Foo</p><p>Bar</p><p>[]Xyz</p>\n\t// <p>Foo</p><p>BarXyz</p>\n\t//\n\t// Client B:\n\t// <p>Foo</p>[<p>Bar</p>]<p>Xyz</p>\n\t// <p>Foo</p><p>[]Xyz</p>\n\t// <p>FooXyz</p>\n\t//\n\t// In this case we need to decide where finally \"Xyz\" will land:\n\t//\n\t// <p>FooXyz</p> graveyard: <p>Bar</p>\n\t// <p>Foo</p> graveyard: <p>BarXyz</p>\n\t//\n\t// Let's move it in a way so that a merge operation that does not target to graveyard is more important so that\n\t// nodes does not end up in the graveyard. It makes sense. Both for Client A and for Client B \"Xyz\" finally did not\n\t// end up in the graveyard (see above).\n\t//\n\t// If neither or both operations point to graveyard, then let `aIsStrong` decide.\n\t//\n\tif (\n\t\ta.sourcePosition.isEqual( b.sourcePosition ) && !a.targetPosition.isEqual( b.targetPosition ) &&\n\t\t!context.bWasUndone && context.abRelation != 'splitAtSource'\n\t) {\n\t\tconst aToGraveyard = a.targetPosition.root.rootName == '$graveyard';\n\t\tconst bToGraveyard = b.targetPosition.root.rootName == '$graveyard';\n\n\t\t// If `aIsWeak` it means that `a` points to graveyard while `b` doesn't. Don't move nodes then.\n\t\tconst aIsWeak = aToGraveyard && !bToGraveyard;\n\n\t\t// If `bIsWeak` it means that `b` points to graveyard while `a` doesn't. Force moving nodes then.\n\t\tconst bIsWeak = bToGraveyard && !aToGraveyard;\n\n\t\t// Force move if `b` is weak or neither operation is weak but `a` is stronger through `context.aIsStrong`.\n\t\tconst forceMove = bIsWeak || ( !aIsWeak && context.aIsStrong );\n\n\t\tif ( forceMove ) {\n\t\t\tconst sourcePosition = b.targetPosition._getTransformedByMergeOperation( b );\n\t\t\tconst targetPosition = a.targetPosition._getTransformedByMergeOperation( b );\n\n\t\t\treturn [ new MoveOperation( sourcePosition, a.howMany, targetPosition, 0 ) ];\n\t\t} else {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t}\n\t}\n\n\t// The default case.\n\t//\n\tif ( a.sourcePosition.hasSameParentAs( b.targetPosition ) ) {\n\t\ta.howMany += b.howMany;\n\t}\n\n\ta.sourcePosition = a.sourcePosition._getTransformedByMergeOperation( b );\n\ta.targetPosition = a.targetPosition._getTransformedByMergeOperation( b );\n\n\t// Handle positions in graveyard.\n\t// If graveyard positions are same and `a` operation is strong - do not transform.\n\tif ( !a.graveyardPosition.isEqual( b.graveyardPosition ) || !context.aIsStrong ) {\n\t\ta.graveyardPosition = a.graveyardPosition._getTransformedByMergeOperation( b );\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( MergeOperation, MoveOperation, ( a, b, context ) => {\n\t// Case 1:\n\t//\n\t// The element to merge got removed.\n\t//\n\t// Merge operation does support merging elements which are not siblings. So it would not be a problem\n\t// from technical point of view. However, if the element was removed, the intention of the user deleting it\n\t// was to have it all deleted, together with its children. From user experience point of view, moving back the\n\t// removed nodes might be unexpected. This means that in this scenario we will block the merging.\n\t//\n\t// The exception of this rule would be if the remove operation was later undone.\n\t//\n\tconst removedRange = Range._createFromPositionAndShift( b.sourcePosition, b.howMany );\n\n\tif ( b.type == 'remove' && !context.bWasUndone && !context.forceWeakRemove ) {\n\t\tif ( a.deletionPosition.hasSameParentAs( b.sourcePosition ) && removedRange.containsPosition( a.sourcePosition ) ) {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t}\n\t}\n\n\t// The default case.\n\t//\n\tif ( a.sourcePosition.hasSameParentAs( b.targetPosition ) ) {\n\t\ta.howMany += b.howMany;\n\t}\n\n\tif ( a.sourcePosition.hasSameParentAs( b.sourcePosition ) ) {\n\t\ta.howMany -= b.howMany;\n\t}\n\n\ta.sourcePosition = a.sourcePosition._getTransformedByMoveOperation( b );\n\ta.targetPosition = a.targetPosition._getTransformedByMoveOperation( b );\n\n\t// `MergeOperation` graveyard position is like `MoveOperation` target position. It is a position where element(s) will\n\t// be moved. Like in other similar cases, we need to consider the scenario when those positions are same.\n\t// Here, we will treat `MergeOperation` like it is always strong (see `InsertOperation` x `InsertOperation` for comparison).\n\t// This means that we won't transform graveyard position if it is equal to move operation target position.\n\tif ( !a.graveyardPosition.isEqual( b.targetPosition ) ) {\n\t\ta.graveyardPosition = a.graveyardPosition._getTransformedByMoveOperation( b );\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( MergeOperation, SplitOperation, ( a, b, context ) => {\n\tif ( b.graveyardPosition ) {\n\t\t// If `b` operation defines graveyard position, a node from graveyard will be moved. This means that we need to\n\t\t// transform `a.graveyardPosition` accordingly.\n\t\ta.graveyardPosition = a.graveyardPosition._getTransformedByDeletion( b.graveyardPosition, 1 );\n\n\t\t// This is a scenario foreseen in `MergeOperation` x `MergeOperation`, with two identical merge operations.\n\t\t//\n\t\t// So, there was `MergeOperation` x `MergeOperation` transformation earlier. Now, `a` is a merge operation which\n\t\t// source position is in graveyard. Interestingly, split operation wants to use the node to be merged by `a`. This\n\t\t// means that `b` is undoing that merge operation from earlier, which caused `a` to be in graveyard.\n\t\t//\n\t\t// If that's the case, at this point, we will only \"fix\" `a.howMany`. It was earlier set to `0` in\n\t\t// `MergeOperation` x `MergeOperation` transformation. Later transformations in this function will change other\n\t\t// properties.\n\t\t//\n\t\tif ( a.deletionPosition.isEqual( b.graveyardPosition ) ) {\n\t\t\ta.howMany = b.howMany;\n\t\t}\n\t}\n\n\t// Case 1:\n\t//\n\t// Merge operation moves nodes to the place where split happens.\n\t// This is a classic situation when there are two paragraphs, and there is a split (enter) after the first\n\t// paragraph and there is a merge (delete) at the beginning of the second paragraph:\n\t//\n\t// <p>Foo{}</p><p>[]Bar</p>.\n\t//\n\t// Split is after `Foo`, while merge is from `Bar` to the end of `Foo`.\n\t//\n\t// State after split:\n\t// <p>Foo</p><p></p><p>Bar</p>\n\t//\n\t// Now, `Bar` should be merged to the new paragraph:\n\t// <p>Foo</p><p>Bar</p>\n\t//\n\t// Instead of merging it to the original paragraph:\n\t// <p>FooBar</p><p></p>\n\t//\n\t// This means that `targetPosition` needs to be transformed. This is the default case though.\n\t// For example, if the split would be after `F`, `targetPosition` should also be transformed.\n\t//\n\t// There are three exceptions, though, when we want to keep `targetPosition` as it was.\n\t//\n\t// First exception is when the merge target position is inside an element (not at the end, as usual). This\n\t// happens when the merge operation earlier was transformed by \"the same\" merge operation. If merge operation\n\t// targets inside the element we want to keep the original target position (and not transform it) because\n\t// we have additional context telling us that we want to merge to the original element. We can check if the\n\t// merge operation points inside element by checking what is `SplitOperation#howMany`. Since merge target position\n\t// is same as split position, if `howMany` is non-zero, it means that the merge target position is inside an element.\n\t//\n\t// Second exception is when the element to merge is in the graveyard and split operation uses it. In that case\n\t// if target position would be transformed, the merge operation would target at the source position:\n\t//\n\t// root: <p>Foo</p>\t\t\t\tgraveyard: <p></p>\n\t//\n\t// SplitOperation: root [ 0, 3 ] using graveyard [ 0 ] (howMany = 0)\n\t// MergeOperation: graveyard [ 0, 0 ] -> root [ 0, 3 ] (howMany = 0)\n\t//\n\t// Since split operation moves the graveyard node back to the root, the merge operation source position changes.\n\t// We would like to merge from the empty <p> to the \"Foo\" <p>:\n\t//\n\t// root: <p>Foo</p><p></p>\t\t\tgraveyard:\n\t//\n\t// MergeOperation#sourcePosition = root [ 1, 0 ]\n\t//\n\t// If `targetPosition` is transformed, it would become root [ 1, 0 ] as well. It has to be kept as it was.\n\t//\n\t// Third exception is connected with relations. If this happens during undo and we have explicit information\n\t// that target position has not been affected by the operation which is undone by this split then this split should\n\t// not move the target position either.\n\t//\n\tif ( a.targetPosition.isEqual( b.splitPosition ) ) {\n\t\tconst mergeInside = b.howMany != 0;\n\t\tconst mergeSplittingElement = b.graveyardPosition && a.deletionPosition.isEqual( b.graveyardPosition );\n\n\t\tif ( mergeInside || mergeSplittingElement || context.abRelation == 'mergeTargetNotMoved' ) {\n\t\t\ta.sourcePosition = a.sourcePosition._getTransformedBySplitOperation( b );\n\n\t\t\treturn [ a ];\n\t\t}\n\t}\n\n\t// Case 2:\n\t//\n\t// Merge source is at the same position as split position. This sometimes happen, mostly during undo.\n\t// The decision here is mostly to choose whether merge source position should stay where it is (so it will be at the end of the\n\t// split element) or should be move to the beginning of the new element.\n\t//\n\tif ( a.sourcePosition.isEqual( b.splitPosition ) ) {\n\t\t// Use context to check if `SplitOperation` is not undoing a merge operation, that didn't change the `a` operation.\n\t\t// This scenario happens the undone merge operation moved nodes at the source position of `a` operation.\n\t\t// In that case `a` operation source position should stay where it is.\n\t\tif ( context.abRelation == 'mergeSourceNotMoved' ) {\n\t\t\ta.howMany = 0;\n\t\t\ta.targetPosition = a.targetPosition._getTransformedBySplitOperation( b );\n\n\t\t\treturn [ a ];\n\t\t}\n\n\t\t// This merge operation might have been earlier transformed by a merge operation which both merged the same element.\n\t\t// See that case in `MergeOperation` x `MergeOperation` transformation. In that scenario, if the merge operation has been undone,\n\t\t// the special case is not applied.\n\t\t//\n\t\t// Now, the merge operation is transformed by the split which has undone that previous merge operation.\n\t\t// So now we are fixing situation which was skipped in `MergeOperation` x `MergeOperation` case.\n\t\t//\n\t\tif ( context.abRelation == 'mergeSameElement' || a.sourcePosition.offset > 0 ) {\n\t\t\ta.sourcePosition = b.moveTargetPosition.clone();\n\t\t\ta.targetPosition = a.targetPosition._getTransformedBySplitOperation( b );\n\n\t\t\treturn [ a ];\n\t\t}\n\t}\n\n\t// The default case.\n\t//\n\tif ( a.sourcePosition.hasSameParentAs( b.splitPosition ) ) {\n\t\ta.howMany = b.splitPosition.offset;\n\t}\n\n\ta.sourcePosition = a.sourcePosition._getTransformedBySplitOperation( b );\n\ta.targetPosition = a.targetPosition._getTransformedBySplitOperation( b );\n\n\treturn [ a ];\n} );\n\n// -----------------------\n\nsetTransformation( MoveOperation, InsertOperation, ( a, b ) => {\n\tconst moveRange = Range._createFromPositionAndShift( a.sourcePosition, a.howMany );\n\tconst transformed = moveRange._getTransformedByInsertOperation( b, false )[ 0 ];\n\n\ta.sourcePosition = transformed.start;\n\ta.howMany = transformed.end.offset - transformed.start.offset;\n\n\t// See `InsertOperation` x `MoveOperation` transformation for details on this case.\n\t//\n\t// In summary, both operations point to the same place, so the order of nodes needs to be decided.\n\t// `MoveOperation` is considered weaker, so it is always transformed, unless there was a certain relation\n\t// between operations.\n\t//\n\tif ( !a.targetPosition.isEqual( b.position ) ) {\n\t\ta.targetPosition = a.targetPosition._getTransformedByInsertOperation( b );\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( MoveOperation, MoveOperation, ( a, b, context ) => {\n\t//\n\t// Setting and evaluating some variables that will be used in special cases and default algorithm.\n\t//\n\t// Create ranges from `MoveOperations` properties.\n\tconst rangeA = Range._createFromPositionAndShift( a.sourcePosition, a.howMany );\n\tconst rangeB = Range._createFromPositionAndShift( b.sourcePosition, b.howMany );\n\n\t// Assign `context.aIsStrong` to a different variable, because the value may change during execution of\n\t// this algorithm and we do not want to override original `context.aIsStrong` that will be used in later transformations.\n\tlet aIsStrong = context.aIsStrong;\n\n\t// This will be used to decide the order of nodes if both operations target at the same position.\n\t// By default, use strong/weak operation mechanism.\n\tlet insertBefore = !context.aIsStrong;\n\n\t// If the relation is set, then use it to decide nodes order.\n\tif ( context.abRelation == 'insertBefore' || context.baRelation == 'insertAfter' ) {\n\t\tinsertBefore = true;\n\t} else if ( context.abRelation == 'insertAfter' || context.baRelation == 'insertBefore' ) {\n\t\tinsertBefore = false;\n\t}\n\n\t// `a.targetPosition` could be affected by the `b` operation. We will transform it.\n\tlet newTargetPosition;\n\n\tif ( a.targetPosition.isEqual( b.targetPosition ) && insertBefore ) {\n\t\tnewTargetPosition = a.targetPosition._getTransformedByDeletion(\n\t\t\tb.sourcePosition,\n\t\t\tb.howMany\n\t\t);\n\t} else {\n\t\tnewTargetPosition = a.targetPosition._getTransformedByMove(\n\t\t\tb.sourcePosition,\n\t\t\tb.targetPosition,\n\t\t\tb.howMany\n\t\t);\n\t}\n\n\t//\n\t// Special case #1 + mirror.\n\t//\n\t// Special case when both move operations' target positions are inside nodes that are\n\t// being moved by the other move operation. So in other words, we move ranges into inside of each other.\n\t// This case can't be solved reasonably (on the other hand, it should not happen often).\n\tif ( _moveTargetIntoMovedRange( a, b ) && _moveTargetIntoMovedRange( b, a ) ) {\n\t\t// Instead of transforming operation, we return a reverse of the operation that we transform by.\n\t\t// So when the results of this \"transformation\" will be applied, `b` MoveOperation will get reversed.\n\t\treturn [ b.getReversed() ];\n\t}\n\t//\n\t// End of special case #1.\n\t//\n\n\t//\n\t// Special case #2.\n\t//\n\t// Check if `b` operation targets inside `rangeA`.\n\tconst bTargetsToA = rangeA.containsPosition( b.targetPosition );\n\n\t// If `b` targets to `rangeA` and `rangeA` contains `rangeB`, `b` operation has no influence on `a` operation.\n\t// You might say that operation `b` is captured inside operation `a`.\n\tif ( bTargetsToA && rangeA.containsRange( rangeB, true ) ) {\n\t\t// There is a mini-special case here, where `rangeB` is on other level than `rangeA`. That's why\n\t\t// we need to transform `a` operation anyway.\n\t\trangeA.start = rangeA.start._getTransformedByMove( b.sourcePosition, b.targetPosition, b.howMany );\n\t\trangeA.end = rangeA.end._getTransformedByMove( b.sourcePosition, b.targetPosition, b.howMany );\n\n\t\treturn _makeMoveOperationsFromRanges( [ rangeA ], newTargetPosition );\n\t}\n\n\t//\n\t// Special case #2 mirror.\n\t//\n\tconst aTargetsToB = rangeB.containsPosition( a.targetPosition );\n\n\tif ( aTargetsToB && rangeB.containsRange( rangeA, true ) ) {\n\t\t// `a` operation is \"moved together\" with `b` operation.\n\t\t// Here, just move `rangeA` \"inside\" `rangeB`.\n\t\trangeA.start = rangeA.start._getCombined( b.sourcePosition, b.getMovedRangeStart() );\n\t\trangeA.end = rangeA.end._getCombined( b.sourcePosition, b.getMovedRangeStart() );\n\n\t\treturn _makeMoveOperationsFromRanges( [ rangeA ], newTargetPosition );\n\t}\n\t//\n\t// End of special case #2.\n\t//\n\n\t//\n\t// Special case #3 + mirror.\n\t//\n\t// `rangeA` has a node which is an ancestor of `rangeB`. In other words, `rangeB` is inside `rangeA`\n\t// but not on the same tree level. In such case ranges have common part but we have to treat it\n\t// differently, because in such case those ranges are not really conflicting and should be treated like\n\t// two separate ranges. Also we have to discard two difference parts.\n\tconst aCompB = compareArrays( a.sourcePosition.getParentPath(), b.sourcePosition.getParentPath() );\n\n\tif ( aCompB == 'prefix' || aCompB == 'extension' ) {\n\t\t// Transform `rangeA` by `b` operation and make operation out of it, and that's all.\n\t\t// Note that this is a simplified version of default case, but here we treat the common part (whole `rangeA`)\n\t\t// like a one difference part.\n\t\trangeA.start = rangeA.start._getTransformedByMove( b.sourcePosition, b.targetPosition, b.howMany );\n\t\trangeA.end = rangeA.end._getTransformedByMove( b.sourcePosition, b.targetPosition, b.howMany );\n\n\t\treturn _makeMoveOperationsFromRanges( [ rangeA ], newTargetPosition );\n\t}\n\t//\n\t// End of special case #3.\n\t//\n\n\t//\n\t// Default case - ranges are on the same level or are not connected with each other.\n\t//\n\t// Modifier for default case.\n\t// Modifies `aIsStrong` flag in certain conditions.\n\t//\n\t// If only one of operations is a remove operation, we force remove operation to be the \"stronger\" one\n\t// to provide more expected results.\n\tif ( a.type == 'remove' && b.type != 'remove' && !context.aWasUndone && !context.forceWeakRemove ) {\n\t\taIsStrong = true;\n\t} else if ( a.type != 'remove' && b.type == 'remove' && !context.bWasUndone && !context.forceWeakRemove ) {\n\t\taIsStrong = false;\n\t}\n\n\t// Handle operation's source ranges - check how `rangeA` is affected by `b` operation.\n\t// This will aggregate transformed ranges.\n\tconst ranges = [];\n\n\t// Get the \"difference part\" of `a` operation source range.\n\t// This is an array with one or two ranges. Two ranges if `rangeB` is inside `rangeA`.\n\tconst difference = rangeA.getDifference( rangeB );\n\n\tfor ( const range of difference ) {\n\t\t// Transform those ranges by `b` operation. For example if `b` moved range from before those ranges, fix those ranges.\n\t\trange.start = range.start._getTransformedByDeletion( b.sourcePosition, b.howMany );\n\t\trange.end = range.end._getTransformedByDeletion( b.sourcePosition, b.howMany );\n\n\t\t// If `b` operation targets into `rangeA` on the same level, spread `rangeA` into two ranges.\n\t\tconst shouldSpread = compareArrays( range.start.getParentPath(), b.getMovedRangeStart().getParentPath() ) == 'same';\n\t\tconst newRanges = range._getTransformedByInsertion( b.getMovedRangeStart(), b.howMany, shouldSpread );\n\n\t\tranges.push( ...newRanges );\n\t}\n\n\t// Then, we have to manage the \"common part\" of both move ranges.\n\tconst common = rangeA.getIntersection( rangeB );\n\n\tif ( common !== null && aIsStrong ) {\n\t\t// Calculate the new position of that part of original range.\n\t\tcommon.start = common.start._getCombined( b.sourcePosition, b.getMovedRangeStart() );\n\t\tcommon.end = common.end._getCombined( b.sourcePosition, b.getMovedRangeStart() );\n\n\t\t// Take care of proper range order.\n\t\t//\n\t\t// Put `common` at appropriate place. Keep in mind that we are interested in original order.\n\t\t// Basically there are only three cases: there is zero, one or two difference ranges.\n\t\t//\n\t\t// If there is zero difference ranges, just push `common` in the array.\n\t\tif ( ranges.length === 0 ) {\n\t\t\tranges.push( common );\n\t\t}\n\t\t// If there is one difference range, we need to check whether common part was before it or after it.\n\t\telse if ( ranges.length == 1 ) {\n\t\t\tif ( rangeB.start.isBefore( rangeA.start ) || rangeB.start.isEqual( rangeA.start ) ) {\n\t\t\t\tranges.unshift( common );\n\t\t\t} else {\n\t\t\t\tranges.push( common );\n\t\t\t}\n\t\t}\n\t\t// If there are more ranges (which means two), put common part between them. This is the only scenario\n\t\t// where there could be two difference ranges so we don't have to make any comparisons.\n\t\telse {\n\t\t\tranges.splice( 1, 0, common );\n\t\t}\n\t}\n\n\tif ( ranges.length === 0 ) {\n\t\t// If there are no \"source ranges\", nothing should be changed.\n\t\t// Note that this can happen only if `aIsStrong == false` and `rangeA.isEqual( rangeB )`.\n\t\treturn [ new NoOperation( a.baseVersion ) ];\n\t}\n\n\treturn _makeMoveOperationsFromRanges( ranges, newTargetPosition );\n} );\n\nsetTransformation( MoveOperation, SplitOperation, ( a, b, context ) => {\n\tlet newTargetPosition = a.targetPosition.clone();\n\n\t// Do not transform if target position is same as split insertion position and this split comes from undo.\n\t// This should be done on relations but it is too much work for now as it would require relations working in collaboration.\n\t// We need to make a decision how we will resolve such conflict and this is less harmful way.\n\tif ( !a.targetPosition.isEqual( b.insertionPosition ) || !b.graveyardPosition || context.abRelation == 'moveTargetAfter' ) {\n\t\tnewTargetPosition = a.targetPosition._getTransformedBySplitOperation( b );\n\t}\n\n\t// Case 1:\n\t//\n\t// Last element in the moved range got split.\n\t//\n\t// In this case the default range transformation will not work correctly as the element created by\n\t// split operation would be outside the range. The range to move needs to be fixed manually.\n\t//\n\tconst moveRange = Range._createFromPositionAndShift( a.sourcePosition, a.howMany );\n\n\tif ( moveRange.end.isEqual( b.insertionPosition ) ) {\n\t\t// Do it only if this is a \"natural\" split, not a one that comes from undo.\n\t\t// If this is undo split, only `targetPosition` needs to be changed (if the move is a remove).\n\t\tif ( !b.graveyardPosition ) {\n\t\t\ta.howMany++;\n\t\t}\n\n\t\ta.targetPosition = newTargetPosition;\n\n\t\treturn [ a ];\n\t}\n\n\t// Case 2:\n\t//\n\t// Split happened between the moved nodes. In this case two ranges to move need to be generated.\n\t//\n\t// Characters `ozba` are moved to the end of paragraph `Xyz` but split happened.\n\t// <p>F[oz|ba]r</p><p>Xyz</p>\n\t//\n\t// After split:\n\t// <p>F[oz</p><p>ba]r</p><p>Xyz</p>\n\t//\n\t// Correct ranges:\n\t// <p>F[oz]</p><p>[ba]r</p><p>Xyz</p>\n\t//\n\t// After move:\n\t// <p>F</p><p>r</p><p>Xyzozba</p>\n\t//\n\tif ( moveRange.start.hasSameParentAs( b.splitPosition ) && moveRange.containsPosition( b.splitPosition ) ) {\n\t\tlet rightRange = new Range( b.splitPosition, moveRange.end );\n\t\trightRange = rightRange._getTransformedBySplitOperation( b );\n\n\t\tconst ranges = [\n\t\t\tnew Range( moveRange.start, b.splitPosition ),\n\t\t\trightRange\n\t\t];\n\n\t\treturn _makeMoveOperationsFromRanges( ranges, newTargetPosition );\n\t}\n\n\t// Case 3:\n\t//\n\t// Move operation targets at the split position. We need to decide if the nodes should be inserted\n\t// at the end of the split element or at the beginning of the new element.\n\t//\n\tif ( a.targetPosition.isEqual( b.splitPosition ) && context.abRelation == 'insertAtSource' ) {\n\t\tnewTargetPosition = b.moveTargetPosition;\n\t}\n\n\t// Case 4:\n\t//\n\t// Move operation targets just after the split element. We need to decide if the nodes should be inserted\n\t// between two parts of split element, or after the new element.\n\t//\n\t// Split at `|`, while move operation moves `<p>Xyz</p>` and targets at `^`:\n\t// <p>Foo|bar</p>^<p>baz</p>\n\t// <p>Foo</p>^<p>bar</p><p>baz</p> or <p>Foo</p><p>bar</p>^<p>baz</p>?\n\t//\n\t// If there is no contextual information between operations (for example, they come from collaborative\n\t// editing), we don't want to put some unrelated content (move) between parts of related content (split parts).\n\t// However, if the split is from undo, in the past, the moved content might be targeting between the\n\t// split parts, meaning that was exactly user's intention:\n\t//\n\t// <p>Foo</p>^<p>bar</p>\t\t<--- original situation, in \"past\".\n\t// <p>Foobar</p>^\t\t\t\t<--- after merge target position is transformed.\n\t// <p>Foo|bar</p>^\t\t\t\t<--- then the merge is undone, and split happens, which leads us to current situation.\n\t//\n\t// In this case it is pretty clear that the intention was to put new paragraph between those nodes,\n\t// so we need to transform accordingly. We can detect this scenario thanks to relations.\n\t//\n\tif ( a.targetPosition.isEqual( b.insertionPosition ) && context.abRelation == 'insertBetween' ) {\n\t\tnewTargetPosition = a.targetPosition;\n\t}\n\n\t// The default case.\n\t//\n\tconst transformed = moveRange._getTransformedBySplitOperation( b );\n\tconst ranges = [ transformed ];\n\n\t// Case 5:\n\t//\n\t// Moved range contains graveyard element used by split operation. Add extra move operation to the result.\n\t//\n\tif ( b.graveyardPosition ) {\n\t\tconst movesGraveyardElement = moveRange.start.isEqual( b.graveyardPosition ) || moveRange.containsPosition( b.graveyardPosition );\n\n\t\tif ( a.howMany > 1 && movesGraveyardElement && !context.aWasUndone ) {\n\t\t\tranges.push( Range._createFromPositionAndShift( b.insertionPosition, 1 ) );\n\t\t}\n\t}\n\n\treturn _makeMoveOperationsFromRanges( ranges, newTargetPosition );\n} );\n\nsetTransformation( MoveOperation, MergeOperation, ( a, b, context ) => {\n\tconst movedRange = Range._createFromPositionAndShift( a.sourcePosition, a.howMany );\n\n\tif ( b.deletionPosition.hasSameParentAs( a.sourcePosition ) && movedRange.containsPosition( b.sourcePosition ) ) {\n\t\tif ( a.type == 'remove' && !context.forceWeakRemove ) {\n\t\t\t// Case 1:\n\t\t\t//\n\t\t\t// The element to remove got merged.\n\t\t\t//\n\t\t\t// Merge operation does support merging elements which are not siblings. So it would not be a problem\n\t\t\t// from technical point of view. However, if the element was removed, the intention of the user\n\t\t\t// deleting it was to have it all deleted. From user experience point of view, moving back the\n\t\t\t// removed nodes might be unexpected. This means that in this scenario we will reverse merging and remove the element.\n\t\t\t//\n\t\t\tif ( !context.aWasUndone ) {\n\t\t\t\tconst results = [];\n\n\t\t\t\tlet gyMoveSource = b.graveyardPosition.clone();\n\t\t\t\tlet splitNodesMoveSource = b.targetPosition._getTransformedByMergeOperation( b );\n\n\t\t\t\tif ( a.howMany > 1 ) {\n\t\t\t\t\tresults.push( new MoveOperation( a.sourcePosition, a.howMany - 1, a.targetPosition, 0 ) );\n\n\t\t\t\t\tgyMoveSource = gyMoveSource._getTransformedByMove( a.sourcePosition, a.targetPosition, a.howMany - 1 );\n\t\t\t\t\tsplitNodesMoveSource = splitNodesMoveSource._getTransformedByMove( a.sourcePosition, a.targetPosition, a.howMany - 1 );\n\t\t\t\t}\n\n\t\t\t\tconst gyMoveTarget = b.deletionPosition._getCombined( a.sourcePosition, a.targetPosition );\n\t\t\t\tconst gyMove = new MoveOperation( gyMoveSource, 1, gyMoveTarget, 0 );\n\n\t\t\t\tconst splitNodesMoveTargetPath = gyMove.getMovedRangeStart().path.slice();\n\t\t\t\tsplitNodesMoveTargetPath.push( 0 );\n\n\t\t\t\tconst splitNodesMoveTarget = new Position( gyMove.targetPosition.root, splitNodesMoveTargetPath );\n\t\t\t\tsplitNodesMoveSource = splitNodesMoveSource._getTransformedByMove( gyMoveSource, gyMoveTarget, 1 );\n\t\t\t\tconst splitNodesMove = new MoveOperation( splitNodesMoveSource, b.howMany, splitNodesMoveTarget, 0 );\n\n\t\t\t\tresults.push( gyMove );\n\t\t\t\tresults.push( splitNodesMove );\n\n\t\t\t\treturn results;\n\t\t\t}\n\t\t} else {\n\t\t\t// Case 2:\n\t\t\t//\n\t\t\t// The element to move got merged and it was the only element to move.\n\t\t\t// In this case just don't do anything, leave the node in the graveyard. Without special case\n\t\t\t// it would be a move operation that moves 0 nodes, so maybe it is better just to return no-op.\n\t\t\t//\n\t\t\tif ( a.howMany == 1 ) {\n\t\t\t\tif ( !context.bWasUndone ) {\n\t\t\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t\t\t} else {\n\t\t\t\t\ta.sourcePosition = b.graveyardPosition.clone();\n\t\t\t\t\ta.targetPosition = a.targetPosition._getTransformedByMergeOperation( b );\n\n\t\t\t\t\treturn [ a ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// The default case.\n\t//\n\tconst moveRange = Range._createFromPositionAndShift( a.sourcePosition, a.howMany );\n\tconst transformed = moveRange._getTransformedByMergeOperation( b );\n\n\ta.sourcePosition = transformed.start;\n\ta.howMany = transformed.end.offset - transformed.start.offset;\n\ta.targetPosition = a.targetPosition._getTransformedByMergeOperation( b );\n\n\treturn [ a ];\n} );\n\n// -----------------------\n\nsetTransformation( RenameOperation, InsertOperation, ( a, b ) => {\n\ta.position = a.position._getTransformedByInsertOperation( b );\n\n\treturn [ a ];\n} );\n\nsetTransformation( RenameOperation, MergeOperation, ( a, b ) => {\n\t// Case 1:\n\t//\n\t// Element to rename got merged, so it was moved to `b.graveyardPosition`.\n\t//\n\tif ( a.position.isEqual( b.deletionPosition ) ) {\n\t\ta.position = b.graveyardPosition.clone();\n\t\ta.position.stickiness = 'toNext';\n\n\t\treturn [ a ];\n\t}\n\n\ta.position = a.position._getTransformedByMergeOperation( b );\n\n\treturn [ a ];\n} );\n\nsetTransformation( RenameOperation, MoveOperation, ( a, b ) => {\n\ta.position = a.position._getTransformedByMoveOperation( b );\n\n\treturn [ a ];\n} );\n\nsetTransformation( RenameOperation, RenameOperation, ( a, b, context ) => {\n\tif ( a.position.isEqual( b.position ) ) {\n\t\tif ( context.aIsStrong ) {\n\t\t\ta.oldName = b.newName;\n\t\t} else {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t}\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( RenameOperation, SplitOperation, ( a, b ) => {\n\t// Case 1:\n\t//\n\t// The element to rename has been split. In this case, the new element should be also renamed.\n\t//\n\t// User decides to change the paragraph to a list item:\n\t// <paragraph>Foobar</paragraph>\n\t//\n\t// However, in meantime, split happens:\n\t// <paragraph>Foo</paragraph><paragraph>bar</paragraph>\n\t//\n\t// As a result, rename both elements:\n\t// <listItem>Foo</listItem><listItem>bar</listItem>\n\t//\n\tconst renamePath = a.position.path;\n\tconst splitPath = b.splitPosition.getParentPath();\n\n\tif ( compareArrays( renamePath, splitPath ) == 'same' && !b.graveyardPosition ) {\n\t\tconst extraRename = new RenameOperation( a.position.getShiftedBy( 1 ), a.oldName, a.newName, 0 );\n\n\t\treturn [ a, extraRename ];\n\t}\n\n\t// The default case.\n\t//\n\ta.position = a.position._getTransformedBySplitOperation( b );\n\n\treturn [ a ];\n} );\n\n// -----------------------\n\nsetTransformation( RootAttributeOperation, RootAttributeOperation, ( a, b, context ) => {\n\tif ( a.root === b.root && a.key === b.key ) {\n\t\tif ( !context.aIsStrong || a.newValue === b.newValue ) {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t} else {\n\t\t\ta.oldValue = b.newValue;\n\t\t}\n\t}\n\n\treturn [ a ];\n} );\n\n// -----------------------\n\nsetTransformation( SplitOperation, InsertOperation, ( a, b ) => {\n\t// The default case.\n\t//\n\tif ( a.splitPosition.hasSameParentAs( b.position ) && a.splitPosition.offset < b.position.offset ) {\n\t\ta.howMany += b.howMany;\n\t}\n\n\ta.splitPosition = a.splitPosition._getTransformedByInsertOperation( b );\n\ta.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition );\n\n\treturn [ a ];\n} );\n\nsetTransformation( SplitOperation, MergeOperation, ( a, b, context ) => {\n\t// Case 1:\n\t//\n\t// Split element got merged. If two different elements were merged, clients will have different content.\n\t//\n\t// Example. Merge at `{}`, split at `[]`:\n\t// <heading>Foo</heading>{}<paragraph>B[]ar</paragraph>\n\t//\n\t// On merge side it will look like this:\n\t// <heading>FooB[]ar</heading>\n\t// <heading>FooB</heading><heading>ar</heading>\n\t//\n\t// On split side it will look like this:\n\t// <heading>Foo</heading>{}<paragraph>B</paragraph><paragraph>ar</paragraph>\n\t// <heading>FooB</heading><paragraph>ar</paragraph>\n\t//\n\t// Clearly, the second element is different for both clients.\n\t//\n\t// We could use the removed merge element from graveyard as a split element but then clients would have a different\n\t// model state (in graveyard), because the split side client would still have an element in graveyard (removed by merge).\n\t//\n\t// To overcome this, in `SplitOperation` x `MergeOperation` transformation we will add additional `SplitOperation`\n\t// in the graveyard, which will actually clone the merged-and-deleted element. Then, that cloned element will be\n\t// used for splitting. Example below.\n\t//\n\t// Original state:\n\t// <heading>Foo</heading>{}<paragraph>B[]ar</paragraph>\n\t//\n\t// Merge side client:\n\t//\n\t// After merge:\n\t// <heading>FooB[]ar</heading> graveyard: <paragraph></paragraph>\n\t//\n\t// Extra split:\n\t// <heading>FooB[]ar</heading> graveyard: <paragraph></paragraph><paragraph></paragraph>\n\t//\n\t// Use the \"cloned\" element from graveyard:\n\t// <heading>FooB</heading><paragraph>ar</paragraph> graveyard: <paragraph></paragraph>\n\t//\n\t// Split side client:\n\t//\n\t// After split:\n\t// <heading>Foo</heading>{}<paragraph>B</paragraph><paragraph>ar</paragraph>\n\t//\n\t// After merge:\n\t// <heading>FooB</heading><paragraph>ar</paragraph> graveyard: <paragraph></paragraph>\n\t//\n\t// This special case scenario only applies if the original split operation clones the split element.\n\t// If the original split operation has `graveyardPosition` set, it all doesn't have sense because split operation\n\t// knows exactly which element it should use. So there would be no original problem with different contents.\n\t//\n\t// Additionally, the special case applies only if the merge wasn't already undone.\n\t//\n\tif ( !a.graveyardPosition && !context.bWasUndone && a.splitPosition.hasSameParentAs( b.sourcePosition ) ) {\n\t\tconst splitPath = b.graveyardPosition.path.slice();\n\t\tsplitPath.push( 0 );\n\n\t\tconst splitPosition = new Position( b.graveyardPosition.root, splitPath );\n\t\tconst insertionPosition = SplitOperation.getInsertionPosition( new Position( b.graveyardPosition.root, splitPath ) );\n\n\t\tconst additionalSplit = new SplitOperation( splitPosition, 0, null, 0 );\n\t\tadditionalSplit.insertionPosition = insertionPosition;\n\n\t\ta.splitPosition = a.splitPosition._getTransformedByMergeOperation( b );\n\t\ta.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition );\n\t\ta.graveyardPosition = additionalSplit.insertionPosition.clone();\n\t\ta.graveyardPosition.stickiness = 'toNext';\n\n\t\treturn [ additionalSplit, a ];\n\t}\n\n\t// The default case.\n\t//\n\tif ( a.splitPosition.hasSameParentAs( b.deletionPosition ) && !a.splitPosition.isAfter( b.deletionPosition ) ) {\n\t\ta.howMany--;\n\t}\n\n\tif ( a.splitPosition.hasSameParentAs( b.targetPosition ) ) {\n\t\ta.howMany += b.howMany;\n\t}\n\n\ta.splitPosition = a.splitPosition._getTransformedByMergeOperation( b );\n\ta.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition );\n\n\tif ( a.graveyardPosition ) {\n\t\ta.graveyardPosition = a.graveyardPosition._getTransformedByMergeOperation( b );\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( SplitOperation, MoveOperation, ( a, b, context ) => {\n\tconst rangeToMove = Range._createFromPositionAndShift( b.sourcePosition, b.howMany );\n\n\tif ( a.graveyardPosition ) {\n\t\t// Case 1:\n\t\t//\n\t\t// Split operation graveyard node was moved. In this case move operation is stronger. Since graveyard element\n\t\t// is already moved to the correct position, we need to only move the nodes after the split position.\n\t\t// This will be done by `MoveOperation` instead of `SplitOperation`.\n\t\t//\n\t\tconst gyElementMoved = rangeToMove.start.isEqual( a.graveyardPosition ) || rangeToMove.containsPosition( a.graveyardPosition );\n\n\t\tif ( !context.bWasUndone && gyElementMoved ) {\n\t\t\tconst sourcePosition = a.splitPosition._getTransformedByMoveOperation( b );\n\n\t\t\tconst newParentPosition = a.graveyardPosition._getTransformedByMoveOperation( b );\n\t\t\tconst newTargetPath = newParentPosition.path.slice();\n\t\t\tnewTargetPath.push( 0 );\n\n\t\t\tconst newTargetPosition = new Position( newParentPosition.root, newTargetPath );\n\t\t\tconst moveOp = new MoveOperation( sourcePosition, a.howMany, newTargetPosition, 0 );\n\n\t\t\treturn [ moveOp ];\n\t\t}\n\n\t\ta.graveyardPosition = a.graveyardPosition._getTransformedByMoveOperation( b );\n\t}\n\n\t// Case 2:\n\t//\n\t// If the split position is inside the moved range, we need to shift the split position to a proper place.\n\t// The position cannot be moved together with moved range because that would result in splitting of an incorrect element.\n\t//\n\t// Characters `bc` should be moved to the second paragraph while split position is between them:\n\t// <paragraph>A[b|c]d</paragraph><paragraph>Xyz</paragraph>\n\t//\n\t// After move, new split position is incorrect:\n\t// <paragraph>Ad</paragraph><paragraph>Xb|cyz</paragraph>\n\t//\n\t// Correct split position:\n\t// <paragraph>A|d</paragraph><paragraph>Xbcyz</paragraph>\n\t//\n\t// After split:\n\t// <paragraph>A</paragraph><paragraph>d</paragraph><paragraph>Xbcyz</paragraph>\n\t//\n\tif ( a.splitPosition.hasSameParentAs( b.sourcePosition ) && rangeToMove.containsPosition( a.splitPosition ) ) {\n\t\tconst howManyRemoved = b.howMany - ( a.splitPosition.offset - b.sourcePosition.offset );\n\t\ta.howMany -= howManyRemoved;\n\n\t\tif ( a.splitPosition.hasSameParentAs( b.targetPosition ) && a.splitPosition.offset < b.targetPosition.offset ) {\n\t\t\ta.howMany += b.howMany;\n\t\t}\n\n\t\ta.splitPosition = b.sourcePosition.clone();\n\t\ta.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition );\n\n\t\treturn [ a ];\n\t}\n\n\t// Case 3:\n\t//\n\t// Split is at a position where nodes were moved.\n\t//\n\t// This is a scenario described in `MoveOperation` x `SplitOperation` transformation but from the\n\t// \"split operation point of view\".\n\t//\n\tconst splitAtTarget = a.splitPosition.isEqual( b.targetPosition );\n\n\tif ( splitAtTarget && ( context.baRelation == 'insertAtSource' || context.abRelation == 'splitBefore' ) ) {\n\t\ta.howMany += b.howMany;\n\t\ta.splitPosition = a.splitPosition._getTransformedByDeletion( b.sourcePosition, b.howMany );\n\t\ta.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition );\n\n\t\treturn [ a ];\n\t}\n\n\t// The default case.\n\t// Don't change `howMany` if move operation does not really move anything.\n\t//\n\tif ( !b.sourcePosition.isEqual( b.targetPosition ) ) {\n\t\tif ( a.splitPosition.hasSameParentAs( b.sourcePosition ) && a.splitPosition.offset <= b.sourcePosition.offset ) {\n\t\t\ta.howMany -= b.howMany;\n\t\t}\n\n\t\tif ( a.splitPosition.hasSameParentAs( b.targetPosition ) && a.splitPosition.offset < b.targetPosition.offset ) {\n\t\t\ta.howMany += b.howMany;\n\t\t}\n\t}\n\n\t// Change position stickiness to force a correct transformation.\n\ta.splitPosition.stickiness = 'toNone';\n\ta.splitPosition = a.splitPosition._getTransformedByMoveOperation( b );\n\ta.splitPosition.stickiness = 'toNext';\n\n\tif ( a.graveyardPosition ) {\n\t\ta.insertionPosition = a.insertionPosition._getTransformedByMoveOperation( b );\n\t} else {\n\t\ta.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition );\n\t}\n\n\treturn [ a ];\n} );\n\nsetTransformation( SplitOperation, SplitOperation, ( a, b, context ) => {\n\t// Case 1:\n\t//\n\t// Split at the same position.\n\t//\n\t// If there already was a split at the same position as in `a` operation, it means that the intention\n\t// conveyed by `a` operation has already been fulfilled and `a` should not do anything (to avoid double split).\n\t//\n\t// However, there is a difference if these are new splits or splits created by undo. These have different\n\t// intentions. Also splits moving back different elements from graveyard have different intentions. They\n\t// are just different operations.\n\t//\n\t// So we cancel split operation only if it was really identical.\n\t//\n\t// Also, there is additional case, where split operations aren't identical and should not be cancelled, however the\n\t// default transformation is incorrect too.\n\t//\n\tif ( a.splitPosition.isEqual( b.splitPosition ) ) {\n\t\tif ( !a.graveyardPosition && !b.graveyardPosition ) {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t}\n\n\t\tif ( a.graveyardPosition && b.graveyardPosition && a.graveyardPosition.isEqual( b.graveyardPosition ) ) {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t}\n\n\t\t// Use context to know that the `a.splitPosition` should stay where it is.\n\t\t// This happens during undo when first a merge operation moved nodes to `a.splitPosition` and now `b` operation undoes that merge.\n\t\tif ( context.abRelation == 'splitBefore' ) {\n\t\t\t// Since split is at the same position, there are no nodes left to split.\n\t\t\ta.howMany = 0;\n\n\t\t\t// Note: there was `if ( a.graveyardPosition )` here but it was uncovered in tests and I couldn't find any scenarios for now.\n\t\t\t// That would have to be a `SplitOperation` that didn't come from undo but is transformed by operations that were undone.\n\t\t\t// It could happen if `context` is enabled in collaboration.\n\t\t\ta.graveyardPosition = a.graveyardPosition._getTransformedBySplitOperation( b );\n\n\t\t\treturn [ a ];\n\t\t}\n\t}\n\n\t// Case 2:\n\t//\n\t// Same node is using to split different elements. This happens in undo when previously same element was merged to\n\t// two different elements. This is described in `MergeOperation` x `MergeOperation` transformation.\n\t//\n\t// In this case we will follow the same logic. We will assume that `insertionPosition` is same for both\n\t// split operations. This might not always be true but in the real cases that were experienced it was. After all,\n\t// if these splits are reverses of merge operations that were merging the same element, then the `insertionPosition`\n\t// should be same for both of those splits.\n\t//\n\t// Again, we will decide which operation is stronger by checking if split happens in graveyard or in non-graveyard root.\n\t//\n\tif ( a.graveyardPosition && b.graveyardPosition && a.graveyardPosition.isEqual( b.graveyardPosition ) ) {\n\t\tconst aInGraveyard = a.splitPosition.root.rootName == '$graveyard';\n\t\tconst bInGraveyard = b.splitPosition.root.rootName == '$graveyard';\n\n\t\t// If `aIsWeak` it means that `a` points to graveyard while `b` doesn't. Don't move nodes then.\n\t\tconst aIsWeak = aInGraveyard && !bInGraveyard;\n\n\t\t// If `bIsWeak` it means that `b` points to graveyard while `a` doesn't. Force moving nodes then.\n\t\tconst bIsWeak = bInGraveyard && !aInGraveyard;\n\n\t\t// Force move if `b` is weak or neither operation is weak but `a` is stronger through `context.aIsStrong`.\n\t\tconst forceMove = bIsWeak || ( !aIsWeak && context.aIsStrong );\n\n\t\tif ( forceMove ) {\n\t\t\tconst result = [];\n\n\t\t\t// First we need to move any nodes split by `b` back to where they were.\n\t\t\t// Do it only if `b` actually moved something.\n\t\t\tif ( b.howMany ) {\n\t\t\t\tresult.push( new MoveOperation( b.moveTargetPosition, b.howMany, b.splitPosition, 0 ) );\n\t\t\t}\n\n\t\t\t// Then we need to move nodes from `a` split position to their new element.\n\t\t\t// Do it only if `a` actually should move something.\n\t\t\tif ( a.howMany ) {\n\t\t\t\tresult.push( new MoveOperation( a.splitPosition, a.howMany, a.moveTargetPosition, 0 ) );\n\t\t\t}\n\n\t\t\treturn result;\n\t\t} else {\n\t\t\treturn [ new NoOperation( 0 ) ];\n\t\t}\n\t}\n\n\tif ( a.graveyardPosition ) {\n\t\ta.graveyardPosition = a.graveyardPosition._getTransformedBySplitOperation( b );\n\t}\n\n\t// Case 3:\n\t//\n\t// Position where operation `b` inserted a new node after split is the same as the operation `a` split position.\n\t// As in similar cases, there is ambiguity if the split should be before the new node (created by `b`) or after.\n\t//\n\tif ( a.splitPosition.isEqual( b.insertionPosition ) && context.abRelation == 'splitBefore' ) {\n\t\ta.howMany++;\n\n\t\treturn [ a ];\n\t}\n\n\t// Case 4:\n\t//\n\t// This is a mirror to the case 2. above.\n\t//\n\tif ( b.splitPosition.isEqual( a.insertionPosition ) && context.baRelation == 'splitBefore' ) {\n\t\tconst newPositionPath = b.insertionPosition.path.slice();\n\t\tnewPositionPath.push( 0 );\n\n\t\tconst newPosition = new Position( b.insertionPosition.root, newPositionPath );\n\t\tconst moveOp = new MoveOperation( a.insertionPosition, 1, newPosition, 0 );\n\n\t\treturn [ a, moveOp ];\n\t}\n\n\t// The default case.\n\t//\n\tif ( a.splitPosition.hasSameParentAs( b.splitPosition ) && a.splitPosition.offset < b.splitPosition.offset ) {\n\t\ta.howMany -= b.howMany;\n\t}\n\n\ta.splitPosition = a.splitPosition._getTransformedBySplitOperation( b );\n\ta.insertionPosition = SplitOperation.getInsertionPosition( a.splitPosition );\n\n\treturn [ a ];\n} );\n\n// Checks whether `MoveOperation` `targetPosition` is inside a node from the moved range of the other `MoveOperation`.\n//\n// @private\n// @param {module:engine/model/operation/moveoperation~MoveOperation} a\n// @param {module:engine/model/operation/moveoperation~MoveOperation} b\n// @returns {Boolean}\nfunction _moveTargetIntoMovedRange( a, b ) {\n\treturn a.targetPosition._getTransformedByDeletion( b.sourcePosition, b.howMany ) === null;\n}\n\n// Helper function for `MoveOperation` x `MoveOperation` transformation. Converts given ranges and target position to\n// move operations and returns them.\n//\n// Ranges and target position will be transformed on-the-fly when generating operations.\n//\n// Given `ranges` should be in the order of how they were in the original transformed operation.\n//\n// Given `targetPosition` is the target position of the first range from `ranges`.\n//\n// @private\n// @param {Array.<module:engine/model/range~Range>} ranges\n// @param {module:engine/model/position~Position} targetPosition\n// @returns {Array.<module:engine/model/operation/moveoperation~MoveOperation>}\nfunction _makeMoveOperationsFromRanges( ranges, targetPosition ) {\n\t// At this moment we have some ranges and a target position, to which those ranges should be moved.\n\t// Order in `ranges` array is the go-to order of after transformation.\n\t//\n\t// We are almost done. We have `ranges` and `targetPosition` to make operations from.\n\t// Unfortunately, those operations may affect each other. Precisely, first operation after move\n\t// may affect source range and target position of second and third operation. Same with second\n\t// operation affecting third.\n\t//\n\t// We need to fix those source ranges and target positions once again, before converting `ranges` to operations.\n\tconst operations = [];\n\n\t// Keep in mind that nothing will be transformed if there is just one range in `ranges`.\n\tfor ( let i = 0; i < ranges.length; i++ ) {\n\t\t// Create new operation out of a range and target position.\n\t\tconst range = ranges[ i ];\n\t\tconst op = new MoveOperation(\n\t\t\trange.start,\n\t\t\trange.end.offset - range.start.offset,\n\t\t\ttargetPosition,\n\t\t\t0\n\t\t);\n\n\t\toperations.push( op );\n\n\t\t// Transform other ranges by the generated operation.\n\t\tfor ( let j = i + 1; j < ranges.length; j++ ) {\n\t\t\t// All ranges in `ranges` array should be:\n\t\t\t//\n\t\t\t// * non-intersecting (these are part of original operation source range), and\n\t\t\t// * `targetPosition` does not target into them (opposite would mean that transformed operation targets \"inside itself\").\n\t\t\t//\n\t\t\t// This means that the transformation will be \"clean\" and always return one result.\n\t\t\tranges[ j ] = ranges[ j ]._getTransformedByMove( op.sourcePosition, op.targetPosition, op.howMany )[ 0 ];\n\t\t}\n\n\t\ttargetPosition = targetPosition._getTransformedByMove( op.sourcePosition, op.targetPosition, op.howMany );\n\t}\n\n\treturn operations;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 undo/basecommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { transformSets } from '@ckeditor/ckeditor5-engine/src/model/operation/transform';\n\n/**\n * Base class for undo feature commands: {@link module:undo/undocommand~UndoCommand} and {@link module:undo/redocommand~RedoCommand}.\n *\n * @protected\n * @extends module:core/command~Command\n */\nexport default class BaseCommand extends Command {\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * Stack of items stored by the command. These are pairs of:\n\t\t *\n\t\t * * {@link module:engine/model/batch~Batch batch} saved by the command,\n\t\t * * {@link module:engine/model/selection~Selection selection} state at the moment of saving the batch.\n\t\t *\n\t\t * @protected\n\t\t * @member {Array} #_stack\n\t\t */\n\t\tthis._stack = [];\n\n\t\t/**\n\t\t * Stores all batches that were created by this command.\n\t\t *\n\t\t * @protected\n\t\t * @member {WeakSet.<module:engine/model/batch~Batch>} #_createdBatches\n\t\t */\n\t\tthis._createdBatches = new WeakSet();\n\n\t\t// Refresh state, so the command is inactive right after initialization.\n\t\tthis.refresh();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.isEnabled = this._stack.length > 0;\n\t}\n\n\t/**\n\t * Stores a batch in the command, together with the selection state of the {@link module:engine/model/document~Document document}\n\t * created by the editor which this command is registered to.\n\t *\n\t * @param {module:engine/model/batch~Batch} batch The batch to add.\n\t */\n\taddBatch( batch ) {\n\t\tconst docSelection = this.editor.model.document.selection;\n\n\t\tconst selection = {\n\t\t\tranges: docSelection.hasOwnRange ? Array.from( docSelection.getRanges() ) : [],\n\t\t\tisBackward: docSelection.isBackward\n\t\t};\n\n\t\tthis._stack.push( { batch, selection } );\n\t\tthis.refresh();\n\t}\n\n\t/**\n\t * Removes all items from the stack.\n\t */\n\tclearStack() {\n\t\tthis._stack = [];\n\t\tthis.refresh();\n\t}\n\n\t/**\n\t * Restores the {@link module:engine/model/document~Document#selection document selection} state after a batch was undone.\n\t *\n\t * @protected\n\t * @param {Array.<module:engine/model/range~Range>} ranges Ranges to be restored.\n\t * @param {Boolean} isBackward A flag describing whether the restored range was selected forward or backward.\n\t * @param {Array.<module:engine/model/operation/operation~Operation>} operations Operations which has been applied\n\t * since selection has been stored.\n\t */\n\t_restoreSelection( ranges, isBackward, operations ) {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\n\t\t// This will keep the transformed selection ranges.\n\t\tconst selectionRanges = [];\n\n\t\t// Transform all ranges from the restored selection.\n\t\tfor ( const range of ranges ) {\n\t\t\tconst transformed = transformSelectionRange( range, operations );\n\n\t\t\t// For each `range` from `ranges`, we take only one transformed range.\n\t\t\t// This is because we want to prevent situation where single-range selection\n\t\t\t// got transformed to multi-range selection. We will take the first range that\n\t\t\t// is not in the graveyard.\n\t\t\tconst newRange = transformed.find(\n\t\t\t\trange => range.start.root != document.graveyard\n\t\t\t);\n\n\t\t\t// `transformedRange` might be `undefined` if transformed range ended up in graveyard.\n\t\t\tif ( newRange ) {\n\t\t\t\tselectionRanges.push( newRange );\n\t\t\t}\n\t\t}\n\n\t\t// `selectionRanges` may be empty if all ranges ended up in graveyard. If that is the case, do not restore selection.\n\t\tif ( selectionRanges.length ) {\n\t\t\tmodel.change( writer => {\n\t\t\t\twriter.setSelection( selectionRanges, { backward: isBackward } );\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Undoes a batch by reversing that batch, transforming reversed batch and finally applying it.\n\t * This is a helper method for {@link #execute}.\n\t *\n\t * @protected\n\t * @param {module:engine/model/batch~Batch} batchToUndo The batch to be undone.\n\t * @param {module:engine/model/batch~Batch} undoingBatch The batch that will contain undoing changes.\n\t */\n\t_undo( batchToUndo, undoingBatch ) {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\n\t\t// All changes done by the command execution will be saved as one batch.\n\t\tthis._createdBatches.add( undoingBatch );\n\n\t\tconst operationsToUndo = batchToUndo.operations.slice().filter( operation => operation.isDocumentOperation );\n\t\toperationsToUndo.reverse();\n\n\t\t// We will process each operation from `batchToUndo`, in reverse order. If there were operations A, B and C in undone batch,\n\t\t// we need to revert them in reverse order, so first C' (reversed C), then B', then A'.\n\t\tfor ( const operationToUndo of operationsToUndo ) {\n\t\t\tconst nextBaseVersion = operationToUndo.baseVersion + 1;\n\t\t\tconst historyOperations = Array.from( document.history.getOperations( nextBaseVersion ) );\n\n\t\t\tconst transformedSets = transformSets(\n\t\t\t\t[ operationToUndo.getReversed() ],\n\t\t\t\thistoryOperations,\n\t\t\t\t{\n\t\t\t\t\tuseRelations: true,\n\t\t\t\t\tdocument: this.editor.model.document,\n\t\t\t\t\tpadWithNoOps: false,\n\t\t\t\t\tforceWeakRemove: true\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tconst reversedOperations = transformedSets.operationsA;\n\n\t\t\t// After reversed operation has been transformed by all history operations, apply it.\n\t\t\tfor ( const operation of reversedOperations ) {\n\t\t\t\t// Before applying, add the operation to the `undoingBatch`.\n\t\t\t\tundoingBatch.addOperation( operation );\n\t\t\t\tmodel.applyOperation( operation );\n\n\t\t\t\tdocument.history.setOperationAsUndone( operationToUndo, operation );\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Transforms given range `range` by given `operations`.\n// Returns an array containing one or more ranges, which are result of the transformation.\nfunction transformSelectionRange( range, operations ) {\n\tconst transformed = range.getTransformedByOperations( operations );\n\n\t// After `range` got transformed, we have an array of ranges. Some of those\n\t// ranges may be \"touching\" -- they can be next to each other and could be merged.\n\t// First, we have to sort those ranges to assure that they are in order.\n\ttransformed.sort( ( a, b ) => a.start.isBefore( b.start ) ? -1 : 1 );\n\n\t// Then, we check if two consecutive ranges are touching.\n\tfor ( let i = 1; i < transformed.length; i++ ) {\n\t\tconst a = transformed[ i - 1 ];\n\t\tconst b = transformed[ i ];\n\n\t\tif ( a.end.isTouching( b.start ) ) {\n\t\t\t// And join them together if they are.\n\t\t\ta.end = b.end;\n\t\t\ttransformed.splice( i, 1 );\n\t\t\ti--;\n\t\t}\n\t}\n\n\treturn transformed;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 undo/undocommand\n */\n\nimport BaseCommand from './basecommand';\n\n/**\n * The undo command stores {@link module:engine/model/batch~Batch batches} applied to the\n * {@link module:engine/model/document~Document document} and is able to undo a batch by reversing it and transforming by\n * batches from {@link module:engine/model/document~Document#history history} that happened after the reversed batch.\n *\n * The undo command also takes care of restoring the {@link module:engine/model/document~Document#selection document selection}.\n *\n * @extends module:undo/basecommand~BaseCommand\n */\nexport default class UndoCommand extends BaseCommand {\n\t/**\n\t * Executes the command. This method reverts a {@link module:engine/model/batch~Batch batch} added to the command's stack, transforms\n\t * and applies the reverted version on the {@link module:engine/model/document~Document document} and removes the batch from the stack.\n\t * Then, it restores the {@link module:engine/model/document~Document#selection document selection}.\n\t *\n\t * @fires execute\n\t * @fires revert\n\t * @param {module:engine/model/batch~Batch} [batch] A batch that should be undone. If not set, the last added batch will be undone.\n\t */\n\texecute( batch = null ) {\n\t\t// If batch is not given, set `batchIndex` to the last index in command stack.\n\t\tconst batchIndex = batch ? this._stack.findIndex( a => a.batch == batch ) : this._stack.length - 1;\n\n\t\tconst item = this._stack.splice( batchIndex, 1 )[ 0 ];\n\t\tconst undoingBatch = this.editor.model.createBatch( 'transparent' );\n\n\t\t// All changes has to be done in one `enqueueChange` callback so other listeners will not\n\t\t// step between consecutive operations, or won't do changes to the document before selection is properly restored.\n\t\tthis.editor.model.enqueueChange( undoingBatch, () => {\n\t\t\tthis._undo( item.batch, undoingBatch );\n\n\t\t\tconst operations = this.editor.model.document.history.getOperations( item.batch.baseVersion );\n\t\t\tthis._restoreSelection( item.selection.ranges, item.selection.isBackward, operations );\n\n\t\t\tthis.fire( 'revert', item.batch, undoingBatch );\n\t\t} );\n\n\t\tthis.refresh();\n\t}\n}\n\n/**\n * Fired when execution of the command reverts some batch.\n *\n * @event revert\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 undo/redocommand\n */\n\nimport BaseCommand from './basecommand';\n\n/**\n * The redo command stores {@link module:engine/model/batch~Batch batches} that were used to undo a batch by\n * {@link module:undo/undocommand~UndoCommand}. It is able to redo a previously undone batch by reversing the undoing\n * batches created by `UndoCommand`. The reversed batch is transformed by all the batches from\n * {@link module:engine/model/document~Document#history history} that happened after the reversed undo batch.\n *\n * The redo command also takes care of restoring the {@link module:engine/model/document~Document#selection document selection}.\n *\n * @extends module:undo/basecommand~BaseCommand\n */\nexport default class RedoCommand extends BaseCommand {\n\t/**\n\t * Executes the command. This method reverts the last {@link module:engine/model/batch~Batch batch} added to\n\t * the command's stack, applies the reverted and transformed version on the\n\t * {@link module:engine/model/document~Document document} and removes the batch from the stack.\n\t * Then, it restores the {@link module:engine/model/document~Document#selection document selection}.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst item = this._stack.pop();\n\t\tconst redoingBatch = this.editor.model.createBatch( 'transparent' );\n\n\t\t// All changes have to be done in one `enqueueChange` callback so other listeners will not step between consecutive\n\t\t// operations, or won't do changes to the document before selection is properly restored.\n\t\tthis.editor.model.enqueueChange( redoingBatch, () => {\n\t\t\tconst lastOperation = item.batch.operations[ item.batch.operations.length - 1 ];\n\t\t\tconst nextBaseVersion = lastOperation.baseVersion + 1;\n\t\t\tconst operations = this.editor.model.document.history.getOperations( nextBaseVersion );\n\n\t\t\tthis._restoreSelection( item.selection.ranges, item.selection.isBackward, operations );\n\t\t\tthis._undo( item.batch, redoingBatch );\n\t\t} );\n\n\t\tthis.refresh();\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 undo/undoediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport UndoCommand from './undocommand';\nimport RedoCommand from './redocommand';\n\n/**\n * The undo engine feature.\n *\n * It introduces the `'undo'` and `'redo'` commands to the editor.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class UndoEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'UndoEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The command that manages undo {@link module:engine/model/batch~Batch batches} stack (history).\n\t\t * Created and registered during the {@link #init feature initialization}.\n\t\t *\n\t\t * @private\n\t\t * @member {module:undo/undocommand~UndoCommand} #_undoCommand\n\t\t */\n\n\t\t/**\n\t\t * The command that manages redo {@link module:engine/model/batch~Batch batches} stack (history).\n\t\t * Created and registered during the {@link #init feature initialization}.\n\t\t *\n\t\t * @private\n\t\t * @member {module:undo/undocommand~UndoCommand} #_redoCommand\n\t\t */\n\n\t\t/**\n\t\t * Keeps track of which batches were registered in undo.\n\t\t *\n\t\t * @private\n\t\t * @member {WeakSet.<module:engine/model/batch~Batch>}\n\t\t */\n\t\tthis._batchRegistry = new WeakSet();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Create commands.\n\t\tthis._undoCommand = new UndoCommand( editor );\n\t\tthis._redoCommand = new RedoCommand( editor );\n\n\t\t// Register command to the editor.\n\t\teditor.commands.add( 'undo', this._undoCommand );\n\t\teditor.commands.add( 'redo', this._redoCommand );\n\n\t\tthis.listenTo( editor.model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\t// Do not register batch if the operation is not a document operation.\n\t\t\t// This prevents from creating empty undo steps, where all operations where non-document operations.\n\t\t\t// Non-document operations creates and alters content in detached tree fragments (for example, document fragments).\n\t\t\t// Most of time this is preparing data before it is inserted into actual tree (for example during copy & paste).\n\t\t\t// Such operations should not be reversed.\n\t\t\tif ( !operation.isDocumentOperation ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst batch = operation.batch;\n\n\t\t\tconst isRedoBatch = this._redoCommand._createdBatches.has( batch );\n\t\t\tconst isUndoBatch = this._undoCommand._createdBatches.has( batch );\n\t\t\tconst isRegisteredBatch = this._batchRegistry.has( batch );\n\n\t\t\t// If changes are not a part of a batch or this is not a new batch, omit those changes.\n\t\t\tif ( isRegisteredBatch || ( batch.type == 'transparent' && !isRedoBatch && !isUndoBatch ) ) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tif ( isRedoBatch ) {\n\t\t\t\t\t// If this batch comes from `redoCommand`, add it to `undoCommand` stack.\n\t\t\t\t\tthis._undoCommand.addBatch( batch );\n\t\t\t\t} else if ( !isUndoBatch ) {\n\t\t\t\t\t// A default batch - these are new changes in the document, not introduced by undo feature.\n\t\t\t\t\t// Add them to `undoCommand` stack and clear `redoCommand` stack.\n\t\t\t\t\tthis._undoCommand.addBatch( batch );\n\t\t\t\t\tthis._redoCommand.clearStack();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the batch to the registry so it will not be processed again.\n\t\t\tthis._batchRegistry.add( batch );\n\t\t}, { priority: 'highest' } );\n\n\t\tthis.listenTo( this._undoCommand, 'revert', ( evt, undoneBatch, undoingBatch ) => {\n\t\t\tthis._redoCommand.addBatch( undoingBatch );\n\t\t} );\n\n\t\teditor.keystrokes.set( 'CTRL+Z', 'undo' );\n\t\teditor.keystrokes.set( 'CTRL+Y', 'redo' );\n\t\teditor.keystrokes.set( 'CTRL+SHIFT+Z', 'redo' );\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M5.042 9.367l2.189 1.837a.75.75 0 0 1-.965 1.149l-3.788-3.18a.747.747 0 0 1-.21-.284.75.75 0 0 1 .17-.945L6.23 4.762a.75.75 0 1 1 .964 1.15L4.863 7.866h8.917A.75.75 0 0 1 14 7.9a4 4 0 1 1-1.477 7.718l.344-1.489a2.5 2.5 0 1 0 1.094-4.73l.008-.032H5.042z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M14.958 9.367l-2.189 1.837a.75.75 0 0 0 .965 1.149l3.788-3.18a.747.747 0 0 0 .21-.284.75.75 0 0 0-.17-.945L13.77 4.762a.75.75 0 1 0-.964 1.15l2.331 1.955H6.22A.75.75 0 0 0 6 7.9a4 4 0 1 0 1.477 7.718l-.344-1.489A2.5 2.5 0 1 1 6.039 9.4l-.008-.032h8.927z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module undo/undoui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport undoIcon from '../theme/icons/undo.svg';\nimport redoIcon from '../theme/icons/redo.svg';\n/**\n * The undo UI feature. It introduces the `'undo'` and `'redo'` buttons to the editor.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class UndoUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const locale = editor.locale;\n const t = editor.t;\n const localizedUndoIcon = locale.uiLanguageDirection == 'ltr' ? undoIcon : redoIcon;\n const localizedRedoIcon = locale.uiLanguageDirection == 'ltr' ? redoIcon : undoIcon;\n this._addButton('undo', t('bf'), 'CTRL+Z', localizedUndoIcon);\n this._addButton('redo', t('bg'), 'CTRL+Y', localizedRedoIcon);\n }\n /**\n\t * Creates a button for the specified command.\n\t *\n\t * @private\n\t * @param {String} name Command name.\n\t * @param {String} label Button label.\n\t * @param {String} keystroke Command keystroke.\n\t * @param {String} Icon Source of the icon.\n\t */\n _addButton(name, label, keystroke, Icon) {\n const editor = this.editor;\n editor.ui.componentFactory.add(name, locale => {\n const command = editor.commands.get(name);\n const view = new ButtonView(locale);\n view.set({\n label,\n icon: Icon,\n keystroke,\n tooltip: true\n });\n view.bind('isEnabled').to(command, 'isEnabled');\n this.listenTo(view, 'execute', () => editor.execute(name));\n return view;\n });\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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 undo/undo\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport UndoEditing from './undoediting';\nimport UndoUI from './undoui';\n\n/**\n * The undo feature.\n *\n * This is a \"glue\" plugin which loads the {@link module:undo/undoediting~UndoEditing undo editing feature}\n * and {@link module:undo/undoui~UndoUI undo UI feature}.\n *\n * Below is the explanation of the undo mechanism working together with {@link module:engine/model/history~History History}:\n *\n * Whenever a {@link module:engine/model/operation/operation~Operation operation} is applied to the\n * {@link module:engine/model/document~Document document}, it is saved to `History` as is.\n * The {@link module:engine/model/batch~Batch batch} that owns that operation is also saved, in\n * {@link module:undo/undocommand~UndoCommand}, together with the selection that was present in the document before the\n * operation was applied. A batch is saved instead of the operation because changes are undone batch-by-batch, not operation-by-operation\n * and a batch is seen as one undo step.\n *\n * After some changes happen to the document, the `History` and `UndoCommand` stack can be represented as follows:\n *\n *\t\t History Undo stack\n *\t\t============== ==================================\n *\t\t[operation A1] [batch A]\n *\t\t[operation B1] [batch B]\n *\t\t[operation B2] [batch C]\n *\t\t[operation C1]\n *\t\t[operation C2]\n *\t\t[operation B3]\n *\t\t[operation C3]\n *\n * Where operations starting with the same letter are from same batch.\n *\n * Undoing a batch means that a set of operations which will reverse the effects of that batch needs to be generated.\n * For example, if a batch added several letters, undoing the batch should remove them. It is important to apply undoing\n * operations in the reversed order, so if a batch has operation `X`, `Y`, `Z`, reversed operations `Zr`, `Yr` and `Xr`\n * need to be applied. Otherwise reversed operation `Xr` would operate on a wrong document state, because operation `X`\n * does not know that operations `Y` and `Z` happened.\n *\n * After operations from an undone batch got {@link module:engine/model/operation/operation~Operation#getReversed reversed},\n * one needs to make sure if they are ready to be applied. In the scenario above, operation `C3` is the last operation and `C3r`\n * bases on up-to-date document state, so it can be applied to the document.\n *\n *\t\t History Undo stack\n *\t\t================= ==================================\n *\t\t[ operation A1 ] [ batch A ]\n *\t\t[ operation B1 ] [ batch B ]\n *\t\t[ operation B2 ] [ processing undoing batch C ]\n *\t\t[ operation C1 ]\n *\t\t[ operation C2 ]\n *\t\t[ operation B3 ]\n *\t\t[ operation C3 ]\n *\t\t[ operation C3r ]\n *\n * Next is operation `C2`, reversed to `C2r`. `C2r` bases on `C2`, so it bases on the wrong document state. It needs to be\n * transformed by operations from history that happened after it, so it \"knows\" about them. Let us assume that `C2' = C2r * B3 * C3 * C3r`,\n * where `*` means \"transformed by\". Rest of operations from that batch are processed in the same fashion.\n *\n *\t\t History Undo stack Redo stack\n *\t\t================= ================================== ==================================\n *\t\t[ operation A1 ] [ batch A ] [ batch Cr ]\n *\t\t[ operation B1 ] [ batch B ]\n *\t\t[ operation B2 ]\n *\t\t[ operation C1 ]\n *\t\t[ operation C2 ]\n *\t\t[ operation B3 ]\n *\t\t[ operation C3 ]\n *\t\t[ operation C3r ]\n *\t\t[ operation C2' ]\n *\t\t[ operation C1' ]\n *\n * Selective undo works on the same basis, however, instead of undoing the last batch in the undo stack, any batch can be undone.\n * The same algorithm applies: operations from a batch (i.e. `A1`) are reversed and then transformed by operations stored in history.\n *\n * Redo also is very similar to undo. It has its own stack that is filled with undoing (reversed batches). Operations from\n * batch that is re-done are reversed-back, transformed in proper order and applied to the document.\n *\n *\t\t History Undo stack Redo stack\n *\t\t================= ================================== ==================================\n *\t\t[ operation A1 ] [ batch A ]\n *\t\t[ operation B1 ] [ batch B ]\n *\t\t[ operation B2 ] [ batch Crr ]\n *\t\t[ operation C1 ]\n *\t\t[ operation C2 ]\n *\t\t[ operation B3 ]\n *\t\t[ operation C3 ]\n *\t\t[ operation C3r ]\n *\t\t[ operation C2' ]\n *\t\t[ operation C1' ]\n *\t\t[ operation C1'r]\n *\t\t[ operation C2'r]\n *\t\t[ operation C3rr]\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Undo extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ UndoEditing, UndoUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Undo';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* globals window, document */\n\n/**\n * @module adapter-ckfinder/utils\n */\n\nconst TOKEN_COOKIE_NAME = 'ckCsrfToken';\nconst TOKEN_LENGTH = 40;\nconst tokenCharset = 'abcdefghijklmnopqrstuvwxyz0123456789';\n\n/**\n * Returns the CSRF token value. The value is a hash stored in `document.cookie`\n * under the `ckCsrfToken` key. The CSRF token can be used to secure the communication\n * between the web browser and the CKFinder server.\n *\n * @returns {String}\n */\nexport function getCsrfToken() {\n\tlet token = getCookie( TOKEN_COOKIE_NAME );\n\n\tif ( !token || token.length != TOKEN_LENGTH ) {\n\t\ttoken = generateToken( TOKEN_LENGTH );\n\t\tsetCookie( TOKEN_COOKIE_NAME, token );\n\t}\n\n\treturn token;\n}\n\n/**\n * Returns the value of the cookie with a given name or `null` if the cookie is not found.\n *\n * @param {String} name\n * @returns {String|null}\n */\nexport function getCookie( name ) {\n\tname = name.toLowerCase();\n\tconst parts = document.cookie.split( ';' );\n\n\tfor ( const part of parts ) {\n\t\tconst pair = part.split( '=' );\n\t\tconst key = decodeURIComponent( pair[ 0 ].trim().toLowerCase() );\n\n\t\tif ( key === name ) {\n\t\t\treturn decodeURIComponent( pair[ 1 ] );\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Sets the value of the cookie with a given name.\n *\n * @param {String} name\n * @param {String} value\n */\nexport function setCookie( name, value ) {\n\tdocument.cookie = encodeURIComponent( name ) + '=' + encodeURIComponent( value ) + ';path=/';\n}\n\n// Generates the CSRF token with the given length.\n//\n// @private\n// @param {Number} length\n// @returns {string}\nfunction generateToken( length ) {\n\tlet result = '';\n\tconst randValues = new Uint8Array( length );\n\n\twindow.crypto.getRandomValues( randValues );\n\n\tfor ( let j = 0; j < randValues.length; j++ ) {\n\t\tconst character = tokenCharset.charAt( randValues[ j ] % tokenCharset.length );\n\t\tresult += Math.random() > 0.5 ? character.toUpperCase() : character;\n\t}\n\n\treturn result;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/* globals XMLHttpRequest, FormData */\n/**\n * @module adapter-ckfinder/uploadadapter\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';\nimport { getCsrfToken } from './utils';\n/**\n * A plugin that enables file uploads in CKEditor 5 using the CKFinder server–side connector.\n *\n * See the {@glink features/image-upload/ckfinder \"CKFinder file manager integration\" guide} to learn how to configure\n * and use this feature as well as find out more about the full integration with the file manager\n * provided by the {@link module:ckfinder/ckfinder~CKFinder} plugin.\n *\n * Check out the {@glink features/image-upload/image-upload comprehensive \"Image upload overview\"} to learn about\n * other ways to upload images into CKEditor 5.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class CKFinderUploadAdapter extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get requires() {\n return [FileRepository];\n }\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'CKFinderUploadAdapter';\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n const url = this.editor.config.get('ckfinder.uploadUrl');\n if (!url) {\n return;\n }\n // Register CKFinderAdapter\n this.editor.plugins.get(FileRepository).createUploadAdapter = loader => new UploadAdapter(loader, url, this.editor.t);\n }\n}\n/**\n * Upload adapter for CKFinder.\n *\n * @private\n * @implements module:upload/filerepository~UploadAdapter\n */\nclass UploadAdapter {\n /**\n\t * Creates a new adapter instance.\n\t *\n\t * @param {module:upload/filerepository~FileLoader} loader\n\t * @param {String} url\n\t * @param {module:utils/locale~Locale#t} t\n\t */\n constructor(loader, url, t) {\n /**\n\t\t * FileLoader instance to use during the upload.\n\t\t *\n\t\t * @member {module:upload/filerepository~FileLoader} #loader\n\t\t */\n this.loader = loader;\n /**\n\t\t * Upload URL.\n\t\t *\n\t\t * @member {String} #url\n\t\t */\n this.url = url;\n /**\n\t\t * Locale translation method.\n\t\t *\n\t\t * @member {module:utils/locale~Locale#t} #t\n\t\t */\n this.t = t;\n }\n /**\n\t * Starts the upload process.\n\t *\n\t * @see module:upload/filerepository~UploadAdapter#upload\n\t * @returns {Promise.<Object>}\n\t */\n upload() {\n return this.loader.file.then(file => {\n return new Promise((resolve, reject) => {\n this._initRequest();\n this._initListeners(resolve, reject, file);\n this._sendRequest(file);\n });\n });\n }\n /**\n\t * Aborts the upload process.\n\t *\n\t * @see module:upload/filerepository~UploadAdapter#abort\n\t */\n abort() {\n if (this.xhr) {\n this.xhr.abort();\n }\n }\n /**\n\t * Initializes the XMLHttpRequest object.\n\t *\n\t * @private\n\t */\n _initRequest() {\n const xhr = this.xhr = new XMLHttpRequest();\n xhr.open('POST', this.url, true);\n xhr.responseType = 'json';\n }\n /**\n\t * Initializes XMLHttpRequest listeners.\n\t *\n\t * @private\n\t * @param {Function} resolve Callback function to be called when the request is successful.\n\t * @param {Function} reject Callback function to be called when the request cannot be completed.\n\t * @param {File} file File instance to be uploaded.\n\t */\n _initListeners(resolve, reject, file) {\n const xhr = this.xhr;\n const loader = this.loader;\n const t = this.t;\n const genericError = t('a') + ` ${ file.name }.`;\n xhr.addEventListener('error', () => reject(genericError));\n xhr.addEventListener('abort', () => reject());\n xhr.addEventListener('load', () => {\n const response = xhr.response;\n if (!response || !response.uploaded) {\n return reject(response && response.error && response.error.message ? response.error.message : genericError);\n }\n resolve({ default: response.url });\n });\n // Upload progress when it's supported.\n /* istanbul ignore else */\n if (xhr.upload) {\n xhr.upload.addEventListener('progress', evt => {\n if (evt.lengthComputable) {\n loader.uploadTotal = evt.total;\n loader.uploaded = evt.loaded;\n }\n });\n }\n }\n /**\n\t * Prepares the data and sends the request.\n\t *\n\t * @private\n\t * @param {File} file File instance to be uploaded.\n\t */\n _sendRequest(file) {\n // Prepare form data.\n const data = new FormData();\n data.append('upload', file);\n data.append('ckCsrfToken', getCsrfToken());\n // Send request.\n this.xhr.send(data);\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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 autoformat/blockautoformatediting\n */\n\nimport LiveRange from '@ckeditor/ckeditor5-engine/src/model/liverange';\n\n/**\n * The block autoformatting engine. It allows to format various block patterns. For example,\n * it can be configured to turn a paragraph starting with `*` and followed by a space into a list item.\n *\n * The autoformatting operation is integrated with the undo manager,\n * so the autoformatting step can be undone if the user's intention was not to format the text.\n *\n * See the constructors documentation to learn how to create custom inline autoformatters. You can also use\n * the {@link module:autoformat/autoformat~Autoformat} feature which enables a set of default autoformatters\n * (lists, headings, bold and italic).\n */\nexport default class BlockAutoformatEditing {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'BlockAutoformatEditing';\n\t}\n\n\t/**\n\t * Creates a listener triggered on `change` event in the document.\n\t * Calls the callback when inserted text matches the regular expression or the command name\n\t * if provided instead of the callback.\n\t *\n\t * Examples of usage:\n\t *\n\t * To convert a paragraph to heading 1 when `- ` is typed, using just the command name:\n\t *\n\t *\t\tnew BlockAutoformatEditing( editor, /^\\- $/, 'heading1' );\n\t *\n\t * To convert a paragraph to heading 1 when `- ` is typed, using just the callback:\n\t *\n\t *\t\tnew BlockAutoformatEditing( editor, /^\\- $/, ( context ) => {\n\t *\t\t\tconst { match } = context;\n\t *\t\t\tconst headingLevel = match[ 1 ].length;\n\t *\n\t *\t\t\teditor.execute( 'heading', {\n\t *\t\t\t\tformatId: `heading${ headingLevel }`\n\t *\t\t\t} );\n\t * \t\t} );\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t * @param {RegExp} pattern The regular expression to execute on just inserted text.\n\t * @param {Function|String} callbackOrCommand The callback to execute or the command to run when the text is matched.\n\t * In case of providing the callback, it receives the following parameter:\n\t * * {Object} match RegExp.exec() result of matching the pattern to inserted text.\n\t */\n\tconstructor( editor, pattern, callbackOrCommand ) {\n\t\tlet callback;\n\t\tlet command = null;\n\n\t\tif ( typeof callbackOrCommand == 'function' ) {\n\t\t\tcallback = callbackOrCommand;\n\t\t} else {\n\t\t\t// We assume that the actual command name was provided.\n\t\t\tcommand = editor.commands.get( callbackOrCommand );\n\n\t\t\tcallback = () => {\n\t\t\t\teditor.execute( callbackOrCommand );\n\t\t\t};\n\t\t}\n\n\t\teditor.model.document.on( 'change', ( evt, batch ) => {\n\t\t\tif ( command && !command.isEnabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( batch.type == 'transparent' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst changes = Array.from( editor.model.document.differ.getChanges() );\n\t\t\tconst entry = changes[ 0 ];\n\n\t\t\t// Typing is represented by only a single change.\n\t\t\tif ( changes.length != 1 || entry.type !== 'insert' || entry.name != '$text' || entry.length != 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst item = entry.position.textNode || entry.position.nodeAfter;\n\n\t\t\tif ( !item.parent.is( 'paragraph' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst match = pattern.exec( item.data );\n\n\t\t\tif ( !match ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Use enqueueChange to create new batch to separate typing batch from the auto-format changes.\n\t\t\teditor.model.enqueueChange( writer => {\n\t\t\t\t// Matched range.\n\t\t\t\tconst start = writer.createPositionAt( item.parent, 0 );\n\t\t\t\tconst end = writer.createPositionAt( item.parent, match[ 0 ].length );\n\t\t\t\tconst range = new LiveRange( start, end );\n\n\t\t\t\tconst wasChanged = callback( { match } );\n\n\t\t\t\t// Remove matched text.\n\t\t\t\tif ( wasChanged !== false ) {\n\t\t\t\t\twriter.remove( range );\n\t\t\t\t}\n\n\t\t\t\trange.detach();\n\t\t\t} );\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/utils/getlasttextline\n */\n\n/**\n * Returns the last text line from the given range.\n *\n * \"The last text line\" is understood as text (from one or more text nodes) which is limited either by a parent block\n * or by inline elements (e.g. `<softBreak>`).\n *\n *\t\tconst rangeToCheck = model.createRange(\n *\t\t\tmodel.createPositionAt( paragraph, 0 ),\n *\t\t\tmodel.createPositionAt( paragraph, 'end' )\n *\t\t);\n *\n *\t\tconst { text, range } = getLastTextLine( rangeToCheck, model );\n *\n * For model below, the returned `text` will be \"Foo bar baz\" and `range` will be set on whole `<paragraph>` content:\n *\n *\t\t<paragraph>Foo bar baz<paragraph>\n *\n * However, in below case, `text` will be set to \"baz\" and `range` will be set only on \"baz\".\n *\n *\t\t<paragraph>Foo<softBreak></softBreak>bar<softBreak></softBreak>baz<paragraph>\n *\n * @protected\n * @param {module:engine/model/range~Range} range\n * @param {module:engine/model/model~Model} model\n * @returns {module:typing/utils/getlasttextline~LastTextLineData}\n */\nexport default function getLastTextLine( range, model ) {\n\tlet start = range.start;\n\n\tconst text = Array.from( range.getItems() ).reduce( ( rangeText, node ) => {\n\t\t// Trim text to a last occurrence of an inline element and update range start.\n\t\tif ( !( node.is( 'text' ) || node.is( 'textProxy' ) ) ) {\n\t\t\tstart = model.createPositionAfter( node );\n\n\t\t\treturn '';\n\t\t}\n\n\t\treturn rangeText + node.data;\n\t}, '' );\n\n\treturn { text, range: model.createRange( start, range.end ) };\n}\n\n/**\n * The value returned by {@link module:typing/utils/getlasttextline~getLastTextLine}.\n *\n * @typedef {Object} module:typing/utils/getlasttextline~LastTextLineData\n *\n * @property {String} text The text from the text nodes in the last text line.\n * @property {module:engine/model/range~Range} range The range set on the text nodes in the last text line.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 autoformat/inlineautoformatediting\n */\n\nimport getLastTextLine from '@ckeditor/ckeditor5-typing/src/utils/getlasttextline';\n\n/**\n * The inline autoformatting engine. It allows to format various inline patterns. For example,\n * it can be configured to make \"foo\" bold when typed `**foo**` (the `**` markers will be removed).\n *\n * The autoformatting operation is integrated with the undo manager,\n * so the autoformatting step can be undone if the user's intention was not to format the text.\n *\n * See the constructors documentation to learn how to create custom inline autoformatters. You can also use\n * the {@link module:autoformat/autoformat~Autoformat} feature which enables a set of default autoformatters\n * (lists, headings, bold and italic).\n */\nexport default class InlineAutoformatEditing {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'InlineAutoformatEditing';\n\t}\n\n\t/**\n\t * Enables autoformatting mechanism for a given {@link module:core/editor/editor~Editor}.\n\t *\n\t * It formats the matched text by applying the given model attribute or by running the provided formatting callback.\n\t * On every change applied to the model the autoformatting engine checks the text on the left of the selection\n\t * and executes the provided action if the text matches given criteria (regular expression or callback).\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t * @param {Function|RegExp} testRegexpOrCallback The regular expression or callback to execute on text.\n\t * Provided regular expression *must* have three capture groups. The first and the third capture group\n\t * should match opening and closing delimiters. The second capture group should match the text to format.\n\t *\n\t *\t\t// Matches the `**bold text**` pattern.\n\t *\t\t// There are three capturing groups:\n\t *\t\t// - The first to match the starting `**` delimiter.\n\t *\t\t// - The second to match the text to format.\n\t *\t\t// - The third to match the ending `**` delimiter.\n\t *\t\tnew InlineAutoformatEditing( editor, /(\\*\\*)([^\\*]+?)(\\*\\*)$/g, 'bold' );\n\t *\n\t * When a function is provided instead of the regular expression, it will be executed with the text to match as a parameter.\n\t * The function should return proper \"ranges\" to delete and format.\n\t *\n\t *\t\t{\n\t *\t\t\tremove: [\n\t *\t\t\t\t[ 0, 1 ],\t// Remove the first letter from the given text.\n\t *\t\t\t\t[ 5, 6 ]\t// Remove the 6th letter from the given text.\n\t *\t\t\t],\n\t *\t\t\tformat: [\n\t *\t\t\t\t[ 1, 5 ]\t// Format all letters from 2nd to 5th.\n\t *\t\t\t]\n\t *\t\t}\n\t *\n\t * @param {Function|String} attributeOrCallback The name of attribute to apply on matching text or a callback for manual\n\t * formatting. If callback is passed it should return `false` if changes should not be applied (e.g. if a command is disabled).\n\t *\n\t *\t\t// Use attribute name:\n\t *\t\tnew InlineAutoformatEditing( editor, /(\\*\\*)([^\\*]+?)(\\*\\*)$/g, 'bold' );\n\t *\n\t *\t\t// Use formatting callback:\n\t *\t\tnew InlineAutoformatEditing( editor, /(\\*\\*)([^\\*]+?)(\\*\\*)$/g, ( writer, rangesToFormat ) => {\n\t *\t\t\tconst command = editor.commands.get( 'bold' );\n\t *\n\t *\t\t\tif ( !command.isEnabled ) {\n\t *\t\t\t\treturn false;\n\t *\t\t\t}\n\t *\n\t *\t\t\tconst validRanges = editor.model.schema.getValidRanges( rangesToFormat, 'bold' );\n\t *\n\t *\t\t\tfor ( let range of validRanges ) {\n\t *\t\t\t\twriter.setAttribute( 'bold', true, range );\n\t *\t\t\t}\n\t *\t\t} );\n\t */\n\tconstructor( editor, testRegexpOrCallback, attributeOrCallback ) {\n\t\tlet regExp;\n\t\tlet attributeKey;\n\t\tlet testCallback;\n\t\tlet formatCallback;\n\n\t\tif ( testRegexpOrCallback instanceof RegExp ) {\n\t\t\tregExp = testRegexpOrCallback;\n\t\t} else {\n\t\t\ttestCallback = testRegexpOrCallback;\n\t\t}\n\n\t\tif ( typeof attributeOrCallback == 'string' ) {\n\t\t\tattributeKey = attributeOrCallback;\n\t\t} else {\n\t\t\tformatCallback = attributeOrCallback;\n\t\t}\n\n\t\t// A test callback run on changed text.\n\t\ttestCallback = testCallback || ( text => {\n\t\t\tlet result;\n\t\t\tconst remove = [];\n\t\t\tconst format = [];\n\n\t\t\twhile ( ( result = regExp.exec( text ) ) !== null ) {\n\t\t\t\t// There should be full match and 3 capture groups.\n\t\t\t\tif ( result && result.length < 4 ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tlet {\n\t\t\t\t\tindex,\n\t\t\t\t\t'1': leftDel,\n\t\t\t\t\t'2': content,\n\t\t\t\t\t'3': rightDel\n\t\t\t\t} = result;\n\n\t\t\t\t// Real matched string - there might be some non-capturing groups so we need to recalculate starting index.\n\t\t\t\tconst found = leftDel + content + rightDel;\n\t\t\t\tindex += result[ 0 ].length - found.length;\n\n\t\t\t\t// Start and End offsets of delimiters to remove.\n\t\t\t\tconst delStart = [\n\t\t\t\t\tindex,\n\t\t\t\t\tindex + leftDel.length\n\t\t\t\t];\n\t\t\t\tconst delEnd = [\n\t\t\t\t\tindex + leftDel.length + content.length,\n\t\t\t\t\tindex + leftDel.length + content.length + rightDel.length\n\t\t\t\t];\n\n\t\t\t\tremove.push( delStart );\n\t\t\t\tremove.push( delEnd );\n\n\t\t\t\tformat.push( [ index + leftDel.length, index + leftDel.length + content.length ] );\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tremove,\n\t\t\t\tformat\n\t\t\t};\n\t\t} );\n\n\t\t// A format callback run on matched text.\n\t\tformatCallback = formatCallback || ( ( writer, rangesToFormat ) => {\n\t\t\tconst validRanges = editor.model.schema.getValidRanges( rangesToFormat, attributeKey );\n\n\t\t\tfor ( const range of validRanges ) {\n\t\t\t\twriter.setAttribute( attributeKey, true, range );\n\t\t\t}\n\n\t\t\t// After applying attribute to the text, remove given attribute from the selection.\n\t\t\t// This way user is able to type a text without attribute used by auto formatter.\n\t\t\twriter.removeSelectionAttribute( attributeKey );\n\t\t} );\n\n\t\teditor.model.document.on( 'change', ( evt, batch ) => {\n\t\t\tif ( batch.type == 'transparent' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst model = editor.model;\n\t\t\tconst selection = model.document.selection;\n\n\t\t\t// Do nothing if selection is not collapsed.\n\t\t\tif ( !selection.isCollapsed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst changes = Array.from( model.document.differ.getChanges() );\n\t\t\tconst entry = changes[ 0 ];\n\n\t\t\t// Typing is represented by only a single change.\n\t\t\tif ( changes.length != 1 || entry.type !== 'insert' || entry.name != '$text' || entry.length != 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst focus = selection.focus;\n\t\t\tconst block = focus.parent;\n\t\t\tconst { text, range } = getLastTextLine( model.createRange( model.createPositionAt( block, 0 ), focus ), model );\n\t\t\tconst testOutput = testCallback( text );\n\t\t\tconst rangesToFormat = testOutputToRanges( range.start, testOutput.format, model );\n\t\t\tconst rangesToRemove = testOutputToRanges( range.start, testOutput.remove, model );\n\n\t\t\tif ( !( rangesToFormat.length && rangesToRemove.length ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Use enqueueChange to create new batch to separate typing batch from the auto-format changes.\n\t\t\tmodel.enqueueChange( writer => {\n\t\t\t\t// Apply format.\n\t\t\t\tconst hasChanged = formatCallback( writer, rangesToFormat );\n\n\t\t\t\t// Strict check on `false` to have backward compatibility (when callbacks were returning `undefined`).\n\t\t\t\tif ( hasChanged === false ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Remove delimiters - use reversed order to not mix the offsets while removing.\n\t\t\t\tfor ( const range of rangesToRemove.reverse() ) {\n\t\t\t\t\twriter.remove( range );\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n}\n\n// Converts output of the test function provided to the InlineAutoformatEditing and converts it to the model ranges\n// inside provided block.\n//\n// @private\n// @param {module:engine/model/position~Position} start\n// @param {Array.<Array>} arrays\n// @param {module:engine/model/model~Model} model\nfunction testOutputToRanges( start, arrays, model ) {\n\treturn arrays\n\t\t.filter( array => ( array[ 0 ] !== undefined && array[ 1 ] !== undefined ) )\n\t\t.map( array => {\n\t\t\treturn model.createRange( start.getShiftedBy( array[ 0 ] ), start.getShiftedBy( array[ 1 ] ) );\n\t\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 autoformat/autoformat\n */\n\nimport BlockAutoformatEditing from './blockautoformatediting';\nimport InlineAutoformatEditing from './inlineautoformatediting';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\n/**\n * Enables a set of predefined autoformatting actions.\n *\n * For a detailed overview, check the {@glink features/autoformat Autoformatting feature documentation}\n * and the {@glink api/autoformat package page}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Autoformat extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Autoformat';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tafterInit() {\n\t\tthis._addListAutoformats();\n\t\tthis._addBasicStylesAutoformats();\n\t\tthis._addHeadingAutoformats();\n\t\tthis._addBlockQuoteAutoformats();\n\t}\n\n\t/**\n\t * Adds autoformatting related to the {@link module:list/list~List}.\n\t *\n\t * When typed:\n\t * - `* ` or `- ` &ndash; A paragraph will be changed to a bulleted list.\n\t * - `1. ` or `1) ` &ndash; A paragraph will be changed to a numbered list (\"1\" can be any digit or a list of digits).\n\t *\n\t * @private\n\t */\n\t_addListAutoformats() {\n\t\tconst commands = this.editor.commands;\n\n\t\tif ( commands.get( 'bulletedList' ) ) {\n\t\t\t// eslint-disable-next-line no-new\n\t\t\tnew BlockAutoformatEditing( this.editor, /^[*-]\\s$/, 'bulletedList' );\n\t\t}\n\n\t\tif ( commands.get( 'numberedList' ) ) {\n\t\t\t// eslint-disable-next-line no-new\n\t\t\tnew BlockAutoformatEditing( this.editor, /^1[.|)]\\s$/, 'numberedList' );\n\t\t}\n\t}\n\n\t/**\n\t * Adds autoformatting related to the {@link module:basic-styles/bold~Bold},\n\t * {@link module:basic-styles/italic~Italic} and {@link module:basic-styles/code~Code}.\n\t *\n\t * When typed:\n\t * - `**foobar**` &ndash; `**` characters are removed and `foobar` is set to bold,\n\t * - `__foobar__` &ndash; `__` characters are removed and `foobar` is set to bold,\n\t * - `*foobar*` &ndash; `*` characters are removed and `foobar` is set to italic,\n\t * - `_foobar_` &ndash; `_` characters are removed and `foobar` is set to italic,\n\t * - ``` `foobar` &ndash; ``` ` ``` characters are removed and `foobar` is set to code.\n\t *\n\t * @private\n\t */\n\t_addBasicStylesAutoformats() {\n\t\tconst commands = this.editor.commands;\n\n\t\tif ( commands.get( 'bold' ) ) {\n\t\t\t/* eslint-disable no-new */\n\t\t\tconst boldCallback = getCallbackFunctionForInlineAutoformat( this.editor, 'bold' );\n\n\t\t\tnew InlineAutoformatEditing( this.editor, /(\\*\\*)([^*]+)(\\*\\*)$/g, boldCallback );\n\t\t\tnew InlineAutoformatEditing( this.editor, /(__)([^_]+)(__)$/g, boldCallback );\n\t\t\t/* eslint-enable no-new */\n\t\t}\n\n\t\tif ( commands.get( 'italic' ) ) {\n\t\t\t/* eslint-disable no-new */\n\t\t\tconst italicCallback = getCallbackFunctionForInlineAutoformat( this.editor, 'italic' );\n\n\t\t\t// The italic autoformatter cannot be triggered by the bold markers, so we need to check the\n\t\t\t// text before the pattern (e.g. `(?:^|[^\\*])`).\n\t\t\tnew InlineAutoformatEditing( this.editor, /(?:^|[^*])(\\*)([^*_]+)(\\*)$/g, italicCallback );\n\t\t\tnew InlineAutoformatEditing( this.editor, /(?:^|[^_])(_)([^_]+)(_)$/g, italicCallback );\n\t\t\t/* eslint-enable no-new */\n\t\t}\n\n\t\tif ( commands.get( 'code' ) ) {\n\t\t\t/* eslint-disable no-new */\n\t\t\tconst codeCallback = getCallbackFunctionForInlineAutoformat( this.editor, 'code' );\n\n\t\t\tnew InlineAutoformatEditing( this.editor, /(`)([^`]+)(`)$/g, codeCallback );\n\t\t\t/* eslint-enable no-new */\n\t\t}\n\t}\n\n\t/**\n\t * Adds autoformatting related to {@link module:heading/heading~Heading}.\n\t *\n\t * It is using a number at the end of the command name to associate it with the proper trigger:\n\t *\n\t * * `heading` with value `heading1` will be executed when typing `#`,\n\t * * `heading` with value `heading2` will be executed when typing `##`,\n\t * * ... up to `heading6` and `######`.\n\t *\n\t * @private\n\t */\n\t_addHeadingAutoformats() {\n\t\tconst command = this.editor.commands.get( 'heading' );\n\n\t\tif ( command ) {\n\t\t\tcommand.modelElements\n\t\t\t\t.filter( name => name.match( /^heading[1-6]$/ ) )\n\t\t\t\t.forEach( commandValue => {\n\t\t\t\t\tconst level = commandValue[ 7 ];\n\t\t\t\t\tconst pattern = new RegExp( `^(#{${ level }})\\\\s$` );\n\n\t\t\t\t\t// eslint-disable-next-line no-new\n\t\t\t\t\tnew BlockAutoformatEditing( this.editor, pattern, () => {\n\t\t\t\t\t\tif ( !command.isEnabled ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis.editor.execute( 'heading', { value: commandValue } );\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Adds autoformatting related to {@link module:block-quote/blockquote~BlockQuote}.\n\t *\n\t * When typed:\n\t * * `> ` &ndash; A paragraph will be changed to a block quote.\n\t *\n\t * @private\n\t */\n\t_addBlockQuoteAutoformats() {\n\t\tif ( this.editor.commands.get( 'blockQuote' ) ) {\n\t\t\t// eslint-disable-next-line no-new\n\t\t\tnew BlockAutoformatEditing( this.editor, /^>\\s$/, 'blockQuote' );\n\t\t}\n\t}\n}\n\n// Helper function for getting `InlineAutoformatEditing` callbacks that checks if command is enabled.\n//\n// @param {module:core/editor/editor~Editor} editor\n// @param {String} attributeKey\n// @returns {Function}\nfunction getCallbackFunctionForInlineAutoformat( editor, attributeKey ) {\n\treturn ( writer, rangesToFormat ) => {\n\t\tconst command = editor.commands.get( attributeKey );\n\n\t\tif ( !command.isEnabled ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst validRanges = editor.model.schema.getValidRanges( rangesToFormat, attributeKey );\n\n\t\tfor ( const range of validRanges ) {\n\t\t\twriter.setAttribute( attributeKey, true, range );\n\t\t}\n\n\t\t// After applying attribute to the text, remove given attribute from the selection.\n\t\t// This way user is able to type a text without attribute used by auto formatter.\n\t\twriter.removeSelectionAttribute( attributeKey );\n\t};\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/attributecommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\n/**\n * An extension of the base {@link module:core/command~Command} class, which provides utilities for a command\n * that toggles a single attribute on a text or an element.\n *\n * `AttributeCommand` uses {@link module:engine/model/document~Document#selection}\n * to decide which nodes (if any) should be changed, and applies or removes the attribute from them.\n *\n * The command checks the {@link module:engine/model/model~Model#schema} to decide if it can be enabled\n * for the current selection and to which nodes the attribute can be applied.\n *\n * @extends module:core/command~Command\n */\nexport default class AttributeCommand extends Command {\n\t/**\n\t * @param {module:core/editor/editor~Editor} editor\n\t * @param {String} attributeKey Attribute that will be set by the command.\n\t */\n\tconstructor( editor, attributeKey ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The attribute that will be set by the command.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.attributeKey = attributeKey;\n\n\t\t/**\n\t\t * Flag indicating whether the command is active. The command is active when the\n\t\t * {@link module:engine/model/selection~Selection#hasAttribute selection has the attribute} which means that:\n\t\t *\n\t\t * * If the selection is not empty &ndash; That the attribute is set on the first node in the selection that allows this attribute.\n\t\t * * If the selection is empty &ndash; That the selection has the attribute itself (which means that newly typed\n\t\t * text will have this attribute, too).\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #value\n\t\t */\n\t}\n\n\t/**\n\t * Updates the command's {@link #value} and {@link #isEnabled} based on the current selection.\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tthis.value = this._getValueFromFirstAllowedNode();\n\t\tthis.isEnabled = model.schema.checkAttributeInSelection( doc.selection, this.attributeKey );\n\t}\n\n\t/**\n\t * Executes the command &mdash; applies the attribute to the selection or removes it from the selection.\n\t *\n\t * If the command is active (`value == true`), it will remove attributes. Otherwise, it will set attributes.\n\t *\n\t * The execution result differs, depending on the {@link module:engine/model/document~Document#selection}:\n\t *\n\t * * If the selection is on a range, the command applies the attribute to all nodes in that range\n\t * (if they are allowed to have this attribute by the {@link module:engine/model/schema~Schema schema}).\n\t * * If the selection is collapsed in a non-empty node, the command applies the attribute to the\n\t * {@link module:engine/model/document~Document#selection} itself (note that typed characters copy attributes from the selection).\n\t * * If the selection is collapsed in an empty node, the command applies the attribute to the parent node of the selection (note\n\t * that the selection inherits all attributes from a node if it is in an empty node).\n\t *\n\t * @fires execute\n\t * @param {Object} [options] Command options.\n\t * @param {Boolean} [options.forceValue] If set, it will force the command behavior. If `true`, the command will apply the attribute,\n\t * otherwise the command will remove the attribute.\n\t * If not set, the command will look for its current value to decide what it should do.\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst selection = doc.selection;\n\t\tconst value = ( options.forceValue === undefined ) ? !this.value : options.forceValue;\n\n\t\tmodel.change( writer => {\n\t\t\tif ( selection.isCollapsed ) {\n\t\t\t\tif ( value ) {\n\t\t\t\t\twriter.setSelectionAttribute( this.attributeKey, true );\n\t\t\t\t} else {\n\t\t\t\t\twriter.removeSelectionAttribute( this.attributeKey );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst ranges = model.schema.getValidRanges( selection.getRanges(), this.attributeKey );\n\n\t\t\t\tfor ( const range of ranges ) {\n\t\t\t\t\tif ( value ) {\n\t\t\t\t\t\twriter.setAttribute( this.attributeKey, value, range );\n\t\t\t\t\t} else {\n\t\t\t\t\t\twriter.removeAttribute( this.attributeKey, range );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Checks the attribute value of the first node in the selection that allows the attribute.\n\t * For the collapsed selection returns the selection attribute.\n\t *\n\t * @private\n\t * @returns {Boolean} The attribute value.\n\t */\n\t_getValueFromFirstAllowedNode() {\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\t\tconst selection = model.document.selection;\n\n\t\tif ( selection.isCollapsed ) {\n\t\t\treturn selection.hasAttribute( this.attributeKey );\n\t\t}\n\n\t\tfor ( const range of selection.getRanges() ) {\n\t\t\tfor ( const item of range.getItems() ) {\n\t\t\t\tif ( schema.checkAttribute( item, this.attributeKey ) ) {\n\t\t\t\t\treturn item.hasAttribute( this.attributeKey );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/bold/boldediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport AttributeCommand from '../attributecommand';\n\nconst BOLD = 'bold';\n\n/**\n * The bold editing feature.\n *\n * It registers the `'bold'` command and introduces the `bold` attribute in the model which renders to the view\n * as a `<strong>` element.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class BoldEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'BoldEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\t// Allow bold attribute on text nodes.\n\t\teditor.model.schema.extend( '$text', { allowAttributes: BOLD } );\n\t\teditor.model.schema.setAttributeProperties( BOLD, {\n\t\t\tisFormatting: true,\n\t\t\tcopyOnEnter: true\n\t\t} );\n\n\t\t// Build converter from model to view for data and editing pipelines.\n\t\teditor.conversion.attributeToElement( {\n\t\t\tmodel: BOLD,\n\t\t\tview: 'strong',\n\t\t\tupcastAlso: [\n\t\t\t\t'b',\n\t\t\t\tviewElement => {\n\t\t\t\t\tconst fontWeight = viewElement.getStyle( 'font-weight' );\n\n\t\t\t\t\tif ( !fontWeight ) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Value of the `font-weight` attribute can be defined as a string or a number.\n\t\t\t\t\tif ( fontWeight == 'bold' || Number( fontWeight ) >= 600 ) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tname: true,\n\t\t\t\t\t\t\tstyles: [ 'font-weight' ]\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\n\t\t// Create bold command.\n\t\teditor.commands.add( BOLD, new AttributeCommand( editor, BOLD ) );\n\n\t\t// Set the Ctrl+B keystroke.\n\t\teditor.keystrokes.set( 'CTRL+B', BOLD );\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M10.187 17H5.773c-.637 0-1.092-.138-1.364-.415-.273-.277-.409-.718-.409-1.323V4.738c0-.617.14-1.062.419-1.332.279-.27.73-.406 1.354-.406h4.68c.69 0 1.288.041 1.793.124.506.083.96.242 1.36.478.341.197.644.447.906.75a3.262 3.262 0 0 1 .808 2.162c0 1.401-.722 2.426-2.167 3.075C15.05 10.175 16 11.315 16 13.01a3.756 3.756 0 0 1-2.296 3.504 6.1 6.1 0 0 1-1.517.377c-.571.073-1.238.11-2 .11zm-.217-6.217H7v4.087h3.069c1.977 0 2.965-.69 2.965-2.072 0-.707-.256-1.22-.768-1.537-.512-.319-1.277-.478-2.296-.478zM7 5.13v3.619h2.606c.729 0 1.292-.067 1.69-.2a1.6 1.6 0 0 0 .91-.765c.165-.267.247-.566.247-.897 0-.707-.26-1.176-.778-1.409-.519-.232-1.31-.348-2.375-.348H7z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module basic-styles/bold/boldui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport boldIcon from '../../theme/icons/bold.svg';\nconst BOLD = 'bold';\n/**\n * The bold UI feature. It introduces the Bold button.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class BoldUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const t = editor.t;\n // Add bold button to feature components.\n editor.ui.componentFactory.add(BOLD, locale => {\n const command = editor.commands.get(BOLD);\n const view = new ButtonView(locale);\n view.set({\n label: t('d'),\n icon: boldIcon,\n keystroke: 'CTRL+B',\n tooltip: true,\n isToggleable: true\n });\n view.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n // Execute command.\n this.listenTo(view, 'execute', () => editor.execute(BOLD));\n return view;\n });\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/code/codeediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport AttributeCommand from '../attributecommand';\n\nconst CODE = 'code';\n\n/**\n * The code editing feature.\n *\n * It registers the `'code'` command and introduces the `code` attribute in the model which renders to the view\n * as a `<code>` element.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class CodeEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'CodeEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Allow code attribute on text nodes.\n\t\teditor.model.schema.extend( '$text', { allowAttributes: CODE } );\n\t\teditor.model.schema.setAttributeProperties( CODE, {\n\t\t\tisFormatting: true,\n\t\t\tcopyOnEnter: true\n\t\t} );\n\n\t\teditor.conversion.attributeToElement( {\n\t\t\tmodel: CODE,\n\t\t\tview: 'code',\n\t\t\tupcastAlso: {\n\t\t\t\tstyles: {\n\t\t\t\t\t'word-wrap': 'break-word'\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t// Create code command.\n\t\teditor.commands.add( CODE, new AttributeCommand( editor, CODE ) );\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M12.5 5.7l5.2 3.9v1.3l-5.6 4c-.1.2-.3.2-.5.2-.3-.1-.6-.7-.6-1l.3-.4 4.7-3.5L11.5 7l-.2-.2c-.1-.3-.1-.6 0-.8.2-.2.5-.4.8-.4a.8.8 0 0 1 .4.1zm-5.2 0L2 9.6v1.3l5.6 4c.1.2.3.2.5.2.3-.1.7-.7.6-1 0-.1 0-.3-.2-.4l-5-3.5L8.2 7l.2-.2c.1-.3.1-.6 0-.8-.2-.2-.5-.4-.8-.4a.8.8 0 0 0-.3.1z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module basic-styles/code/codeui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport codeIcon from '../../theme/icons/code.svg';\nimport '../../theme/code.css';\nconst CODE = 'code';\n/**\n * The code UI feature. It introduces the Code button.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class CodeUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const t = editor.t;\n // Add code button to feature components.\n editor.ui.componentFactory.add(CODE, locale => {\n const command = editor.commands.get(CODE);\n const view = new ButtonView(locale);\n view.set({\n label: t('e'),\n icon: codeIcon,\n tooltip: true,\n isToggleable: true\n });\n view.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n // Execute command.\n this.listenTo(view, 'execute', () => editor.execute(CODE));\n return view;\n });\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/strikethrough/strikethroughediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport AttributeCommand from '../attributecommand';\n\nconst STRIKETHROUGH = 'strikethrough';\n\n/**\n * The strikethrough editing feature.\n *\n * It registers the `'strikethrough'` command, the <kbd>Ctrl+Shift+X</kbd> keystroke and introduces the\n * `strikethroughsthrough` attribute in the model which renders to the view\n * as a `<s>` element.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class StrikethroughEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'StrikethroughEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Allow strikethrough attribute on text nodes.\n\t\teditor.model.schema.extend( '$text', { allowAttributes: STRIKETHROUGH } );\n\t\teditor.model.schema.setAttributeProperties( STRIKETHROUGH, {\n\t\t\tisFormatting: true,\n\t\t\tcopyOnEnter: true\n\t\t} );\n\n\t\teditor.conversion.attributeToElement( {\n\t\t\tmodel: STRIKETHROUGH,\n\t\t\tview: 's',\n\t\t\tupcastAlso: [\n\t\t\t\t'del',\n\t\t\t\t'strike',\n\t\t\t\t{\n\t\t\t\t\tstyles: {\n\t\t\t\t\t\t'text-decoration': 'line-through'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\n\t\t// Create strikethrough command.\n\t\teditor.commands.add( STRIKETHROUGH, new AttributeCommand( editor, STRIKETHROUGH ) );\n\n\t\t// Set the Ctrl+Shift+X keystroke.\n\t\teditor.keystrokes.set( 'CTRL+SHIFT+X', 'strikethrough' );\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M7 16.4c-.8-.4-1.5-.9-2.2-1.5a.6.6 0 0 1-.2-.5l.3-.6h1c1 1.2 2.1 1.7 3.7 1.7 1 0 1.8-.3 2.3-.6.6-.4.6-1.2.6-1.3.2-1.2-.9-2.1-.9-2.1h2.1c.3.7.4 1.2.4 1.7v.8l-.6 1.2c-.6.8-1.1 1-1.6 1.2a6 6 0 0 1-2.4.6c-1 0-1.8-.3-2.5-.6zM6.8 9L6 8.3c-.4-.5-.5-.8-.5-1.6 0-.7.1-1.3.5-1.8.4-.6 1-1 1.6-1.3a6.3 6.3 0 0 1 4.7 0 4 4 0 0 1 1.7 1l.3.7c0 .1.2.4-.2.7-.4.2-.9.1-1 0a3 3 0 0 0-1.2-1c-.4-.2-1-.3-2-.4-.7 0-1.4.2-2 .6-.8.6-1 .8-1 1.5 0 .8.5 1 1.2 1.5.6.4 1.1.7 1.9 1H6.8z\\\"/><path d=\\\"M3 10.5V9h14v1.5z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module basic-styles/strikethrough/strikethroughui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport strikethroughIcon from '../../theme/icons/strikethrough.svg';\nconst STRIKETHROUGH = 'strikethrough';\n/**\n * The strikethrough UI feature. It introduces the Strikethrough button.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class StrikethroughUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const t = editor.t;\n // Add strikethrough button to feature components.\n editor.ui.componentFactory.add(STRIKETHROUGH, locale => {\n const command = editor.commands.get(STRIKETHROUGH);\n const view = new ButtonView(locale);\n view.set({\n label: t('f'),\n icon: strikethroughIcon,\n keystroke: 'CTRL+SHIFT+X',\n tooltip: true,\n isToggleable: true\n });\n view.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n // Execute command.\n this.listenTo(view, 'execute', () => editor.execute(STRIKETHROUGH));\n return view;\n });\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/italic/italicediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport AttributeCommand from '../attributecommand';\n\nconst ITALIC = 'italic';\n\n/**\n * The italic editing feature.\n *\n * It registers the `'italic'` command, the <kbd>Ctrl+I</kbd> keystroke and introduces the `italic` attribute in the model\n * which renders to the view as an `<i>` element.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ItalicEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ItalicEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Allow italic attribute on text nodes.\n\t\teditor.model.schema.extend( '$text', { allowAttributes: ITALIC } );\n\t\teditor.model.schema.setAttributeProperties( ITALIC, {\n\t\t\tisFormatting: true,\n\t\t\tcopyOnEnter: true\n\t\t} );\n\n\t\teditor.conversion.attributeToElement( {\n\t\t\tmodel: ITALIC,\n\t\t\tview: 'i',\n\t\t\tupcastAlso: [\n\t\t\t\t'em',\n\t\t\t\t{\n\t\t\t\t\tstyles: {\n\t\t\t\t\t\t'font-style': 'italic'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\n\t\t// Create italic command.\n\t\teditor.commands.add( ITALIC, new AttributeCommand( editor, ITALIC ) );\n\n\t\t// Set the Ctrl+I keystroke.\n\t\teditor.keystrokes.set( 'CTRL+I', ITALIC );\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M9.586 14.633l.021.004c-.036.335.095.655.393.962.082.083.173.15.274.201h1.474a.6.6 0 1 1 0 1.2H5.304a.6.6 0 0 1 0-1.2h1.15c.474-.07.809-.182 1.005-.334.157-.122.291-.32.404-.597l2.416-9.55a1.053 1.053 0 0 0-.281-.823 1.12 1.12 0 0 0-.442-.296H8.15a.6.6 0 0 1 0-1.2h6.443a.6.6 0 1 1 0 1.2h-1.195c-.376.056-.65.155-.823.296-.215.175-.423.439-.623.79l-2.366 9.347z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module basic-styles/italic/italicui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport italicIcon from '../../theme/icons/italic.svg';\nconst ITALIC = 'italic';\n/**\n * The italic UI feature. It introduces the Italic button.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ItalicUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const t = editor.t;\n // Add bold button to feature components.\n editor.ui.componentFactory.add(ITALIC, locale => {\n const command = editor.commands.get(ITALIC);\n const view = new ButtonView(locale);\n view.set({\n label: t('g'),\n icon: italicIcon,\n keystroke: 'CTRL+I',\n tooltip: true,\n isToggleable: true\n });\n view.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n // Execute command.\n this.listenTo(view, 'execute', () => editor.execute(ITALIC));\n return view;\n });\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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-2019, 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 block-quote/blockquotecommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\nimport first from '@ckeditor/ckeditor5-utils/src/first';\n\n/**\n * The block quote command plugin.\n *\n * @extends module:core/command~Command\n */\nexport default class BlockQuoteCommand extends Command {\n\t/**\n\t * Whether the selection starts in a block quote.\n\t *\n\t * @observable\n\t * @readonly\n\t * @member {Boolean} #value\n\t */\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.value = this._getValue();\n\t\tthis.isEnabled = this._checkEnabled();\n\t}\n\n\t/**\n\t * Executes the command. When the command {@link #value is on}, all top-most block quotes within\n\t * the selection will be removed. If it is off, all selected blocks will be wrapped with\n\t * a block quote.\n\t *\n\t * @fires execute\n\t * @param {Object} [options] Command options.\n\t * @param {Boolean} [options.forceValue] If set, it will force the command behavior. If `true`, the command will apply a block quote,\n\t * otherwise the command will remove the block quote. If not set, the command will act basing on its current value.\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\t\tconst selection = model.document.selection;\n\n\t\tconst blocks = Array.from( selection.getSelectedBlocks() );\n\n\t\tconst value = ( options.forceValue === undefined ) ? !this.value : options.forceValue;\n\n\t\tmodel.change( writer => {\n\t\t\tif ( !value ) {\n\t\t\t\tthis._removeQuote( writer, blocks.filter( findQuote ) );\n\t\t\t} else {\n\t\t\t\tconst blocksToQuote = blocks.filter( block => {\n\t\t\t\t\t// Already quoted blocks needs to be considered while quoting too\n\t\t\t\t\t// in order to reuse their <bQ> elements.\n\t\t\t\t\treturn findQuote( block ) || checkCanBeQuoted( schema, block );\n\t\t\t\t} );\n\n\t\t\t\tthis._applyQuote( writer, blocksToQuote );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Checks the command's {@link #value}.\n\t *\n\t * @private\n\t * @returns {Boolean} The current value.\n\t */\n\t_getValue() {\n\t\tconst selection = this.editor.model.document.selection;\n\n\t\tconst firstBlock = first( selection.getSelectedBlocks() );\n\n\t\t// In the current implementation, the block quote must be an immediate parent of a block element.\n\t\treturn !!( firstBlock && findQuote( firstBlock ) );\n\t}\n\n\t/**\n\t * Checks whether the command can be enabled in the current context.\n\t *\n\t * @private\n\t * @returns {Boolean} Whether the command should be enabled.\n\t */\n\t_checkEnabled() {\n\t\tif ( this.value ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst selection = this.editor.model.document.selection;\n\t\tconst schema = this.editor.model.schema;\n\n\t\tconst firstBlock = first( selection.getSelectedBlocks() );\n\n\t\tif ( !firstBlock ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn checkCanBeQuoted( schema, firstBlock );\n\t}\n\n\t/**\n\t * Removes the quote from given blocks.\n\t *\n\t * If blocks which are supposed to be \"unquoted\" are in the middle of a quote,\n\t * start it or end it, then the quote will be split (if needed) and the blocks\n\t * will be moved out of it, so other quoted blocks remained quoted.\n\t *\n\t * @private\n\t * @param {module:engine/model/writer~Writer} writer\n\t * @param {Array.<module:engine/model/element~Element>} blocks\n\t */\n\t_removeQuote( writer, blocks ) {\n\t\t// Unquote all groups of block. Iterate in the reverse order to not break following ranges.\n\t\tgetRangesOfBlockGroups( writer, blocks ).reverse().forEach( groupRange => {\n\t\t\tif ( groupRange.start.isAtStart && groupRange.end.isAtEnd ) {\n\t\t\t\twriter.unwrap( groupRange.start.parent );\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// The group of blocks are at the beginning of an <bQ> so let's move them left (out of the <bQ>).\n\t\t\tif ( groupRange.start.isAtStart ) {\n\t\t\t\tconst positionBefore = writer.createPositionBefore( groupRange.start.parent );\n\n\t\t\t\twriter.move( groupRange, positionBefore );\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// The blocks are in the middle of an <bQ> so we need to split the <bQ> after the last block\n\t\t\t// so we move the items there.\n\t\t\tif ( !groupRange.end.isAtEnd ) {\n\t\t\t\twriter.split( groupRange.end );\n\t\t\t}\n\n\t\t\t// Now we are sure that groupRange.end.isAtEnd is true, so let's move the blocks right.\n\n\t\t\tconst positionAfter = writer.createPositionAfter( groupRange.end.parent );\n\n\t\t\twriter.move( groupRange, positionAfter );\n\t\t} );\n\t}\n\n\t/**\n\t * Applies the quote to given blocks.\n\t *\n\t * @private\n\t * @param {module:engine/model/writer~Writer} writer\n\t * @param {Array.<module:engine/model/element~Element>} blocks\n\t */\n\t_applyQuote( writer, blocks ) {\n\t\tconst quotesToMerge = [];\n\n\t\t// Quote all groups of block. Iterate in the reverse order to not break following ranges.\n\t\tgetRangesOfBlockGroups( writer, blocks ).reverse().forEach( groupRange => {\n\t\t\tlet quote = findQuote( groupRange.start );\n\n\t\t\tif ( !quote ) {\n\t\t\t\tquote = writer.createElement( 'blockQuote' );\n\n\t\t\t\twriter.wrap( groupRange, quote );\n\t\t\t}\n\n\t\t\tquotesToMerge.push( quote );\n\t\t} );\n\n\t\t// Merge subsequent <bQ> elements. Reverse the order again because this time we want to go through\n\t\t// the <bQ> elements in the source order (due to how merge works – it moves the right element's content\n\t\t// to the first element and removes the right one. Since we may need to merge a couple of subsequent `<bQ>` elements\n\t\t// we want to keep the reference to the first (furthest left) one.\n\t\tquotesToMerge.reverse().reduce( ( currentQuote, nextQuote ) => {\n\t\t\tif ( currentQuote.nextSibling == nextQuote ) {\n\t\t\t\twriter.merge( writer.createPositionAfter( currentQuote ) );\n\n\t\t\t\treturn currentQuote;\n\t\t\t}\n\n\t\t\treturn nextQuote;\n\t\t} );\n\t}\n}\n\nfunction findQuote( elementOrPosition ) {\n\treturn elementOrPosition.parent.name == 'blockQuote' ? elementOrPosition.parent : null;\n}\n\n// Returns a minimal array of ranges containing groups of subsequent blocks.\n//\n// content: abcdefgh\n// blocks: [ a, b, d, f, g, h ]\n// output ranges: [ab]c[d]e[fgh]\n//\n// @param {Array.<module:engine/model/element~Element>} blocks\n// @returns {Array.<module:engine/model/range~Range>}\nfunction getRangesOfBlockGroups( writer, blocks ) {\n\tlet startPosition;\n\tlet i = 0;\n\tconst ranges = [];\n\n\twhile ( i < blocks.length ) {\n\t\tconst block = blocks[ i ];\n\t\tconst nextBlock = blocks[ i + 1 ];\n\n\t\tif ( !startPosition ) {\n\t\t\tstartPosition = writer.createPositionBefore( block );\n\t\t}\n\n\t\tif ( !nextBlock || block.nextSibling != nextBlock ) {\n\t\t\tranges.push( writer.createRange( startPosition, writer.createPositionAfter( block ) ) );\n\t\t\tstartPosition = null;\n\t\t}\n\n\t\ti++;\n\t}\n\n\treturn ranges;\n}\n\n// Checks whether <bQ> can wrap the block.\nfunction checkCanBeQuoted( schema, block ) {\n\t// TMP will be replaced with schema.checkWrap().\n\tconst isBQAllowed = schema.checkChild( block.parent, 'blockQuote' );\n\tconst isBlockAllowedInBQ = schema.checkChild( [ '$root', 'blockQuote' ], block );\n\n\treturn isBQAllowed && isBlockAllowedInBQ;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 block-quote/blockquoteediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport BlockQuoteCommand from './blockquotecommand';\n\n/**\n * The block quote editing.\n *\n * Introduces the `'blockQuote'` command and the `'blockQuote'` model element.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class BlockQuoteEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'BlockQuoteEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst schema = editor.model.schema;\n\n\t\teditor.commands.add( 'blockQuote', new BlockQuoteCommand( editor ) );\n\n\t\tschema.register( 'blockQuote', {\n\t\t\tallowWhere: '$block',\n\t\t\tallowContentOf: '$root'\n\t\t} );\n\n\t\t// Disallow blockQuote in blockQuote.\n\t\tschema.addChildCheck( ( ctx, childDef ) => {\n\t\t\tif ( ctx.endsWith( 'blockQuote' ) && childDef.name == 'blockQuote' ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\n\t\teditor.conversion.elementToElement( { model: 'blockQuote', view: 'blockquote' } );\n\n\t\t// Postfixer which cleans incorrect model states connected with block quotes.\n\t\teditor.model.document.registerPostFixer( writer => {\n\t\t\tconst changes = editor.model.document.differ.getChanges();\n\n\t\t\tfor ( const entry of changes ) {\n\t\t\t\tif ( entry.type == 'insert' ) {\n\t\t\t\t\tconst element = entry.position.nodeAfter;\n\n\t\t\t\t\tif ( !element ) {\n\t\t\t\t\t\t// We are inside a text node.\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( element.is( 'blockQuote' ) && element.isEmpty ) {\n\t\t\t\t\t\t// Added an empty blockQuote - remove it.\n\t\t\t\t\t\twriter.remove( element );\n\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else if ( element.is( 'blockQuote' ) && !schema.checkChild( entry.position, element ) ) {\n\t\t\t\t\t\t// Added a blockQuote in incorrect place - most likely inside another blockQuote. Unwrap it\n\t\t\t\t\t\t// so the content inside is not lost.\n\t\t\t\t\t\twriter.unwrap( element );\n\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else if ( element.is( 'element' ) ) {\n\t\t\t\t\t\t// Just added an element. Check its children to see if there are no nested blockQuotes somewhere inside.\n\t\t\t\t\t\tconst range = writer.createRangeIn( element );\n\n\t\t\t\t\t\tfor ( const child of range.getItems() ) {\n\t\t\t\t\t\t\tif ( child.is( 'blockQuote' ) && !schema.checkChild( writer.createPositionBefore( child ), child ) ) {\n\t\t\t\t\t\t\t\twriter.unwrap( child );\n\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ( entry.type == 'remove' ) {\n\t\t\t\t\tconst parent = entry.position.parent;\n\n\t\t\t\t\tif ( parent.is( 'blockQuote' ) && parent.isEmpty ) {\n\t\t\t\t\t\t// Something got removed and now blockQuote is empty. Remove the blockQuote as well.\n\t\t\t\t\t\twriter.remove( parent );\n\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tafterInit() {\n\t\tconst editor = this.editor;\n\t\tconst command = editor.commands.get( 'blockQuote' );\n\n\t\t// Overwrite default Enter key behavior.\n\t\t// If Enter key is pressed with selection collapsed in empty block inside a quote, break the quote.\n\t\t// This listener is added in afterInit in order to register it after list's feature listener.\n\t\t// We can't use a priority for this, because 'low' is already used by the enter feature, unless\n\t\t// we'd use numeric priority in this case.\n\t\tthis.listenTo( this.editor.editing.view.document, 'enter', ( evt, data ) => {\n\t\t\tconst doc = this.editor.model.document;\n\t\t\tconst positionParent = doc.selection.getLastPosition().parent;\n\n\t\t\tif ( doc.selection.isCollapsed && positionParent.isEmpty && command.value ) {\n\t\t\t\tthis.editor.execute( 'blockQuote' );\n\t\t\t\tthis.editor.editing.view.scrollToTheSelection();\n\n\t\t\t\tdata.preventDefault();\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t} );\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M3 10.423a6.5 6.5 0 0 1 6.056-6.408l.038.67C6.448 5.423 5.354 7.663 5.22 10H9c.552 0 .5.432.5.986v4.511c0 .554-.448.503-1 .503h-5c-.552 0-.5-.449-.5-1.003v-4.574zm8 0a6.5 6.5 0 0 1 6.056-6.408l.038.67c-2.646.739-3.74 2.979-3.873 5.315H17c.552 0 .5.432.5.986v4.511c0 .554-.448.503-1 .503h-5c-.552 0-.5-.449-.5-1.003v-4.574z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module block-quote/blockquoteui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport quoteIcon from '@ckeditor/ckeditor5-core/theme/icons/quote.svg';\nimport '../theme/blockquote.css';\n/**\n * The block quote UI plugin.\n *\n * It introduces the `'blockQuote'` button.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class BlockQuoteUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const t = editor.t;\n editor.ui.componentFactory.add('blockQuote', locale => {\n const command = editor.commands.get('blockQuote');\n const buttonView = new ButtonView(locale);\n buttonView.set({\n label: t('bk'),\n icon: quoteIcon,\n tooltip: true,\n isToggleable: true\n });\n // Bind button model to command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n // Execute command.\n this.listenTo(buttonView, 'execute', () => editor.execute('blockQuote'));\n return buttonView;\n });\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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 paragraph/paragraphcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport first from '@ckeditor/ckeditor5-utils/src/first';\n\n/**\n * The paragraph command.\n *\n * @extends module:core/command~Command\n */\nexport default class ParagraphCommand extends Command {\n\t/**\n\t * The value of the command. Indicates whether the selection start is placed in a paragraph.\n\t *\n\t * @readonly\n\t * @observable\n\t * @member {Boolean} #value\n\t */\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\t\tconst block = first( document.selection.getSelectedBlocks() );\n\n\t\tthis.value = !!block && block.is( 'paragraph' );\n\t\tthis.isEnabled = !!block && checkCanBecomeParagraph( block, model.schema );\n\t}\n\n\t/**\n\t * Executes the command. All the blocks (see {@link module:engine/model/schema~Schema}) in the selection\n\t * will be turned to paragraphs.\n\t *\n\t * @fires execute\n\t * @param {Object} [options] Options for the executed command.\n\t * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} [options.selection]\n\t * The selection that the command should be applied to.\n\t * By default, if not provided, the command is applied to the {@link module:engine/model/document~Document#selection}.\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\n\t\tmodel.change( writer => {\n\t\t\tconst blocks = ( options.selection || document.selection ).getSelectedBlocks();\n\n\t\t\tfor ( const block of blocks ) {\n\t\t\t\tif ( !block.is( 'paragraph' ) && checkCanBecomeParagraph( block, model.schema ) ) {\n\t\t\t\t\twriter.rename( block, 'paragraph' );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n}\n\n// Checks whether the given block can be replaced by a paragraph.\n//\n// @private\n// @param {module:engine/model/element~Element} block A block to be tested.\n// @param {module:engine/model/schema~Schema} schema The schema of the document.\n// @returns {Boolean}\nfunction checkCanBecomeParagraph( block, schema ) {\n\treturn schema.checkChild( block.parent, 'paragraph' ) && !schema.isObject( block );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 paragraph/paragraph\n */\n\nimport ParagraphCommand from './paragraphcommand';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\n/**\n * The paragraph feature for the editor.\n *\n * It introduces the `<paragraph>` element in the model which renders as a `<p>` element in the DOM and data.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Paragraph extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Paragraph';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst data = editor.data;\n\n\t\teditor.commands.add( 'paragraph', new ParagraphCommand( editor ) );\n\n\t\t// Schema.\n\t\tmodel.schema.register( 'paragraph', { inheritAllFrom: '$block' } );\n\n\t\teditor.conversion.elementToElement( { model: 'paragraph', view: 'p' } );\n\n\t\t// Content autoparagraphing. --------------------------------------------------\n\n\t\t// Handles element which has not been converted by any plugin and checks if it would be converted if\n\t\t// we wrap it in a paragraph or change it to a paragraph.\n\t\teditor.conversion.for( 'upcast' ).elementToElement( {\n\t\t\tmodel: ( viewElement, modelWriter ) => {\n\t\t\t\tif ( !Paragraph.paragraphLikeElements.has( viewElement.name ) ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Do not auto-paragraph empty elements.\n\t\t\t\tif ( viewElement.isEmpty ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\treturn modelWriter.createElement( 'paragraph' );\n\t\t\t},\n\t\t\tconverterPriority: 'low'\n\t\t} );\n\n\t\tdata.upcastDispatcher.on( 'element', ( evt, data, conversionApi ) => {\n\t\t\t// Do not try auto-paragraphing if the element was already converted.\n\t\t\tif ( !conversionApi.consumable.test( data.viewItem, { name: data.viewItem.name } ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If the element is not paragraph-like try wrapping it in a paragraph.\n\t\t\tif ( isParagraphable( data.viewItem, data.modelCursor, conversionApi.schema ) ) {\n\t\t\t\tObject.assign( data, wrapInParagraph( data.viewItem, data.modelCursor, conversionApi ) );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\n\t\t// Handles not converted text nodes and checks if would be converted if we wraps then by a paragraph.\n\t\tdata.upcastDispatcher.on( 'text', ( evt, data, conversionApi ) => {\n\t\t\t// When node is already converted then do nothing.\n\t\t\tif ( data.modelRange ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isParagraphable( data.viewItem, data.modelCursor, conversionApi.schema ) ) {\n\t\t\t\tObject.assign( data, wrapInParagraph( data.viewItem, data.modelCursor, conversionApi ) );\n\t\t\t}\n\t\t}, { priority: 'lowest' } );\n\n\t\t// Empty roots autoparagraphing. -----------------------------------------------\n\n\t\t// Post-fixer which takes care of adding empty paragraph elements to empty roots.\n\t\t// Besides fixing content on #changesDone we also need to handle editor.data#ready event because\n\t\t// if initial data is empty or setData() wasn't even called there will be no #change fired.\n\t\tmodel.document.registerPostFixer( writer => this._autoparagraphEmptyRoots( writer ) );\n\n\t\teditor.data.on( 'ready', () => {\n\t\t\tmodel.enqueueChange( 'transparent', writer => this._autoparagraphEmptyRoots( writer ) );\n\t\t}, { priority: 'lowest' } );\n\t}\n\n\t/**\n\t * Fixes all empty roots.\n\t *\n\t * @private\n\t * @returns {Boolean} `true` if any change has been applied, `false` otherwise.\n\t */\n\t_autoparagraphEmptyRoots( writer ) {\n\t\tconst model = this.editor.model;\n\n\t\tfor ( const rootName of model.document.getRootNames() ) {\n\t\t\tconst root = model.document.getRoot( rootName );\n\n\t\t\tif ( root.isEmpty && root.rootName != '$graveyard' ) {\n\t\t\t\t// If paragraph element is allowed in the root, create paragraph element.\n\t\t\t\tif ( model.schema.checkChild( root, 'paragraph' ) ) {\n\t\t\t\t\twriter.insertElement( 'paragraph', root );\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * A list of element names which should be treated by the autoparagraphing algorithms as\n * paragraph-like. This means that e.g. the following content:\n *\n *\t\t<h1>Foo</h1>\n *\t\t<table>\n *\t\t\t<tr>\n *\t\t\t\t<td>X</td>\n *\t\t\t\t<td>\n *\t\t\t\t\t<ul>\n *\t\t\t\t\t\t<li>Y</li>\n *\t\t\t\t\t\t<li>Z</li>\n *\t\t\t\t\t</ul>\n *\t\t\t\t</td>\n *\t\t\t</tr>\n *\t\t</table>\n *\n * contains five paragraph-like elements: `<h1>`, two `<td>`s and two `<li>`s.\n * Hence, if none of the features is going to convert those elements the above content will be automatically handled\n * by the paragraph feature and converted to:\n *\n *\t\t<p>Foo</p>\n *\t\t<p>X</p>\n *\t\t<p>Y</p>\n *\t\t<p>Z</p>\n *\n * Note: The `<td>` containing two `<li>` elements was ignored as the innermost paragraph-like elements\n * have a priority upon conversion.\n *\n * @member {Set.<String>} module:paragraph/paragraph~Paragraph.paragraphLikeElements\n */\nParagraph.paragraphLikeElements = new Set( [\n\t'blockquote',\n\t'dd',\n\t'div',\n\t'dt',\n\t'h1',\n\t'h2',\n\t'h3',\n\t'h4',\n\t'h5',\n\t'h6',\n\t'li',\n\t'p',\n\t'td'\n] );\n\nfunction wrapInParagraph( input, position, conversionApi ) {\n\tconst paragraph = conversionApi.writer.createElement( 'paragraph' );\n\n\tconversionApi.writer.insert( paragraph, position );\n\treturn conversionApi.convertItem( input, conversionApi.writer.createPositionAt( paragraph, 0 ) );\n}\n\nfunction isParagraphable( node, position, schema ) {\n\tconst context = schema.createContext( position );\n\n\t// When paragraph is allowed in this context...\n\tif ( !schema.checkChild( context, 'paragraph' ) ) {\n\t\treturn false;\n\t}\n\n\t// And a node would be allowed in this paragraph...\n\tif ( !schema.checkChild( context.push( 'paragraph' ), node ) ) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 heading/headingcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport first from '@ckeditor/ckeditor5-utils/src/first';\n\n/**\n * The heading command. It is used by the {@link module:heading/heading~Heading heading feature} to apply headings.\n *\n * @extends module:core/command~Command\n */\nexport default class HeadingCommand extends Command {\n\t/**\n\t * Creates an instance of the command.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor Editor instance.\n\t * @param {Array.<String>} modelElements Names of the element which this command can apply in the model.\n\t */\n\tconstructor( editor, modelElements ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * If the selection starts in a heading (which {@link #modelElements is supported by this command})\n\t\t * the value is set to the name of that heading model element.\n\t\t * It is set to `false` otherwise.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean|String} #value\n\t\t */\n\n\t\t/**\n\t\t * Set of defined model's elements names that this command support.\n\t\t * See {@link module:heading/heading~HeadingOption}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Array.<String>}\n\t\t */\n\t\tthis.modelElements = modelElements;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst block = first( this.editor.model.document.selection.getSelectedBlocks() );\n\n\t\tthis.value = !!block && this.modelElements.includes( block.name ) && block.name;\n\t\tthis.isEnabled = !!block && this.modelElements.some( heading => checkCanBecomeHeading( block, heading, this.editor.model.schema ) );\n\t}\n\n\t/**\n\t * Executes the command. Applies the heading to the selected blocks or, if the first selected\n\t * block is a heading already, turns selected headings (of this level only) to paragraphs.\n\t *\n\t * @param {Object} options\n\t * @param {String} options.value Name of the element which this command will apply in the model.\n\t * @fires execute\n\t */\n\texecute( options ) {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\n\t\tconst modelElement = options.value;\n\n\t\tmodel.change( writer => {\n\t\t\tconst blocks = Array.from( document.selection.getSelectedBlocks() )\n\t\t\t\t.filter( block => {\n\t\t\t\t\treturn checkCanBecomeHeading( block, modelElement, model.schema );\n\t\t\t\t} );\n\n\t\t\tfor ( const block of blocks ) {\n\t\t\t\tif ( !block.is( modelElement ) ) {\n\t\t\t\t\twriter.rename( block, modelElement );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n}\n\n// Checks whether the given block can be replaced by a specific heading.\n//\n// @private\n// @param {module:engine/model/element~Element} block A block to be tested.\n// @param {module:heading/headingcommand~HeadingCommand#modelElement} heading Command element name in the model.\n// @param {module:engine/model/schema~Schema} schema The schema of the document.\n// @returns {Boolean}\nfunction checkCanBecomeHeading( block, heading, schema ) {\n\treturn schema.checkChild( block.parent, heading ) && !schema.isObject( block );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 heading/headingediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';\nimport HeadingCommand from './headingcommand';\n\nimport priorities from '@ckeditor/ckeditor5-utils/src/priorities';\n\nconst defaultModelElement = 'paragraph';\n\n/**\n * The headings engine feature. It handles switching between block formats &ndash; headings and paragraph.\n * This class represents the engine part of the heading feature. See also {@link module:heading/heading~Heading}.\n * It introduces `heading1`-`headingN` commands which allow to convert paragraphs into headings.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class HeadingEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'HeadingEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\teditor.config.define( 'heading', {\n\t\t\toptions: [\n\t\t\t\t{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },\n\t\t\t\t{ model: 'heading1', view: 'h2', title: 'Heading 1', class: 'ck-heading_heading1' },\n\t\t\t\t{ model: 'heading2', view: 'h3', title: 'Heading 2', class: 'ck-heading_heading2' },\n\t\t\t\t{ model: 'heading3', view: 'h4', title: 'Heading 3', class: 'ck-heading_heading3' }\n\t\t\t]\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ Paragraph ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst options = editor.config.get( 'heading.options' );\n\n\t\tconst modelElements = [];\n\n\t\tfor ( const option of options ) {\n\t\t\t// Skip paragraph - it is defined in required Paragraph feature.\n\t\t\tif ( option.model !== defaultModelElement ) {\n\t\t\t\t// Schema.\n\t\t\t\teditor.model.schema.register( option.model, {\n\t\t\t\t\tinheritAllFrom: '$block'\n\t\t\t\t} );\n\n\t\t\t\teditor.conversion.elementToElement( option );\n\n\t\t\t\tmodelElements.push( option.model );\n\t\t\t}\n\t\t}\n\n\t\tthis._addDefaultH1Conversion( editor );\n\n\t\t// Register the heading command for this option.\n\t\teditor.commands.add( 'heading', new HeadingCommand( editor, modelElements ) );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tafterInit() {\n\t\t// If the enter command is added to the editor, alter its behavior.\n\t\t// Enter at the end of a heading element should create a paragraph.\n\t\tconst editor = this.editor;\n\t\tconst enterCommand = editor.commands.get( 'enter' );\n\t\tconst options = editor.config.get( 'heading.options' );\n\n\t\tif ( enterCommand ) {\n\t\t\tthis.listenTo( enterCommand, 'afterExecute', ( evt, data ) => {\n\t\t\t\tconst positionParent = editor.model.document.selection.getFirstPosition().parent;\n\t\t\t\tconst isHeading = options.some( option => positionParent.is( option.model ) );\n\n\t\t\t\tif ( isHeading && !positionParent.is( defaultModelElement ) && positionParent.childCount === 0 ) {\n\t\t\t\t\tdata.writer.rename( positionParent, defaultModelElement );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Adds default conversion for `h1` -> `heading1` with a low priority.\n\t *\n\t * @private\n\t * @param {module:core/editor/editor~Editor} editor Editor instance on which to add the `h1` conversion.\n\t */\n\t_addDefaultH1Conversion( editor ) {\n\t\teditor.conversion.for( 'upcast' ).elementToElement( {\n\t\t\tmodel: 'heading1',\n\t\t\tview: 'h1',\n\t\t\t// With a `low` priority, `paragraph` plugin autoparagraphing mechanism is executed. Make sure\n\t\t\t// this listener is called before it. If not, `h1` will be transformed into a paragraph.\n\t\t\tconverterPriority: priorities.get( 'low' ) + 1\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/model\n */\n\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport { extend } from 'lodash-es';\n\n/**\n * The base MVC model class.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class Model {\n\t/**\n\t * Creates a new Model instance.\n\t *\n\t * @param {Object} [attributes] The model state attributes to be defined during the instance creation.\n\t * @param {Object} [properties] The (out of state) properties to be appended to the instance during creation.\n\t */\n\tconstructor( attributes, properties ) {\n\t\t// Extend this instance with the additional (out of state) properties.\n\t\tif ( properties ) {\n\t\t\textend( this, properties );\n\t\t}\n\n\t\t// Initialize the attributes.\n\t\tif ( attributes ) {\n\t\t\tthis.set( attributes );\n\t\t}\n\t}\n}\n\nmix( Model, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module heading/headingui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport Model from '@ckeditor/ckeditor5-ui/src/model';\nimport {\n createDropdown,\n addListToDropdown\n} from '@ckeditor/ckeditor5-ui/src/dropdown/utils';\nimport { getLocalizedOptions } from './utils';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport '../theme/heading.css';\n/**\n * The headings UI feature. It introduces the `headings` dropdown.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class HeadingUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const t = editor.t;\n const options = getLocalizedOptions(editor);\n const defaultTitle = t('bh');\n const dropdownTooltip = t('bi');\n // Register UI component.\n editor.ui.componentFactory.add('heading', locale => {\n const titles = {};\n const itemDefinitions = new Collection();\n const headingCommand = editor.commands.get('heading');\n const paragraphCommand = editor.commands.get('paragraph');\n const commands = [headingCommand];\n for (const option of options) {\n const def = {\n type: 'button',\n model: new Model({\n label: option.title,\n class: option.class,\n withText: true\n })\n };\n if (option.model === 'paragraph') {\n def.model.bind('isOn').to(paragraphCommand, 'value');\n def.model.set('commandName', 'paragraph');\n commands.push(paragraphCommand);\n } else {\n def.model.bind('isOn').to(headingCommand, 'value', value => value === option.model);\n def.model.set({\n commandName: 'heading',\n commandValue: option.model\n });\n }\n // Add the option to the collection.\n itemDefinitions.add(def);\n titles[option.model] = option.title;\n }\n const dropdownView = createDropdown(locale);\n addListToDropdown(dropdownView, itemDefinitions);\n dropdownView.buttonView.set({\n isOn: false,\n withText: true,\n tooltip: dropdownTooltip\n });\n dropdownView.extendTemplate({ attributes: { class: ['ck-heading-dropdown'] } });\n dropdownView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled) => {\n return areEnabled.some(isEnabled => isEnabled);\n });\n dropdownView.buttonView.bind('label').to(headingCommand, 'value', paragraphCommand, 'value', (value, para) => {\n const whichModel = value || para && 'paragraph';\n // If none of the commands is active, display default title.\n return titles[whichModel] ? titles[whichModel] : defaultTitle;\n });\n // Execute command when an item from the dropdown is selected.\n this.listenTo(dropdownView, 'execute', evt => {\n editor.execute(evt.source.commandName, evt.source.commandValue ? { value: evt.source.commandValue } : undefined);\n editor.editing.view.focus();\n });\n return dropdownView;\n });\n }\n}","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module heading/utils\n */\n/**\n * Returns heading options as defined in `config.heading.options` but processed to consider\n * the editor localization, i.e. to display {@link module:heading/heading~HeadingOption}\n * in the correct language.\n *\n * Note: The reason behind this method is that there is no way to use {@link module:utils/locale~Locale#t}\n * when the user configuration is defined because the editor does not exist yet.\n *\n * @param {module:core/editor/editor~Editor} editor\n * @returns {Array.<module:heading/heading~HeadingOption>}.\n */\nexport function getLocalizedOptions(editor) {\n const t = editor.t;\n const localizedTitles = {\n Paragraph: t('bl'),\n 'Heading 1': t('bm'),\n 'Heading 2': t('bn'),\n 'Heading 3': t('bo'),\n 'Heading 4': t('bp'),\n 'Heading 5': t('bq'),\n 'Heading 6': t('br')\n };\n return editor.config.get('heading.options').map(option => {\n const title = localizedTitles[option.title];\n if (title && title != option.title) {\n option.title = title;\n }\n return option;\n });\n}","/**\n * @license Copyright (c) 2003-2019, 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 image/image/imageloadobserver\n */\n\nimport Observer from '@ckeditor/ckeditor5-engine/src/view/observer/observer';\n\n/**\n * Observes all new images added to the {@link module:engine/view/document~Document},\n * fires {@link module:engine/view/document~Document#event:imageLoaded} and\n * {@link module:engine/view/document~Document#event:layoutChanged} event every time when the new image\n * has been loaded.\n *\n * **Note:** This event is not fired for images that has been added to the document and rendered as `complete` (already loaded).\n *\n * @extends module:engine/view/observer/observer~Observer\n */\nexport default class ImageLoadObserver extends Observer {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\t/**\n\t\t * List of img DOM elements that are observed by this observer.\n\t\t *\n\t\t * @private\n\t\t * @type {Set.<HTMLElement>}\n\t\t */\n\t\tthis._observedElements = new Set();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tobserve( domRoot, name ) {\n\t\tconst viewRoot = this.document.getRoot( name );\n\n\t\t// When there is a change in one of the view element\n\t\t// we need to check if there are any new `<img/>` elements to observe.\n\t\tviewRoot.on( 'change:children', ( evt, node ) => {\n\t\t\t// Wait for the render to be sure that `<img/>` elements are rendered in the DOM root.\n\t\t\tthis.view.once( 'render', () => this._updateObservedElements( domRoot, node ) );\n\t\t} );\n\t}\n\n\t/**\n\t * Updates the list of observed `<img/>` elements.\n\t *\n\t * @private\n\t * @param {HTMLElement} domRoot DOM root element.\n\t * @param {module:engine/view/element~Element} viewNode View element where children have changed.\n\t */\n\t_updateObservedElements( domRoot, viewNode ) {\n\t\tif ( !viewNode.is( 'element' ) || viewNode.is( 'attributeElement' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst domNode = this.view.domConverter.mapViewToDom( viewNode );\n\n\t\t// If there is no `domNode` it means that it was removed from the DOM in the meanwhile.\n\t\tif ( !domNode ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( const domElement of domNode.querySelectorAll( 'img' ) ) {\n\t\t\tif ( !this._observedElements.has( domElement ) ) {\n\t\t\t\tthis.listenTo( domElement, 'load', ( evt, domEvt ) => this._fireEvents( domEvt ) );\n\t\t\t\tthis._observedElements.add( domElement );\n\t\t\t}\n\t\t}\n\n\t\t// Clean up the list of observed elements from elements that has been removed from the root.\n\t\tfor ( const domElement of this._observedElements ) {\n\t\t\tif ( !domRoot.contains( domElement ) ) {\n\t\t\t\tthis.stopListening( domElement );\n\t\t\t\tthis._observedElements.delete( domElement );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Fires {@link module:engine/view/document~Document#event:layoutChanged} and\n\t * {@link module:engine/view/document~Document#event:imageLoaded}\n\t * if observer {@link #isEnabled is enabled}.\n\t *\n\t * @protected\n\t * @param {Event} domEvent The DOM event.\n\t */\n\t_fireEvents( domEvent ) {\n\t\tif ( this.isEnabled ) {\n\t\t\tthis.document.fire( 'layoutChanged' );\n\t\t\tthis.document.fire( 'imageLoaded', domEvent );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tthis._observedElements.clear();\n\t\tsuper.destroy();\n\t}\n}\n\n/**\n * Fired when an <img/> DOM element has been loaded in the DOM root.\n *\n * Introduced by {@link module:image/image/imageloadobserver~ImageLoadObserver}.\n *\n * @see module:image/image/imageloadobserver~ImageLoadObserver\n * @event module:engine/view/document~Document#event:imageLoaded\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 image/image/converters\n */\n\nimport first from '@ckeditor/ckeditor5-utils/src/first';\n\n/**\n * Returns a function that converts the image view representation:\n *\n *\t\t<figure class=\"image\"><img src=\"...\" alt=\"...\"></img></figure>\n *\n * to the model representation:\n *\n *\t\t<image src=\"...\" alt=\"...\"></image>\n *\n * The entire content of the `<figure>` element except the first `<img>` is being converted as children\n * of the `<image>` model element.\n *\n * @returns {Function}\n */\nexport function viewFigureToModel() {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'element:figure', converter );\n\t};\n\n\tfunction converter( evt, data, conversionApi ) {\n\t\t// Do not convert if this is not an \"image figure\".\n\t\tif ( !conversionApi.consumable.test( data.viewItem, { name: true, classes: 'image' } ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Find an image element inside the figure element.\n\t\tconst viewImage = Array.from( data.viewItem.getChildren() ).find( viewChild => viewChild.is( 'img' ) );\n\n\t\t// Do not convert if image element is absent, is missing src attribute or was already converted.\n\t\tif ( !viewImage || !viewImage.hasAttribute( 'src' ) || !conversionApi.consumable.test( viewImage, { name: true } ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Convert view image to model image.\n\t\tconst conversionResult = conversionApi.convertItem( viewImage, data.modelCursor );\n\n\t\t// Get image element from conversion result.\n\t\tconst modelImage = first( conversionResult.modelRange.getItems() );\n\n\t\t// When image wasn't successfully converted then finish conversion.\n\t\tif ( !modelImage ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Convert rest of the figure element's children as an image children.\n\t\tconversionApi.convertChildren( data.viewItem, conversionApi.writer.createPositionAt( modelImage, 0 ) );\n\n\t\t// Set image range as conversion result.\n\t\tdata.modelRange = conversionResult.modelRange;\n\n\t\t// Continue conversion where image conversion ends.\n\t\tdata.modelCursor = conversionResult.modelCursor;\n\t}\n}\n\n/**\n * Converter used to convert the `srcset` model image attribute to the `srcset`, `sizes` and `width` attributes in the view.\n *\n * @returns {Function}\n */\nexport function srcsetAttributeConverter() {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'attribute:srcset:image', converter );\n\t};\n\n\tfunction converter( evt, data, conversionApi ) {\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst writer = conversionApi.writer;\n\t\tconst figure = conversionApi.mapper.toViewElement( data.item );\n\t\tconst img = figure.getChild( 0 );\n\n\t\tif ( data.attributeNewValue === null ) {\n\t\t\tconst srcset = data.attributeOldValue;\n\n\t\t\tif ( srcset.data ) {\n\t\t\t\twriter.removeAttribute( 'srcset', img );\n\t\t\t\twriter.removeAttribute( 'sizes', img );\n\n\t\t\t\tif ( srcset.width ) {\n\t\t\t\t\twriter.removeAttribute( 'width', img );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst srcset = data.attributeNewValue;\n\n\t\t\tif ( srcset.data ) {\n\t\t\t\twriter.setAttribute( 'srcset', srcset.data, img );\n\t\t\t\t// Always outputting `100vw`. See https://github.com/ckeditor/ckeditor5-image/issues/2.\n\t\t\t\twriter.setAttribute( 'sizes', '100vw', img );\n\n\t\t\t\tif ( srcset.width ) {\n\t\t\t\t\twriter.setAttribute( 'width', srcset.width, img );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport function modelToViewAttributeConverter( attributeKey ) {\n\treturn dispatcher => {\n\t\tdispatcher.on( `attribute:${ attributeKey }:image`, converter );\n\t};\n\n\tfunction converter( evt, data, conversionApi ) {\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst figure = conversionApi.mapper.toViewElement( data.item );\n\t\tconst img = figure.getChild( 0 );\n\n\t\tif ( data.attributeNewValue !== null ) {\n\t\t\tviewWriter.setAttribute( data.attributeKey, data.attributeNewValue, img );\n\t\t} else {\n\t\t\tviewWriter.removeAttribute( data.attributeKey, img );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { insertImage, isImageAllowed } from './utils';\n\n/**\n * @module image/image/imageinsertcommand\n */\n\n/**\n * Insert image command.\n *\n * The command is registered by the {@link module:image/image/imageediting~ImageEditing} plugin as `'imageInsert'`.\n *\n * In order to insert an image at the current selection position\n * (according to the {@link module:widget/utils~findOptimalInsertionPosition} algorithm),\n * execute the command and specify the image source:\n *\n *\t\teditor.execute( 'imageInsert', { source: 'http://url.to.the/image' } );\n *\n * It is also possible to insert multiple images at once:\n *\n *\t\teditor.execute( 'imageInsert', {\n *\t\t\tsource: [\n *\t\t\t\t'path/to/image.jpg',\n *\t\t\t\t'path/to/other-image.jpg'\n *\t\t\t]\n *\t\t} );\n *\n * @extends module:core/command~Command\n */\nexport default class ImageInsertCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.isEnabled = isImageAllowed( this.editor.model );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @fires execute\n\t * @param {Object} options Options for the executed command.\n\t * @param {String|Array.<String>} options.source The image source or an array of image sources to insert.\n\t */\n\texecute( options ) {\n\t\tconst model = this.editor.model;\n\n\t\tmodel.change( writer => {\n\t\t\tconst sources = Array.isArray( options.source ) ? options.source : [ options.source ];\n\n\t\t\tfor ( const src of sources ) {\n\t\t\t\tinsertImage( writer, model, { src } );\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module image/image/imageediting\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ImageLoadObserver from './imageloadobserver';\nimport {\n viewFigureToModel,\n modelToViewAttributeConverter,\n srcsetAttributeConverter\n} from './converters';\nimport { toImageWidget } from './utils';\nimport ImageInsertCommand from './imageinsertcommand';\n/**\n * The image engine plugin.\n *\n * It registers:\n *\n * * `<image>` as a block element in the document schema, and allows `alt`, `src` and `srcset` attributes.\n * * converters for editing and data pipelines.\n * * `'imageInsert'` command.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageEditing extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'ImageEditing';\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const schema = editor.model.schema;\n const t = editor.t;\n const conversion = editor.conversion;\n // See https://github.com/ckeditor/ckeditor5-image/issues/142.\n editor.editing.view.addObserver(ImageLoadObserver);\n // Configure schema.\n schema.register('image', {\n isObject: true,\n isBlock: true,\n allowWhere: '$block',\n allowAttributes: [\n 'alt',\n 'src',\n 'srcset'\n ]\n });\n conversion.for('dataDowncast').elementToElement({\n model: 'image',\n view: (modelElement, viewWriter) => createImageViewElement(viewWriter)\n });\n conversion.for('editingDowncast').elementToElement({\n model: 'image',\n view: (modelElement, viewWriter) => toImageWidget(createImageViewElement(viewWriter), viewWriter, t('ao'))\n });\n conversion.for('downcast').add(modelToViewAttributeConverter('src')).add(modelToViewAttributeConverter('alt')).add(srcsetAttributeConverter());\n conversion.for('upcast').elementToElement({\n view: {\n name: 'img',\n attributes: { src: true }\n },\n model: (viewImage, modelWriter) => modelWriter.createElement('image', { src: viewImage.getAttribute('src') })\n }).attributeToAttribute({\n view: {\n name: 'img',\n key: 'alt'\n },\n model: 'alt'\n }).attributeToAttribute({\n view: {\n name: 'img',\n key: 'srcset'\n },\n model: {\n key: 'srcset',\n value: viewImage => {\n const value = { data: viewImage.getAttribute('srcset') };\n if (viewImage.hasAttribute('width')) {\n value.width = viewImage.getAttribute('width');\n }\n return value;\n }\n }\n }).add(viewFigureToModel());\n // Register imageUpload command.\n editor.commands.add('imageInsert', new ImageInsertCommand(editor));\n }\n}\n// Creates a view element representing the image.\n//\n//\t\t<figure class=\"image\"><img></img></figure>\n//\n// Note that `alt` and `src` attributes are converted separately, so they are not included.\n//\n// @private\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\n// @returns {module:engine/view/containerelement~ContainerElement}\nexport function createImageViewElement(writer) {\n const emptyElement = writer.createEmptyElement('img');\n const figure = writer.createContainerElement('figure', { class: 'image' });\n writer.insert(writer.createPositionAt(figure, 0), emptyElement);\n return figure;\n}","/**\n * @license Copyright (c) 2003-2019, 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 image/imagetextalternative/imagetextalternativecommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { isImage } from '../image/utils';\n\n/**\n * The image text alternative command. It is used to change the `alt` attribute of `<image>` elements.\n *\n * @extends module:core/command~Command\n */\nexport default class ImageTextAlternativeCommand extends Command {\n\t/**\n\t * The command value: `false` if there is no `alt` attribute, otherwise the value of the `alt` attribute.\n\t *\n\t * @readonly\n\t * @observable\n\t * @member {String|Boolean} #value\n\t */\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst element = this.editor.model.document.selection.getSelectedElement();\n\n\t\tthis.isEnabled = isImage( element );\n\n\t\tif ( isImage( element ) && element.hasAttribute( 'alt' ) ) {\n\t\t\tthis.value = element.getAttribute( 'alt' );\n\t\t} else {\n\t\t\tthis.value = false;\n\t\t}\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @fires execute\n\t * @param {Object} options\n\t * @param {String} options.newValue The new value of the `alt` attribute to set.\n\t */\n\texecute( options ) {\n\t\tconst model = this.editor.model;\n\t\tconst imageElement = model.document.selection.getSelectedElement();\n\n\t\tmodel.change( writer => {\n\t\t\twriter.setAttribute( 'alt', options.newValue, imageElement );\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 image/imagetextalternative/imagetextalternativeediting\n */\n\nimport ImageTextAlternativeCommand from './imagetextalternativecommand';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\n/**\n * The image text alternative editing plugin.\n *\n * Registers the `'imageTextAlternative'` command.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageTextAlternativeEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ImageTextAlternativeEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tthis.editor.commands.add( 'imageTextAlternative', new ImageTextAlternativeCommand( this.editor ) );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/label/labelview\n */\n\nimport View from '../view';\n\nimport '../../theme/components/label/label.css';\n\n/**\n * The label view class.\n *\n * @extends module:ui/view~View\n */\nexport default class LabelView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * The text of the label.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #text\n\t\t */\n\t\tthis.set( 'text' );\n\n\t\t/**\n\t\t * The `for` attribute of the label (i.e. to pair with an `<input>` element).\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #for\n\t\t */\n\t\tthis.set( 'for' );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'label',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-label'\n\t\t\t\t],\n\t\t\t\tfor: bind.to( 'for' )\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttext: bind.to( 'text' )\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/labeledinput/labeledinputview\n */\n\nimport View from '../view';\nimport uid from '@ckeditor/ckeditor5-utils/src/uid';\nimport LabelView from '../label/labelview';\nimport '../../theme/components/labeledinput/labeledinput.css';\n\n/**\n * The labeled input view class.\n *\n * @extends module:ui/view~View\n */\nexport default class LabeledInputView extends View {\n\t/**\n\t * Creates an instance of the labeled input view class.\n\t *\n\t * @param {module:utils/locale~Locale} locale The locale instance.\n\t * @param {Function} InputView Constructor of the input view.\n\t */\n\tconstructor( locale, InputView ) {\n\t\tsuper( locale );\n\n\t\tconst inputUid = `ck-input-${ uid() }`;\n\t\tconst statusUid = `ck-status-${ uid() }`;\n\n\t\t/**\n\t\t * The text of the label.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #label\n\t\t */\n\t\tthis.set( 'label' );\n\n\t\t/**\n\t\t * The value of the input.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #value\n\t\t */\n\t\tthis.set( 'value' );\n\n\t\t/**\n\t\t * Controls whether the component is in read-only mode.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isReadOnly\n\t\t */\n\t\tthis.set( 'isReadOnly', false );\n\n\t\t/**\n\t\t * The validation error text. When set, it will be displayed\n\t\t * next to the {@link #inputView} as a typical validation error message.\n\t\t * Set it to `null` to hide the message.\n\t\t *\n\t\t * **Note:** Setting this property to anything but `null` will automatically\n\t\t * make the {@link module:ui/inputtext/inputtextview~InputTextView#hasError `hasError`}\n\t\t * of the {@link #inputView} `true`.\n\t\t *\n\t\t * **Note:** Typing in the {@link #inputView} which fires the\n\t\t * {@link module:ui/inputtext/inputtextview~InputTextView#event:input `input` event}\n\t\t * resets this property back to `null`, indicating that the input field can be re–validated.\n\t\t *\n\t\t * @observable\n\t\t * @member {String|null} #errorText\n\t\t */\n\t\tthis.set( 'errorText', null );\n\n\t\t/**\n\t\t * The additional information text displayed next to the {@link #inputView} which can\n\t\t * be used to inform the user about the purpose of the input, provide help or hints.\n\t\t *\n\t\t * Set it to `null` to hide the message.\n\t\t *\n\t\t * **Note:** This text will be displayed in the same place as {@link #errorText} but the\n\t\t * latter always takes precedence: if the {@link #errorText} is set, it replaces\n\t\t * {@link #errorText} for as long as the value of the input is invalid.\n\t\t *\n\t\t * @observable\n\t\t * @member {String|null} #infoText\n\t\t */\n\t\tthis.set( 'infoText', null );\n\n\t\t/**\n\t\t * The label view.\n\t\t *\n\t\t * @member {module:ui/label/labelview~LabelView} #labelView\n\t\t */\n\t\tthis.labelView = this._createLabelView( inputUid );\n\n\t\t/**\n\t\t * The input view.\n\t\t *\n\t\t * @member {module:ui/inputtext/inputtextview~InputTextView} #inputView\n\t\t */\n\t\tthis.inputView = this._createInputView( InputView, inputUid, statusUid );\n\n\t\t/**\n\t\t * The status view for the {@link #inputView}. It displays {@link #errorText} and\n\t\t * {@link #infoText}.\n\t\t *\n\t\t * @member {module:ui/view~View} #statusView\n\t\t */\n\t\tthis.statusView = this._createStatusView( statusUid );\n\n\t\t/**\n\t\t * The combined status text made of {@link #errorText} and {@link #infoText}.\n\t\t * Note that when present, {@link #errorText} always takes precedence in the\n\t\t * status.\n\t\t *\n\t\t * @see #errorText\n\t\t * @see #infoText\n\t\t * @see #statusView\n\t\t * @private\n\t\t * @observable\n\t\t * @member {String|null} #_statusText\n\t\t */\n\t\tthis.bind( '_statusText' ).to(\n\t\t\tthis, 'errorText',\n\t\t\tthis, 'infoText',\n\t\t\t( errorText, infoText ) => errorText || infoText\n\t\t);\n\n\t\tconst bind = this.bindTemplate;\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-labeled-input',\n\t\t\t\t\tbind.if( 'isReadOnly', 'ck-disabled' )\n\t\t\t\t]\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\tthis.labelView,\n\t\t\t\tthis.inputView,\n\t\t\t\tthis.statusView\n\t\t\t]\n\t\t} );\n\t}\n\n\t/**\n\t * Creates label view class instance and bind with view.\n\t *\n\t * @private\n\t * @param {String} id Unique id to set as labelView#for attribute.\n\t * @returns {module:ui/label/labelview~LabelView}\n\t */\n\t_createLabelView( id ) {\n\t\tconst labelView = new LabelView( this.locale );\n\n\t\tlabelView.for = id;\n\t\tlabelView.bind( 'text' ).to( this, 'label' );\n\n\t\treturn labelView;\n\t}\n\n\t/**\n\t * Creates input view class instance and bind with view.\n\t *\n\t * @private\n\t * @param {Function} InputView Input view constructor.\n\t * @param {String} inputUid Unique id to set as inputView#id attribute.\n\t * @param {String} statusUid Unique id of the status for the input's `aria-describedby` attribute.\n\t * @returns {module:ui/inputtext/inputtextview~InputTextView}\n\t */\n\t_createInputView( InputView, inputUid, statusUid ) {\n\t\tconst inputView = new InputView( this.locale, statusUid );\n\n\t\tinputView.id = inputUid;\n\t\tinputView.ariaDescribedById = statusUid;\n\t\tinputView.bind( 'value' ).to( this );\n\t\tinputView.bind( 'isReadOnly' ).to( this );\n\t\tinputView.bind( 'hasError' ).to( this, 'errorText', value => !!value );\n\n\t\tinputView.on( 'input', () => {\n\t\t\t// UX: Make the error text disappear and disable the error indicator as the user\n\t\t\t// starts fixing the errors.\n\t\t\tthis.errorText = null;\n\t\t} );\n\n\t\treturn inputView;\n\t}\n\n\t/**\n\t * Creates the status view instance. It displays {@link #errorText} and {@link #infoText}\n\t * next to the {@link #inputView}. See {@link #_statusText}.\n\t *\n\t * @private\n\t * @param {String} statusUid Unique id of the status, shared with the input's `aria-describedby` attribute.\n\t * @returns {module:ui/view~View}\n\t */\n\t_createStatusView( statusUid ) {\n\t\tconst statusView = new View( this.locale );\n\t\tconst bind = this.bindTemplate;\n\n\t\tstatusView.setTemplate( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-labeled-input__status',\n\t\t\t\t\tbind.if( 'errorText', 'ck-labeled-input__status_error' ),\n\t\t\t\t\tbind.if( '_statusText', 'ck-hidden', value => !value )\n\t\t\t\t],\n\t\t\t\tid: statusUid,\n\t\t\t\trole: bind.if( 'errorText', 'alert' )\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttext: bind.to( '_statusText' )\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\n\t\treturn statusView;\n\t}\n\n\t/**\n\t * Moves the focus to the input and selects the value.\n\t */\n\tselect() {\n\t\tthis.inputView.select();\n\t}\n\n\t/**\n\t * Focuses the input.\n\t */\n\tfocus() {\n\t\tthis.inputView.focus();\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/inputtext/inputtextview\n */\n\nimport View from '../view';\nimport '../../theme/components/inputtext/inputtext.css';\n\n/**\n * The text input view class.\n *\n * @extends module:ui/view~View\n */\nexport default class InputTextView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * The value of the input.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #value\n\t\t */\n\t\tthis.set( 'value' );\n\n\t\t/**\n\t\t * The `id` attribute of the input (i.e. to pair with a `<label>` element).\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #id\n\t\t */\n\t\tthis.set( 'id' );\n\n\t\t/**\n\t\t * The `placeholder` attribute of the input.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #placeholder\n\t\t */\n\t\tthis.set( 'placeholder' );\n\n\t\t/**\n\t\t * Controls whether the input view is in read-only mode.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isReadOnly\n\t\t */\n\t\tthis.set( 'isReadOnly', false );\n\n\t\t/**\n\t\t * Set to `true` when the field has some error. Usually controlled via\n\t\t * {@link module:ui/labeledinput/labeledinputview~LabeledInputView#errorText}.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #hasError\n\t\t */\n\t\tthis.set( 'hasError', false );\n\n\t\t/**\n\t\t * The `id` of the element describing this field, e.g. when it has\n\t\t * some error, it helps screen readers read the error text.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #ariaDescribedById\n\t\t */\n\t\tthis.set( 'ariaDescribedById' );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'input',\n\t\t\tattributes: {\n\t\t\t\ttype: 'text',\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-input',\n\t\t\t\t\t'ck-input-text',\n\t\t\t\t\tbind.if( 'hasError', 'ck-error' )\n\t\t\t\t],\n\t\t\t\tid: bind.to( 'id' ),\n\t\t\t\tplaceholder: bind.to( 'placeholder' ),\n\t\t\t\treadonly: bind.to( 'isReadOnly' ),\n\t\t\t\t'aria-invalid': bind.if( 'hasError', true ),\n\t\t\t\t'aria-describedby': bind.to( 'ariaDescribedById' )\n\t\t\t},\n\t\t\ton: {\n\t\t\t\tinput: bind.to( 'input' )\n\t\t\t}\n\t\t} );\n\n\t\t/**\n\t\t * Fired when the user types in the input. Corresponds to the native\n\t\t * DOM `input` event.\n\t\t *\n\t\t * @event input\n\t\t */\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tconst setValue = value => {\n\t\t\tthis.element.value = ( !value && value !== 0 ) ? '' : value;\n\t\t};\n\n\t\tsetValue( this.value );\n\n\t\t// Bind `this.value` to the DOM element's value.\n\t\t// We cannot use `value` DOM attribute because removing it on Edge does not clear the DOM element's value property.\n\t\tthis.on( 'change:value', ( evt, name, value ) => {\n\t\t\tsetValue( value );\n\t\t} );\n\t}\n\n\t/**\n\t * Moves the focus to the input and selects the value.\n\t */\n\tselect() {\n\t\tthis.element.select();\n\t}\n\n\t/**\n\t * Focuses the input.\n\t */\n\tfocus() {\n\t\tthis.element.focus();\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 ui/bindings/submithandler\n */\n\n/**\n * A handler useful for {@link module:ui/view~View views} working as HTML forms. It intercepts a native DOM\n * `submit` event, prevents the default web browser behavior (navigation and page reload) and\n * fires the `submit` event on a view instead. Such a custom event can be then used by any\n * {@link module:utils/dom/emittermixin~Emitter emitter}, e.g. to serialize the form data.\n *\n *\t\timport submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler';\n *\n *\t\t// ...\n *\n *\t\tclass AnyFormView extends View {\n *\t\t\tconstructor() {\n *\t\t\t\tsuper();\n *\n *\t\t\t\t// ...\n *\n *\t\t\t\tsubmitHandler( {\n *\t\t\t\t\tview: this\n *\t\t\t\t} );\n *\t\t\t}\n *\t\t}\n *\n *\t\t// ...\n *\n *\t\tconst view = new AnyFormView();\n *\n *\t\t// A sample listener attached by an emitter working with the view.\n *\t\tthis.listenTo( view, 'submit', () => {\n *\t\t\tsaveTheFormData();\n *\t\t\thideTheForm();\n *\t\t} );\n *\n * @param {Object} [options] Configuration options.\n * @param {module:ui/view~View} options.view The view which DOM `submit` events should be handled.\n */\nexport default function submitHandler( { view } ) {\n\tview.listenTo( view.element, 'submit', ( evt, domEvt ) => {\n\t\tdomEvt.preventDefault();\n\t\tview.fire( 'submit' );\n\t}, { useCapture: true } );\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M6.972 16.615a.997.997 0 0 1-.744-.292l-4.596-4.596a1 1 0 1 1 1.414-1.414l3.926 3.926 9.937-9.937a1 1 0 0 1 1.414 1.415L7.717 16.323a.997.997 0 0 1-.745.292z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M11.591 10.177l4.243 4.242a1 1 0 0 1-1.415 1.415l-4.242-4.243-4.243 4.243a1 1 0 0 1-1.414-1.415l4.243-4.242L4.52 5.934A1 1 0 0 1 5.934 4.52l4.243 4.243 4.242-4.243a1 1 0 1 1 1.415 1.414l-4.243 4.243z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module image/imagetextalternative/ui/textalternativeformview\n */\nimport View from '@ckeditor/ckeditor5-ui/src/view';\nimport ViewCollection from '@ckeditor/ckeditor5-ui/src/viewcollection';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport LabeledInputView from '@ckeditor/ckeditor5-ui/src/labeledinput/labeledinputview';\nimport InputTextView from '@ckeditor/ckeditor5-ui/src/inputtext/inputtextview';\nimport submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler';\nimport KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\nimport FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';\nimport checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg';\nimport cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg';\nimport '../../../theme/textalternativeform.css';\n/**\n * The TextAlternativeFormView class.\n *\n * @extends module:ui/view~View\n */\nexport default class TextAlternativeFormView extends View {\n /**\n\t * @inheritDoc\n\t */\n constructor(locale) {\n super(locale);\n const t = this.locale.t;\n /**\n\t\t * Tracks information about the DOM focus in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n this.focusTracker = new FocusTracker();\n /**\n\t\t * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler}\n\t\t */\n this.keystrokes = new KeystrokeHandler();\n /**\n\t\t * A textarea with a label.\n\t\t *\n\t\t * @member {module:ui/labeledinput/labeledinputview~LabeledInputView} #labeledTextarea\n\t\t */\n this.labeledInput = this._createLabeledInputView();\n /**\n\t\t * A button used to submit the form.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView} #saveButtonView\n\t\t */\n this.saveButtonView = this._createButton(t('av'), checkIcon, 'ck-button-save');\n this.saveButtonView.type = 'submit';\n /**\n\t\t * A button used to cancel the form.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView} #cancelButtonView\n\t\t */\n this.cancelButtonView = this._createButton(t('aw'), cancelIcon, 'ck-button-cancel', 'cancel');\n /**\n\t\t * A collection of views which can be focused in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this._focusables = new ViewCollection();\n /**\n\t\t * Helps cycling over {@link #_focusables} in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/focuscycler~FocusCycler}\n\t\t */\n this._focusCycler = new FocusCycler({\n focusables: this._focusables,\n focusTracker: this.focusTracker,\n keystrokeHandler: this.keystrokes,\n actions: {\n // Navigate form fields backwards using the Shift + Tab keystroke.\n focusPrevious: 'shift + tab',\n // Navigate form fields forwards using the Tab key.\n focusNext: 'tab'\n }\n });\n this.setTemplate({\n tag: 'form',\n attributes: {\n class: [\n 'ck',\n 'ck-text-alternative-form'\n ],\n // https://github.com/ckeditor/ckeditor5-image/issues/40\n tabindex: '-1'\n },\n children: [\n this.labeledInput,\n this.saveButtonView,\n this.cancelButtonView\n ]\n });\n }\n /**\n\t * @inheritDoc\n\t */\n render() {\n super.render();\n this.keystrokes.listenTo(this.element);\n submitHandler({ view: this });\n [\n this.labeledInput,\n this.saveButtonView,\n this.cancelButtonView\n ].forEach(v => {\n // Register the view as focusable.\n this._focusables.add(v);\n // Register the view in the focus tracker.\n this.focusTracker.add(v.element);\n });\n }\n /**\n\t * Creates the button view.\n\t *\n\t * @private\n\t * @param {String} label The button label\n\t * @param {String} icon The button's icon.\n\t * @param {String} className The additional button CSS class name.\n\t * @param {String} [eventName] The event name that the ButtonView#execute event will be delegated to.\n\t * @returns {module:ui/button/buttonview~ButtonView} The button view instance.\n\t */\n _createButton(label, icon, className, eventName) {\n const button = new ButtonView(this.locale);\n button.set({\n label,\n icon,\n tooltip: true\n });\n button.extendTemplate({ attributes: { class: className } });\n if (eventName) {\n button.delegate('execute').to(this, eventName);\n }\n return button;\n }\n /**\n\t * Creates an input with a label.\n\t *\n\t * @private\n\t * @returns {module:ui/labeledinput/labeledinputview~LabeledInputView}\n\t */\n _createLabeledInputView() {\n const t = this.locale.t;\n const labeledInput = new LabeledInputView(this.locale, InputTextView);\n labeledInput.label = t('ax');\n labeledInput.inputView.placeholder = t('ax');\n return labeledInput;\n }\n}","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M5.085 6.22L2.943 4.078a.75.75 0 1 1 1.06-1.06l2.592 2.59A11.094 11.094 0 0 1 10 5.068c4.738 0 8.578 3.101 8.578 5.083 0 1.197-1.401 2.803-3.555 3.887l1.714 1.713a.75.75 0 0 1-.09 1.138.488.488 0 0 1-.15.084.75.75 0 0 1-.821-.16L6.17 7.304c-.258.11-.51.233-.757.365l6.239 6.24-.006.005.78.78c-.388.094-.78.166-1.174.215l-1.11-1.11h.011L4.55 8.197a7.2 7.2 0 0 0-.665.514l-.112.098 4.897 4.897-.005.006 1.276 1.276a10.164 10.164 0 0 1-1.477-.117l-.479-.479-.009.009-4.863-4.863-.022.031a2.563 2.563 0 0 0-.124.2c-.043.077-.08.158-.108.241a.534.534 0 0 0-.028.133.29.29 0 0 0 .008.072.927.927 0 0 0 .082.226c.067.133.145.26.234.379l3.242 3.365.025.01.59.623c-3.265-.918-5.59-3.155-5.59-4.668 0-1.194 1.448-2.838 3.663-3.93zm7.07.531a4.632 4.632 0 0 1 1.108 5.992l.345.344.046-.018a9.313 9.313 0 0 0 2-1.112c.256-.187.5-.392.727-.613.137-.134.27-.277.392-.431.072-.091.141-.185.203-.286.057-.093.107-.19.148-.292a.72.72 0 0 0 .036-.12.29.29 0 0 0 .008-.072.492.492 0 0 0-.028-.133.999.999 0 0 0-.036-.096 2.165 2.165 0 0 0-.071-.145 2.917 2.917 0 0 0-.125-.2 3.592 3.592 0 0 0-.263-.335 5.444 5.444 0 0 0-.53-.523 7.955 7.955 0 0 0-1.054-.768 9.766 9.766 0 0 0-1.879-.891c-.337-.118-.68-.219-1.027-.301zm-2.85.21l-.069.002a.508.508 0 0 0-.254.097.496.496 0 0 0-.104.679.498.498 0 0 0 .326.199l.045.005c.091.003.181.003.272.012a2.45 2.45 0 0 1 2.017 1.513c.024.061.043.125.069.185a.494.494 0 0 0 .45.287h.008a.496.496 0 0 0 .35-.158.482.482 0 0 0 .13-.335.638.638 0 0 0-.048-.219 3.379 3.379 0 0 0-.36-.723 3.438 3.438 0 0 0-2.791-1.543l-.028-.001h-.013z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, 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 image/image/ui/utils\n */\n\nimport BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';\nimport { getSelectedImageWidget } from '../utils';\n\n/**\n * A helper utility that positions the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} instance\n * with respect to the image in the editor content, if one is selected.\n *\n * @param {module:core/editor/editor~Editor} editor The editor instance.\n */\nexport function repositionContextualBalloon( editor ) {\n\tconst balloon = editor.plugins.get( 'ContextualBalloon' );\n\n\tif ( getSelectedImageWidget( editor.editing.view.document.selection ) ) {\n\t\tconst position = getBalloonPositionData( editor );\n\n\t\tballoon.updatePosition( position );\n\t}\n}\n\n/**\n * Returns the positioning options that control the geometry of the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} with respect\n * to the selected element in the editor content.\n *\n * @param {module:core/editor/editor~Editor} editor The editor instance.\n * @returns {module:utils/dom/position~Options}\n */\nexport function getBalloonPositionData( editor ) {\n\tconst editingView = editor.editing.view;\n\tconst defaultPositions = BalloonPanelView.defaultPositions;\n\n\treturn {\n\t\ttarget: editingView.domConverter.viewToDom( editingView.document.selection.getSelectedElement() ),\n\t\tpositions: [\n\t\t\tdefaultPositions.northArrowSouth,\n\t\t\tdefaultPositions.northArrowSouthWest,\n\t\t\tdefaultPositions.northArrowSouthEast,\n\t\t\tdefaultPositions.southArrowNorth,\n\t\t\tdefaultPositions.southArrowNorthWest,\n\t\t\tdefaultPositions.southArrowNorthEast\n\t\t]\n\t};\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module image/imagetextalternative/imagetextalternativeui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler';\nimport TextAlternativeFormView from './ui/textalternativeformview';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\nimport textAlternativeIcon from '@ckeditor/ckeditor5-core/theme/icons/low-vision.svg';\nimport {\n repositionContextualBalloon,\n getBalloonPositionData\n} from '../image/ui/utils';\nimport { getSelectedImageWidget } from '../image/utils';\n/**\n * The image text alternative UI plugin.\n *\n * The plugin uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageTextAlternativeUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get requires() {\n return [ContextualBalloon];\n }\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'ImageTextAlternativeUI';\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n this._createButton();\n this._createForm();\n }\n /**\n\t * @inheritDoc\n\t */\n destroy() {\n super.destroy();\n // Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).\n this._form.destroy();\n }\n /**\n\t * Creates a button showing the balloon panel for changing the image text alternative and\n\t * registers it in the editor {@link module:ui/componentfactory~ComponentFactory ComponentFactory}.\n\t *\n\t * @private\n\t */\n _createButton() {\n const editor = this.editor;\n const t = editor.t;\n editor.ui.componentFactory.add('imageTextAlternative', locale => {\n const command = editor.commands.get('imageTextAlternative');\n const view = new ButtonView(locale);\n view.set({\n label: t('au'),\n icon: textAlternativeIcon,\n tooltip: true\n });\n view.bind('isEnabled').to(command, 'isEnabled');\n this.listenTo(view, 'execute', () => this._showForm());\n return view;\n });\n }\n /**\n\t * Creates the {@link module:image/imagetextalternative/ui/textalternativeformview~TextAlternativeFormView}\n\t * form.\n\t *\n\t * @private\n\t */\n _createForm() {\n const editor = this.editor;\n const view = editor.editing.view;\n const viewDocument = view.document;\n /**\n\t\t * The contextual balloon plugin instance.\n\t\t *\n\t\t * @private\n\t\t * @member {module:ui/panel/balloon/contextualballoon~ContextualBalloon}\n\t\t */\n this._balloon = this.editor.plugins.get('ContextualBalloon');\n /**\n\t\t * A form containing a textarea and buttons, used to change the `alt` text value.\n\t\t *\n\t\t * @member {module:image/imagetextalternative/ui/textalternativeformview~TextAlternativeFormView}\n\t\t */\n this._form = new TextAlternativeFormView(editor.locale);\n // Render the form so its #element is available for clickOutsideHandler.\n this._form.render();\n this.listenTo(this._form, 'submit', () => {\n editor.execute('imageTextAlternative', { newValue: this._form.labeledInput.inputView.element.value });\n this._hideForm(true);\n });\n this.listenTo(this._form, 'cancel', () => {\n this._hideForm(true);\n });\n // Close the form on Esc key press.\n this._form.keystrokes.set('Esc', (data, cancel) => {\n this._hideForm(true);\n cancel();\n });\n // Reposition the balloon or hide the form if an image widget is no longer selected.\n this.listenTo(editor.ui, 'update', () => {\n if (!getSelectedImageWidget(viewDocument.selection)) {\n this._hideForm(true);\n } else if (this._isVisible) {\n repositionContextualBalloon(editor);\n }\n });\n // Close on click outside of balloon panel element.\n clickOutsideHandler({\n emitter: this._form,\n activator: () => this._isVisible,\n contextElements: [this._balloon.view.element],\n callback: () => this._hideForm()\n });\n }\n /**\n\t * Shows the {@link #_form} in the {@link #_balloon}.\n\t *\n\t * @private\n\t */\n _showForm() {\n if (this._isVisible) {\n return;\n }\n const editor = this.editor;\n const command = editor.commands.get('imageTextAlternative');\n const labeledInput = this._form.labeledInput;\n if (!this._isInBalloon) {\n this._balloon.add({\n view: this._form,\n position: getBalloonPositionData(editor)\n });\n }\n // Make sure that each time the panel shows up, the field remains in sync with the value of\n // the command. If the user typed in the input, then canceled the balloon (`labeledInput#value`\n // stays unaltered) and re-opened it without changing the value of the command, they would see the\n // old value instead of the actual value of the command.\n // https://github.com/ckeditor/ckeditor5-image/issues/114\n labeledInput.value = labeledInput.inputView.element.value = command.value || '';\n this._form.labeledInput.select();\n }\n /**\n\t * Removes the {@link #_form} from the {@link #_balloon}.\n\t *\n\t * @param {Boolean} [focusEditable=false] Controls whether the editing view is focused afterwards.\n\t * @private\n\t */\n _hideForm(focusEditable) {\n if (!this._isInBalloon) {\n return;\n }\n // Blur the input element before removing it from DOM to prevent issues in some browsers.\n // See https://github.com/ckeditor/ckeditor5/issues/1501.\n if (this._form.focusTracker.isFocused) {\n this._form.saveButtonView.focus();\n }\n this._balloon.remove(this._form);\n if (focusEditable) {\n this.editor.editing.view.focus();\n }\n }\n /**\n\t * Returns `true` when the {@link #_form} is the visible view in the {@link #_balloon}.\n\t *\n\t * @private\n\t * @type {Boolean}\n\t */\n get _isVisible() {\n return this._balloon.visibleView === this._form;\n }\n /**\n\t * Returns `true` when the {@link #_form} is in the {@link #_balloon}.\n\t *\n\t * @private\n\t * @type {Boolean}\n\t */\n get _isInBalloon() {\n return this._balloon.hasView(this._form);\n }\n}","/**\n * @license Copyright (c) 2003-2019, 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 image/imagetextalternative\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ImageTextAlternativeEditing from './imagetextalternative/imagetextalternativeediting';\nimport ImageTextAlternativeUI from './imagetextalternative/imagetextalternativeui';\n\n/**\n * The image text alternative plugin.\n *\n * For a detailed overview, check the {@glink features/image#image-styles image styles} documentation.\n *\n * This is a \"glue\" plugin which loads the\n * {@link module:image/imagetextalternative/imagetextalternativeediting~ImageTextAlternativeEditing}\n * and {@link module:image/imagetextalternative/imagetextalternativeui~ImageTextAlternativeUI} plugins.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageTextAlternative extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ImageTextAlternativeEditing, ImageTextAlternativeUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ImageTextAlternative';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 image/imagecaption/utils\n */\n\nimport { enablePlaceholder } from '@ckeditor/ckeditor5-engine/src/view/placeholder';\nimport { toWidgetEditable } from '@ckeditor/ckeditor5-widget/src/utils';\n\n/**\n * Returns a function that creates a caption editable element for the given {@link module:engine/view/document~Document}.\n *\n * @param {module:engine/view/view~View} view\n * @param {String} placeholderText The text to be displayed when the caption is empty.\n * @returns {Function}\n */\nexport function captionElementCreator( view, placeholderText ) {\n\treturn writer => {\n\t\tconst editable = writer.createEditableElement( 'figcaption' );\n\t\twriter.setCustomProperty( 'imageCaption', true, editable );\n\n\t\tenablePlaceholder( {\n\t\t\tview,\n\t\t\telement: editable,\n\t\t\ttext: placeholderText\n\t\t} );\n\n\t\treturn toWidgetEditable( editable, writer );\n\t};\n}\n\n/**\n * Returns `true` if a given view element is the image caption editable.\n *\n * @param {module:engine/view/element~Element} viewElement\n * @returns {Boolean}\n */\nexport function isCaption( viewElement ) {\n\treturn !!viewElement.getCustomProperty( 'imageCaption' );\n}\n\n/**\n * Returns the caption model element from a given image element. Returns `null` if no caption is found.\n *\n * @param {module:engine/model/element~Element} imageModelElement\n * @returns {module:engine/model/element~Element|null}\n */\nexport function getCaptionFromImage( imageModelElement ) {\n\tfor ( const node of imageModelElement.getChildren() ) {\n\t\tif ( !!node && node.is( 'caption' ) ) {\n\t\t\treturn node;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * {@link module:engine/view/matcher~Matcher} pattern. Checks if a given element is a `<figcaption>` element that is placed\n * inside the image `<figure>` element.\n *\n * @param {module:engine/view/element~Element} element\n * @returns {Object|null} Returns the object accepted by {@link module:engine/view/matcher~Matcher} or `null` if the element\n * cannot be matched.\n */\nexport function matchImageCaption( element ) {\n\tconst parent = element.parent;\n\n\t// Convert only captions for images.\n\tif ( element.name == 'figcaption' && parent && parent.name == 'figure' && parent.hasClass( 'image' ) ) {\n\t\treturn { name: true };\n\t}\n\n\treturn null;\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module image/imagecaption/imagecaptionediting\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport { isImage } from '../image/utils';\nimport {\n captionElementCreator,\n getCaptionFromImage,\n matchImageCaption\n} from './utils';\n/**\n * The image caption engine plugin.\n *\n * It registers proper converters. It takes care of adding a caption element if the image without it is inserted\n * to the model document.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageCaptionEditing extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'ImageCaptionEditing';\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const view = editor.editing.view;\n const schema = editor.model.schema;\n const data = editor.data;\n const editing = editor.editing;\n const t = editor.t;\n /**\n\t\t * The last selected caption editable.\n\t\t * It is used for hiding the editable when it is empty and the image widget is no longer selected.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/view/editableelement~EditableElement} #_lastSelectedCaption\n\t\t */\n // Schema configuration.\n schema.register('caption', {\n allowIn: 'image',\n allowContentOf: '$block',\n isLimit: true\n });\n // Add caption element to each image inserted without it.\n editor.model.document.registerPostFixer(writer => this._insertMissingModelCaptionElement(writer));\n // View to model converter for the data pipeline.\n editor.conversion.for('upcast').elementToElement({\n view: matchImageCaption,\n model: 'caption'\n });\n // Model to view converter for the data pipeline.\n const createCaptionForData = writer => writer.createContainerElement('figcaption');\n data.downcastDispatcher.on('insert:caption', captionModelToView(createCaptionForData, false));\n // Model to view converter for the editing pipeline.\n const createCaptionForEditing = captionElementCreator(view, t('ap'));\n editing.downcastDispatcher.on('insert:caption', captionModelToView(createCaptionForEditing));\n // Always show caption in view when something is inserted in model.\n editing.downcastDispatcher.on('insert', this._fixCaptionVisibility(data => data.item), { priority: 'high' });\n // Hide caption when everything is removed from it.\n editing.downcastDispatcher.on('remove', this._fixCaptionVisibility(data => data.position.parent), { priority: 'high' });\n // Update caption visibility on view in post fixer.\n view.document.registerPostFixer(writer => this._updateCaptionVisibility(writer));\n }\n /**\n\t * Updates the view before each rendering, making sure that empty captions (so unnecessary ones) are hidden\n\t * and then visible when the image is selected.\n\t *\n\t * @private\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter\n\t * @returns {Boolean} Returns `true` when the view is updated.\n\t */\n _updateCaptionVisibility(viewWriter) {\n const mapper = this.editor.editing.mapper;\n const lastCaption = this._lastSelectedCaption;\n let viewCaption;\n // If whole image is selected.\n const modelSelection = this.editor.model.document.selection;\n const selectedElement = modelSelection.getSelectedElement();\n if (selectedElement && selectedElement.is('image')) {\n const modelCaption = getCaptionFromImage(selectedElement);\n viewCaption = mapper.toViewElement(modelCaption);\n }\n // If selection is placed inside caption.\n const position = modelSelection.getFirstPosition();\n const modelCaption = getParentCaption(position.parent);\n if (modelCaption) {\n viewCaption = mapper.toViewElement(modelCaption);\n }\n // Is currently any caption selected?\n if (viewCaption) {\n // Was any caption selected before?\n if (lastCaption) {\n // Same caption as before?\n if (lastCaption === viewCaption) {\n return showCaption(viewCaption, viewWriter);\n } else {\n hideCaptionIfEmpty(lastCaption, viewWriter);\n this._lastSelectedCaption = viewCaption;\n return showCaption(viewCaption, viewWriter);\n }\n } else {\n this._lastSelectedCaption = viewCaption;\n return showCaption(viewCaption, viewWriter);\n }\n } else {\n // Was any caption selected before?\n if (lastCaption) {\n const viewModified = hideCaptionIfEmpty(lastCaption, viewWriter);\n this._lastSelectedCaption = null;\n return viewModified;\n } else {\n return false;\n }\n }\n }\n /**\n\t * Returns a converter that fixes caption visibility during the model-to-view conversion.\n\t * Checks if the changed node is placed inside the caption element and fixes its visibility in the view.\n\t *\n\t * @private\n\t * @param {Function} nodeFinder\n\t * @returns {Function}\n\t */\n _fixCaptionVisibility(nodeFinder) {\n return (evt, data, conversionApi) => {\n const node = nodeFinder(data);\n const modelCaption = getParentCaption(node);\n const mapper = this.editor.editing.mapper;\n const viewWriter = conversionApi.writer;\n if (modelCaption) {\n const viewCaption = mapper.toViewElement(modelCaption);\n if (viewCaption) {\n if (modelCaption.childCount) {\n viewWriter.removeClass('ck-hidden', viewCaption);\n } else {\n viewWriter.addClass('ck-hidden', viewCaption);\n }\n }\n }\n };\n }\n /**\n\t * Checks whether the data inserted to the model document have an image element that has no caption element inside it.\n\t * If there is none, it adds it to the image element.\n\t *\n\t * @private\n\t * @param {module:engine/model/writer~Writer} writer The writer to make changes with.\n\t * @returns {Boolean} `true` if any change was applied, `false` otherwise.\n\t */\n _insertMissingModelCaptionElement(writer) {\n const model = this.editor.model;\n const changes = model.document.differ.getChanges();\n const imagesWithoutCaption = [];\n for (const entry of changes) {\n if (entry.type == 'insert' && entry.name != '$text') {\n const item = entry.position.nodeAfter;\n if (item.is('image') && !getCaptionFromImage(item)) {\n imagesWithoutCaption.push(item);\n }\n // Check elements with children for nested images.\n if (!item.is('image') && item.childCount) {\n for (const nestedItem of model.createRangeIn(item).getItems()) {\n if (nestedItem.is('image') && !getCaptionFromImage(nestedItem)) {\n imagesWithoutCaption.push(nestedItem);\n }\n }\n }\n }\n }\n for (const image of imagesWithoutCaption) {\n writer.appendElement('caption', image);\n }\n return !!imagesWithoutCaption.length;\n }\n}\n// Creates a converter that converts image caption model element to view element.\n//\n// @private\n// @param {Function} elementCreator\n// @param {Boolean} [hide=true] When set to `false` view element will not be inserted when it's empty.\n// @returns {Function}\nfunction captionModelToView(elementCreator, hide = true) {\n return (evt, data, conversionApi) => {\n const captionElement = data.item;\n // Return if element shouldn't be present when empty.\n if (!captionElement.childCount && !hide) {\n return;\n }\n if (isImage(captionElement.parent)) {\n if (!conversionApi.consumable.consume(data.item, 'insert')) {\n return;\n }\n const viewImage = conversionApi.mapper.toViewElement(data.range.start.parent);\n const viewCaption = elementCreator(conversionApi.writer);\n const viewWriter = conversionApi.writer;\n // Hide if empty.\n if (!captionElement.childCount) {\n viewWriter.addClass('ck-hidden', viewCaption);\n }\n insertViewCaptionAndBind(viewCaption, data.item, viewImage, conversionApi);\n }\n };\n}\n// Inserts `viewCaption` at the end of `viewImage` and binds it to `modelCaption`.\n//\n// @private\n// @param {module:engine/view/containerelement~ContainerElement} viewCaption\n// @param {module:engine/model/element~Element} modelCaption\n// @param {module:engine/view/containerelement~ContainerElement} viewImage\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction insertViewCaptionAndBind(viewCaption, modelCaption, viewImage, conversionApi) {\n const viewPosition = conversionApi.writer.createPositionAt(viewImage, 'end');\n conversionApi.writer.insert(viewPosition, viewCaption);\n conversionApi.mapper.bindElements(modelCaption, viewCaption);\n}\n// Checks if the provided node or one of its ancestors is a caption element, and returns it.\n//\n// @private\n// @param {module:engine/model/node~Node} node\n// @returns {module:engine/model/element~Element|null}\nfunction getParentCaption(node) {\n const ancestors = node.getAncestors({ includeSelf: true });\n const caption = ancestors.find(ancestor => ancestor.name == 'caption');\n if (caption && caption.parent && caption.parent.name == 'image') {\n return caption;\n }\n return null;\n}\n// Hides a given caption in the view if it is empty.\n//\n// @private\n// @param {module:engine/view/containerelement~ContainerElement} caption\n// @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter\n// @returns {Boolean} Returns `true` if the view was modified.\nfunction hideCaptionIfEmpty(caption, viewWriter) {\n if (!caption.childCount && !caption.hasClass('ck-hidden')) {\n viewWriter.addClass('ck-hidden', caption);\n return true;\n }\n return false;\n}\n// Shows the caption.\n//\n// @private\n// @param {module:engine/view/containerelement~ContainerElement} caption\n// @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter\n// @returns {Boolean} Returns `true` if the view was modified.\nfunction showCaption(caption, viewWriter) {\n if (caption.hasClass('ck-hidden')) {\n viewWriter.removeClass('ck-hidden', caption);\n return true;\n }\n return false;\n}","/**\n * @license Copyright (c) 2003-2019, 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 image/imagestyle/imagestylecommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { isImage } from '../image/utils';\n\n/**\n * The image style command. It is used to apply different image styles.\n *\n * @extends module:core/command~Command\n */\nexport default class ImageStyleCommand extends Command {\n\t/**\n\t * Creates an instance of the image style command. Each command instance is handling one style.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t * @param {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat>} styles The styles that this command supports.\n\t */\n\tconstructor( editor, styles ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The name of the default style, if it is present. If there is no default style, it defaults to `false`.\n\t\t *\n\t\t * @readonly\n\t\t * @type {Boolean|String}\n\t\t */\n\t\tthis.defaultStyle = false;\n\n\t\t/**\n\t\t * A style handled by this command.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat>} #styles\n\t\t */\n\t\tthis.styles = styles.reduce( ( styles, style ) => {\n\t\t\tstyles[ style.name ] = style;\n\n\t\t\tif ( style.isDefault ) {\n\t\t\t\tthis.defaultStyle = style.name;\n\t\t\t}\n\n\t\t\treturn styles;\n\t\t}, {} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst element = this.editor.model.document.selection.getSelectedElement();\n\n\t\tthis.isEnabled = isImage( element );\n\n\t\tif ( !element ) {\n\t\t\tthis.value = false;\n\t\t} else if ( element.hasAttribute( 'imageStyle' ) ) {\n\t\t\tconst attributeValue = element.getAttribute( 'imageStyle' );\n\t\t\tthis.value = this.styles[ attributeValue ] ? attributeValue : false;\n\t\t} else {\n\t\t\tthis.value = this.defaultStyle;\n\t\t}\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t *\t\teditor.execute( 'imageStyle', { value: 'side' } );\n\t *\n\t * @param {Object} options\n\t * @param {String} options.value The name of the style (based on the\n\t * {@link module:image/image~ImageConfig#styles `image.styles`} configuration option).\n\t * @fires execute\n\t */\n\texecute( options ) {\n\t\tconst styleName = options.value;\n\n\t\tconst model = this.editor.model;\n\t\tconst imageElement = model.document.selection.getSelectedElement();\n\n\t\tmodel.change( writer => {\n\t\t\t// Default style means that there is no `imageStyle` attribute in the model.\n\t\t\t// https://github.com/ckeditor/ckeditor5-image/issues/147\n\t\t\tif ( this.styles[ styleName ].isDefault ) {\n\t\t\t\twriter.removeAttribute( 'imageStyle', imageElement );\n\t\t\t} else {\n\t\t\t\twriter.setAttribute( 'imageStyle', styleName, imageElement );\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nimport first from '@ckeditor/ckeditor5-utils/src/first';\n\n/**\n * @module image/imagestyle/converters\n */\n\n/**\n * Returns a converter for the `imageStyle` attribute. It can be used for adding, changing and removing the attribute.\n *\n * @param {Object} styles An object containing available styles. See {@link module:image/imagestyle/imagestyleediting~ImageStyleFormat}\n * for more details.\n * @returns {Function} A model-to-view attribute converter.\n */\nexport function modelToViewStyleAttribute( styles ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if there is class name associated with given value.\n\t\tconst newStyle = getStyleByName( data.attributeNewValue, styles );\n\t\tconst oldStyle = getStyleByName( data.attributeOldValue, styles );\n\n\t\tconst viewElement = conversionApi.mapper.toViewElement( data.item );\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\tif ( oldStyle ) {\n\t\t\tviewWriter.removeClass( oldStyle.className, viewElement );\n\t\t}\n\n\t\tif ( newStyle ) {\n\t\t\tviewWriter.addClass( newStyle.className, viewElement );\n\t\t}\n\t};\n}\n\n/**\n * Returns a view-to-model converter converting image CSS classes to a proper value in the model.\n *\n * @param {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat>} styles The styles for which the converter is created.\n * @returns {Function} A view-to-model converter.\n */\nexport function viewToModelStyleAttribute( styles ) {\n\t// Convert only non–default styles.\n\tconst filteredStyles = styles.filter( style => !style.isDefault );\n\n\treturn ( evt, data, conversionApi ) => {\n\t\tif ( !data.modelRange ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewFigureElement = data.viewItem;\n\t\tconst modelImageElement = first( data.modelRange.getItems() );\n\n\t\t// Check if `imageStyle` attribute is allowed for current element.\n\t\tif ( !conversionApi.schema.checkAttribute( modelImageElement, 'imageStyle' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Convert style one by one.\n\t\tfor ( const style of filteredStyles ) {\n\t\t\t// Try to consume class corresponding with style.\n\t\t\tif ( conversionApi.consumable.consume( viewFigureElement, { classes: style.className } ) ) {\n\t\t\t\t// And convert this style to model attribute.\n\t\t\t\tconversionApi.writer.setAttribute( 'imageStyle', style.name, modelImageElement );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Returns the style with a given `name` from an array of styles.\n//\n// @param {String} name\n// @param {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat> } styles\n// @returns {module:image/imagestyle/imagestyleediting~ImageStyleFormat|undefined}\nfunction getStyleByName( name, styles ) {\n\tfor ( const style of styles ) {\n\t\tif ( style.name === name ) {\n\t\t\treturn style;\n\t\t}\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M2 4.5V3h16v1.5zm2.5 3V12h11V7.5h-11zM4.061 6H15.94c.586 0 1.061.407 1.061.91v5.68c0 .503-.475.91-1.061.91H4.06c-.585 0-1.06-.407-1.06-.91V6.91C3 6.406 3.475 6 4.061 6zM2 16.5V15h16v1.5z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" clip-rule=\\\"evenodd\\\" stroke-linejoin=\\\"round\\\" stroke-miterlimit=\\\"1.414\\\"><path d=\\\"M18 4.5V3H2v1.5h16zm0 3V6h-5.674v1.5H18zm0 3V9h-5.674v1.5H18zm0 3V12h-5.674v1.5H18zm-8.5-6V12h-6V7.5h6zm.818-1.5H2.682C2.305 6 2 6.407 2 6.91v5.68c0 .503.305.91.682.91h7.636c.377 0 .682-.407.682-.91V6.91c0-.503-.305-.91-.682-.91zM18 16.5V15H2v1.5h16z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M2 4.5V3h16v1.5zm4.5 3V12h7V7.5h-7zM5.758 6h8.484c.419 0 .758.407.758.91v5.681c0 .502-.34.909-.758.909H5.758c-.419 0-.758-.407-.758-.91V6.91c0-.503.34-.91.758-.91zM2 16.5V15h16v1.5z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M2 4.5V3h16v1.5zm0 3V6h5.674v1.5zm0 3V9h5.674v1.5zm0 3V12h5.674v1.5zm8.5-6V12h6V7.5h-6zM9.682 6h7.636c.377 0 .682.407.682.91v5.68c0 .503-.305.91-.682.91H9.682c-.377 0-.682-.407-.682-.91V6.91c0-.503.305-.91.682-.91zM2 16.5V15h16v1.5z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, 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 image/imagestyle/utils\n */\n\n/* globals console */\n\nimport fullWidthIcon from '@ckeditor/ckeditor5-core/theme/icons/object-full-width.svg';\nimport leftIcon from '@ckeditor/ckeditor5-core/theme/icons/object-left.svg';\nimport centerIcon from '@ckeditor/ckeditor5-core/theme/icons/object-center.svg';\nimport rightIcon from '@ckeditor/ckeditor5-core/theme/icons/object-right.svg';\nimport { attachLinkToDocumentation } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Default image styles provided by the plugin that can be referred in the\n * {@link module:image/image~ImageConfig#styles} configuration.\n *\n * Among them, 2 default semantic content styles are available:\n *\n * * `full` is a full–width image without any CSS class,\n * * `side` is a side image styled with the `image-style-side` CSS class.\n *\n * There are also 3 styles focused on formatting:\n *\n * * `alignLeft` aligns the image to the left using the `image-style-align-left` class,\n * * `alignCenter` centers the image using the `image-style-align-center` class,\n * * `alignRight` aligns the image to the right using the `image-style-align-right` class,\n *\n * @member {Object.<String,Object>}\n */\nconst defaultStyles = {\n\t// This option is equal to the situation when no style is applied.\n\tfull: {\n\t\tname: 'full',\n\t\ttitle: 'Full size image',\n\t\ticon: fullWidthIcon,\n\t\tisDefault: true\n\t},\n\n\t// This represents a side image.\n\tside: {\n\t\tname: 'side',\n\t\ttitle: 'Side image',\n\t\ticon: rightIcon,\n\t\tclassName: 'image-style-side'\n\t},\n\n\t// This style represents an image aligned to the left.\n\talignLeft: {\n\t\tname: 'alignLeft',\n\t\ttitle: 'Left aligned image',\n\t\ticon: leftIcon,\n\t\tclassName: 'image-style-align-left'\n\t},\n\n\t// This style represents a centered image.\n\talignCenter: {\n\t\tname: 'alignCenter',\n\t\ttitle: 'Centered image',\n\t\ticon: centerIcon,\n\t\tclassName: 'image-style-align-center'\n\t},\n\n\t// This style represents an image aligned to the right.\n\talignRight: {\n\t\tname: 'alignRight',\n\t\ttitle: 'Right aligned image',\n\t\ticon: rightIcon,\n\t\tclassName: 'image-style-align-right'\n\t}\n};\n\n/**\n * Default image style icons provided by the plugin that can be referred in the\n * {@link module:image/image~ImageConfig#styles} configuration.\n *\n * There are 4 icons available: `'full'`, `'left'`, `'center'` and `'right'`.\n *\n * @member {Object.<String, String>}\n */\nconst defaultIcons = {\n\tfull: fullWidthIcon,\n\tleft: leftIcon,\n\tright: rightIcon,\n\tcenter: centerIcon\n};\n\n/**\n * Returns a {@link module:image/image~ImageConfig#styles} array with items normalized in the\n * {@link module:image/imagestyle/imagestyleediting~ImageStyleFormat} format and a complete `icon` markup for each style.\n *\n * @returns {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat>}\n */\nexport function normalizeImageStyles( configuredStyles = [] ) {\n\treturn configuredStyles.map( _normalizeStyle );\n}\n\n// Normalizes an image style provided in the {@link module:image/image~ImageConfig#styles}\n// and returns it in a {@link module:image/imagestyle/imagestyleediting~ImageStyleFormat}.\n//\n// @param {Object} style\n// @returns {@link module:image/imagestyle/imagestyleediting~ImageStyleFormat}\nfunction _normalizeStyle( style ) {\n\t// Just the name of the style has been passed.\n\tif ( typeof style == 'string' ) {\n\t\tconst styleName = style;\n\n\t\t// If it's one of the defaults, just use it.\n\t\tif ( defaultStyles[ styleName ] ) {\n\t\t\t// Clone the style to avoid overriding defaults.\n\t\t\tstyle = Object.assign( {}, defaultStyles[ styleName ] );\n\t\t}\n\t\t// If it's just a name but none of the defaults, warn because probably it's a mistake.\n\t\telse {\n\t\t\tconsole.warn(\n\t\t\t\tattachLinkToDocumentation( 'image-style-not-found: There is no such image style of given name.' ),\n\t\t\t\t{ name: styleName }\n\t\t\t);\n\n\t\t\t// Normalize the style anyway to prevent errors.\n\t\t\tstyle = {\n\t\t\t\tname: styleName\n\t\t\t};\n\t\t}\n\t}\n\t// If an object style has been passed and if the name matches one of the defaults,\n\t// extend it with defaults – the user wants to customize a default style.\n\t// Note: Don't override the user–defined style object, clone it instead.\n\telse if ( defaultStyles[ style.name ] ) {\n\t\tconst defaultStyle = defaultStyles[ style.name ];\n\t\tconst extendedStyle = Object.assign( {}, style );\n\n\t\tfor ( const prop in defaultStyle ) {\n\t\t\tif ( !style.hasOwnProperty( prop ) ) {\n\t\t\t\textendedStyle[ prop ] = defaultStyle[ prop ];\n\t\t\t}\n\t\t}\n\n\t\tstyle = extendedStyle;\n\t}\n\n\t// If an icon is defined as a string and correspond with a name\n\t// in default icons, use the default icon provided by the plugin.\n\tif ( typeof style.icon == 'string' && defaultIcons[ style.icon ] ) {\n\t\tstyle.icon = defaultIcons[ style.icon ];\n\t}\n\n\treturn style;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 image/imagestyle/imagestyleediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ImageStyleCommand from './imagestylecommand';\nimport { viewToModelStyleAttribute, modelToViewStyleAttribute } from './converters';\nimport { normalizeImageStyles } from './utils';\n\n/**\n * The image style engine plugin. It sets the default configuration, creates converters and registers\n * {@link module:image/imagestyle/imagestylecommand~ImageStyleCommand ImageStyleCommand}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageStyleEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ImageStyleEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst schema = editor.model.schema;\n\t\tconst data = editor.data;\n\t\tconst editing = editor.editing;\n\n\t\t// Define default configuration.\n\t\teditor.config.define( 'image.styles', [ 'full', 'side' ] );\n\n\t\t// Get configuration.\n\t\tconst styles = normalizeImageStyles( editor.config.get( 'image.styles' ) );\n\n\t\t// Allow imageStyle attribute in image.\n\t\t// We could call it 'style' but https://github.com/ckeditor/ckeditor5-engine/issues/559.\n\t\tschema.extend( 'image', { allowAttributes: 'imageStyle' } );\n\n\t\t// Converters for imageStyle attribute from model to view.\n\t\tconst modelToViewConverter = modelToViewStyleAttribute( styles );\n\t\tediting.downcastDispatcher.on( 'attribute:imageStyle:image', modelToViewConverter );\n\t\tdata.downcastDispatcher.on( 'attribute:imageStyle:image', modelToViewConverter );\n\n\t\t// Converter for figure element from view to model.\n\t\tdata.upcastDispatcher.on( 'element:figure', viewToModelStyleAttribute( styles ), { priority: 'low' } );\n\n\t\t// Register imageStyle command.\n\t\teditor.commands.add( 'imageStyle', new ImageStyleCommand( editor, styles ) );\n\t}\n}\n\n/**\n * The image style format descriptor.\n *\n *\t\timport fullSizeIcon from 'path/to/icon.svg';\n *\n *\t\tconst imageStyleFormat = {\n *\t\t\tname: 'fullSize',\n *\t\t\ticon: fullSizeIcon,\n *\t\t\ttitle: 'Full size image',\n *\t\t\tclassName: 'image-full-size'\n *\t\t}\n *\n * @typedef {Object} module:image/imagestyle/imagestyleediting~ImageStyleFormat\n *\n * @property {String} name The unique name of the style. It will be used to:\n *\n * * Store the chosen style in the model by setting the `imageStyle` attribute of the `<image>` element.\n * * As a value of the {@link module:image/imagestyle/imagestylecommand~ImageStyleCommand#execute `imageStyle` command},\n * * when registering a button for each of the styles (`'imageStyle:{name}'`) in the\n * {@link module:ui/componentfactory~ComponentFactory UI components factory} (this functionality is provided by the\n * {@link module:image/imagestyle/imagestyleui~ImageStyleUI} plugin).\n *\n * @property {Boolean} [isDefault] When set, the style will be used as the default one.\n * A default style does not apply any CSS class to the view element.\n *\n * @property {String} icon One of the following to be used when creating the style's button:\n *\n * * An SVG icon source (as an XML string).\n * * One of {@link module:image/imagestyle/utils~defaultIcons} to use a default icon provided by the plugin.\n *\n * @property {String} title The style's title.\n *\n * @property {String} className The CSS class used to represent the style in the view.\n */\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module image/imagestyle/imagestyleui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport { normalizeImageStyles } from './utils';\nimport '../../theme/imagestyle.css';\n/**\n * The image style UI plugin.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageStyleUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'ImageStyleUI';\n }\n /**\n\t * Returns the default localized style titles provided by the plugin.\n\t *\n\t * The following localized titles corresponding with\n\t * {@link module:image/imagestyle/utils~defaultStyles} are available:\n\t *\n\t * * `'Full size image'`,\n\t * * `'Side image'`,\n\t * * `'Left aligned image'`,\n\t * * `'Centered image'`,\n\t * * `'Right aligned image'`\n\t *\n\t * @returns {Object.<String,String>}\n\t */\n get localizedDefaultStylesTitles() {\n const t = this.editor.t;\n return {\n 'Full size image': t('ag'),\n 'Side image': t('ah'),\n 'Left aligned image': t('ai'),\n 'Centered image': t('aj'),\n 'Right aligned image': t('ak')\n };\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const configuredStyles = editor.config.get('image.styles');\n const translatedStyles = translateStyles(normalizeImageStyles(configuredStyles), this.localizedDefaultStylesTitles);\n for (const style of translatedStyles) {\n this._createButton(style);\n }\n }\n /**\n\t * Creates a button for each style and stores it in the editor {@link module:ui/componentfactory~ComponentFactory ComponentFactory}.\n\t *\n\t * @private\n\t * @param {module:image/imagestyle/imagestyleediting~ImageStyleFormat} style\n\t */\n _createButton(style) {\n const editor = this.editor;\n const componentName = `imageStyle:${ style.name }`;\n editor.ui.componentFactory.add(componentName, locale => {\n const command = editor.commands.get('imageStyle');\n const view = new ButtonView(locale);\n view.set({\n label: style.title,\n icon: style.icon,\n tooltip: true,\n isToggleable: true\n });\n view.bind('isEnabled').to(command, 'isEnabled');\n view.bind('isOn').to(command, 'value', value => value === style.name);\n this.listenTo(view, 'execute', () => editor.execute('imageStyle', { value: style.name }));\n return view;\n });\n }\n}\n/**\n * Returns the translated `title` from the passed styles array.\n *\n * @param {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat>} styles\n * @param titles\n * @returns {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat>}\n */\nfunction translateStyles(styles, titles) {\n for (const style of styles) {\n // Localize the titles of the styles, if a title corresponds with\n // a localized default provided by the plugin.\n if (titles[style.title]) {\n style.title = titles[style.title];\n }\n }\n return styles;\n}","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module widget/widgettoolbarrepository\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\nimport ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';\nimport BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';\nimport { isWidget } from './utils';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n/**\n * Widget toolbar repository plugin. A central point for registering widget toolbars. This plugin handles the whole\n * toolbar rendering process and exposes a concise API.\n *\n * To add a toolbar for your widget use the {@link ~WidgetToolbarRepository#register `WidgetToolbarRepository#register()`} method.\n *\n * The following example comes from the {@link module:image/imagetoolbar~ImageToolbar} plugin:\n *\n * \t\tclass ImageToolbar extends Plugin {\n *\t\t\tstatic get requires() {\n *\t\t\t\treturn [ WidgetToolbarRepository ];\n *\t\t\t}\n *\n *\t\t\tafterInit() {\n *\t\t\t\tconst editor = this.editor;\n *\t\t\t\tconst widgetToolbarRepository = editor.plugins.get( WidgetToolbarRepository );\n *\n *\t\t\t\twidgetToolbarRepository.register( 'image', {\n *\t\t\t\t\titems: editor.config.get( 'image.toolbar' ),\n *\t\t\t\t\tgetRelatedElement: getSelectedImageWidget\n *\t\t\t\t} );\n *\t\t\t}\n *\t\t}\n */\nexport default class WidgetToolbarRepository extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get requires() {\n return [ContextualBalloon];\n }\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'WidgetToolbarRepository';\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n // Disables the default balloon toolbar for all widgets.\n if (editor.plugins.has('BalloonToolbar')) {\n const balloonToolbar = editor.plugins.get('BalloonToolbar');\n this.listenTo(balloonToolbar, 'show', evt => {\n if (isWidgetSelected(editor.editing.view.document.selection)) {\n evt.stop();\n }\n }, { priority: 'high' });\n }\n /**\n\t\t * A map of toolbar definitions.\n\t\t *\n\t\t * @protected\n\t\t * @member {Map.<String,module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition>} #_toolbarDefinitions\n\t\t */\n this._toolbarDefinitions = new Map();\n /**\n\t\t * @private\n\t\t */\n this._balloon = this.editor.plugins.get('ContextualBalloon');\n this.listenTo(editor.ui, 'update', () => {\n this._updateToolbarsVisibility();\n });\n // UI#update is not fired after focus is back in editor, we need to check if balloon panel should be visible.\n this.listenTo(editor.ui.focusTracker, 'change:isFocused', () => {\n this._updateToolbarsVisibility();\n }, { priority: 'low' });\n }\n destroy() {\n super.destroy();\n for (const toolbarConfig of this._toolbarDefinitions.values()) {\n toolbarConfig.view.destroy();\n }\n }\n /**\n\t * Registers toolbar in the WidgetToolbarRepository. It renders it in the `ContextualBalloon` based on the value of the invoked\n\t * `getRelatedElement` function. Toolbar items are gathered from `items` array.\n\t * The balloon's CSS class is by default `ck-toolbar-container` and may be override with the `balloonClassName` option.\n\t *\n\t * Note: This method should be called in the {@link module:core/plugin~PluginInterface#afterInit `Plugin#afterInit()`}\n\t * callback (or later) to make sure that the given toolbar items were already registered by other plugins.\n\t *\n\t * @param {String} toolbarId An id for the toolbar. Used to\n\t * @param {Object} options\n\t * @param {String} [options.ariaLabel] Label used by assistive technologies to describe this toolbar element.\n\t * @param {Array.<String>} options.items Array of toolbar items.\n\t * @param {Function} options.getRelatedElement Callback which returns an element the toolbar should be attached to.\n\t * @param {String} [options.balloonClassName='ck-toolbar-container'] CSS class for the widget balloon.\n\t */\n register(toolbarId, {ariaLabel, items, getRelatedElement, balloonClassName = 'ck-toolbar-container'}) {\n const editor = this.editor;\n const t = editor.t;\n const toolbarView = new ToolbarView(editor.locale);\n toolbarView.ariaLabel = ariaLabel || t('ad');\n if (this._toolbarDefinitions.has(toolbarId)) {\n /**\n\t\t\t * Toolbar with the given id was already added.\n\t\t\t *\n\t\t\t * @error widget-toolbar-duplicated\n\t\t\t * @param toolbarId Toolbar id.\n\t\t\t */\n throw new CKEditorError('widget-toolbar-duplicated: Toolbar with the given id was already added.', this, { toolbarId });\n }\n toolbarView.fillFromConfig(items, editor.ui.componentFactory);\n this._toolbarDefinitions.set(toolbarId, {\n view: toolbarView,\n getRelatedElement,\n balloonClassName\n });\n }\n /**\n\t * Iterates over stored toolbars and makes them visible or hidden.\n\t *\n\t * @private\n\t */\n _updateToolbarsVisibility() {\n let maxRelatedElementDepth = 0;\n let deepestRelatedElement = null;\n let deepestToolbarDefinition = null;\n for (const definition of this._toolbarDefinitions.values()) {\n const relatedElement = definition.getRelatedElement(this.editor.editing.view.document.selection);\n if (!this.editor.ui.focusTracker.isFocused) {\n if (this._isToolbarVisible(definition)) {\n this._hideToolbar(definition);\n }\n } else if (!relatedElement) {\n if (this._isToolbarInBalloon(definition)) {\n this._hideToolbar(definition);\n }\n } else {\n const relatedElementDepth = relatedElement.getAncestors().length;\n // Many toolbars can express willingness to be displayed but they do not know about\n // each other. Figure out which toolbar is deepest in the view tree to decide which\n // should be displayed. For instance, if a selected image is inside a table cell, display\n // the ImageToolbar rather than the TableToolbar (#60).\n if (relatedElementDepth > maxRelatedElementDepth) {\n maxRelatedElementDepth = relatedElementDepth;\n deepestRelatedElement = relatedElement;\n deepestToolbarDefinition = definition;\n }\n }\n }\n if (deepestToolbarDefinition) {\n this._showToolbar(deepestToolbarDefinition, deepestRelatedElement);\n }\n }\n /**\n\t * Hides the given toolbar.\n\t *\n\t * @private\n\t * @param {module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition} toolbarDefinition\n\t */\n _hideToolbar(toolbarDefinition) {\n this._balloon.remove(toolbarDefinition.view);\n this.stopListening(this._balloon, 'change:visibleView');\n }\n /**\n\t * Shows up the toolbar if the toolbar is not visible.\n\t * Otherwise, repositions the toolbar's balloon when toolbar's view is the most top view in balloon stack.\n\t *\n\t * It might happen here that the toolbar's view is under another view. Then do nothing as the other toolbar view\n\t * should be still visible after the {@link module:core/editor/editorui~EditorUI#event:update}.\n\t *\n\t * @private\n\t * @param {module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition} toolbarDefinition\n\t * @param {module:engine/view/element~Element} relatedElement\n\t */\n _showToolbar(toolbarDefinition, relatedElement) {\n if (this._isToolbarVisible(toolbarDefinition)) {\n repositionContextualBalloon(this.editor, relatedElement);\n } else if (!this._isToolbarInBalloon(toolbarDefinition)) {\n this._balloon.add({\n view: toolbarDefinition.view,\n position: getBalloonPositionData(this.editor, relatedElement),\n balloonClassName: toolbarDefinition.balloonClassName\n });\n // Update toolbar position each time stack with toolbar view is switched to visible.\n // This is in a case target element has changed when toolbar was in invisible stack\n // e.g. target image was wrapped by a block quote.\n // See https://github.com/ckeditor/ckeditor5-widget/issues/92.\n this.listenTo(this._balloon, 'change:visibleView', () => {\n for (const definition of this._toolbarDefinitions.values()) {\n if (this._isToolbarVisible(definition)) {\n const relatedElement = definition.getRelatedElement(this.editor.editing.view.document.selection);\n repositionContextualBalloon(this.editor, relatedElement);\n }\n }\n });\n }\n }\n /**\n\t * @private\n\t * @param {Object} toolbar\n\t * @returns {Boolean}\n\t */\n _isToolbarVisible(toolbar) {\n return this._balloon.visibleView === toolbar.view;\n }\n /**\n\t * @private\n\t * @param {Object} toolbar\n\t * @returns {Boolean}\n\t */\n _isToolbarInBalloon(toolbar) {\n return this._balloon.hasView(toolbar.view);\n }\n}\nfunction repositionContextualBalloon(editor, relatedElement) {\n const balloon = editor.plugins.get('ContextualBalloon');\n const position = getBalloonPositionData(editor, relatedElement);\n balloon.updatePosition(position);\n}\nfunction getBalloonPositionData(editor, relatedElement) {\n const editingView = editor.editing.view;\n const defaultPositions = BalloonPanelView.defaultPositions;\n return {\n target: editingView.domConverter.mapViewToDom(relatedElement),\n positions: [\n defaultPositions.northArrowSouth,\n defaultPositions.northArrowSouthWest,\n defaultPositions.northArrowSouthEast,\n defaultPositions.southArrowNorth,\n defaultPositions.southArrowNorthWest,\n defaultPositions.southArrowNorthEast\n ]\n };\n}\nfunction isWidgetSelected(selection) {\n const viewElement = selection.getSelectedElement();\n return !!(viewElement && isWidget(viewElement));\n} /**\n * The toolbar definition object used by the toolbar repository to manage toolbars.\n * It contains information necessary to display the toolbar in the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} and\n * update it during its life (display) cycle.\n *\n * @typedef {Object} module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition\n *\n * @property {module:ui/view~View} view The UI view of the toolbar.\n * @property {Function} getRelatedElement A function that returns an engine {@link module:engine/view/view~View}\n * element the toolbar is to be attached to. For instance, an image widget or a table widget (or `null` when\n * there is no such element). The function accepts an instance of {@link module:engine/view/selection~Selection}.\n * @property {String} balloonClassName CSS class for the widget balloon when a toolbar is displayed.\n */","/**\n * @license Copyright (c) 2003-2019, 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 link/findlinkrange\n */\n\n/**\n * Returns a range containing the entire link in which the given `position` is placed.\n *\n * It can be used e.g. to get the entire range on which the `linkHref` attribute needs to be changed when having a\n * selection inside a link.\n *\n * @param {module:engine/model/position~Position} position The start position.\n * @param {String} value The `linkHref` attribute value.\n * @returns {module:engine/model/range~Range} The link range.\n */\nexport default function findLinkRange( position, value, model ) {\n\treturn model.createRange( _findBound( position, value, true, model ), _findBound( position, value, false, model ) );\n}\n\n// Walks forward or backward (depends on the `lookBack` flag), node by node, as long as they have the same `linkHref` attribute value\n// and returns a position just before or after (depends on the `lookBack` flag) the last matched node.\n//\n// @param {module:engine/model/position~Position} position The start position.\n// @param {String} value The `linkHref` attribute value.\n// @param {Boolean} lookBack Whether the walk direction is forward (`false`) or backward (`true`).\n// @returns {module:engine/model/position~Position} The position just before the last matched node.\nfunction _findBound( position, value, lookBack, model ) {\n\t// Get node before or after position (depends on `lookBack` flag).\n\t// When position is inside text node then start searching from text node.\n\tlet node = position.textNode || ( lookBack ? position.nodeBefore : position.nodeAfter );\n\n\tlet lastNode = null;\n\n\twhile ( node && node.getAttribute( 'linkHref' ) == value ) {\n\t\tlastNode = node;\n\t\tnode = lookBack ? node.previousSibling : node.nextSibling;\n\t}\n\n\treturn lastNode ? model.createPositionAt( lastNode, lookBack ? 'before' : 'after' ) : position;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 link/linkcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport findLinkRange from './findlinkrange';\nimport toMap from '@ckeditor/ckeditor5-utils/src/tomap';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\n\n/**\n * The link command. It is used by the {@link module:link/link~Link link feature}.\n *\n * @extends module:core/command~Command\n */\nexport default class LinkCommand extends Command {\n\t/**\n\t * The value of the `'linkHref'` attribute if the start of the selection is located in a node with this attribute.\n\t *\n\t * @observable\n\t * @readonly\n\t * @member {Object|undefined} #value\n\t */\n\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * A collection of {@link module:link/utils~ManualDecorator manual decorators}\n\t\t * corresponding to the {@link module:link/link~LinkConfig#decorators decorator configuration}.\n\t\t *\n\t\t * You can consider it a model with states of manual decorators added to the currently selected link.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:utils/collection~Collection}\n\t\t */\n\t\tthis.manualDecorators = new Collection();\n\t}\n\n\t/**\n\t * Synchronizes the state of {@link #manualDecorators} with the currently present elements in the model.\n\t */\n\trestoreManualDecoratorStates() {\n\t\tfor ( const manualDecorator of this.manualDecorators ) {\n\t\t\tmanualDecorator.value = this._getDecoratorStateFromModel( manualDecorator.id );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tthis.value = doc.selection.getAttribute( 'linkHref' );\n\n\t\tfor ( const manualDecorator of this.manualDecorators ) {\n\t\t\tmanualDecorator.value = this._getDecoratorStateFromModel( manualDecorator.id );\n\t\t}\n\n\t\tthis.isEnabled = model.schema.checkAttributeInSelection( doc.selection, 'linkHref' );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * When the selection is non-collapsed, the `linkHref` attribute will be applied to nodes inside the selection, but only to\n\t * those nodes where the `linkHref` attribute is allowed (disallowed nodes will be omitted).\n\t *\n\t * When the selection is collapsed and is not inside the text with the `linkHref` attribute, a\n\t * new {@link module:engine/model/text~Text text node} with the `linkHref` attribute will be inserted in place of the caret, but\n\t * only if such element is allowed in this place. The `_data` of the inserted text will equal the `href` parameter.\n\t * The selection will be updated to wrap the just inserted text node.\n\t *\n\t * When the selection is collapsed and inside the text with the `linkHref` attribute, the attribute value will be updated.\n\t *\n\t * # Decorators and model attribute management\n\t *\n\t * There is an optional argument to this command that applies or removes model\n\t * {@glink framework/guides/architecture/editing-engine#text-attributes text attributes} brought by\n\t * {@link module:link/utils~ManualDecorator manual link decorators}.\n\t *\n\t * Text attribute names in the model correspond to the entries in the {@link module:link/link~LinkConfig#decorators configuration}.\n\t * For every decorator configured, a model text attribute exists with the \"link\" prefix. For example, a `'linkMyDecorator'` attribute\n\t * corresponds to `'myDecorator'` in the configuration.\n\t *\n\t * To learn more about link decorators, check out the {@link module:link/link~LinkConfig#decorators `config.link.decorators`}\n\t * documentation.\n\t *\n\t * Here is how to manage decorator attributes with the link command:\n\t *\n\t *\t\tconst linkCommand = editor.commands.get( 'link' );\n\t *\n\t *\t\t// Adding a new decorator attribute.\n\t *\t\tlinkCommand.execute( 'http://example.com', {\n\t *\t\t\tlinkIsExternal: true\n\t *\t\t} );\n\t *\n\t *\t\t// Removing a decorator attribute from the selection.\n\t *\t\tlinkCommand.execute( 'http://example.com', {\n\t *\t\t\tlinkIsExternal: false\n\t *\t\t} );\n\t *\n\t *\t\t// Adding multiple decorator attributes at the same time.\n\t *\t\tlinkCommand.execute( 'http://example.com', {\n\t *\t\t\tlinkIsExternal: true,\n\t *\t\t\tlinkIsDownloadable: true,\n\t *\t\t} );\n\t *\n\t *\t\t// Removing and adding decorator attributes at the same time.\n\t *\t\tlinkCommand.execute( 'http://example.com', {\n\t *\t\t\tlinkIsExternal: false,\n\t *\t\t\tlinkFoo: true,\n\t *\t\t\tlinkIsDownloadable: false,\n\t *\t\t} );\n\t *\n\t * **Note**: If the decorator attribute name is not specified, its state remains untouched.\n\t *\n\t * **Note**: {@link module:link/unlinkcommand~UnlinkCommand#execute `UnlinkCommand#execute()`} removes all\n\t * decorator attributes.\n\t *\n\t * @fires execute\n\t * @param {String} href Link destination.\n\t * @param {Object} [manualDecoratorIds={}] The information about manual decorator attributes to be applied or removed upon execution.\n\t */\n\texecute( href, manualDecoratorIds = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\t// Stores information about manual decorators to turn them on/off when command is applied.\n\t\tconst truthyManualDecorators = [];\n\t\tconst falsyManualDecorators = [];\n\n\t\tfor ( const name in manualDecoratorIds ) {\n\t\t\tif ( manualDecoratorIds[ name ] ) {\n\t\t\t\ttruthyManualDecorators.push( name );\n\t\t\t} else {\n\t\t\t\tfalsyManualDecorators.push( name );\n\t\t\t}\n\t\t}\n\n\t\tmodel.change( writer => {\n\t\t\t// If selection is collapsed then update selected link or insert new one at the place of caret.\n\t\t\tif ( selection.isCollapsed ) {\n\t\t\t\tconst position = selection.getFirstPosition();\n\n\t\t\t\t// When selection is inside text with `linkHref` attribute.\n\t\t\t\tif ( selection.hasAttribute( 'linkHref' ) ) {\n\t\t\t\t\t// Then update `linkHref` value.\n\t\t\t\t\tconst linkRange = findLinkRange( position, selection.getAttribute( 'linkHref' ), model );\n\n\t\t\t\t\twriter.setAttribute( 'linkHref', href, linkRange );\n\n\t\t\t\t\ttruthyManualDecorators.forEach( item => {\n\t\t\t\t\t\twriter.setAttribute( item, true, linkRange );\n\t\t\t\t\t} );\n\n\t\t\t\t\tfalsyManualDecorators.forEach( item => {\n\t\t\t\t\t\twriter.removeAttribute( item, linkRange );\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Create new range wrapping changed link.\n\t\t\t\t\twriter.setSelection( linkRange );\n\t\t\t\t}\n\t\t\t\t// If not then insert text node with `linkHref` attribute in place of caret.\n\t\t\t\t// However, since selection in collapsed, attribute value will be used as data for text node.\n\t\t\t\t// So, if `href` is empty, do not create text node.\n\t\t\t\telse if ( href !== '' ) {\n\t\t\t\t\tconst attributes = toMap( selection.getAttributes() );\n\n\t\t\t\t\tattributes.set( 'linkHref', href );\n\n\t\t\t\t\ttruthyManualDecorators.forEach( item => {\n\t\t\t\t\t\tattributes.set( item, true );\n\t\t\t\t\t} );\n\n\t\t\t\t\tconst node = writer.createText( href, attributes );\n\n\t\t\t\t\tmodel.insertContent( node, position );\n\n\t\t\t\t\t// Create new range wrapping created node.\n\t\t\t\t\twriter.setSelection( writer.createRangeOn( node ) );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If selection has non-collapsed ranges, we change attribute on nodes inside those ranges\n\t\t\t\t// omitting nodes where `linkHref` attribute is disallowed.\n\t\t\t\tconst ranges = model.schema.getValidRanges( selection.getRanges(), 'linkHref' );\n\n\t\t\t\tfor ( const range of ranges ) {\n\t\t\t\t\twriter.setAttribute( 'linkHref', href, range );\n\n\t\t\t\t\ttruthyManualDecorators.forEach( item => {\n\t\t\t\t\t\twriter.setAttribute( item, true, range );\n\t\t\t\t\t} );\n\n\t\t\t\t\tfalsyManualDecorators.forEach( item => {\n\t\t\t\t\t\twriter.removeAttribute( item, range );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Provides information whether a decorator with a given name is present in the currently processed selection.\n\t *\n\t * @private\n\t * @param {String} decoratorName The name of the manual decorator used in the model\n\t * @returns {Boolean} The information whether a given decorator is currently present in the selection.\n\t */\n\t_getDecoratorStateFromModel( decoratorName ) {\n\t\tconst doc = this.editor.model.document;\n\t\treturn doc.selection.getAttribute( decoratorName ) || false;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 link/unlinkcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport findLinkRange from './findlinkrange';\n\n/**\n * The unlink command. It is used by the {@link module:link/link~Link link plugin}.\n *\n * @extends module:core/command~Command\n */\nexport default class UnlinkCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.isEnabled = this.editor.model.document.selection.hasAttribute( 'linkHref' );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * When the selection is collapsed, it removes the `linkHref` attribute from each node with the same `linkHref` attribute value.\n\t * When the selection is non-collapsed, it removes the `linkHref` attribute from each node in selected ranges.\n\t *\n\t * # Decorators\n\t *\n\t * If {@link module:link/link~LinkConfig#decorators `config.link.decorators`} is specified,\n\t * all configured decorators are removed together with the `linkHref` attribute.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst editor = this.editor;\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\n\t\tmodel.change( writer => {\n\t\t\t// Get ranges to unlink.\n\t\t\tconst rangesToUnlink = selection.isCollapsed ?\n\t\t\t\t[ findLinkRange( selection.getFirstPosition(), selection.getAttribute( 'linkHref' ), model ) ] : selection.getRanges();\n\n\t\t\t// Remove `linkHref` attribute from specified ranges.\n\t\t\tfor ( const range of rangesToUnlink ) {\n\t\t\t\twriter.removeAttribute( 'linkHref', range );\n\t\t\t\t// If there are registered custom attributes, then remove them during unlink.\n\t\t\t\tif ( linkCommand ) {\n\t\t\t\t\tfor ( const manualDecorator of linkCommand.manualDecorators ) {\n\t\t\t\t\t\twriter.removeAttribute( manualDecorator.id, range );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\nfunction baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = end > length ? length : end;\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n}\n\nexport default baseSlice;\n","import baseSlice from './_baseSlice.js';\n\n/**\n * Casts `array` to a slice if it's needed.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {number} start The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the cast slice.\n */\nfunction castSlice(array, start, end) {\n var length = array.length;\n end = end === undefined ? length : end;\n return (!start && end >= length) ? array : baseSlice(array, start, end);\n}\n\nexport default castSlice;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsZWJ = '\\\\u200d';\n\n/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\nvar reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');\n\n/**\n * Checks if `string` contains Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n */\nfunction hasUnicode(string) {\n return reHasUnicode.test(string);\n}\n\nexport default hasUnicode;\n","/**\n * Converts an ASCII `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction asciiToArray(string) {\n return string.split('');\n}\n\nexport default asciiToArray;\n","/** Used to compose unicode character classes. */\nvar rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsVarRange = '\\\\ufe0e\\\\ufe0f';\n\n/** Used to compose unicode capture groups. */\nvar rsAstral = '[' + rsAstralRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsZWJ = '\\\\u200d';\n\n/** Used to compose unicode regexes. */\nvar reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\nvar reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n/**\n * Converts a Unicode `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction unicodeToArray(string) {\n return string.match(reUnicode) || [];\n}\n\nexport default unicodeToArray;\n","import asciiToArray from './_asciiToArray.js';\nimport hasUnicode from './_hasUnicode.js';\nimport unicodeToArray from './_unicodeToArray.js';\n\n/**\n * Converts `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\nfunction stringToArray(string) {\n return hasUnicode(string)\n ? unicodeToArray(string)\n : asciiToArray(string);\n}\n\nexport default stringToArray;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n}\n\nexport default arrayMap;\n","import Symbol from './_Symbol.js';\nimport arrayMap from './_arrayMap.js';\nimport isArray from './isArray.js';\nimport isSymbol from './isSymbol.js';\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n/**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n // Exit early for strings to avoid a performance hit in some environments.\n if (typeof value == 'string') {\n return value;\n }\n if (isArray(value)) {\n // Recursively convert values (susceptible to call stack limits).\n return arrayMap(value, baseToString) + '';\n }\n if (isSymbol(value)) {\n return symbolToString ? symbolToString.call(value) : '';\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nexport default baseToString;\n","import baseToString from './_baseToString.js';\n\n/**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\nfunction toString(value) {\n return value == null ? '' : baseToString(value);\n}\n\nexport default toString;\n","import castSlice from './_castSlice.js';\nimport hasUnicode from './_hasUnicode.js';\nimport stringToArray from './_stringToArray.js';\nimport toString from './toString.js';\n\n/**\n * Creates a function like `_.lowerFirst`.\n *\n * @private\n * @param {string} methodName The name of the `String` case method to use.\n * @returns {Function} Returns the new case function.\n */\nfunction createCaseFirst(methodName) {\n return function(string) {\n string = toString(string);\n\n var strSymbols = hasUnicode(string)\n ? stringToArray(string)\n : undefined;\n\n var chr = strSymbols\n ? strSymbols[0]\n : string.charAt(0);\n\n var trailing = strSymbols\n ? castSlice(strSymbols, 1).join('')\n : string.slice(1);\n\n return chr[methodName]() + trailing;\n };\n}\n\nexport default createCaseFirst;\n","import createCaseFirst from './_createCaseFirst.js';\n\n/**\n * Converts the first character of `string` to upper case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.upperFirst('fred');\n * // => 'Fred'\n *\n * _.upperFirst('FRED');\n * // => 'FRED'\n */\nvar upperFirst = createCaseFirst('toUpperCase');\n\nexport default upperFirst;\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module link/utils\n */\nimport { upperFirst } from 'lodash-es';\nconst ATTRIBUTE_WHITESPACES = /[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205f\\u3000]/g;\n// eslint-disable-line no-control-regex\nconst SAFE_URL = /^(?:(?:https?|ftps?|mailto):|[^a-z]|[a-z+.-]+(?:[^a-z+.:-]|$))/i;\n/**\n * Returns `true` if a given view node is the link element.\n *\n * @param {module:engine/view/node~Node} node\n * @returns {Boolean}\n */\nexport function isLinkElement(node) {\n return node.is('attributeElement') && !!node.getCustomProperty('link');\n}\n/**\n * Creates link {@link module:engine/view/attributeelement~AttributeElement} with the provided `href` attribute.\n *\n * @param {String} href\n * @returns {module:engine/view/attributeelement~AttributeElement}\n */\nexport function createLinkElement(href, writer) {\n // Priority 5 - https://github.com/ckeditor/ckeditor5-link/issues/121.\n const linkElement = writer.createAttributeElement('a', { href }, { priority: 5 });\n writer.setCustomProperty('link', true, linkElement);\n return linkElement;\n}\n/**\n * Returns a safe URL based on a given value.\n *\n * A URL is considered safe if it is safe for the user (does not contain any malicious code).\n *\n * If a URL is considered unsafe, a simple `\"#\"` is returned.\n *\n * @protected\n * @param {*} url\n * @returns {String} Safe URL.\n */\nexport function ensureSafeUrl(url) {\n url = String(url);\n return isSafeUrl(url) ? url : '#';\n}\n// Checks whether the given URL is safe for the user (does not contain any malicious code).\n//\n// @param {String} url URL to check.\nfunction isSafeUrl(url) {\n const normalizedUrl = url.replace(ATTRIBUTE_WHITESPACES, '');\n return normalizedUrl.match(SAFE_URL);\n}\n/**\n * Returns the {@link module:link/link~LinkConfig#decorators `config.link.decorators`} configuration processed\n * to respect the locale of the editor, i.e. to display the {@link module:link/link~LinkDecoratorManualDefinition label}\n * in the correct language.\n *\n * **Note**: Only the few most commonly used labels are translated automatically. Other labels should be manually\n * translated in the {@link module:link/link~LinkConfig#decorators `config.link.decorators`} configuration.\n *\n * @param {module:utils/locale~Locale#t} t shorthand for {@link module:utils/locale~Locale#t Locale#t}\n * @param {Array.<module:link/link~LinkDecoratorDefinition>} The decorator reference\n * where the label values should be localized.\n * @returns {Array.<module:link/link~LinkDecoratorDefinition>}\n */\nexport function getLocalizedDecorators(t, decorators) {\n const localizedDecoratorsLabels = {\n 'Open in a new tab': t('ay'),\n 'Downloadable': t('az')\n };\n decorators.forEach(decorator => {\n if (decorator.label && localizedDecoratorsLabels[decorator.label]) {\n decorator.label = localizedDecoratorsLabels[decorator.label];\n }\n return decorator;\n });\n return decorators;\n}\n/**\n * Converts an object with defined decorators to a normalized array of decorators. The `id` key is added for each decorator and\n * is used as the attribute's name in the model.\n *\n * @param {Object.<String, module:link/link~LinkDecoratorDefinition>} decorators\n * @returns {Array.<module:link/link~LinkDecoratorDefinition>}\n */\nexport function normalizeDecorators(decorators) {\n const retArray = [];\n if (decorators) {\n for (const [key, value] of Object.entries(decorators)) {\n const decorator = Object.assign({}, value, { id: `link${ upperFirst(key) }` });\n retArray.push(decorator);\n }\n }\n return retArray;\n}","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md.\n */\n\n/**\n * @module link/utils\n */\n\n/**\n * Helper class that ties together all {@link module:link/link~LinkDecoratorAutomaticDefinition} and provides\n * a {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToElement downcast dispatcher} for them.\n */\nexport default class AutomaticDecorators {\n\tconstructor() {\n\t\t/**\n\t\t * Stores the definition of {@link module:link/link~LinkDecoratorAutomaticDefinition automatic decorators}.\n\t\t * This data is used as a source for a downcast dispatcher to create a proper conversion to output data.\n\t\t *\n\t\t * @private\n\t\t * @type {Set}\n\t\t */\n\t\tthis._definitions = new Set();\n\t}\n\n\t/**\n\t * Gives information about the number of decorators stored in the {@link module:link/utils~AutomaticDecorators} instance.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Number}\n\t */\n\tget length() {\n\t\treturn this._definitions.size;\n\t}\n\n\t/**\n\t * Adds automatic decorator objects or an array with them to be used during downcasting.\n\t *\n\t * @param {module:link/link~LinkDecoratorAutomaticDefinition|Array.<module:link/link~LinkDecoratorAutomaticDefinition>} item\n\t * A configuration object of automatic rules for decorating links. It might also be an array of such objects.\n\t */\n\tadd( item ) {\n\t\tif ( Array.isArray( item ) ) {\n\t\t\titem.forEach( item => this._definitions.add( item ) );\n\t\t} else {\n\t\t\tthis._definitions.add( item );\n\t\t}\n\t}\n\n\t/**\n\t * Provides the conversion helper used in the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add} method.\n\t *\n\t * @returns {Function} A dispatcher function used as conversion helper\n\t * in {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add}.\n\t */\n\tgetDispatcher() {\n\t\treturn dispatcher => {\n\t\t\tdispatcher.on( 'attribute:linkHref', ( evt, data, conversionApi ) => {\n\t\t\t\t// There is only test as this behavior decorates links and\n\t\t\t\t// it is run before dispatcher which actually consumes this node.\n\t\t\t\t// This allows on writing own dispatcher with highest priority,\n\t\t\t\t// which blocks both native converter and this additional decoration.\n\t\t\t\tif ( !conversionApi.consumable.test( data.item, 'attribute:linkHref' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst viewWriter = conversionApi.writer;\n\t\t\t\tconst viewSelection = viewWriter.document.selection;\n\n\t\t\t\tfor ( const item of this._definitions ) {\n\t\t\t\t\tconst viewElement = viewWriter.createAttributeElement( 'a', item.attributes, {\n\t\t\t\t\t\tpriority: 5\n\t\t\t\t\t} );\n\t\t\t\t\tviewWriter.setCustomProperty( 'link', true, viewElement );\n\t\t\t\t\tif ( item.callback( data.attributeNewValue ) ) {\n\t\t\t\t\t\tif ( data.item.is( 'selection' ) ) {\n\t\t\t\t\t\t\tviewWriter.wrap( viewSelection.getFirstRange(), viewElement );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tviewWriter.wrap( conversionApi.mapper.toViewRange( data.range ), viewElement );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tviewWriter.unwrap( conversionApi.mapper.toViewRange( data.range ), viewElement );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, { priority: 'high' } );\n\t\t};\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 link/utils\n */\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Helper class that stores manual decorators with observable {@link module:link/utils~ManualDecorator#value}\n * to support integration with the UI state. An instance of this class is a model with the state of individual manual decorators.\n * These decorators are kept as collections in {@link module:link/linkcommand~LinkCommand#manualDecorators}.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class ManualDecorator {\n\t/**\n\t * Creates a new instance of {@link module:link/utils~ManualDecorator}.\n\t *\n\t * @param {Object} config\n\t * @param {String} config.id The name of the attribute used in the model that represents a given manual decorator.\n\t * For example: `'linkIsExternal'`.\n\t * @param {String} config.label The label used in the user interface to toggle the manual decorator.\n\t * @param {Object} config.attributes A set of attributes added to output data when the decorator is active for a specific link.\n\t * Attributes should keep the format of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.\n\t */\n\tconstructor( { id, label, attributes } ) {\n\t\t/**\n\t\t * An ID of a manual decorator which is the name of the attribute in the model, for example: 'linkManualDecorator0'.\n\t\t *\n\t\t * @type {String}\n\t\t */\n\t\tthis.id = id;\n\n\t\t/**\n\t\t * The value of the current manual decorator. It reflects its state from the UI.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} module:link/utils~ManualDecorator#value\n\t\t */\n\t\tthis.set( 'value' );\n\n\t\t/**\n\t\t * The label used in the user interface to toggle the manual decorator.\n\t\t *\n\t\t * @type {String}\n\t\t */\n\t\tthis.label = label;\n\n\t\t/**\n\t\t * A set of attributes added to downcasted data when the decorator is activated for a specific link.\n\t\t * Attributes should be added in a form of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.\n\t\t *\n\t\t * @type {Object}\n\t\t */\n\t\tthis.attributes = attributes;\n\t}\n}\n\nmix( ManualDecorator, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2019, 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 engine/utils/bindtwostepcarettoattribute\n */\n\nimport { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport priorities from '@ckeditor/ckeditor5-utils/src/priorities';\n\n/**\n * This helper enables the two-step caret (phantom) movement behavior for the given {@link module:engine/model/model~Model}\n * attribute on arrow right (<kbd>→</kbd>) and left (<kbd>←</kbd>) key press.\n *\n * Thanks to this (phantom) caret movement the user is able to type before/after as well as at the\n * beginning/end of an attribute.\n *\n * **Note:** This helper support right–to–left (Arabic, Hebrew, etc.) content by mirroring its behavior\n * but for the sake of simplicity examples showcase only left–to–right use–cases.\n *\n * # Forward movement\n *\n * ## \"Entering\" an attribute:\n *\n * When this behavior is enabled for the `a` attribute and the selection is right before it\n * (at the attribute boundary), pressing the right arrow key will not move the selection but update its\n * attributes accordingly:\n *\n * * When enabled:\n *\n * \t\tfoo{}<$text a=\"true\">bar</$text>\n *\n * <kbd>→</kbd>\n *\n * \t\tfoo<$text a=\"true\">{}bar</$text>\n *\n * * When disabled:\n *\n * \t\tfoo{}<$text a=\"true\">bar</$text>\n *\n * <kbd>→</kbd>\n *\n * \t\tfoo<$text a=\"true\">b{}ar</$text>\n *\n *\n * ## \"Leaving\" an attribute:\n *\n * * When enabled:\n *\n * \t\t<$text a=\"true\">bar{}</$text>baz\n *\n * <kbd>→</kbd>\n *\n * \t\t<$text a=\"true\">bar</$text>{}baz\n *\n * * When disabled:\n *\n * \t\t<$text a=\"true\">bar{}</$text>baz\n *\n * <kbd>→</kbd>\n *\n * \t\t<$text a=\"true\">bar</$text>b{}az\n *\n * # Backward movement\n *\n * * When enabled:\n *\n * \t\t<$text a=\"true\">bar</$text>{}baz\n *\n * <kbd>←</kbd>\n *\n * \t\t<$text a=\"true\">bar{}</$text>baz\n *\n * * When disabled:\n *\n * \t\t<$text a=\"true\">bar</$text>{}baz\n *\n * <kbd>←</kbd>\n *\n * \t\t<$text a=\"true\">ba{}r</$text>b{}az\n *\n * @param {Object} options Helper options.\n * @param {module:engine/view/view~View} options.view View controller instance.\n * @param {module:engine/model/model~Model} options.model Data model instance.\n * @param {module:utils/dom/emittermixin~Emitter} options.emitter The emitter to which this behavior should be added\n * (e.g. a plugin instance).\n * @param {String} options.attribute Attribute for which this behavior will be added.\n * @param {module:utils/locale~Locale} options.locale The {@link module:core/editor/editor~Editor#locale} instance.\n */\nexport default function bindTwoStepCaretToAttribute( { view, model, emitter, attribute, locale } ) {\n\tconst twoStepCaretHandler = new TwoStepCaretHandler( model, emitter, attribute );\n\tconst modelSelection = model.document.selection;\n\n\t// Listen to keyboard events and handle the caret movement according to the 2-step caret logic.\n\t//\n\t// Note: This listener has the \"high+1\" priority:\n\t// * \"high\" because of the filler logic implemented in the renderer which also engages on #keydown.\n\t// When the gravity is overridden the attributes of the (model) selection attributes are reset.\n\t// It may end up with the filler kicking in and breaking the selection.\n\t// * \"+1\" because we would like to avoid collisions with other features (like Widgets), which\n\t// take over the keydown events with the \"high\" priority. Two-step caret movement takes precedence\n\t// over Widgets in that matter.\n\t//\n\t// Find out more in https://github.com/ckeditor/ckeditor5-engine/issues/1301.\n\temitter.listenTo( view.document, 'keydown', ( evt, data ) => {\n\t\t// This implementation works only for collapsed selection.\n\t\tif ( !modelSelection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// When user tries to expand the selection or jump over the whole word or to the beginning/end then\n\t\t// two-steps movement is not necessary.\n\t\tif ( data.shiftKey || data.altKey || data.ctrlKey ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst arrowRightPressed = data.keyCode == keyCodes.arrowright;\n\t\tconst arrowLeftPressed = data.keyCode == keyCodes.arrowleft;\n\n\t\t// When neither left or right arrow has been pressed then do noting.\n\t\tif ( !arrowRightPressed && !arrowLeftPressed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst position = modelSelection.getFirstPosition();\n\t\tconst contentDirection = locale.contentLanguageDirection;\n\t\tlet isMovementHandled;\n\n\t\tif ( ( contentDirection === 'ltr' && arrowRightPressed ) || ( contentDirection === 'rtl' && arrowLeftPressed ) ) {\n\t\t\tisMovementHandled = twoStepCaretHandler.handleForwardMovement( position, data );\n\t\t} else {\n\t\t\tisMovementHandled = twoStepCaretHandler.handleBackwardMovement( position, data );\n\t\t}\n\n\t\t// Stop the keydown event if the two-step caret movement handled it. Avoid collisions\n\t\t// with other features which may also take over the caret movement (e.g. Widget).\n\t\tif ( isMovementHandled ) {\n\t\t\tevt.stop();\n\t\t}\n\t}, { priority: priorities.get( 'high' ) + 1 } );\n}\n\n/**\n * This is a protected helper–class for {@link module:engine/utils/bindtwostepcarettoattribute}.\n * It handles the state of the 2-step caret movement for a single {@link module:engine/model/model~Model}\n * attribute upon the `keypress` in the {@link module:engine/view/view~View}.\n *\n * @protected\n */\nexport class TwoStepCaretHandler {\n\t/*\n\t * Creates two step handler instance.\n\t *\n\t * @param {module:engine/model/model~Model} model Data model instance.\n\t * @param {module:utils/dom/emittermixin~Emitter} emitter The emitter to which this behavior should be added\n\t * (e.g. a plugin instance).\n\t * @param {String} attribute Attribute for which the behavior will be added.\n\t */\n\tconstructor( model, emitter, attribute ) {\n\t\t/**\n\t\t * The model instance this class instance operates on.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/model~Model#schema}\n\t\t */\n\t\tthis.model = model;\n\n\t\t/**\n\t\t * The Attribute this class instance operates on.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String}\n\t\t */\n\t\tthis.attribute = attribute;\n\n\t\t/**\n\t\t * A reference to the document selection.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/selection~Selection}\n\t\t */\n\t\tthis._modelSelection = model.document.selection;\n\n\t\t/**\n\t\t * The current UID of the overridden gravity, as returned by\n\t\t * {@link module:engine/model/writer~Writer#overrideSelectionGravity}.\n\t\t *\n\t\t * @private\n\t\t * @member {String}\n\t\t */\n\t\tthis._overrideUid = null;\n\n\t\t/**\n\t\t * A flag indicating that the automatic gravity restoration for this attribute\n\t\t * should not happen upon the next\n\t\t * {@link module:engine/model/selection~Selection#event:change:range} event.\n\t\t *\n\t\t * @private\n\t\t * @member {String}\n\t\t */\n\t\tthis._isNextGravityRestorationSkipped = false;\n\n\t\t// The automatic gravity restoration logic.\n\t\temitter.listenTo( this._modelSelection, 'change:range', ( evt, data ) => {\n\t\t\t// Skipping the automatic restoration is needed if the selection should change\n\t\t\t// but the gravity must remain overridden afterwards. See the #handleBackwardMovement\n\t\t\t// to learn more.\n\t\t\tif ( this._isNextGravityRestorationSkipped ) {\n\t\t\t\tthis._isNextGravityRestorationSkipped = false;\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Skip automatic restore when the gravity is not overridden — simply, there's nothing to restore\n\t\t\t// at this moment.\n\t\t\tif ( !this._isGravityOverridden ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Skip automatic restore when the change is indirect AND the selection is at the attribute boundary.\n\t\t\t// It means that e.g. if the change was external (collaboration) and the user had their\n\t\t\t// selection around the link, its gravity should remain intact in this change:range event.\n\t\t\tif ( !data.directChange && isAtBoundary( this._modelSelection.getFirstPosition(), attribute ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._restoreGravity();\n\t\t} );\n\t}\n\n\t/**\n\t * Updates the document selection and the view according to the two–step caret movement state\n\t * when moving **forwards**. Executed upon `keypress` in the {@link module:engine/view/view~View}.\n\t *\n\t * @param {module:engine/model/position~Position} position The model position at the moment of the key press.\n\t * @param {module:engine/view/observer/domeventdata~DomEventData} data Data of the key press.\n\t * @returns {Boolean} `true` when the handler prevented caret movement\n\t */\n\thandleForwardMovement( position, data ) {\n\t\tconst attribute = this.attribute;\n\n\t\t// DON'T ENGAGE 2-SCM if gravity is already overridden. It means that we just entered\n\t\t//\n\t\t// \t\t<paragraph>foo<$text attribute>{}bar</$text>baz</paragraph>\n\t\t//\n\t\t// or left the attribute\n\t\t//\n\t\t// \t\t<paragraph>foo<$text attribute>bar</$text>{}baz</paragraph>\n\t\t//\n\t\t// and the gravity will be restored automatically.\n\t\tif ( this._isGravityOverridden ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// DON'T ENGAGE 2-SCM when the selection is at the beginning of the block AND already has the\n\t\t// attribute:\n\t\t// * when the selection was initially set there using the mouse,\n\t\t// * when the editor has just started\n\t\t//\n\t\t//\t\t<paragraph><$text attribute>{}bar</$text>baz</paragraph>\n\t\t//\n\t\tif ( position.isAtStart && this._hasSelectionAttribute ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// ENGAGE 2-SCM when about to leave one attribute value and enter another:\n\t\t//\n\t\t// \t\t<paragraph><$text attribute=\"1\">foo{}</$text><$text attribute=\"2\">bar</$text></paragraph>\n\t\t//\n\t\t// but DON'T when already in between of them (no attribute selection):\n\t\t//\n\t\t// \t\t<paragraph><$text attribute=\"1\">foo</$text>{}<$text attribute=\"2\">bar</$text></paragraph>\n\t\t//\n\t\tif ( isBetweenDifferentValues( position, attribute ) && this._hasSelectionAttribute ) {\n\t\t\tthis._preventCaretMovement( data );\n\t\t\tthis._removeSelectionAttribute();\n\n\t\t\treturn true;\n\t\t}\n\n\t\t// ENGAGE 2-SCM when entering an attribute:\n\t\t//\n\t\t// \t\t<paragraph>foo{}<$text attribute>bar</$text>baz</paragraph>\n\t\t//\n\t\tif ( isAtStartBoundary( position, attribute ) ) {\n\t\t\tthis._preventCaretMovement( data );\n\t\t\tthis._overrideGravity();\n\n\t\t\treturn true;\n\t\t}\n\n\t\t// ENGAGE 2-SCM when leaving an attribute:\n\t\t//\n\t\t//\t\t<paragraph>foo<$text attribute>bar{}</$text>baz</paragraph>\n\t\t//\n\t\tif ( isAtEndBoundary( position, attribute ) && this._hasSelectionAttribute ) {\n\t\t\tthis._preventCaretMovement( data );\n\t\t\tthis._overrideGravity();\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * Updates the document selection and the view according to the two–step caret movement state\n\t * when moving **backwards**. Executed upon `keypress` in the {@link module:engine/view/view~View}.\n\t *\n\t * @param {module:engine/model/position~Position} position The model position at the moment of the key press.\n\t * @param {module:engine/view/observer/domeventdata~DomEventData} data Data of the key press.\n\t * @returns {Boolean} `true` when the handler prevented caret movement\n\t */\n\thandleBackwardMovement( position, data ) {\n\t\tconst attribute = this.attribute;\n\n\t\t// When the gravity is already overridden...\n\t\tif ( this._isGravityOverridden ) {\n\t\t\t// ENGAGE 2-SCM & REMOVE SELECTION ATTRIBUTE\n\t\t\t// when about to leave one attribute value and enter another:\n\t\t\t//\n\t\t\t// \t\t<paragraph><$text attribute=\"1\">foo</$text><$text attribute=\"2\">{}bar</$text></paragraph>\n\t\t\t//\n\t\t\t// but DON'T when already in between of them (no attribute selection):\n\t\t\t//\n\t\t\t// \t\t<paragraph><$text attribute=\"1\">foo</$text>{}<$text attribute=\"2\">bar</$text></paragraph>\n\t\t\t//\n\t\t\tif ( isBetweenDifferentValues( position, attribute ) && this._hasSelectionAttribute ) {\n\t\t\t\tthis._preventCaretMovement( data );\n\t\t\t\tthis._restoreGravity();\n\t\t\t\tthis._removeSelectionAttribute();\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// ENGAGE 2-SCM when at any boundary of the attribute:\n\t\t\t//\n\t\t\t// \t\t<paragraph>foo<$text attribute>bar</$text>{}baz</paragraph>\n\t\t\t// \t\t<paragraph>foo<$text attribute>{}bar</$text>baz</paragraph>\n\t\t\t//\n\t\t\telse {\n\t\t\t\tthis._preventCaretMovement( data );\n\t\t\t\tthis._restoreGravity();\n\n\t\t\t\t// REMOVE SELECTION ATRIBUTE at the beginning of the block.\n\t\t\t\t// It's like restoring gravity but towards a non-existent content when\n\t\t\t\t// the gravity is overridden:\n\t\t\t\t//\n\t\t\t\t// \t\t<paragraph><$text attribute>{}bar</$text></paragraph>\n\t\t\t\t//\n\t\t\t\t// becomes:\n\t\t\t\t//\n\t\t\t\t// \t\t<paragraph>{}<$text attribute>bar</$text></paragraph>\n\t\t\t\t//\n\t\t\t\tif ( position.isAtStart ) {\n\t\t\t\t\tthis._removeSelectionAttribute();\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else {\n\t\t\t// ENGAGE 2-SCM when between two different attribute values but selection has no attribute:\n\t\t\t//\n\t\t\t// \t\t<paragraph><$text attribute=\"1\">foo</$text>{}<$text attribute=\"2\">bar</$text></paragraph>\n\t\t\t//\n\t\t\tif ( isBetweenDifferentValues( position, attribute ) && !this._hasSelectionAttribute ) {\n\t\t\t\tthis._preventCaretMovement( data );\n\t\t\t\tthis._setSelectionAttributeFromTheNodeBefore( position );\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// End of block boundary cases:\n\t\t\t//\n\t\t\t// \t\t<paragraph><$text attribute>bar{}</$text></paragraph>\n\t\t\t// \t\t<paragraph><$text attribute>bar</$text>{}</paragraph>\n\t\t\t//\n\t\t\tif ( position.isAtEnd && isAtEndBoundary( position, attribute ) ) {\n\t\t\t\t// DON'T ENGAGE 2-SCM if the selection has the attribute already.\n\t\t\t\t// This is a common selection if set using the mouse.\n\t\t\t\t//\n\t\t\t\t// \t\t<paragraph><$text attribute>bar{}</$text></paragraph>\n\t\t\t\t//\n\t\t\t\tif ( this._hasSelectionAttribute ) {\n\t\t\t\t\t// DON'T ENGAGE 2-SCM if the attribute at the end of the block which has length == 1.\n\t\t\t\t\t// Make sure the selection will not the attribute after it moves backwards.\n\t\t\t\t\t//\n\t\t\t\t\t// \t\t<paragraph>foo<$text attribute>b{}</$text></paragraph>\n\t\t\t\t\t//\n\t\t\t\t\tif ( isStepAfterTheAttributeBoundary( position, attribute ) ) {\n\t\t\t\t\t\t// Skip the automatic gravity restore upon the next selection#change:range event.\n\t\t\t\t\t\t// If not skipped, it would automatically restore the gravity, which should remain\n\t\t\t\t\t\t// overridden.\n\t\t\t\t\t\tthis._skipNextAutomaticGravityRestoration();\n\t\t\t\t\t\tthis._overrideGravity();\n\n\t\t\t\t\t\t// Don't return \"true\" here because we didn't call _preventCaretMovement.\n\t\t\t\t\t\t// Returning here will destabilize the filler logic, which also listens to\n\t\t\t\t\t\t// keydown (and the event would be stopped).\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// ENGAGE 2-SCM if the selection has no attribute. This may happen when the user\n\t\t\t\t// left the attribute using a FORWARD 2-SCM.\n\t\t\t\t//\n\t\t\t\t// \t\t<paragraph><$text attribute>bar</$text>{}</paragraph>\n\t\t\t\t//\n\t\t\t\telse {\n\t\t\t\t\tthis._preventCaretMovement( data );\n\t\t\t\t\tthis._setSelectionAttributeFromTheNodeBefore( position );\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// REMOVE SELECTION ATRIBUTE when restoring gravity towards a non-existent content at the\n\t\t\t// beginning of the block.\n\t\t\t//\n\t\t\t// \t\t<paragraph>{}<$text attribute>bar</$text></paragraph>\n\t\t\t//\n\t\t\tif ( position.isAtStart ) {\n\t\t\t\tif ( this._hasSelectionAttribute ) {\n\t\t\t\t\tthis._removeSelectionAttribute();\n\t\t\t\t\tthis._preventCaretMovement( data );\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// DON'T ENGAGE 2-SCM when about to enter of leave an attribute.\n\t\t\t// We need to check if the caret is a one position before the attribute boundary:\n\t\t\t//\n\t\t\t// \t\t<paragraph>foo<$text attribute>b{}ar</$text>baz</paragraph>\n\t\t\t// \t\t<paragraph>foo<$text attribute>bar</$text>b{}az</paragraph>\n\t\t\t//\n\t\t\tif ( isStepAfterTheAttributeBoundary( position, attribute ) ) {\n\t\t\t\t// Skip the automatic gravity restore upon the next selection#change:range event.\n\t\t\t\t// If not skipped, it would automatically restore the gravity, which should remain\n\t\t\t\t// overridden.\n\t\t\t\tthis._skipNextAutomaticGravityRestoration();\n\t\t\t\tthis._overrideGravity();\n\n\t\t\t\t// Don't return \"true\" here because we didn't call _preventCaretMovement.\n\t\t\t\t// Returning here will destabilize the filler logic, which also listens to\n\t\t\t\t// keydown (and the event would be stopped).\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * `true` when the gravity is overridden for the {@link #attribute}.\n\t *\n\t * @readonly\n\t * @private\n\t * @type {Boolean}\n\t */\n\tget _isGravityOverridden() {\n\t\treturn !!this._overrideUid;\n\t}\n\n\t/**\n\t * `true` when the {@link module:engine/model/selection~Selection} has the {@link #attribute}.\n\t *\n\t * @readonly\n\t * @private\n\t * @type {Boolean}\n\t */\n\tget _hasSelectionAttribute() {\n\t\treturn this._modelSelection.hasAttribute( this.attribute );\n\t}\n\n\t/**\n\t * Overrides the gravity using the {@link module:engine/model/writer~Writer model writer}\n\t * and stores the information about this fact in the {@link #_overrideUid}.\n\t *\n\t * A shorthand for {@link module:engine/model/writer~Writer#overrideSelectionGravity}.\n\t *\n\t * @private\n\t */\n\t_overrideGravity() {\n\t\tthis._overrideUid = this.model.change( writer => writer.overrideSelectionGravity() );\n\t}\n\n\t/**\n\t * Restores the gravity using the {@link module:engine/model/writer~Writer model writer}.\n\t *\n\t * A shorthand for {@link module:engine/model/writer~Writer#restoreSelectionGravity}.\n\t *\n\t * @private\n\t */\n\t_restoreGravity() {\n\t\tthis.model.change( writer => {\n\t\t\twriter.restoreSelectionGravity( this._overrideUid );\n\t\t\tthis._overrideUid = null;\n\t\t} );\n\t}\n\n\t/**\n\t * Prevents the caret movement in the view by calling `preventDefault` on the event data.\n\t *\n\t * @private\n\t */\n\t_preventCaretMovement( data ) {\n\t\tdata.preventDefault();\n\t}\n\n\t/**\n\t * Removes the {@link #attribute} from the selection using using the\n\t * {@link module:engine/model/writer~Writer model writer}.\n\t *\n\t * @private\n\t */\n\t_removeSelectionAttribute() {\n\t\tthis.model.change( writer => {\n\t\t\twriter.removeSelectionAttribute( this.attribute );\n\t\t} );\n\t}\n\n\t/**\n\t * Applies the {@link #attribute} to the current selection using using the\n\t * value from the node before the current position. Uses\n\t * the {@link module:engine/model/writer~Writer model writer}.\n\t *\n\t * @private\n\t * @param {module:engine/model/position~Position} position\n\t */\n\t_setSelectionAttributeFromTheNodeBefore( position ) {\n\t\tconst attribute = this.attribute;\n\n\t\tthis.model.change( writer => {\n\t\t\twriter.setSelectionAttribute( this.attribute, position.nodeBefore.getAttribute( attribute ) );\n\t\t} );\n\t}\n\n\t/**\n\t * Skips the next automatic selection gravity restoration upon the\n\t * {@link module:engine/model/selection~Selection#event:change:range} event.\n\t *\n\t * See {@link #_isNextGravityRestorationSkipped}.\n\t *\n\t * @private\n\t */\n\t_skipNextAutomaticGravityRestoration() {\n\t\tthis._isNextGravityRestorationSkipped = true;\n\t}\n}\n\n// @param {module:engine/model/position~Position} position\n// @param {String} attribute\n// @returns {Boolean} `true` when position between the nodes sticks to the bound of text with given attribute.\nfunction isAtBoundary( position, attribute ) {\n\treturn isAtStartBoundary( position, attribute ) || isAtEndBoundary( position, attribute );\n}\n\n// @param {module:engine/model/position~Position} position\n// @param {String} attribute\nfunction isAtStartBoundary( position, attribute ) {\n\tconst { nodeBefore, nodeAfter } = position;\n\tconst isAttrBefore = nodeBefore ? nodeBefore.hasAttribute( attribute ) : false;\n\tconst isAttrAfter = nodeAfter ? nodeAfter.hasAttribute( attribute ) : false;\n\n\treturn isAttrAfter && ( !isAttrBefore || nodeBefore.getAttribute( attribute ) !== nodeAfter.getAttribute( attribute ) );\n}\n\n// @param {module:engine/model/position~Position} position\n// @param {String} attribute\nfunction isAtEndBoundary( position, attribute ) {\n\tconst { nodeBefore, nodeAfter } = position;\n\tconst isAttrBefore = nodeBefore ? nodeBefore.hasAttribute( attribute ) : false;\n\tconst isAttrAfter = nodeAfter ? nodeAfter.hasAttribute( attribute ) : false;\n\n\treturn isAttrBefore && ( !isAttrAfter || nodeBefore.getAttribute( attribute ) !== nodeAfter.getAttribute( attribute ) );\n}\n\n// @param {module:engine/model/position~Position} position\n// @param {String} attribute\nfunction isBetweenDifferentValues( position, attribute ) {\n\tconst { nodeBefore, nodeAfter } = position;\n\tconst isAttrBefore = nodeBefore ? nodeBefore.hasAttribute( attribute ) : false;\n\tconst isAttrAfter = nodeAfter ? nodeAfter.hasAttribute( attribute ) : false;\n\n\tif ( !isAttrAfter || !isAttrBefore ) {\n\t\treturn;\n\t}\n\n\treturn nodeAfter.getAttribute( attribute ) !== nodeBefore.getAttribute( attribute );\n}\n\n// @param {module:engine/model/position~Position} position\n// @param {String} attribute\nfunction isStepAfterTheAttributeBoundary( position, attribute ) {\n\treturn isAtBoundary( position.getShiftedBy( -1 ), attribute );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 link/linkediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport LinkCommand from './linkcommand';\nimport UnlinkCommand from './unlinkcommand';\nimport { createLinkElement, ensureSafeUrl, getLocalizedDecorators, normalizeDecorators } from './utils';\nimport AutomaticDecorators from './utils/automaticdecorators';\nimport ManualDecorator from './utils/manualdecorator';\nimport bindTwoStepCaretToAttribute from '@ckeditor/ckeditor5-engine/src/utils/bindtwostepcarettoattribute';\nimport findLinkRange from './findlinkrange';\nimport '../theme/link.css';\n\nconst HIGHLIGHT_CLASS = 'ck-link_selected';\nconst DECORATOR_AUTOMATIC = 'automatic';\nconst DECORATOR_MANUAL = 'manual';\nconst EXTERNAL_LINKS_REGEXP = /^(https?:)?\\/\\//;\n\n/**\n * The link engine feature.\n *\n * It introduces the `linkHref=\"url\"` attribute in the model which renders to the view as a `<a href=\"url\">` element\n * as well as `'link'` and `'unlink'` commands.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class LinkEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'LinkEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\teditor.config.define( 'link', {\n\t\t\taddTargetToExternalLinks: false\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst locale = editor.locale;\n\n\t\t// Allow link attribute on all inline nodes.\n\t\teditor.model.schema.extend( '$text', { allowAttributes: 'linkHref' } );\n\n\t\teditor.conversion.for( 'dataDowncast' )\n\t\t\t.attributeToElement( { model: 'linkHref', view: createLinkElement } );\n\n\t\teditor.conversion.for( 'editingDowncast' )\n\t\t\t.attributeToElement( { model: 'linkHref', view: ( href, writer ) => {\n\t\t\t\treturn createLinkElement( ensureSafeUrl( href ), writer );\n\t\t\t} } );\n\n\t\teditor.conversion.for( 'upcast' )\n\t\t\t.elementToAttribute( {\n\t\t\t\tview: {\n\t\t\t\t\tname: 'a',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\thref: true\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmodel: {\n\t\t\t\t\tkey: 'linkHref',\n\t\t\t\t\tvalue: viewElement => viewElement.getAttribute( 'href' )\n\t\t\t\t}\n\t\t\t} );\n\n\t\t// Create linking commands.\n\t\teditor.commands.add( 'link', new LinkCommand( editor ) );\n\t\teditor.commands.add( 'unlink', new UnlinkCommand( editor ) );\n\n\t\tconst linkDecorators = getLocalizedDecorators( editor.t, normalizeDecorators( editor.config.get( 'link.decorators' ) ) );\n\n\t\tthis._enableAutomaticDecorators( linkDecorators.filter( item => item.mode === DECORATOR_AUTOMATIC ) );\n\t\tthis._enableManualDecorators( linkDecorators.filter( item => item.mode === DECORATOR_MANUAL ) );\n\n\t\t// Enable two-step caret movement for `linkHref` attribute.\n\t\tbindTwoStepCaretToAttribute( {\n\t\t\tview: editor.editing.view,\n\t\t\tmodel: editor.model,\n\t\t\temitter: this,\n\t\t\tattribute: 'linkHref',\n\t\t\tlocale\n\t\t} );\n\n\t\t// Setup highlight over selected link.\n\t\tthis._setupLinkHighlight();\n\t}\n\n\t/**\n\t * Processes an array of configured {@link module:link/link~LinkDecoratorAutomaticDefinition automatic decorators}\n\t * and registers a {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast dispatcher}\n\t * for each one of them. Downcast dispatchers are obtained using the\n\t * {@link module:link/utils~AutomaticDecorators#getDispatcher} method.\n\t *\n\t * **Note**: This method also activates the automatic external link decorator if enabled with\n\t * {@link module:link/link~LinkConfig#addTargetToExternalLinks `config.link.addTargetToExternalLinks`}.\n\t *\n\t * @private\n\t * @param {Array.<module:link/link~LinkDecoratorAutomaticDefinition>} automaticDecoratorDefinitions\n\t */\n\t_enableAutomaticDecorators( automaticDecoratorDefinitions ) {\n\t\tconst editor = this.editor;\n\t\tconst automaticDecorators = new AutomaticDecorators();\n\n\t\t// Adds a default decorator for external links.\n\t\tif ( editor.config.get( 'link.addTargetToExternalLinks' ) ) {\n\t\t\tautomaticDecorators.add( {\n\t\t\t\tid: 'linkIsExternal',\n\t\t\t\tmode: DECORATOR_AUTOMATIC,\n\t\t\t\tcallback: url => EXTERNAL_LINKS_REGEXP.test( url ),\n\t\t\t\tattributes: {\n\t\t\t\t\ttarget: '_blank',\n\t\t\t\t\trel: 'noopener noreferrer'\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tautomaticDecorators.add( automaticDecoratorDefinitions );\n\n\t\tif ( automaticDecorators.length ) {\n\t\t\teditor.conversion.for( 'downcast' ).add( automaticDecorators.getDispatcher() );\n\t\t}\n\t}\n\n\t/**\n\t * Processes an array of configured {@link module:link/link~LinkDecoratorManualDefinition manual decorators},\n\t * transforms them into {@link module:link/utils~ManualDecorator} instances and stores them in the\n\t * {@link module:link/linkcommand~LinkCommand#manualDecorators} collection (a model for manual decorators state).\n\t *\n\t * Also registers an {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToElement attribute-to-element}\n\t * converter for each manual decorator and extends the {@link module:engine/model/schema~Schema model's schema}\n\t * with adequate model attributes.\n\t *\n\t * @private\n\t * @param {Array.<module:link/link~LinkDecoratorManualDefinition>} manualDecoratorDefinitions\n\t */\n\t_enableManualDecorators( manualDecoratorDefinitions ) {\n\t\tif ( !manualDecoratorDefinitions.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst editor = this.editor;\n\t\tconst command = editor.commands.get( 'link' );\n\t\tconst manualDecorators = command.manualDecorators;\n\n\t\tmanualDecoratorDefinitions.forEach( decorator => {\n\t\t\teditor.model.schema.extend( '$text', { allowAttributes: decorator.id } );\n\n\t\t\t// Keeps reference to manual decorator to decode its name to attributes during downcast.\n\t\t\tmanualDecorators.add( new ManualDecorator( decorator ) );\n\n\t\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t\t\t\tmodel: decorator.id,\n\t\t\t\tview: ( manualDecoratorName, writer ) => {\n\t\t\t\t\tif ( manualDecoratorName ) {\n\t\t\t\t\t\tconst attributes = manualDecorators.get( decorator.id ).attributes;\n\t\t\t\t\t\tconst element = writer.createAttributeElement( 'a', attributes, { priority: 5 } );\n\t\t\t\t\t\twriter.setCustomProperty( 'link', true, element );\n\n\t\t\t\t\t\treturn element;\n\t\t\t\t\t}\n\t\t\t\t} } );\n\n\t\t\teditor.conversion.for( 'upcast' ).elementToAttribute( {\n\t\t\t\tview: {\n\t\t\t\t\tname: 'a',\n\t\t\t\t\tattributes: manualDecorators.get( decorator.id ).attributes\n\t\t\t\t},\n\t\t\t\tmodel: {\n\t\t\t\t\tkey: decorator.id\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t/**\n\t * Adds a visual highlight style to a link in which the selection is anchored.\n\t * Together with two-step caret movement, they indicate that the user is typing inside the link.\n\t *\n\t * Highlight is turned on by adding the `.ck-link_selected` class to the link in the view:\n\t *\n\t * * The class is removed before the conversion has started, as callbacks added with the `'highest'` priority\n\t * to {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher} events.\n\t * * The class is added in the view post fixer, after other changes in the model tree were converted to the view.\n\t *\n\t * This way, adding and removing the highlight does not interfere with conversion.\n\t *\n\t * @private\n\t */\n\t_setupLinkHighlight() {\n\t\tconst editor = this.editor;\n\t\tconst view = editor.editing.view;\n\t\tconst highlightedLinks = new Set();\n\n\t\t// Adding the class.\n\t\tview.document.registerPostFixer( writer => {\n\t\t\tconst selection = editor.model.document.selection;\n\t\t\tlet changed = false;\n\n\t\t\tif ( selection.hasAttribute( 'linkHref' ) ) {\n\t\t\t\tconst modelRange = findLinkRange( selection.getFirstPosition(), selection.getAttribute( 'linkHref' ), editor.model );\n\t\t\t\tconst viewRange = editor.editing.mapper.toViewRange( modelRange );\n\n\t\t\t\t// There might be multiple `a` elements in the `viewRange`, for example, when the `a` element is\n\t\t\t\t// broken by a UIElement.\n\t\t\t\tfor ( const item of viewRange.getItems() ) {\n\t\t\t\t\tif ( item.is( 'a' ) && !item.hasClass( HIGHLIGHT_CLASS ) ) {\n\t\t\t\t\t\twriter.addClass( HIGHLIGHT_CLASS, item );\n\t\t\t\t\t\thighlightedLinks.add( item );\n\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn changed;\n\t\t} );\n\n\t\t// Removing the class.\n\t\teditor.conversion.for( 'editingDowncast' ).add( dispatcher => {\n\t\t\t// Make sure the highlight is removed on every possible event, before conversion is started.\n\t\t\tdispatcher.on( 'insert', removeHighlight, { priority: 'highest' } );\n\t\t\tdispatcher.on( 'remove', removeHighlight, { priority: 'highest' } );\n\t\t\tdispatcher.on( 'attribute', removeHighlight, { priority: 'highest' } );\n\t\t\tdispatcher.on( 'selection', removeHighlight, { priority: 'highest' } );\n\n\t\t\tfunction removeHighlight() {\n\t\t\t\tview.change( writer => {\n\t\t\t\t\tfor ( const item of highlightedLinks.values() ) {\n\t\t\t\t\t\twriter.removeClass( HIGHLIGHT_CLASS, item );\n\t\t\t\t\t\thighlightedLinks.delete( item );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t}\n}\n","\n/**\n * @license Copyright (c) 2003-2019, 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 engine/view/observer/clickobserver\n */\n\nimport DomEventObserver from './domeventobserver';\n\n/**\n * {@link module:engine/view/document~Document#event:click Click} event observer.\n *\n * Note that this observer is not available by default. To make it available it needs to be added to\n * {@link module:engine/view/view~View view controller}\n * by a {@link module:engine/view/view~View#addObserver} method.\n *\n * @extends module:engine/view/observer/domeventobserver~DomEventObserver\n */\nexport default class ClickObserver extends DomEventObserver {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tthis.domEventType = 'click';\n\t}\n\n\tonDomEvent( domEvent ) {\n\t\tthis.fire( domEvent.type, domEvent );\n\t}\n}\n\n/**\n * Fired when one of the editables has been clicked.\n *\n * Introduced by {@link module:engine/view/observer/clickobserver~ClickObserver}.\n *\n * Note that this event is not available by default. To make it available\n * {@link module:engine/view/observer/clickobserver~ClickObserver} needs to be added\n * to {@link module:engine/view/view~View} by a {@link module:engine/view/view~View#addObserver} method.\n *\n * @see module:engine/view/observer/clickobserver~ClickObserver\n * @event module:engine/view/document~Document#event:click\n * @param {module:engine/view/observer/domeventdata~DomEventData} data Event data.\n */\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module link/ui/linkformview\n */\nimport View from '@ckeditor/ckeditor5-ui/src/view';\nimport ViewCollection from '@ckeditor/ckeditor5-ui/src/viewcollection';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport SwitchButtonView from '@ckeditor/ckeditor5-ui/src/button/switchbuttonview';\nimport LabeledInputView from '@ckeditor/ckeditor5-ui/src/labeledinput/labeledinputview';\nimport InputTextView from '@ckeditor/ckeditor5-ui/src/inputtext/inputtextview';\nimport submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\nimport FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';\nimport KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';\nimport checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg';\nimport cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg';\nimport '../../theme/linkform.css';\n/**\n * The link form view controller class.\n *\n * See {@link module:link/ui/linkformview~LinkFormView}.\n *\n * @extends module:ui/view~View\n */\nexport default class LinkFormView extends View {\n /**\n\t * Creates an instance of the {@link module:link/ui/linkformview~LinkFormView} class.\n\t *\n\t * Also see {@link #render}.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The localization services instance.\n\t * @param {module:utils/collection~Collection} [manualDecorators] Reference to manual decorators in\n\t * {@link module:link/linkcommand~LinkCommand#manualDecorators}.\n\t */\n constructor(locale, manualDecorators = []) {\n super(locale);\n const t = locale.t;\n /**\n\t\t * Tracks information about DOM focus in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n this.focusTracker = new FocusTracker();\n /**\n\t\t * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler}\n\t\t */\n this.keystrokes = new KeystrokeHandler();\n /**\n\t\t * The URL input view.\n\t\t *\n\t\t * @member {module:ui/labeledinput/labeledinputview~LabeledInputView}\n\t\t */\n this.urlInputView = this._createUrlInput();\n /**\n\t\t * The Save button view.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n this.saveButtonView = this._createButton(t('av'), checkIcon, 'ck-button-save');\n this.saveButtonView.type = 'submit';\n /**\n\t\t * The Cancel button view.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n this.cancelButtonView = this._createButton(t('aw'), cancelIcon, 'ck-button-cancel', 'cancel');\n /**\n\t\t * A collection of {@link module:ui/button/switchbuttonview~SwitchButtonView},\n\t\t * which corresponds to {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators}\n\t\t * configured in the editor.\n\t\t *\n\t\t * @private\n\t\t * @readonly\n\t\t * @type {module:ui/viewcollection~ViewCollection}\n\t\t */\n this._manualDecoratorSwitches = this._createManualDecoratorSwitches(manualDecorators);\n /**\n\t\t * A collection of child views in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:ui/viewcollection~ViewCollection}\n\t\t */\n this.children = this._createFormChildren(manualDecorators);\n /**\n\t\t * A collection of views that can be focused in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this._focusables = new ViewCollection();\n /**\n\t\t * Helps cycling over {@link #_focusables} in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/focuscycler~FocusCycler}\n\t\t */\n this._focusCycler = new FocusCycler({\n focusables: this._focusables,\n focusTracker: this.focusTracker,\n keystrokeHandler: this.keystrokes,\n actions: {\n // Navigate form fields backwards using the Shift + Tab keystroke.\n focusPrevious: 'shift + tab',\n // Navigate form fields forwards using the Tab key.\n focusNext: 'tab'\n }\n });\n const classList = [\n 'ck',\n 'ck-link-form'\n ];\n if (manualDecorators.length) {\n classList.push('ck-link-form_layout-vertical');\n }\n this.setTemplate({\n tag: 'form',\n attributes: {\n class: classList,\n // https://github.com/ckeditor/ckeditor5-link/issues/90\n tabindex: '-1'\n },\n children: this.children\n });\n }\n /**\n\t * Obtains the state of the {@link module:ui/button/switchbuttonview~SwitchButtonView switch buttons} representing\n\t * {@link module:link/linkcommand~LinkCommand#manualDecorators manual link decorators}\n\t * in the {@link module:link/ui/linkformview~LinkFormView}.\n\t *\n\t * @returns {Object.<String,Boolean>} Key-value pairs, where the key is the name of the decorator and the value is\n\t * its state.\n\t */\n getDecoratorSwitchesState() {\n return Array.from(this._manualDecoratorSwitches).reduce((accumulator, switchButton) => {\n accumulator[switchButton.name] = switchButton.isOn;\n return accumulator;\n }, {});\n }\n /**\n\t * @inheritDoc\n\t */\n render() {\n super.render();\n submitHandler({ view: this });\n const childViews = [\n this.urlInputView,\n ...this._manualDecoratorSwitches,\n this.saveButtonView,\n this.cancelButtonView\n ];\n childViews.forEach(v => {\n // Register the view as focusable.\n this._focusables.add(v);\n // Register the view in the focus tracker.\n this.focusTracker.add(v.element);\n });\n // Start listening for the keystrokes coming from #element.\n this.keystrokes.listenTo(this.element);\n }\n /**\n\t * Focuses the fist {@link #_focusables} in the form.\n\t */\n focus() {\n this._focusCycler.focusFirst();\n }\n /**\n\t * Creates a labeled input view.\n\t *\n\t * @private\n\t * @returns {module:ui/labeledinput/labeledinputview~LabeledInputView} Labeled input view instance.\n\t */\n _createUrlInput() {\n const t = this.locale.t;\n const labeledInput = new LabeledInputView(this.locale, InputTextView);\n labeledInput.label = t('be');\n labeledInput.inputView.placeholder = 'https://example.com';\n return labeledInput;\n }\n /**\n\t * Creates a button view.\n\t *\n\t * @private\n\t * @param {String} label The button label.\n\t * @param {String} icon The button icon.\n\t * @param {String} className The additional button CSS class name.\n\t * @param {String} [eventName] An event name that the `ButtonView#execute` event will be delegated to.\n\t * @returns {module:ui/button/buttonview~ButtonView} The button view instance.\n\t */\n _createButton(label, icon, className, eventName) {\n const button = new ButtonView(this.locale);\n button.set({\n label,\n icon,\n tooltip: true\n });\n button.extendTemplate({ attributes: { class: className } });\n if (eventName) {\n button.delegate('execute').to(this, eventName);\n }\n return button;\n }\n /**\n\t * Populates {@link module:ui/viewcollection~ViewCollection} of {@link module:ui/button/switchbuttonview~SwitchButtonView}\n\t * made based on {@link module:link/linkcommand~LinkCommand#manualDecorators}.\n\t *\n\t * @private\n\t * @param {module:utils/collection~Collection} manualDecorators A reference to the\n\t * collection of manual decorators stored in the link command.\n\t * @returns {module:ui/viewcollection~ViewCollection} of switch buttons.\n\t */\n _createManualDecoratorSwitches(manualDecorators) {\n const switches = this.createCollection();\n for (const manualDecorator of manualDecorators) {\n const switchButton = new SwitchButtonView(this.locale);\n switchButton.set({\n name: manualDecorator.id,\n label: manualDecorator.label,\n withText: true\n });\n switchButton.bind('isOn').to(manualDecorator, 'value');\n switchButton.on('execute', () => {\n manualDecorator.set('value', !switchButton.isOn);\n });\n switches.add(switchButton);\n }\n return switches;\n }\n /**\n\t * Populates the {@link #children} collection of the form.\n\t *\n\t * If {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators} are configured in the editor, it creates an\n\t * additional `View` wrapping all {@link #_manualDecoratorSwitches} switch buttons corresponding\n\t * to these decorators.\n\t *\n\t * @private\n\t * @param {module:utils/collection~Collection} manualDecorators A reference to\n\t * the collection of manual decorators stored in the link command.\n\t * @returns {module:ui/viewcollection~ViewCollection} The children of link form view.\n\t */\n _createFormChildren(manualDecorators) {\n const children = this.createCollection();\n children.add(this.urlInputView);\n if (manualDecorators.length) {\n const additionalButtonsView = new View();\n additionalButtonsView.setTemplate({\n tag: 'ul',\n children: this._manualDecoratorSwitches.map(switchButton => ({\n tag: 'li',\n children: [switchButton],\n attributes: {\n class: [\n 'ck',\n 'ck-list__item'\n ]\n }\n })),\n attributes: {\n class: [\n 'ck',\n 'ck-reset',\n 'ck-list'\n ]\n }\n });\n children.add(additionalButtonsView);\n }\n children.add(this.saveButtonView);\n children.add(this.cancelButtonView);\n return children;\n }\n} /**\n * Fired when the form view is submitted (when one of the children triggered the submit event),\n * for example with a click on {@link #saveButtonView}.\n *\n * @event submit\n */\n /**\n * Fired when the form view is canceled, for example with a click on {@link #cancelButtonView}.\n *\n * @event cancel\n */","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M11.077 15l.991-1.416a.75.75 0 1 1 1.229.86l-1.148 1.64a.748.748 0 0 1-.217.206 5.251 5.251 0 0 1-8.503-5.955.741.741 0 0 1 .12-.274l1.147-1.639a.75.75 0 1 1 1.228.86L4.933 10.7l.006.003a3.75 3.75 0 0 0 6.132 4.294l.006.004zm5.494-5.335a.748.748 0 0 1-.12.274l-1.147 1.639a.75.75 0 1 1-1.228-.86l.86-1.23a3.75 3.75 0 0 0-6.144-4.301l-.86 1.229a.75.75 0 0 1-1.229-.86l1.148-1.64a.748.748 0 0 1 .217-.206 5.251 5.251 0 0 1 8.503 5.955zm-4.563-2.532a.75.75 0 0 1 .184 1.045l-3.155 4.505a.75.75 0 1 1-1.229-.86l3.155-4.506a.75.75 0 0 1 1.045-.184zm4.919 10.562l-1.414 1.414a.75.75 0 1 1-1.06-1.06l1.414-1.415-1.415-1.414a.75.75 0 0 1 1.061-1.06l1.414 1.414 1.414-1.415a.75.75 0 0 1 1.061 1.061l-1.414 1.414 1.414 1.415a.75.75 0 0 1-1.06 1.06l-1.415-1.414z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M7.3 17.37l-.061.088a1.518 1.518 0 0 1-.934.535l-4.178.663-.806-4.153a1.495 1.495 0 0 1 .187-1.058l.056-.086L8.77 2.639c.958-1.351 2.803-1.076 4.296-.03 1.497 1.047 2.387 2.693 1.433 4.055L7.3 17.37zM9.14 4.728l-5.545 8.346 3.277 2.294 5.544-8.346L9.14 4.728zM6.07 16.512l-3.276-2.295.53 2.73 2.746-.435zM9.994 3.506L13.271 5.8c.316-.452-.16-1.333-1.065-1.966-.905-.634-1.895-.78-2.212-.328zM8 18.5L9.375 17H19v1.5H8z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module link/ui/linkactionsview\n */\nimport View from '@ckeditor/ckeditor5-ui/src/view';\nimport ViewCollection from '@ckeditor/ckeditor5-ui/src/viewcollection';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\nimport FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';\nimport KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';\nimport { ensureSafeUrl } from '../utils';\nimport unlinkIcon from '../../theme/icons/unlink.svg';\nimport pencilIcon from '@ckeditor/ckeditor5-core/theme/icons/pencil.svg';\nimport '../../theme/linkactions.css';\n/**\n * The link actions view class. This view displays the link preview, allows\n * unlinking or editing the link.\n *\n * @extends module:ui/view~View\n */\nexport default class LinkActionsView extends View {\n /**\n\t * @inheritDoc\n\t */\n constructor(locale) {\n super(locale);\n const t = locale.t;\n /**\n\t\t * Tracks information about DOM focus in the actions.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n this.focusTracker = new FocusTracker();\n /**\n\t\t * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler}\n\t\t */\n this.keystrokes = new KeystrokeHandler();\n /**\n\t\t * The href preview view.\n\t\t *\n\t\t * @member {module:ui/view~View}\n\t\t */\n this.previewButtonView = this._createPreviewButton();\n /**\n\t\t * The unlink button view.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n this.unlinkButtonView = this._createButton(t('ba'), unlinkIcon, 'unlink');\n /**\n\t\t * The edit link button view.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n this.editButtonView = this._createButton(t('bb'), pencilIcon, 'edit');\n /**\n\t\t * The value of the \"href\" attribute of the link to use in the {@link #previewButtonView}.\n\t\t *\n\t\t * @observable\n\t\t * @member {String}\n\t\t */\n this.set('href');\n /**\n\t\t * A collection of views that can be focused in the view.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n this._focusables = new ViewCollection();\n /**\n\t\t * Helps cycling over {@link #_focusables} in the view.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/focuscycler~FocusCycler}\n\t\t */\n this._focusCycler = new FocusCycler({\n focusables: this._focusables,\n focusTracker: this.focusTracker,\n keystrokeHandler: this.keystrokes,\n actions: {\n // Navigate fields backwards using the Shift + Tab keystroke.\n focusPrevious: 'shift + tab',\n // Navigate fields forwards using the Tab key.\n focusNext: 'tab'\n }\n });\n this.setTemplate({\n tag: 'div',\n attributes: {\n class: [\n 'ck',\n 'ck-link-actions'\n ],\n // https://github.com/ckeditor/ckeditor5-link/issues/90\n tabindex: '-1'\n },\n children: [\n this.previewButtonView,\n this.editButtonView,\n this.unlinkButtonView\n ]\n });\n }\n /**\n\t * @inheritDoc\n\t */\n render() {\n super.render();\n const childViews = [\n this.previewButtonView,\n this.editButtonView,\n this.unlinkButtonView\n ];\n childViews.forEach(v => {\n // Register the view as focusable.\n this._focusables.add(v);\n // Register the view in the focus tracker.\n this.focusTracker.add(v.element);\n });\n // Start listening for the keystrokes coming from #element.\n this.keystrokes.listenTo(this.element);\n }\n /**\n\t * Focuses the fist {@link #_focusables} in the actions.\n\t */\n focus() {\n this._focusCycler.focusFirst();\n }\n /**\n\t * Creates a button view.\n\t *\n\t * @private\n\t * @param {String} label The button label.\n\t * @param {String} icon The button icon.\n\t * @param {String} [eventName] An event name that the `ButtonView#execute` event will be delegated to.\n\t * @returns {module:ui/button/buttonview~ButtonView} The button view instance.\n\t */\n _createButton(label, icon, eventName) {\n const button = new ButtonView(this.locale);\n button.set({\n label,\n icon,\n tooltip: true\n });\n button.delegate('execute').to(this, eventName);\n return button;\n }\n /**\n\t * Creates a link href preview button.\n\t *\n\t * @private\n\t * @returns {module:ui/button/buttonview~ButtonView} The button view instance.\n\t */\n _createPreviewButton() {\n const button = new ButtonView(this.locale);\n const bind = this.bindTemplate;\n const t = this.t;\n button.set({\n withText: true,\n tooltip: t('bc')\n });\n button.extendTemplate({\n attributes: {\n class: [\n 'ck',\n 'ck-link-actions__preview'\n ],\n href: bind.to('href', href => href && ensureSafeUrl(href)),\n target: '_blank'\n }\n });\n button.bind('label').to(this, 'href', href => {\n return href || t('bd');\n });\n button.bind('isEnabled').to(this, 'href', href => !!href);\n button.template.tag = 'a';\n button.template.eventListeners = {};\n return button;\n }\n} /**\n * Fired when the {@link #editButtonView} is clicked.\n *\n * @event edit\n */\n /**\n * Fired when the {@link #unlinkButtonView} is clicked.\n *\n * @event unlink\n */","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M11.077 15l.991-1.416a.75.75 0 1 1 1.229.86l-1.148 1.64a.748.748 0 0 1-.217.206 5.251 5.251 0 0 1-8.503-5.955.741.741 0 0 1 .12-.274l1.147-1.639a.75.75 0 1 1 1.228.86L4.933 10.7l.006.003a3.75 3.75 0 0 0 6.132 4.294l.006.004zm5.494-5.335a.748.748 0 0 1-.12.274l-1.147 1.639a.75.75 0 1 1-1.228-.86l.86-1.23a3.75 3.75 0 0 0-6.144-4.301l-.86 1.229a.75.75 0 0 1-1.229-.86l1.148-1.64a.748.748 0 0 1 .217-.206 5.251 5.251 0 0 1 8.503 5.955zm-4.563-2.532a.75.75 0 0 1 .184 1.045l-3.155 4.505a.75.75 0 1 1-1.229-.86l3.155-4.506a.75.75 0 0 1 1.045-.184z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module link/linkui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ClickObserver from '@ckeditor/ckeditor5-engine/src/view/observer/clickobserver';\nimport { isLinkElement } from './utils';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\nimport clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport LinkFormView from './ui/linkformview';\nimport LinkActionsView from './ui/linkactionsview';\nimport linkIcon from '../theme/icons/link.svg';\nconst linkKeystroke = 'Ctrl+K';\n/**\n * The link UI plugin. It introduces the `'link'` and `'unlink'` buttons and support for the <kbd>Ctrl+K</kbd> keystroke.\n *\n * It uses the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class LinkUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get requires() {\n return [ContextualBalloon];\n }\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'LinkUI';\n }\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n editor.editing.view.addObserver(ClickObserver);\n /**\n\t\t * The actions view displayed inside of the balloon.\n\t\t *\n\t\t * @member {module:link/ui/linkactionsview~LinkActionsView}\n\t\t */\n this.actionsView = this._createActionsView();\n /**\n\t\t * The form view displayed inside the balloon.\n\t\t *\n\t\t * @member {module:link/ui/linkformview~LinkFormView}\n\t\t */\n this.formView = this._createFormView();\n /**\n\t\t * The contextual balloon plugin instance.\n\t\t *\n\t\t * @private\n\t\t * @member {module:ui/panel/balloon/contextualballoon~ContextualBalloon}\n\t\t */\n this._balloon = editor.plugins.get(ContextualBalloon);\n // Create toolbar buttons.\n this._createToolbarLinkButton();\n // Attach lifecycle actions to the the balloon.\n this._enableUserBalloonInteractions();\n }\n /**\n\t * @inheritDoc\n\t */\n destroy() {\n super.destroy();\n // Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).\n this.formView.destroy();\n }\n /**\n\t * Creates the {@link module:link/ui/linkactionsview~LinkActionsView} instance.\n\t *\n\t * @private\n\t * @returns {module:link/ui/linkactionsview~LinkActionsView} The link actions view instance.\n\t */\n _createActionsView() {\n const editor = this.editor;\n const actionsView = new LinkActionsView(editor.locale);\n const linkCommand = editor.commands.get('link');\n const unlinkCommand = editor.commands.get('unlink');\n actionsView.bind('href').to(linkCommand, 'value');\n actionsView.editButtonView.bind('isEnabled').to(linkCommand);\n actionsView.unlinkButtonView.bind('isEnabled').to(unlinkCommand);\n // Execute unlink command after clicking on the \"Edit\" button.\n this.listenTo(actionsView, 'edit', () => {\n this._addFormView();\n });\n // Execute unlink command after clicking on the \"Unlink\" button.\n this.listenTo(actionsView, 'unlink', () => {\n editor.execute('unlink');\n this._hideUI();\n });\n // Close the panel on esc key press when the **actions have focus**.\n actionsView.keystrokes.set('Esc', (data, cancel) => {\n this._hideUI();\n cancel();\n });\n // Open the form view on Ctrl+K when the **actions have focus**..\n actionsView.keystrokes.set(linkKeystroke, (data, cancel) => {\n this._addFormView();\n cancel();\n });\n return actionsView;\n }\n /**\n\t * Creates the {@link module:link/ui/linkformview~LinkFormView} instance.\n\t *\n\t * @private\n\t * @returns {module:link/ui/linkformview~LinkFormView} The link form view instance.\n\t */\n _createFormView() {\n const editor = this.editor;\n const linkCommand = editor.commands.get('link');\n const formView = new LinkFormView(editor.locale, linkCommand.manualDecorators);\n formView.urlInputView.bind('value').to(linkCommand, 'value');\n // Form elements should be read-only when corresponding commands are disabled.\n formView.urlInputView.bind('isReadOnly').to(linkCommand, 'isEnabled', value => !value);\n formView.saveButtonView.bind('isEnabled').to(linkCommand);\n // Execute link command after clicking the \"Save\" button.\n this.listenTo(formView, 'submit', () => {\n editor.execute('link', formView.urlInputView.inputView.element.value, formView.getDecoratorSwitchesState());\n this._closeFormView();\n });\n // Hide the panel after clicking the \"Cancel\" button.\n this.listenTo(formView, 'cancel', () => {\n this._closeFormView();\n });\n // Close the panel on esc key press when the **form has focus**.\n formView.keystrokes.set('Esc', (data, cancel) => {\n this._closeFormView();\n cancel();\n });\n return formView;\n }\n /**\n\t * Creates a toolbar Link button. Clicking this button will show\n\t * a {@link #_balloon} attached to the selection.\n\t *\n\t * @private\n\t */\n _createToolbarLinkButton() {\n const editor = this.editor;\n const linkCommand = editor.commands.get('link');\n const t = editor.t;\n // Handle the `Ctrl+K` keystroke and show the panel.\n editor.keystrokes.set(linkKeystroke, (keyEvtData, cancel) => {\n // Prevent focusing the search bar in FF and opening new tab in Edge. #153, #154.\n cancel();\n if (linkCommand.isEnabled) {\n this._showUI(true);\n }\n });\n editor.ui.componentFactory.add('link', locale => {\n const button = new ButtonView(locale);\n button.isEnabled = true;\n button.label = t('an');\n button.icon = linkIcon;\n button.keystroke = linkKeystroke;\n button.tooltip = true;\n button.isToggleable = true;\n // Bind button to the command.\n button.bind('isEnabled').to(linkCommand, 'isEnabled');\n button.bind('isOn').to(linkCommand, 'value', value => !!value);\n // Show the panel on button click.\n this.listenTo(button, 'execute', () => this._showUI(true));\n return button;\n });\n }\n /**\n\t * Attaches actions that control whether the balloon panel containing the\n\t * {@link #formView} is visible or not.\n\t *\n\t * @private\n\t */\n _enableUserBalloonInteractions() {\n const viewDocument = this.editor.editing.view.document;\n // Handle click on view document and show panel when selection is placed inside the link element.\n // Keep panel open until selection will be inside the same link element.\n this.listenTo(viewDocument, 'click', () => {\n const parentLink = this._getSelectedLinkElement();\n if (parentLink) {\n // Then show panel but keep focus inside editor editable.\n this._showUI();\n }\n });\n // Focus the form if the balloon is visible and the Tab key has been pressed.\n this.editor.keystrokes.set('Tab', (data, cancel) => {\n if (this._areActionsVisible && !this.actionsView.focusTracker.isFocused) {\n this.actionsView.focus();\n cancel();\n }\n }, {\n // Use the high priority because the link UI navigation is more important\n // than other feature's actions, e.g. list indentation.\n // https://github.com/ckeditor/ckeditor5-link/issues/146\n priority: 'high'\n });\n // Close the panel on the Esc key press when the editable has focus and the balloon is visible.\n this.editor.keystrokes.set('Esc', (data, cancel) => {\n if (this._isUIVisible) {\n this._hideUI();\n cancel();\n }\n });\n // Close on click outside of balloon panel element.\n clickOutsideHandler({\n emitter: this.formView,\n activator: () => this._isUIInPanel,\n contextElements: [this._balloon.view.element],\n callback: () => this._hideUI()\n });\n }\n /**\n\t * Adds the {@link #actionsView} to the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n _addActionsView() {\n if (this._areActionsInPanel) {\n return;\n }\n this._balloon.add({\n view: this.actionsView,\n position: this._getBalloonPositionData()\n });\n }\n /**\n\t * Adds the {@link #formView} to the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n _addFormView() {\n if (this._isFormInPanel) {\n return;\n }\n const editor = this.editor;\n const linkCommand = editor.commands.get('link');\n this._balloon.add({\n view: this.formView,\n position: this._getBalloonPositionData()\n });\n // Select input when form view is currently visible.\n if (this._balloon.visibleView === this.formView) {\n this.formView.urlInputView.select();\n }\n // Make sure that each time the panel shows up, the URL field remains in sync with the value of\n // the command. If the user typed in the input, then canceled the balloon (`urlInputView#value` stays\n // unaltered) and re-opened it without changing the value of the link command (e.g. because they\n // clicked the same link), they would see the old value instead of the actual value of the command.\n // https://github.com/ckeditor/ckeditor5-link/issues/78\n // https://github.com/ckeditor/ckeditor5-link/issues/123\n this.formView.urlInputView.inputView.element.value = linkCommand.value || '';\n }\n /**\n\t * Closes the form view. Decides whether the balloon should be hidden completely or if the action view should be shown. This is\n\t * decided upon the link command value (which has a value if the document selection is in the link).\n\t *\n\t * Additionally, if any {@link module:link/link~LinkConfig#decorators} are defined in the editor configuration, the state of\n\t * switch buttons responsible for manual decorator handling is restored.\n\t *\n\t * @private\n\t */\n _closeFormView() {\n const linkCommand = this.editor.commands.get('link');\n // Restore manual decorator states to represent the current model state. This case is important to reset the switch buttons\n // when the user cancels the editing form.\n linkCommand.restoreManualDecoratorStates();\n if (linkCommand.value !== undefined) {\n this._removeFormView();\n } else {\n this._hideUI();\n }\n }\n /**\n\t * Removes the {@link #formView} from the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n _removeFormView() {\n if (this._isFormInPanel) {\n // Blur the input element before removing it from DOM to prevent issues in some browsers.\n // See https://github.com/ckeditor/ckeditor5/issues/1501.\n this.formView.saveButtonView.focus();\n this._balloon.remove(this.formView);\n // Because the form has an input which has focus, the focus must be brought back\n // to the editor. Otherwise, it would be lost.\n this.editor.editing.view.focus();\n }\n }\n /**\n\t * Shows the correct UI type for the current state of the command. It is either\n\t * {@link #formView} or {@link #actionsView}.\n\t *\n\t * @param {Boolean} forceVisible\n\t * @private\n\t */\n _showUI(forceVisible = false) {\n const editor = this.editor;\n const linkCommand = editor.commands.get('link');\n if (!linkCommand.isEnabled) {\n return;\n }\n // When there's no link under the selection, go straight to the editing UI.\n if (!this._getSelectedLinkElement()) {\n this._addActionsView();\n // Be sure panel with link is visible.\n if (forceVisible) {\n this._balloon.showStack('main');\n }\n this._addFormView();\n } // If there's a link under the selection...\n else {\n // Go to the editing UI if actions are already visible.\n if (this._areActionsVisible) {\n this._addFormView();\n } // Otherwise display just the actions UI.\n else {\n this._addActionsView();\n }\n // Be sure panel with link is visible.\n if (forceVisible) {\n this._balloon.showStack('main');\n }\n }\n // Begin responding to ui#update once the UI is added.\n this._startUpdatingUI();\n }\n /**\n\t * Removes the {@link #formView} from the {@link #_balloon}.\n\t *\n\t * See {@link #_addFormView}, {@link #_addActionsView}.\n\t *\n\t * @protected\n\t */\n _hideUI() {\n if (!this._isUIInPanel) {\n return;\n }\n const editor = this.editor;\n this.stopListening(editor.ui, 'update');\n this.stopListening(this._balloon, 'change:visibleView');\n // Make sure the focus always gets back to the editable _before_ removing the focused form view.\n // Doing otherwise causes issues in some browsers. See https://github.com/ckeditor/ckeditor5-link/issues/193.\n editor.editing.view.focus();\n // Remove form first because it's on top of the stack.\n this._removeFormView();\n // Then remove the actions view because it's beneath the form.\n this._balloon.remove(this.actionsView);\n }\n /**\n\t * Makes the UI react to the {@link module:core/editor/editorui~EditorUI#event:update} event to\n\t * reposition itself when the editor UI should be refreshed.\n\t *\n\t * See: {@link #_hideUI} to learn when the UI stops reacting to the `update` event.\n\t *\n\t * @protected\n\t */\n _startUpdatingUI() {\n const editor = this.editor;\n const viewDocument = editor.editing.view.document;\n let prevSelectedLink = this._getSelectedLinkElement();\n let prevSelectionParent = getSelectionParent();\n const update = () => {\n const selectedLink = this._getSelectedLinkElement();\n const selectionParent = getSelectionParent();\n // Hide the panel if:\n //\n // * the selection went out of the EXISTING link element. E.g. user moved the caret out\n // of the link,\n // * the selection went to a different parent when creating a NEW link. E.g. someone\n // else modified the document.\n // * the selection has expanded (e.g. displaying link actions then pressing SHIFT+Right arrow).\n //\n // Note: #_getSelectedLinkElement will return a link for a non-collapsed selection only\n // when fully selected.\n if (prevSelectedLink && !selectedLink || !prevSelectedLink && selectionParent !== prevSelectionParent) {\n this._hideUI();\n } // Update the position of the panel when:\n // * link panel is in the visible stack\n // * the selection remains in the original link element,\n // * there was no link element in the first place, i.e. creating a new link\n else if (this._isUIVisible) {\n // If still in a link element, simply update the position of the balloon.\n // If there was no link (e.g. inserting one), the balloon must be moved\n // to the new position in the editing view (a new native DOM range).\n this._balloon.updatePosition(this._getBalloonPositionData());\n }\n prevSelectedLink = selectedLink;\n prevSelectionParent = selectionParent;\n };\n function getSelectionParent() {\n return viewDocument.selection.focus.getAncestors().reverse().find(node => node.is('element'));\n }\n this.listenTo(editor.ui, 'update', update);\n this.listenTo(this._balloon, 'change:visibleView', update);\n }\n /**\n\t * Returns `true` when {@link #formView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n get _isFormInPanel() {\n return this._balloon.hasView(this.formView);\n }\n /**\n\t * Returns `true` when {@link #actionsView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n get _areActionsInPanel() {\n return this._balloon.hasView(this.actionsView);\n }\n /**\n\t * Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is\n\t * currently visible.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n get _areActionsVisible() {\n return this._balloon.visibleView === this.actionsView;\n }\n /**\n\t * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n get _isUIInPanel() {\n return this._isFormInPanel || this._areActionsInPanel;\n }\n /**\n\t * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is\n\t * currently visible.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n get _isUIVisible() {\n const visibleView = this._balloon.visibleView;\n return visibleView == this.formView || this._areActionsVisible;\n }\n /**\n\t * Returns positioning options for the {@link #_balloon}. They control the way the balloon is attached\n\t * to the target element or selection.\n\t *\n\t * If the selection is collapsed and inside a link element, the panel will be attached to the\n\t * entire link element. Otherwise, it will be attached to the selection.\n\t *\n\t * @private\n\t * @returns {module:utils/dom/position~Options}\n\t */\n _getBalloonPositionData() {\n const view = this.editor.editing.view;\n const viewDocument = view.document;\n const targetLink = this._getSelectedLinkElement();\n const target = targetLink ? // When selection is inside link element, then attach panel to this element.\n view.domConverter.mapViewToDom(targetLink) : // Otherwise attach panel to the selection.\n view.domConverter.viewRangeToDom(viewDocument.selection.getFirstRange());\n return { target };\n }\n /**\n\t * Returns the link {@link module:engine/view/attributeelement~AttributeElement} under\n\t * the {@link module:engine/view/document~Document editing view's} selection or `null`\n\t * if there is none.\n\t *\n\t * **Note**: For a non–collapsed selection, the link element is only returned when **fully**\n\t * selected and the **only** element within the selection boundaries.\n\t *\n\t * @private\n\t * @returns {module:engine/view/attributeelement~AttributeElement|null}\n\t */\n _getSelectedLinkElement() {\n const view = this.editor.editing.view;\n const selection = view.document.selection;\n if (selection.isCollapsed) {\n return findLinkElementAncestor(selection.getFirstPosition());\n } else {\n // The range for fully selected link is usually anchored in adjacent text nodes.\n // Trim it to get closer to the actual link element.\n const range = selection.getFirstRange().getTrimmed();\n const startLink = findLinkElementAncestor(range.start);\n const endLink = findLinkElementAncestor(range.end);\n if (!startLink || startLink != endLink) {\n return null;\n }\n // Check if the link element is fully selected.\n if (view.createRangeIn(startLink).getTrimmed().isEqual(range)) {\n return startLink;\n } else {\n return null;\n }\n }\n }\n}\n// Returns a link element if there's one among the ancestors of the provided `Position`.\n//\n// @private\n// @param {module:engine/view/position~Position} View position to analyze.\n// @returns {module:engine/view/attributeelement~AttributeElement|null} Link element at the position or null.\nfunction findLinkElementAncestor(position) {\n return position.getAncestors().find(ancestor => isLinkElement(ancestor));\n}","/**\n * @license Copyright (c) 2003-2019, 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 list/listcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport first from '@ckeditor/ckeditor5-utils/src/first';\n\n/**\n * The list command. It is used by the {@link module:list/list~List list feature}.\n *\n * @extends module:core/command~Command\n */\nexport default class ListCommand extends Command {\n\t/**\n\t * Creates an instance of the command.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t * @param {'numbered'|'bulleted'} type List type that will be handled by this command.\n\t */\n\tconstructor( editor, type ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The type of the list created by the command.\n\t\t *\n\t\t * @readonly\n\t\t * @member {'numbered'|'bulleted'|'todo'}\n\t\t */\n\t\tthis.type = type;\n\n\t\t/**\n\t\t * A flag indicating whether the command is active, which means that the selection starts in a list of the same type.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #value\n\t\t */\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.value = this._getValue();\n\t\tthis.isEnabled = this._checkEnabled();\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @protected\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\t\tconst blocks = Array.from( document.selection.getSelectedBlocks() )\n\t\t\t.filter( block => checkCanBecomeListItem( block, model.schema ) );\n\n\t\t// Whether we are turning off some items.\n\t\tconst turnOff = this.value === true;\n\t\t// If we are turning off items, we are going to rename them to paragraphs.\n\n\t\tmodel.change( writer => {\n\t\t\t// If part of a list got turned off, we need to handle (outdent) all of sub-items of the last turned-off item.\n\t\t\t// To be sure that model is all the time in a good state, we first fix items below turned-off item.\n\t\t\tif ( turnOff ) {\n\t\t\t\t// Start from the model item that is just after the last turned-off item.\n\t\t\t\tlet next = blocks[ blocks.length - 1 ].nextSibling;\n\t\t\t\tlet currentIndent = Number.POSITIVE_INFINITY;\n\t\t\t\tlet changes = [];\n\n\t\t\t\t// Correct indent of all items after the last turned off item.\n\t\t\t\t// Rules that should be followed:\n\t\t\t\t// 1. All direct sub-items of turned-off item should become indent 0, because the first item after it\n\t\t\t\t// will be the first item of a new list. Other items are at the same level, so should have same 0 index.\n\t\t\t\t// 2. All items with indent lower than indent of turned-off item should become indent 0, because they\n\t\t\t\t// should not end up as a child of any of list items that they were not children of before.\n\t\t\t\t// 3. All other items should have their indent changed relatively to it's parent.\n\t\t\t\t//\n\t\t\t\t// For example:\n\t\t\t\t// 1 * --------\n\t\t\t\t// 2 * --------\n\t\t\t\t// 3 * --------\t\t\t<-- this is turned off.\n\t\t\t\t// 4 * --------\t\t<-- this has to become indent = 0, because it will be first item on a new list.\n\t\t\t\t// 5 * --------\t<-- this should be still be a child of item above, so indent = 1.\n\t\t\t\t// 6 * --------\t\t\t<-- this has to become indent = 0, because it should not be a child of any of items above.\n\t\t\t\t// 7 * --------\t\t<-- this should be still be a child of item above, so indent = 1.\n\t\t\t\t// 8 * --------\t\t\t\t<-- this has to become indent = 0.\n\t\t\t\t// 9 * --------\t\t\t<-- this should still be a child of item above, so indent = 1.\n\t\t\t\t// 10 * --------\t\t<-- this should still be a child of item above, so indent = 2.\n\t\t\t\t// 11 * --------\t\t<-- this should still be at the same level as item above, so indent = 2.\n\t\t\t\t// 12 * --------\t\t\t\t<-- this and all below are left unchanged.\n\t\t\t\t// 13 * --------\n\t\t\t\t// 14 * --------\n\t\t\t\t//\n\t\t\t\t// After turning off 3 the list becomes:\n\t\t\t\t//\n\t\t\t\t// 1 * --------\n\t\t\t\t// 2 * --------\n\t\t\t\t//\n\t\t\t\t// 3 --------\n\t\t\t\t//\n\t\t\t\t// 4 * --------\n\t\t\t\t// 5 * --------\n\t\t\t\t// 6 * --------\n\t\t\t\t// 7 * --------\n\t\t\t\t// 8 * --------\n\t\t\t\t// 9 * --------\n\t\t\t\t// 10 * --------\n\t\t\t\t// 11 * --------\n\t\t\t\t// 12 * --------\n\t\t\t\t// 13 * --------\n\t\t\t\t// 14 * --------\n\t\t\t\t//\n\t\t\t\t// Thanks to this algorithm no lists are mismatched and no items get unexpected children/parent, while\n\t\t\t\t// those parent-child connection which are possible to maintain are still maintained. It's worth noting\n\t\t\t\t// that this is the same effect that we would be get by multiple use of outdent command. However doing\n\t\t\t\t// it like this is much more efficient because it's less operation (less memory usage, easier OT) and\n\t\t\t\t// less conversion (faster).\n\t\t\t\twhile ( next && next.name == 'listItem' && next.getAttribute( 'listIndent' ) !== 0 ) {\n\t\t\t\t\t// Check each next list item, as long as its indent is bigger than 0.\n\t\t\t\t\t// If the indent is 0 we are not going to change anything anyway.\n\t\t\t\t\tconst indent = next.getAttribute( 'listIndent' );\n\n\t\t\t\t\t// We check if that's item indent is lower as current relative indent.\n\t\t\t\t\tif ( indent < currentIndent ) {\n\t\t\t\t\t\t// If it is, current relative indent becomes that indent.\n\t\t\t\t\t\tcurrentIndent = indent;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fix indent relatively to current relative indent.\n\t\t\t\t\t// Note, that if we just changed the current relative indent, the newIndent will be equal to 0.\n\t\t\t\t\tconst newIndent = indent - currentIndent;\n\n\t\t\t\t\t// Save the entry in changes array. We do not apply it at the moment, because we will need to\n\t\t\t\t\t// reverse the changes so the last item is changed first.\n\t\t\t\t\t// This is to keep model in correct state all the time.\n\t\t\t\t\tchanges.push( { element: next, listIndent: newIndent } );\n\n\t\t\t\t\t// Find next item.\n\t\t\t\t\tnext = next.nextSibling;\n\t\t\t\t}\n\n\t\t\t\tchanges = changes.reverse();\n\n\t\t\t\tfor ( const item of changes ) {\n\t\t\t\t\twriter.setAttribute( 'listIndent', item.listIndent, item.element );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we are turning on, we might change some items that are already `listItem`s but with different type.\n\t\t\t// Changing one nested list item to other type should also trigger changing all its siblings so the\n\t\t\t// whole nested list is of the same type.\n\t\t\t// Example (assume changing to numbered list):\n\t\t\t// * ------\t\t\t\t<-- do not fix, top level item\n\t\t\t// * ------\t\t\t<-- fix, because latter list item of this item's list is changed\n\t\t\t// * ------\t\t<-- do not fix, item is not affected (different list)\n\t\t\t// * ------\t\t\t<-- fix, because latter list item of this item's list is changed\n\t\t\t// * ------\t\t<-- fix, because latter list item of this item's list is changed\n\t\t\t// * ---[--\t\t<-- already in selection\n\t\t\t// * ------\t\t\t<-- already in selection\n\t\t\t// * ------\t\t\t<-- already in selection\n\t\t\t// * ------\t\t\t\t<-- already in selection, but does not cause other list items to change because is top-level\n\t\t\t// * ---]--\t\t\t<-- already in selection\n\t\t\t// * ------\t\t\t<-- fix, because preceding list item of this item's list is changed\n\t\t\t// * ------\t\t<-- do not fix, item is not affected (different list)\n\t\t\t// * ------\t\t\t\t<-- do not fix, top level item\n\t\t\tif ( !turnOff ) {\n\t\t\t\t// Find lowest indent among selected items. This will be indicator what is the indent of\n\t\t\t\t// top-most list affected by the command.\n\t\t\t\tlet lowestIndent = Number.POSITIVE_INFINITY;\n\n\t\t\t\tfor ( const item of blocks ) {\n\t\t\t\t\tif ( item.is( 'listItem' ) && item.getAttribute( 'listIndent' ) < lowestIndent ) {\n\t\t\t\t\t\tlowestIndent = item.getAttribute( 'listIndent' );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Do not execute the fix for top-level lists.\n\t\t\t\tlowestIndent = lowestIndent === 0 ? 1 : lowestIndent;\n\n\t\t\t\t// Fix types of list items that are \"before\" the selected blocks.\n\t\t\t\t_fixType( blocks, true, lowestIndent );\n\n\t\t\t\t// Fix types of list items that are \"after\" the selected blocks.\n\t\t\t\t_fixType( blocks, false, lowestIndent );\n\t\t\t}\n\n\t\t\t// Phew! Now it will be easier :).\n\t\t\t// For each block element that was in the selection, we will either: turn it to list item,\n\t\t\t// turn it to paragraph, or change it's type. Or leave it as it is.\n\t\t\t// Do it in reverse as there might be multiple blocks (same as with changing indents).\n\t\t\tfor ( const element of blocks.reverse() ) {\n\t\t\t\tif ( turnOff && element.name == 'listItem' ) {\n\t\t\t\t\t// We are turning off and the element is a `listItem` - it should be converted to `paragraph`.\n\t\t\t\t\t// List item specific attributes are removed by post fixer.\n\t\t\t\t\twriter.rename( element, 'paragraph' );\n\t\t\t\t} else if ( !turnOff && element.name != 'listItem' ) {\n\t\t\t\t\t// We are turning on and the element is not a `listItem` - it should be converted to `listItem`.\n\t\t\t\t\t// The order of operations is important to keep model in correct state.\n\t\t\t\t\twriter.setAttributes( { listType: this.type, listIndent: 0 }, element );\n\t\t\t\t\twriter.rename( element, 'listItem' );\n\t\t\t\t} else if ( !turnOff && element.name == 'listItem' && element.getAttribute( 'listType' ) != this.type ) {\n\t\t\t\t\t// We are turning on and the element is a `listItem` but has different type - change it's type and\n\t\t\t\t\t// type of it's all siblings that have same indent.\n\t\t\t\t\twriter.setAttribute( 'listType', this.type, element );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Checks the command's {@link #value}.\n\t *\n\t * @private\n\t * @returns {Boolean} The current value.\n\t */\n\t_getValue() {\n\t\t// Check whether closest `listItem` ancestor of the position has a correct type.\n\t\tconst listItem = first( this.editor.model.document.selection.getSelectedBlocks() );\n\n\t\treturn !!listItem && listItem.is( 'listItem' ) && listItem.getAttribute( 'listType' ) == this.type;\n\t}\n\n\t/**\n\t * Checks whether the command can be enabled in the current context.\n\t *\n\t * @private\n\t * @returns {Boolean} Whether the command should be enabled.\n\t */\n\t_checkEnabled() {\n\t\t// If command value is true it means that we are in list item, so the command should be enabled.\n\t\tif ( this.value ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst selection = this.editor.model.document.selection;\n\t\tconst schema = this.editor.model.schema;\n\n\t\tconst firstBlock = first( selection.getSelectedBlocks() );\n\n\t\tif ( !firstBlock ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Otherwise, check if list item can be inserted at the position start.\n\t\treturn checkCanBecomeListItem( firstBlock, schema );\n\t}\n}\n\n// Helper function used when one or more list item have their type changed. Fixes type of other list items\n// that are affected by the change (are in same lists) but are not directly in selection. The function got extracted\n// not to duplicated code, as same fix has to be performed before and after selection.\n//\n// @param {Array.<module:engine/model/node~Node>} blocks Blocks that are in selection.\n// @param {Boolean} isBackward Specified whether fix will be applied for blocks before first selected block (`true`)\n// or blocks after last selected block (`false`).\n// @param {Number} lowestIndent Lowest indent among selected blocks.\nfunction _fixType( blocks, isBackward, lowestIndent ) {\n\t// We need to check previous sibling of first changed item and next siblings of last changed item.\n\tconst startingItem = isBackward ? blocks[ 0 ] : blocks[ blocks.length - 1 ];\n\n\tif ( startingItem.is( 'listItem' ) ) {\n\t\tlet item = startingItem[ isBackward ? 'previousSibling' : 'nextSibling' ];\n\t\t// During processing items, keeps the lowest indent of already processed items.\n\t\t// This saves us from changing too many items.\n\t\t// Following example is for going forward as it is easier to read, however same applies to going backward.\n\t\t// * ------\n\t\t// * ------\n\t\t// * --[---\n\t\t// * ------\t\t<-- `lowestIndent` should be 1\n\t\t// * --]---\t\t<-- `startingItem`, `currentIndent` = 2, `lowestIndent` == 1\n\t\t// * ------\t\t<-- should be fixed, `indent` == 2 == `currentIndent`\n\t\t// * ------\t\t<-- should be fixed, set `currentIndent` to 1, `indent` == 1 == `currentIndent`\n\t\t// * ------\t\t<-- should not be fixed, item is in different list, `indent` = 2, `indent` != `currentIndent`\n\t\t// * ------\t\t<-- should be fixed, `indent` == 1 == `currentIndent`\n\t\t// * ------\t\t\t<-- break loop (`indent` < `lowestIndent`)\n\t\tlet currentIndent = startingItem.getAttribute( 'listIndent' );\n\n\t\t// Look back until a list item with indent lower than reference `lowestIndent`.\n\t\t// That would be the parent of nested sublist which contains item having `lowestIndent`.\n\t\twhile ( item && item.is( 'listItem' ) && item.getAttribute( 'listIndent' ) >= lowestIndent ) {\n\t\t\tif ( currentIndent > item.getAttribute( 'listIndent' ) ) {\n\t\t\t\tcurrentIndent = item.getAttribute( 'listIndent' );\n\t\t\t}\n\n\t\t\t// Found an item that is in the same nested sublist.\n\t\t\tif ( item.getAttribute( 'listIndent' ) == currentIndent ) {\n\t\t\t\t// Just add the item to selected blocks like it was selected by the user.\n\t\t\t\tblocks[ isBackward ? 'unshift' : 'push' ]( item );\n\t\t\t}\n\n\t\t\titem = item[ isBackward ? 'previousSibling' : 'nextSibling' ];\n\t\t}\n\t}\n}\n\n// Checks whether the given block can be replaced by a listItem.\n//\n// @private\n// @param {module:engine/model/element~Element} block A block to be tested.\n// @param {module:engine/model/schema~Schema} schema The schema of the document.\n// @returns {Boolean}\nfunction checkCanBecomeListItem( block, schema ) {\n\treturn schema.checkChild( block.parent, 'listItem' ) && !schema.isObject( block );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 list/indentcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport first from '@ckeditor/ckeditor5-utils/src/first';\n\n/**\n * The list indent command. It is used by the {@link module:list/list~List list feature}.\n *\n * @extends module:core/command~Command\n */\nexport default class IndentCommand extends Command {\n\t/**\n\t * Creates an instance of the command.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t * @param {'forward'|'backward'} indentDirection The direction of indent. If it is equal to `backward`, the command\n\t * will outdent a list item.\n\t */\n\tconstructor( editor, indentDirection ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * Determines by how much the command will change the list item's indent attribute.\n\t\t *\n\t\t * @readonly\n\t\t * @private\n\t\t * @member {Number}\n\t\t */\n\t\tthis._indentBy = indentDirection == 'forward' ? 1 : -1;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.isEnabled = this._checkEnabled();\n\t}\n\n\t/**\n\t * Indents or outdents (depending on the {@link #constructor}'s `indentDirection` parameter) selected list items.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tlet itemsToChange = Array.from( doc.selection.getSelectedBlocks() );\n\n\t\tmodel.change( writer => {\n\t\t\tconst lastItem = itemsToChange[ itemsToChange.length - 1 ];\n\n\t\t\t// Indenting a list item should also indent all the items that are already sub-items of indented item.\n\t\t\tlet next = lastItem.nextSibling;\n\n\t\t\t// Check all items after last indented item, as long as their indent is bigger than indent of that item.\n\t\t\twhile ( next && next.name == 'listItem' && next.getAttribute( 'listIndent' ) > lastItem.getAttribute( 'listIndent' ) ) {\n\t\t\t\titemsToChange.push( next );\n\n\t\t\t\tnext = next.nextSibling;\n\t\t\t}\n\n\t\t\t// We need to be sure to keep model in correct state after each small change, because converters\n\t\t\t// bases on that state and assumes that model is correct.\n\t\t\t// Because of that, if the command outdents items, we will outdent them starting from the last item, as\n\t\t\t// it is safer.\n\t\t\tif ( this._indentBy < 0 ) {\n\t\t\t\titemsToChange = itemsToChange.reverse();\n\t\t\t}\n\n\t\t\tfor ( const item of itemsToChange ) {\n\t\t\t\tconst indent = item.getAttribute( 'listIndent' ) + this._indentBy;\n\n\t\t\t\t// If indent is lower than 0, it means that the item got outdented when it was not indented.\n\t\t\t\t// This means that we need to convert that list item to paragraph.\n\t\t\t\tif ( indent < 0 ) {\n\t\t\t\t\t// To keep the model as correct as possible, first rename listItem, then remove attributes,\n\t\t\t\t\t// as listItem without attributes is very incorrect and will cause problems in converters.\n\t\t\t\t\t// No need to remove attributes, will be removed by post fixer.\n\t\t\t\t\twriter.rename( item, 'paragraph' );\n\t\t\t\t}\n\t\t\t\t// If indent is >= 0, change the attribute value.\n\t\t\t\telse {\n\t\t\t\t\twriter.setAttribute( 'listIndent', indent, item );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Checks whether the command can be enabled in the current context.\n\t *\n\t * @private\n\t * @returns {Boolean} Whether the command should be enabled.\n\t */\n\t_checkEnabled() {\n\t\t// Check whether any of position's ancestor is a list item.\n\t\tconst listItem = first( this.editor.model.document.selection.getSelectedBlocks() );\n\n\t\t// If selection is not in a list item, the command is disabled.\n\t\tif ( !listItem || !listItem.is( 'listItem' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this._indentBy > 0 ) {\n\t\t\t// Cannot indent first item in it's list. Check if before `listItem` is a list item that is in same list.\n\t\t\t// To be in the same list, the item has to have same attributes and cannot be \"split\" by an item with lower indent.\n\t\t\tconst indent = listItem.getAttribute( 'listIndent' );\n\t\t\tconst type = listItem.getAttribute( 'listType' );\n\n\t\t\tlet prev = listItem.previousSibling;\n\n\t\t\twhile ( prev && prev.is( 'listItem' ) && prev.getAttribute( 'listIndent' ) >= indent ) {\n\t\t\t\tif ( prev.getAttribute( 'listIndent' ) == indent ) {\n\t\t\t\t\t// The item is on the same level.\n\t\t\t\t\t// If it has same type, it means that we found a preceding sibling from the same list.\n\t\t\t\t\t// If it does not have same type, it means that `listItem` is on different list (this can happen only\n\t\t\t\t\t// on top level lists, though).\n\t\t\t\t\treturn prev.getAttribute( 'listType' ) == type;\n\t\t\t\t}\n\n\t\t\t\tprev = prev.previousSibling;\n\t\t\t}\n\n\t\t\t// Could not find similar list item, this means that `listItem` is first in its list.\n\t\t\treturn false;\n\t\t}\n\n\t\t// If we are outdenting it is enough to be in list item. Every list item can always be outdented.\n\t\treturn true;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 list/utils\n */\n\nimport { getFillerOffset } from '@ckeditor/ckeditor5-engine/src/view/containerelement';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\n/**\n * Creates a list item {@link module:engine/view/containerelement~ContainerElement}.\n *\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer The writer instance.\n * @returns {module:engine/view/containerelement~ContainerElement}\n */\nexport function createViewListItemElement( writer ) {\n\tconst viewItem = writer.createContainerElement( 'li' );\n\n\tviewItem.getFillerOffset = getListItemFillerOffset;\n\n\treturn viewItem;\n}\n\n/**\n * Helper function that creates a `<ul><li></li></ul>` or (`<ol>`) structure out of the given `modelItem` model `listItem` element.\n * Then, it binds the created view list item (<li>) with the model `listItem` element.\n * The function then returns the created view list item (<li>).\n *\n * @param {module:engine/model/item~Item} modelItem Model list item.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface.\n * @returns {module:engine/view/containerelement~ContainerElement} View list element.\n */\nexport function generateLiInUl( modelItem, conversionApi ) {\n\tconst mapper = conversionApi.mapper;\n\tconst viewWriter = conversionApi.writer;\n\tconst listType = modelItem.getAttribute( 'listType' ) == 'numbered' ? 'ol' : 'ul';\n\tconst viewItem = createViewListItemElement( viewWriter );\n\n\tconst viewList = viewWriter.createContainerElement( listType, null );\n\n\tviewWriter.insert( viewWriter.createPositionAt( viewList, 0 ), viewItem );\n\n\tmapper.bindElements( modelItem, viewItem );\n\n\treturn viewItem;\n}\n\n/**\n * Helper function that inserts a view list at a correct place and merges it with its siblings.\n * It takes a model list item element (`modelItem`) and a corresponding view list item element (`injectedItem`). The view list item\n * should be in a view list element (`<ul>` or `<ol>`) and should be its only child.\n * See comments below to better understand the algorithm.\n *\n * @param {module:engine/view/item~Item} modelItem Model list item.\n * @param {module:engine/view/containerelement~ContainerElement} injectedItem\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface.\n * @param {module:engine/model/model~Model} model The model instance.\n */\nexport function injectViewList( modelItem, injectedItem, conversionApi, model ) {\n\tconst injectedList = injectedItem.parent;\n\tconst mapper = conversionApi.mapper;\n\tconst viewWriter = conversionApi.writer;\n\n\t// The position where the view list will be inserted.\n\tlet insertPosition = mapper.toViewPosition( model.createPositionBefore( modelItem ) );\n\n\t// 1. Find the previous list item that has the same or smaller indent. Basically we are looking for the first model item\n\t// that is a \"parent\" or \"sibling\" of the injected model item.\n\t// If there is no such list item, it means that the injected list item is the first item in \"its list\".\n\tconst refItem = getSiblingListItem( modelItem.previousSibling, {\n\t\tsameIndent: true,\n\t\tsmallerIndent: true,\n\t\tlistIndent: modelItem.getAttribute( 'listIndent' )\n\t} );\n\tconst prevItem = modelItem.previousSibling;\n\n\tif ( refItem && refItem.getAttribute( 'listIndent' ) == modelItem.getAttribute( 'listIndent' ) ) {\n\t\t// There is a list item with the same indent - we found the same-level sibling.\n\t\t// Break the list after it. The inserted view item will be added in the broken space.\n\t\tconst viewItem = mapper.toViewElement( refItem );\n\t\tinsertPosition = viewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) );\n\t} else {\n\t\t// There is no list item with the same indent. Check the previous model item.\n\t\tif ( prevItem && prevItem.name == 'listItem' ) {\n\t\t\t// If it is a list item, it has to have a lower indent.\n\t\t\t// It means that the inserted item should be added to it as its nested item.\n\t\t\tinsertPosition = mapper.toViewPosition( model.createPositionAt( prevItem, 'end' ) );\n\t\t} else {\n\t\t\t// The previous item is not a list item (or does not exist at all).\n\t\t\t// Just map the position and insert the view item at the mapped position.\n\t\t\tinsertPosition = mapper.toViewPosition( model.createPositionBefore( modelItem ) );\n\t\t}\n\t}\n\n\tinsertPosition = positionAfterUiElements( insertPosition );\n\n\t// Insert the view item.\n\tviewWriter.insert( insertPosition, injectedList );\n\n\t// 2. Handle possible children of the injected model item.\n\tif ( prevItem && prevItem.name == 'listItem' ) {\n\t\tconst prevView = mapper.toViewElement( prevItem );\n\n\t\tconst walkerBoundaries = viewWriter.createRange( viewWriter.createPositionAt( prevView, 0 ), insertPosition );\n\t\tconst walker = walkerBoundaries.getWalker( { ignoreElementEnd: true } );\n\n\t\tfor ( const value of walker ) {\n\t\t\tif ( value.item.is( 'li' ) ) {\n\t\t\t\tconst breakPosition = viewWriter.breakContainer( viewWriter.createPositionBefore( value.item ) );\n\t\t\t\tconst viewList = value.item.parent;\n\n\t\t\t\tconst targetPosition = viewWriter.createPositionAt( injectedItem, 'end' );\n\t\t\t\tmergeViewLists( viewWriter, targetPosition.nodeBefore, targetPosition.nodeAfter );\n\t\t\t\tviewWriter.move( viewWriter.createRangeOn( viewList ), targetPosition );\n\n\t\t\t\twalker.position = breakPosition;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconst nextViewList = injectedList.nextSibling;\n\n\t\tif ( nextViewList && ( nextViewList.is( 'ul' ) || nextViewList.is( 'ol' ) ) ) {\n\t\t\tlet lastSubChild = null;\n\n\t\t\tfor ( const child of nextViewList.getChildren() ) {\n\t\t\t\tconst modelChild = mapper.toModelElement( child );\n\n\t\t\t\tif ( modelChild && modelChild.getAttribute( 'listIndent' ) > modelItem.getAttribute( 'listIndent' ) ) {\n\t\t\t\t\tlastSubChild = child;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( lastSubChild ) {\n\t\t\t\tviewWriter.breakContainer( viewWriter.createPositionAfter( lastSubChild ) );\n\t\t\t\tviewWriter.move( viewWriter.createRangeOn( lastSubChild.parent ), viewWriter.createPositionAt( injectedItem, 'end' ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Merge the inserted view list with its possible neighbor lists.\n\tmergeViewLists( viewWriter, injectedList, injectedList.nextSibling );\n\tmergeViewLists( viewWriter, injectedList.previousSibling, injectedList );\n}\n\n/**\n * Helper function that takes two parameters that are expected to be view list elements, and merges them.\n * The merge happens only if both parameters are list elements of the same type (the same element name and the same class attributes).\n *\n * @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter The writer instance.\n * @param {module:engine/view/item~Item} firstList The first element to compare.\n * @param {module:engine/view/item~Item} secondList The second element to compare.\n * @returns {module:engine/view/position~Position|null} The position after merge or `null` when there was no merge.\n */\nexport function mergeViewLists( viewWriter, firstList, secondList ) {\n\t// Check if two lists are going to be merged.\n\tif ( !firstList || !secondList || ( firstList.name != 'ul' && firstList.name != 'ol' ) ) {\n\t\treturn null;\n\t}\n\n\t// Both parameters are list elements, so compare types now.\n\tif ( firstList.name != secondList.name || firstList.getAttribute( 'class' ) !== secondList.getAttribute( 'class' ) ) {\n\t\treturn null;\n\t}\n\n\treturn viewWriter.mergeContainers( viewWriter.createPositionAfter( firstList ) );\n}\n\n/**\n * Helper function that for a given `view.Position`, returns a `view.Position` that is after all `view.UIElement`s that\n * are after the given position.\n *\n * For example:\n * `<container:p>foo^<ui:span></ui:span><ui:span></ui:span>bar</container:p>`\n * For position ^, the position before \"bar\" will be returned.\n *\n * @param {module:engine/view/position~Position} viewPosition\n * @returns {module:engine/view/position~Position}\n */\nexport function positionAfterUiElements( viewPosition ) {\n\treturn viewPosition.getLastMatchingPosition( value => value.item.is( 'uiElement' ) );\n}\n\n/**\n * Helper function that searches for a previous list item sibling of a given model item that meets the given criteria\n * passed by the options object.\n *\n * @param {module:engine/model/item~Item} modelItem\n * @param {Object} options Search criteria.\n * @param {Boolean} [options.sameIndent=false] Whether the sought sibling should have the same indentation.\n * @param {Boolean} [options.smallerIndent=false] Whether the sought sibling should have a smaller indentation.\n * @param {Number} [options.listIndent] The reference indentation.\n * @returns {module:engine/model/item~Item|null}\n */\nexport function getSiblingListItem( modelItem, options ) {\n\tconst sameIndent = !!options.sameIndent;\n\tconst smallerIndent = !!options.smallerIndent;\n\tconst indent = options.listIndent;\n\n\tlet item = modelItem;\n\n\twhile ( item && item.name == 'listItem' ) {\n\t\tconst itemIndent = item.getAttribute( 'listIndent' );\n\n\t\tif ( ( sameIndent && indent == itemIndent ) || ( smallerIndent && indent > itemIndent ) ) {\n\t\t\treturn item;\n\t\t}\n\n\t\titem = item.previousSibling;\n\t}\n\n\treturn null;\n}\n\n/**\n * Helper method for creating a UI button and linking it with an appropriate command.\n *\n * @private\n * @param {module:core/editor/editor~Editor} editor The editor instance to which the UI component will be added.\n * @param {String} commandName The name of the command.\n * @param {Object} label The button label.\n * @param {String} icon The source of the icon.\n */\nexport function createUIComponent( editor, commandName, label, icon ) {\n\teditor.ui.componentFactory.add( commandName, locale => {\n\t\tconst command = editor.commands.get( commandName );\n\t\tconst buttonView = new ButtonView( locale );\n\n\t\tbuttonView.set( {\n\t\t\tlabel,\n\t\t\ticon,\n\t\t\ttooltip: true,\n\t\t\tisToggleable: true\n\t\t} );\n\n\t\t// Bind button model to command.\n\t\tbuttonView.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );\n\n\t\t// Execute command.\n\t\tbuttonView.on( 'execute', () => editor.execute( commandName ) );\n\n\t\treturn buttonView;\n\t} );\n}\n\n// Implementation of getFillerOffset for view list item element.\n//\n// @returns {Number|null} Block filler offset or `null` if block filler is not needed.\nfunction getListItemFillerOffset() {\n\tconst hasOnlyLists = !this.isEmpty && ( this.getChild( 0 ).name == 'ul' || this.getChild( 0 ).name == 'ol' );\n\n\tif ( this.isEmpty || hasOnlyLists ) {\n\t\treturn 0;\n\t}\n\n\treturn getFillerOffset.call( this );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 list/converters\n */\n\nimport {\n\tgenerateLiInUl,\n\tinjectViewList,\n\tmergeViewLists,\n\tgetSiblingListItem,\n\tpositionAfterUiElements\n} from './utils';\nimport TreeWalker from '@ckeditor/ckeditor5-engine/src/model/treewalker';\n\n/**\n * A model-to-view converter for the `listItem` model element insertion.\n *\n * It creates a `<ul><li></li><ul>` (or `<ol>`) view structure out of a `listItem` model element, inserts it at the correct\n * position, and merges the list with surrounding lists (if available).\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewInsertion( model ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst consumable = conversionApi.consumable;\n\n\t\tif ( !consumable.test( data.item, 'insert' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listType' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listIndent' )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconsumable.consume( data.item, 'insert' );\n\t\tconsumable.consume( data.item, 'attribute:listType' );\n\t\tconsumable.consume( data.item, 'attribute:listIndent' );\n\n\t\tconst modelItem = data.item;\n\t\tconst viewItem = generateLiInUl( modelItem, conversionApi );\n\n\t\tinjectViewList( modelItem, viewItem, conversionApi, model );\n\t};\n}\n\n/**\n * A model-to-view converter for the `listItem` model element removal.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:remove\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewRemove( model ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst viewStart = conversionApi.mapper.toViewPosition( data.position ).getLastMatchingPosition( value => !value.item.is( 'li' ) );\n\t\tconst viewItem = viewStart.nodeAfter;\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\t// 1. Break the container after and before the list item.\n\t\t// This will create a view list with one view list item - the one to remove.\n\t\tviewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) );\n\t\tviewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) );\n\n\t\t// 2. Remove the list with the item to remove.\n\t\tconst viewList = viewItem.parent;\n\t\tconst viewListPrev = viewList.previousSibling;\n\t\tconst removeRange = viewWriter.createRangeOn( viewList );\n\t\tconst removed = viewWriter.remove( removeRange );\n\n\t\t// 3. Merge the whole created by breaking and removing the list.\n\t\tif ( viewListPrev && viewListPrev.nextSibling ) {\n\t\t\tmergeViewLists( viewWriter, viewListPrev, viewListPrev.nextSibling );\n\t\t}\n\n\t\t// 4. Bring back nested list that was in the removed <li>.\n\t\tconst modelItem = conversionApi.mapper.toModelElement( viewItem );\n\n\t\thoistNestedLists( modelItem.getAttribute( 'listIndent' ) + 1, data.position, removeRange.start, viewItem, conversionApi, model );\n\n\t\t// 5. Unbind removed view item and all children.\n\t\tfor ( const child of viewWriter.createRangeIn( removed ).getItems() ) {\n\t\t\tconversionApi.mapper.unbindViewElement( child );\n\t\t}\n\n\t\tevt.stop();\n\t};\n}\n\n/**\n * A model-to-view converter for the `type` attribute change on the `listItem` model element.\n *\n * This change means that the `<li>` element parent changes from `<ul>` to `<ol>` (or vice versa). This is accomplished\n * by breaking view elements and changing their name. The next {@link module:list/converters~modelViewMergeAfterChangeType}\n * converter will attempt to merge split nodes.\n *\n * Splitting this conversion into 2 steps makes it possible to add an additional conversion in the middle.\n * Check {@link module:list/todolistconverters~modelViewChangeType} to see an example of it.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function modelViewChangeType( evt, data, conversionApi ) {\n\tif ( !conversionApi.consumable.consume( data.item, 'attribute:listType' ) ) {\n\t\treturn;\n\t}\n\n\tconst viewItem = conversionApi.mapper.toViewElement( data.item );\n\tconst viewWriter = conversionApi.writer;\n\n\t// Break the container after and before the list item.\n\t// This will create a view list with one view list item -- the one that changed type.\n\tviewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) );\n\tviewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) );\n\n\t// Change name of the view list that holds the changed view item.\n\t// We cannot just change name property, because that would not render properly.\n\tconst viewList = viewItem.parent;\n\tconst listName = data.attributeNewValue == 'numbered' ? 'ol' : 'ul';\n\n\tviewWriter.rename( listName, viewList );\n}\n\n/**\n * A model-to-view converter that attempts to merge nodes split by {@link module:list/converters~modelViewChangeType}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function modelViewMergeAfterChangeType( evt, data, conversionApi ) {\n\tconst viewItem = conversionApi.mapper.toViewElement( data.item );\n\tconst viewList = viewItem.parent;\n\tconst viewWriter = conversionApi.writer;\n\n\t// Merge the changed view list with other lists, if possible.\n\tmergeViewLists( viewWriter, viewList, viewList.nextSibling );\n\tmergeViewLists( viewWriter, viewList.previousSibling, viewList );\n\n\t// Consumable insertion of children inside the item. They are already handled by re-building the item in view.\n\tfor ( const child of data.item.getChildren() ) {\n\t\tconversionApi.consumable.consume( child, 'insert' );\n\t}\n}\n\n/**\n * A model-to-view converter for the `listIndent` attribute change on the `listItem` model element.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewChangeIndent( model ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tif ( !conversionApi.consumable.consume( data.item, 'attribute:listIndent' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewItem = conversionApi.mapper.toViewElement( data.item );\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\t// 1. Break the container after and before the list item.\n\t\t// This will create a view list with one view list item -- the one that changed type.\n\t\tviewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) );\n\t\tviewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) );\n\n\t\t// 2. Extract view list with changed view list item and merge \"hole\" possibly created by breaking and removing elements.\n\t\tconst viewList = viewItem.parent;\n\t\tconst viewListPrev = viewList.previousSibling;\n\t\tconst removeRange = viewWriter.createRangeOn( viewList );\n\t\tviewWriter.remove( removeRange );\n\n\t\tif ( viewListPrev && viewListPrev.nextSibling ) {\n\t\t\tmergeViewLists( viewWriter, viewListPrev, viewListPrev.nextSibling );\n\t\t}\n\n\t\t// 3. Bring back nested list that was in the removed <li>.\n\t\thoistNestedLists( data.attributeOldValue + 1, data.range.start, removeRange.start, viewItem, conversionApi, model );\n\n\t\t// 4. Inject view list like it is newly inserted.\n\t\tinjectViewList( data.item, viewItem, conversionApi, model );\n\n\t\t// 5. Consume insertion of children inside the item. They are already handled by re-building the item in view.\n\t\tfor ( const child of data.item.getChildren() ) {\n\t\t\tconversionApi.consumable.consume( child, 'insert' );\n\t\t}\n\t};\n}\n\n/**\n * A special model-to-view converter introduced by the {@link module:list/list~List list feature}. This converter is fired for\n * insert change of every model item, and should be fired before the actual converter. The converter checks whether the inserted\n * model item is a non-`listItem` element. If it is, and it is inserted inside a view list, the converter breaks the\n * list so the model element is inserted to the view parent element corresponding to its model parent element.\n *\n * The converter prevents such situations:\n *\n *\t\t// Model: // View:\n *\t\t<listItem>foo</listItem> <ul>\n *\t\t<listItem>bar</listItem> <li>foo</li>\n *\t\t <li>bar</li>\n *\t\t </ul>\n *\n *\t\t// After change: // Correct view guaranteed by this converter:\n *\t\t<listItem>foo</listItem> <ul><li>foo</li></ul><p>xxx</p><ul><li>bar</li></ul>\n *\t\t<paragraph>xxx</paragraph> // Instead of this wrong view state:\n *\t\t<listItem>bar</listItem> <ul><li>foo</li><p>xxx</p><li>bar</li></ul>\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function modelViewSplitOnInsert( evt, data, conversionApi ) {\n\tif ( data.item.name != 'listItem' ) {\n\t\tlet viewPosition = conversionApi.mapper.toViewPosition( data.range.start );\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst lists = [];\n\n\t\t// Break multiple ULs/OLs if there are.\n\t\t//\n\t\t// Imagine following list:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.1.1 --------\n\t\t// 1.1.2 --------\n\t\t// 1.1.3 --------\n\t\t// 1.1.3.1 --------\n\t\t// 1.2 --------\n\t\t// 1.2.1 --------\n\t\t// 2 --------\n\t\t//\n\t\t// Insert paragraph after item 1.1.1:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.1.1 --------\n\t\t//\n\t\t// Lorem ipsum.\n\t\t//\n\t\t// 1.1.2 --------\n\t\t// 1.1.3 --------\n\t\t// 1.1.3.1 --------\n\t\t// 1.2 --------\n\t\t// 1.2.1 --------\n\t\t// 2 --------\n\t\t//\n\t\t// In this case 1.1.2 has to become beginning of a new list.\n\t\t// We need to break list before 1.1.2 (obvious), then we need to break list also before 1.2.\n\t\t// Then we need to move those broken pieces one after another and merge:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.1.1 --------\n\t\t//\n\t\t// Lorem ipsum.\n\t\t//\n\t\t// 1.1.2 --------\n\t\t// 1.1.3 --------\n\t\t// 1.1.3.1 --------\n\t\t// 1.2 --------\n\t\t// 1.2.1 --------\n\t\t// 2 --------\n\t\t//\n\t\twhile ( viewPosition.parent.name == 'ul' || viewPosition.parent.name == 'ol' ) {\n\t\t\tviewPosition = viewWriter.breakContainer( viewPosition );\n\n\t\t\tif ( viewPosition.parent.name != 'li' ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Remove lists that are after inserted element.\n\t\t\t// They will be brought back later, below the inserted element.\n\t\t\tconst removeStart = viewPosition;\n\t\t\tconst removeEnd = viewWriter.createPositionAt( viewPosition.parent, 'end' );\n\n\t\t\t// Don't remove if there is nothing to remove.\n\t\t\tif ( !removeStart.isEqual( removeEnd ) ) {\n\t\t\t\tconst removed = viewWriter.remove( viewWriter.createRange( removeStart, removeEnd ) );\n\t\t\t\tlists.push( removed );\n\t\t\t}\n\n\t\t\tviewPosition = viewWriter.createPositionAfter( viewPosition.parent );\n\t\t}\n\n\t\t// Bring back removed lists.\n\t\tif ( lists.length > 0 ) {\n\t\t\tfor ( let i = 0; i < lists.length; i++ ) {\n\t\t\t\tconst previousList = viewPosition.nodeBefore;\n\t\t\t\tconst insertedRange = viewWriter.insert( viewPosition, lists[ i ] );\n\t\t\t\tviewPosition = insertedRange.end;\n\n\t\t\t\t// Don't merge first list! We want a split in that place (this is why this converter is introduced).\n\t\t\t\tif ( i > 0 ) {\n\t\t\t\t\tconst mergePos = mergeViewLists( viewWriter, previousList, previousList.nextSibling );\n\n\t\t\t\t\t// If `mergePos` is in `previousList` it means that the lists got merged.\n\t\t\t\t\t// In this case, we need to fix insert position.\n\t\t\t\t\tif ( mergePos && mergePos.parent == previousList ) {\n\t\t\t\t\t\tviewPosition.offset--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Merge last inserted list with element after it.\n\t\t\tmergeViewLists( viewWriter, viewPosition.nodeBefore, viewPosition.nodeAfter );\n\t\t}\n\t}\n}\n\n/**\n * A special model-to-view converter introduced by the {@link module:list/list~List list feature}. This converter takes care of\n * merging view lists after something is removed or moved from near them.\n *\n * Example:\n *\n *\t\t// Model: // View:\n *\t\t<listItem>foo</listItem> <ul><li>foo</li></ul>\n *\t\t<paragraph>xxx</paragraph> <p>xxx</p>\n *\t\t<listItem>bar</listItem> <ul><li>bar</li></ul>\n *\n *\t\t// After change: // Correct view guaranteed by this converter:\n *\t\t<listItem>foo</listItem> <ul>\n *\t\t<listItem>bar</listItem> <li>foo</li>\n *\t\t <li>bar</li>\n *\t\t </ul>\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:remove\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function modelViewMergeAfter( evt, data, conversionApi ) {\n\tconst viewPosition = conversionApi.mapper.toViewPosition( data.position );\n\tconst viewItemPrev = viewPosition.nodeBefore;\n\tconst viewItemNext = viewPosition.nodeAfter;\n\n\t// Merge lists if something (remove, move) was done from inside of list.\n\t// Merging will be done only if both items are view lists of the same type.\n\t// The check is done inside the helper function.\n\tmergeViewLists( conversionApi.writer, viewItemPrev, viewItemNext );\n}\n\n/**\n * A view-to-model converter that converts the `<li>` view elements into the `listItem` model elements.\n *\n * To set correct values of the `listType` and `listIndent` attributes the converter:\n * * checks `<li>`'s parent,\n * * stores and increases the `conversionApi.store.indent` value when `<li>`'s sub-items are converted.\n *\n * @see module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n */\nexport function viewModelConverter( evt, data, conversionApi ) {\n\tif ( conversionApi.consumable.consume( data.viewItem, { name: true } ) ) {\n\t\tconst writer = conversionApi.writer;\n\n\t\t// 1. Create `listItem` model element.\n\t\tconst listItem = writer.createElement( 'listItem' );\n\n\t\t// 2. Handle `listItem` model element attributes.\n\t\tconst indent = getIndent( data.viewItem );\n\n\t\twriter.setAttribute( 'listIndent', indent, listItem );\n\n\t\t// Set 'bulleted' as default. If this item is pasted into a context,\n\t\tconst type = data.viewItem.parent && data.viewItem.parent.name == 'ol' ? 'numbered' : 'bulleted';\n\t\twriter.setAttribute( 'listType', type, listItem );\n\n\t\t// Try to find allowed parent for list item.\n\t\tconst splitResult = conversionApi.splitToAllowedParent( listItem, data.modelCursor );\n\n\t\t// When there is no allowed parent it means that list item cannot be converted at current model position\n\t\t// and in any of position ancestors.\n\t\tif ( !splitResult ) {\n\t\t\treturn;\n\t\t}\n\n\t\twriter.insert( listItem, splitResult.position );\n\n\t\tconst nextPosition = viewToModelListItemChildrenConverter( listItem, data.viewItem.getChildren(), conversionApi );\n\n\t\t// Result range starts before the first item and ends after the last.\n\t\tdata.modelRange = writer.createRange( data.modelCursor, nextPosition );\n\n\t\t// When `data.modelCursor` parent had to be split to insert list item...\n\t\tif ( splitResult.cursorParent ) {\n\t\t\t// Continue conversion in the split element.\n\t\t\tdata.modelCursor = writer.createPositionAt( splitResult.cursorParent, 0 );\n\t\t} else {\n\t\t\t// Otherwise continue conversion after the last list item.\n\t\t\tdata.modelCursor = data.modelRange.end;\n\t\t}\n\t}\n}\n\n/**\n * A view-to-model converter for the `<ul>` and `<ol>` view elements that cleans the input view of garbage.\n * This is mostly to clean whitespaces from between the `<li>` view elements inside the view list element, however, also\n * incorrect data can be cleared if the view was incorrect.\n *\n * @see module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n */\nexport function cleanList( evt, data, conversionApi ) {\n\tif ( conversionApi.consumable.test( data.viewItem, { name: true } ) ) {\n\t\t// Caching children because when we start removing them iterating fails.\n\t\tconst children = Array.from( data.viewItem.getChildren() );\n\n\t\tfor ( const child of children ) {\n\t\t\tconst isWrongElement = !( child.is( 'li' ) || isList( child ) );\n\n\t\t\tif ( isWrongElement ) {\n\t\t\t\tchild._remove();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * A view-to-model converter for the `<li>` elements that cleans whitespace formatting from the input view.\n *\n * @see module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n */\nexport function cleanListItem( evt, data, conversionApi ) {\n\tif ( conversionApi.consumable.test( data.viewItem, { name: true } ) ) {\n\t\tif ( data.viewItem.childCount === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst children = [ ...data.viewItem.getChildren() ];\n\n\t\tlet foundList = false;\n\t\tlet firstNode = true;\n\n\t\tfor ( const child of children ) {\n\t\t\tif ( foundList && !isList( child ) ) {\n\t\t\t\tchild._remove();\n\t\t\t}\n\n\t\t\tif ( child.is( 'text' ) ) {\n\t\t\t\t// If this is the first node and it's a text node, left-trim it.\n\t\t\t\tif ( firstNode ) {\n\t\t\t\t\tchild._data = child.data.replace( /^\\s+/, '' );\n\t\t\t\t}\n\n\t\t\t\t// If this is the last text node before <ul> or <ol>, right-trim it.\n\t\t\t\tif ( !child.nextSibling || isList( child.nextSibling ) ) {\n\t\t\t\t\tchild._data = child.data.replace( /\\s+$/, '' );\n\t\t\t\t}\n\t\t\t} else if ( isList( child ) ) {\n\t\t\t\t// If this is a <ul> or <ol>, do not process it, just mark that we already visited list element.\n\t\t\t\tfoundList = true;\n\t\t\t}\n\n\t\t\tfirstNode = false;\n\t\t}\n\t}\n}\n\n/**\n * Returns a callback for model position to view position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes\n * positions between the `listItem` elements that would be incorrectly mapped because of how list items are represented in the model\n * and in the view.\n *\n * @see module:engine/conversion/mapper~Mapper#event:modelToViewPosition\n * @param {module:engine/view/view~View} view A view instance.\n * @returns {Function}\n */\nexport function modelToViewPosition( view ) {\n\treturn ( evt, data ) => {\n\t\tif ( data.isPhantom ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelItem = data.modelPosition.nodeBefore;\n\n\t\tif ( modelItem && modelItem.is( 'listItem' ) ) {\n\t\t\tconst viewItem = data.mapper.toViewElement( modelItem );\n\t\t\tconst topmostViewList = viewItem.getAncestors().find( isList );\n\t\t\tconst walker = view.createPositionAt( viewItem, 0 ).getWalker();\n\n\t\t\tfor ( const value of walker ) {\n\t\t\t\tif ( value.type == 'elementStart' && value.item.is( 'li' ) ) {\n\t\t\t\t\tdata.viewPosition = value.previousPosition;\n\n\t\t\t\t\tbreak;\n\t\t\t\t} else if ( value.type == 'elementEnd' && value.item == topmostViewList ) {\n\t\t\t\t\tdata.viewPosition = value.nextPosition;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * The callback for view position to model position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes\n * positions between the `<li>` elements that would be incorrectly mapped because of how list items are represented in the model\n * and in the view.\n *\n * @see module:engine/conversion/mapper~Mapper#event:viewToModelPosition\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function viewToModelPosition( model ) {\n\treturn ( evt, data ) => {\n\t\tconst viewPos = data.viewPosition;\n\t\tconst viewParent = viewPos.parent;\n\t\tconst mapper = data.mapper;\n\n\t\tif ( viewParent.name == 'ul' || viewParent.name == 'ol' ) {\n\t\t\t// Position is directly in <ul> or <ol>.\n\t\t\tif ( !viewPos.isAtEnd ) {\n\t\t\t\t// If position is not at the end, it must be before <li>.\n\t\t\t\t// Get that <li>, map it to `listItem` and set model position before that `listItem`.\n\t\t\t\tconst modelNode = mapper.toModelElement( viewPos.nodeAfter );\n\n\t\t\t\tdata.modelPosition = model.createPositionBefore( modelNode );\n\t\t\t} else {\n\t\t\t\t// Position is at the end of <ul> or <ol>, so there is no <li> after it to be mapped.\n\t\t\t\t// There is <li> before the position, but we cannot just map it to `listItem` and set model position after it,\n\t\t\t\t// because that <li> may contain nested items.\n\t\t\t\t// We will check \"model length\" of that <li>, in other words - how many `listItem`s are in that <li>.\n\t\t\t\tconst modelNode = mapper.toModelElement( viewPos.nodeBefore );\n\t\t\t\tconst modelLength = mapper.getModelLength( viewPos.nodeBefore );\n\n\t\t\t\t// Then we get model position before mapped `listItem` and shift it accordingly.\n\t\t\t\tdata.modelPosition = model.createPositionBefore( modelNode ).getShiftedBy( modelLength );\n\t\t\t}\n\n\t\t\tevt.stop();\n\t\t} else if (\n\t\t\tviewParent.name == 'li' &&\n\t\t\tviewPos.nodeBefore &&\n\t\t\t( viewPos.nodeBefore.name == 'ul' || viewPos.nodeBefore.name == 'ol' )\n\t\t) {\n\t\t\t// In most cases when view position is in <li> it is in text and this is a correct position.\n\t\t\t// However, if position is after <ul> or <ol> we have to fix it -- because in model <ul>/<ol> are not in the `listItem`.\n\t\t\tconst modelNode = mapper.toModelElement( viewParent );\n\n\t\t\t// Check all <ul>s and <ol>s that are in the <li> but before mapped position.\n\t\t\t// Get model length of those elements and then add it to the offset of `listItem` mapped to the original <li>.\n\t\t\tlet modelLength = 1; // Starts from 1 because the original <li> has to be counted in too.\n\t\t\tlet viewList = viewPos.nodeBefore;\n\n\t\t\twhile ( viewList && isList( viewList ) ) {\n\t\t\t\tmodelLength += mapper.getModelLength( viewList );\n\n\t\t\t\tviewList = viewList.previousSibling;\n\t\t\t}\n\n\t\t\tdata.modelPosition = model.createPositionBefore( modelNode ).getShiftedBy( modelLength );\n\n\t\t\tevt.stop();\n\t\t}\n\t};\n}\n\n/**\n * Post-fixer that reacts to changes on document and fixes incorrect model states.\n *\n * In the example below, there is a correct list structure.\n * Then the middle element is removed so the list structure will become incorrect:\n *\n *\t\t<listItem listType=\"bulleted\" listIndent=0>Item 1</listItem>\n *\t\t<listItem listType=\"bulleted\" listIndent=1>Item 2</listItem> <--- this is removed.\n *\t\t<listItem listType=\"bulleted\" listIndent=2>Item 3</listItem>\n *\n * The list structure after the middle element is removed:\n *\n * \t\t<listItem listType=\"bulleted\" listIndent=0>Item 1</listItem>\n *\t\t<listItem listType=\"bulleted\" listIndent=2>Item 3</listItem>\n *\n * Should become:\n *\n *\t\t<listItem listType=\"bulleted\" listIndent=0>Item 1</listItem>\n *\t\t<listItem listType=\"bulleted\" listIndent=1>Item 3</listItem> <--- note that indent got post-fixed.\n *\n * @param {module:engine/model/model~Model} model The data model.\n * @param {module:engine/model/writer~Writer} writer The writer to do changes with.\n * @returns {Boolean} `true` if any change has been applied, `false` otherwise.\n */\nexport function modelChangePostFixer( model, writer ) {\n\tconst changes = model.document.differ.getChanges();\n\tconst itemToListHead = new Map();\n\n\tlet applied = false;\n\n\tfor ( const entry of changes ) {\n\t\tif ( entry.type == 'insert' && entry.name == 'listItem' ) {\n\t\t\t_addListToFix( entry.position );\n\t\t} else if ( entry.type == 'insert' && entry.name != 'listItem' ) {\n\t\t\tif ( entry.name != '$text' ) {\n\t\t\t\t// In case of renamed element.\n\t\t\t\tconst item = entry.position.nodeAfter;\n\n\t\t\t\tif ( item.hasAttribute( 'listIndent' ) ) {\n\t\t\t\t\twriter.removeAttribute( 'listIndent', item );\n\n\t\t\t\t\tapplied = true;\n\t\t\t\t}\n\n\t\t\t\tif ( item.hasAttribute( 'listType' ) ) {\n\t\t\t\t\twriter.removeAttribute( 'listType', item );\n\n\t\t\t\t\tapplied = true;\n\t\t\t\t}\n\n\t\t\t\tfor ( const innerItem of Array.from( model.createRangeIn( item ) ).filter( e => e.item.is( 'listItem' ) ) ) {\n\t\t\t\t\t_addListToFix( innerItem.previousPosition );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst posAfter = entry.position.getShiftedBy( entry.length );\n\n\t\t\t_addListToFix( posAfter );\n\t\t} else if ( entry.type == 'remove' && entry.name == 'listItem' ) {\n\t\t\t_addListToFix( entry.position );\n\t\t} else if ( entry.type == 'attribute' && entry.attributeKey == 'listIndent' ) {\n\t\t\t_addListToFix( entry.range.start );\n\t\t} else if ( entry.type == 'attribute' && entry.attributeKey == 'listType' ) {\n\t\t\t_addListToFix( entry.range.start );\n\t\t}\n\t}\n\n\tfor ( const listHead of itemToListHead.values() ) {\n\t\t_fixListIndents( listHead );\n\t\t_fixListTypes( listHead );\n\t}\n\n\treturn applied;\n\n\tfunction _addListToFix( position ) {\n\t\tconst prev = position.nodeBefore;\n\n\t\tif ( !prev || !prev.is( 'listItem' ) ) {\n\t\t\tconst item = position.nodeAfter;\n\n\t\t\tif ( item && item.is( 'listItem' ) ) {\n\t\t\t\titemToListHead.set( item, item );\n\t\t\t}\n\t\t} else {\n\t\t\tlet listHead = prev;\n\n\t\t\tif ( itemToListHead.has( listHead ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twhile ( listHead.previousSibling && listHead.previousSibling.is( 'listItem' ) ) {\n\t\t\t\tlistHead = listHead.previousSibling;\n\n\t\t\t\tif ( itemToListHead.has( listHead ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\titemToListHead.set( position.nodeBefore, listHead );\n\t\t}\n\t}\n\n\tfunction _fixListIndents( item ) {\n\t\tlet maxIndent = 0;\n\t\tlet fixBy = null;\n\n\t\twhile ( item && item.is( 'listItem' ) ) {\n\t\t\tconst itemIndent = item.getAttribute( 'listIndent' );\n\n\t\t\tif ( itemIndent > maxIndent ) {\n\t\t\t\tlet newIndent;\n\n\t\t\t\tif ( fixBy === null ) {\n\t\t\t\t\tfixBy = itemIndent - maxIndent;\n\t\t\t\t\tnewIndent = maxIndent;\n\t\t\t\t} else {\n\t\t\t\t\tif ( fixBy > itemIndent ) {\n\t\t\t\t\t\tfixBy = itemIndent;\n\t\t\t\t\t}\n\n\t\t\t\t\tnewIndent = itemIndent - fixBy;\n\t\t\t\t}\n\n\t\t\t\twriter.setAttribute( 'listIndent', newIndent, item );\n\n\t\t\t\tapplied = true;\n\t\t\t} else {\n\t\t\t\tfixBy = null;\n\t\t\t\tmaxIndent = item.getAttribute( 'listIndent' ) + 1;\n\t\t\t}\n\n\t\t\titem = item.nextSibling;\n\t\t}\n\t}\n\n\tfunction _fixListTypes( item ) {\n\t\tlet typesStack = [];\n\t\tlet prev = null;\n\n\t\twhile ( item && item.is( 'listItem' ) ) {\n\t\t\tconst itemIndent = item.getAttribute( 'listIndent' );\n\n\t\t\tif ( prev && prev.getAttribute( 'listIndent' ) > itemIndent ) {\n\t\t\t\ttypesStack = typesStack.slice( 0, itemIndent + 1 );\n\t\t\t}\n\n\t\t\tif ( itemIndent != 0 ) {\n\t\t\t\tif ( typesStack[ itemIndent ] ) {\n\t\t\t\t\tconst type = typesStack[ itemIndent ];\n\n\t\t\t\t\tif ( item.getAttribute( 'listType' ) != type ) {\n\t\t\t\t\t\twriter.setAttribute( 'listType', type, item );\n\n\t\t\t\t\t\tapplied = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttypesStack[ itemIndent ] = item.getAttribute( 'listType' );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprev = item;\n\t\t\titem = item.nextSibling;\n\t\t}\n\t}\n}\n\n/**\n * A fixer for pasted content that includes list items.\n *\n * It fixes indentation of pasted list items so the pasted items match correctly to the context they are pasted into.\n *\n * Example:\n *\n *\t\t<listItem listType=\"bulleted\" listIndent=0>A</listItem>\n *\t\t<listItem listType=\"bulleted\" listIndent=1>B^</listItem>\n *\t\t// At ^ paste: <listItem listType=\"bulleted\" listIndent=4>X</listItem>\n *\t\t// <listItem listType=\"bulleted\" listIndent=5>Y</listItem>\n *\t\t<listItem listType=\"bulleted\" listIndent=2>C</listItem>\n *\n * Should become:\n *\n *\t\t<listItem listType=\"bulleted\" listIndent=0>A</listItem>\n *\t\t<listItem listType=\"bulleted\" listIndent=1>BX</listItem>\n *\t\t<listItem listType=\"bulleted\" listIndent=2>Y/listItem>\n *\t\t<listItem listType=\"bulleted\" listIndent=2>C</listItem>\n *\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Array} args Arguments of {@link module:engine/model/model~Model#insertContent}.\n */\nexport function modelIndentPasteFixer( evt, [ content, selectable ] ) {\n\t// Check whether inserted content starts from a `listItem`. If it does not, it means that there are some other\n\t// elements before it and there is no need to fix indents, because even if we insert that content into a list,\n\t// that list will be broken.\n\t// Note: we also need to handle singular elements because inserting item with indent 0 into 0,1,[],2\n\t// would create incorrect model.\n\tlet item = content.is( 'documentFragment' ) ? content.getChild( 0 ) : content;\n\n\tlet selection;\n\n\tif ( !selectable ) {\n\t\tselection = this.document.selection;\n\t} else {\n\t\tselection = this.createSelection( selectable );\n\t}\n\n\tif ( item && item.is( 'listItem' ) ) {\n\t\t// Get a reference list item. Inserted list items will be fixed according to that item.\n\t\tconst pos = selection.getFirstPosition();\n\t\tlet refItem = null;\n\n\t\tif ( pos.parent.is( 'listItem' ) ) {\n\t\t\trefItem = pos.parent;\n\t\t} else if ( pos.nodeBefore && pos.nodeBefore.is( 'listItem' ) ) {\n\t\t\trefItem = pos.nodeBefore;\n\t\t}\n\n\t\t// If there is `refItem` it means that we do insert list items into an existing list.\n\t\tif ( refItem ) {\n\t\t\t// First list item in `data` has indent equal to 0 (it is a first list item). It should have indent equal\n\t\t\t// to the indent of reference item. We have to fix the first item and all of it's children and following siblings.\n\t\t\t// Indent of all those items has to be adjusted to reference item.\n\t\t\tconst indentChange = refItem.getAttribute( 'listIndent' );\n\n\t\t\t// Fix only if there is anything to fix.\n\t\t\tif ( indentChange > 0 ) {\n\t\t\t\t// Adjust indent of all \"first\" list items in inserted data.\n\t\t\t\twhile ( item && item.is( 'listItem' ) ) {\n\t\t\t\t\titem._setAttribute( 'listIndent', item.getAttribute( 'listIndent' ) + indentChange );\n\n\t\t\t\t\titem = item.nextSibling;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Helper function that converts children of a given `<li>` view element into corresponding model elements.\n// The function maintains proper order of elements if model `listItem` is split during the conversion\n// due to block children conversion.\n//\n// @param {module:engine/model/element~Element} listItemModel List item model element to which converted children will be inserted.\n// @param {Iterable.<module:engine/view/node~Node>} viewChildren View elements which will be converted.\n// @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n// @returns {module:engine/model/position~Position} Position on which next elements should be inserted after children conversion.\nfunction viewToModelListItemChildrenConverter( listItemModel, viewChildren, conversionApi ) {\n\tconst { writer, schema } = conversionApi;\n\n\t// A position after the last inserted `listItem`.\n\tlet nextPosition = writer.createPositionAfter( listItemModel );\n\n\t// Check all children of the converted `<li>`. At this point we assume there are no \"whitespace\" view text nodes\n\t// in view list, between view list items. This should be handled by `<ul>` and `<ol>` converters.\n\tfor ( const child of viewChildren ) {\n\t\tif ( child.name == 'ul' || child.name == 'ol' ) {\n\t\t\t// If the children is a list, we will insert its conversion result after currently handled `listItem`.\n\t\t\t// Then, next insertion position will be set after all the new list items (and maybe other elements if\n\t\t\t// something split list item).\n\t\t\t//\n\t\t\t// If this is a list, we expect that some `listItem`s and possibly other blocks will be inserted, however `.modelCursor`\n\t\t\t// should be set after last `listItem` (or block). This is why it feels safe to use it as `nextPosition`\n\t\t\tnextPosition = conversionApi.convertItem( child, nextPosition ).modelCursor;\n\t\t} else {\n\t\t\t// If this is not a list, try inserting content at the end of the currently handled `listItem`.\n\t\t\tconst result = conversionApi.convertItem( child, writer.createPositionAt( listItemModel, 'end' ) );\n\n\t\t\t// It may end up that the current `listItem` becomes split (if that content cannot be inside `listItem`). For example:\n\t\t\t//\n\t\t\t// <li><p>Foo</p></li>\n\t\t\t//\n\t\t\t// will be converted to:\n\t\t\t//\n\t\t\t// <listItem></listItem><paragraph>Foo</paragraph><listItem></listItem>\n\t\t\t//\n\t\t\tconst convertedChild = result.modelRange.start.nodeAfter;\n\t\t\tconst wasSplit = convertedChild && convertedChild.is( 'element' ) && !schema.checkChild( listItemModel, convertedChild.name );\n\n\t\t\tif ( wasSplit ) {\n\t\t\t\t// As `lastListItem` got split, we need to update it to the second part of the split `listItem` element.\n\t\t\t\t//\n\t\t\t\t// `modelCursor` should be set to a position where the conversion should continue. There are multiple possible scenarios\n\t\t\t\t// that may happen. Usually, `modelCursor` (marked as `#` below) would point to the second list item after conversion:\n\t\t\t\t//\n\t\t\t\t//\t\t`<li><p>Foo</p></li>` -> `<listItem></listItem><paragraph>Foo</paragraph><listItem>#</listItem>`\n\t\t\t\t//\n\t\t\t\t// However, in some cases, like auto-paragraphing, the position is placed at the end of the block element:\n\t\t\t\t//\n\t\t\t\t//\t\t`<li><div>Foo</div></li>` -> `<listItem></listItem><paragraph>Foo#</paragraph><listItem></listItem>`\n\t\t\t\t//\n\t\t\t\t// or after an element if another element broken auto-paragraphed element:\n\t\t\t\t//\n\t\t\t\t//\t\t`<li><div><h2>Foo</h2></div></li>` -> `<listItem></listItem><heading1>Foo</heading1>#<listItem></listItem>`\n\t\t\t\t//\n\t\t\t\t// We need to check for such cases and use proper list item and position based on it.\n\t\t\t\t//\n\t\t\t\tif ( result.modelCursor.parent.is( 'listItem' ) ) {\n\t\t\t\t\t// (1).\n\t\t\t\t\tlistItemModel = result.modelCursor.parent;\n\t\t\t\t} else {\n\t\t\t\t\t// (2), (3).\n\t\t\t\t\tlistItemModel = findNextListItem( result.modelCursor );\n\t\t\t\t}\n\n\t\t\t\tnextPosition = writer.createPositionAfter( listItemModel );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nextPosition;\n}\n\n// Helper function that seeks for a next list item starting from given `startPosition`.\nfunction findNextListItem( startPosition ) {\n\tconst treeWalker = new TreeWalker( { startPosition } );\n\n\tlet value;\n\n\tdo {\n\t\tvalue = treeWalker.next();\n\t} while ( !value.value.item.is( 'listItem' ) );\n\n\treturn value.value.item;\n}\n\n// Helper function that takes all children of given `viewRemovedItem` and moves them in a correct place, according\n// to other given parameters.\nfunction hoistNestedLists( nextIndent, modelRemoveStartPosition, viewRemoveStartPosition, viewRemovedItem, conversionApi, model ) {\n\t// Find correct previous model list item element.\n\t// The element has to have either same or smaller indent than given reference indent.\n\t// This will be the model element which will get nested items (if it has smaller indent) or sibling items (if it has same indent).\n\t// Keep in mind that such element might not be found, if removed item was the first item.\n\tconst prevModelItem = getSiblingListItem( modelRemoveStartPosition.nodeBefore, {\n\t\tsameIndent: true,\n\t\tsmallerIndent: true,\n\t\tlistIndent: nextIndent,\n\t\tfoo: 'b'\n\t} );\n\n\tconst mapper = conversionApi.mapper;\n\tconst viewWriter = conversionApi.writer;\n\n\t// Indent of found element or `null` if the element has not been found.\n\tconst prevIndent = prevModelItem ? prevModelItem.getAttribute( 'listIndent' ) : null;\n\n\tlet insertPosition;\n\n\tif ( !prevModelItem ) {\n\t\t// If element has not been found, simply insert lists at the position where the removed item was:\n\t\t//\n\t\t// Lorem ipsum.\n\t\t// 1 -------- <--- this is removed, no previous list item, put nested items in place of removed item.\n\t\t// 1.1 -------- <--- this is reference indent.\n\t\t// 1.1.1 --------\n\t\t// 1.1.2 --------\n\t\t// 1.2 --------\n\t\t//\n\t\t// Becomes:\n\t\t//\n\t\t// Lorem ipsum.\n\t\t// 1.1 --------\n\t\t// 1.1.1 --------\n\t\t// 1.1.2 --------\n\t\t// 1.2 --------\n\t\tinsertPosition = viewRemoveStartPosition;\n\t} else if ( prevIndent == nextIndent ) {\n\t\t// If element has been found and has same indent as reference indent it means that nested items should\n\t\t// become siblings of found element:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.2 -------- <--- this is `prevModelItem`.\n\t\t// 2 -------- <--- this is removed, previous list item has indent same as reference indent.\n\t\t// 2.1 -------- <--- this is reference indent, this and 2.2 should become siblings of 1.2.\n\t\t// 2.2 --------\n\t\t//\n\t\t// Becomes:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.2 --------\n\t\t// 2.1 --------\n\t\t// 2.2 --------\n\t\tconst prevViewList = mapper.toViewElement( prevModelItem ).parent;\n\t\tinsertPosition = viewWriter.createPositionAfter( prevViewList );\n\t} else {\n\t\t// If element has been found and has smaller indent as reference indent it means that nested items\n\t\t// should become nested items of found item:\n\t\t//\n\t\t// 1 -------- <--- this is `prevModelItem`.\n\t\t// 1.1 -------- <--- this is removed, previous list item has indent smaller than reference indent.\n\t\t// 1.1.1 -------- <--- this is reference indent, this and 1.1.1 should become nested items of 1.\n\t\t// 1.1.2 --------\n\t\t// 1.2 --------\n\t\t//\n\t\t// Becomes:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1.1 --------\n\t\t// 1.1.2 --------\n\t\t// 1.2 --------\n\t\t//\n\t\t// Note: in this case 1.1.1 have indent 2 while 1 have indent 0. In model that should not be possible,\n\t\t// because following item may have indent bigger only by one. But this is fixed by postfixer.\n\t\tconst modelPosition = model.createPositionAt( prevModelItem, 'end' );\n\t\tinsertPosition = mapper.toViewPosition( modelPosition );\n\t}\n\n\tinsertPosition = positionAfterUiElements( insertPosition );\n\n\t// Handle multiple lists. This happens if list item has nested numbered and bulleted lists. Following lists\n\t// are inserted after the first list (no need to recalculate insertion position for them).\n\tfor ( const child of [ ...viewRemovedItem.getChildren() ] ) {\n\t\tif ( isList( child ) ) {\n\t\t\tinsertPosition = viewWriter.move( viewWriter.createRangeOn( child ), insertPosition ).end;\n\n\t\t\tmergeViewLists( viewWriter, child, child.nextSibling );\n\t\t\tmergeViewLists( viewWriter, child.previousSibling, child );\n\t\t}\n\t}\n}\n\n// Checks if view element is a list type (ul or ol).\n//\n// @param {module:engine/view/element~Element} viewElement\n// @returns {Boolean}\nfunction isList( viewElement ) {\n\treturn viewElement.is( 'ol' ) || viewElement.is( 'ul' );\n}\n\n// Calculates the indent value for a list item. Handles HTML compliant and non-compliant lists.\n//\n// Also, fixes non HTML compliant lists indents:\n//\n//\t\tbefore: fixed list:\n//\t\tOL OL\n//\t\t|-> LI (parent LIs: 0) |-> LI (indent: 0)\n//\t\t |-> OL |-> OL\n//\t\t |-> OL |\n//\t\t | |-> OL |\n//\t\t | |-> OL |\n//\t\t | |-> LI (parent LIs: 1) |-> LI (indent: 1)\n//\t\t |-> LI (parent LIs: 1) |-> LI (indent: 1)\n//\n//\t\tbefore: fixed list:\n//\t\tOL OL\n//\t\t|-> OL |\n//\t\t |-> OL |\n//\t\t |-> OL |\n//\t\t |-> LI (parent LIs: 0) |-> LI (indent: 0)\n//\n//\t\tbefore: fixed list:\n//\t\tOL OL\n//\t\t|-> LI (parent LIs: 0) |-> LI (indent: 0)\n//\t\t|-> OL |-> OL\n//\t\t |-> LI (parent LIs: 0) |-> LI (indent: 1)\n//\n// @param {module:engine/view/element~Element} listItem\n// @param {Object} conversionStore\n// @returns {Number}\nfunction getIndent( listItem ) {\n\tlet indent = 0;\n\n\tlet parent = listItem.parent;\n\n\twhile ( parent ) {\n\t\t// Each LI in the tree will result in an increased indent for HTML compliant lists.\n\t\tif ( parent.is( 'li' ) ) {\n\t\t\tindent++;\n\t\t} else {\n\t\t\t// If however the list is nested in other list we should check previous sibling of any of the list elements...\n\t\t\tconst previousSibling = parent.previousSibling;\n\n\t\t\t// ...because the we might need increase its indent:\n\t\t\t//\t\tbefore: fixed list:\n\t\t\t//\t\tOL OL\n\t\t\t//\t\t|-> LI (parent LIs: 0) |-> LI (indent: 0)\n\t\t\t//\t\t|-> OL |-> OL\n\t\t\t//\t\t |-> LI (parent LIs: 0) |-> LI (indent: 1)\n\t\t\tif ( previousSibling && previousSibling.is( 'li' ) ) {\n\t\t\t\tindent++;\n\t\t\t}\n\t\t}\n\n\t\tparent = parent.parent;\n\t}\n\n\treturn indent;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 list/listediting\n */\n\nimport ListCommand from './listcommand';\nimport IndentCommand from './indentcommand';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';\n\nimport {\n\tcleanList,\n\tcleanListItem,\n\tmodelViewInsertion,\n\tmodelViewChangeType,\n\tmodelViewMergeAfterChangeType,\n\tmodelViewMergeAfter,\n\tmodelViewRemove,\n\tmodelViewSplitOnInsert,\n\tmodelViewChangeIndent,\n\tmodelChangePostFixer,\n\tmodelIndentPasteFixer,\n\tviewModelConverter,\n\tmodelToViewPosition,\n\tviewToModelPosition\n} from './converters';\n\n/**\n * The engine of the list feature. It handles creating, editing and removing lists and list items.\n *\n * It registers the `'numberedList'`, `'bulletedList'`, `'indentList'` and `'outdentList'` commands.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ListEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ListEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ Paragraph ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Schema.\n\t\t// Note: in case `$block` will ever be allowed in `listItem`, keep in mind that this feature\n\t\t// uses `Selection#getSelectedBlocks()` without any additional processing to obtain all selected list items.\n\t\t// If there are blocks allowed inside list item, algorithms using `getSelectedBlocks()` will have to be modified.\n\t\teditor.model.schema.register( 'listItem', {\n\t\t\tinheritAllFrom: '$block',\n\t\t\tallowAttributes: [ 'listType', 'listIndent' ]\n\t\t} );\n\n\t\t// Converters.\n\t\tconst data = editor.data;\n\t\tconst editing = editor.editing;\n\n\t\teditor.model.document.registerPostFixer( writer => modelChangePostFixer( editor.model, writer ) );\n\n\t\tediting.mapper.registerViewToModelLength( 'li', getViewListItemLength );\n\t\tdata.mapper.registerViewToModelLength( 'li', getViewListItemLength );\n\n\t\tediting.mapper.on( 'modelToViewPosition', modelToViewPosition( editing.view ) );\n\t\tediting.mapper.on( 'viewToModelPosition', viewToModelPosition( editor.model ) );\n\t\tdata.mapper.on( 'modelToViewPosition', modelToViewPosition( editing.view ) );\n\n\t\tediting.downcastDispatcher.on( 'insert', modelViewSplitOnInsert, { priority: 'high' } );\n\t\tediting.downcastDispatcher.on( 'insert:listItem', modelViewInsertion( editor.model ) );\n\t\tdata.downcastDispatcher.on( 'insert', modelViewSplitOnInsert, { priority: 'high' } );\n\t\tdata.downcastDispatcher.on( 'insert:listItem', modelViewInsertion( editor.model ) );\n\n\t\tediting.downcastDispatcher.on( 'attribute:listType:listItem', modelViewChangeType, { priority: 'high' } );\n\t\tediting.downcastDispatcher.on( 'attribute:listType:listItem', modelViewMergeAfterChangeType, { priority: 'low' } );\n\t\tediting.downcastDispatcher.on( 'attribute:listIndent:listItem', modelViewChangeIndent( editor.model ) );\n\n\t\tediting.downcastDispatcher.on( 'remove:listItem', modelViewRemove( editor.model ) );\n\t\tediting.downcastDispatcher.on( 'remove', modelViewMergeAfter, { priority: 'low' } );\n\n\t\tdata.upcastDispatcher.on( 'element:ul', cleanList, { priority: 'high' } );\n\t\tdata.upcastDispatcher.on( 'element:ol', cleanList, { priority: 'high' } );\n\t\tdata.upcastDispatcher.on( 'element:li', cleanListItem, { priority: 'high' } );\n\t\tdata.upcastDispatcher.on( 'element:li', viewModelConverter );\n\n\t\t// Fix indentation of pasted items.\n\t\teditor.model.on( 'insertContent', modelIndentPasteFixer, { priority: 'high' } );\n\n\t\t// Register commands for numbered and bulleted list.\n\t\teditor.commands.add( 'numberedList', new ListCommand( editor, 'numbered' ) );\n\t\teditor.commands.add( 'bulletedList', new ListCommand( editor, 'bulleted' ) );\n\n\t\t// Register commands for indenting.\n\t\teditor.commands.add( 'indentList', new IndentCommand( editor, 'forward' ) );\n\t\teditor.commands.add( 'outdentList', new IndentCommand( editor, 'backward' ) );\n\n\t\tconst viewDocument = editing.view.document;\n\n\t\t// Overwrite default Enter key behavior.\n\t\t// If Enter key is pressed with selection collapsed in empty list item, outdent it instead of breaking it.\n\t\tthis.listenTo( viewDocument, 'enter', ( evt, data ) => {\n\t\t\tconst doc = this.editor.model.document;\n\t\t\tconst positionParent = doc.selection.getLastPosition().parent;\n\n\t\t\tif ( doc.selection.isCollapsed && positionParent.name == 'listItem' && positionParent.isEmpty ) {\n\t\t\t\tthis.editor.execute( 'outdentList' );\n\n\t\t\t\tdata.preventDefault();\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t} );\n\n\t\t// Overwrite default Backspace key behavior.\n\t\t// If Backspace key is pressed with selection collapsed on first position in first list item, outdent it. #83\n\t\tthis.listenTo( viewDocument, 'delete', ( evt, data ) => {\n\t\t\t// Check conditions from those that require less computations like those immediately available.\n\t\t\tif ( data.direction !== 'backward' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst selection = this.editor.model.document.selection;\n\n\t\t\tif ( !selection.isCollapsed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst firstPosition = selection.getFirstPosition();\n\n\t\t\tif ( !firstPosition.isAtStart ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst positionParent = firstPosition.parent;\n\n\t\t\tif ( positionParent.name !== 'listItem' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst previousIsAListItem = positionParent.previousSibling && positionParent.previousSibling.name === 'listItem';\n\n\t\t\tif ( previousIsAListItem ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.editor.execute( 'outdentList' );\n\n\t\t\tdata.preventDefault();\n\t\t\tevt.stop();\n\t\t}, { priority: 'high' } );\n\n\t\tconst getCommandExecuter = commandName => {\n\t\t\treturn ( data, cancel ) => {\n\t\t\t\tconst command = this.editor.commands.get( commandName );\n\n\t\t\t\tif ( command.isEnabled ) {\n\t\t\t\t\tthis.editor.execute( commandName );\n\t\t\t\t\tcancel();\n\t\t\t\t}\n\t\t\t};\n\t\t};\n\n\t\teditor.keystrokes.set( 'Tab', getCommandExecuter( 'indentList' ) );\n\t\teditor.keystrokes.set( 'Shift+Tab', getCommandExecuter( 'outdentList' ) );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tafterInit() {\n\t\tconst commands = this.editor.commands;\n\n\t\tconst indent = commands.get( 'indent' );\n\t\tconst outdent = commands.get( 'outdent' );\n\n\t\tif ( indent ) {\n\t\t\tindent.registerChildCommand( commands.get( 'indentList' ) );\n\t\t}\n\n\t\tif ( outdent ) {\n\t\t\toutdent.registerChildCommand( commands.get( 'outdentList' ) );\n\t\t}\n\t}\n}\n\nfunction getViewListItemLength( element ) {\n\tlet length = 1;\n\n\tfor ( const child of element.getChildren() ) {\n\t\tif ( child.name == 'ul' || child.name == 'ol' ) {\n\t\t\tfor ( const item of child.getChildren() ) {\n\t\t\t\tlength += getViewListItemLength( item );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn length;\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M7 5.75c0 .414.336.75.75.75h9.5a.75.75 0 1 0 0-1.5h-9.5a.75.75 0 0 0-.75.75zM3.5 3v5H2V3.7H1v-1h2.5V3zM.343 17.857l2.59-3.257H2.92a.6.6 0 1 0-1.04 0H.302a2 2 0 1 1 3.995 0h-.001c-.048.405-.16.734-.333.988-.175.254-.59.692-1.244 1.312H4.3v1h-4l.043-.043zM7 14.75a.75.75 0 0 1 .75-.75h9.5a.75.75 0 1 1 0 1.5h-9.5a.75.75 0 0 1-.75-.75z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M7 5.75c0 .414.336.75.75.75h9.5a.75.75 0 1 0 0-1.5h-9.5a.75.75 0 0 0-.75.75zm-6 0C1 4.784 1.777 4 2.75 4c.966 0 1.75.777 1.75 1.75 0 .966-.777 1.75-1.75 1.75C1.784 7.5 1 6.723 1 5.75zm6 9c0 .414.336.75.75.75h9.5a.75.75 0 1 0 0-1.5h-9.5a.75.75 0 0 0-.75.75zm-6 0c0-.966.777-1.75 1.75-1.75.966 0 1.75.777 1.75 1.75 0 .966-.777 1.75-1.75 1.75-.966 0-1.75-.777-1.75-1.75z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module list/listui\n */\nimport { createUIComponent } from './utils';\nimport numberedListIcon from '../theme/icons/numberedlist.svg';\nimport bulletedListIcon from '../theme/icons/bulletedlist.svg';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n/**\n * The list UI feature. It introduces the `'numberedList'` and `'bulletedList'` buttons that\n * allow to convert paragraphs to and from list items and indent or outdent them.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ListUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const t = this.editor.t;\n // Create two buttons and link them with numberedList and bulletedList commands.\n createUIComponent(this.editor, 'numberedList', t('ae'), numberedListIcon);\n createUIComponent(this.editor, 'bulletedList', t('af'), bulletedListIcon);\n }\n}","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 512 512\\\"><path d=\\\"M415.462 96.978c-88.1-88.1-230.824-88.1-318.924 0-87.22 87.22-87.22 229.943 0 318.044 88.1 88.1 230.824 88.1 318.924 0 87.22-88.1 87.22-230.824 0-318.044zM246.31 437.047c-24.668 0-44.05-20.263-44.05-44.05 0-24.669 19.382-44.05 44.05-44.05 24.668 0 44.05 19.381 44.05 44.05 0 23.787-20.263 44.05-44.05 44.05zm30.835-154.176v23.787c0 12.334-4.405 16.74-15.858 16.74h-32.597c-11.453 0-15.858-4.406-15.858-16.74v-53.742c0-14.096 14.096-18.5 26.43-22.025 2.643-.88 6.167-1.762 8.81-2.643 16.74-6.167 26.43-13.215 26.43-30.835 0-6.167 0-23.787-29.073-23.787-17.62 0-33.478 7.048-43.17 10.572-5.285 2.643-7.929 3.524-11.453 3.524-5.286 0-10.572-4.405-11.453-9.691L167.9 148.958c-.88-2.643-.88-5.286-.88-7.048 0-21.145 66.075-33.479 88.1-33.479 55.503 0 93.387 36.122 93.387 88.982 0 58.146-44.05 75.767-71.362 85.458z\\\"/></svg>\"","export default \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n xmlns:dc=\\\"http://purl.org/dc/elements/1.1/\\\"\\n xmlns:cc=\\\"http://creativecommons.org/ns#\\\"\\n xmlns:rdf=\\\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\\\"\\n xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n xmlns:sodipodi=\\\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\\\"\\n xmlns:inkscape=\\\"http://www.inkscape.org/namespaces/inkscape\\\"\\n class=\\\"ck ck-icon ck-button__icon\\\"\\n viewBox=\\\"0 0 20 20\\\"\\n version=\\\"1.1\\\"\\n id=\\\"svg10\\\"\\n sodipodi:docname=\\\"code-block.svg\\\"\\n inkscape:version=\\\"0.92.3 (2405546, 2018-03-11)\\\">\\n <defs\\n id=\\\"defs14\\\" />\\n <sodipodi:namedview\\n pagecolor=\\\"#ffffff\\\"\\n bordercolor=\\\"#666666\\\"\\n borderopacity=\\\"1\\\"\\n objecttolerance=\\\"10\\\"\\n gridtolerance=\\\"10\\\"\\n guidetolerance=\\\"10\\\"\\n inkscape:pageopacity=\\\"0\\\"\\n inkscape:pageshadow=\\\"2\\\"\\n inkscape:window-width=\\\"640\\\"\\n inkscape:window-height=\\\"480\\\"\\n id=\\\"namedview12\\\"\\n showgrid=\\\"false\\\"\\n inkscape:zoom=\\\"33.37544\\\"\\n inkscape:cx=\\\"10.656564\\\"\\n inkscape:cy=\\\"13.670445\\\"\\n inkscape:current-layer=\\\"svg10\\\" />\\n <g\\n id=\\\"g8\\\"\\n style=\\\"fill:none;fill-rule:evenodd\\\"\\n transform=\\\"matrix(0.8751128,0,0,0.8751128,1.3360704,0.91121972)\\\">\\n <g\\n id=\\\"g6\\\"\\n style=\\\"fill:#353535\\\">\\n <g\\n transform=\\\"translate(2,5.6)\\\"\\n id=\\\"g4\\\">\\n <path\\n d=\\\"M 10.5,0.1 15.7,4 v 1.3 l -5.6,4 C 10,9.5 9.8,9.5 9.6,9.5 9.3,9.4 9,8.8 9,8.5 L 9.3,8.1 14,4.6 9.5,1.4 9.3,1.2 C 9.2,0.9 9.2,0.6 9.3,0.4 9.5,0.2 9.8,0 10.1,0 a 0.8,0.8 0 0 1 0.4,0.1 z M 5.3,0.1 0,4 v 1.3 l 5.6,4 C 5.7,9.5 5.9,9.5 6.1,9.5 6.4,9.4 6.8,8.8 6.7,8.5 6.7,8.4 6.7,8.2 6.5,8.1 L 1.5,4.6 6.2,1.4 6.4,1.2 C 6.5,0.9 6.5,0.6 6.4,0.4 6.2,0.2 5.9,0 5.6,0 A 0.8,0.8 0 0 0 5.3,0.1 Z\\\"\\n id=\\\"path2\\\"\\n inkscape:connector-curvature=\\\"0\\\" />\\n </g>\\n </g>\\n </g>\\n <path\\n style=\\\"color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#353535;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.09228408;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate\\\"\\n d=\\\"M 0.22004104,0.22004104 V 0.76600468 19.779959 H 19.779959 V 0.22004104 Z M 1.3119682,1.3119682 H 18.688032 V 18.688032 H 1.3119682 Z\\\"\\n id=\\\"rect3722\\\"\\n inkscape:connector-curvature=\\\"0\\\" />\\n <metadata\\n id=\\\"metadata4596\\\">\\n <rdf:RDF>\\n <cc:Work\\n rdf:about=\\\"\\\">\\n <dc:title></dc:title>\\n <dc:format>image/svg+xml</dc:format>\\n <dc:type\\n rdf:resource=\\\"http://purl.org/dc/dcmitype/StillImage\\\" />\\n </cc:Work>\\n </rdf:RDF>\\n </metadata>\\n</svg>\\n\"","import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';\nimport {toWidget, isWidget} from '@ckeditor/ckeditor5-widget/src/utils';\nimport {setContent} from './widget';\n\nconst codeBlockSymbol = Symbol( 'isOPCodeBlock' );\n\nexport function toCodeBlockWidget( viewElement, writer, label ) {\n\twriter.setCustomProperty( codeBlockSymbol, true, viewElement );\n\treturn toWidget( viewElement, writer, { label: label } );\n}\n\n\nexport function isCodeBlockWidget( viewElement ) {\n\treturn !!viewElement.getCustomProperty( codeBlockSymbol ) && isWidget( viewElement );\n}\n\n\nexport function isCodeBlockWidgetSelected( selection ) {\n\tconst viewElement = selection.getSelectedElement();\n\n\treturn !!( viewElement && isCodeBlockWidget( viewElement ) );\n}\n\nexport function createCodeBlockWidget( modelElement, writer, label ) {\n\tconst container = writer.createContainerElement(\n\t\t'div',\n\t\t{\n\t\t\tclass: 'op-ckeditor--code-block',\n\t\t\ttitle: window.I18n.t('js.editor.macro.toolbar_help')\n\t\t}\n\t);\n\trenderCodeBlockContent( writer, modelElement, container );\n\n\treturn toCodeBlockWidget( container, writer, label );\n}\n\nexport function renderCodeBlockContent( writer, modelElement, container ) {\n\t// Append language element\n\tconst languageClass = modelElement.getAttribute( 'opCodeblockLanguage' ) || 'language-text';\n\tconst language = languageClass.replace(/^language-/, '');\n\tconst langElement = writer.createContainerElement( 'div', { class: 'op-ckeditor--code-block-language' } );\n\tsetTextNode( writer, language, langElement, 'text' );\n\twriter.insert( writer.createPositionAt( container, 0 ), langElement );\n\n\t// Append code block content\n\tconst content = modelElement.getAttribute( 'opCodeblockContent' );\n\tsetTextNode( writer, content, container, '(empty)' );\n}\n\nexport function setTextNode( writer, content, container, empty_text ) {\n const placeholder = writer.createText( content || empty_text );\n writer.insert( writer.createPositionAt( container, 0 ), placeholder );\n}\n","import DomEventObserver from \"@ckeditor/ckeditor5-engine/src/view/observer/domeventobserver\";\n\nexport default class DoubleClickObserver extends DomEventObserver {\n\tconstructor( view ) {\n\t\tsuper( view );\n\n\t\tthis.domEventType = 'dblclick';\n\t}\n\n\tonDomEvent( domEvent ) {\n\t\tthis.fire( domEvent.type, domEvent );\n\t}\n}\n","import icon from '../../icons/code-block.svg';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport {modelCodeBlockToView, viewCodeBlockToModel, codeBlockContentToView} from './converters';\nimport {createCodeBlockWidget, isCodeBlockWidget} from './widget';\nimport DoubleClickObserver from './click-observer';\nimport { getPluginContext } from '../op-context/op-context';\n\nexport default class CodeBlockEditing extends Plugin {\n\n\tstatic get pluginName() {\n\t\treturn 'CodeBlockEditing';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst schema = editor.model.schema;\n\t\tconst conversion = editor.conversion;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\t\tconst pluginContext = getPluginContext(editor);\n\n\t\t// Configure schema.\n\t\tschema.register('codeblock', {\n\t\t\tisObject: true,\n\t\t\tisBlock: true,\n\t\t\tallowContentOf: '$block',\n\t\t\tallowWhere: ['$root', '$block'],\n\t\t\tallowIn: ['$root'],\n\t\t\tallowAttributes: ['opCodeblockLanguage', 'opCodeblockContent']\n\t\t});\n\n\t\tconversion.for( 'upcast' )\n\t\t\t.add(viewCodeBlockToModel());\n\n\t\tconversion.for( 'editingDowncast' )\n\t\t\t.elementToElement( {\n\t\t\t\tmodel: 'codeblock',\n\t\t\t\tview: (modelElement, viewWriter) => {\n\t\t\t\t\treturn createCodeBlockWidget( modelElement, viewWriter, 'Code block' );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.add ( codeBlockContentToView() );\n\n\t\tconversion\n\t\t\t.for('dataDowncast')\n\t\t\t.add(modelCodeBlockToView());\n\n\t\t// Register click handler to code block to edit it immediately\n\t\tview.addObserver( DoubleClickObserver );\n\t\tthis.listenTo( viewDocument, 'dblclick', ( eventInfo, domEventData ) => {\n\t\t\tlet element = domEventData.target;\n\t\t\tlet evt = domEventData.domEvent;\n\n\t\t\t// Avoid opening the widget with modifiers selected to allow selecting the widget\n\t\t\tif (evt.shiftKey || evt.altKey || evt.metaKey) {\n\t\t\t\treturn;\n\t\t\t}\n\n\n\t\t\t// If target is our widget\n\t\t\tif ( !isCodeBlockWidget( element ) ) {\n\t\t\t\telement = element.findAncestor( isCodeBlockWidget );\n\n\t\t\t\tif ( !element ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdomEventData.preventDefault();\n\t\t\tdomEventData.stopPropagation();\n\n\t\t\t// Create model selection over widget.\n\t\t\tconst modelElement = editor.editing.mapper.toModelElement( element );\n\n\t\t\tconst macroService = pluginContext.services.macros;\n\t\t\tconst language = modelElement.getAttribute( 'opCodeblockLanguage' );\n\t\t\tconst content = modelElement.getAttribute( 'opCodeblockContent' );\n\n\t\t\tmacroService\n\t\t\t\t.editCodeBlock( content, language )\n\t\t\t\t.then((update) => editor.model.change(writer => {\n\t\t\t\t\twriter.setAttribute( 'opCodeblockLanguage', update.languageClass, modelElement );\n\t\t\t\t\twriter.setAttribute( 'opCodeblockContent', update.content, modelElement );\n\t\t\t\t})\n\t\t\t);\n\n\t\t} );\n\n\t\t// Register toolbar button to create code block\n\t\teditor.ui.componentFactory.add( 'insertCodeBlock', locale => {\n\t\t\tconst view = new ButtonView( locale );\n\n\t\t\tview.set( {\n\t\t\t\tlabel: window.I18n.t('js.editor.macro.code_block.button'),\n\t\t\t\ticon: icon,\n\t\t\t\ttooltip: true\n\t\t\t} );\n\n\t\t\t// Callback executed once the image is clicked.\n\t\t\tview.on( 'execute', () => {\n\t\t\t\tpluginContext.services.macros\n\t\t\t\t\t.editCodeBlock()\n\t\t\t\t\t.then((update) => editor.model.change(writer => {\n\n\t\t\t\t\t\tconst element = writer.createElement( 'codeblock' );\n\t\t\t\t\t\twriter.setAttribute( 'opCodeblockLanguage', update.languageClass, element );\n\t\t\t\t\t\twriter.setAttribute( 'opCodeblockContent', update.content, element );\n\t\t\t\t\t\teditor.model.insertContent( element, editor.model.document.selection );\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t} );\n\n\t\t\treturn view;\n\t\t} );\n\t}\n}\n","import ModelPosition from '@ckeditor/ckeditor5-engine/src/model/position';\nimport ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';\nimport ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';\nimport ViewRange from '@ckeditor/ckeditor5-engine/src/view/range';\nimport {renderCodeBlockContent} from './widget';\n\n\nexport function modelCodeBlockToView() {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'insert:codeblock', converter, { priority: 'high' } );\n\t};\n\n\tfunction converter( evt, data, conversionApi ) {\n\t\tconst codeBlock = data.item;\n\t\tconst language = codeBlock.getAttribute('opCodeblockLanguage') || 'language-text';\n\t\tconst content = codeBlock.getAttribute('opCodeblockContent');\n\n\t\t// Consume the codeblock and text\n\t\tconversionApi.consumable.consume( codeBlock, 'insert' );\n\n\t\t// Wrap the element in a <pre> <code> block\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst preElement = viewWriter.createContainerElement( 'pre' );\n\t\tconst langElement = viewWriter.createContainerElement( 'div', { class: 'op-ckeditor--code-block-language' } );\n\t\tconst codeElement = viewWriter.createContainerElement( 'code', { class: language } );\n\t\tconst langContent = viewWriter.createText( language );\n\t\tconst contentElement = viewWriter.createText( content );\n\n\t\tviewWriter.insert( viewWriter.createPositionAt( codeElement, 0 ), contentElement );\n\t\tviewWriter.insert( viewWriter.createPositionAt( langElement, 0 ), langContent );\n\t\tviewWriter.insert( viewWriter.createPositionAt( preElement, 0 ), langElement );\n\t\tviewWriter.insert( viewWriter.createPositionAt( preElement, 0 ), codeElement );\n\n\t\tconversionApi.mapper.bindElements( codeBlock, codeElement );\n\t\tconversionApi.mapper.bindElements( codeBlock, preElement );\n\n\t\t// Insert at matching position\n\t\tconst insertPosition = conversionApi.mapper.toViewPosition( data.range.start );\n\t\tviewWriter.insert( insertPosition, preElement );\n\n\t\tevt.stop();\n\t}\n}\n\nexport function viewCodeBlockToModel() {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'element:pre', converter, { priority: 'high' } );\n\t};\n\n\tfunction converter( evt, data, conversionApi ) {\n\t\t// Do not convert if this is not an \"image figure\".\n\t\tif ( !conversionApi.consumable.test( data.viewItem, { name: true } ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Find an code element inside the pre element.\n\t\tconst codeBlock = Array.from( data.viewItem.getChildren() ).find( viewChild => viewChild.is( 'code' ) );\n\n\t\t// Do not convert if code block is absent\n\t\tif ( !codeBlock || !conversionApi.consumable.consume( codeBlock, { name: true } ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Create the model element\n\t\tconst modelCodeBlock = conversionApi.writer.createElement( 'codeblock' );\n\t\tconversionApi.writer.setAttribute( 'opCodeblockLanguage', codeBlock.getAttribute('class'), modelCodeBlock );\n\n\t\t// Find allowed parent for paragraph that we are going to insert. If current parent does not allow\n\t\t// to insert paragraph but one of the ancestors does then split nodes to allowed parent.\n\t\tconst splitResult = conversionApi.splitToAllowedParent( modelCodeBlock, data.modelCursor );\n\n\t\t// When there is no split result it means that we can't insert paragraph in this position.\n\t\tif ( splitResult ) {\n\t\t\t// Insert codeblock in allowed position.\n\t\t\tconversionApi.writer.insert( modelCodeBlock, splitResult.position );\n\n\t\t\t// Convert text child of codeblock\n\t\t\tconst child = codeBlock.getChild(0);\n\t\t\tconversionApi.consumable.consume( child, { name: true } );\n\t\t\t// Replace last newline since that text is incorrectly mapped\n\t\t\t// Regression OP#28609\n\t\t\tconst content = child.data.replace(/\\n$/, \"\");\n\t\t\tconversionApi.writer.setAttribute( 'opCodeblockContent', content, modelCodeBlock );\n\n\t\t\t// Set as conversion result, attribute converters may use this property.\n\t\t\tdata.modelRange = new ModelRange(\n\t\t\t\tconversionApi.writer.createPositionBefore( modelCodeBlock ),\n\t\t\t\tconversionApi.writer.createPositionAfter( modelCodeBlock )\n\t\t\t);\n\n\t\t\t// Convert after pre element\n\t\t\tdata.modelCursor = data.modelRange.end;\n\t\t}\n\t}\n}\n\n\nexport function codeBlockContentToView() {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'attribute:opCodeblockContent', converter );\n\t\tdispatcher.on( 'attribute:opCodeblockLanguage', converter );\n\t};\n\n\tfunction converter( evt, data, conversionApi ) {\n const modelElement = data.item;\n\n // Mark element as consumed by conversion.\n conversionApi.consumable.consume( data.item, evt.name );\n\n // Get mapped view element to update.\n const viewElement = conversionApi.mapper.toViewElement( modelElement );\n\n // Remove current <div> element contents.\n conversionApi.writer.remove( conversionApi.writer.createRangeOn( viewElement.getChild( 1 ) ) );\n conversionApi.writer.remove( conversionApi.writer.createRangeOn( viewElement.getChild( 0 ) ) );\n\n\t\t// Set current content\n\t\trenderCodeBlockContent( conversionApi.writer, modelElement, viewElement );\n\t}\n}\n","import Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\n\nimport {createToolbarEditButton} from '../../helpers/create-toolbar-edit-button';\nimport {createEditToolbar} from '../../helpers/create-toolbar';\nimport {isCodeBlockWidgetSelected} from './widget';\nimport {getPluginContext} from '../op-context/op-context';\n\nexport default class CodeBlockToolbar extends Plugin {\n\tstatic get requires() {\n\t\treturn [ ContextualBalloon ];\n\t}\n\n\tstatic get pluginName() {\n\t\treturn 'CodeBlockToolbar';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = this.editor.model;\n\t\tconst pluginContext = getPluginContext(editor);\n\n\t\t// Add editing button\n\t\tcreateToolbarEditButton( editor, 'opEditCodeBlock', widget => {\n\t\t\tconst macroService = pluginContext.services.macros;\n\t\t\tconst language = widget.getAttribute( 'opCodeblockLanguage' );\n\t\t\tconst content = widget.getAttribute( 'opCodeblockContent' );\n\n\t\t\tmacroService\n\t\t\t\t.editCodeBlock( content, language )\n\t\t\t\t.then((update) => model.change(writer => {\n\t\t\t\t\twriter.setAttribute( 'opCodeblockLanguage', update.languageClass, widget );\n\t\t\t\t\twriter.setAttribute( 'opCodeblockContent', update.content, widget );\n\t\t\t\t})\n\t\t\t);\n\t\t} );\n\t}\n\n\tafterInit() {\n\t\t// Add actual toolbar\n\t\tcreateEditToolbar(\n\t\t\tthis,\n\t\t\tthis.editor,\n\t\t\t'OPCodeBlock',\n\t\t\tisCodeBlockWidgetSelected\n\t\t);\n\t}\n}\n","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 512 512\\\" width=\\\"20\\\"><path d=\\\"M124 334v14c84 139 279 139 362 0v-14c-83-139-278-139-362 0zm181 91c-46 0-83-38-83-84s37-83 83-83c47 0 84 37 84 83s-37 84-84 84zm42-84c0 23-19 42-42 42s-41-19-41-42 18-42 41-42 42 19 42 42zm83-254L312-32H37v512h127v-46H83V14h210l91 92v91h46V87z\\\"/></svg>\\n\"","import FileDialogButtonView from '@ckeditor/ckeditor5-upload/src/ui/filedialogbuttonview';\n\nexport function getToolbarItems(editor) {\n\teditor.__currentlyDisabled = editor.__currentlyDisabled || [];\n\n\tif (!editor.ui.view.toolbar) {\n\t\treturn [];\n\t}\n\n\treturn editor.ui.view.toolbar.items._items;\n}\n\nexport function disableItems(editor, except) {\n\tjQuery.each(getToolbarItems(editor), function(index, item) {\n\t\tlet toDisable = item;\n\n\t\tif (item instanceof FileDialogButtonView) {\n\t\t\ttoDisable = item.buttonView;\n\t\t} else if (item === except || !item.hasOwnProperty('isEnabled')) {\n\t\t\ttoDisable = null;\n\t\t}\n\n\t\tif (!toDisable) {\n\t\t\t// do nothing\n\t\t} else if (toDisable.isEnabled) {\n\t\t\ttoDisable.isEnabled = false;\n\t\t} else {\n\t\t\teditor.__currentlyDisabled.push(toDisable);\n\t\t}\n\t});\n}\n\nexport function enableItems(editor) {\n\tjQuery.each(getToolbarItems(editor), function(index, item) {\n\t\tlet toEnable = item;\n\n\t\tif (item instanceof FileDialogButtonView) {\n\t\t\ttoEnable = item.buttonView;\n\t\t}\n\n\t\tif (editor.__currentlyDisabled.indexOf(toEnable) < 0) {\n\t\t\ttoEnable.isEnabled = true\n\t\t}\n\t});\n\n\teditor.__currentlyDisabled = [];\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/utils\n */\n\n/**\n * Returns the parent element of given name. Returns undefined if position is not inside desired parent.\n *\n * @param {String} parentName Name of parent element to find.\n * @param {module:engine/model/position~Position|module:engine/model/position~Position} position Position to start searching.\n * @returns {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment}\n */\nexport function findAncestor( parentName, position ) {\n\tlet parent = position.parent;\n\n\twhile ( parent ) {\n\t\tif ( parent.name === parentName ) {\n\t\t\treturn parent;\n\t\t}\n\n\t\tparent = parent.parent;\n\t}\n}\n\n/**\n * A common method to update the numeric value. If a value is the default one, it will be unset.\n *\n * @param {String} key Attribute key.\n * @param {*} value The new attribute value.\n * @param {module:engine/model/item~Item} item Model item on which the attribute will be set.\n * @param {module:engine/model/writer~Writer} writer\n * @param {*} defaultValue Default attribute value. If a value is lower or equal, it will be unset.\n */\nexport function updateNumericAttribute( key, value, item, writer, defaultValue = 1 ) {\n\tif ( value > defaultValue ) {\n\t\twriter.setAttribute( key, value, item );\n\t} else {\n\t\twriter.removeAttribute( key, item );\n\t}\n}\n\n/**\n * Common method to create empty table cell - it will create proper model structure as table cell must have at least one block inside.\n *\n * @param {module:engine/model/writer~Writer} writer Model writer.\n * @param {module:engine/model/position~Position} insertPosition Position at which table cell should be inserted.\n * @param {Object} attributes Element's attributes.\n */\nexport function createEmptyTableCell( writer, insertPosition, attributes = {} ) {\n\tconst tableCell = writer.createElement( 'tableCell', attributes );\n\twriter.insertElement( 'paragraph', tableCell );\n\twriter.insert( tableCell, insertPosition );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/converters/upcasttable\n */\n\nimport { createEmptyTableCell } from '../commands/utils';\n\n/**\n * View table element to model table element conversion helper.\n *\n * This conversion helper converts the table element as well as table rows.\n *\n * @returns {Function} Conversion helper.\n */\nexport default function upcastTable() {\n\treturn dispatcher => {\n\t\tdispatcher.on( 'element:table', ( evt, data, conversionApi ) => {\n\t\t\tconst viewTable = data.viewItem;\n\n\t\t\t// When element was already consumed then skip it.\n\t\t\tif ( !conversionApi.consumable.test( viewTable, { name: true } ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst { rows, headingRows, headingColumns } = scanTable( viewTable );\n\n\t\t\t// Only set attributes if values is greater then 0.\n\t\t\tconst attributes = {};\n\n\t\t\tif ( headingColumns ) {\n\t\t\t\tattributes.headingColumns = headingColumns;\n\t\t\t}\n\n\t\t\tif ( headingRows ) {\n\t\t\t\tattributes.headingRows = headingRows;\n\t\t\t}\n\n\t\t\tconst table = conversionApi.writer.createElement( 'table', attributes );\n\n\t\t\t// Insert element on allowed position.\n\t\t\tconst splitResult = conversionApi.splitToAllowedParent( table, data.modelCursor );\n\n\t\t\t// When there is no split result it means that we can't insert element to model tree, so let's skip it.\n\t\t\tif ( !splitResult ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconversionApi.writer.insert( table, splitResult.position );\n\t\t\tconversionApi.consumable.consume( viewTable, { name: true } );\n\n\t\t\tif ( rows.length ) {\n\t\t\t\t// Upcast table rows in proper order (heading rows first).\n\t\t\t\trows.forEach( row => conversionApi.convertItem( row, conversionApi.writer.createPositionAt( table, 'end' ) ) );\n\t\t\t} else {\n\t\t\t\t// Create one row and one table cell for empty table.\n\t\t\t\tconst row = conversionApi.writer.createElement( 'tableRow' );\n\t\t\t\tconversionApi.writer.insert( row, conversionApi.writer.createPositionAt( table, 'end' ) );\n\n\t\t\t\tcreateEmptyTableCell( conversionApi.writer, conversionApi.writer.createPositionAt( row, 'end' ) );\n\t\t\t}\n\n\t\t\t// Set conversion result range.\n\t\t\tdata.modelRange = conversionApi.writer.createRange(\n\t\t\t\t// Range should start before inserted element\n\t\t\t\tconversionApi.writer.createPositionBefore( table ),\n\t\t\t\t// Should end after but we need to take into consideration that children could split our\n\t\t\t\t// element, so we need to move range after parent of the last converted child.\n\t\t\t\t// before: <allowed>[]</allowed>\n\t\t\t\t// after: <allowed>[<converted><child></child></converted><child></child><converted>]</converted></allowed>\n\t\t\t\tconversionApi.writer.createPositionAfter( table )\n\t\t\t);\n\n\t\t\t// Now we need to check where the modelCursor should be.\n\t\t\t// If we had to split parent to insert our element then we want to continue conversion inside split parent.\n\t\t\t//\n\t\t\t// before: <allowed><notAllowed>[]</notAllowed></allowed>\n\t\t\t// after: <allowed><notAllowed></notAllowed><converted></converted><notAllowed>[]</notAllowed></allowed>\n\t\t\tif ( splitResult.cursorParent ) {\n\t\t\t\tdata.modelCursor = conversionApi.writer.createPositionAt( splitResult.cursorParent, 0 );\n\n\t\t\t\t// Otherwise just continue after inserted element.\n\t\t\t} else {\n\t\t\t\tdata.modelCursor = data.modelRange.end;\n\t\t\t}\n\t\t} );\n\t};\n}\n\nexport function upcastTableCell( elementName ) {\n\treturn dispatcher => {\n\t\tdispatcher.on( `element:${ elementName }`, ( evt, data, conversionApi ) => {\n\t\t\tconst viewTableCell = data.viewItem;\n\n\t\t\t// When element was already consumed then skip it.\n\t\t\tif ( !conversionApi.consumable.test( viewTableCell, { name: true } ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst tableCell = conversionApi.writer.createElement( 'tableCell' );\n\n\t\t\t// Insert element on allowed position.\n\t\t\tconst splitResult = conversionApi.splitToAllowedParent( tableCell, data.modelCursor );\n\n\t\t\t// When there is no split result it means that we can't insert element to model tree, so let's skip it.\n\t\t\tif ( !splitResult ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconversionApi.writer.insert( tableCell, splitResult.position );\n\t\t\tconversionApi.consumable.consume( viewTableCell, { name: true } );\n\n\t\t\tconst modelCursor = conversionApi.writer.createPositionAt( tableCell, 0 );\n\t\t\tconversionApi.convertChildren( viewTableCell, modelCursor );\n\n\t\t\t// Ensure a paragraph in the model for empty table cells.\n\t\t\tif ( !tableCell.childCount ) {\n\t\t\t\tconversionApi.writer.insertElement( 'paragraph', modelCursor );\n\t\t\t}\n\n\t\t\t// Set conversion result range.\n\t\t\tdata.modelRange = conversionApi.writer.createRange(\n\t\t\t\t// Range should start before inserted element\n\t\t\t\tconversionApi.writer.createPositionBefore( tableCell ),\n\t\t\t\t// Should end after but we need to take into consideration that children could split our\n\t\t\t\t// element, so we need to move range after parent of the last converted child.\n\t\t\t\t// before: <allowed>[]</allowed>\n\t\t\t\t// after: <allowed>[<converted><child></child></converted><child></child><converted>]</converted></allowed>\n\t\t\t\tconversionApi.writer.createPositionAfter( tableCell )\n\t\t\t);\n\n\t\t\t// Continue after inserted element.\n\t\t\tdata.modelCursor = data.modelRange.end;\n\t\t} );\n\t};\n}\n\n// Scans table rows and extracts required metadata from the table:\n//\n// headingRows - the number of rows that goes as table header.\n// headingColumns - max number of row headings.\n// rows - sorted `<tr>`s as they should go into the model - ie. if `<thead>` is inserted after `<tbody>` in the view.\n//\n// @param {module:engine/view/element~Element} viewTable\n// @returns {{headingRows, headingColumns, rows}}\nfunction scanTable( viewTable ) {\n\tconst tableMeta = {\n\t\theadingRows: 0,\n\t\theadingColumns: 0\n\t};\n\n\t// The `<tbody>` and <thead> sections in the DOM do not have to be in order `<thead>` -> `<tbody>` and there might be more then one of\n\t// them.\n\t// As the model does not have those sections, rows from different sections must be sorted.\n\t// For example, below is a valid HTML table:\n\t//\n\t//\t\t<table>\n\t//\t\t\t<tbody><tr><td>2</td></tr></tbody>\n\t//\t\t\t<thead><tr><td>1</td></tr></thead>\n\t//\t\t\t<tbody><tr><td>3</td></tr></tbody>\n\t//\t\t</table>\n\t//\n\t// But browsers will render rows in order as: 1 as heading and 2 and 3 as (body).\n\tconst headRows = [];\n\tconst bodyRows = [];\n\n\t// Currently the editor does not support more then one <thead> section.\n\t// Only the first <thead> from the view will be used as heading rows and others will be converted to body rows.\n\tlet firstTheadElement;\n\n\tfor ( const tableChild of Array.from( viewTable.getChildren() ) ) {\n\t\t// Only <thead>, <tbody> & <tfoot> from allowed table children can have <tr>s.\n\t\t// The else is for future purposes (mainly <caption>).\n\t\tif ( tableChild.name === 'tbody' || tableChild.name === 'thead' || tableChild.name === 'tfoot' ) {\n\t\t\t// Save the first <thead> in the table as table header - all other ones will be converted to table body rows.\n\t\t\tif ( tableChild.name === 'thead' && !firstTheadElement ) {\n\t\t\t\tfirstTheadElement = tableChild;\n\t\t\t}\n\n\t\t\t// There might be some extra empty text nodes between the `tr`s.\n\t\t\t// Make sure further code operates on `tr`s only. (#145)\n\t\t\tconst trs = Array.from( tableChild.getChildren() ).filter( el => el.is( 'element', 'tr' ) );\n\n\t\t\tfor ( const tr of trs ) {\n\t\t\t\t// This <tr> is a child of a first <thead> element.\n\t\t\t\tif ( tr.parent.name === 'thead' && tr.parent === firstTheadElement ) {\n\t\t\t\t\ttableMeta.headingRows++;\n\t\t\t\t\theadRows.push( tr );\n\t\t\t\t} else {\n\t\t\t\t\tbodyRows.push( tr );\n\t\t\t\t\t// For other rows check how many column headings this row has.\n\n\t\t\t\t\tconst headingCols = scanRowForHeadingColumns( tr, tableMeta, firstTheadElement );\n\n\t\t\t\t\tif ( headingCols > tableMeta.headingColumns ) {\n\t\t\t\t\t\ttableMeta.headingColumns = headingCols;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\ttableMeta.rows = [ ...headRows, ...bodyRows ];\n\n\treturn tableMeta;\n}\n\n// Scans `<tr>` and its children for metadata:\n// - For heading row:\n// - either adds this row to heading or body rows.\n// - updates number of heading rows.\n// - For body rows:\n// - calculates the number of column headings.\n//\n// @param {module:engine/view/element~Element} tr\n// @returns {Number}\nfunction scanRowForHeadingColumns( tr ) {\n\tlet headingColumns = 0;\n\tlet index = 0;\n\n\t// Filter out empty text nodes from tr children.\n\tconst children = Array.from( tr.getChildren() )\n\t\t.filter( child => child.name === 'th' || child.name === 'td' );\n\n\t// Count starting adjacent <th> elements of a <tr>.\n\twhile ( index < children.length && children[ index ].name === 'th' ) {\n\t\tconst th = children[ index ];\n\n\t\t// Adjust columns calculation by the number of spanned columns.\n\t\tconst colspan = parseInt( th.getAttribute( 'colspan' ) || 1 );\n\n\t\theadingColumns = headingColumns + colspan;\n\t\tindex++;\n\t}\n\n\treturn headingColumns;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/tablewalker\n */\n\n/**\n * Table iterator class. It allows to iterate over table cells. For each cell the iterator yields\n * {@link module:table/tablewalker~TableWalkerValue} with proper table cell attributes.\n */\nexport default class TableWalker {\n\t/**\n\t * Creates an instance of the table walker.\n\t *\n\t * The table walker iterates internally by traversing the table from row index = 0 and column index = 0.\n\t * It walks row by row and column by column in order to output values defined in the constructor.\n\t * By default it will output only those locations that are occupied by a cell. To include also spanned rows and columns,\n\t * pass the `includeSpanned` option to the constructor.\n\t *\n\t * The most important values of the iterator are column and row indexes of a cell.\n\t *\n\t * See {@link module:table/tablewalker~TableWalkerValue} what values are returned by the table walker.\n\t *\n\t * To iterate over a given row:\n\t *\n\t *\t\tconst tableWalker = new TableWalker( table, { startRow: 1, endRow: 2 } );\n\t *\n\t *\t\tfor ( const cellInfo of tableWalker ) {\n\t *\t\t\tconsole.log( 'A cell at row ' + cellInfo.row + ' and column ' + cellInfo.column );\n\t *\t\t}\n\t *\n\t * For instance the code above for the following table:\n\t *\n\t *\t\t+----+----+----+----+----+----+\n\t *\t\t| 00 | 02 | 03 | 04 | 05 |\n\t *\t\t| +----+----+----+----+\n\t *\t\t| | 12 | 14 | 15 |\n\t *\t\t| +----+----+----+ +\n\t *\t\t| | 22 | |\n\t *\t\t|----+----+----+----+----+ +\n\t *\t\t| 30 | 31 | 32 | 33 | 34 | |\n\t *\t\t+----+----+----+----+----+----+\n\t *\n\t * will log in the console:\n\t *\n\t *\t\t'A cell at row 1 and column 2'\n\t *\t\t'A cell at row 1 and column 4'\n\t *\t\t'A cell at row 1 and column 5'\n\t *\t\t'A cell at row 2 and column 2'\n\t *\n\t * To also iterate over spanned cells:\n\t *\n\t *\t\tconst tableWalker = new TableWalker( table, { startRow: 1, endRow: 1, includeSpanned: true } );\n\t *\n\t *\t\tfor ( const value of tableWalker ) {\n\t *\t\t\tconsole.log( 'Cell at ' + value.row + ' x ' + value.column + ' : ' + ( value.isSpanned ? 'is spanned' : 'has data' ) );\n\t *\t\t}\n\t *\n\t * will log in the console for the table from previous example:\n\t *\n\t *\t\t'Cell at 1 x 0 : is spanned'\n\t *\t\t'Cell at 1 x 1 : is spanned'\n\t *\t\t'Cell at 1 x 2 : has data'\n\t *\t\t'Cell at 1 x 3 : is spanned'\n\t *\t\t'Cell at 1 x 4 : has data'\n\t *\t\t'Cell at 1 x 5 : has data'\n\t *\n\t * @constructor\n\t * @param {module:engine/model/element~Element} table A table over which the walker iterates.\n\t * @param {Object} [options={}] An object with configuration.\n\t * @param {Number} [options.column] A column index for which this iterator will output cells.\n\t * @param {Number} [options.startRow=0] A row index for which this iterator should start.\n\t * @param {Number} [options.endRow] A row index for which this iterator should end.\n\t * @param {Boolean} [options.includeSpanned=false] Also return values for spanned cells.\n\t */\n\tconstructor( table, options = {} ) {\n\t\t/**\n\t\t * The walker's table element.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:engine/model/element~Element}\n\t\t */\n\t\tthis.table = table;\n\n\t\t/**\n\t\t * A row index on which this iterator will start.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t */\n\t\tthis.startRow = options.startRow || 0;\n\n\t\t/**\n\t\t * A row index on which this iterator will end.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t */\n\t\tthis.endRow = typeof options.endRow == 'number' ? options.endRow : undefined;\n\n\t\t/**\n\t\t * Enables output of spanned cells that are normally not yielded.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean}\n\t\t */\n\t\tthis.includeSpanned = !!options.includeSpanned;\n\n\t\t/**\n\t\t * If set, the table walker will only output cells of a given column or cells that overlap it.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t */\n\t\tthis.column = typeof options.column == 'number' ? options.column : undefined;\n\n\t\t/**\n\t\t * Row indexes to skip from the iteration.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Set<Number>}\n\t\t * @private\n\t\t */\n\t\tthis._skipRows = new Set();\n\n\t\t/**\n\t\t * The current row index.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t * @private\n\t\t */\n\t\tthis._row = 0;\n\n\t\t/**\n\t\t * The current column index.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t * @private\n\t\t */\n\t\tthis._column = 0;\n\n\t\t/**\n\t\t * The cell index in a parent row. For spanned cells when {@link #includeSpanned} is set to `true`,\n\t\t * this represents the index of the next table cell.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t * @private\n\t\t */\n\t\tthis._cellIndex = 0;\n\n\t\t/**\n\t\t * Holds a map of spanned cells in a table.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Map<Number, Map.<Number, module:engine/model/element~Element>>}\n\t\t * @private\n\t\t */\n\t\tthis._spannedCells = new Map();\n\n\t\tthis._nextCellAtColumn = -1;\n\t}\n\n\t/**\n\t * Iterable interface.\n\t *\n\t * @returns {Iterable.<module:table/tablewalker~TableWalkerValue>}\n\t */\n\t[ Symbol.iterator ]() {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the next table walker's value.\n\t *\n\t * @returns {module:table/tablewalker~TableWalkerValue} The next table walker's value.\n\t */\n\tnext() {\n\t\tconst row = this.table.getChild( this._row );\n\n\t\t// Iterator is done when there's no row (table ended) or the row is after `endRow` limit.\n\t\tif ( !row || this._isOverEndRow() ) {\n\t\t\treturn { done: true };\n\t\t}\n\n\t\tlet cell, skipCurrentValue, outValue;\n\n\t\tif ( this._isSpanned( this._row, this._column ) ) {\n\t\t\tcell = this._getSpanned( this._row, this._column );\n\n\t\t\tskipCurrentValue = !this.includeSpanned || this._shouldSkipRow() || this._shouldSkipColumn();\n\t\t\toutValue = this._formatOutValue( cell, this._column, true );\n\t\t} else {\n\t\t\tcell = row.getChild( this._cellIndex );\n\n\t\t\tif ( !cell ) {\n\t\t\t\t// If there are no more cells left in row advance to the next row.\n\t\t\t\tthis._row++;\n\t\t\t\tthis._column = 0;\n\t\t\t\tthis._cellIndex = 0;\n\t\t\t\tthis._nextCellAtColumn = -1;\n\n\t\t\t\treturn this.next();\n\t\t\t}\n\n\t\t\tconst colspan = parseInt( cell.getAttribute( 'colspan' ) || 1 );\n\t\t\tconst rowspan = parseInt( cell.getAttribute( 'rowspan' ) || 1 );\n\n\t\t\t// Record this cell spans if it's not 1x1 cell.\n\t\t\tif ( colspan > 1 || rowspan > 1 ) {\n\t\t\t\tthis._recordSpans( this._row, this._column, rowspan, colspan, cell );\n\t\t\t}\n\n\t\t\tthis._nextCellAtColumn = this._column + colspan;\n\n\t\t\tskipCurrentValue = this._shouldSkipRow() || this._shouldSkipColumn();\n\t\t\toutValue = this._formatOutValue( cell, this._column, false, rowspan, colspan );\n\t\t}\n\n\t\t// Advance to the next column before returning value.\n\t\tthis._column++;\n\n\t\tif ( this._column == this._nextCellAtColumn ) {\n\t\t\tthis._cellIndex++;\n\t\t}\n\n\t\t// The current value will be returned only if current row and column are not skipped.\n\t\treturn skipCurrentValue ? this.next() : outValue;\n\t}\n\n\t/**\n\t * Marks a row to skip in the next iteration. It will also skip cells from the current row if there are any cells from the current row\n\t * to output.\n\t *\n\t * @param {Number} row Row index to skip.\n\t */\n\tskipRow( row ) {\n\t\tthis._skipRows.add( row );\n\t}\n\n\t/**\n\t * Checks if the current row is over {@link #endRow}.\n\t *\n\t * @private\n\t * @returns {Boolean}\n\t */\n\t_isOverEndRow() {\n\t\t// If {@link #endRow) is defined skip all rows above it.\n\t\treturn this.endRow !== undefined && this._row > this.endRow;\n\t}\n\n\t/**\n\t * A common method for formatting the iterator's output value.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} cell The table cell to output.\n\t * @param {Number} column Column index (use the cached value).\n\t * @param {Boolean} isSpanned Whether the value is returned for a spanned cell location or actual cell.\n\t * @param {Number} rowspan Rowspan of the current cell.\n\t * @param {Number} colspan Colspan of the current cell.\n\t * @returns {{done: boolean, value: {cell: *, row: Number, column: *, rowspan: *, colspan: *, cellIndex: Number}}}\n\t */\n\t_formatOutValue( cell, column, isSpanned, rowspan = 1, colspan = 1 ) {\n\t\treturn {\n\t\t\tdone: false,\n\t\t\tvalue: {\n\t\t\t\tcell,\n\t\t\t\trow: this._row,\n\t\t\t\tcolumn,\n\t\t\t\tisSpanned,\n\t\t\t\trowspan,\n\t\t\t\tcolspan,\n\t\t\t\tcellIndex: this._cellIndex\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Checks if the current row should be skipped.\n\t *\n\t * @private\n\t * @returns {Boolean}\n\t */\n\t_shouldSkipRow() {\n\t\tconst rowIsBelowStartRow = this._row < this.startRow;\n\t\tconst rowIsMarkedAsSkipped = this._skipRows.has( this._row );\n\n\t\treturn rowIsBelowStartRow || rowIsMarkedAsSkipped;\n\t}\n\n\t/**\n\t * Checks if the current column should be skipped.\n\t *\n\t * @private\n\t * @returns {Boolean}\n\t */\n\t_shouldSkipColumn() {\n\t\tif ( this.column === undefined ) {\n\t\t\t// The {@link #column} is not defined so output all columns.\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.column != this._column;\n\t}\n\n\t/**\n\t * Checks if the current cell location (row x column) is spanned by another cell.\n\t *\n\t * @private\n\t * @param {Number} row Row index of a cell location to check.\n\t * @param {Number} column Column index of a cell location to check.\n\t * @returns {Boolean}\n\t */\n\t_isSpanned( row, column ) {\n\t\tif ( !this._spannedCells.has( row ) ) {\n\t\t\t// No spans for given row.\n\t\t\treturn false;\n\t\t}\n\n\t\tconst rowSpans = this._spannedCells.get( row );\n\n\t\t// If spans for given rows has entry for column it means that this location if spanned by other cell.\n\t\treturn rowSpans.has( column );\n\t}\n\n\t/**\n\t * Returns the cell element that is spanned over `row` x `column` location.\n\t *\n\t * @private\n\t * @param {Number} row Row index of the cell location.\n\t * @param {Number} column Column index of the cell location.\n\t * @returns {module:engine/model/element~Element}\n\t */\n\t_getSpanned( row, column ) {\n\t\treturn this._spannedCells.get( row ).get( column );\n\t}\n\n\t/**\n\t * Updates spanned cells map relative to the current cell location and its span dimensions.\n\t *\n\t * @private\n\t * @param {Number} row Row index of a cell.\n\t * @param {Number} column Column index of a cell.\n\t * @param {Number} rowspan Cell height.\n\t * @param {Number} colspan Cell width.\n\t * @param {module:engine/model/element~Element} cell Cell that is spanned.\n\t */\n\t_recordSpans( row, column, rowspan, colspan, cell ) {\n\t\t// This will update all cell locations after current column - ie a cell has colspan set.\n\t\tfor ( let columnToUpdate = column + 1; columnToUpdate <= column + colspan - 1; columnToUpdate++ ) {\n\t\t\tthis._markSpannedCell( row, columnToUpdate, cell );\n\t\t}\n\n\t\t// This will update all rows below current up to row's height.\n\t\tfor ( let rowToUpdate = row + 1; rowToUpdate < row + rowspan; rowToUpdate++ ) {\n\t\t\tfor ( let columnToUpdate = column; columnToUpdate <= column + colspan - 1; columnToUpdate++ ) {\n\t\t\t\tthis._markSpannedCell( rowToUpdate, columnToUpdate, cell );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Marks the cell location as spanned by another cell.\n\t *\n\t * @private\n\t * @param {Number} row Row index of the cell location.\n\t * @param {Number} column Column index of the cell location.\n\t * @param {module:engine/model/element~Element} cell Cell that is spanned.\n\t */\n\t_markSpannedCell( row, column, cell ) {\n\t\tif ( !this._spannedCells.has( row ) ) {\n\t\t\tthis._spannedCells.set( row, new Map() );\n\t\t}\n\n\t\tconst rowSpans = this._spannedCells.get( row );\n\n\t\trowSpans.set( column, cell );\n\t}\n}\n\n/**\n * An object returned by {@link module:table/tablewalker~TableWalker} when traversing table cells.\n *\n * @typedef {Object} module:table/tablewalker~TableWalkerValue\n * @property {module:engine/model/element~Element} cell The current table cell.\n * @property {Number} row The row index of a cell.\n * @property {Number} column The column index of a cell. Column index is adjusted to widths and heights of previous cells.\n * @param {Boolean} isSpanned Whether the value is returned for a spanned cell location or actual cell.\n * @property {Number} colspan The `colspan` attribute of a cell. It the model attribute is not present, it is set to `1`. For spanned\n * table locations, it is set to `1`.\n * @property {Number} rowspan The `rowspan` attribute of a cell. It the model attribute is not present, it is set to `1`. For spanned\n * table locations, it is set to `1`.\n * @property {Number} cellIndex The index of the current cell in a parent row.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 table/utils\n */\n\nimport { isWidget, toWidget } from '@ckeditor/ckeditor5-widget/src/utils';\nimport { findAncestor } from './commands/utils';\n\n/**\n * Converts a given {@link module:engine/view/element~Element} to a table widget:\n * * Adds a {@link module:engine/view/element~Element#_setCustomProperty custom property} allowing to recognize the table widget element.\n * * Calls the {@link module:widget/utils~toWidget} function with the proper element's label creator.\n *\n * @param {module:engine/view/element~Element} viewElement\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer An instance of the view writer.\n * @param {String} label The element's label. It will be concatenated with the table `alt` attribute if one is present.\n * @returns {module:engine/view/element~Element}\n */\nexport function toTableWidget( viewElement, writer ) {\n\twriter.setCustomProperty( 'table', true, viewElement );\n\n\treturn toWidget( viewElement, writer, { hasSelectionHandle: true } );\n}\n\n/**\n * Checks if a given view element is a table widget.\n *\n * @param {module:engine/view/element~Element} viewElement\n * @returns {Boolean}\n */\nexport function isTableWidget( viewElement ) {\n\treturn !!viewElement.getCustomProperty( 'table' ) && isWidget( viewElement );\n}\n\n/**\n * Returns a table widget editing view element if one is selected.\n *\n * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection} selection\n * @returns {module:engine/view/element~Element|null}\n */\nexport function getSelectedTableWidget( selection ) {\n\tconst viewElement = selection.getSelectedElement();\n\n\tif ( viewElement && isTableWidget( viewElement ) ) {\n\t\treturn viewElement;\n\t}\n\n\treturn null;\n}\n\n/**\n * Returns a table widget editing view element if one is among selection's ancestors.\n *\n * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection} selection\n * @returns {module:engine/view/element~Element|null}\n */\nexport function getTableWidgetAncestor( selection ) {\n\tconst parentTable = findAncestor( 'table', selection.getFirstPosition() );\n\n\tif ( parentTable && isTableWidget( parentTable.parent ) ) {\n\t\treturn parentTable.parent;\n\t}\n\n\treturn null;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/converters/downcast\n */\n\nimport TableWalker from './../tablewalker';\nimport { toWidgetEditable } from '@ckeditor/ckeditor5-widget/src/utils';\nimport { toTableWidget } from '../utils';\n\n/**\n * Model table element to view table element conversion helper.\n *\n * This conversion helper creates the whole table element with child elements.\n *\n * @param {Object} options\n * @param {Boolean} options.asWidget If set to `true`, the downcast conversion will produce a widget.\n * @returns {Function} Conversion helper.\n */\nexport function downcastInsertTable( options = {} ) {\n\treturn dispatcher => dispatcher.on( 'insert:table', ( evt, data, conversionApi ) => {\n\t\tconst table = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( table, 'insert' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Consume attributes if present to not fire attribute change downcast\n\t\tconversionApi.consumable.consume( table, 'attribute:headingRows:table' );\n\t\tconversionApi.consumable.consume( table, 'attribute:headingColumns:table' );\n\n\t\tconst asWidget = options && options.asWidget;\n\n\t\tconst figureElement = conversionApi.writer.createContainerElement( 'figure', { class: 'table' } );\n\t\tconst tableElement = conversionApi.writer.createContainerElement( 'table' );\n\t\tconversionApi.writer.insert( conversionApi.writer.createPositionAt( figureElement, 0 ), tableElement );\n\n\t\tlet tableWidget;\n\n\t\tif ( asWidget ) {\n\t\t\ttableWidget = toTableWidget( figureElement, conversionApi.writer );\n\t\t}\n\n\t\tconst tableWalker = new TableWalker( table );\n\n\t\tconst tableAttributes = {\n\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t};\n\n\t\t// Cache for created table rows.\n\t\tconst viewRows = new Map();\n\n\t\tfor ( const tableWalkerValue of tableWalker ) {\n\t\t\tconst { row, cell } = tableWalkerValue;\n\n\t\t\tconst tableSection = getOrCreateTableSection( getSectionName( row, tableAttributes ), tableElement, conversionApi );\n\t\t\tconst tableRow = table.getChild( row );\n\n\t\t\tconst trElement = viewRows.get( row ) || createTr( tableRow, row, tableSection, conversionApi );\n\t\t\tviewRows.set( row, trElement );\n\n\t\t\t// Consume table cell - it will be always consumed as we convert whole table at once.\n\t\t\tconversionApi.consumable.consume( cell, 'insert' );\n\n\t\t\tconst insertPosition = conversionApi.writer.createPositionAt( trElement, 'end' );\n\n\t\t\tcreateViewTableCellElement( tableWalkerValue, tableAttributes, insertPosition, conversionApi, options );\n\t\t}\n\n\t\tconst viewPosition = conversionApi.mapper.toViewPosition( data.range.start );\n\n\t\tconversionApi.mapper.bindElements( table, asWidget ? tableWidget : figureElement );\n\t\tconversionApi.writer.insert( viewPosition, asWidget ? tableWidget : figureElement );\n\t} );\n}\n\n/**\n * Model row element to view `<tr>` element conversion helper.\n *\n * This conversion helper creates the whole `<tr>` element with child elements.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastInsertRow( options = {} ) {\n\treturn dispatcher => dispatcher.on( 'insert:tableRow', ( evt, data, conversionApi ) => {\n\t\tconst tableRow = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( tableRow, 'insert' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst table = tableRow.parent;\n\n\t\tconst figureElement = conversionApi.mapper.toViewElement( table );\n\t\tconst tableElement = getViewTable( figureElement );\n\n\t\tconst row = table.getChildIndex( tableRow );\n\n\t\tconst tableWalker = new TableWalker( table, { startRow: row, endRow: row } );\n\n\t\tconst tableAttributes = {\n\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t};\n\n\t\t// Cache for created table rows.\n\t\tconst viewRows = new Map();\n\n\t\tfor ( const tableWalkerValue of tableWalker ) {\n\t\t\tconst tableSection = getOrCreateTableSection( getSectionName( row, tableAttributes ), tableElement, conversionApi );\n\n\t\t\tconst trElement = viewRows.get( row ) || createTr( tableRow, row, tableSection, conversionApi );\n\t\t\tviewRows.set( row, trElement );\n\n\t\t\t// Consume table cell - it will be always consumed as we convert whole row at once.\n\t\t\tconversionApi.consumable.consume( tableWalkerValue.cell, 'insert' );\n\n\t\t\tconst insertPosition = conversionApi.writer.createPositionAt( trElement, 'end' );\n\n\t\t\tcreateViewTableCellElement( tableWalkerValue, tableAttributes, insertPosition, conversionApi, options );\n\t\t}\n\t} );\n}\n\n/**\n * Model table cell element to view `<td>` or `<th>` element conversion helper.\n *\n * This conversion helper will create proper `<th>` elements for table cells that are in the heading section (heading row or column)\n * and `<td>` otherwise.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastInsertCell( options = {} ) {\n\treturn dispatcher => dispatcher.on( 'insert:tableCell', ( evt, data, conversionApi ) => {\n\t\tconst tableCell = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( tableCell, 'insert' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\t\tconst rowIndex = table.getChildIndex( tableRow );\n\n\t\tconst tableWalker = new TableWalker( table, { startRow: rowIndex, endRow: rowIndex } );\n\n\t\tconst tableAttributes = {\n\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t};\n\n\t\t// We need to iterate over a table in order to get proper row & column values from a walker\n\t\tfor ( const tableWalkerValue of tableWalker ) {\n\t\t\tif ( tableWalkerValue.cell === tableCell ) {\n\t\t\t\tconst trElement = conversionApi.mapper.toViewElement( tableRow );\n\t\t\t\tconst insertPosition = conversionApi.writer.createPositionAt( trElement, tableRow.getChildIndex( tableCell ) );\n\n\t\t\t\tcreateViewTableCellElement( tableWalkerValue, tableAttributes, insertPosition, conversionApi, options );\n\n\t\t\t\t// No need to iterate further.\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t} );\n}\n\n/**\n * Conversion helper that acts on heading rows table attribute change.\n *\n * This converter will:\n *\n * * Rename `<td>` to `<th>` elements or vice versa depending on headings.\n * * Create `<thead>` or `<tbody>` elements if needed.\n * * Remove empty `<thead>` or `<tbody>` if needed.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastTableHeadingRowsChange( options = {} ) {\n\tconst asWidget = !!options.asWidget;\n\n\treturn dispatcher => dispatcher.on( 'attribute:headingRows:table', ( evt, data, conversionApi ) => {\n\t\tconst table = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst figureElement = conversionApi.mapper.toViewElement( table );\n\t\tconst viewTable = getViewTable( figureElement );\n\n\t\tconst oldRows = data.attributeOldValue;\n\t\tconst newRows = data.attributeNewValue;\n\n\t\t// The head section has grown so move rows from <tbody> to <thead>.\n\t\tif ( newRows > oldRows ) {\n\t\t\t// Filter out only those rows that are in wrong section.\n\t\t\tconst rowsToMove = Array.from( table.getChildren() ).filter( ( { index } ) => isBetween( index, oldRows - 1, newRows ) );\n\n\t\t\tconst viewTableHead = getOrCreateTableSection( 'thead', viewTable, conversionApi );\n\t\t\tmoveViewRowsToTableSection( rowsToMove, viewTableHead, conversionApi, 'end' );\n\n\t\t\t// Rename all table cells from moved rows to 'th' as they lands in <thead>.\n\t\t\tfor ( const tableRow of rowsToMove ) {\n\t\t\t\tfor ( const tableCell of tableRow.getChildren() ) {\n\t\t\t\t\trenameViewTableCell( tableCell, 'th', conversionApi, asWidget );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Cleanup: this will remove any empty section from the view which may happen when moving all rows from a table section.\n\t\t\tremoveTableSectionIfEmpty( 'tbody', viewTable, conversionApi );\n\t\t}\n\t\t// The head section has shrunk so move rows from <thead> to <tbody>.\n\t\telse {\n\t\t\t// Filter out only those rows that are in wrong section.\n\t\t\tconst rowsToMove = Array.from( table.getChildren() )\n\t\t\t\t.filter( ( { index } ) => isBetween( index, newRows - 1, oldRows ) )\n\t\t\t\t.reverse(); // The rows will be moved from <thead> to <tbody> in reverse order at the beginning of a <tbody>.\n\n\t\t\tconst viewTableBody = getOrCreateTableSection( 'tbody', viewTable, conversionApi );\n\t\t\tmoveViewRowsToTableSection( rowsToMove, viewTableBody, conversionApi, 0 );\n\n\t\t\t// Check if cells moved from <thead> to <tbody> requires renaming to <td> as this depends on current heading columns attribute.\n\t\t\tconst tableWalker = new TableWalker( table, { startRow: newRows ? newRows - 1 : newRows, endRow: oldRows - 1 } );\n\n\t\t\tconst tableAttributes = {\n\t\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t\t};\n\n\t\t\tfor ( const tableWalkerValue of tableWalker ) {\n\t\t\t\trenameViewTableCellIfRequired( tableWalkerValue, tableAttributes, conversionApi, asWidget );\n\t\t\t}\n\n\t\t\t// Cleanup: this will remove any empty section from the view which may happen when moving all rows from a table section.\n\t\t\tremoveTableSectionIfEmpty( 'thead', viewTable, conversionApi );\n\t\t}\n\n\t\tfunction isBetween( index, lower, upper ) {\n\t\t\treturn index > lower && index < upper;\n\t\t}\n\t} );\n}\n\n/**\n * Conversion helper that acts on heading columns table attribute change.\n *\n * Depending on changed attributes this converter will rename `<td` to `<th>` elements or vice versa depending of the cell column index.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastTableHeadingColumnsChange( options = {} ) {\n\tconst asWidget = !!options.asWidget;\n\n\treturn dispatcher => dispatcher.on( 'attribute:headingColumns:table', ( evt, data, conversionApi ) => {\n\t\tconst table = data.item;\n\n\t\tif ( !conversionApi.consumable.consume( data.item, evt.name ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst tableAttributes = {\n\t\t\theadingRows: table.getAttribute( 'headingRows' ) || 0,\n\t\t\theadingColumns: table.getAttribute( 'headingColumns' ) || 0\n\t\t};\n\n\t\tconst oldColumns = data.attributeOldValue;\n\t\tconst newColumns = data.attributeNewValue;\n\n\t\tconst lastColumnToCheck = ( oldColumns > newColumns ? oldColumns : newColumns ) - 1;\n\n\t\tfor ( const tableWalkerValue of new TableWalker( table ) ) {\n\t\t\t// Skip cells that were not in heading section before and after the change.\n\t\t\tif ( tableWalkerValue.column > lastColumnToCheck ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\trenameViewTableCellIfRequired( tableWalkerValue, tableAttributes, conversionApi, asWidget );\n\t\t}\n\t} );\n}\n\n/**\n * Conversion helper that acts on a removed row.\n *\n * @returns {Function} Conversion helper.\n */\nexport function downcastRemoveRow() {\n\treturn dispatcher => dispatcher.on( 'remove:tableRow', ( evt, data, conversionApi ) => {\n\t\t// Prevent default remove converter.\n\t\tevt.stop();\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst mapper = conversionApi.mapper;\n\n\t\tconst viewStart = mapper.toViewPosition( data.position ).getLastMatchingPosition( value => !value.item.is( 'tr' ) );\n\t\tconst viewItem = viewStart.nodeAfter;\n\t\tconst tableSection = viewItem.parent;\n\n\t\t// Remove associated <tr> from the view.\n\t\tconst removeRange = viewWriter.createRangeOn( viewItem );\n\t\tconst removed = viewWriter.remove( removeRange );\n\n\t\tfor ( const child of viewWriter.createRangeIn( removed ).getItems() ) {\n\t\t\tmapper.unbindViewElement( child );\n\t\t}\n\n\t\t// Check if table section has any children left - if not remove it from the view.\n\t\tif ( !tableSection.childCount ) {\n\t\t\t// No need to unbind anything as table section is not represented in the model.\n\t\t\tviewWriter.remove( viewWriter.createRangeOn( tableSection ) );\n\t\t}\n\t}, { priority: 'higher' } );\n}\n\n// Renames an existing table cell in the view to a given element name.\n//\n// **Note** This method will not do anything if a view table cell was not yet converted.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @param {String} desiredCellElementName\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @param {Boolean} asWidget\nfunction renameViewTableCell( tableCell, desiredCellElementName, conversionApi, asWidget ) {\n\tconst viewWriter = conversionApi.writer;\n\tconst viewCell = conversionApi.mapper.toViewElement( tableCell );\n\n\t// View cell might be not yet converted - skip it as it will be properly created by cell converter later on.\n\tif ( !viewCell ) {\n\t\treturn;\n\t}\n\n\tlet renamedCell;\n\n\tif ( asWidget ) {\n\t\tconst editable = viewWriter.createEditableElement( desiredCellElementName, viewCell.getAttributes() );\n\t\trenamedCell = toWidgetEditable( editable, viewWriter );\n\n\t\tviewWriter.insert( viewWriter.createPositionAfter( viewCell ), renamedCell );\n\t\tviewWriter.move( viewWriter.createRangeIn( viewCell ), viewWriter.createPositionAt( renamedCell, 0 ) );\n\t\tviewWriter.remove( viewWriter.createRangeOn( viewCell ) );\n\t} else {\n\t\trenamedCell = viewWriter.rename( desiredCellElementName, viewCell );\n\t}\n\n\tconversionApi.mapper.unbindViewElement( viewCell );\n\tconversionApi.mapper.bindElements( tableCell, renamedCell );\n}\n\n// Renames a table cell element in the view according to its location in the table.\n//\n// @param {module:table/tablewalker~TableWalkerValue} tableWalkerValue\n// @param {{headingColumns, headingRows}} tableAttributes\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @param {Boolean} asWidget\nfunction renameViewTableCellIfRequired( tableWalkerValue, tableAttributes, conversionApi, asWidget ) {\n\tconst { cell } = tableWalkerValue;\n\n\t// Check whether current columnIndex is overlapped by table cells from previous rows.\n\tconst desiredCellElementName = getCellElementName( tableWalkerValue, tableAttributes );\n\n\tconst viewCell = conversionApi.mapper.toViewElement( cell );\n\n\t// If in single change we're converting attribute changes and inserting cell the table cell might not be inserted into view\n\t// because of child conversion is done after parent.\n\tif ( viewCell && viewCell.name !== desiredCellElementName ) {\n\t\trenameViewTableCell( cell, desiredCellElementName, conversionApi, asWidget );\n\t}\n}\n\n// Creates a table cell element in the view.\n//\n// @param {module:table/tablewalker~TableWalkerValue} tableWalkerValue\n// @param {module:engine/view/position~Position} insertPosition\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction createViewTableCellElement( tableWalkerValue, tableAttributes, insertPosition, conversionApi, options ) {\n\tconst asWidget = options && options.asWidget;\n\tconst cellElementName = getCellElementName( tableWalkerValue, tableAttributes );\n\n\tconst cellElement = asWidget ?\n\t\ttoWidgetEditable( conversionApi.writer.createEditableElement( cellElementName ), conversionApi.writer ) :\n\t\tconversionApi.writer.createContainerElement( cellElementName );\n\n\tconst tableCell = tableWalkerValue.cell;\n\n\tconst firstChild = tableCell.getChild( 0 );\n\tconst isSingleParagraph = tableCell.childCount === 1 && firstChild.name === 'paragraph';\n\n\tconversionApi.writer.insert( insertPosition, cellElement );\n\n\tif ( isSingleParagraph && !hasAnyAttribute( firstChild ) ) {\n\t\tconst innerParagraph = tableCell.getChild( 0 );\n\t\tconst paragraphInsertPosition = conversionApi.writer.createPositionAt( cellElement, 'end' );\n\n\t\tconversionApi.consumable.consume( innerParagraph, 'insert' );\n\n\t\tif ( options.asWidget ) {\n\t\t\tconst fakeParagraph = conversionApi.writer.createContainerElement( 'span' );\n\n\t\t\tconversionApi.mapper.bindElements( innerParagraph, fakeParagraph );\n\t\t\tconversionApi.writer.insert( paragraphInsertPosition, fakeParagraph );\n\n\t\t\tconversionApi.mapper.bindElements( tableCell, cellElement );\n\t\t} else {\n\t\t\tconversionApi.mapper.bindElements( tableCell, cellElement );\n\t\t\tconversionApi.mapper.bindElements( innerParagraph, cellElement );\n\t\t}\n\t} else {\n\t\tconversionApi.mapper.bindElements( tableCell, cellElement );\n\t}\n}\n\n// Creates `<tr>` view element.\n//\n// @param {module:engine/view/element~Element} tableRow\n// @param {Number} rowIndex\n// @param {module:engine/view/element~Element} tableSection\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @returns {module:engine/view/element~Element}\nfunction createTr( tableRow, rowIndex, tableSection, conversionApi ) {\n\t// Will always consume since we're converting <tableRow> element from a parent <table>.\n\tconversionApi.consumable.consume( tableRow, 'insert' );\n\n\tconst trElement = conversionApi.writer.createContainerElement( 'tr' );\n\tconversionApi.mapper.bindElements( tableRow, trElement );\n\n\tconst headingRows = tableRow.parent.getAttribute( 'headingRows' ) || 0;\n\tconst offset = headingRows > 0 && rowIndex >= headingRows ? rowIndex - headingRows : rowIndex;\n\n\tconst position = conversionApi.writer.createPositionAt( tableSection, offset );\n\tconversionApi.writer.insert( position, trElement );\n\n\treturn trElement;\n}\n\n// Returns `th` for heading cells and `td` for other cells for the current table walker value.\n//\n// @param {module:table/tablewalker~TableWalkerValue} tableWalkerValue\n// @param {{headingColumns, headingRows}} tableAttributes\n// @returns {String}\nfunction getCellElementName( tableWalkerValue, tableAttributes ) {\n\tconst { row, column } = tableWalkerValue;\n\tconst { headingColumns, headingRows } = tableAttributes;\n\n\t// Column heading are all tableCells in the first `columnHeading` rows.\n\tconst isColumnHeading = headingRows && headingRows > row;\n\n\t// So a whole row gets <th> element.\n\tif ( isColumnHeading ) {\n\t\treturn 'th';\n\t}\n\n\t// Row heading are tableCells which columnIndex is lower then headingColumns.\n\tconst isRowHeading = headingColumns && headingColumns > column;\n\n\treturn isRowHeading ? 'th' : 'td';\n}\n\n// Returns the table section name for the current table walker value.\n//\n// @param {Number} row\n// @param {{headingColumns, headingRows}} tableAttributes\n// @returns {String}\nfunction getSectionName( row, tableAttributes ) {\n\treturn row < tableAttributes.headingRows ? 'thead' : 'tbody';\n}\n\n// Creates or returns an existing `<tbody>` or `<thead>` element witch caching.\n//\n// @param {String} sectionName\n// @param {module:engine/view/element~Element} viewTable\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @param {Object} cachedTableSection An object that stores cached elements.\n// @returns {module:engine/view/containerelement~ContainerElement}\nfunction getOrCreateTableSection( sectionName, viewTable, conversionApi ) {\n\tconst viewTableSection = getExistingTableSectionElement( sectionName, viewTable );\n\n\treturn viewTableSection ? viewTableSection : createTableSection( sectionName, viewTable, conversionApi );\n}\n\n// Finds an existing `<tbody>` or `<thead>` element or returns undefined.\n//\n// @param {String} sectionName\n// @param {module:engine/view/element~Element} tableElement\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction getExistingTableSectionElement( sectionName, tableElement ) {\n\tfor ( const tableSection of tableElement.getChildren() ) {\n\t\tif ( tableSection.name == sectionName ) {\n\t\t\treturn tableSection;\n\t\t}\n\t}\n}\n\n// Creates a table section at the end of the table.\n//\n// @param {String} sectionName\n// @param {module:engine/view/element~Element} tableElement\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @returns {module:engine/view/containerelement~ContainerElement}\nfunction createTableSection( sectionName, tableElement, conversionApi ) {\n\tconst tableChildElement = conversionApi.writer.createContainerElement( sectionName );\n\n\tconst insertPosition = conversionApi.writer.createPositionAt( tableElement, sectionName == 'tbody' ? 'end' : 0 );\n\n\tconversionApi.writer.insert( insertPosition, tableChildElement );\n\n\treturn tableChildElement;\n}\n\n// Removes an existing `<tbody>` or `<thead>` element if it is empty.\n//\n// @param {String} sectionName\n// @param {module:engine/view/element~Element} tableElement\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\nfunction removeTableSectionIfEmpty( sectionName, tableElement, conversionApi ) {\n\tconst tableSection = getExistingTableSectionElement( sectionName, tableElement );\n\n\tif ( tableSection && tableSection.childCount === 0 ) {\n\t\tconversionApi.writer.remove( conversionApi.writer.createRangeOn( tableSection ) );\n\t}\n}\n\n// Moves view table rows associated with passed model rows to the provided table section element.\n//\n// **Note** This method will skip not converted table rows.\n//\n// @param {Array.<module:engine/model/element~Element>} rowsToMove\n// @param {module:engine/view/element~Element} viewTableSection\n// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n// @param {Number|'end'|'before'|'after'} offset Offset or one of the flags.\nfunction moveViewRowsToTableSection( rowsToMove, viewTableSection, conversionApi, offset ) {\n\tfor ( const tableRow of rowsToMove ) {\n\t\tconst viewTableRow = conversionApi.mapper.toViewElement( tableRow );\n\n\t\t// View table row might be not yet converted - skip it as it will be properly created by cell converter later on.\n\t\tif ( viewTableRow ) {\n\t\t\tconversionApi.writer.move(\n\t\t\t\tconversionApi.writer.createRangeOn( viewTableRow ),\n\t\t\t\tconversionApi.writer.createPositionAt( viewTableSection, offset )\n\t\t\t);\n\t\t}\n\t}\n}\n\n// Properly finds '<table>' element inside `<figure>` widget.\n//\n// @param {module:engine/view/element~Element} viewFigure\nfunction getViewTable( viewFigure ) {\n\tfor ( const child of viewFigure.getChildren() ) {\n\t\tif ( child.name === 'table' ) {\n\t\t\treturn child;\n\t\t}\n\t}\n}\n\n// Checks if element has any attribute set.\n//\n// @param {module:engine/model/element~Element element\n// @returns {Boolean}\nfunction hasAnyAttribute( element ) {\n\treturn !![ ...element.getAttributeKeys() ].length;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/inserttablecommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { findOptimalInsertionPosition } from '@ckeditor/ckeditor5-widget/src/utils';\n\n/**\n * The insert table command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'insertTable'` editor command.\n *\n * To insert a table at the current selection, execute the command and specify the dimensions:\n *\n *\t\teditor.execute( 'insertTable', { rows: 20, columns: 5 } );\n *\n * @extends module:core/command~Command\n */\nexport default class InsertTableCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\tconst schema = model.schema;\n\n\t\tconst validParent = getInsertTableParent( selection.getFirstPosition() );\n\n\t\tthis.isEnabled = schema.checkChild( validParent, 'table' );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * Inserts a table with the given number of rows and columns into the editor.\n\t *\n\t * @param {Object} options\n\t * @param {Number} [options.rows=2] The number of rows to create in the inserted table.\n\t * @param {Number} [options.columns=2] The number of columns to create in the inserted table.\n\t * @fires execute\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\n\t\tconst rows = parseInt( options.rows ) || 2;\n\t\tconst columns = parseInt( options.columns ) || 2;\n\n\t\tconst insertPosition = findOptimalInsertionPosition( selection, model );\n\n\t\tmodel.change( writer => {\n\t\t\tconst table = tableUtils.createTable( writer, rows, columns );\n\n\t\t\tmodel.insertContent( table, insertPosition );\n\n\t\t\twriter.setSelection( writer.createPositionAt( table.getNodeByPath( [ 0, 0, 0 ] ), 0 ) );\n\t\t} );\n\t}\n}\n\n// Returns valid parent to insert table\n//\n// @param {module:engine/model/position} position\nfunction getInsertTableParent( position ) {\n\tconst parent = position.parent;\n\n\treturn parent === parent.root ? parent : parent.parent;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/insertrowcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { findAncestor } from './utils';\n\n/**\n * The insert row command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'insertTableRowBelow'` and\n * `'insertTableRowAbove'` editor commands.\n *\n * To insert a row below the selected cell, execute the following command:\n *\n *\t\teditor.execute( 'insertTableRowBelow' );\n *\n * To insert a row above the selected cell, execute the following command:\n *\n *\t\teditor.execute( 'insertTableRowAbove' );\n *\n * @extends module:core/command~Command\n */\nexport default class InsertRowCommand extends Command {\n\t/**\n\t * Creates a new `InsertRowCommand` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor on which this command will be used.\n\t * @param {Object} options\n\t * @param {String} [options.order=\"below\"] The order of insertion relative to the row in which the caret is located.\n\t * Possible values: `\"above\"` and `\"below\"`.\n\t */\n\tconstructor( editor, options = {} ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The order of insertion relative to the row in which the caret is located.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} module:table/commands/insertrowcommand~InsertRowCommand#order\n\t\t */\n\t\tthis.order = options.order || 'below';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selection = this.editor.model.document.selection;\n\n\t\tconst tableParent = findAncestor( 'table', selection.getFirstPosition() );\n\n\t\tthis.isEnabled = !!tableParent;\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * Depending on the command's {@link #order} value, it inserts a row `'below'` or `'above'` the row in which selection is set.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\t\tconst tableUtils = editor.plugins.get( 'TableUtils' );\n\n\t\tconst tableCell = findAncestor( 'tableCell', selection.getFirstPosition() );\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\n\t\tconst row = table.getChildIndex( tableRow );\n\t\tconst insertAt = this.order === 'below' ? row + 1 : row;\n\n\t\ttableUtils.insertRows( table, { rows: 1, at: insertAt } );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/insertcolumncommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { findAncestor } from './utils';\n\n/**\n * The insert column command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'insertTableColumnLeft'` and\n * `'insertTableColumnRight'` editor commands.\n *\n * To insert a column to the left of the selected cell, execute the following command:\n *\n *\t\teditor.execute( 'insertTableColumnLeft' );\n *\n * To insert a column to the right of the selected cell, execute the following command:\n *\n *\t\teditor.execute( 'insertTableColumnRight' );\n *\n * @extends module:core/command~Command\n */\nexport default class InsertColumnCommand extends Command {\n\t/**\n\t * Creates a new `InsertColumnCommand` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor An editor on which this command will be used.\n\t * @param {Object} options\n\t * @param {String} [options.order=\"right\"] The order of insertion relative to the column in which the caret is located.\n\t * Possible values: `\"left\"` and `\"right\"`.\n\t */\n\tconstructor( editor, options = {} ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The order of insertion relative to the column in which the caret is located.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} module:table/commands/insertcolumncommand~InsertColumnCommand#order\n\t\t */\n\t\tthis.order = options.order || 'right';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst selection = this.editor.model.document.selection;\n\n\t\tconst tableParent = findAncestor( 'table', selection.getFirstPosition() );\n\n\t\tthis.isEnabled = !!tableParent;\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * Depending on the command's {@link #order} value, it inserts a column to the `'left'` or `'right'` of the column\n\t * in which the selection is set.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\t\tconst tableUtils = editor.plugins.get( 'TableUtils' );\n\n\t\tconst firstPosition = selection.getFirstPosition();\n\n\t\tconst tableCell = findAncestor( 'tableCell', firstPosition );\n\t\tconst table = tableCell.parent.parent;\n\n\t\tconst { column } = tableUtils.getCellLocation( tableCell );\n\t\tconst insertAt = this.order === 'right' ? column + 1 : column;\n\n\t\ttableUtils.insertColumns( table, { columns: 1, at: insertAt } );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/splitcellcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport { findAncestor } from './utils';\n\n/**\n * The split cell command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'splitTableCellVertically'`\n * and `'splitTableCellHorizontally'` editor commands.\n *\n * You can split any cell vertically or horizontally by executing this command. For example, to split the selected table cell vertically:\n *\n *\t\teditor.execute( 'splitTableCellVertically' );\n *\n * @extends module:core/command~Command\n */\nexport default class SplitCellCommand extends Command {\n\t/**\n\t * Creates a new `SplitCellCommand` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor on which this command will be used.\n\t * @param {Object} options\n\t * @param {String} options.direction Indicates whether the command should split cells `'horizontally'` or `'vertically'`.\n\t */\n\tconstructor( editor, options = {} ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The direction that indicates which cell will be split.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} #direction\n\t\t */\n\t\tthis.direction = options.direction || 'horizontally';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tconst tableCell = findAncestor( 'tableCell', doc.selection.getFirstPosition() );\n\n\t\tthis.isEnabled = !!tableCell;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\t\tconst selection = document.selection;\n\n\t\tconst firstPosition = selection.getFirstPosition();\n\t\tconst tableCell = findAncestor( 'tableCell', firstPosition );\n\n\t\tconst isHorizontally = this.direction === 'horizontally';\n\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\n\t\tif ( isHorizontally ) {\n\t\t\ttableUtils.splitCellHorizontally( tableCell, 2 );\n\t\t} else {\n\t\t\ttableUtils.splitCellVertically( tableCell, 2 );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/mergecellcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport TableWalker from '../tablewalker';\nimport { findAncestor, updateNumericAttribute } from './utils';\n\n/**\n * The merge cell command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'mergeTableCellRight'`, `'mergeTableCellLeft'`,\n * `'mergeTableCellUp'` and `'mergeTableCellDown'` editor commands.\n *\n * To merge a table cell at the current selection with another cell, execute the command corresponding with the preferred direction.\n *\n * For example, to merge with a cell to the right:\n *\n *\t\teditor.execute( 'mergeTableCellRight' );\n *\n * **Note**: If a table cell has a different [`rowspan`](https://www.w3.org/TR/html50/tabular-data.html#attr-tdth-rowspan)\n * (for `'mergeTableCellRight'` and `'mergeTableCellLeft'`) or [`colspan`](https://www.w3.org/TR/html50/tabular-data.html#attr-tdth-colspan)\n * (for `'mergeTableCellUp'` and `'mergeTableCellDown'`), the command will be disabled.\n *\n * @extends module:core/command~Command\n */\nexport default class MergeCellCommand extends Command {\n\t/**\n\t * Creates a new `MergeCellCommand` instance.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor on which this command will be used.\n\t * @param {Object} options\n\t * @param {String} options.direction Indicates which cell to merge with the currently selected one.\n\t * Possible values are: `'left'`, `'right'`, `'up'` and `'down'`.\n\t */\n\tconstructor( editor, options ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The direction that indicates which cell will be merged with the currently selected one.\n\t\t *\n\t\t * @readonly\n\t\t * @member {String} #direction\n\t\t */\n\t\tthis.direction = options.direction;\n\n\t\t/**\n\t\t * Whether the merge is horizontal (left/right) or vertical (up/down).\n\t\t *\n\t\t * @readonly\n\t\t * @member {Boolean} #isHorizontal\n\t\t */\n\t\tthis.isHorizontal = this.direction == 'right' || this.direction == 'left';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst cellToMerge = this._getMergeableCell();\n\n\t\tthis.value = cellToMerge;\n\t\tthis.isEnabled = !!cellToMerge;\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * Depending on the command's {@link #direction} value, it will merge the cell that is to the `'left'`, `'right'`, `'up'` or `'down'`.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst tableCell = findAncestor( 'tableCell', doc.selection.getFirstPosition() );\n\t\tconst cellToMerge = this.value;\n\t\tconst direction = this.direction;\n\n\t\tmodel.change( writer => {\n\t\t\tconst isMergeNext = direction == 'right' || direction == 'down';\n\n\t\t\t// The merge mechanism is always the same so sort cells to be merged.\n\t\t\tconst cellToExpand = isMergeNext ? tableCell : cellToMerge;\n\t\t\tconst cellToRemove = isMergeNext ? cellToMerge : tableCell;\n\n\t\t\t// Cache the parent of cell to remove for later check.\n\t\t\tconst removedTableCellRow = cellToRemove.parent;\n\n\t\t\tmergeTableCells( cellToRemove, cellToExpand, writer );\n\n\t\t\tconst spanAttribute = this.isHorizontal ? 'colspan' : 'rowspan';\n\t\t\tconst cellSpan = parseInt( tableCell.getAttribute( spanAttribute ) || 1 );\n\t\t\tconst cellToMergeSpan = parseInt( cellToMerge.getAttribute( spanAttribute ) || 1 );\n\n\t\t\t// Update table cell span attribute and merge set selection on merged contents.\n\t\t\twriter.setAttribute( spanAttribute, cellSpan + cellToMergeSpan, cellToExpand );\n\t\t\twriter.setSelection( writer.createRangeIn( cellToExpand ) );\n\n\t\t\t// Remove empty row after merging.\n\t\t\tif ( !removedTableCellRow.childCount ) {\n\t\t\t\tremoveEmptyRow( removedTableCellRow, writer );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Returns a cell that can be merged with the current cell depending on the command's direction.\n\t *\n\t * @returns {module:engine/model/element~Element|undefined}\n\t * @private\n\t */\n\t_getMergeableCell() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst tableCell = findAncestor( 'tableCell', doc.selection.getFirstPosition() );\n\n\t\tif ( !tableCell ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\n\t\t// First get the cell on proper direction.\n\t\tconst cellToMerge = this.isHorizontal ?\n\t\t\tgetHorizontalCell( tableCell, this.direction, tableUtils ) :\n\t\t\tgetVerticalCell( tableCell, this.direction );\n\n\t\tif ( !cellToMerge ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If found check if the span perpendicular to merge direction is equal on both cells.\n\t\tconst spanAttribute = this.isHorizontal ? 'rowspan' : 'colspan';\n\t\tconst span = parseInt( tableCell.getAttribute( spanAttribute ) || 1 );\n\n\t\tconst cellToMergeSpan = parseInt( cellToMerge.getAttribute( spanAttribute ) || 1 );\n\n\t\tif ( cellToMergeSpan === span ) {\n\t\t\treturn cellToMerge;\n\t\t}\n\t}\n}\n\n// Returns the cell that can be merged horizontally.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @param {String} direction\n// @returns {module:engine/model/node~Node|null}\nfunction getHorizontalCell( tableCell, direction, tableUtils ) {\n\tconst horizontalCell = direction == 'right' ? tableCell.nextSibling : tableCell.previousSibling;\n\n\tif ( !horizontalCell ) {\n\t\treturn;\n\t}\n\n\t// Sort cells:\n\tconst cellOnLeft = direction == 'right' ? tableCell : horizontalCell;\n\tconst cellOnRight = direction == 'right' ? horizontalCell : tableCell;\n\n\t// Get their column indexes:\n\tconst { column: leftCellColumn } = tableUtils.getCellLocation( cellOnLeft );\n\tconst { column: rightCellColumn } = tableUtils.getCellLocation( cellOnRight );\n\n\tconst leftCellSpan = parseInt( cellOnLeft.getAttribute( 'colspan' ) || 1 );\n\n\t// The cell on the right must have index that is distant to the cell on the left by the left cell's width (colspan).\n\tconst cellsAreTouching = leftCellColumn + leftCellSpan === rightCellColumn;\n\n\t// If the right cell's column index is different it means that there are rowspanned cells between them.\n\treturn cellsAreTouching ? horizontalCell : undefined;\n}\n\n// Returns the cell that can be merged vertically.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @param {String} direction\n// @returns {module:engine/model/node~Node|null}\nfunction getVerticalCell( tableCell, direction ) {\n\tconst tableRow = tableCell.parent;\n\tconst table = tableRow.parent;\n\n\tconst rowIndex = table.getChildIndex( tableRow );\n\n\t// Don't search for mergeable cell if direction points out of the table.\n\tif ( ( direction == 'down' && rowIndex === table.childCount - 1 ) || ( direction == 'up' && rowIndex === 0 ) ) {\n\t\treturn;\n\t}\n\n\tconst rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );\n\tconst headingRows = table.getAttribute( 'headingRows' ) || 0;\n\n\tconst isMergeWithBodyCell = direction == 'down' && ( rowIndex + rowspan ) === headingRows;\n\tconst isMergeWithHeadCell = direction == 'up' && rowIndex === headingRows;\n\n\t// Don't search for mergeable cell if direction points out of the current table section.\n\tif ( headingRows && ( isMergeWithBodyCell || isMergeWithHeadCell ) ) {\n\t\treturn;\n\t}\n\n\tconst currentCellRowSpan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );\n\tconst rowOfCellToMerge = direction == 'down' ? rowIndex + currentCellRowSpan : rowIndex;\n\n\tconst tableMap = [ ...new TableWalker( table, { endRow: rowOfCellToMerge } ) ];\n\n\tconst currentCellData = tableMap.find( value => value.cell === tableCell );\n\tconst mergeColumn = currentCellData.column;\n\n\tconst cellToMergeData = tableMap.find( ( { row, rowspan, column } ) => {\n\t\tif ( column !== mergeColumn ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( direction == 'down' ) {\n\t\t\t// If merging a cell below the mergeRow is already calculated.\n\t\t\treturn row === rowOfCellToMerge;\n\t\t} else {\n\t\t\t// If merging a cell above calculate if it spans to mergeRow.\n\t\t\treturn rowOfCellToMerge === row + rowspan;\n\t\t}\n\t} );\n\n\treturn cellToMergeData && cellToMergeData.cell;\n}\n\n// Properly removes empty row from a table. Will update `rowspan` attribute of cells that overlaps removed row.\n//\n// @param {module:engine/model/element~Element} removedTableCellRow\n// @param {module:engine/model/writer~Writer} writer\nfunction removeEmptyRow( removedTableCellRow, writer ) {\n\tconst table = removedTableCellRow.parent;\n\n\tconst removedRowIndex = table.getChildIndex( removedTableCellRow );\n\n\tfor ( const { cell, row, rowspan } of new TableWalker( table, { endRow: removedRowIndex } ) ) {\n\t\tconst overlapsRemovedRow = row + rowspan - 1 >= removedRowIndex;\n\n\t\tif ( overlapsRemovedRow ) {\n\t\t\tupdateNumericAttribute( 'rowspan', rowspan - 1, cell, writer );\n\t\t}\n\t}\n\n\twriter.remove( removedTableCellRow );\n}\n\n// Merges two table cells - will ensure that after merging cells with empty paragraph the result table cell will only have one paragraph.\n// If one of the merged table cell is empty the merged table cell will have contents of the non-empty table cell.\n// If both are empty the merged table cell will have only one empty paragraph.\n//\n// @param {module:engine/model/element~Element} cellToRemove\n// @param {module:engine/model/element~Element} cellToExpand\n// @param {module:engine/model/writer~Writer} writer\nfunction mergeTableCells( cellToRemove, cellToExpand, writer ) {\n\tif ( !isEmpty( cellToRemove ) ) {\n\t\tif ( isEmpty( cellToExpand ) ) {\n\t\t\twriter.remove( writer.createRangeIn( cellToExpand ) );\n\t\t}\n\n\t\twriter.move( writer.createRangeIn( cellToRemove ), writer.createPositionAt( cellToExpand, 'end' ) );\n\t}\n\n\t// Remove merged table cell.\n\twriter.remove( cellToRemove );\n}\n\n// Checks if passed table cell contains empty paragraph.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @returns {Boolean}\nfunction isEmpty( tableCell ) {\n\treturn tableCell.childCount == 1 && tableCell.getChild( 0 ).is( 'paragraph' ) && tableCell.getChild( 0 ).isEmpty;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/removerowcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\nimport TableWalker from '../tablewalker';\nimport { findAncestor, updateNumericAttribute } from './utils';\n\n/**\n * The remove row command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'removeTableRow'` editor command.\n *\n * To remove the row containing the selected cell, execute the command:\n *\n *\t\teditor.execute( 'removeTableRow' );\n *\n * @extends module:core/command~Command\n */\nexport default class RemoveRowCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tconst tableCell = findAncestor( 'tableCell', doc.selection.getFirstPosition() );\n\n\t\tthis.isEnabled = !!tableCell && tableCell.parent.parent.childCount > 1;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\n\t\tconst firstPosition = selection.getFirstPosition();\n\t\tconst tableCell = findAncestor( 'tableCell', firstPosition );\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\n\t\tconst currentRow = table.getChildIndex( tableRow );\n\t\tconst headingRows = table.getAttribute( 'headingRows' ) || 0;\n\n\t\tmodel.change( writer => {\n\t\t\tif ( headingRows && currentRow <= headingRows ) {\n\t\t\t\tupdateNumericAttribute( 'headingRows', headingRows - 1, table, writer, 0 );\n\t\t\t}\n\n\t\t\tconst tableMap = [ ...new TableWalker( table, { endRow: currentRow } ) ];\n\n\t\t\tconst cellsToMove = new Map();\n\n\t\t\t// Get cells from removed row that are spanned over multiple rows.\n\t\t\ttableMap\n\t\t\t\t.filter( ( { row, rowspan } ) => row === currentRow && rowspan > 1 )\n\t\t\t\t.forEach( ( { column, cell, rowspan } ) => cellsToMove.set( column, { cell, rowspanToSet: rowspan - 1 } ) );\n\n\t\t\t// Reduce rowspan on cells that are above removed row and overlaps removed row.\n\t\t\ttableMap\n\t\t\t\t.filter( ( { row, rowspan } ) => row <= currentRow - 1 && row + rowspan > currentRow )\n\t\t\t\t.forEach( ( { cell, rowspan } ) => updateNumericAttribute( 'rowspan', rowspan - 1, cell, writer ) );\n\n\t\t\t// Move cells to another row.\n\t\t\tconst targetRow = currentRow + 1;\n\t\t\tconst tableWalker = new TableWalker( table, { includeSpanned: true, startRow: targetRow, endRow: targetRow } );\n\n\t\t\tlet previousCell;\n\n\t\t\tfor ( const { row, column, cell } of [ ...tableWalker ] ) {\n\t\t\t\tif ( cellsToMove.has( column ) ) {\n\t\t\t\t\tconst { cell: cellToMove, rowspanToSet } = cellsToMove.get( column );\n\t\t\t\t\tconst targetPosition = previousCell ?\n\t\t\t\t\t\twriter.createPositionAfter( previousCell ) :\n\t\t\t\t\t\twriter.createPositionAt( table.getChild( row ), 0 );\n\n\t\t\t\t\twriter.move( writer.createRangeOn( cellToMove ), targetPosition );\n\t\t\t\t\tupdateNumericAttribute( 'rowspan', rowspanToSet, cellToMove, writer );\n\n\t\t\t\t\tpreviousCell = cellToMove;\n\t\t\t\t} else {\n\t\t\t\t\tpreviousCell = cell;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\twriter.remove( tableRow );\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/removecolumncommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\nimport TableWalker from '../tablewalker';\nimport { findAncestor, updateNumericAttribute } from './utils';\n\n/**\n * The remove column command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'removeTableColumn'` editor command.\n *\n * To remove the column containing the selected cell, execute the command:\n *\n *\t\teditor.execute( 'removeTableColumn' );\n *\n * @extends module:core/command~Command\n */\nexport default class RemoveColumnCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\t\tconst tableUtils = editor.plugins.get( 'TableUtils' );\n\n\t\tconst tableCell = findAncestor( 'tableCell', selection.getFirstPosition() );\n\n\t\tthis.isEnabled = !!tableCell && tableUtils.getColumns( tableCell.parent.parent ) > 1;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\n\t\tconst firstPosition = selection.getFirstPosition();\n\n\t\tconst tableCell = findAncestor( 'tableCell', firstPosition );\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\n\t\tconst headingColumns = table.getAttribute( 'headingColumns' ) || 0;\n\t\tconst row = table.getChildIndex( tableRow );\n\n\t\t// Cache the table before removing or updating colspans.\n\t\tconst tableMap = [ ...new TableWalker( table ) ];\n\n\t\t// Get column index of removed column.\n\t\tconst cellData = tableMap.find( value => value.cell === tableCell );\n\t\tconst removedColumn = cellData.column;\n\n\t\tmodel.change( writer => {\n\t\t\t// Update heading columns attribute if removing a row from head section.\n\t\t\tif ( headingColumns && row <= headingColumns ) {\n\t\t\t\twriter.setAttribute( 'headingColumns', headingColumns - 1, table );\n\t\t\t}\n\n\t\t\tfor ( const { cell, column, colspan } of tableMap ) {\n\t\t\t\t// If colspaned cell overlaps removed column decrease it's span.\n\t\t\t\tif ( column <= removedColumn && colspan > 1 && column + colspan > removedColumn ) {\n\t\t\t\t\tupdateNumericAttribute( 'colspan', colspan - 1, cell, writer );\n\t\t\t\t} else if ( column === removedColumn ) {\n\t\t\t\t\t// The cell in removed column has colspan of 1.\n\t\t\t\t\twriter.remove( cell );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/setheaderrowcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\nimport { createEmptyTableCell, findAncestor, updateNumericAttribute } from './utils';\nimport TableWalker from '../tablewalker';\n\n/**\n * The header row command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'setTableColumnHeader'` editor command.\n *\n * You can make the row containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element) by executing:\n *\n *\t\teditor.execute( 'setTableRowHeader' );\n *\n * **Note:** All preceding rows will also become headers. If the current row is already a header, executing this command\n * will make it a regular row back again (including the following rows).\n *\n * @extends module:core/command~Command\n */\nexport default class SetHeaderRowCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst selection = doc.selection;\n\n\t\tconst position = selection.getFirstPosition();\n\t\tconst tableCell = findAncestor( 'tableCell', position );\n\t\tconst isInTable = !!tableCell;\n\n\t\tthis.isEnabled = isInTable;\n\n\t\t/**\n\t\t * Flag indicating whether the command is active. The command is active when the\n\t\t * {@link module:engine/model/selection~Selection} is in a header row.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #value\n\t\t */\n\t\tthis.value = isInTable && this._isInHeading( tableCell, tableCell.parent.parent );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * When the selection is in a non-header row, the command will set the `headingRows` table attribute to cover that row.\n\t *\n\t * When the selection is already in a header row, it will set `headingRows` so the heading section will end before that row.\n\t *\n\t * @fires execute\n\t * @param {Object} options\n\t * @param {Boolean} [options.forceValue] If set, the command will set (`true`) or unset (`false`) header rows according to `forceValue`\n\t * parameter instead of the current model state.\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst selection = doc.selection;\n\n\t\tconst position = selection.getFirstPosition();\n\t\tconst tableCell = findAncestor( 'tableCell', position );\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\n\t\tconst currentHeadingRows = table.getAttribute( 'headingRows' ) || 0;\n\t\tconst selectionRow = tableRow.index;\n\n\t\tif ( options.forceValue === this.value ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst headingRowsToSet = this.value ? selectionRow : selectionRow + 1;\n\n\t\tmodel.change( writer => {\n\t\t\tif ( headingRowsToSet ) {\n\t\t\t\t// Changing heading rows requires to check if any of a heading cell is overlapping vertically the table head.\n\t\t\t\t// Any table cell that has a rowspan attribute > 1 will not exceed the table head so we need to fix it in rows below.\n\t\t\t\tconst cellsToSplit = getOverlappingCells( table, headingRowsToSet, currentHeadingRows );\n\n\t\t\t\tfor ( const cell of cellsToSplit ) {\n\t\t\t\t\tsplitHorizontally( cell, headingRowsToSet, writer );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tupdateNumericAttribute( 'headingRows', headingRowsToSet, table, writer, 0 );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks if a table cell is in the heading section.\n\t *\n\t * @param {module:engine/model/element~Element} tableCell\n\t * @param {module:engine/model/element~Element} table\n\t * @returns {Boolean}\n\t * @private\n\t */\n\t_isInHeading( tableCell, table ) {\n\t\tconst headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );\n\n\t\treturn !!headingRows && tableCell.parent.index < headingRows;\n\t}\n}\n\n// Returns cells that span beyond the new heading section.\n//\n// @param {module:engine/model/element~Element} table The table to check.\n// @param {Number} headingRowsToSet New heading rows attribute.\n// @param {Number} currentHeadingRows Current heading rows attribute.\n// @returns {Array.<module:engine/model/element~Element>}\nfunction getOverlappingCells( table, headingRowsToSet, currentHeadingRows ) {\n\tconst cellsToSplit = [];\n\n\tconst startAnalysisRow = headingRowsToSet > currentHeadingRows ? currentHeadingRows : 0;\n\t// We're analyzing only when headingRowsToSet > 0.\n\tconst endAnalysisRow = headingRowsToSet - 1;\n\n\tconst tableWalker = new TableWalker( table, { startRow: startAnalysisRow, endRow: endAnalysisRow } );\n\n\tfor ( const { row, rowspan, cell } of tableWalker ) {\n\t\tif ( rowspan > 1 && row + rowspan > headingRowsToSet ) {\n\t\t\tcellsToSplit.push( cell );\n\t\t}\n\t}\n\n\treturn cellsToSplit;\n}\n\n// Splits the table cell horizontally.\n//\n// @param {module:engine/model/element~Element} tableCell\n// @param {Number} headingRows\n// @param {module:engine/model/writer~Writer} writer\nfunction splitHorizontally( tableCell, headingRows, writer ) {\n\tconst tableRow = tableCell.parent;\n\tconst table = tableRow.parent;\n\tconst rowIndex = tableRow.index;\n\n\tconst rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) );\n\tconst newRowspan = headingRows - rowIndex;\n\n\tconst attributes = {};\n\n\tconst spanToSet = rowspan - newRowspan;\n\n\tif ( spanToSet > 1 ) {\n\t\tattributes.rowspan = spanToSet;\n\t}\n\n\tconst colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 );\n\n\tif ( colspan > 1 ) {\n\t\tattributes.colspan = colspan;\n\t}\n\n\tconst startRow = table.getChildIndex( tableRow );\n\tconst endRow = startRow + newRowspan;\n\tconst tableMap = [ ...new TableWalker( table, { startRow, endRow, includeSpanned: true } ) ];\n\n\tlet columnIndex;\n\n\tfor ( const { row, column, cell, cellIndex } of tableMap ) {\n\t\tif ( cell === tableCell && columnIndex === undefined ) {\n\t\t\tcolumnIndex = column;\n\t\t}\n\n\t\tif ( columnIndex !== undefined && columnIndex === column && row === endRow ) {\n\t\t\tconst tableRow = table.getChild( row );\n\t\t\tconst tableCellPosition = writer.createPositionAt( tableRow, cellIndex );\n\n\t\t\tcreateEmptyTableCell( writer, tableCellPosition, attributes );\n\t\t}\n\t}\n\n\t// Update the rowspan attribute after updating table.\n\tupdateNumericAttribute( 'rowspan', newRowspan, tableCell, writer );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/commands/setheadercolumncommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\nimport { findAncestor, updateNumericAttribute } from './utils';\n\n/**\n * The header column command.\n *\n * The command is registered by {@link module:table/tableediting~TableEditing} as `'setTableColumnHeader'` editor command.\n *\n * You can make the column containing the selected cell a [header](https://www.w3.org/TR/html50/tabular-data.html#the-th-element)\n * by executing:\n *\n *\t\teditor.execute( 'setTableColumnHeader' );\n *\n * **Note:** All preceding columns will also become headers. If the current column is already a header, executing this command\n * will make it a regular column back again (including the following columns).\n *\n * @extends module:core/command~Command\n */\nexport default class SetHeaderColumnCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst selection = doc.selection;\n\n\t\tconst position = selection.getFirstPosition();\n\t\tconst tableCell = findAncestor( 'tableCell', position );\n\n\t\tconst isInTable = !!tableCell;\n\n\t\tthis.isEnabled = isInTable;\n\n\t\t/**\n\t\t * Flag indicating whether the command is active. The command is active when the\n\t\t * {@link module:engine/model/selection~Selection} is in a header column.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #value\n\t\t */\n\t\tthis.value = isInTable && this._isInHeading( tableCell, tableCell.parent.parent );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * When the selection is in a non-header column, the command will set the `headingColumns` table attribute to cover that column.\n\t *\n\t * When the selection is already in a header column, it will set `headingColumns` so the heading section will end before that column.\n\t *\n\t * @fires execute\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.forceValue] If set, the command will set (`true`) or unset (`false`) header columns according to\n\t * `forceValue` parameter instead of the current model state.\n\t */\n\texecute( options = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tconst selection = doc.selection;\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\n\t\tconst position = selection.getFirstPosition();\n\t\tconst tableCell = findAncestor( 'tableCell', position );\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\n\t\tconst { column: selectionColumn } = tableUtils.getCellLocation( tableCell );\n\n\t\tif ( options.forceValue === this.value ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst headingColumnsToSet = this.value ? selectionColumn : selectionColumn + 1;\n\n\t\tmodel.change( writer => {\n\t\t\tupdateNumericAttribute( 'headingColumns', headingColumnsToSet, table, writer, 0 );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks if a table cell is in the heading section.\n\t *\n\t * @param {module:engine/model/element~Element} tableCell\n\t * @param {module:engine/model/element~Element} table\n\t * @returns {Boolean}\n\t * @private\n\t */\n\t_isInHeading( tableCell, table ) {\n\t\tconst headingColumns = parseInt( table.getAttribute( 'headingColumns' ) || 0 );\n\n\t\tconst tableUtils = this.editor.plugins.get( 'TableUtils' );\n\n\t\tconst { column } = tableUtils.getCellLocation( tableCell );\n\n\t\treturn !!headingColumns && column < headingColumns;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/tableutils\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport TableWalker from './tablewalker';\nimport { createEmptyTableCell, updateNumericAttribute } from './commands/utils';\n\n/**\n * The table utilities plugin.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TableUtils extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'TableUtils';\n\t}\n\n\t/**\n\t * Returns the table cell location as an object with table row and table column indexes.\n\t *\n\t * For instance in the table below:\n\t *\n\t *\t\t 0 1 2 3\n\t *\t\t +---+---+---+---+\n\t *\t\t0 | a | b | c |\n\t *\t\t + + +---+\n\t *\t\t1 | | | d |\n\t *\t\t +---+---+ +---+\n\t *\t\t2 | e | | f |\n\t *\t\t +---+---+---+---+\n\t *\n\t * the method will return:\n\t *\n\t *\t\tconst cellA = table.getNodeByPath( [ 0, 0 ] );\n\t *\t\teditor.plugins.get( 'TableUtils' ).getCellLocation( cellA );\n\t *\t\t// will return { row: 0, column: 0 }\n\t *\n\t *\t\tconst cellD = table.getNodeByPath( [ 1, 0 ] );\n\t *\t\teditor.plugins.get( 'TableUtils' ).getCellLocation( cellD );\n\t *\t\t// will return { row: 1, column: 3 }\n\t *\n\t * @param {module:engine/model/element~Element} tableCell\n\t * @returns {Object} Returns a `{row, column}` object.\n\t */\n\tgetCellLocation( tableCell ) {\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\n\t\tconst rowIndex = table.getChildIndex( tableRow );\n\n\t\tconst tableWalker = new TableWalker( table, { startRow: rowIndex, endRow: rowIndex } );\n\n\t\tfor ( const { cell, row, column } of tableWalker ) {\n\t\t\tif ( cell === tableCell ) {\n\t\t\t\treturn { row, column };\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Creates an empty table with proper structure. The table needs to be inserted into the model,\n\t * ie. using {@link module:engine/model/model~Model#insertContent} function.\n\t *\n\t *\t\tmodel.change( ( writer ) => {\n\t *\t\t\t// Create a table of 2 rows and 7 columns:\n\t *\t\t\tconst table = tableUtils.createTable( writer, 2, 7);\n\t *\n\t *\t\t\t// Insert table to the model at the best position taking current selection:\n\t *\t\t\tmodel.insertContent( table );\n\t *\t\t}\n\t *\n\t * @param {module:engine/model/writer~Writer} writer The model writer.\n\t * @param {Number} rows The number of rows to create.\n\t * @param {Number} columns The number of columns to create.\n\t * @returns {module:engine/model/element~Element} The created table element.\n\t */\n\tcreateTable( writer, rows, columns ) {\n\t\tconst table = writer.createElement( 'table' );\n\n\t\tcreateEmptyRows( writer, table, 0, rows, columns );\n\n\t\treturn table;\n\t}\n\n\t/**\n\t * Inserts rows into a table.\n\t *\n\t *\t\teditor.plugins.get( 'TableUtils' ).insertRows( table, { at: 1, rows: 2 } );\n\t *\n\t * Assuming the table on the left, the above code will transform it to the table on the right:\n\t *\n\t *\t\trow index\n\t *\t\t 0 +---+---+---+ `at` = 1, +---+---+---+ 0\n\t *\t\t | a | b | c | `rows` = 2, | a | b | c |\n\t *\t\t 1 + +---+---+ <-- insert here + +---+---+ 1\n\t *\t\t | | d | e | | | | |\n\t *\t\t 2 + +---+---+ will give: + +---+---+ 2\n\t *\t\t | | f | g | | | | |\n\t *\t\t 3 +---+---+---+ + +---+---+ 3\n\t *\t\t | | d | e |\n\t *\t\t +---+---+---+ 4\n\t *\t\t + + f | g |\n\t *\t\t +---+---+---+ 5\n\t *\n\t * @param {module:engine/model/element~Element} table The table model element where the rows will be inserted.\n\t * @param {Object} options\n\t * @param {Number} [options.at=0] Row index at which the rows will be inserted.\n\t * @param {Number} [options.rows=1] The number of rows to insert.\n\t */\n\tinsertRows( table, options = {} ) {\n\t\tconst model = this.editor.model;\n\n\t\tconst insertAt = options.at || 0;\n\t\tconst rowsToInsert = options.rows || 1;\n\n\t\tmodel.change( writer => {\n\t\t\tconst headingRows = table.getAttribute( 'headingRows' ) || 0;\n\n\t\t\t// Inserting rows inside heading section requires to update `headingRows` attribute as the heading section will grow.\n\t\t\tif ( headingRows > insertAt ) {\n\t\t\t\twriter.setAttribute( 'headingRows', headingRows + rowsToInsert, table );\n\t\t\t}\n\n\t\t\t// Inserting at the end and at the beginning of a table doesn't require to calculate anything special.\n\t\t\tif ( insertAt === 0 || insertAt === table.childCount ) {\n\t\t\t\tcreateEmptyRows( writer, table, insertAt, rowsToInsert, this.getColumns( table ) );\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Iterate over all rows above inserted rows in order to check for rowspanned cells.\n\t\t\tconst tableIterator = new TableWalker( table, { endRow: insertAt } );\n\n\t\t\t// Will hold number of cells needed to insert in created rows.\n\t\t\t// The number might be different then table cell width when there are rowspanned cells.\n\t\t\tlet cellsToInsert = 0;\n\n\t\t\tfor ( const { row, rowspan, colspan, cell } of tableIterator ) {\n\t\t\t\tconst isBeforeInsertedRow = row < insertAt;\n\t\t\t\tconst overlapsInsertedRow = row + rowspan > insertAt;\n\n\t\t\t\tif ( isBeforeInsertedRow && overlapsInsertedRow ) {\n\t\t\t\t\t// This cell overlaps inserted rows so we need to expand it further.\n\t\t\t\t\twriter.setAttribute( 'rowspan', rowspan + rowsToInsert, cell );\n\t\t\t\t}\n\n\t\t\t\t// Calculate how many cells to insert based on the width of cells in a row at insert position.\n\t\t\t\t// It might be lower then table width as some cells might overlaps inserted row.\n\t\t\t\t// In the table above the cell 'a' overlaps inserted row so only two empty cells are need to be created.\n\t\t\t\tif ( row === insertAt ) {\n\t\t\t\t\tcellsToInsert += colspan;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcreateEmptyRows( writer, table, insertAt, rowsToInsert, cellsToInsert );\n\t\t} );\n\t}\n\n\t/**\n\t * Inserts columns into a table.\n\t *\n\t *\t\teditor.plugins.get( 'TableUtils' ).insertColumns( table, { at: 1, columns: 2 } );\n\t *\n\t * Assuming the table on the left, the above code will transform it to the table on the right:\n\t *\n\t *\t\t0 1 2 3 0 1 2 3 4 5\n\t *\t\t+---+---+---+ +---+---+---+---+---+\n\t *\t\t| a | b | | a | b |\n\t *\t\t+ +---+ + +---+\n\t *\t\t| | c | | | c |\n\t *\t\t+---+---+---+ will give: +---+---+---+---+---+\n\t *\t\t| d | e | f | | d | | | e | f |\n\t *\t\t+---+ +---+ +---+---+---+ +---+\n\t *\t\t| g | | h | | g | | | | h |\n\t *\t\t+---+---+---+ +---+---+---+---+---+\n\t *\t\t| i | | i |\n\t *\t\t+---+---+---+ +---+---+---+---+---+\n\t *\t\t ^---- insert here, `at` = 1, `columns` = 2\n\t *\n\t * @param {module:engine/model/element~Element} table The table model element where the columns will be inserted.\n\t * @param {Object} options\n\t * @param {Number} [options.at=0] Column index at which the columns will be inserted.\n\t * @param {Number} [options.columns=1] The number of columns to insert.\n\t */\n\tinsertColumns( table, options = {} ) {\n\t\tconst model = this.editor.model;\n\n\t\tconst insertAt = options.at || 0;\n\t\tconst columnsToInsert = options.columns || 1;\n\n\t\tmodel.change( writer => {\n\t\t\tconst headingColumns = table.getAttribute( 'headingColumns' );\n\n\t\t\t// Inserting columns inside heading section requires to update `headingColumns` attribute as the heading section will grow.\n\t\t\tif ( insertAt < headingColumns ) {\n\t\t\t\twriter.setAttribute( 'headingColumns', headingColumns + columnsToInsert, table );\n\t\t\t}\n\n\t\t\tconst tableColumns = this.getColumns( table );\n\n\t\t\t// Inserting at the end and at the beginning of a table doesn't require to calculate anything special.\n\t\t\tif ( insertAt === 0 || tableColumns === insertAt ) {\n\t\t\t\tfor ( const tableRow of table.getChildren() ) {\n\t\t\t\t\tcreateCells( columnsToInsert, writer, writer.createPositionAt( tableRow, insertAt ? 'end' : 0 ) );\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst tableWalker = new TableWalker( table, { column: insertAt, includeSpanned: true } );\n\n\t\t\tfor ( const { row, cell, cellIndex } of tableWalker ) {\n\t\t\t\t// When iterating over column the table walker outputs either:\n\t\t\t\t// - cells at given column index (cell \"e\" from method docs),\n\t\t\t\t// - spanned columns (spanned cell from row between cells \"g\" and \"h\" - spanned by \"e\", only if `includeSpanned: true`),\n\t\t\t\t// - or a cell from the same row which spans over this column (cell \"a\").\n\n\t\t\t\tconst rowspan = parseInt( cell.getAttribute( 'rowspan' ) || 1 );\n\t\t\t\tconst colspan = parseInt( cell.getAttribute( 'colspan' ) || 1 );\n\n\t\t\t\tif ( cell.index !== insertAt && colspan > 1 ) {\n\t\t\t\t\t// If column is different than `insertAt`, it is a cell that spans over an inserted column (cell \"a\" & \"i\").\n\t\t\t\t\t// For such cells expand them by a number of columns inserted.\n\t\t\t\t\twriter.setAttribute( 'colspan', colspan + columnsToInsert, cell );\n\n\t\t\t\t\t// The `includeSpanned` option will output the \"empty\"/spanned column so skip this row already.\n\t\t\t\t\ttableWalker.skipRow( row );\n\n\t\t\t\t\t// This cell will overlap cells in rows below so skip them also (because of `includeSpanned` option) - (cell \"a\")\n\t\t\t\t\tif ( rowspan > 1 ) {\n\t\t\t\t\t\tfor ( let i = row + 1; i < row + rowspan; i++ ) {\n\t\t\t\t\t\t\ttableWalker.skipRow( i );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// It's either cell at this column index or spanned cell by a rowspanned cell from row above.\n\t\t\t\t\t// In table above it's cell \"e\" and a spanned position from row below (empty cell between cells \"g\" and \"h\")\n\t\t\t\t\tconst insertPosition = writer.createPositionAt( table.getChild( row ), cellIndex );\n\n\t\t\t\t\tcreateCells( columnsToInsert, writer, insertPosition );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Divides a table cell vertically into several ones.\n\t *\n\t * The cell will be visually split into more cells by updating colspans of other cells in a column\n\t * and inserting cells (columns) after that cell.\n\t *\n\t * In the table below, if cell \"a\" is split to 3 cells:\n\t *\n\t *\t\t+---+---+---+\n\t *\t\t| a | b | c |\n\t *\t\t+---+---+---+\n\t *\t\t| d | e | f |\n\t *\t\t+---+---+---+\n\t *\n\t * it will result in the table below:\n\t *\n\t *\t\t+---+---+---+---+---+\n\t *\t\t| a | | | b | c |\n\t *\t\t+---+---+---+---+---+\n\t *\t\t| d | e | f |\n\t *\t\t+---+---+---+---+---+\n\t *\n\t * So cell \"d\" will get its `colspan` updated to `3` and 2 cells will be added (2 columns will be created).\n\t *\n\t * Splitting a cell that already has a `colspan` attribute set will distribute the cell `colspan` evenly and the remainder\n\t * will be left to the original cell:\n\t *\n\t *\t\t+---+---+---+\n\t *\t\t| a |\n\t *\t\t+---+---+---+\n\t *\t\t| b | c | d |\n\t *\t\t+---+---+---+\n\t *\n\t * Splitting cell \"a\" with `colspan=3` to 2 cells will create 1 cell with a `colspan=a` and cell \"a\" that will have `colspan=2`:\n\t *\n\t *\t\t+---+---+---+\n\t *\t\t| a | |\n\t *\t\t+---+---+---+\n\t *\t\t| b | c | d |\n\t *\t\t+---+---+---+\n\t *\n\t * @param {module:engine/model/element~Element} tableCell\n\t * @param {Number} numberOfCells\n\t */\n\tsplitCellVertically( tableCell, numberOfCells = 2 ) {\n\t\tconst model = this.editor.model;\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\n\t\tconst rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );\n\t\tconst colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 );\n\n\t\tmodel.change( writer => {\n\t\t\t// First check - the cell spans over multiple rows so before doing anything else just split this cell.\n\t\t\tif ( colspan > 1 ) {\n\t\t\t\t// Get spans of new (inserted) cells and span to update of split cell.\n\t\t\t\tconst { newCellsSpan, updatedSpan } = breakSpanEvenly( colspan, numberOfCells );\n\n\t\t\t\tupdateNumericAttribute( 'colspan', updatedSpan, tableCell, writer );\n\n\t\t\t\t// Each inserted cell will have the same attributes:\n\t\t\t\tconst newCellsAttributes = {};\n\n\t\t\t\t// Do not store default value in the model.\n\t\t\t\tif ( newCellsSpan > 1 ) {\n\t\t\t\t\tnewCellsAttributes.colspan = newCellsSpan;\n\t\t\t\t}\n\n\t\t\t\t// Copy rowspan of split cell.\n\t\t\t\tif ( rowspan > 1 ) {\n\t\t\t\t\tnewCellsAttributes.rowspan = rowspan;\n\t\t\t\t}\n\n\t\t\t\tconst cellsToInsert = colspan > numberOfCells ? numberOfCells - 1 : colspan - 1;\n\t\t\t\tcreateCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellsAttributes );\n\t\t\t}\n\n\t\t\t// Second check - the cell has colspan of 1 or we need to create more cells then the currently one spans over.\n\t\t\tif ( colspan < numberOfCells ) {\n\t\t\t\tconst cellsToInsert = numberOfCells - colspan;\n\n\t\t\t\t// First step: expand cells on the same column as split cell.\n\t\t\t\tconst tableMap = [ ...new TableWalker( table ) ];\n\n\t\t\t\t// Get the column index of split cell.\n\t\t\t\tconst { column: splitCellColumn } = tableMap.find( ( { cell } ) => cell === tableCell );\n\n\t\t\t\t// Find cells which needs to be expanded vertically - those on the same column or those that spans over split cell's column.\n\t\t\t\tconst cellsToUpdate = tableMap.filter( ( { cell, colspan, column } ) => {\n\t\t\t\t\tconst isOnSameColumn = cell !== tableCell && column === splitCellColumn;\n\t\t\t\t\tconst spansOverColumn = ( column < splitCellColumn && column + colspan > splitCellColumn );\n\n\t\t\t\t\treturn isOnSameColumn || spansOverColumn;\n\t\t\t\t} );\n\n\t\t\t\t// Expand cells vertically.\n\t\t\t\tfor ( const { cell, colspan } of cellsToUpdate ) {\n\t\t\t\t\twriter.setAttribute( 'colspan', colspan + cellsToInsert, cell );\n\t\t\t\t}\n\n\t\t\t\t// Second step: create columns after split cell.\n\n\t\t\t\t// Each inserted cell will have the same attributes:\n\t\t\t\tconst newCellsAttributes = {};\n\n\t\t\t\t// Do not store default value in the model.\n\n\t\t\t\t// Copy rowspan of split cell.\n\t\t\t\tif ( rowspan > 1 ) {\n\t\t\t\t\tnewCellsAttributes.rowspan = rowspan;\n\t\t\t\t}\n\n\t\t\t\tcreateCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellsAttributes );\n\n\t\t\t\tconst headingColumns = table.getAttribute( 'headingColumns' ) || 0;\n\n\t\t\t\t// Update heading section if split cell is in heading section.\n\t\t\t\tif ( headingColumns > splitCellColumn ) {\n\t\t\t\t\tupdateNumericAttribute( 'headingColumns', headingColumns + cellsToInsert, table, writer );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Divides a table cell horizontally into several ones.\n\t *\n\t * The cell will be visually split into more cells by updating rowspans of other cells in the row and inserting rows with a single cell\n\t * below.\n\t *\n\t * If in the table below cell \"b\" is split to 3 cells:\n\t *\n\t *\t\t+---+---+---+\n\t *\t\t| a | b | c |\n\t *\t\t+---+---+---+\n\t *\t\t| d | e | f |\n\t *\t\t+---+---+---+\n\t *\n\t * It will result in the table below:\n\t *\n\t *\t\t+---+---+---+\n\t *\t\t| a | b | c |\n\t *\t\t+ +---+ +\n\t *\t\t| | | |\n\t *\t\t+ +---+ +\n\t *\t\t| | | |\n\t *\t\t+---+---+---+\n\t *\t\t| d | e | f |\n\t *\t\t+---+---+---+\n\t *\n\t * So cells \"a\" and \"b\" will get their `rowspan` updated to `3` and 2 rows with a single cell will be added.\n\t *\n\t * Splitting a cell that already has a `rowspan` attribute set will distribute the cell `rowspan` evenly and the remainder\n\t * will be left to the original cell:\n\t *\n\t *\t\t+---+---+---+\n\t *\t\t| a | b | c |\n\t *\t\t+ +---+---+\n\t *\t\t| | d | e |\n\t *\t\t+ +---+---+\n\t *\t\t| | f | g |\n\t *\t\t+ +---+---+\n\t *\t\t| | h | i |\n\t *\t\t+---+---+---+\n\t *\n\t * Splitting cell \"a\" with `rowspan=4` to 3 cells will create 2 cells with a `rowspan=1` and cell \"a\" will have `rowspan=2`:\n\t *\n\t *\t\t+---+---+---+\n\t *\t\t| a | b | c |\n\t *\t\t+ +---+---+\n\t *\t\t| | d | e |\n\t *\t\t+---+---+---+\n\t *\t\t| | f | g |\n\t *\t\t+---+---+---+\n\t *\t\t| | h | i |\n\t *\t\t+---+---+---+\n\t *\n\t * @param {module:engine/model/element~Element} tableCell\n\t * @param {Number} numberOfCells\n\t */\n\tsplitCellHorizontally( tableCell, numberOfCells = 2 ) {\n\t\tconst model = this.editor.model;\n\n\t\tconst tableRow = tableCell.parent;\n\t\tconst table = tableRow.parent;\n\t\tconst splitCellRow = table.getChildIndex( tableRow );\n\n\t\tconst rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );\n\t\tconst colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 );\n\n\t\tmodel.change( writer => {\n\t\t\t// First check - the cell spans over multiple rows so before doing anything else just split this cell.\n\t\t\tif ( rowspan > 1 ) {\n\t\t\t\t// Cache table map before updating table.\n\t\t\t\tconst tableMap = [ ...new TableWalker( table, {\n\t\t\t\t\tstartRow: splitCellRow,\n\t\t\t\t\tendRow: splitCellRow + rowspan - 1,\n\t\t\t\t\tincludeSpanned: true\n\t\t\t\t} ) ];\n\n\t\t\t\t// Get spans of new (inserted) cells and span to update of split cell.\n\t\t\t\tconst { newCellsSpan, updatedSpan } = breakSpanEvenly( rowspan, numberOfCells );\n\n\t\t\t\tupdateNumericAttribute( 'rowspan', updatedSpan, tableCell, writer );\n\n\t\t\t\tconst { column: cellColumn } = tableMap.find( ( { cell } ) => cell === tableCell );\n\n\t\t\t\t// Each inserted cell will have the same attributes:\n\t\t\t\tconst newCellsAttributes = {};\n\n\t\t\t\t// Do not store default value in the model.\n\t\t\t\tif ( newCellsSpan > 1 ) {\n\t\t\t\t\tnewCellsAttributes.rowspan = newCellsSpan;\n\t\t\t\t}\n\n\t\t\t\t// Copy colspan of split cell.\n\t\t\t\tif ( colspan > 1 ) {\n\t\t\t\t\tnewCellsAttributes.colspan = colspan;\n\t\t\t\t}\n\n\t\t\t\tfor ( const { column, row, cellIndex } of tableMap ) {\n\t\t\t\t\t// As both newly created cells and the split cell might have rowspan,\n\t\t\t\t\t// the insertion of new cells must go to appropriate rows:\n\t\t\t\t\t//\n\t\t\t\t\t// 1. It's a row after split cell + it's height.\n\t\t\t\t\tconst isAfterSplitCell = row >= splitCellRow + updatedSpan;\n\t\t\t\t\t// 2. Is on the same column.\n\t\t\t\t\tconst isOnSameColumn = column === cellColumn;\n\t\t\t\t\t// 3. And it's row index is after previous cell height.\n\t\t\t\t\tconst isInEvenlySplitRow = ( row + splitCellRow + updatedSpan ) % newCellsSpan === 0;\n\n\t\t\t\t\tif ( isAfterSplitCell && isOnSameColumn && isInEvenlySplitRow ) {\n\t\t\t\t\t\tconst position = writer.createPositionAt( table.getChild( row ), cellIndex );\n\n\t\t\t\t\t\tcreateCells( 1, writer, position, newCellsAttributes );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Second check - the cell has rowspan of 1 or we need to create more cells than the current cell spans over.\n\t\t\tif ( rowspan < numberOfCells ) {\n\t\t\t\t// We already split the cell in check one so here we split to the remaining number of cells only.\n\t\t\t\tconst cellsToInsert = numberOfCells - rowspan;\n\n\t\t\t\t// This check is needed since we need to check if there are any cells from previous rows than spans over this cell's row.\n\t\t\t\tconst tableMap = [ ...new TableWalker( table, { startRow: 0, endRow: splitCellRow } ) ];\n\n\t\t\t\t// First step: expand cells.\n\t\t\t\tfor ( const { cell, rowspan, row } of tableMap ) {\n\t\t\t\t\t// Expand rowspan of cells that are either:\n\t\t\t\t\t// - on the same row as current cell,\n\t\t\t\t\t// - or are below split cell row and overlaps that row.\n\t\t\t\t\tif ( cell !== tableCell && row + rowspan > splitCellRow ) {\n\t\t\t\t\t\tconst rowspanToSet = rowspan + cellsToInsert;\n\n\t\t\t\t\t\twriter.setAttribute( 'rowspan', rowspanToSet, cell );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Second step: create rows with single cell below split cell.\n\t\t\t\tconst newCellsAttributes = {};\n\n\t\t\t\t// Copy colspan of split cell.\n\t\t\t\tif ( colspan > 1 ) {\n\t\t\t\t\tnewCellsAttributes.colspan = colspan;\n\t\t\t\t}\n\n\t\t\t\tcreateEmptyRows( writer, table, splitCellRow + 1, cellsToInsert, 1, newCellsAttributes );\n\n\t\t\t\t// Update heading section if split cell is in heading section.\n\t\t\t\tconst headingRows = table.getAttribute( 'headingRows' ) || 0;\n\n\t\t\t\tif ( headingRows > splitCellRow ) {\n\t\t\t\t\tupdateNumericAttribute( 'headingRows', headingRows + cellsToInsert, table, writer );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Returns the number of columns for a given table.\n\t *\n\t *\t\teditor.plugins.get( 'TableUtils' ).getColumns( table );\n\t *\n\t * @param {module:engine/model/element~Element} table The table to analyze.\n\t * @returns {Number}\n\t */\n\tgetColumns( table ) {\n\t\t// Analyze first row only as all the rows should have the same width.\n\t\tconst row = table.getChild( 0 );\n\n\t\treturn [ ...row.getChildren() ].reduce( ( columns, row ) => {\n\t\t\tconst columnWidth = parseInt( row.getAttribute( 'colspan' ) || 1 );\n\n\t\t\treturn columns + columnWidth;\n\t\t}, 0 );\n\t}\n}\n\n// Creates empty rows at the given index in an existing table.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/element~Element} table\n// @param {Number} insertAt Row index of row insertion.\n// @param {Number} rows Number of rows to create.\n// @param {Number} tableCellToInsert Number of cells to insert in each row.\nfunction createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, attributes = {} ) {\n\tfor ( let i = 0; i < rows; i++ ) {\n\t\tconst tableRow = writer.createElement( 'tableRow' );\n\n\t\twriter.insert( tableRow, table, insertAt );\n\n\t\tcreateCells( tableCellToInsert, writer, writer.createPositionAt( tableRow, 'end' ), attributes );\n\t}\n}\n\n// Creates cells at a given position.\n//\n// @param {Number} columns Number of columns to create\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/position~Position} insertPosition\nfunction createCells( cells, writer, insertPosition, attributes = {} ) {\n\tfor ( let i = 0; i < cells; i++ ) {\n\t\tcreateEmptyTableCell( writer, insertPosition, attributes );\n\t}\n}\n\n// Evenly distributes the span of a cell to a number of provided cells.\n// The resulting spans will always be integer values.\n//\n// For instance breaking a span of 7 into 3 cells will return:\n//\n//\t\t{ newCellsSpan: 2, updatedSpan: 3 }\n//\n// as two cells will have a span of 2 and the remainder will go the first cell so its span will change to 3.\n//\n// @param {Number} span Span value do break.\n// @param {Number} numberOfCells Number of resulting spans.\n// @returns {{newCellsSpan: Number, updatedSpan: Number}}\nfunction breakSpanEvenly( span, numberOfCells ) {\n\tif ( span < numberOfCells ) {\n\t\treturn { newCellsSpan: 1, updatedSpan: 1 };\n\t}\n\n\tconst newCellsSpan = Math.floor( span / numberOfCells );\n\tconst updatedSpan = ( span - newCellsSpan * numberOfCells ) + newCellsSpan;\n\n\treturn { newCellsSpan, updatedSpan };\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/converters/table-layout-post-fixer\n */\n\nimport { createEmptyTableCell, findAncestor, updateNumericAttribute } from './../commands/utils';\nimport TableWalker from './../tablewalker';\n\n/**\n * Injects a table layout post-fixer into the model.\n *\n * The role of the table layout post-fixer is to ensure that the table rows have the correct structure\n * after a {@link module:engine/model/model~Model#change `change()`} block was executed.\n *\n * The correct structure means that:\n *\n * * All table rows have the same size.\n * * None of a table cells that extend vertically beyond their section (either header or body).\n * * A table cell has always at least one element as child.\n *\n * If the table structure is not correct, the post-fixer will automatically correct it in two steps:\n *\n * 1. It will clip table cells that extends beyond it section.\n * 2. It will add empty table cells to those rows which are narrower then the widest table row.\n *\n * ## Clipping overlapping table cells\n *\n * Such situation may occur when pasting a table (or part of a table) to the editor from external sources.\n *\n * For example, see the following table which has the cell (FOO) with the rowspan attribute (2):\n *\n *\t\t<table headingRows=\"1\">\n *\t\t\t<tableRow>\n *\t\t\t\t<tableCell rowspan=\"2\"><paragraph>FOO</paragraph></tableCell>\n *\t\t\t\t<tableCell colspan=\"2\"><paragraph>BAR</paragraph></tableCell>\n *\t\t\t</tableRow>\n *\t\t\t<tableRow>\n *\t\t\t\t<tableCell><paragraph>BAZ</paragraph></tableCell>\n *\t\t\t\t<tableCell><paragraph>XYZ</paragraph></tableCell>\n *\t\t\t</tableRow>\n *\t\t</table>\n *\n * will be rendered in the view as:\n *\n *\t\t<table>\n *\t\t\t<thead>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td rowspan=\"2\">FOO</td>\n *\t\t\t\t\t<td colspan=\"2\">BAR</td>\n *\t\t\t\t</tr>\n *\t\t\t</thead>\n *\t\t\t<tbody>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>BAZ</td>\n *\t\t\t\t\t<td>XYZ</td>\n *\t\t\t\t</tr>\n *\t\t\t</tbody>\n *\t\t</table>\n *\n * In the above example the table will be rendered as a table with two rows - one in the header and second one in the body.\n * The table cell (FOO) cannot span over multiple rows as it would expand from the header to the body section.\n * The `rowspan` attribute must be changed to (1). The value (1) is a default value of the `rowspan` attribute\n * so the `rowspan` attribute will be removed from the model.\n *\n * The table cell with BAZ contents will be in the first column of the table.\n *\n * ## Adding missing table cells\n *\n * The table post-fixer will insert empty table cells to equalize table rows sizes (number of columns).\n * The size of a table row is calculated by counting column spans of table cells - both horizontal (from the same row) and\n * vertical (from rows above).\n *\n * In the above example, the table row in the body section of the table is narrower then the row from the header - it has two cells\n * with the default colspan (1). The header row has one cell with colspan (1) and second with colspan (2).\n * The table cell (FOO) does not expand beyond the head section (and as such will be fixed in the first step of this post-fixer).\n * The post-fixer will add a missing table cell to the row in the body section of the table.\n *\n * The table from the above example will be fixed and rendered to the view as below:\n *\n *\t\t<table>\n *\t\t\t<thead>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td rowspan=\"2\">FOO</td>\n *\t\t\t\t\t<td colspan=\"2\">BAR</td>\n *\t\t\t\t</tr>\n *\t\t\t</thead>\n *\t\t\t<tbody>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>BAZ</td>\n *\t\t\t\t\t<td>XYZ</td>\n *\t\t\t\t</tr>\n *\t\t\t</tbody>\n *\t\t</table>\n *\n * ## Collaboration & Undo - Expectations vs post-fixer results\n *\n * The table post-fixer only ensures proper structure without deeper analysis of the nature of a change. As such, it might lead\n * to a structure which was not intended by the user changes. In particular, it will also fix undo steps (in conjunction with collaboration)\n * in which editor content might not return to the original state.\n *\n * This will usually happen when one or more users changes size of the table.\n *\n * As en example see a table below:\n *\n *\t\t<table>\n *\t\t\t<tbody>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>11</td>\n *\t\t\t\t\t<td>12</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>21</td>\n *\t\t\t\t\t<td>22</td>\n *\t\t\t\t</tr>\n *\t\t\t</tbody>\n *\t\t</table>\n *\n * and user actions:\n *\n * 1. Both user have table with two rows and two columns.\n * 2. User A adds a column at the end of the table - this will insert empty table cells to two rows.\n * 3. User B adds a row at the end of the table- this will insert a row with two empty table cells.\n * 4. Both users will have a table as below:\n *\n *\n *\t\t<table>\n *\t\t\t<tbody>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>11</td>\n *\t\t\t\t\t<td>12</td>\n *\t\t\t\t\t<td>(empty, inserted by A)</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>21</td>\n *\t\t\t\t\t<td>22</td>\n *\t\t\t\t\t<td>(empty, inserted by A)</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>(empty, inserted by B)</td>\n *\t\t\t\t\t<td>(empty, inserted by B)</td>\n *\t\t\t\t</tr>\n *\t\t\t</tbody>\n *\t\t</table>\n *\n * The last row is shorter then others so table post-fixer will add empty row to tha last row:\n *\n *\t\t<table>\n *\t\t\t<tbody>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>11</td>\n *\t\t\t\t\t<td>12</td>\n *\t\t\t\t\t<td>(empty, inserted by A)</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>21</td>\n *\t\t\t\t\t<td>22</td>\n *\t\t\t\t\t<td>(empty, inserted by A)</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>(empty, inserted by B)</td>\n *\t\t\t\t\t<td>(empty, inserted by B)</td>\n *\t\t\t\t\t<td>(empty, inserted by a post-fixer)</td>\n *\t\t\t\t</tr>\n *\t\t\t</tbody>\n *\t\t</table>\n *\n * Unfortunately undo doesn't know the nature of changes and depending which user will apply post-fixer changes undoing them might lead to\n * broken table. If User B will undo inserting column to a table the undo engine will undo only operations of\n * inserting empty cells to rows from initial table state (row 1 & 2) but the cell in post-fixed row will remain:\n *\n *\t\t<table>\n *\t\t\t<tbody>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>11</td>\n *\t\t\t\t\t<td>12</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>21</td>\n *\t\t\t\t\t<td>22</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>(empty, inserted by B)</td>\n *\t\t\t\t\t<td>(empty, inserted by B)</td>\n *\t\t\t\t\t<td>(empty, inserted by a post-fixer)</td>\n *\t\t\t\t</tr>\n *\t\t\t</tbody>\n *\t\t</table>\n *\n * After undo the table post-fixer will detect that two rows are shorter then other and will fix table to:\n *\n *\t\t<table>\n *\t\t\t<tbody>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>11</td>\n *\t\t\t\t\t<td>12</td>\n *\t\t\t\t\t<td>(empty, inserted by a post-fixer after undo)</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>21</td>\n *\t\t\t\t\t<td>22</td>\n *\t\t\t\t\t<td>(empty, inserted by a post-fixer after undo)</td>\n *\t\t\t\t</tr>\n *\t\t\t\t<tr>\n *\t\t\t\t\t<td>(empty, inserted by B)</td>\n *\t\t\t\t\t<td>(empty, inserted by B)</td>\n *\t\t\t\t\t<td>(empty, inserted by a post-fixer)</td>\n *\t\t\t\t</tr>\n *\t\t\t</tbody>\n *\t\t</table>\n * @param {module:engine/model/model~Model} model\n */\nexport default function injectTableLayoutPostFixer( model ) {\n\tmodel.document.registerPostFixer( writer => tableLayoutPostFixer( writer, model ) );\n}\n\n// The table layout post-fixer.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/model~Model} model\nfunction tableLayoutPostFixer( writer, model ) {\n\tconst changes = model.document.differ.getChanges();\n\n\tlet wasFixed = false;\n\n\t// Do not analyze the same table more then once - may happen for multiple changes in the same table.\n\tconst analyzedTables = new Set();\n\n\tfor ( const entry of changes ) {\n\t\tlet table;\n\n\t\tif ( entry.name == 'table' && entry.type == 'insert' ) {\n\t\t\ttable = entry.position.nodeAfter;\n\t\t}\n\n\t\t// Fix table on adding/removing table cells and rows.\n\t\tif ( entry.name == 'tableRow' || entry.name == 'tableCell' ) {\n\t\t\ttable = findAncestor( 'table', entry.position );\n\t\t}\n\n\t\t// Fix table on any table's attribute change - including attributes of table cells.\n\t\tif ( isTableAttributeEntry( entry ) ) {\n\t\t\ttable = findAncestor( 'table', entry.range.start );\n\t\t}\n\n\t\tif ( table && !analyzedTables.has( table ) ) {\n\t\t\t// Step 1: correct rowspans of table cells if necessary.\n\t\t\t// The wasFixed flag should be true if any of tables in batch was fixed - might be more then one.\n\t\t\twasFixed = fixTableCellsRowspan( table, writer ) || wasFixed;\n\t\t\t// Step 2: fix table rows sizes.\n\t\t\twasFixed = fixTableRowsSizes( table, writer ) || wasFixed;\n\n\t\t\tanalyzedTables.add( table );\n\t\t}\n\t}\n\n\treturn wasFixed;\n}\n\n// Fixes the invalid value of the rowspan attribute because a table cell cannot vertically extend beyond the table section it belongs to.\n//\n// @param {module:engine/model/element~Element} table\n// @param {module:engine/model/writer~Writer} writer\n// @returns {Boolean} Returns true if table was fixed.\nfunction fixTableCellsRowspan( table, writer ) {\n\tlet wasFixed = false;\n\n\tconst cellsToTrim = findCellsToTrim( table );\n\n\tif ( cellsToTrim.length ) {\n\t\twasFixed = true;\n\n\t\tfor ( const data of cellsToTrim ) {\n\t\t\tupdateNumericAttribute( 'rowspan', data.rowspan, data.cell, writer, 1 );\n\t\t}\n\t}\n\n\treturn wasFixed;\n}\n\n// Makes all table rows in a table the same size.\n//\n// @param {module:engine/model/element~Element} table\n// @param {module:engine/model/writer~Writer} writer\n// @returns {Boolean} Returns true if table was fixed.\nfunction fixTableRowsSizes( table, writer ) {\n\tlet wasFixed = false;\n\n\tconst rowsLengths = getRowsLengths( table );\n\tconst tableSize = rowsLengths[ 0 ];\n\n\tconst isValid = Object.values( rowsLengths ).every( length => length === tableSize );\n\n\tif ( !isValid ) {\n\t\tconst maxColumns = Object.values( rowsLengths ).reduce( ( prev, current ) => current > prev ? current : prev, 0 );\n\n\t\tfor ( const [ rowIndex, size ] of Object.entries( rowsLengths ) ) {\n\t\t\tconst columnsToInsert = maxColumns - size;\n\n\t\t\tif ( columnsToInsert ) {\n\t\t\t\tfor ( let i = 0; i < columnsToInsert; i++ ) {\n\t\t\t\t\tcreateEmptyTableCell( writer, writer.createPositionAt( table.getChild( rowIndex ), 'end' ) );\n\t\t\t\t}\n\n\t\t\t\twasFixed = true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn wasFixed;\n}\n\n// Searches for the table cells that extends beyond the table section to which they belong to. It will return an array of objects\n// that holds table cells to be trimmed and correct value of a rowspan attribute to set.\n//\n// @param {module:engine/model/element~Element} table\n// @returns {Array.<{{cell, rowspan}}>}\nfunction findCellsToTrim( table ) {\n\tconst headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );\n\tconst maxRows = table.childCount;\n\n\tconst cellsToTrim = [];\n\n\tfor ( const { row, rowspan, cell } of new TableWalker( table ) ) {\n\t\t// Skip cells that do not expand over its row.\n\t\tif ( rowspan < 2 ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst isInHeader = row < headingRows;\n\n\t\t// Row limit is either end of header section or whole table as table body is after the header.\n\t\tconst rowLimit = isInHeader ? headingRows : maxRows;\n\n\t\t// If table cell expands over its limit reduce it height to proper value.\n\t\tif ( row + rowspan > rowLimit ) {\n\t\t\tconst newRowspan = rowLimit - row;\n\n\t\t\tcellsToTrim.push( { cell, rowspan: newRowspan } );\n\t\t}\n\t}\n\n\treturn cellsToTrim;\n}\n\n// Returns an object with lengths of rows assigned to the corresponding row index.\n//\n// @param {module:engine/model/element~Element} table\n// @returns {Object}\nfunction getRowsLengths( table ) {\n\tconst lengths = {};\n\n\tfor ( const { row } of new TableWalker( table, { includeSpanned: true } ) ) {\n\t\tif ( !lengths[ row ] ) {\n\t\t\tlengths[ row ] = 0;\n\t\t}\n\n\t\tlengths[ row ] += 1;\n\t}\n\n\treturn lengths;\n}\n\n// Checks if the differ entry for an attribute change is one of table's attributes.\n//\n// @param entry\n// @returns {Boolean}\nfunction isTableAttributeEntry( entry ) {\n\tconst isAttributeType = entry.type === 'attribute';\n\tconst key = entry.attributeKey;\n\n\treturn isAttributeType && ( key === 'headingRows' || key === 'colspan' || key === 'rowspan' );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/converters/table-cell-paragraph-post-fixer\n */\n\n/**\n * Injects a table cell post-fixer into the model which inserts `paragraph` element into empty table cells.\n *\n * A table cell must contain at least one block element as a child. An empty table cell will have empty `paragraph` as a child.\n *\n *\t\t<table>\n *\t\t\t<tableRow>\n *\t\t\t\t<tableCell></tableCell>\n *\t\t\t</tableRow>\n *\t\t</table>\n *\n * Will be fixed to:\n *\n *\t\t<table>\n *\t\t\t<tableRow>\n *\t\t\t\t<tableCell><paragraph></paragraph></tableCell>\n *\t\t\t</tableRow>\n *\t\t</table>\n *\n * @param {module:engine/model/model~Model} model\n */\nexport default function injectTableCellParagraphPostFixer( model ) {\n\tmodel.document.registerPostFixer( writer => tableCellContentsPostFixer( writer, model ) );\n}\n\n// The table cell contents post-fixer.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/model~Model} model\nfunction tableCellContentsPostFixer( writer, model ) {\n\tconst changes = model.document.differ.getChanges();\n\n\tlet wasFixed = false;\n\n\tfor ( const entry of changes ) {\n\t\tif ( entry.type == 'insert' && entry.name == 'table' ) {\n\t\t\twasFixed = fixTable( entry.position.nodeAfter, writer ) || wasFixed;\n\t\t}\n\n\t\tif ( entry.type == 'insert' && entry.name == 'tableRow' ) {\n\t\t\twasFixed = fixTableRow( entry.position.nodeAfter, writer ) || wasFixed;\n\t\t}\n\n\t\tif ( entry.type == 'insert' && entry.name == 'tableCell' ) {\n\t\t\twasFixed = fixTableCellContent( entry.position.nodeAfter, writer ) || wasFixed;\n\t\t}\n\n\t\tif ( checkTableCellChange( entry ) ) {\n\t\t\twasFixed = fixTableCellContent( entry.position.parent, writer ) || wasFixed;\n\t\t}\n\t}\n\n\treturn wasFixed;\n}\n\n// Fixes all table cells in a table.\n//\n// @param {module:engine/model/element~Element} table\n// @param {module:engine/model/writer~Writer} writer\nfunction fixTable( table, writer ) {\n\tlet wasFixed = false;\n\n\tfor ( const row of table.getChildren() ) {\n\t\twasFixed = fixTableRow( row, writer ) || wasFixed;\n\t}\n\n\treturn wasFixed;\n}\n\n// Fixes all table cells in a table row.\n//\n// @param {module:engine/model/element~Element} tableRow\n// @param {module:engine/model/writer~Writer} writer\nfunction fixTableRow( tableRow, writer ) {\n\tlet wasFixed = false;\n\n\tfor ( const tableCell of tableRow.getChildren() ) {\n\t\twasFixed = fixTableCellContent( tableCell, writer ) || wasFixed;\n\t}\n\n\treturn wasFixed;\n}\n\n// Fixes all table cell content by:\n// - adding paragraph to a table cell without any child.\n// - wrapping direct $text in <paragraph>.\n//\n// @param {module:engine/model/element~Element} table\n// @param {module:engine/model/writer~Writer} writer\n// @returns {Boolean}\nfunction fixTableCellContent( tableCell, writer ) {\n\t// Insert paragraph to an empty table cell.\n\tif ( tableCell.childCount == 0 ) {\n\t\twriter.insertElement( 'paragraph', tableCell );\n\n\t\treturn true;\n\t}\n\n\t// Check table cell children for directly placed text nodes.\n\t// Temporary solution. See https://github.com/ckeditor/ckeditor5/issues/1464.\n\tconst textNodes = Array.from( tableCell.getChildren() ).filter( child => child.is( 'text' ) );\n\n\tfor ( const child of textNodes ) {\n\t\twriter.wrap( writer.createRangeOn( child ), 'paragraph' );\n\t}\n\n\t// Return true when there were text nodes to fix.\n\treturn !!textNodes.length;\n}\n\n// Check if differ change should fix table cell. This happens on:\n// - removing content from table cell (ie tableCell can be left empty).\n// - adding text node directly into a table cell.\n//\n// @param {Object} differ change entry\n// @returns {Boolean}\nfunction checkTableCellChange( entry ) {\n\tif ( !entry.position || !entry.position.parent.is( 'tableCell' ) ) {\n\t\treturn false;\n\t}\n\n\treturn entry.type == 'insert' && entry.name == '$text' || entry.type == 'remove';\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/converters/table-cell-refresh-post-fixer\n */\n\n/**\n * Injects a table cell post-fixer into the model which marks the table cell in the differ to have it re-rendered.\n *\n * Model `paragraph` inside a table cell can be rendered as `<span>` or `<p>`. It is rendered as `<span>` if this is the only block\n * element in that table cell and it doesn't have any attributes. It is rendered as `<p>` otherwise.\n *\n * When table cell content changes, for example a second `paragraph` element is added we need to ensure that the first `paragraph` is\n * re-rendered so it changes to `<p>` from `<span>`. The easiest way to do it is to re-render whole table cell.\n *\n * @param {module:engine/model/model~Model} model\n */\nexport default function injectTableCellRefreshPostFixer( model ) {\n\tmodel.document.registerPostFixer( () => tableCellRefreshPostFixer( model ) );\n}\n\nfunction tableCellRefreshPostFixer( model ) {\n\tconst differ = model.document.differ;\n\n\t// Stores cells to be refreshed so the table cell will be refreshed once for multiple changes.\n\tconst cellsToRefresh = new Set();\n\n\tfor ( const change of differ.getChanges() ) {\n\t\tconst parent = change.type == 'insert' || change.type == 'remove' ? change.position.parent : change.range.start.parent;\n\n\t\tif ( parent.is( 'tableCell' ) && checkRefresh( parent, change.type ) ) {\n\t\t\tcellsToRefresh.add( parent );\n\t\t}\n\t}\n\n\tif ( cellsToRefresh.size ) {\n\t\tfor ( const tableCell of cellsToRefresh.values() ) {\n\t\t\tdiffer.refreshItem( tableCell );\n\t\t}\n\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n// Checks if the model table cell requires refreshing to be re-rendered to a proper state in the view.\n//\n// This methods detects changes that will require renaming <span> to <p> (or vice versa) in the view.\n//\n// This method is a simple heuristic that checks only a single change and will sometimes give a false positive result when multiple changes\n// will result in a state that does not require renaming in the view (but will be seen as requiring a refresh).\n//\n// For instance: a `<span>` should be renamed to `<p>` when adding an attribute to a `<paragraph>`.\n// But adding one attribute and removing another one will result in a false positive: the check for added attribute will see one attribute\n// on a paragraph and will falsy qualify such change as adding an attribute to a paragraph without any attribute.\n//\n// @param {module:engine/model/element~Element} tableCell Table cell to check.\n// @param {String} type Type of change.\nfunction checkRefresh( tableCell, type ) {\n\tconst hasInnerParagraph = Array.from( tableCell.getChildren() ).some( child => child.is( 'paragraph' ) );\n\n\t// If there is no paragraph in table cell then the view doesn't require refreshing.\n\t//\n\t// Why? What we really want to achieve is to make all the old paragraphs (which weren't added in this batch) to be\n\t// converted once again, so that the paragraph-in-table-cell converter can correctly create a `<p>` or a `<span>` element.\n\t// If there are no paragraphs in the table cell, we don't care.\n\tif ( !hasInnerParagraph ) {\n\t\treturn false;\n\t}\n\n\t// For attribute change we only refresh if there is a single paragraph as in this case we may want to change existing `<span>` to `<p>`.\n\tif ( type == 'attribute' ) {\n\t\tconst attributesCount = Array.from( tableCell.getChild( 0 ).getAttributeKeys() ).length;\n\n\t\treturn tableCell.childCount === 1 && attributesCount < 2;\n\t}\n\n\t// For other changes (insert, remove) the `<span>` to `<p>` change is needed when:\n\t//\n\t// - another element is added to a single paragraph (childCount becomes >= 2)\n\t// - another element is removed and a single paragraph is left (childCount == 1)\n\treturn tableCell.childCount <= ( type == 'insert' ? 2 : 1 );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/tableediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport upcastTable, { upcastTableCell } from './converters/upcasttable';\nimport {\n\tdowncastInsertCell,\n\tdowncastInsertRow,\n\tdowncastInsertTable,\n\tdowncastRemoveRow,\n\tdowncastTableHeadingColumnsChange,\n\tdowncastTableHeadingRowsChange\n} from './converters/downcast';\n\nimport InsertTableCommand from './commands/inserttablecommand';\nimport InsertRowCommand from './commands/insertrowcommand';\nimport InsertColumnCommand from './commands/insertcolumncommand';\nimport SplitCellCommand from './commands/splitcellcommand';\nimport MergeCellCommand from './commands/mergecellcommand';\nimport RemoveRowCommand from './commands/removerowcommand';\nimport RemoveColumnCommand from './commands/removecolumncommand';\nimport SetHeaderRowCommand from './commands/setheaderrowcommand';\nimport SetHeaderColumnCommand from './commands/setheadercolumncommand';\nimport { findAncestor } from './commands/utils';\nimport TableUtils from '../src/tableutils';\n\nimport injectTableLayoutPostFixer from './converters/table-layout-post-fixer';\nimport injectTableCellParagraphPostFixer from './converters/table-cell-paragraph-post-fixer';\nimport injectTableCellRefreshPostFixer from './converters/table-cell-refresh-post-fixer';\n\nimport '../theme/tableediting.css';\n\n/**\n * The table editing feature.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TableEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'TableEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst schema = model.schema;\n\t\tconst conversion = editor.conversion;\n\n\t\tschema.register( 'table', {\n\t\t\tallowWhere: '$block',\n\t\t\tallowAttributes: [ 'headingRows', 'headingColumns' ],\n\t\t\tisLimit: true,\n\t\t\tisObject: true,\n\t\t\tisBlock: true\n\t\t} );\n\n\t\tschema.register( 'tableRow', {\n\t\t\tallowIn: 'table',\n\t\t\tisLimit: true\n\t\t} );\n\n\t\tschema.register( 'tableCell', {\n\t\t\tallowIn: 'tableRow',\n\t\t\tallowAttributes: [ 'colspan', 'rowspan' ],\n\t\t\tisLimit: true\n\t\t} );\n\n\t\t// Allow all $block content inside table cell.\n\t\tschema.extend( '$block', { allowIn: 'tableCell' } );\n\n\t\t// Disallow table in table.\n\t\tschema.addChildCheck( ( context, childDefinition ) => {\n\t\t\tif ( childDefinition.name == 'table' && Array.from( context.getNames() ).includes( 'table' ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\n\t\t// Table conversion.\n\t\tconversion.for( 'upcast' ).add( upcastTable() );\n\n\t\tconversion.for( 'editingDowncast' ).add( downcastInsertTable( { asWidget: true } ) );\n\t\tconversion.for( 'dataDowncast' ).add( downcastInsertTable() );\n\n\t\t// Table row conversion.\n\t\tconversion.for( 'upcast' ).elementToElement( { model: 'tableRow', view: 'tr' } );\n\n\t\tconversion.for( 'editingDowncast' ).add( downcastInsertRow( { asWidget: true } ) );\n\t\tconversion.for( 'dataDowncast' ).add( downcastInsertRow() );\n\t\tconversion.for( 'downcast' ).add( downcastRemoveRow() );\n\n\t\t// Table cell conversion.\n\t\tconversion.for( 'upcast' ).add( upcastTableCell( 'td' ) );\n\t\tconversion.for( 'upcast' ).add( upcastTableCell( 'th' ) );\n\n\t\tconversion.for( 'editingDowncast' ).add( downcastInsertCell( { asWidget: true } ) );\n\t\tconversion.for( 'dataDowncast' ).add( downcastInsertCell() );\n\n\t\t// Table attributes conversion.\n\t\tconversion.attributeToAttribute( { model: 'colspan', view: 'colspan' } );\n\t\tconversion.attributeToAttribute( { model: 'rowspan', view: 'rowspan' } );\n\n\t\t// Table heading rows and cols conversion.\n\t\tconversion.for( 'editingDowncast' ).add( downcastTableHeadingColumnsChange( { asWidget: true } ) );\n\t\tconversion.for( 'dataDowncast' ).add( downcastTableHeadingColumnsChange() );\n\t\tconversion.for( 'editingDowncast' ).add( downcastTableHeadingRowsChange( { asWidget: true } ) );\n\t\tconversion.for( 'dataDowncast' ).add( downcastTableHeadingRowsChange() );\n\n\t\t// Define all the commands.\n\t\teditor.commands.add( 'insertTable', new InsertTableCommand( editor ) );\n\t\teditor.commands.add( 'insertTableRowAbove', new InsertRowCommand( editor, { order: 'above' } ) );\n\t\teditor.commands.add( 'insertTableRowBelow', new InsertRowCommand( editor, { order: 'below' } ) );\n\t\teditor.commands.add( 'insertTableColumnLeft', new InsertColumnCommand( editor, { order: 'left' } ) );\n\t\teditor.commands.add( 'insertTableColumnRight', new InsertColumnCommand( editor, { order: 'right' } ) );\n\n\t\teditor.commands.add( 'removeTableRow', new RemoveRowCommand( editor ) );\n\t\teditor.commands.add( 'removeTableColumn', new RemoveColumnCommand( editor ) );\n\n\t\teditor.commands.add( 'splitTableCellVertically', new SplitCellCommand( editor, { direction: 'vertically' } ) );\n\t\teditor.commands.add( 'splitTableCellHorizontally', new SplitCellCommand( editor, { direction: 'horizontally' } ) );\n\n\t\teditor.commands.add( 'mergeTableCellRight', new MergeCellCommand( editor, { direction: 'right' } ) );\n\t\teditor.commands.add( 'mergeTableCellLeft', new MergeCellCommand( editor, { direction: 'left' } ) );\n\t\teditor.commands.add( 'mergeTableCellDown', new MergeCellCommand( editor, { direction: 'down' } ) );\n\t\teditor.commands.add( 'mergeTableCellUp', new MergeCellCommand( editor, { direction: 'up' } ) );\n\n\t\teditor.commands.add( 'setTableColumnHeader', new SetHeaderColumnCommand( editor ) );\n\t\teditor.commands.add( 'setTableRowHeader', new SetHeaderRowCommand( editor ) );\n\n\t\tinjectTableLayoutPostFixer( model );\n\t\tinjectTableCellRefreshPostFixer( model );\n\t\tinjectTableCellParagraphPostFixer( model );\n\n\t\t// Handle tab key navigation.\n\t\tthis.editor.keystrokes.set( 'Tab', ( ...args ) => this._handleTabOnSelectedTable( ...args ), { priority: 'low' } );\n\t\tthis.editor.keystrokes.set( 'Tab', this._getTabHandler( true ), { priority: 'low' } );\n\t\tthis.editor.keystrokes.set( 'Shift+Tab', this._getTabHandler( false ), { priority: 'low' } );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ TableUtils ];\n\t}\n\n\t/**\n\t * Handles {@link module:engine/view/document~Document#event:keydown keydown} events for the <kbd>Tab</kbd> key executed\n\t * when the table widget is selected.\n\t *\n\t * @private\n\t * @param {module:utils/eventinfo~EventInfo} eventInfo\n\t * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData\n\t */\n\t_handleTabOnSelectedTable( domEventData, cancel ) {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\n\t\tif ( !selection.isCollapsed && selection.rangeCount === 1 && selection.getFirstRange().isFlat ) {\n\t\t\tconst selectedElement = selection.getSelectedElement();\n\n\t\t\tif ( !selectedElement || !selectedElement.is( 'table' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcancel();\n\n\t\t\teditor.model.change( writer => {\n\t\t\t\twriter.setSelection( writer.createRangeIn( selectedElement.getChild( 0 ).getChild( 0 ) ) );\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Returns a handler for {@link module:engine/view/document~Document#event:keydown keydown} events for the <kbd>Tab</kbd> key executed\n\t * inside table cell.\n\t *\n\t * @private\n\t * @param {Boolean} isForward Whether this handler will move selection to the next cell or previous.\n\t */\n\t_getTabHandler( isForward ) {\n\t\tconst editor = this.editor;\n\n\t\treturn ( domEventData, cancel ) => {\n\t\t\tconst selection = editor.model.document.selection;\n\n\t\t\tconst firstPosition = selection.getFirstPosition();\n\n\t\t\tconst tableCell = findAncestor( 'tableCell', firstPosition );\n\n\t\t\tif ( !tableCell ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcancel();\n\n\t\t\tconst tableRow = tableCell.parent;\n\t\t\tconst table = tableRow.parent;\n\n\t\t\tconst currentRowIndex = table.getChildIndex( tableRow );\n\t\t\tconst currentCellIndex = tableRow.getChildIndex( tableCell );\n\n\t\t\tconst isFirstCellInRow = currentCellIndex === 0;\n\n\t\t\tif ( !isForward && isFirstCellInRow && currentRowIndex === 0 ) {\n\t\t\t\t// It's the first cell of a table - don't do anything (stay in current position).\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst isLastCellInRow = currentCellIndex === tableRow.childCount - 1;\n\t\t\tconst isLastRow = currentRowIndex === table.childCount - 1;\n\n\t\t\tif ( isForward && isLastRow && isLastCellInRow ) {\n\t\t\t\teditor.execute( 'insertTableRowBelow' );\n\n\t\t\t\t// Check if the command actually added a row. If `insertTableRowBelow` execution didn't add a row (because it was disabled\n\t\t\t\t// or it got overwritten) do not change the selection.\n\t\t\t\tif ( currentRowIndex === table.childCount - 1 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet cellToFocus;\n\n\t\t\t// Move to first cell in next row.\n\t\t\tif ( isForward && isLastCellInRow ) {\n\t\t\t\tconst nextRow = table.getChild( currentRowIndex + 1 );\n\n\t\t\t\tcellToFocus = nextRow.getChild( 0 );\n\t\t\t}\n\t\t\t// Move to last cell in a previous row.\n\t\t\telse if ( !isForward && isFirstCellInRow ) {\n\t\t\t\tconst previousRow = table.getChild( currentRowIndex - 1 );\n\n\t\t\t\tcellToFocus = previousRow.getChild( previousRow.childCount - 1 );\n\t\t\t}\n\t\t\t// Move to next/previous cell.\n\t\t\telse {\n\t\t\t\tcellToFocus = tableRow.getChild( currentCellIndex + ( isForward ? 1 : -1 ) );\n\t\t\t}\n\n\t\t\teditor.model.change( writer => {\n\t\t\t\twriter.setSelection( writer.createRangeIn( cellToFocus ) );\n\t\t\t} );\n\t\t};\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 table/ui/inserttableview\n */\n\nimport View from '@ckeditor/ckeditor5-ui/src/view';\n\nimport './../../theme/inserttable.css';\n\n/**\n * The table size view.\n *\n * It renders a 10x10 grid to choose the inserted table size.\n *\n * @extends module:ui/view~View\n * @implements module:ui/dropdown/dropdownpanelfocusable~DropdownPanelFocusable\n */\nexport default class InsertTableView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\t/**\n\t\t * A collection of table size box items.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis.items = this.createCollection();\n\n\t\t/**\n\t\t * The currently selected number of rows of the new table.\n\t\t *\n\t\t * @observable\n\t\t * @member {Number} #rows\n\t\t */\n\t\tthis.set( 'rows', 0 );\n\n\t\t/**\n\t\t * The currently selected number of columns of the new table.\n\t\t *\n\t\t * @observable\n\t\t * @member {Number} #columns\n\t\t */\n\t\tthis.set( 'columns', 0 );\n\n\t\t/**\n\t\t * The label text displayed under the boxes.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #label\n\t\t */\n\t\tthis.bind( 'label' )\n\t\t\t.to( this, 'columns', this, 'rows', ( columns, rows ) => `${ rows } × ${ columns }` );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [ 'ck' ]\n\t\t\t},\n\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'div',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tclass: [ 'ck-insert-table-dropdown__grid' ]\n\t\t\t\t\t},\n\t\t\t\t\tchildren: this.items\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttag: 'div',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tclass: [ 'ck-insert-table-dropdown__label' ]\n\t\t\t\t\t},\n\t\t\t\t\tchildren: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttext: bind.to( 'label' )\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t],\n\n\t\t\ton: {\n\t\t\t\tmousedown: bind.to( evt => {\n\t\t\t\t\tevt.preventDefault();\n\t\t\t\t} ),\n\n\t\t\t\tclick: bind.to( () => {\n\t\t\t\t\tthis.fire( 'execute' );\n\t\t\t\t} )\n\t\t\t}\n\t\t} );\n\n\t\t// Add grid boxes to table selection view.\n\t\tfor ( let index = 0; index < 100; index++ ) {\n\t\t\tconst boxView = new TableSizeGridBoxView();\n\n\t\t\t// Listen to box view 'over' event which indicates that mouse is over this box.\n\t\t\tboxView.on( 'over', () => {\n\t\t\t\t// Translate box index to the row & column index.\n\t\t\t\tconst row = Math.floor( index / 10 );\n\t\t\t\tconst column = index % 10;\n\n\t\t\t\t// As row & column indexes are zero-based transform it to number of selected rows & columns.\n\t\t\t\tthis.set( 'rows', row + 1 );\n\t\t\t\tthis.set( 'columns', column + 1 );\n\t\t\t} );\n\n\t\t\tthis.items.add( boxView );\n\t\t}\n\n\t\tthis.on( 'change:columns', () => {\n\t\t\tthis._highlightGridBoxes();\n\t\t} );\n\n\t\tthis.on( 'change:rows', () => {\n\t\t\tthis._highlightGridBoxes();\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tfocus() {\n\t\t// The dropdown panel expects DropdownPanelFocusable interface on views passed to dropdown panel. See #30.\n\t\t// The method should be implemented while working on keyboard support for this view. See #22.\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tfocusLast() {\n\t\t// The dropdown panel expects DropdownPanelFocusable interface on views passed to dropdown panel. See #30.\n\t\t// The method should be implemented while working on keyboard support for this view. See #22.\n\t}\n\n\t/**\n\t * Highlights grid boxes depending on rows and columns selected.\n\t *\n\t * @private\n\t */\n\t_highlightGridBoxes() {\n\t\tconst rows = this.rows;\n\t\tconst columns = this.columns;\n\n\t\tthis.items.map( ( boxView, index ) => {\n\t\t\t// Translate box index to the row & column index.\n\t\t\tconst itemRow = Math.floor( index / 10 );\n\t\t\tconst itemColumn = index % 10;\n\n\t\t\t// Grid box is highlighted when its row & column index belongs to selected number of rows & columns.\n\t\t\tconst isOn = itemRow < rows && itemColumn < columns;\n\n\t\t\tboxView.set( 'isOn', isOn );\n\t\t} );\n\t}\n}\n\n/**\n * A single grid box view element.\n *\n * This class is used to render the table size selection grid in {@link module:table/ui/inserttableview~InsertTableView}.\n *\n * @private\n */\nclass TableSizeGridBoxView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\t/**\n\t\t * Controls whether the grid box view is \"on\".\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #isOn\n\t\t */\n\t\tthis.set( 'isOn', false );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck-insert-table-dropdown-grid-box',\n\t\t\t\t\tbind.if( 'isOn', 'ck-on' )\n\t\t\t\t]\n\t\t\t},\n\t\t\ton: {\n\t\t\t\tmouseover: bind.to( 'over' )\n\t\t\t}\n\t\t} );\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M3 6v3h4V6H3zm0 4v3h4v-3H3zm0 4v3h4v-3H3zm5 3h4v-3H8v3zm5 0h4v-3h-4v3zm4-4v-3h-4v3h4zm0-4V6h-4v3h4zm1.5 8a1.5 1.5 0 0 1-1.5 1.5H3A1.5 1.5 0 0 1 1.5 17V4c.222-.863 1.068-1.5 2-1.5h13c.932 0 1.778.637 2 1.5v13zM12 13v-3H8v3h4zm0-4V6H8v3h4z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M2.5 1h15A1.5 1.5 0 0 1 19 2.5v15a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 1 17.5v-15A1.5 1.5 0 0 1 2.5 1zM2 2v16h16V2H2z\\\" opacity=\\\".6\\\"/><path d=\\\"M18 7v1H2V7h16zm0 5v1H2v-1h16z\\\" opacity=\\\".6\\\"/><path d=\\\"M14 1v18a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1zm-2 1H8v4h4V2zm0 6H8v4h4V8zm0 6H8v4h4v-4z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M2.5 1h15A1.5 1.5 0 0 1 19 2.5v15a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 1 17.5v-15A1.5 1.5 0 0 1 2.5 1zM2 2v16h16V2H2z\\\" opacity=\\\".6\\\"/><path d=\\\"M7 2h1v16H7V2zm5 0h1v16h-1V2z\\\" opacity=\\\".6\\\"/><path d=\\\"M1 6h18a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm1 2v4h4V8H2zm6 0v4h4V8H8zm6 0v4h4V8h-4z\\\"/></svg>\"","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M2.5 1h15A1.5 1.5 0 0 1 19 2.5v15a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 1 17.5v-15A1.5 1.5 0 0 1 2.5 1zM2 2v16h16V2H2z\\\" opacity=\\\".6\\\"/><path d=\\\"M7 2h1v16H7V2zm5 0h1v7h-1V2zm6 5v1H2V7h16zM8 12v1H2v-1h6z\\\" opacity=\\\".6\\\"/><path d=\\\"M7 7h12a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1zm1 2v9h10V9H8z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module table/tableui\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport {\n addListToDropdown,\n createDropdown\n} from '@ckeditor/ckeditor5-ui/src/dropdown/utils';\nimport Model from '@ckeditor/ckeditor5-ui/src/model';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport InsertTableView from './ui/inserttableview';\nimport tableIcon from './../theme/icons/table.svg';\nimport tableColumnIcon from './../theme/icons/table-column.svg';\nimport tableRowIcon from './../theme/icons/table-row.svg';\nimport tableMergeCellIcon from './../theme/icons/table-merge-cell.svg';\n/**\n * The table UI plugin. It introduces:\n *\n * * The `'insertTable'` dropdown,\n * * The `'tableColumn'` dropdown,\n * * The `'tableRow'` dropdown,\n * * The `'mergeTableCells'` dropdown.\n *\n * The `'tableColumn'`, `'tableRow'`, `'mergeTableCells'` dropdowns work best with {@link module:table/tabletoolbar~TableToolbar}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TableUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const editor = this.editor;\n const t = this.editor.t;\n const contentLanguageDirection = editor.locale.contentLanguageDirection;\n const isContentLtr = contentLanguageDirection === 'ltr';\n editor.ui.componentFactory.add('insertTable', locale => {\n const command = editor.commands.get('insertTable');\n const dropdownView = createDropdown(locale);\n dropdownView.bind('isEnabled').to(command);\n // Decorate dropdown's button.\n dropdownView.buttonView.set({\n icon: tableIcon,\n label: t('k'),\n tooltip: true\n });\n // Prepare custom view for dropdown's panel.\n const insertTableView = new InsertTableView(locale);\n dropdownView.panelView.children.add(insertTableView);\n insertTableView.delegate('execute').to(dropdownView);\n dropdownView.buttonView.on('open', () => {\n // Reset the chooser before showing it to the user.\n insertTableView.rows = 0;\n insertTableView.columns = 0;\n });\n dropdownView.on('execute', () => {\n editor.execute('insertTable', {\n rows: insertTableView.rows,\n columns: insertTableView.columns\n });\n editor.editing.view.focus();\n });\n return dropdownView;\n });\n editor.ui.componentFactory.add('tableColumn', locale => {\n const options = [\n {\n type: 'switchbutton',\n model: {\n commandName: 'setTableColumnHeader',\n label: t('l'),\n bindIsOn: true\n }\n },\n { type: 'separator' },\n {\n type: 'button',\n model: {\n commandName: isContentLtr ? 'insertTableColumnLeft' : 'insertTableColumnRight',\n label: t('m')\n }\n },\n {\n type: 'button',\n model: {\n commandName: isContentLtr ? 'insertTableColumnRight' : 'insertTableColumnLeft',\n label: t('n')\n }\n },\n {\n type: 'button',\n model: {\n commandName: 'removeTableColumn',\n label: t('o')\n }\n }\n ];\n return this._prepareDropdown(t('p'), tableColumnIcon, options, locale);\n });\n editor.ui.componentFactory.add('tableRow', locale => {\n const options = [\n {\n type: 'switchbutton',\n model: {\n commandName: 'setTableRowHeader',\n label: t('q'),\n bindIsOn: true\n }\n },\n { type: 'separator' },\n {\n type: 'button',\n model: {\n commandName: 'insertTableRowBelow',\n label: t('r')\n }\n },\n {\n type: 'button',\n model: {\n commandName: 'insertTableRowAbove',\n label: t('s')\n }\n },\n {\n type: 'button',\n model: {\n commandName: 'removeTableRow',\n label: t('t')\n }\n }\n ];\n return this._prepareDropdown(t('u'), tableRowIcon, options, locale);\n });\n editor.ui.componentFactory.add('mergeTableCells', locale => {\n const options = [\n {\n type: 'button',\n model: {\n commandName: 'mergeTableCellUp',\n label: t('v')\n }\n },\n {\n type: 'button',\n model: {\n commandName: isContentLtr ? 'mergeTableCellRight' : 'mergeTableCellLeft',\n label: t('w')\n }\n },\n {\n type: 'button',\n model: {\n commandName: 'mergeTableCellDown',\n label: t('x')\n }\n },\n {\n type: 'button',\n model: {\n commandName: isContentLtr ? 'mergeTableCellLeft' : 'mergeTableCellRight',\n label: t('y')\n }\n },\n { type: 'separator' },\n {\n type: 'button',\n model: {\n commandName: 'splitTableCellVertically',\n label: t('z')\n }\n },\n {\n type: 'button',\n model: {\n commandName: 'splitTableCellHorizontally',\n label: t('aa')\n }\n }\n ];\n return this._prepareDropdown(t('ab'), tableMergeCellIcon, options, locale);\n });\n }\n /**\n\t * Creates a dropdown view from the set of options.\n\t *\n\t * @private\n\t * @param {String} label The dropdown button label.\n\t * @param {String} icon An icon for the dropdown button.\n\t * @param {Array.<module:ui/dropdown/utils~ListDropdownItemDefinition>} options The list of options for the dropdown.\n\t * @param {module:utils/locale~Locale} locale\n\t * @returns {module:ui/dropdown/dropdownview~DropdownView}\n\t */\n _prepareDropdown(label, icon, options, locale) {\n const editor = this.editor;\n const dropdownView = createDropdown(locale);\n const commands = [];\n // Prepare dropdown list items for list dropdown.\n const itemDefinitions = new Collection();\n for (const option of options) {\n addListOption(option, editor, commands, itemDefinitions);\n }\n addListToDropdown(dropdownView, itemDefinitions);\n // Decorate dropdown's button.\n dropdownView.buttonView.set({\n label,\n icon,\n tooltip: true\n });\n // Make dropdown button disabled when all options are disabled.\n dropdownView.bind('isEnabled').toMany(commands, 'isEnabled', (...areEnabled) => {\n return areEnabled.some(isEnabled => isEnabled);\n });\n this.listenTo(dropdownView, 'execute', evt => {\n editor.execute(evt.source.commandName);\n editor.editing.view.focus();\n });\n return dropdownView;\n }\n}\n// Adds an option to a list view.\n//\n// @param {module:table/tableui~DropdownOption} option Configuration option.\n// @param {module:core/editor/editor~Editor} editor\n// @param {Array.<module:core/command~Command>} commands List of commands to update.\n// @param {Iterable.<module:ui/dropdown/utils~ListDropdownItemDefinition>} itemDefinitions\n// Collection of dropdown items to update with given option.\nfunction addListOption(option, editor, commands, itemDefinitions) {\n const model = option.model = new Model(option.model);\n const {commandName, bindIsOn} = option.model;\n if (option.type !== 'separator') {\n const command = editor.commands.get(commandName);\n commands.push(command);\n model.set({ commandName });\n model.bind('isEnabled').to(command);\n if (bindIsOn) {\n model.bind('isOn').to(command, 'value');\n }\n }\n model.set({ withText: true });\n itemDefinitions.add(option);\n}","/**\n * @license Copyright (c) 2003-2019, 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 paste-from-office/filters/list\n */\n\nimport Element from '@ckeditor/ckeditor5-engine/src/view/element';\nimport Matcher from '@ckeditor/ckeditor5-engine/src/view/matcher';\nimport UpcastWriter from '@ckeditor/ckeditor5-engine/src/view/upcastwriter';\n\n/**\n * Transforms Word specific list-like elements to the semantic HTML lists.\n *\n * Lists in Word are represented by block elements with special attributes like:\n *\n *\t\t<p class=MsoListParagraphCxSpFirst style='mso-list:l1 level1 lfo1'>...</p> // Paragraph based list.\n *\t\t<h1 style='mso-list:l0 level1 lfo1'>...</h1> // Heading 1 based list.\n *\n * @param {module:engine/view/documentfragment~DocumentFragment} documentFragment The view structure which to transform.\n * @param {String} stylesString Styles from which list-like elements styling will be extracted.\n */\nexport function transformListItemLikeElementsIntoLists( documentFragment, stylesString ) {\n\tif ( !documentFragment.childCount ) {\n\t\treturn;\n\t}\n\n\tconst writer = new UpcastWriter();\n\tconst itemLikeElements = findAllItemLikeElements( documentFragment, writer );\n\n\tif ( !itemLikeElements.length ) {\n\t\treturn;\n\t}\n\n\tlet currentList = null;\n\n\titemLikeElements.forEach( ( itemLikeElement, i ) => {\n\t\tif ( !currentList || isNewListNeeded( itemLikeElements[ i - 1 ], itemLikeElement ) ) {\n\t\t\tconst listStyle = detectListStyle( itemLikeElement, stylesString );\n\n\t\t\tcurrentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer );\n\t\t}\n\n\t\tconst listItem = transformElementIntoListItem( itemLikeElement.element, writer );\n\n\t\twriter.appendChild( listItem, currentList );\n\t} );\n}\n\n/**\n * Removes paragraph wrapping content inside a list item.\n *\n * @param {module:engine/view/documentfragment~DocumentFragment} documentFragment\n * @param {module:engine/view/upcastwriter~UpcastWriter} writer\n */\nexport function unwrapParagraphInListItem( documentFragment, writer ) {\n\tfor ( const value of writer.createRangeIn( documentFragment ) ) {\n\t\tconst element = value.item;\n\n\t\tif ( element.is( 'li' ) ) {\n\t\t\t// Google Docs allows on single paragraph inside LI.\n\t\t\tconst firstChild = element.getChild( 0 );\n\n\t\t\tif ( firstChild.is( 'p' ) ) {\n\t\t\t\twriter.unwrapElement( firstChild );\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Finds all list-like elements in a given document fragment.\n//\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment\n// in which to look for list-like nodes.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {Array.<Object>} Array of found list-like items. Each item is an object containing:\n//\n//\t\t* {module:engine/src/view/element~Element} element List-like element.\n//\t\t* {Number} id List item id parsed from `mso-list` style (see `getListItemData()` function).\n//\t\t* {Number} order List item creation order parsed from `mso-list` style (see `getListItemData()` function).\n//\t\t* {Number} indent List item indentation level parsed from `mso-list` style (see `getListItemData()` function).\nfunction findAllItemLikeElements( documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\t// Matcher for finding list-like elements.\n\tconst itemLikeElementsMatcher = new Matcher( {\n\t\tname: /^p|h\\d+$/,\n\t\tstyles: {\n\t\t\t'mso-list': /.*/\n\t\t}\n\t} );\n\n\tconst itemLikeElements = [];\n\n\tfor ( const value of range ) {\n\t\tif ( value.type === 'elementStart' && itemLikeElementsMatcher.match( value.item ) ) {\n\t\t\tconst itemData = getListItemData( value.item );\n\n\t\t\titemLikeElements.push( {\n\t\t\t\telement: value.item,\n\t\t\t\tid: itemData.id,\n\t\t\t\torder: itemData.order,\n\t\t\t\tindent: itemData.indent\n\t\t\t} );\n\t\t}\n\t}\n\n\treturn itemLikeElements;\n}\n\n// Extracts list item style from the provided CSS.\n//\n// List item style is extracted from CSS stylesheet. Each list with its specific style attribute\n// value (`mso-list:l1 level1 lfo1`) has its dedicated properties in a CSS stylesheet defined with a selector like:\n//\n// \t\t@list l1:level1 { ... }\n//\n// It contains `mso-level-number-format` property which defines list numbering/bullet style. If this property\n// is not defined it means default `decimal` numbering.\n//\n// Here CSS string representation is used as `mso-level-number-format` property is an invalid CSS property\n// and will be removed during CSS parsing.\n//\n// @param {Object} listLikeItem List-like item for which list style will be searched for. Usually\n// a result of `findAllItemLikeElements()` function.\n// @param {String} stylesString CSS stylesheet.\n// @returns {Object} result\n// @returns {String} result.type List type, could be `ul` or `ol`.\n// @returns {String} result.style List style, for example: `decimal`, `lower-roman`, etc. It is extracted\n// directly from Word stylesheet without further processing and may be not compatible\n// with CSS `list-style-type` property accepted values.\nfunction detectListStyle( listLikeItem, stylesString ) {\n\tconst listStyleRegexp = new RegExp( `@list l${ listLikeItem.id }:level${ listLikeItem.indent }\\\\s*({[^}]*)`, 'gi' );\n\tconst listStyleTypeRegex = /mso-level-number-format:([^;]*);/gi;\n\n\tconst listStyleMatch = listStyleRegexp.exec( stylesString );\n\n\tlet listStyleType = 'decimal'; // Decimal is default one.\n\tif ( listStyleMatch && listStyleMatch[ 1 ] ) {\n\t\tconst listStyleTypeMatch = listStyleTypeRegex.exec( listStyleMatch[ 1 ] );\n\n\t\tif ( listStyleTypeMatch && listStyleTypeMatch[ 1 ] ) {\n\t\t\tlistStyleType = listStyleTypeMatch[ 1 ].trim();\n\t\t}\n\t}\n\n\treturn {\n\t\ttype: listStyleType !== 'bullet' && listStyleType !== 'image' ? 'ol' : 'ul',\n\t\tstyle: listStyleType\n\t};\n}\n\n// Creates empty list of a given type and inserts it after a specified element.\n//\n// @param {Object} listStyle List style object which determines the type of newly created list.\n// Usually a result of `detectListStyle()` function.\n// @param {module:engine/view/element~Element} element Element before which list is inserted.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {module:engine/view/element~Element} Newly created list element.\nfunction insertNewEmptyList( listStyle, element, writer ) {\n\tconst list = new Element( listStyle.type );\n\tconst position = element.parent.getChildIndex( element );\n\n\twriter.insertChild( position, list, element.parent );\n\n\treturn list;\n}\n\n// Transforms given element into a semantic list item. As the function operates on a provided\n// {module:engine/src/view/element~Element element} it will modify the view structure to which this element belongs.\n//\n// @param {module:engine/view/element~Element} element Element which will be transformed into list item.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {module:engine/view/element~Element} New element to which the given one was transformed. It is\n// inserted in place of the old element (the reference to the old element is lost due to renaming).\nfunction transformElementIntoListItem( element, writer ) {\n\tremoveBulletElement( element, writer );\n\n\treturn writer.rename( 'li', element );\n}\n\n// Extracts list item information from Word specific list-like element style:\n//\n//\t\t`style=\"mso-list:l1 level1 lfo1\"`\n//\n// where:\n//\n//\t\t* `l1` is a list id (however it does not mean this is a continuous list - see #43),\n//\t\t* `level1` is a list item indentation level,\n//\t\t* `lfo1` is a list insertion order in a document.\n//\n// @param {module:engine/view/element~Element} element Element from which style data is extracted.\n// @returns {Object} result\n// @returns {Number} result.id Parent list id.\n// @returns {Number} result.order List item creation order.\n// @returns {Number} result.indent List item indentation level.\nfunction getListItemData( element ) {\n\tconst data = {};\n\tconst listStyle = element.getStyle( 'mso-list' );\n\n\tif ( listStyle ) {\n\t\tdata.id = parseInt( listStyle.match( /(^|\\s+)l(\\d+)/i )[ 2 ] );\n\t\tdata.order = parseInt( listStyle.match( /\\s*lfo(\\d+)/i )[ 1 ] );\n\t\tdata.indent = parseInt( listStyle.match( /\\s*level(\\d+)/i )[ 1 ] );\n\t}\n\n\treturn data;\n}\n\n// Removes span with a numbering/bullet from a given element.\n//\n// @param {module:engine/view/element~Element} element\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\nfunction removeBulletElement( element, writer ) {\n\t// Matcher for finding `span` elements holding lists numbering/bullets.\n\tconst bulletMatcher = new Matcher( {\n\t\tname: 'span',\n\t\tstyles: {\n\t\t\t'mso-list': 'Ignore'\n\t\t}\n\t} );\n\n\tconst range = writer.createRangeIn( element );\n\n\tfor ( const value of range ) {\n\t\tif ( value.type === 'elementStart' && bulletMatcher.match( value.item ) ) {\n\t\t\twriter.remove( value.item );\n\t\t}\n\t}\n}\n\n// Whether previous and current item belongs to the same list. It is determined based on `item.id`\n// (extracted from `mso-list` style, see #getListItemData) and previous sibling of the current item.\n//\n// @param {Object} previousItem\n// @param {Object} currentItem\n// @returns {Boolean}\nfunction isNewListNeeded( previousItem, currentItem ) {\n\tif ( previousItem.id !== currentItem.id ) {\n\t\treturn true;\n\t}\n\n\tconst previousSibling = currentItem.element.previousSibling;\n\n\tif ( !previousSibling ) {\n\t\treturn true;\n\t}\n\n\t// Even with the same id the list does not have to be continuous (#43).\n\treturn !isList( previousSibling );\n}\n\nfunction isList( element ) {\n\treturn element.is( 'ol' ) || element.is( 'ul' );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 paste-from-office/normalizers/googledocsnormalizer\n */\n\nimport removeBoldWrapper from '../filters/removeboldwrapper';\nimport { unwrapParagraphInListItem } from '../filters/list';\nimport UpcastWriter from '@ckeditor/ckeditor5-engine/src/view/upcastwriter';\n\nconst googleDocsMatch = /id=(\"|')docs-internal-guid-[-0-9a-f]+(\"|')/i;\n\n/**\n * Normalizer for the content pasted from Google Docs.\n *\n * @implements module:paste-from-office/normalizer~Normalizer\n */\nexport default class GoogleDocsNormalizer {\n\t/**\n\t * @inheritDoc\n\t */\n\tisActive( htmlString ) {\n\t\treturn googleDocsMatch.test( htmlString );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute( data ) {\n\t\tconst writer = new UpcastWriter();\n\n\t\tremoveBoldWrapper( data.content, writer );\n\t\tunwrapParagraphInListItem( data.content, writer );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 paste-from-office/filters/removeboldwrapper\n */\n\n/**\n * Removes `<b>` tag wrapper added by Google Docs to a copied content.\n *\n * @param {module:engine/view/documentfragment~DocumentFragment} documentFragment element `data.content` obtained from clipboard\n * @param {module:engine/view/upcastwriter~UpcastWriter} writer\n */\nexport default function removeBoldWrapper( documentFragment, writer ) {\n\tfor ( const child of documentFragment.getChildren() ) {\n\t\tif ( child.is( 'b' ) && child.getStyle( 'font-weight' ) === 'normal' ) {\n\t\t\tconst childIndex = documentFragment.getChildIndex( child );\n\n\t\t\twriter.remove( child );\n\t\t\twriter.insertChild( childIndex, child.getChildren(), documentFragment );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 paste-from-office/filters/space\n */\n\n/**\n * Replaces last space preceding elements closing tag with `&nbsp;`. Such operation prevents spaces from being removed\n * during further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).\n * This method also takes into account Word specific `<o:p></o:p>` empty tags.\n * Additionally multiline sequences of spaces and new lines between tags are removed (see #39 and #40).\n *\n * @param {String} htmlString HTML string in which spacing should be normalized.\n * @returns {String} Input HTML with spaces normalized.\n */\nexport function normalizeSpacing( htmlString ) {\n\t// Run normalizeSafariSpaceSpans() two times to cover nested spans.\n\treturn normalizeSafariSpaceSpans( normalizeSafariSpaceSpans( htmlString ) )\n\t\t// Remove all \\r\\n from \"spacerun spans\" so the last replace line doesn't strip all whitespaces.\n\t\t.replace( /(<span style=['\"]mso-spacerun:yes['\"]>[\\s]*?)[\\r\\n]+(\\s*<\\/span>)/g, '$1$2' )\n\t\t.replace( /<span style=['\"]mso-spacerun:yes['\"]><\\/span>/g, '' )\n\t\t.replace( / <\\//g, '\\u00A0</' )\n\t\t.replace( / <o:p><\\/o:p>/g, '\\u00A0<o:p></o:p>' )\n\t\t// Remove <o:p> block filler from empty paragraph. Safari uses \\u00A0 instead of &nbsp;.\n\t\t.replace( /<o:p>(&nbsp;|\\u00A0)<\\/o:p>/g, '' )\n\t\t// Remove all whitespaces when they contain any \\r or \\n.\n\t\t.replace( />(\\s*[\\r\\n]\\s*)</g, '><' );\n}\n\n/**\n * Normalizes spacing in special Word `spacerun spans` (`<span style='mso-spacerun:yes'>\\s+</span>`) by replacing\n * all spaces with `&nbsp; ` pairs. This prevents spaces from being removed during further DOM/View processing\n * (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).\n *\n * @param {Document} htmlDocument Native `Document` object in which spacing should be normalized.\n */\nexport function normalizeSpacerunSpans( htmlDocument ) {\n\thtmlDocument.querySelectorAll( 'span[style*=spacerun]' ).forEach( el => {\n\t\t// Use `el.childNodes[ 0 ].data.length` instead of `el.innerText.length`. For `el.innerText.length` which\n\t\t// contains spaces mixed with `&nbsp;` Edge browser returns incorrect length.\n\t\tconst innerTextLength = el.childNodes[ 0 ].data.length;\n\n\t\tel.innerHTML = Array( innerTextLength + 1 ).join( '\\u00A0 ' ).substr( 0, innerTextLength );\n\t} );\n}\n\n// Normalizes specific spacing generated by Safari when content pasted from Word (`<span class=\"Apple-converted-space\"> </span>`)\n// by replacing all spaces sequences longer than 1 space with `&nbsp; ` pairs. This prevents spaces from being removed during\n// further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).\n//\n// This function is similar to {@link module:clipboard/utils/normalizeclipboarddata normalizeClipboardData util} but uses\n// regular spaces / &nbsp; sequence for replacement.\n//\n// @param {String} htmlString HTML string in which spacing should be normalized\n// @returns {String} Input HTML with spaces normalized.\nfunction normalizeSafariSpaceSpans( htmlString ) {\n\treturn htmlString.replace( /<span(?: class=\"Apple-converted-space\"|)>(\\s+)<\\/span>/g, ( fullMatch, spaces ) => {\n\t\treturn spaces.length === 1 ? ' ' : Array( spaces.length + 1 ).join( '\\u00A0 ' ).substr( 0, spaces.length );\n\t} );\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 paste-from-office/filters/parse\n */\n\n/* globals DOMParser */\n\nimport DomConverter from '@ckeditor/ckeditor5-engine/src/view/domconverter';\n\nimport { normalizeSpacing, normalizeSpacerunSpans } from './space';\n\n/**\n * Parses provided HTML extracting contents of `<body>` and `<style>` tags.\n *\n * @param {String} htmlString HTML string to be parsed.\n * @returns {Object} result\n * @returns {module:engine/view/documentfragment~DocumentFragment} result.body Parsed body\n * content as a traversable structure.\n * @returns {String} result.bodyString Entire body content as a string.\n * @returns {Array.<CSSStyleSheet>} result.styles Array of native `CSSStyleSheet` objects, each representing\n * separate `style` tag from the source HTML.\n * @returns {String} result.stylesString All `style` tags contents combined in the order of occurrence into one string.\n */\nexport function parseHtml( htmlString ) {\n\tconst domParser = new DOMParser();\n\n\t// Remove Word specific \"if comments\" so content inside is not omitted by the parser.\n\thtmlString = htmlString.replace( /<!--\\[if gte vml 1]>/g, '' );\n\n\tconst normalizedHtml = normalizeSpacing( cleanContentAfterBody( htmlString ) );\n\n\t// Parse htmlString as native Document object.\n\tconst htmlDocument = domParser.parseFromString( normalizedHtml, 'text/html' );\n\n\tnormalizeSpacerunSpans( htmlDocument );\n\n\t// Get `innerHTML` first as transforming to View modifies the source document.\n\tconst bodyString = htmlDocument.body.innerHTML;\n\n\t// Transform document.body to View.\n\tconst bodyView = documentToView( htmlDocument );\n\n\t// Extract stylesheets.\n\tconst stylesObject = extractStyles( htmlDocument );\n\n\treturn {\n\t\tbody: bodyView,\n\t\tbodyString,\n\t\tstyles: stylesObject.styles,\n\t\tstylesString: stylesObject.stylesString\n\t};\n}\n\n// Transforms native `Document` object into {@link module:engine/view/documentfragment~DocumentFragment}.\n//\n// @param {Document} htmlDocument Native `Document` object to be transformed.\n// @returns {module:engine/view/documentfragment~DocumentFragment}\nfunction documentToView( htmlDocument ) {\n\tconst domConverter = new DomConverter( { blockFillerMode: 'nbsp' } );\n\tconst fragment = htmlDocument.createDocumentFragment();\n\tconst nodes = htmlDocument.body.childNodes;\n\n\twhile ( nodes.length > 0 ) {\n\t\tfragment.appendChild( nodes[ 0 ] );\n\t}\n\n\treturn domConverter.domToView( fragment );\n}\n\n// Extracts both `CSSStyleSheet` and string representation from all `style` elements available in a provided `htmlDocument`.\n//\n// @param {Document} htmlDocument Native `Document` object from which styles will be extracted.\n// @returns {Object} result\n// @returns {Array.<CSSStyleSheet>} result.styles Array of native `CSSStyleSheet` object, each representing\n// separate `style` tag from the source object.\n// @returns {String} result.stylesString All `style` tags contents combined in the order of occurrence as one string.\nfunction extractStyles( htmlDocument ) {\n\tconst styles = [];\n\tconst stylesString = [];\n\tconst styleTags = Array.from( htmlDocument.getElementsByTagName( 'style' ) );\n\n\tfor ( const style of styleTags ) {\n\t\tif ( style.sheet && style.sheet.cssRules && style.sheet.cssRules.length ) {\n\t\t\tstyles.push( style.sheet );\n\t\t\tstylesString.push( style.innerHTML );\n\t\t}\n\t}\n\n\treturn {\n\t\tstyles,\n\t\tstylesString: stylesString.join( ' ' )\n\t};\n}\n\n// Removes leftover content from between closing </body> and closing </html> tag:\n//\n// \t\t<html><body><p>Foo Bar</p></body><span>Fo</span></html> -> <html><body><p>Foo Bar</p></body></html>\n//\n// This function is used as specific browsers (Edge) add some random content after `body` tag when pasting from Word.\n// @param {String} htmlString The HTML string to be cleaned.\n// @returns {String} The HTML string with leftover content removed.\nfunction cleanContentAfterBody( htmlString ) {\n\tconst regexp = /<\\/body>(.*?)(<\\/html>|$)/;\n\tconst match = htmlString.match( regexp );\n\n\tif ( match && match[ 1 ] ) {\n\t\thtmlString = htmlString.slice( 0, match.index ) + htmlString.slice( match.index ).replace( match[ 1 ], '' );\n\t}\n\n\treturn htmlString;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 paste-from-office/filters/image\n */\n\n/* globals btoa */\n\nimport ViewMatcher from '@ckeditor/ckeditor5-engine/src/view/matcher';\nimport UpcastWriter from '@ckeditor/ckeditor5-engine/src/view/upcastwriter';\n\n/**\n * Replaces source attribute of all `<img>` elements representing regular\n * images (not the Word shapes) with inlined base64 image representation extracted from RTF or Blob data.\n *\n * @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment on which transform images.\n * @param {String} rtfData The RTF data from which images representation will be used.\n */\nexport function replaceImagesSourceWithBase64( documentFragment, rtfData ) {\n\tif ( !documentFragment.childCount ) {\n\t\treturn;\n\t}\n\n\tconst upcastWriter = new UpcastWriter();\n\tconst shapesIds = findAllShapesIds( documentFragment, upcastWriter );\n\n\tremoveAllImgElementsRepresentingShapes( shapesIds, documentFragment, upcastWriter );\n\tremoveAllShapeElements( documentFragment, upcastWriter );\n\n\tconst images = findAllImageElementsWithLocalSource( documentFragment, upcastWriter );\n\n\tif ( images.length ) {\n\t\treplaceImagesFileSourceWithInlineRepresentation( images, extractImageDataFromRtf( rtfData ), upcastWriter );\n\t}\n}\n\n/**\n * Converts given HEX string to base64 representation.\n *\n * @protected\n * @param {String} hexString The HEX string to be converted.\n * @returns {String} Base64 representation of a given HEX string.\n */\nexport function _convertHexToBase64( hexString ) {\n\treturn btoa( hexString.match( /\\w{2}/g ).map( char => {\n\t\treturn String.fromCharCode( parseInt( char, 16 ) );\n\t} ).join( '' ) );\n}\n\n// Finds all shapes (`<v:*>...</v:*>`) ids. Shapes can represent images (canvas)\n// or Word shapes (which does not have RTF or Blob representation).\n//\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment\n// from which to extract shape ids.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {Array.<String>} Array of shape ids.\nfunction findAllShapesIds( documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\tconst shapeElementsMatcher = new ViewMatcher( {\n\t\tname: /v:(.+)/\n\t} );\n\n\tconst shapesIds = [];\n\n\tfor ( const value of range ) {\n\t\tconst el = value.item;\n\t\tconst prevSiblingName = el.previousSibling && el.previousSibling.name || null;\n\n\t\t// If shape element have 'o:gfxdata' attribute and is not directly before `<v:shapetype>` element it means it represent Word shape.\n\t\tif ( shapeElementsMatcher.match( el ) && el.getAttribute( 'o:gfxdata' ) && prevSiblingName !== 'v:shapetype' ) {\n\t\t\tshapesIds.push( value.item.getAttribute( 'id' ) );\n\t\t}\n\t}\n\n\treturn shapesIds;\n}\n\n// Removes all `<img>` elements which represents Word shapes and not regular images.\n//\n// @param {Array.<String>} shapesIds Shape ids which will be checked against `<img>` elements.\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment from which to remove `<img>` elements.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\nfunction removeAllImgElementsRepresentingShapes( shapesIds, documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\tconst imageElementsMatcher = new ViewMatcher( {\n\t\tname: 'img'\n\t} );\n\n\tconst imgs = [];\n\n\tfor ( const value of range ) {\n\t\tif ( imageElementsMatcher.match( value.item ) ) {\n\t\t\tconst el = value.item;\n\t\t\tconst shapes = el.getAttribute( 'v:shapes' ) ? el.getAttribute( 'v:shapes' ).split( ' ' ) : [];\n\n\t\t\tif ( shapes.length && shapes.every( shape => shapesIds.indexOf( shape ) > -1 ) ) {\n\t\t\t\timgs.push( el );\n\t\t\t// Shapes may also have empty source while content is paste in some browsers (Safari).\n\t\t\t} else if ( !el.getAttribute( 'src' ) ) {\n\t\t\t\timgs.push( el );\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( const img of imgs ) {\n\t\twriter.remove( img );\n\t}\n}\n\n// Removes all shape elements (`<v:*>...</v:*>`) so they do not pollute the output structure.\n//\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment from which to remove shape elements.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\nfunction removeAllShapeElements( documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\tconst shapeElementsMatcher = new ViewMatcher( {\n\t\tname: /v:(.+)/\n\t} );\n\n\tconst shapes = [];\n\n\tfor ( const value of range ) {\n\t\tif ( shapeElementsMatcher.match( value.item ) ) {\n\t\t\tshapes.push( value.item );\n\t\t}\n\t}\n\n\tfor ( const shape of shapes ) {\n\t\twriter.remove( shape );\n\t}\n}\n\n// Finds all `<img>` elements in a given document fragment which have source pointing to local `file://` resource.\n//\n// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment Document fragment in which to look for `<img>` elements.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\n// @returns {Object} result All found images grouped by source type.\n// @returns {Array.<module:engine/view/element~Element>} result.file Array of found `<img>` elements with `file://` source.\n// @returns {Array.<module:engine/view/element~Element>} result.blob Array of found `<img>` elements with `blob:` source.\nfunction findAllImageElementsWithLocalSource( documentFragment, writer ) {\n\tconst range = writer.createRangeIn( documentFragment );\n\n\tconst imageElementsMatcher = new ViewMatcher( {\n\t\tname: 'img'\n\t} );\n\n\tconst imgs = [];\n\n\tfor ( const value of range ) {\n\t\tif ( imageElementsMatcher.match( value.item ) ) {\n\t\t\tif ( value.item.getAttribute( 'src' ).startsWith( 'file://' ) ) {\n\t\t\t\timgs.push( value.item );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn imgs;\n}\n\n// Extracts all images HEX representations from a given RTF data.\n//\n// @param {String} rtfData The RTF data from which to extract images HEX representation.\n// @returns {Array.<Object>} Array of found HEX representations. Each array item is an object containing:\n//\n// \t\t* {String} hex Image representation in HEX format.\n// \t\t* {string} type Type of image, `image/png` or `image/jpeg`.\nfunction extractImageDataFromRtf( rtfData ) {\n\tif ( !rtfData ) {\n\t\treturn [];\n\t}\n\n\tconst regexPictureHeader = /{\\\\pict[\\s\\S]+?\\\\bliptag-?\\d+(\\\\blipupi-?\\d+)?({\\\\\\*\\\\blipuid\\s?[\\da-fA-F]+)?[\\s}]*?/;\n\tconst regexPicture = new RegExp( '(?:(' + regexPictureHeader.source + '))([\\\\da-fA-F\\\\s]+)\\\\}', 'g' );\n\tconst images = rtfData.match( regexPicture );\n\tconst result = [];\n\n\tif ( images ) {\n\t\tfor ( const image of images ) {\n\t\t\tlet imageType = false;\n\n\t\t\tif ( image.includes( '\\\\pngblip' ) ) {\n\t\t\t\timageType = 'image/png';\n\t\t\t} else if ( image.includes( '\\\\jpegblip' ) ) {\n\t\t\t\timageType = 'image/jpeg';\n\t\t\t}\n\n\t\t\tif ( imageType ) {\n\t\t\t\tresult.push( {\n\t\t\t\t\thex: image.replace( regexPictureHeader, '' ).replace( /[^\\da-fA-F]/g, '' ),\n\t\t\t\t\ttype: imageType\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// Replaces `src` attribute value of all given images with the corresponding base64 image representation.\n//\n// @param {Array.<module:engine/view/element~Element>} imageElements Array of image elements which will have its source replaced.\n// @param {Array.<Object>} imagesHexSources Array of images hex sources (usually the result of `extractImageDataFromRtf()` function).\n// The array should be the same length as `imageElements` parameter.\n// @param {module:engine/view/upcastwriter~UpcastWriter} writer\nfunction replaceImagesFileSourceWithInlineRepresentation( imageElements, imagesHexSources, writer ) {\n\t// Assume there is an equal amount of image elements and images HEX sources so they can be matched accordingly based on existing order.\n\tif ( imageElements.length === imagesHexSources.length ) {\n\t\tfor ( let i = 0; i < imageElements.length; i++ ) {\n\t\t\tconst newSrc = `data:${ imagesHexSources[ i ].type };base64,${ _convertHexToBase64( imagesHexSources[ i ].hex ) }`;\n\t\t\twriter.setAttribute( 'src', newSrc, imageElements[ i ] );\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 paste-from-office/normalizers/mswordnormalizer\n */\n\nimport { parseHtml } from '../filters/parse';\nimport { transformListItemLikeElementsIntoLists } from '../filters/list';\nimport { replaceImagesSourceWithBase64 } from '../filters/image';\n\nconst msWordMatch1 = /<meta\\s*name=\"?generator\"?\\s*content=\"?microsoft\\s*word\\s*\\d+\"?\\/?>/i;\nconst msWordMatch2 = /xmlns:o=\"urn:schemas-microsoft-com/i;\n\n/**\n * Normalizer for the content pasted from Microsoft Word.\n *\n * @implements module:paste-from-office/normalizer~Normalizer\n */\nexport default class MSWordNormalizer {\n\t/**\n\t * @inheritDoc\n\t */\n\tisActive( htmlString ) {\n\t\treturn msWordMatch1.test( htmlString ) || msWordMatch2.test( htmlString );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\texecute( data ) {\n\t\tconst { body, stylesString } = parseHtml( data.dataTransfer.getData( 'text/html' ) );\n\n\t\ttransformListItemLikeElementsIntoLists( body, stylesString );\n\t\treplaceImagesSourceWithBase64( body, data.dataTransfer.getData( 'text/rtf' ) );\n\n\t\tdata.content = body;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 list/todolistcheckedcommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\n\nconst attributeKey = 'todoListChecked';\n\n/**\n * @extends module:core/command~Command\n */\nexport default class TodoListCheckCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * A flag indicating whether the command is active. The command is active when at least one of\n\t\t * {@link module:engine/model/selection~Selection selected} elements is a to-do list item.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #isEnabled\n\t\t */\n\n\t\t/**\n\t\t * A list of to-do list items selected by the {@link module:engine/model/selection~Selection}.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Array.<module:engine/model/element~Element>} #value\n\t\t */\n\n\t\t/**\n\t\t * A list of to-do list items selected by the {@link module:engine/model/selection~Selection}.\n\t\t *\n\t\t * @protected\n\t\t * @type {Array.<module:engine/model/element~Element>}\n\t\t */\n\t\tthis._selectedElements = [];\n\n\t\t// Refresh command before executing to be sure all values are up to date.\n\t\t// It is needed when selection has changed before command execution, in the same change block.\n\t\tthis.on( 'execute', () => {\n\t\t\tthis.refresh();\n\t\t}, { priority: 'highest' } );\n\t}\n\n\t/**\n\t * Updates the command's {@link #value} and {@link #isEnabled} properties based on the current selection.\n\t */\n\trefresh() {\n\t\tthis._selectedElements = this._getSelectedItems();\n\t\tthis.value = this._selectedElements.every( element => !!element.getAttribute( 'todoListChecked' ) );\n\t\tthis.isEnabled = !!this._selectedElements.length;\n\t}\n\n\t/**\n\t * Gets all to-do list items selected by the {@link module:engine/model/selection~Selection}.\n\t *\n\t * @private\n\t * @returns {Array.<module:engine/model/element~Element>}\n\t */\n\t_getSelectedItems() {\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\n\t\tconst selectionRange = model.document.selection.getFirstRange();\n\t\tconst startElement = selectionRange.start.parent;\n\t\tconst elements = [];\n\n\t\tif ( schema.checkAttribute( startElement, attributeKey ) ) {\n\t\t\telements.push( startElement );\n\t\t}\n\n\t\tfor ( const item of selectionRange.getItems() ) {\n\t\t\tif ( schema.checkAttribute( item, attributeKey ) && !elements.includes( item ) ) {\n\t\t\t\telements.push( item );\n\t\t\t}\n\t\t}\n\n\t\treturn elements;\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.forceValue] If set, it will force the command behavior. If `true`, the command will apply\n\t * the attribute. Otherwise, the command will remove the attribute. If not set, the command will look for its current\n\t * value to decide what it should do.\n\t */\n\texecute( options = {} ) {\n\t\tthis.editor.model.change( writer => {\n\t\t\tfor ( const element of this._selectedElements ) {\n\t\t\t\tconst value = ( options.forceValue === undefined ) ? !this.value : options.forceValue;\n\n\t\t\t\tif ( value ) {\n\t\t\t\t\twriter.setAttribute( attributeKey, true, element );\n\t\t\t\t} else {\n\t\t\t\t\twriter.removeAttribute( attributeKey, element );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n}\n","import baseGetTag from './_baseGetTag.js';\nimport isArray from './isArray.js';\nimport isObjectLike from './isObjectLike.js';\n\n/** `Object#toString` result references. */\nvar stringTag = '[object String]';\n\n/**\n * Checks if `value` is classified as a `String` primitive or object.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a string, else `false`.\n * @example\n *\n * _.isString('abc');\n * // => true\n *\n * _.isString(1);\n * // => false\n */\nfunction isString(value) {\n return typeof value == 'string' ||\n (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);\n}\n\nexport default isString;\n","/**\n * @license Copyright (c) 2003-2019, 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 list/todolistconverters\n */\n\n/* global document */\n\nimport { generateLiInUl, injectViewList } from './utils';\nimport createElement from '@ckeditor/ckeditor5-utils/src/dom/createelement';\n\n/**\n * A model-to-view converter for the `listItem` model element insertion.\n *\n * It converts the `listItem` model element to an unordered list with a {@link module:engine/view/uielement~UIElement checkbox element}\n * at the beginning of each list item. It also merges the list with surrounding lists (if available).\n *\n * It is used by {@link module:engine/controller/editingcontroller~EditingController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewInsertion( model, onCheckboxChecked ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst consumable = conversionApi.consumable;\n\n\t\tif ( !consumable.test( data.item, 'insert' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listType' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listIndent' )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data.item.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelItem = data.item;\n\n\t\tconsumable.consume( modelItem, 'insert' );\n\t\tconsumable.consume( modelItem, 'attribute:listType' );\n\t\tconsumable.consume( modelItem, 'attribute:listIndent' );\n\t\tconsumable.consume( modelItem, 'attribute:todoListChecked' );\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst viewItem = generateLiInUl( modelItem, conversionApi );\n\n\t\tconst isChecked = !!modelItem.getAttribute( 'todoListChecked' );\n\t\tconst checkmarkElement = createCheckmarkElement( modelItem, viewWriter, isChecked, onCheckboxChecked );\n\n\t\tviewWriter.addClass( 'todo-list', viewItem.parent );\n\t\tviewWriter.insert( viewWriter.createPositionAt( viewItem, 0 ), checkmarkElement );\n\n\t\tinjectViewList( modelItem, viewItem, conversionApi, model );\n\t};\n}\n\n/**\n * A model-to-view converter for the `listItem` model element insertion.\n *\n * It is used by {@link module:engine/controller/datacontroller~DataController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function dataModelViewInsertion( model ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst consumable = conversionApi.consumable;\n\n\t\tif ( !consumable.test( data.item, 'insert' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listType' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listIndent' )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data.item.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconsumable.consume( data.item, 'insert' );\n\t\tconsumable.consume( data.item, 'attribute:listType' );\n\t\tconsumable.consume( data.item, 'attribute:listIndent' );\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst modelItem = data.item;\n\t\tconst viewItem = generateLiInUl( modelItem, conversionApi );\n\n\t\tviewWriter.addClass( 'todo-list', viewItem.parent );\n\n\t\tconst label = viewWriter.createAttributeElement( 'label', {\n\t\t\tclass: 'todo-list__label'\n\t\t} );\n\n\t\tconst checkbox = viewWriter.createEmptyElement( 'input', {\n\t\t\ttype: 'checkbox',\n\t\t\tdisabled: 'disabled',\n\t\t} );\n\n\t\tif ( data.item.getAttribute( 'todoListChecked' ) ) {\n\t\t\tviewWriter.setAttribute( 'checked', 'checked', checkbox );\n\t\t\tviewWriter.addClass( 'todo-list__label', label );\n\t\t}\n\n\t\tviewWriter.insert( viewWriter.createPositionAt( viewItem, 0 ), checkbox );\n\t\tviewWriter.wrap( viewWriter.createRangeOn( checkbox ), label );\n\n\t\tinjectViewList( modelItem, viewItem, conversionApi, model );\n\t};\n}\n\n/**\n * A model-to-view converter for the model `$text` element inside a to-do list item.\n *\n * It is used by {@link module:engine/controller/datacontroller~DataController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function dataModelViewTextInsertion( evt, data, conversionApi ) {\n\tconst parent = data.range.start.parent;\n\n\tif ( parent.name != 'listItem' || parent.getAttribute( 'listType' ) != 'todo' ) {\n\t\treturn;\n\t}\n\n\tif ( !conversionApi.consumable.consume( data.item, 'insert' ) ) {\n\t\treturn;\n\t}\n\n\tconst viewWriter = conversionApi.writer;\n\tconst viewPosition = conversionApi.mapper.toViewPosition( data.range.start );\n\tconst viewText = viewWriter.createText( data.item.data );\n\n\tconst span = viewWriter.createAttributeElement( 'span', { class: 'todo-list__label__description' } );\n\tconst label = viewPosition.parent.getChild( 0 );\n\n\tviewWriter.insert( viewWriter.createPositionAt( viewPosition.parent, 'end' ), viewText );\n\tviewWriter.wrap( viewWriter.createRangeOn( viewText ), span );\n\tviewWriter.wrap( viewWriter.createRangeOn( viewText.parent ), label );\n}\n\n/**\n * A view-to-model converter for the checkbox element inside a view list item.\n *\n * It changes the `listType` of the model `listItem` to a `todo` value.\n * When a view checkbox element is marked as checked, an additional `todoListChecked=\"true\"` attribute is added to the model item.\n *\n * It is used by {@link module:engine/controller/datacontroller~DataController}.\n *\n * @see module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data An object containing conversion input, a placeholder for conversion output and possibly other values.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n */\nexport function dataViewModelCheckmarkInsertion( evt, data, conversionApi ) {\n\tconst modelCursor = data.modelCursor;\n\tconst modelItem = modelCursor.parent;\n\tconst viewItem = data.viewItem;\n\n\tif ( viewItem.getAttribute( 'type' ) != 'checkbox' || modelItem.name != 'listItem' || !modelCursor.isAtStart ) {\n\t\treturn;\n\t}\n\n\tif ( !conversionApi.consumable.consume( viewItem, { name: true } ) ) {\n\t\treturn;\n\t}\n\n\tconst writer = conversionApi.writer;\n\n\twriter.setAttribute( 'listType', 'todo', modelItem );\n\n\tif ( data.viewItem.hasAttribute( 'checked' ) ) {\n\t\twriter.setAttribute( 'todoListChecked', true, modelItem );\n\t}\n\n\tdata.modelRange = writer.createRange( modelCursor );\n}\n\n/**\n * A model-to-view converter for the `listType` attribute change on the `listItem` model element.\n *\n * This change means that the `<li>` element parent changes to `<ul class=\"todo-list\">` and a\n * {@link module:engine/view/uielement~UIElement checkbox UI element} is added at the beginning\n * of the list item element (or vice versa).\n *\n * This converter is preceded by {@link module:list/converters~modelViewChangeType} and followed by\n * {@link module:list/converters~modelViewMergeAfterChangeType} to handle splitting and merging surrounding lists of the same type.\n *\n * It is used by {@link module:engine/controller/editingcontroller~EditingController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {Function} onCheckedChange Callback fired after clicking the checkbox UI element.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewChangeType( onCheckedChange, view ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst viewItem = conversionApi.mapper.toViewElement( data.item );\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\tif ( data.attributeNewValue == 'todo' ) {\n\t\t\tconst isChecked = !!data.item.getAttribute( 'todoListChecked' );\n\t\t\tconst checkmarkElement = createCheckmarkElement( data.item, viewWriter, isChecked, onCheckedChange );\n\n\t\t\tviewWriter.addClass( 'todo-list', viewItem.parent );\n\t\t\tviewWriter.insert( viewWriter.createPositionAt( viewItem, 0 ), checkmarkElement );\n\t\t} else if ( data.attributeOldValue == 'todo' ) {\n\t\t\tviewWriter.removeClass( 'todo-list', viewItem.parent );\n\t\t\tviewWriter.remove( findLabel( viewItem, view ) );\n\t\t}\n\t};\n}\n\n/**\n * A model-to-view converter for the `todoListChecked` attribute change on the `listItem` model element.\n *\n * It marks the {@link module:engine/view/uielement~UIElement checkbox UI element} as checked.\n *\n * It is used by {@link module:engine/controller/editingcontroller~EditingController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {Function} onCheckedChange Callback fired after clicking the checkbox UI element.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewChangeChecked( onCheckedChange ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\t// Do not convert `todoListChecked` attribute when to-do list item has changed to other list item.\n\t\t// This attribute will be removed by the model post fixer.\n\t\tif ( data.item.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.consume( data.item, 'attribute:todoListChecked' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { mapper, writer: viewWriter } = conversionApi;\n\t\tconst isChecked = !!data.item.getAttribute( 'todoListChecked' );\n\t\tconst viewItem = mapper.toViewElement( data.item );\n\t\t// Because of m -> v position mapper we can be sure checkbox is always at the beginning.\n\t\tconst oldCheckmarkElement = viewItem.getChild( 0 );\n\t\tconst newCheckmarkElement = createCheckmarkElement( data.item, viewWriter, isChecked, onCheckedChange );\n\n\t\tviewWriter.insert( viewWriter.createPositionAfter( oldCheckmarkElement ), newCheckmarkElement );\n\t\tviewWriter.remove( oldCheckmarkElement );\n\t};\n}\n\n/**\n * A model-to-view position at zero offset mapper.\n *\n * This helper ensures that position inside todo-list in the view is mapped after the checkbox.\n *\n * It only handles the position at the beginning of a list item as other positions are properly mapped be the default mapper.\n *\n * @param {module:engine/view/view~View} view\n * @param {module:engine/conversion/mapper~Mapper} mapper\n * @return {Function}\n */\nexport function mapModelToViewZeroOffsetPosition( view, mapper ) {\n\treturn ( evt, data ) => {\n\t\tconst modelPosition = data.modelPosition;\n\t\tconst parent = modelPosition.parent;\n\n\t\t// Handle only position at the beginning of a todo list item.\n\t\tif ( !parent.is( 'listItem' ) || parent.getAttribute( 'listType' ) != 'todo' || modelPosition.offset !== 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewLi = mapper.toViewElement( parent );\n\t\tconst label = findLabel( viewLi, view );\n\n\t\t// If there is no label then most probably the default converter was overridden.\n\t\tif ( !label ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Map the position to the next sibling (if it is not a marker) - most likely it will be a text node...\n\t\tif ( label.nextSibling && !label.nextSibling.is( 'uiElement' ) ) {\n\t\t\tdata.viewPosition = view.createPositionAt( label.nextSibling, 0 );\n\t\t}\n\t\t// ... otherwise return position after the label.\n\t\telse {\n\t\t\tdata.viewPosition = view.createPositionAfter( label );\n\t\t}\n\t};\n}\n\n// Creates a checkbox UI element.\n//\n// @private\n// @param {module:engine/model/item~Item} modelItem\n// @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter\n// @param {Boolean} isChecked\n// @param {Function} onChange\n// @returns {module:view/uielement~UIElement}\nfunction createCheckmarkElement( modelItem, viewWriter, isChecked, onChange ) {\n\tconst uiElement = viewWriter.createUIElement(\n\t\t'label',\n\t\t{\n\t\t\tclass: 'todo-list__label',\n\t\t\tcontenteditable: false\n\t\t},\n\t\tfunction( domDocument ) {\n\t\t\tconst checkbox = createElement( document, 'input', { type: 'checkbox' } );\n\n\t\t\tif ( isChecked ) {\n\t\t\t\tcheckbox.setAttribute( 'checked', 'checked' );\n\t\t\t}\n\n\t\t\tcheckbox.addEventListener( 'change', () => onChange( modelItem ) );\n\n\t\t\tconst domElement = this.toDomElement( domDocument );\n\n\t\t\tdomElement.appendChild( checkbox );\n\n\t\t\treturn domElement;\n\t\t}\n\t);\n\n\treturn uiElement;\n}\n\n// Helper method to find label element inside li.\nfunction findLabel( viewItem, view ) {\n\tconst range = view.createRangeIn( viewItem );\n\n\tfor ( const value of range ) {\n\t\tif ( value.item.is( 'uiElement', 'label' ) ) {\n\t\t\treturn value.item;\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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/dom/createelement\n */\n\nimport isIterable from '../isiterable';\nimport { isString } from 'lodash-es';\n\n/**\n * Creates element with attributes and children.\n *\n *\t\tcreateElement( document, 'p' ); // <p>\n *\t\tcreateElement( document, 'p', { class: 'foo' } ); // <p class=\"foo\">\n *\t\tcreateElement( document, 'p', null, 'foo' ); // <p>foo</p>\n *\t\tcreateElement( document, 'p', null, [ 'foo', createElement( document, 'img' ) ] ); // <p>foo<img></p>\n *\n * @param {Document} doc Document used to create element.\n * @param {String} name Name of the element.\n * @param {Object} [attributes] Object keys will become attributes keys and object values will became attributes values.\n * @param {Node|String|Array.<Node|String>} [children] Child or array of children. Strings will be automatically turned\n * into Text nodes.\n * @returns {Element} Created element.\n */\nexport default function createElement( doc, name, attributes = {}, children = [] ) {\n\tconst namespace = attributes && attributes.xmlns;\n\tconst element = namespace ? doc.createElementNS( namespace, name ) : doc.createElement( name );\n\n\tfor ( const key in attributes ) {\n\t\telement.setAttribute( key, attributes[ key ] );\n\t}\n\n\tif ( isString( children ) || !isIterable( children ) ) {\n\t\tchildren = [ children ];\n\t}\n\n\tfor ( let child of children ) {\n\t\tif ( isString( child ) ) {\n\t\t\tchild = doc.createTextNode( child );\n\t\t}\n\n\t\telement.appendChild( child );\n\t}\n\n\treturn element;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 list/todolistediting\n */\n\nimport ListCommand from './listcommand';\nimport ListEditing from './listediting';\nimport TodoListCheckCommand from './todolistcheckcommand';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport {\n\tdataModelViewInsertion,\n\tdataModelViewTextInsertion,\n\tdataViewModelCheckmarkInsertion,\n\tmapModelToViewZeroOffsetPosition,\n\tmodelViewChangeChecked,\n\tmodelViewChangeType,\n\tmodelViewInsertion\n} from './todolistconverters';\n\n/**\n * The engine of the to-do list feature. It handles creating, editing and removing to-do lists and their items.\n *\n * It registers the entire functionality of the {@link module:list/listediting~ListEditing list editing plugin} and extends\n * it with the `'todoList'` command.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TodoListEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'TodoListEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ListEditing ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst { editing, data, model } = editor;\n\n\t\t// Extend schema.\n\t\tmodel.schema.extend( 'listItem', {\n\t\t\tallowAttributes: [ 'todoListChecked' ]\n\t\t} );\n\n\t\t// Disallow todoListChecked attribute on other nodes than listItem with to-do listType.\n\t\tmodel.schema.addAttributeCheck( ( context, attributeName ) => {\n\t\t\tconst item = context.last;\n\n\t\t\tif ( attributeName == 'todoListChecked' && item.name == 'listItem' && item.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\n\t\t// Register commands.\n\t\teditor.commands.add( 'todoList', new ListCommand( editor, 'todo' ) );\n\t\teditor.commands.add( 'todoListCheck', new TodoListCheckCommand( editor ) );\n\n\t\t// Define converters.\n\t\tediting.downcastDispatcher.on(\n\t\t\t'insert:listItem',\n\t\t\tmodelViewInsertion( model, listItem => this._handleCheckmarkChange( listItem ) ),\n\t\t\t{ priority: 'high' }\n\t\t);\n\t\tdata.downcastDispatcher.on( 'insert:listItem', dataModelViewInsertion( model ), { priority: 'high' } );\n\t\tdata.downcastDispatcher.on( 'insert:$text', dataModelViewTextInsertion, { priority: 'high' } );\n\n\t\tediting.downcastDispatcher.on(\n\t\t\t'attribute:listType:listItem',\n\t\t\tmodelViewChangeType( listItem => this._handleCheckmarkChange( listItem ), editing.view )\n\t\t);\n\t\tediting.downcastDispatcher.on(\n\t\t\t'attribute:todoListChecked:listItem',\n\t\t\tmodelViewChangeChecked( listItem => this._handleCheckmarkChange( listItem ) )\n\t\t);\n\n\t\tediting.mapper.on( 'modelToViewPosition', mapModelToViewZeroOffsetPosition( editing.view, editing.mapper ) );\n\n\t\tdata.upcastDispatcher.on( 'element:input', dataViewModelCheckmarkInsertion, { priority: 'high' } );\n\n\t\t// Jump at the end of the previous node on left arrow key press, when selection is after the checkbox.\n\t\t//\n\t\t// <blockquote><p>Foo</p></blockquote>\n\t\t// <ul><li><checkbox/>{}Bar</li></ul>\n\t\t//\n\t\t// press: `<-`\n\t\t//\n\t\t// <blockquote><p>Foo{}</p></blockquote>\n\t\t// <ul><li><checkbox/>Bar</li></ul>\n\t\t//\n\t\t// Note: When content language direction is RTL, the behaviour is mirrored.\n\t\tconst localizedJumpOverCheckmarkKey = editor.locale.contentLanguageDirection === 'ltr' ? 'arrowleft' : 'arrowright';\n\n\t\teditor.keystrokes.set( localizedJumpOverCheckmarkKey, ( evt, stop ) => jumpOverCheckmarkOnSideArrowKeyPress( stop, model ) );\n\n\t\t// Toggle check state of selected to-do list items on keystroke.\n\t\teditor.keystrokes.set( 'Ctrl+space', () => editor.execute( 'todoListCheck' ) );\n\n\t\t// Remove `todoListChecked` attribute when a host element is no longer a to-do list item.\n\t\tconst listItemsToFix = new Set();\n\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.type == 'rename' && operation.oldName == 'listItem' ) {\n\t\t\t\tconst item = operation.position.nodeAfter;\n\n\t\t\t\tif ( item.hasAttribute( 'todoListChecked' ) ) {\n\t\t\t\t\tlistItemsToFix.add( item );\n\t\t\t\t}\n\t\t\t} else if ( operation.type == 'changeAttribute' && operation.key == 'listType' && operation.oldValue === 'todo' ) {\n\t\t\t\tfor ( const item of operation.range.getItems() ) {\n\t\t\t\t\tif ( item.hasAttribute( 'todoListChecked' ) && item.getAttribute( 'listType' ) !== 'todo' ) {\n\t\t\t\t\t\tlistItemsToFix.add( item );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\tmodel.document.registerPostFixer( writer => {\n\t\t\tlet hasChanged = false;\n\n\t\t\tfor ( const listItem of listItemsToFix ) {\n\t\t\t\twriter.removeAttribute( 'todoListChecked', listItem );\n\t\t\t\thasChanged = true;\n\t\t\t}\n\n\t\t\tlistItemsToFix.clear();\n\n\t\t\treturn hasChanged;\n\t\t} );\n\t}\n\n\t/**\n\t * Handles the checkbox element change, moves the selection to the corresponding model item to make it possible\n\t * to toggle the `todoListChecked` attribute using the command, and restores the selection position.\n\t *\n\t * Some say it's a hack :) Moving the selection only for executing the command on a certain node and restoring it after,\n\t * is not a clear solution. We need to design an API for using commands beyond the selection range.\n\t * See https://github.com/ckeditor/ckeditor5/issues/1954.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} listItem\n\t */\n\t_handleCheckmarkChange( listItem ) {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst previousSelectionRanges = Array.from( model.document.selection.getRanges() );\n\n\t\tmodel.change( writer => {\n\t\t\twriter.setSelection( listItem, 'end' );\n\t\t\teditor.execute( 'todoListCheck' );\n\t\t\twriter.setSelection( previousSelectionRanges );\n\t\t} );\n\t}\n}\n\n// Handles the left/right (LTR/RTL content) arrow key and moves the selection at the end of the previous block element\n// if the selection is just after the checkbox element. In other words, it jumps over the checkbox element when\n// moving the selection to the left/right (LTR/RTL).\n//\n// @private\n// @param {Function} stopKeyEvent\n// @param {module:engine/model/model~Model} model\nfunction jumpOverCheckmarkOnSideArrowKeyPress( stopKeyEvent, model ) {\n\tconst schema = model.schema;\n\tconst selection = model.document.selection;\n\n\tif ( !selection.isCollapsed ) {\n\t\treturn;\n\t}\n\n\tconst position = selection.getFirstPosition();\n\tconst parent = position.parent;\n\n\tif ( parent.name === 'listItem' && parent.getAttribute( 'listType' ) == 'todo' && position.isAtStart ) {\n\t\tconst newRange = schema.getNearestSelectionRange( model.createPositionBefore( parent ), 'backward' );\n\n\t\tif ( newRange ) {\n\t\t\tstopKeyEvent();\n\t\t\tmodel.change( writer => writer.setSelection( newRange ) );\n\t\t}\n\t}\n}\n","export default \"<svg viewBox=\\\"0 0 20 20\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\"><path d=\\\"M2.3148 14.7048l2.2237-2.2406c.2661-.2622.6975-.2622.9636 0a.6644.6644 0 0 1 0 .9494l-2.6373 2.6573a.6823.6823 0 0 1-.1115.089c-.2526.1968-.6193.1797-.852-.0512L.6885 14.886a.6352.6352 0 0 1 0-.9032.6471.6471 0 0 1 .9102 0l.7161.722zM7.5 14.75a.75.75 0 0 1 .75-.75h9.5a.75.75 0 1 1 0 1.5h-9.5c-.414 0-.75-.336-.75-.75zM2.3288 5.7453l2.2097-2.2265c.2661-.2622.6975-.2622.9636 0a.6644.6644 0 0 1 0 .9494L2.8648 7.1256a.6848.6848 0 0 1-.4953.1965.6444.6444 0 0 1-.4682-.187L.6885 5.9125a.6352.6352 0 0 1 0-.9033.6471.6471 0 0 1 .9102 0l.7301.7361zM7.5 5.75A.75.75 0 0 1 8.25 5h9.5a.75.75 0 1 1 0 1.5h-9.5c-.414 0-.75-.336-.75-.75z\\\"/></svg>\"","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module list/todolistui\n */\nimport { createUIComponent } from './utils';\nimport todoListIcon from '../theme/icons/todolist.svg';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n/**\n * The to-do list UI feature. It introduces the `'todoList'` button that\n * allows to convert elements to and from to-do list items and to indent or outdent them.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TodoListUI extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n init() {\n const t = this.editor.t;\n createUIComponent(this.editor, 'todoList', t('ac'), todoListIcon);\n }\n}","var highlightRegExp = /highlight-(?:text|source)-([a-z0-9]+)/;\n\nfunction highlightedCodeBlock (turndownService) {\n turndownService.addRule('highlightedCodeBlock', {\n filter: function (node) {\n var firstChild = node.firstChild;\n return (\n node.nodeName === 'DIV' &&\n highlightRegExp.test(node.className) &&\n firstChild &&\n firstChild.nodeName === 'PRE'\n )\n },\n replacement: function (content, node, options) {\n var className = node.className || '';\n var language = (className.match(highlightRegExp) || [null, ''])[1];\n\n return (\n '\\n\\n' + options.fence + language + '\\n' +\n node.firstChild.textContent +\n '\\n' + options.fence + '\\n\\n'\n )\n }\n });\n}\n\nfunction strikethrough (turndownService) {\n turndownService.addRule('strikethrough', {\n filter: ['del', 's', 'strike'],\n replacement: function (content) {\n return '~' + content + '~'\n }\n });\n}\n\nvar indexOf = Array.prototype.indexOf;\nvar every = Array.prototype.every;\nvar rules = {};\n\nrules.tableCell = {\n filter: ['th', 'td'],\n replacement: function (content, node) {\n return cell(content, node)\n }\n};\n\nrules.tableRow = {\n filter: 'tr',\n replacement: function (content, node) {\n var borderCells = '';\n var alignMap = { left: ':--', right: '--:', center: ':-:' };\n\n if (isHeadingRow(node)) {\n for (var i = 0; i < node.childNodes.length; i++) {\n var border = '---';\n var align = (\n node.childNodes[i].getAttribute('align') || ''\n ).toLowerCase();\n\n if (align) border = alignMap[align] || border;\n\n borderCells += cell(border, node.childNodes[i]);\n }\n }\n return '\\n' + content + (borderCells ? '\\n' + borderCells : '')\n }\n};\n\nrules.table = {\n // Only convert tables with a heading row.\n // Tables with no heading row are kept using `keep` (see below).\n filter: function (node) {\n return node.nodeName === 'TABLE' && isHeadingRow(node.rows[0])\n },\n\n replacement: function (content) {\n // Ensure there are no blank lines\n content = content.replace('\\n\\n', '\\n');\n return '\\n\\n' + content + '\\n\\n'\n }\n};\n\nrules.tableSection = {\n filter: ['thead', 'tbody', 'tfoot'],\n replacement: function (content) {\n return content\n }\n};\n\n// A tr is a heading row if:\n// - the parent is a THEAD\n// - or if its the first child of the TABLE or the first TBODY (possibly\n// following a blank THEAD)\n// - and every cell is a TH\nfunction isHeadingRow (tr) {\n var parentNode = tr.parentNode;\n return (\n parentNode.nodeName === 'THEAD' ||\n (\n parentNode.firstChild === tr &&\n (parentNode.nodeName === 'TABLE' || isFirstTbody(parentNode)) &&\n every.call(tr.childNodes, function (n) { return n.nodeName === 'TH' })\n )\n )\n}\n\nfunction isFirstTbody (element) {\n var previousSibling = element.previousSibling;\n return (\n element.nodeName === 'TBODY' && (\n !previousSibling ||\n (\n previousSibling.nodeName === 'THEAD' &&\n /^\\s*$/i.test(previousSibling.textContent)\n )\n )\n )\n}\n\nfunction cell (content, node) {\n var index = indexOf.call(node.parentNode.childNodes, node);\n var prefix = ' ';\n if (index === 0) prefix = '| ';\n return prefix + content + ' |'\n}\n\nfunction tables (turndownService) {\n turndownService.keep(function (node) {\n return node.nodeName === 'TABLE' && !isHeadingRow(node.rows[0])\n });\n for (var key in rules) turndownService.addRule(key, rules[key]);\n}\n\nfunction taskListItems (turndownService) {\n turndownService.addRule('taskListItems', {\n filter: function (node) {\n return node.type === 'checkbox' && node.parentNode.nodeName === 'LI'\n },\n replacement: function (content, node) {\n return (node.checked ? '[x]' : '[ ]') + ' '\n }\n });\n}\n\nfunction gfm (turndownService) {\n turndownService.use([\n highlightedCodeBlock,\n strikethrough,\n tables,\n taskListItems\n ]);\n}\n\nexport { gfm, highlightedCodeBlock, strikethrough, tables, taskListItems };\n","function extend (destination) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (source.hasOwnProperty(key)) destination[key] = source[key];\n }\n }\n return destination\n}\n\nfunction repeat (character, count) {\n return Array(count + 1).join(character)\n}\n\nvar blockElements = [\n 'address', 'article', 'aside', 'audio', 'blockquote', 'body', 'canvas',\n 'center', 'dd', 'dir', 'div', 'dl', 'dt', 'fieldset', 'figcaption',\n 'figure', 'footer', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'header', 'hgroup', 'hr', 'html', 'isindex', 'li', 'main', 'menu', 'nav',\n 'noframes', 'noscript', 'ol', 'output', 'p', 'pre', 'section', 'table',\n 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul'\n];\n\nfunction isBlock (node) {\n return blockElements.indexOf(node.nodeName.toLowerCase()) !== -1\n}\n\nvar voidElements = [\n 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input',\n 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'\n];\n\nfunction isVoid (node) {\n return voidElements.indexOf(node.nodeName.toLowerCase()) !== -1\n}\n\nvar voidSelector = voidElements.join();\nfunction hasVoid (node) {\n return node.querySelector && node.querySelector(voidSelector)\n}\n\nvar rules = {};\n\nrules.paragraph = {\n filter: 'p',\n\n replacement: function (content) {\n return '\\n\\n' + content + '\\n\\n'\n }\n};\n\nrules.lineBreak = {\n filter: 'br',\n\n replacement: function (content, node, options) {\n return options.br + '\\n'\n }\n};\n\nrules.heading = {\n filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],\n\n replacement: function (content, node, options) {\n var hLevel = Number(node.nodeName.charAt(1));\n\n if (options.headingStyle === 'setext' && hLevel < 3) {\n var underline = repeat((hLevel === 1 ? '=' : '-'), content.length);\n return (\n '\\n\\n' + content + '\\n' + underline + '\\n\\n'\n )\n } else {\n return '\\n\\n' + repeat('#', hLevel) + ' ' + content + '\\n\\n'\n }\n }\n};\n\nrules.blockquote = {\n filter: 'blockquote',\n\n replacement: function (content) {\n content = content.replace(/^\\n+|\\n+$/g, '');\n content = content.replace(/^/gm, '> ');\n return '\\n\\n' + content + '\\n\\n'\n }\n};\n\nrules.list = {\n filter: ['ul', 'ol'],\n\n replacement: function (content, node) {\n var parent = node.parentNode;\n if (parent.nodeName === 'LI' && parent.lastElementChild === node) {\n return '\\n' + content\n } else {\n return '\\n\\n' + content + '\\n\\n'\n }\n }\n};\n\nrules.listItem = {\n filter: 'li',\n\n replacement: function (content, node, options) {\n content = content\n .replace(/^\\n+/, '') // remove leading newlines\n .replace(/\\n+$/, '\\n') // replace trailing newlines with just a single one\n .replace(/\\n/gm, '\\n '); // indent\n var prefix = options.bulletListMarker + ' ';\n var parent = node.parentNode;\n if (parent.nodeName === 'OL') {\n var start = parent.getAttribute('start');\n var index = Array.prototype.indexOf.call(parent.children, node);\n prefix = (start ? Number(start) + index : index + 1) + '. ';\n }\n return (\n prefix + content + (node.nextSibling && !/\\n$/.test(content) ? '\\n' : '')\n )\n }\n};\n\nrules.indentedCodeBlock = {\n filter: function (node, options) {\n return (\n options.codeBlockStyle === 'indented' &&\n node.nodeName === 'PRE' &&\n node.firstChild &&\n node.firstChild.nodeName === 'CODE'\n )\n },\n\n replacement: function (content, node, options) {\n return (\n '\\n\\n ' +\n node.firstChild.textContent.replace(/\\n/g, '\\n ') +\n '\\n\\n'\n )\n }\n};\n\nrules.fencedCodeBlock = {\n filter: function (node, options) {\n return (\n options.codeBlockStyle === 'fenced' &&\n node.nodeName === 'PRE' &&\n node.firstChild &&\n node.firstChild.nodeName === 'CODE'\n )\n },\n\n replacement: function (content, node, options) {\n var className = node.firstChild.className || '';\n var language = (className.match(/language-(\\S+)/) || [null, ''])[1];\n\n return (\n '\\n\\n' + options.fence + language + '\\n' +\n node.firstChild.textContent +\n '\\n' + options.fence + '\\n\\n'\n )\n }\n};\n\nrules.horizontalRule = {\n filter: 'hr',\n\n replacement: function (content, node, options) {\n return '\\n\\n' + options.hr + '\\n\\n'\n }\n};\n\nrules.inlineLink = {\n filter: function (node, options) {\n return (\n options.linkStyle === 'inlined' &&\n node.nodeName === 'A' &&\n node.getAttribute('href')\n )\n },\n\n replacement: function (content, node) {\n var href = node.getAttribute('href');\n var title = node.title ? ' \"' + node.title + '\"' : '';\n return '[' + content + '](' + href + title + ')'\n }\n};\n\nrules.referenceLink = {\n filter: function (node, options) {\n return (\n options.linkStyle === 'referenced' &&\n node.nodeName === 'A' &&\n node.getAttribute('href')\n )\n },\n\n replacement: function (content, node, options) {\n var href = node.getAttribute('href');\n var title = node.title ? ' \"' + node.title + '\"' : '';\n var replacement;\n var reference;\n\n switch (options.linkReferenceStyle) {\n case 'collapsed':\n replacement = '[' + content + '][]';\n reference = '[' + content + ']: ' + href + title;\n break\n case 'shortcut':\n replacement = '[' + content + ']';\n reference = '[' + content + ']: ' + href + title;\n break\n default:\n var id = this.references.length + 1;\n replacement = '[' + content + '][' + id + ']';\n reference = '[' + id + ']: ' + href + title;\n }\n\n this.references.push(reference);\n return replacement\n },\n\n references: [],\n\n append: function (options) {\n var references = '';\n if (this.references.length) {\n references = '\\n\\n' + this.references.join('\\n') + '\\n\\n';\n this.references = []; // Reset references\n }\n return references\n }\n};\n\nrules.emphasis = {\n filter: ['em', 'i'],\n\n replacement: function (content, node, options) {\n if (!content.trim()) return ''\n return options.emDelimiter + content + options.emDelimiter\n }\n};\n\nrules.strong = {\n filter: ['strong', 'b'],\n\n replacement: function (content, node, options) {\n if (!content.trim()) return ''\n return options.strongDelimiter + content + options.strongDelimiter\n }\n};\n\nrules.code = {\n filter: function (node) {\n var hasSiblings = node.previousSibling || node.nextSibling;\n var isCodeBlock = node.parentNode.nodeName === 'PRE' && !hasSiblings;\n\n return node.nodeName === 'CODE' && !isCodeBlock\n },\n\n replacement: function (content) {\n if (!content.trim()) return ''\n\n var delimiter = '`';\n var leadingSpace = '';\n var trailingSpace = '';\n var matches = content.match(/`+/gm);\n if (matches) {\n if (/^`/.test(content)) leadingSpace = ' ';\n if (/`$/.test(content)) trailingSpace = ' ';\n while (matches.indexOf(delimiter) !== -1) delimiter = delimiter + '`';\n }\n\n return delimiter + leadingSpace + content + trailingSpace + delimiter\n }\n};\n\nrules.image = {\n filter: 'img',\n\n replacement: function (content, node) {\n var alt = node.alt || '';\n var src = node.getAttribute('src') || '';\n var title = node.title || '';\n var titlePart = title ? ' \"' + title + '\"' : '';\n return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : ''\n }\n};\n\n/**\n * Manages a collection of rules used to convert HTML to Markdown\n */\n\nfunction Rules (options) {\n this.options = options;\n this._keep = [];\n this._remove = [];\n\n this.blankRule = {\n replacement: options.blankReplacement\n };\n\n this.keepReplacement = options.keepReplacement;\n\n this.defaultRule = {\n replacement: options.defaultReplacement\n };\n\n this.array = [];\n for (var key in options.rules) this.array.push(options.rules[key]);\n}\n\nRules.prototype = {\n add: function (key, rule) {\n this.array.unshift(rule);\n },\n\n keep: function (filter) {\n this._keep.unshift({\n filter: filter,\n replacement: this.keepReplacement\n });\n },\n\n remove: function (filter) {\n this._remove.unshift({\n filter: filter,\n replacement: function () {\n return ''\n }\n });\n },\n\n forNode: function (node) {\n if (node.isBlank) return this.blankRule\n var rule;\n\n if ((rule = findRule(this.array, node, this.options))) return rule\n if ((rule = findRule(this._keep, node, this.options))) return rule\n if ((rule = findRule(this._remove, node, this.options))) return rule\n\n return this.defaultRule\n },\n\n forEach: function (fn) {\n for (var i = 0; i < this.array.length; i++) fn(this.array[i], i);\n }\n};\n\nfunction findRule (rules, node, options) {\n for (var i = 0; i < rules.length; i++) {\n var rule = rules[i];\n if (filterValue(rule, node, options)) return rule\n }\n return void 0\n}\n\nfunction filterValue (rule, node, options) {\n var filter = rule.filter;\n if (typeof filter === 'string') {\n if (filter === node.nodeName.toLowerCase()) return true\n } else if (Array.isArray(filter)) {\n if (filter.indexOf(node.nodeName.toLowerCase()) > -1) return true\n } else if (typeof filter === 'function') {\n if (filter.call(rule, node, options)) return true\n } else {\n throw new TypeError('`filter` needs to be a string, array, or function')\n }\n}\n\n/**\n * The collapseWhitespace function is adapted from collapse-whitespace\n * by Luc Thevenard.\n *\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Luc Thevenard <lucthevenard@gmail.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n/**\n * collapseWhitespace(options) removes extraneous whitespace from an the given element.\n *\n * @param {Object} options\n */\nfunction collapseWhitespace (options) {\n var element = options.element;\n var isBlock = options.isBlock;\n var isVoid = options.isVoid;\n var isPre = options.isPre || function (node) {\n return node.nodeName === 'PRE'\n };\n\n if (!element.firstChild || isPre(element)) return\n\n var prevText = null;\n var prevVoid = false;\n\n var prev = null;\n var node = next(prev, element, isPre);\n\n while (node !== element) {\n if (node.nodeType === 3 || node.nodeType === 4) { // Node.TEXT_NODE or Node.CDATA_SECTION_NODE\n var text = node.data.replace(/[ \\r\\n\\t]+/g, ' ');\n\n if ((!prevText || / $/.test(prevText.data)) &&\n !prevVoid && text[0] === ' ') {\n text = text.substr(1);\n }\n\n // `text` might be empty at this point.\n if (!text) {\n node = remove(node);\n continue\n }\n\n node.data = text;\n\n prevText = node;\n } else if (node.nodeType === 1) { // Node.ELEMENT_NODE\n if (isBlock(node) || node.nodeName === 'BR') {\n if (prevText) {\n prevText.data = prevText.data.replace(/ $/, '');\n }\n\n prevText = null;\n prevVoid = false;\n } else if (isVoid(node)) {\n // Avoid trimming space around non-block, non-BR void elements.\n prevText = null;\n prevVoid = true;\n }\n } else {\n node = remove(node);\n continue\n }\n\n var nextNode = next(prev, node, isPre);\n prev = node;\n node = nextNode;\n }\n\n if (prevText) {\n prevText.data = prevText.data.replace(/ $/, '');\n if (!prevText.data) {\n remove(prevText);\n }\n }\n}\n\n/**\n * remove(node) removes the given node from the DOM and returns the\n * next node in the sequence.\n *\n * @param {Node} node\n * @return {Node} node\n */\nfunction remove (node) {\n var next = node.nextSibling || node.parentNode;\n\n node.parentNode.removeChild(node);\n\n return next\n}\n\n/**\n * next(prev, current, isPre) returns the next node in the sequence, given the\n * current and previous nodes.\n *\n * @param {Node} prev\n * @param {Node} current\n * @param {Function} isPre\n * @return {Node}\n */\nfunction next (prev, current, isPre) {\n if ((prev && prev.parentNode === current) || isPre(current)) {\n return current.nextSibling || current.parentNode\n }\n\n return current.firstChild || current.nextSibling || current.parentNode\n}\n\n/*\n * Set up window for Node.js\n */\n\nvar root = (typeof window !== 'undefined' ? window : {});\n\n/*\n * Parsing HTML strings\n */\n\nfunction canParseHTMLNatively () {\n var Parser = root.DOMParser;\n var canParse = false;\n\n // Adapted from https://gist.github.com/1129031\n // Firefox/Opera/IE throw errors on unsupported types\n try {\n // WebKit returns null on unsupported types\n if (new Parser().parseFromString('', 'text/html')) {\n canParse = true;\n }\n } catch (e) {}\n\n return canParse\n}\n\nfunction createHTMLParser () {\n var Parser = function () {};\n\n {\n var JSDOM = require('jsdom').JSDOM;\n Parser.prototype.parseFromString = function (string) {\n return new JSDOM(string).window.document\n };\n }\n return Parser\n}\n\nvar HTMLParser = canParseHTMLNatively() ? root.DOMParser : createHTMLParser();\n\nfunction RootNode (input) {\n var root;\n if (typeof input === 'string') {\n var doc = htmlParser().parseFromString(\n // DOM parsers arrange elements in the <head> and <body>.\n // Wrapping in a custom element ensures elements are reliably arranged in\n // a single element.\n '<x-turndown id=\"turndown-root\">' + input + '</x-turndown>',\n 'text/html'\n );\n root = doc.getElementById('turndown-root');\n } else {\n root = input.cloneNode(true);\n }\n collapseWhitespace({\n element: root,\n isBlock: isBlock,\n isVoid: isVoid\n });\n\n return root\n}\n\nvar _htmlParser;\nfunction htmlParser () {\n _htmlParser = _htmlParser || new HTMLParser();\n return _htmlParser\n}\n\nfunction Node (node) {\n node.isBlock = isBlock(node);\n node.isCode = node.nodeName.toLowerCase() === 'code' || node.parentNode.isCode;\n node.isBlank = isBlank(node);\n node.flankingWhitespace = flankingWhitespace(node);\n return node\n}\n\nfunction isBlank (node) {\n return (\n ['A', 'TH', 'TD', 'IFRAME', 'SCRIPT', 'AUDIO', 'VIDEO'].indexOf(node.nodeName) === -1 &&\n /^\\s*$/i.test(node.textContent) &&\n !isVoid(node) &&\n !hasVoid(node)\n )\n}\n\nfunction flankingWhitespace (node) {\n var leading = '';\n var trailing = '';\n\n if (!node.isBlock) {\n var hasLeading = /^[ \\r\\n\\t]/.test(node.textContent);\n var hasTrailing = /[ \\r\\n\\t]$/.test(node.textContent);\n\n if (hasLeading && !isFlankedByWhitespace('left', node)) {\n leading = ' ';\n }\n if (hasTrailing && !isFlankedByWhitespace('right', node)) {\n trailing = ' ';\n }\n }\n\n return { leading: leading, trailing: trailing }\n}\n\nfunction isFlankedByWhitespace (side, node) {\n var sibling;\n var regExp;\n var isFlanked;\n\n if (side === 'left') {\n sibling = node.previousSibling;\n regExp = / $/;\n } else {\n sibling = node.nextSibling;\n regExp = /^ /;\n }\n\n if (sibling) {\n if (sibling.nodeType === 3) {\n isFlanked = regExp.test(sibling.nodeValue);\n } else if (sibling.nodeType === 1 && !isBlock(sibling)) {\n isFlanked = regExp.test(sibling.textContent);\n }\n }\n return isFlanked\n}\n\nvar reduce = Array.prototype.reduce;\nvar leadingNewLinesRegExp = /^\\n*/;\nvar trailingNewLinesRegExp = /\\n*$/;\nvar escapes = [\n [/\\\\/g, '\\\\\\\\'],\n [/\\*/g, '\\\\*'],\n [/^-/g, '\\\\-'],\n [/^\\+ /g, '\\\\+ '],\n [/^(=+)/g, '\\\\$1'],\n [/^(#{1,6}) /g, '\\\\$1 '],\n [/`/g, '\\\\`'],\n [/^~~~/g, '\\\\~~~'],\n [/\\[/g, '\\\\['],\n [/\\]/g, '\\\\]'],\n [/^>/g, '\\\\>'],\n [/_/g, '\\\\_'],\n [/^(\\d+)\\. /g, '$1\\\\. ']\n];\n\nfunction TurndownService (options) {\n if (!(this instanceof TurndownService)) return new TurndownService(options)\n\n var defaults = {\n rules: rules,\n headingStyle: 'setext',\n hr: '* * *',\n bulletListMarker: '*',\n codeBlockStyle: 'indented',\n fence: '```',\n emDelimiter: '_',\n strongDelimiter: '**',\n linkStyle: 'inlined',\n linkReferenceStyle: 'full',\n br: ' ',\n blankReplacement: function (content, node) {\n return node.isBlock ? '\\n\\n' : ''\n },\n keepReplacement: function (content, node) {\n return node.isBlock ? '\\n\\n' + node.outerHTML + '\\n\\n' : node.outerHTML\n },\n defaultReplacement: function (content, node) {\n return node.isBlock ? '\\n\\n' + content + '\\n\\n' : content\n }\n };\n this.options = extend({}, defaults, options);\n this.rules = new Rules(this.options);\n}\n\nTurndownService.prototype = {\n /**\n * The entry point for converting a string or DOM node to Markdown\n * @public\n * @param {String|HTMLElement} input The string or DOM node to convert\n * @returns A Markdown representation of the input\n * @type String\n */\n\n turndown: function (input) {\n if (!canConvert(input)) {\n throw new TypeError(\n input + ' is not a string, or an element/document/fragment node.'\n )\n }\n\n if (input === '') return ''\n\n var output = process.call(this, new RootNode(input));\n return postProcess.call(this, output)\n },\n\n /**\n * Add one or more plugins\n * @public\n * @param {Function|Array} plugin The plugin or array of plugins to add\n * @returns The Turndown instance for chaining\n * @type Object\n */\n\n use: function (plugin) {\n if (Array.isArray(plugin)) {\n for (var i = 0; i < plugin.length; i++) this.use(plugin[i]);\n } else if (typeof plugin === 'function') {\n plugin(this);\n } else {\n throw new TypeError('plugin must be a Function or an Array of Functions')\n }\n return this\n },\n\n /**\n * Adds a rule\n * @public\n * @param {String} key The unique key of the rule\n * @param {Object} rule The rule\n * @returns The Turndown instance for chaining\n * @type Object\n */\n\n addRule: function (key, rule) {\n this.rules.add(key, rule);\n return this\n },\n\n /**\n * Keep a node (as HTML) that matches the filter\n * @public\n * @param {String|Array|Function} filter The unique key of the rule\n * @returns The Turndown instance for chaining\n * @type Object\n */\n\n keep: function (filter) {\n this.rules.keep(filter);\n return this\n },\n\n /**\n * Remove a node that matches the filter\n * @public\n * @param {String|Array|Function} filter The unique key of the rule\n * @returns The Turndown instance for chaining\n * @type Object\n */\n\n remove: function (filter) {\n this.rules.remove(filter);\n return this\n },\n\n /**\n * Escapes Markdown syntax\n * @public\n * @param {String} string The string to escape\n * @returns A string with Markdown syntax escaped\n * @type String\n */\n\n escape: function (string) {\n return escapes.reduce(function (accumulator, escape) {\n return accumulator.replace(escape[0], escape[1])\n }, string)\n }\n};\n\n/**\n * Reduces a DOM node down to its Markdown string equivalent\n * @private\n * @param {HTMLElement} parentNode The node to convert\n * @returns A Markdown representation of the node\n * @type String\n */\n\nfunction process (parentNode) {\n var self = this;\n return reduce.call(parentNode.childNodes, function (output, node) {\n node = new Node(node);\n\n var replacement = '';\n if (node.nodeType === 3) {\n replacement = node.isCode ? node.nodeValue : self.escape(node.nodeValue);\n } else if (node.nodeType === 1) {\n replacement = replacementForNode.call(self, node);\n }\n\n return join(output, replacement)\n }, '')\n}\n\n/**\n * Appends strings as each rule requires and trims the output\n * @private\n * @param {String} output The conversion output\n * @returns A trimmed version of the ouput\n * @type String\n */\n\nfunction postProcess (output) {\n var self = this;\n this.rules.forEach(function (rule) {\n if (typeof rule.append === 'function') {\n output = join(output, rule.append(self.options));\n }\n });\n\n return output.replace(/^[\\t\\r\\n]+/, '').replace(/[\\t\\r\\n\\s]+$/, '')\n}\n\n/**\n * Converts an element node to its Markdown equivalent\n * @private\n * @param {HTMLElement} node The node to convert\n * @returns A Markdown representation of the node\n * @type String\n */\n\nfunction replacementForNode (node) {\n var rule = this.rules.forNode(node);\n var content = process.call(this, node);\n var whitespace = node.flankingWhitespace;\n if (whitespace.leading || whitespace.trailing) content = content.trim();\n return (\n whitespace.leading +\n rule.replacement(content, node, this.options) +\n whitespace.trailing\n )\n}\n\n/**\n * Determines the new lines between the current output and the replacement\n * @private\n * @param {String} output The current conversion output\n * @param {String} replacement The string to append to the output\n * @returns The whitespace to separate the current output and the replacement\n * @type String\n */\n\nfunction separatingNewlines (output, replacement) {\n var newlines = [\n output.match(trailingNewLinesRegExp)[0],\n replacement.match(leadingNewLinesRegExp)[0]\n ].sort();\n var maxNewlines = newlines[newlines.length - 1];\n return maxNewlines.length < 2 ? maxNewlines : '\\n\\n'\n}\n\nfunction join (string1, string2) {\n var separator = separatingNewlines(string1, string2);\n\n // Remove trailing/leading newlines and replace with separator\n string1 = string1.replace(trailingNewLinesRegExp, '');\n string2 = string2.replace(leadingNewLinesRegExp, '');\n\n return string1 + separator + string2\n}\n\n/**\n * Determines whether an input can be converted\n * @private\n * @param {String|HTMLElement} input Describe this parameter\n * @returns Describe what it returns\n * @type String|Object|Array|Boolean|Number\n */\n\nfunction canConvert (input) {\n return (\n input != null && (\n typeof input === 'string' ||\n (input.nodeType && (\n input.nodeType === 1 || input.nodeType === 9 || input.nodeType === 11\n ))\n )\n )\n}\n\nexport default TurndownService;\n","\n/**\n * Replace whitespace of text nodes within the given parents in the given root element.\n * @param {*} root An HTMLElement to look for text nodes within\n * @param {*} allowed_whitespace_nodes String array of allowed text nodes ( ['STRONG', 'EM'] ... )\n * @param {*} allowed_raw_nodes String array of allowed raw text nodes ( ['PRE', 'CODE'] ... )\n */\nexport function textNodesPreprocessor(root, allowed_whitespace_nodes, allowed_raw_nodes) {\n\tallowed_whitespace_nodes = allowed_whitespace_nodes.map(el => el.toUpperCase());\n\tallowed_raw_nodes = allowed_raw_nodes.map(el => el.toUpperCase());\n\n\tlet walker = document.createNodeIterator(\n\t\troot,\n\t\t// Only consider text nodes\n\t\tNodeFilter.SHOW_TEXT,\n\t );\n\n\tlet node;\n\twhile(node = walker.nextNode()) {\n\t\t// Strip NBSP whitespace in given nodes\n\t\tif ( node.parentElement && allowed_whitespace_nodes.indexOf(node.parentElement.nodeName) >= 0) {\n\t\tnode.nodeValue = node.nodeValue\n\t\t\t.replace(/^[\\u00a0]+/g, ' ')\n\t\t\t.replace(/[\\u00a0]+$/g, ' ');\n\t\t}\n\n\t\t// Re-encode < and > that would otherwise be output as HTML by turndown\n\t\t// https://github.com/domchristie/turndown/issues/106\n\t\tif (!hasParentOfType(node, allowed_raw_nodes)) {\n\t\t\tnode.nodeValue = _.escape(node.nodeValue);\n\t\t}\n\t}\n}\n\n/**\n * Replace links of A elements with their computed .href attribute\n * https://community.ooject.com/wp/29742\n * @param {} root\n * @param {*} allowed_whitespace_nodes\n * @param {*} allowed_raw_nodes\n */\nexport function linkPreprocessor(root, allowed_whitespace_nodes, allowed_raw_nodes) {\n\tlet walker = document.createNodeIterator(\n\t\troot,\n\t\t// Only consider element nodes\n\t\tNodeFilter.SHOW_ELEMENT,\n\t\t// Accept only A tags\n\t\tfunction(node) {\n\t\t\treturn node.nodeName.toLowerCase() === 'a' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;\n\t\t}\n\t );\n\n\tlet node;\n\twhile(node = walker.nextNode()) {\n\t\t// node.href is properly escaped, while the attribute is not\n\t\t// and turndown uses the getAttribute version\n\t\tnode.setAttribute('href', node.href);\n\t}\n}\n\n\nexport function hasParentOfType(node, tagNames) {\n\tlet parent = node.parentElement;\n\n\twhile (parent) {\n\t\tif (tagNames.indexOf(parent.tagName) >= 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tparent = parent.parentElement;\n\t}\n\n\treturn false;\n}\n","/**\n * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md.\n */\n\n/**\n * @module markdown-gfm/commonmarkdataprocessor\n */\n\n/* eslint-env browser */\n\nimport HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';\nimport DomConverter from '@ckeditor/ckeditor5-engine/src/view/domconverter';\nimport {highlightedCodeBlock, taskListItems} from 'turndown-plugin-gfm';\nimport TurndownService from 'turndown';\nimport {textNodesPreprocessor, linkPreprocessor} from './utils/preprocessor';\nimport {removeParagraphsInLists} from './utils/paragraph-in-lists';\n\nexport const originalSrcAttribute = 'data-original-src';\n\n/**\n * This data processor implementation uses CommonMark as input/output data.\n *\n * @implements module:engine/dataprocessor/dataprocessor~DataProcessor\n */\nexport default class CommonMarkDataProcessor {\n\tconstructor() {\n\t\tthis._htmlDP = new HtmlDataProcessor();\n\t\tthis._domConverter = new DomConverter();\n\t}\n\n\t/**\n\t * Converts the provided CommonMark string to view tree.\n\t *\n\t * @param {String} data A CommonMark string.\n\t * @returns {module:engine/view/documentfragment~DocumentFragment} The converted view element.\n\t */\n\ttoView( data ) {\n\t\tconst md = require( 'markdown-it' )( {\n\t\t\t// Output html\n\t\t\thtml: true,\n\t\t\t// Use GFM language fence prefix\n\t\t\tlangPrefix: 'language-',\n\t\t} );\n\n\t\t// Use tasklist plugin\n\t\tlet taskLists = require('markdown-it-task-lists');\n\t\tlet parser = md.use(taskLists, {label: true});\n\n\t\tconst html = parser.render( data );\n\n\t\t// Convert input HTML data to DOM DocumentFragment.\n\t\tconst domFragment = this._htmlDP._toDom( html );\n\n\t\t// Fix some CommonMark specifics\n\t\t// Paragraphs within list elements (https://community.openproject.com/work_packages/28765)\n\t\tremoveParagraphsInLists( domFragment );\n\n\t\t// Convert DOM DocumentFragment to view DocumentFragment.\n\t\treturn this._domConverter.domToView( domFragment );\n\t}\n\n\t/**\n\t * Converts the provided {@link module:engine/view/documentfragment~DocumentFragment} to data format &mdash; in this\n\t * case to a CommonMark string.\n\t *\n\t * @param {module:engine/view/documentfragment~DocumentFragment} viewFragment\n\t * @returns {String} CommonMark string.\n\t */\n\ttoData( viewFragment ) {\n\t\t// Convert view DocumentFragment to DOM DocumentFragment.\n\t\tconst domFragment = this._domConverter.viewToDom( viewFragment, document );\n\n\t\t// Replace leading and trailing nbsp at the end of strong and em tags\n\t\t// with single spaces\n\t\ttextNodesPreprocessor(\n\t\t\tdomFragment,\n\t\t\t['strong', 'em'],\n\t\t\t// Ensure tables are allowed to have HTML contents\n\t\t\t// OP#29457\n\t\t\t['pre', 'code', 'table']\n\t\t);\n\n\t\t// Replace link attributes with their computed href attribute\n\t\tlinkPreprocessor(domFragment);\n\n\t\t// Use Turndown to convert DOM fragment to markdown\n\t\tconst turndownService = new TurndownService( {\n\t\t\theadingStyle: 'atx',\n\t\t\tcodeBlockStyle: 'fenced'\n\t\t} );\n\n\t\tturndownService.use([\n\t\t\thighlightedCodeBlock,\n\t\t]);\n\n\t\t// Replace todolist with markdown representation\n\t\tturndownService.addRule('todolist', {\n\t\t\tfilter: function (node) {\n\t\t\t\t// check if we're a todo list item\n\t\t\t\treturn node.nodeName === 'LI' && node.closest('ul.todo-list');\n\t\t\t },\n\t\t\t replacement: function (content, node, options) {\n\t\t\t\tcontent = content\n\t\t\t\t\t.replace(/^\\n+/, '') // remove leading newlines\n\t\t\t\t\t.replace(/\\n+$/, '\\n') // replace trailing newlines with just a single one\n\t\t\t\t\t.replace(/\\n/gm, '\\n ') // indent\n\n\t\t\t\tvar prefix = options.bulletListMarker + ' ';\n\t\t\t\tvar input = node.querySelector('input[type=checkbox]');\n\t\t\t\tvar tasklist = (input && input.checked) ? '[x] ' : '[ ] ';\n\t\t\t\treturn prefix + tasklist + content + (node.nextSibling && !/\\n$/.test(content) ? '\\n' : '');\n\t\t\t }\n\t\t});\n\n\t\t// Replace images with appropriate source URLs derived from an attachment,\n\t\t// if any. Otherwise use the original src\n\t\tturndownService.addRule('img', {\n\t\t\tfilter: 'img',\n\n\t\t\treplacement: function (content, node) {\n\t\t\t var alt = node.alt || '';\n\t\t\t var src = node.getAttribute(originalSrcAttribute) || node.getAttribute('src') || '';\n\t\t\t var title = node.title || '';\n\t\t\t var titlePart = title ? ' \"' + title + '\"' : '';\n\n\t\t\t return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : '';\n\t\t\t}\n\t\t});\n\n\t\t// Keep HTML tables and remove filler elements\n\t\tturndownService.addRule('htmlTables', {\n\t\t\tfilter: ['table'],\n\t\t\treplacement: function (_content, node) {\n\t\t\t\t// Remove filler nodes\n\t\t\t\tnode.querySelectorAll('td br[data-cke-filler]')\n\t\t\t\t\t.forEach((node) => node.remove());\n\n\t\t\t\treturn node.outerHTML;\n\t\t\t}\n\t\t});\n\n\t\tturndownService.addRule('strikethrough', {\n\t\t\tfilter: ['del', 's', 'strike'],\n\t\t\treplacement: function (content) {\n\t\t\t return '~~' + content + '~~'\n\t\t\t}\n\t\t});\n\n\t\tturndownService.addRule( 'openProjectMacros', {\n\t\t\tfilter: [ 'macro' ],\n\t\t\treplacement: ( _content, node ) => {\n\t\t\t\tnode.innerHTML = '';\n\t\t\t\tvar outer = node.outerHTML;\n\t\t\t\treturn outer.replace(\"</macro>\", \"\\n</macro>\")\n\t\t\t}\n\t\t});\n\n\t\treturn turndownService.turndown( domFragment );\n\t}\n}\n","\n/**\n * Remove paragraphs within lists since they will be stripped by CKEditor\n * https://community.openproject.com/work_packages/28765\n */\nexport function removeParagraphsInLists(root) {\n\tlet walker = document.createNodeIterator(\n\t\troot,\n\t\t// Only consider element nodes\n\t\tNodeFilter.SHOW_ELEMENT,\n\t\t// Only except text nodes whose parent is one of parents\n\t\t { acceptNode: function(node) {\n\t\t\tif ( node.tagName === 'P' && node.parentElement && node.parentElement.tagName === 'LI') {\n\t\t\t return NodeFilter.FILTER_ACCEPT;\n\t\t\t}\n\t\t }\n\t\t},\n\t\tfalse\n\t );\n\n\tlet node;\n\twhile(node = walker.nextNode()) {\n\t\tnode.outerHTML = node.innerHTML;\n\t}\n}\n","export default \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n xmlns:dc=\\\"http://purl.org/dc/elements/1.1/\\\"\\n xmlns:cc=\\\"http://creativecommons.org/ns#\\\"\\n xmlns:rdf=\\\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\\\"\\n xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n xmlns:sodipodi=\\\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\\\"\\n xmlns:inkscape=\\\"http://www.inkscape.org/namespaces/inkscape\\\"\\n class=\\\"ck ck-icon ck-button__icon\\\"\\n viewBox=\\\"0 0 20 20\\\"\\n version=\\\"1.1\\\"\\n id=\\\"svg10\\\"\\n sodipodi:docname=\\\"source.svg\\\"\\n inkscape:version=\\\"0.92.3 (2405546, 2018-03-11)\\\">\\n <defs\\n id=\\\"defs14\\\" />\\n <sodipodi:namedview\\n pagecolor=\\\"#ffffff\\\"\\n bordercolor=\\\"#666666\\\"\\n borderopacity=\\\"1\\\"\\n objecttolerance=\\\"10\\\"\\n gridtolerance=\\\"10\\\"\\n guidetolerance=\\\"10\\\"\\n inkscape:pageopacity=\\\"0\\\"\\n inkscape:pageshadow=\\\"2\\\"\\n inkscape:window-width=\\\"640\\\"\\n inkscape:window-height=\\\"480\\\"\\n id=\\\"namedview12\\\"\\n showgrid=\\\"false\\\"\\n inkscape:zoom=\\\"33.37544\\\"\\n inkscape:cx=\\\"10.656564\\\"\\n inkscape:cy=\\\"13.670445\\\"\\n inkscape:current-layer=\\\"svg10\\\" />\\n <g\\n id=\\\"g8\\\"\\n style=\\\"fill:#000000;fill-rule:evenodd\\\"\\n transform=\\\"matrix(0.8751128,0,0,0.8751128,4.2423992,5.525391)\\\">\\n <g\\n id=\\\"g6\\\"\\n style=\\\"fill:#000000\\\">\\n <g\\n transform=\\\"translate(2,5.6)\\\"\\n id=\\\"g4\\\"\\n style=\\\"fill:#000000\\\">\\n <path\\n d=\\\"M 10.5,0.1 15.7,4 v 1.3 l -5.6,4 C 10,9.5 9.8,9.5 9.6,9.5 9.3,9.4 9,8.8 9,8.5 L 9.3,8.1 14,4.6 9.5,1.4 9.3,1.2 C 9.2,0.9 9.2,0.6 9.3,0.4 9.5,0.2 9.8,0 10.1,0 a 0.8,0.8 0 0 1 0.4,0.1 z M 5.3,0.1 0,4 v 1.3 l 5.6,4 C 5.7,9.5 5.9,9.5 6.1,9.5 6.4,9.4 6.8,8.8 6.7,8.5 6.7,8.4 6.7,8.2 6.5,8.1 L 1.5,4.6 6.2,1.4 6.4,1.2 C 6.5,0.9 6.5,0.6 6.4,0.4 6.2,0.2 5.9,0 5.6,0 A 0.8,0.8 0 0 0 5.3,0.1 Z\\\"\\n id=\\\"path2\\\"\\n inkscape:connector-curvature=\\\"0\\\"\\n style=\\\"fill:#000000\\\" />\\n </g>\\n </g>\\n </g>\\n <metadata\\n id=\\\"metadata4596\\\">\\n <rdf:RDF>\\n <cc:Work\\n rdf:about=\\\"\\\">\\n <dc:title></dc:title>\\n <dc:format>image/svg+xml</dc:format>\\n <dc:type\\n rdf:resource=\\\"http://purl.org/dc/dcmitype/StillImage\\\" />\\n </cc:Work>\\n </rdf:RDF>\\n </metadata>\\n <path\\n style=\\\"stroke-width:0.0390625\\\"\\n d=\\\"M 1.2772336,0.02277222 V 20.022772 H 6.2381712 V 18.225897 H 3.0741087 V 1.8196472 h 8.2031253 l 3.554687,3.59375 v 3.5546875 h 1.796875 V 4.6712097 L 12.019421,0.02277222 Z\\\"\\n id=\\\"path2-3\\\"\\n inkscape:connector-curvature=\\\"0\\\" />\\n</svg>\\n\"","export default \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"no\\\"?>\\n<svg\\n xmlns:dc=\\\"http://purl.org/dc/elements/1.1/\\\"\\n xmlns:cc=\\\"http://creativecommons.org/ns#\\\"\\n xmlns:rdf=\\\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\\\"\\n xmlns:svg=\\\"http://www.w3.org/2000/svg\\\"\\n xmlns=\\\"http://www.w3.org/2000/svg\\\"\\n xmlns:sodipodi=\\\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\\\"\\n xmlns:inkscape=\\\"http://www.inkscape.org/namespaces/inkscape\\\"\\n viewBox=\\\"0 0 512 512\\\"\\n version=\\\"1.1\\\"\\n id=\\\"svg4\\\"\\n sodipodi:docname=\\\"wysiwyg.svg\\\"\\n inkscape:version=\\\"0.92.3 (2405546, 2018-03-11)\\\">\\n <metadata\\n id=\\\"metadata10\\\">\\n <rdf:RDF>\\n <cc:Work\\n rdf:about=\\\"\\\">\\n <dc:format>image/svg+xml</dc:format>\\n <dc:type\\n rdf:resource=\\\"http://purl.org/dc/dcmitype/StillImage\\\" />\\n </cc:Work>\\n </rdf:RDF>\\n </metadata>\\n <defs\\n id=\\\"defs8\\\" />\\n <sodipodi:namedview\\n pagecolor=\\\"#ffffff\\\"\\n bordercolor=\\\"#666666\\\"\\n borderopacity=\\\"1\\\"\\n objecttolerance=\\\"10\\\"\\n gridtolerance=\\\"10\\\"\\n guidetolerance=\\\"10\\\"\\n inkscape:pageopacity=\\\"0\\\"\\n inkscape:pageshadow=\\\"2\\\"\\n inkscape:window-width=\\\"640\\\"\\n inkscape:window-height=\\\"480\\\"\\n id=\\\"namedview6\\\"\\n showgrid=\\\"false\\\"\\n inkscape:zoom=\\\"1.3037281\\\"\\n inkscape:cx=\\\"252.52639\\\"\\n inkscape:cy=\\\"155.86537\\\"\\n inkscape:current-layer=\\\"svg4\\\" />\\n <path\\n d=\\\"m 166.9714,230.61312 h 185 v 31 h -185 z m 1,-61 h 185 v 32 h -185 z m 0,-61 h 185 v 32 h -185 z m 289,5 -118,-118.0000009 H 63.971404 V 507.61312 H 457.9714 v -394 z m -347,348 V 41.613119 h 210 l 92,92.000001 v 328 z\\\"\\n id=\\\"path2\\\"\\n inkscape:connector-curvature=\\\"0\\\"\\n sodipodi:nodetypes=\\\"cccccccccccccccccccccccccccc\\\" />\\n <rect\\n style=\\\"fill:#000000;fill-opacity:1;stroke:#353535;stroke-opacity:1\\\"\\n id=\\\"rect832\\\"\\n width=\\\"184.08746\\\"\\n height=\\\"112.75357\\\"\\n x=\\\"169.51387\\\"\\n y=\\\"313.33896\\\" />\\n</svg>\\n\"","/**\n * @license Copyright (c) 2003-2019, 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 mention/mentioncommand\n */\n\nimport Command from '@ckeditor/ckeditor5-core/src/command';\nimport toMap from '@ckeditor/ckeditor5-utils/src/tomap';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport { _addMentionAttributes } from './mentionediting';\n\n/**\n * The mention command.\n *\n * The command is registered by {@link module:mention/mentionediting~MentionEditing} as `'mention'`.\n *\n * To insert a mention onto a range, execute the command and specify a mention object with a range to replace:\n *\n *\t\tconst focus = editor.model.document.selection.focus;\n *\n *\t\t// It will replace one character before the selection focus with the '#1234' text\n *\t\t// with the mention attribute filled with passed attributes.\n *\t\teditor.execute( 'mention', {\n *\t\t\tmarker: '#',\n *\t\t\tmention: {\n *\t\t\t\tid: '#1234',\n *\t\t\t\tname: 'Foo',\n *\t\t\t\ttitle: 'Big Foo'\n *\t\t\t},\n *\t\t\trange: model.createRange( focus, focus.getShiftedBy( -1 ) )\n *\t\t} );\n *\n *\t\t// It will replace one character before the selection focus with the 'The \"Big Foo\"' text\n *\t\t// with the mention attribute filled with passed attributes.\n *\t\teditor.execute( 'mention', {\n *\t\t\tmarker: '#',\n *\t\t\tmention: {\n *\t\t\t\tid: '#1234',\n *\t\t\t\tname: 'Foo',\n *\t\t\t\ttitle: 'Big Foo'\n *\t\t\t},\n *\t\t\ttext: 'The \"Big Foo\"',\n *\t\t\trange: model.createRange( focus, focus.getShiftedBy( -1 ) )\n *\t\t} );\n *\n * @extends module:core/command~Command\n */\nexport default class MentionCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tthis.isEnabled = model.schema.checkAttributeInSelection( doc.selection, 'mention' );\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @param {Object} [options] Options for the executed command.\n\t * @param {Object|String} options.mention The mention object to insert. When a string is passed, it will be used to create a plain\n\t * object with the name attribute that equals the passed string.\n\t * @param {String} options.marker The marker character (e.g. `'@'`).\n\t * @param {String} [options.text] The text of the inserted mention. Defaults to the full mention string composed from `marker` and\n\t * `mention` string or `mention.id` if an object is passed.\n\t * @param {String} [options.range] The range to replace. Note that the replaced range might be shorter than the inserted text with the\n\t * mention attribute.\n\t * @fires execute\n\t */\n\texecute( options ) {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\t\tconst selection = document.selection;\n\n\t\tconst mentionData = typeof options.mention == 'string' ? { id: options.mention } : options.mention;\n\t\tconst mentionID = mentionData.id;\n\n\t\tconst range = options.range || selection.getFirstRange();\n\n\t\tconst mentionText = options.text || mentionID;\n\n\t\tconst mention = _addMentionAttributes( { _text: mentionText, id: mentionID }, mentionData );\n\n\t\tif ( options.marker.length != 1 ) {\n\t\t\t/**\n\t\t\t * The marker must be a single character.\n\t\t\t *\n\t\t\t * Correct markers: `'@'`, `'#'`.\n\t\t\t *\n\t\t\t * Incorrect markers: `'$$'`, `'[@'`.\n\t\t\t *\n\t\t\t * See {@link module:mention/mention~MentionConfig}.\n\t\t\t *\n\t\t\t * @error mentioncommand-incorrect-marker\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'mentioncommand-incorrect-marker: The marker must be a single character.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tif ( mentionID.charAt( 0 ) != options.marker ) {\n\t\t\t/**\n\t\t\t * The feed item ID must start with the marker character.\n\t\t\t *\n\t\t\t * Correct mention feed setting:\n\t\t\t *\n\t\t\t *\t\tmentions: [\n\t\t\t *\t\t\t{\n\t\t\t *\t\t\t\tmarker: '@',\n\t\t\t *\t\t\t\tfeed: [ '@Ann', '@Barney', ... ]\n\t\t\t *\t\t\t}\n\t\t\t *\t\t]\n\t\t\t *\n\t\t\t * Incorrect mention feed setting:\n\t\t\t *\n\t\t\t *\t\tmentions: [\n\t\t\t *\t\t\t{\n\t\t\t *\t\t\t\tmarker: '@',\n\t\t\t *\t\t\t\tfeed: [ 'Ann', 'Barney', ... ]\n\t\t\t *\t\t\t}\n\t\t\t *\t\t]\n\t\t\t *\n\t\t\t * See {@link module:mention/mention~MentionConfig}.\n\t\t\t *\n\t\t\t * @error mentioncommand-incorrect-id\n\t\t\t */\n\t\t\tthrow new CKEditorError(\n\t\t\t\t'mentioncommand-incorrect-id: The item id must start with the marker character.',\n\t\t\t\tthis\n\t\t\t);\n\t\t}\n\n\t\tmodel.change( writer => {\n\t\t\tconst currentAttributes = toMap( selection.getAttributes() );\n\t\t\tconst attributesWithMention = new Map( currentAttributes.entries() );\n\n\t\t\tattributesWithMention.set( 'mention', mention );\n\n\t\t\t// Replace a range with the text with a mention.\n\t\t\tmodel.insertContent( writer.createText( mentionText, attributesWithMention ), range );\n\t\t\tmodel.insertContent( writer.createText( ' ', currentAttributes ), range.start.getShiftedBy( mentionText.length ) );\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 mention/mentionediting\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport uid from '@ckeditor/ckeditor5-utils/src/uid';\n\nimport MentionCommand from './mentioncommand';\n\n/**\n * The mention editing feature.\n *\n * It introduces the {@link module:mention/mentioncommand~MentionCommand command} and the `mention`\n * attribute in the {@link module:engine/model/model~Model model} which renders in the {@link module:engine/view/view view}\n * as a `<span class=\"mention\" data-mention=\"@mention\">`.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class MentionEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'MentionEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst doc = model.document;\n\n\t\t// Allow the mention attribute on all text nodes.\n\t\tmodel.schema.extend( '$text', { allowAttributes: 'mention' } );\n\n\t\t// Upcast conversion.\n\t\teditor.conversion.for( 'upcast' ).elementToAttribute( {\n\t\t\tview: {\n\t\t\t\tname: 'span',\n\t\t\t\tkey: 'data-mention',\n\t\t\t\tclasses: 'mention'\n\t\t\t},\n\t\t\tmodel: {\n\t\t\t\tkey: 'mention',\n\t\t\t\tvalue: _toMentionAttribute\n\t\t\t}\n\t\t} );\n\n\t\t// Downcast conversion.\n\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t\t\tmodel: 'mention',\n\t\t\tview: createViewMentionElement\n\t\t} );\n\t\teditor.conversion.for( 'downcast' ).add( preventPartialMentionDowncast );\n\n\t\tdoc.registerPostFixer( writer => removePartialMentionPostFixer( writer, doc, model.schema ) );\n\t\tdoc.registerPostFixer( writer => extendAttributeOnMentionPostFixer( writer, doc ) );\n\t\tdoc.registerPostFixer( writer => selectionMentionAttributePostFixer( writer, doc ) );\n\n\t\teditor.commands.add( 'mention', new MentionCommand( editor ) );\n\t}\n}\n\nexport function _addMentionAttributes( baseMentionData, data ) {\n\treturn Object.assign( { _uid: uid() }, baseMentionData, data || {} );\n}\n\n/**\n * Creates a mention attribute value from the provided view element and optional data.\n *\n * This function is exposed as\n * {@link module:mention/mention~Mention#toMentionAttribute `editor.plugins.get( 'Mention' ).toMentionAttribute()`}.\n *\n * @protected\n * @param {module:engine/view/element~Element} viewElementOrMention\n * @param {String|Object} [data] Mention data to be extended.\n * @return {module:mention/mention~MentionAttribute}\n */\nexport function _toMentionAttribute( viewElementOrMention, data ) {\n\tconst dataMention = viewElementOrMention.getAttribute( 'data-mention' );\n\n\tconst textNode = viewElementOrMention.getChild( 0 );\n\n\t// Do not convert empty mentions.\n\tif ( !textNode ) {\n\t\treturn;\n\t}\n\n\tconst baseMentionData = {\n\t\tid: dataMention,\n\t\t_text: textNode.data\n\t};\n\n\treturn _addMentionAttributes( baseMentionData, data );\n}\n\n// A converter that blocks partial mention from being converted.\n//\n// This converter is registered with 'highest' priority in order to consume mention attribute before it is converted by\n// any other converters. This converter only consumes partial mention - those whose `_text` attribute is not equal to text with mention\n// attribute. This may happen when copying part of mention text.\n//\n// @param {module:engine/conversion/dwoncastdispatcher~DowncastDispatcher}\nfunction preventPartialMentionDowncast( dispatcher ) {\n\tdispatcher.on( 'attribute:mention', ( evt, data, conversionApi ) => {\n\t\tconst mention = data.attributeNewValue;\n\n\t\tif ( !data.item.is( 'textProxy' ) || !mention ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst start = data.range.start;\n\t\tconst textNode = start.textNode || start.nodeAfter;\n\n\t\tif ( textNode.data != mention._text ) {\n\t\t\t// Consume item to prevent partial mention conversion.\n\t\t\tconversionApi.consumable.consume( data.item, evt.name );\n\t\t}\n\t}, { priority: 'highest' } );\n}\n\n// Creates a mention element from the mention data.\n//\n// @param {Object} mention\n// @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter\n// @returns {module:engine/view/attributeelement~AttributeElement}\nfunction createViewMentionElement( mention, viewWriter ) {\n\tif ( !mention ) {\n\t\treturn;\n\t}\n\n\tconst attributes = {\n\t\tclass: 'mention',\n\t\t'data-mention': mention.id\n\t};\n\n\tconst options = {\n\t\tid: mention._uid,\n\t\tpriority: 20\n\t};\n\n\treturn viewWriter.createAttributeElement( 'span', attributes, options );\n}\n\n// Model post-fixer that disallows typing with selection when the selection is placed after the text node with the mention attribute or\n// before a text node with mention attribute.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/document~Document} doc\n// @returns {Boolean} Returns `true` if the selection was fixed.\nfunction selectionMentionAttributePostFixer( writer, doc ) {\n\tconst selection = doc.selection;\n\tconst focus = selection.focus;\n\n\tif ( selection.isCollapsed && selection.hasAttribute( 'mention' ) && shouldNotTypeWithMentionAt( focus ) ) {\n\t\twriter.removeSelectionAttribute( 'mention' );\n\n\t\treturn true;\n\t}\n}\n\n// Helper function to detect if mention attribute should be removed from selection.\n// This check makes only sense if the selection has mention attribute.\n//\n// The mention attribute should be removed from a selection when selection focus is placed:\n// a) after a text node\n// b) the position is at parents start - the selection will set attributes from node after.\nfunction shouldNotTypeWithMentionAt( position ) {\n\tconst isAtStart = position.isAtStart;\n\tconst isAfterAMention = position.nodeBefore && position.nodeBefore.is( 'text' );\n\n\treturn isAfterAMention || isAtStart;\n}\n\n// Model post-fixer that removes the mention attribute from the modified text node.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/document~Document} doc\n// @returns {Boolean} Returns `true` if the selection was fixed.\nfunction removePartialMentionPostFixer( writer, doc, schema ) {\n\tconst changes = doc.differ.getChanges();\n\n\tlet wasChanged = false;\n\n\tfor ( const change of changes ) {\n\t\t// Checks the text node on the current position.\n\t\tconst position = change.position;\n\n\t\tif ( change.name == '$text' ) {\n\t\t\tconst nodeAfterInsertedTextNode = position.textNode && position.textNode.nextSibling;\n\n\t\t\t// Checks the text node where the change occurred.\n\t\t\twasChanged = checkAndFix( position.textNode, writer ) || wasChanged;\n\n\t\t\t// Occurs on paste inside a text node with mention.\n\t\t\twasChanged = checkAndFix( nodeAfterInsertedTextNode, writer ) || wasChanged;\n\t\t\twasChanged = checkAndFix( position.nodeBefore, writer ) || wasChanged;\n\t\t\twasChanged = checkAndFix( position.nodeAfter, writer ) || wasChanged;\n\t\t}\n\n\t\t// Checks text nodes in inserted elements (might occur when splitting a paragraph or pasting content inside text with mention).\n\t\tif ( change.name != '$text' && change.type == 'insert' ) {\n\t\t\tconst insertedNode = position.nodeAfter;\n\n\t\t\tfor ( const item of writer.createRangeIn( insertedNode ).getItems() ) {\n\t\t\t\twasChanged = checkAndFix( item, writer ) || wasChanged;\n\t\t\t}\n\t\t}\n\n\t\t// Inserted inline elements might break mention.\n\t\tif ( change.type == 'insert' && schema.isInline( change.name ) ) {\n\t\t\tconst nodeAfterInserted = position.nodeAfter && position.nodeAfter.nextSibling;\n\n\t\t\twasChanged = checkAndFix( position.nodeBefore, writer ) || wasChanged;\n\t\t\twasChanged = checkAndFix( nodeAfterInserted, writer ) || wasChanged;\n\t\t}\n\t}\n\n\treturn wasChanged;\n}\n\n// This post-fixer will extend the attribute applied on the part of the mention so the whole text node of the mention will have\n// the added attribute.\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:engine/model/document~Document} doc\n// @returns {Boolean} Returns `true` if the selection was fixed.\nfunction extendAttributeOnMentionPostFixer( writer, doc ) {\n\tconst changes = doc.differ.getChanges();\n\n\tlet wasChanged = false;\n\n\tfor ( const change of changes ) {\n\t\tif ( change.type === 'attribute' && change.attributeKey != 'mention' ) {\n\t\t\t// Checks the node on the left side of the range...\n\t\t\tconst nodeBefore = change.range.start.nodeBefore;\n\t\t\t// ... and on the right side of the range.\n\t\t\tconst nodeAfter = change.range.end.nodeAfter;\n\n\t\t\tfor ( const node of [ nodeBefore, nodeAfter ] ) {\n\t\t\t\tif ( isBrokenMentionNode( node ) && node.getAttribute( change.attributeKey ) != change.attributeNewValue ) {\n\t\t\t\t\twriter.setAttribute( change.attributeKey, change.attributeNewValue, node );\n\n\t\t\t\t\twasChanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn wasChanged;\n}\n\n// Checks if a node has a correct mention attribute if present.\n// Returns `true` if the node is text and has a mention attribute whose text does not match the expected mention text.\n//\n// @param {module:engine/model/node~Node} node The node to check.\n// @returns {Boolean}\nfunction isBrokenMentionNode( node ) {\n\tif ( !node || !( node.is( 'text' ) || node.is( 'textProxy' ) ) || !node.hasAttribute( 'mention' ) ) {\n\t\treturn false;\n\t}\n\n\tconst text = node.data;\n\tconst mention = node.getAttribute( 'mention' );\n\n\tconst expectedText = mention._text;\n\n\treturn text != expectedText;\n}\n\n// Fixes a mention on a text node if it needs a fix.\n//\n// @param {module:engine/model/text~Text} textNode\n// @param {module:engine/model/writer~Writer} writer\n// @returns {Boolean}\nfunction checkAndFix( textNode, writer ) {\n\tif ( isBrokenMentionNode( textNode ) ) {\n\t\twriter.removeAttribute( 'mention', textNode );\n\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 typing/textwatcher\n */\n\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport getLastTextLine from './utils/getlasttextline';\n\n/**\n * The text watcher feature.\n *\n * Fires the {@link module:typing/textwatcher~TextWatcher#event:matched:data `matched:data`},\n * {@link module:typing/textwatcher~TextWatcher#event:matched:selection `matched:selection`} and\n * {@link module:typing/textwatcher~TextWatcher#event:unmatched `unmatched`} events on typing or selection changes.\n *\n * @private\n */\nexport default class TextWatcher {\n\t/**\n\t * Creates a text watcher instance.\n\t * @param {module:engine/model/model~Model} model\n\t * @param {Function} testCallback The function used to match the text.\n\t */\n\tconstructor( model, testCallback ) {\n\t\tthis.model = model;\n\t\tthis.testCallback = testCallback;\n\t\tthis.hasMatch = false;\n\n\t\tthis._startListening();\n\t}\n\n\t/**\n\t * Starts listening to the editor for typing and selection events.\n\t *\n\t * @private\n\t */\n\t_startListening() {\n\t\tconst model = this.model;\n\t\tconst document = model.document;\n\n\t\tdocument.selection.on( 'change:range', ( evt, { directChange } ) => {\n\t\t\t// Indirect changes (i.e. when the user types or external changes are applied) are handled in the document's change event.\n\t\t\tif ( !directChange ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Act only on collapsed selection.\n\t\t\tif ( !document.selection.isCollapsed ) {\n\t\t\t\tif ( this.hasMatch ) {\n\t\t\t\t\tthis.fire( 'unmatched' );\n\t\t\t\t\tthis.hasMatch = false;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._evaluateTextBeforeSelection( 'selection' );\n\t\t} );\n\n\t\tdocument.on( 'change:data', ( evt, batch ) => {\n\t\t\tif ( batch.type == 'transparent' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._evaluateTextBeforeSelection( 'data', { batch } );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks the editor content for matched text.\n\t *\n\t * @fires matched:data\n\t * @fires matched:selection\n\t * @fires unmatched\n\t *\n\t * @private\n\t * @param {'data'|'selection'} suffix A suffix used for generating the event name.\n\t * @param {Object} data Data object for event.\n\t */\n\t_evaluateTextBeforeSelection( suffix, data = {} ) {\n\t\tconst model = this.model;\n\t\tconst document = model.document;\n\t\tconst selection = document.selection;\n\n\t\tconst rangeBeforeSelection = model.createRange( model.createPositionAt( selection.focus.parent, 0 ), selection.focus );\n\n\t\tconst { text, range } = getLastTextLine( rangeBeforeSelection, model );\n\n\t\tconst textHasMatch = this.testCallback( text );\n\n\t\tif ( !textHasMatch && this.hasMatch ) {\n\t\t\t/**\n\t\t\t * Fired whenever the text does not match anymore. Fired only when the text watcher found a match.\n\t\t\t *\n\t\t\t * @event unmatched\n\t\t\t */\n\t\t\tthis.fire( 'unmatched' );\n\t\t}\n\n\t\tthis.hasMatch = textHasMatch;\n\n\t\tif ( textHasMatch ) {\n\t\t\tconst eventData = Object.assign( data, { text, range } );\n\n\t\t\t/**\n\t\t\t * Fired whenever the text watcher found a match for data changes.\n\t\t\t *\n\t\t\t * @event matched:data\n\t\t\t * @param {Object} data Event data.\n\t\t\t * @param {String} data.text The full text before selection.\n\t\t\t * @param {module:engine/model/batch~Batch} data.batch A batch associated with a change.\n\t\t\t */\n\t\t\t/**\n\t\t\t * Fired whenever the text watcher found a match for selection changes.\n\t\t\t *\n\t\t\t * @event matched:selection\n\t\t\t * @param {Object} data Event data.\n\t\t\t * @param {String} data.text The full text before selection.\n\t\t\t */\n\t\t\tthis.fire( `matched:${ suffix }`, eventData );\n\t\t}\n\t}\n}\n\nmix( TextWatcher, EmitterMixin );\n\n","/**\n * @license Copyright (c) 2003-2019, 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 mention/ui/mentionsview\n */\n\nimport ListView from '@ckeditor/ckeditor5-ui/src/list/listview';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\n\nimport '../../theme/mentionui.css';\n\n/**\n * The mention ui view.\n *\n * @extends module:ui/list/listview~ListView\n */\nexport default class MentionsView extends ListView {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tthis.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck-mentions'\n\t\t\t\t],\n\n\t\t\t\ttabindex: '-1'\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * {@link #select Selects} the first item.\n\t */\n\tselectFirst() {\n\t\tthis.select( 0 );\n\t}\n\n\t/**\n\t * Selects next item to the currently {@link #select selected}.\n\t *\n\t * If the last item is already selected, it will select the first item.\n\t */\n\tselectNext() {\n\t\tconst item = this.selected;\n\t\tconst index = this.items.getIndex( item );\n\n\t\tthis.select( index + 1 );\n\t}\n\n\t/**\n\t * Selects previous item to the currently {@link #select selected}.\n\t *\n\t * If the first item is already selected, it will select the last item.\n\t */\n\tselectPrevious() {\n\t\tconst item = this.selected;\n\t\tconst index = this.items.getIndex( item );\n\n\t\tthis.select( index - 1 );\n\t}\n\n\t/**\n\t * Marks item at a given index as selected.\n\t *\n\t * Handles selection cycling when passed index is out of bounds:\n\t * - if the index is lower than 0, it will select the last item,\n\t * - if the index is higher than the last item index, it will select the first item.\n\t *\n\t * @param {Number} index Index of an item to be marked as selected.\n\t */\n\tselect( index ) {\n\t\tlet indexToGet = 0;\n\n\t\tif ( index > 0 && index < this.items.length ) {\n\t\t\tindexToGet = index;\n\t\t} else if ( index < 0 ) {\n\t\t\tindexToGet = this.items.length - 1;\n\t\t}\n\n\t\tconst item = this.items.get( indexToGet );\n\n\t\t// Return early if item is already selected.\n\t\tif ( this.selected === item ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove highlight of previously selected item.\n\t\tif ( this.selected ) {\n\t\t\tthis.selected.removeHighlight();\n\t\t}\n\n\t\titem.highlight();\n\t\tthis.selected = item;\n\n\t\t// Scroll the mentions view to the selected element.\n\t\tif ( !this._isItemVisibleInScrolledArea( item ) ) {\n\t\t\tthis.element.scrollTop = item.element.offsetTop;\n\t\t}\n\t}\n\n\t/**\n\t * Triggers the `execute` event on the {@link #select selected} item.\n\t */\n\texecuteSelected() {\n\t\tthis.selected.fire( 'execute' );\n\t}\n\n\t// Checks if an item is visible in the scrollable area.\n\t//\n\t// The item is considered visible when:\n\t// - its top boundary is inside the scrollable rect\n\t// - its bottom boundary is inside the scrollable rect (the whole item must be visible)\n\t_isItemVisibleInScrolledArea( item ) {\n\t\treturn new Rect( this.element ).contains( new Rect( item.element ) );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 mention/ui/domwrapperview\n */\n\nimport View from '@ckeditor/ckeditor5-ui/src/view';\n\n/**\n * This class wraps DOM element as a CKEditor5 UI View.\n *\n * It allows to render any DOM element and use it in mentions list.\n */\nexport default class DomWrapperView extends View {\n\t/**\n\t * Creates an instance of {@link module:mention/ui/domwrapperview~DomWrapperView} class.\n\t *\n\t * Also see {@link #render}.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The localization services instance.\n\t * @param {Element} domElement\n\t */\n\tconstructor( locale, domElement ) {\n\t\tsuper( locale );\n\n\t\t// Disable template rendering on this view.\n\t\tthis.template = false;\n\n\t\t/**\n\t\t * The DOM element for which wrapper was created.\n\t\t *\n\t\t * @type {Element}\n\t\t */\n\t\tthis.domElement = domElement;\n\n\t\t// Render dom wrapper as a button.\n\t\tthis.domElement.classList.add( 'ck-button' );\n\n\t\t/**\n\t\t * Controls whether the dom wrapper view is \"on\". This is in line with {@link module:ui/button/button~Button#isOn} property.\n\t\t *\n\t\t * @observable\n\t\t * @default true\n\t\t * @member {Boolean} #isOn\n\t\t */\n\t\tthis.set( 'isOn', false );\n\n\t\t// Handle isOn state as in buttons.\n\t\tthis.on( 'change:isOn', ( evt, name, isOn ) => {\n\t\t\tif ( isOn ) {\n\t\t\t\tthis.domElement.classList.add( 'ck-on' );\n\t\t\t\tthis.domElement.classList.remove( 'ck-off' );\n\t\t\t} else {\n\t\t\t\tthis.domElement.classList.add( 'ck-off' );\n\t\t\t\tthis.domElement.classList.remove( 'ck-on' );\n\t\t\t}\n\t\t} );\n\n\t\t// Pass click event as execute event.\n\t\tthis.listenTo( this.domElement, 'click', () => {\n\t\t\tthis.fire( 'execute' );\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tthis.element = this.domElement;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 mention/ui/mentionlistitemview\n */\n\nimport ListItemView from '@ckeditor/ckeditor5-ui/src/list/listitemview';\n\nexport default class MentionListItemView extends ListItemView {\n\thighlight() {\n\t\tconst child = this.children.first;\n\n\t\tchild.isOn = true;\n\t}\n\n\tremoveHighlight() {\n\t\tconst child = this.children.first;\n\n\t\tchild.isOn = false;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 mention/mentionui\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler';\nimport { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\n\nimport TextWatcher from '@ckeditor/ckeditor5-typing/src/textwatcher';\n\nimport MentionsView from './ui/mentionsview';\nimport DomWrapperView from './ui/domwrapperview';\nimport MentionListItemView from './ui/mentionlistitemview';\n\nconst VERTICAL_SPACING = 3;\n\n/**\n * The mention UI feature.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class MentionUI extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'MentionUI';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The mention view.\n\t\t *\n\t\t * @type {module:mention/ui/mentionsview~MentionsView}\n\t\t * @private\n\t\t */\n\t\tthis._mentionsView = this._createMentionView();\n\n\t\t/**\n\t\t * Stores mention feeds configurations.\n\t\t *\n\t\t * @type {Map<String, Object>}\n\t\t * @private\n\t\t */\n\t\tthis._mentionsConfigurations = new Map();\n\n\t\teditor.config.define( 'mention', { feeds: [] } );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t/**\n\t\t * The contextual balloon plugin instance.\n\t\t *\n\t\t * @private\n\t\t * @member {module:ui/panel/balloon/contextualballoon~ContextualBalloon}\n\t\t */\n\t\tthis._balloon = editor.plugins.get( ContextualBalloon );\n\n\t\t// Key listener that handles navigation in mention view.\n\t\teditor.editing.view.document.on( 'keydown', ( evt, data ) => {\n\t\t\tif ( isHandledKey( data.keyCode ) && this._isUIVisible ) {\n\t\t\t\tdata.preventDefault();\n\t\t\t\tevt.stop(); // Required for Enter key overriding.\n\n\t\t\t\tif ( data.keyCode == keyCodes.arrowdown ) {\n\t\t\t\t\tthis._mentionsView.selectNext();\n\t\t\t\t}\n\n\t\t\t\tif ( data.keyCode == keyCodes.arrowup ) {\n\t\t\t\t\tthis._mentionsView.selectPrevious();\n\t\t\t\t}\n\n\t\t\t\tif ( data.keyCode == keyCodes.enter || data.keyCode == keyCodes.tab || data.keyCode == keyCodes.space ) {\n\t\t\t\t\tthis._mentionsView.executeSelected();\n\t\t\t\t}\n\n\t\t\t\tif ( data.keyCode == keyCodes.esc ) {\n\t\t\t\t\tthis._hideUIAndRemoveMarker();\n\t\t\t\t}\n\t\t\t}\n\t\t}, { priority: 'highest' } ); // Required to override the Enter key.\n\n\t\t// Close the dropdown upon clicking outside of the plugin UI.\n\t\tclickOutsideHandler( {\n\t\t\temitter: this._mentionsView,\n\t\t\tactivator: () => this._isUIVisible,\n\t\t\tcontextElements: [ this._balloon.view.element ],\n\t\t\tcallback: () => this._hideUIAndRemoveMarker()\n\t\t} );\n\n\t\tconst feeds = editor.config.get( 'mention.feeds' );\n\n\t\tfor ( const mentionDescription of feeds ) {\n\t\t\tconst feed = mentionDescription.feed;\n\n\t\t\tconst marker = mentionDescription.marker;\n\n\t\t\tif ( !marker || marker.length != 1 ) {\n\t\t\t\t/**\n\t\t\t\t * The marker must be a single character.\n\t\t\t\t *\n\t\t\t\t * Correct markers: `'@'`, `'#'`.\n\t\t\t\t *\n\t\t\t\t * Incorrect markers: `'$$'`, `'[@'`.\n\t\t\t\t *\n\t\t\t\t * See {@link module:mention/mention~MentionConfig}.\n\t\t\t\t *\n\t\t\t\t * @error mentionconfig-incorrect-marker\n\t\t\t\t */\n\t\t\t\tthrow new CKEditorError(\n\t\t\t\t\t'mentionconfig-incorrect-marker: The marker must be provided and it must be a single character.',\n\t\t\t\t\tnull\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst minimumCharacters = mentionDescription.minimumCharacters || 0;\n\t\t\tconst feedCallback = typeof feed == 'function' ? feed.bind( this.editor ) : createFeedCallback( feed );\n\t\t\tconst watcher = this._setupTextWatcherForFeed( marker, minimumCharacters );\n\t\t\tconst itemRenderer = mentionDescription.itemRenderer;\n\n\t\t\tconst definition = { watcher, marker, feedCallback, itemRenderer };\n\n\t\t\tthis._mentionsConfigurations.set( marker, definition );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\t// Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).\n\t\tthis._mentionsView.destroy();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ContextualBalloon ];\n\t}\n\n\t/**\n\t * Returns true when {@link #_mentionsView} is in the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon} and it is\n\t * currently visible.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _isUIVisible() {\n\t\treturn this._balloon.visibleView === this._mentionsView;\n\t}\n\n\t/**\n\t * Creates the {@link #_mentionsView}.\n\t *\n\t * @private\n\t * @returns {module:mention/ui/mentionsview~MentionsView}\n\t */\n\t_createMentionView() {\n\t\tconst locale = this.editor.locale;\n\n\t\tconst mentionsView = new MentionsView( locale );\n\n\t\tthis._items = new Collection();\n\n\t\tmentionsView.items.bindTo( this._items ).using( data => {\n\t\t\tconst { item, marker } = data;\n\n\t\t\tconst listItemView = new MentionListItemView( locale );\n\n\t\t\tconst view = this._renderItem( item, marker );\n\t\t\tview.delegate( 'execute' ).to( listItemView );\n\n\t\t\tlistItemView.children.add( view );\n\t\t\tlistItemView.item = item;\n\t\t\tlistItemView.marker = marker;\n\n\t\t\tlistItemView.on( 'execute', () => {\n\t\t\t\tmentionsView.fire( 'execute', {\n\t\t\t\t\titem,\n\t\t\t\t\tmarker\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\treturn listItemView;\n\t\t} );\n\n\t\tmentionsView.on( 'execute', ( evt, data ) => {\n\t\t\tconst editor = this.editor;\n\t\t\tconst model = editor.model;\n\n\t\t\tconst item = data.item;\n\t\t\tconst marker = data.marker;\n\n\t\t\tconst mentionMarker = editor.model.markers.get( 'mention' );\n\n\t\t\t// Create a range on matched text.\n\t\t\tconst end = model.createPositionAt( model.document.selection.focus );\n\t\t\tconst start = model.createPositionAt( mentionMarker.getStart() );\n\t\t\tconst range = model.createRange( start, end );\n\n\t\t\tthis._hideUIAndRemoveMarker();\n\n\t\t\teditor.execute( 'mention', {\n\t\t\t\tmention: item,\n\t\t\t\ttext: item.text,\n\t\t\t\tmarker,\n\t\t\t\trange\n\t\t\t} );\n\n\t\t\teditor.editing.view.focus();\n\t\t} );\n\n\t\treturn mentionsView;\n\t}\n\n\t/**\n\t * Returns item renderer for the marker.\n\t *\n\t * @private\n\t * @param {String} marker\n\t * @returns {Function|null}\n\t */\n\t_getItemRenderer( marker ) {\n\t\tconst { itemRenderer } = this._mentionsConfigurations.get( marker );\n\n\t\treturn itemRenderer;\n\t}\n\n\t/**\n\t * Returns a promise that resolves with autocomplete items for a given text.\n\t *\n\t * @param {String} marker\n\t * @param {String} feedText\n\t * @return {Promise<module:mention/mention~MentionFeedItem>}\n\t * @private\n\t */\n\t_getFeed( marker, feedText ) {\n\t\tconst { feedCallback } = this._mentionsConfigurations.get( marker );\n\n\t\treturn Promise.resolve().then( () => feedCallback( feedText ) );\n\t}\n\n\t/**\n\t * Registers a text watcher for the marker.\n\t *\n\t * @private\n\t * @param {String} marker\n\t * @param {Number} minimumCharacters\n\t * @returns {module:typing/textwatcher~TextWatcher}\n\t */\n\t_setupTextWatcherForFeed( marker, minimumCharacters ) {\n\t\tconst editor = this.editor;\n\n\t\tconst watcher = new TextWatcher( editor.model, createTestCallback( marker, minimumCharacters ) );\n\n\t\twatcher.on( 'matched', ( evt, data ) => {\n\t\t\tconst selection = editor.model.document.selection;\n\t\t\tconst focus = selection.focus;\n\n\t\t\t// The text watcher listens only to changed range in selection - so the selection attributes are not yet available\n\t\t\t// and you cannot use selection.hasAttribute( 'mention' ) just yet.\n\t\t\t// See https://github.com/ckeditor/ckeditor5-engine/issues/1723.\n\t\t\tconst hasMention = focus.textNode && focus.textNode.hasAttribute( 'mention' );\n\n\t\t\tconst nodeBefore = focus.nodeBefore;\n\n\t\t\tif ( hasMention || nodeBefore && nodeBefore.is( 'text' ) && nodeBefore.hasAttribute( 'mention' ) ) {\n\t\t\t\tthis._hideUIAndRemoveMarker();\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst feedText = getFeedText( marker, data.text );\n\t\t\tconst matchedTextLength = marker.length + feedText.length;\n\n\t\t\t// Create a marker range.\n\t\t\tconst start = focus.getShiftedBy( -matchedTextLength );\n\t\t\tconst end = focus.getShiftedBy( -feedText.length );\n\n\t\t\tconst markerRange = editor.model.createRange( start, end );\n\n\t\t\tlet mentionMarker;\n\n\t\t\tif ( editor.model.markers.has( 'mention' ) ) {\n\t\t\t\tmentionMarker = editor.model.markers.get( 'mention' );\n\t\t\t} else {\n\t\t\t\tmentionMarker = editor.model.change( writer => writer.addMarker( 'mention', {\n\t\t\t\t\trange: markerRange,\n\t\t\t\t\tusingOperation: false,\n\t\t\t\t\taffectsData: false\n\t\t\t\t} ) );\n\t\t\t}\n\n\t\t\tthis._getFeed( marker, feedText )\n\t\t\t\t.then( feed => {\n\t\t\t\t\tthis._items.clear();\n\n\t\t\t\t\tfor ( const feedItem of feed ) {\n\t\t\t\t\t\tconst item = typeof feedItem != 'object' ? { id: feedItem, text: feedItem } : feedItem;\n\n\t\t\t\t\t\tthis._items.add( { item, marker } );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( this._items.length ) {\n\t\t\t\t\t\tthis._showUI( mentionMarker );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._hideUIAndRemoveMarker();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t} );\n\n\t\twatcher.on( 'unmatched', () => {\n\t\t\tthis._hideUIAndRemoveMarker();\n\t\t} );\n\n\t\treturn watcher;\n\t}\n\n\t/**\n\t * Shows the mentions balloon. If the panel is already visible, it will reposition it.\n\t *\n\t * @private\n\t */\n\t_showUI( markerMarker ) {\n\t\tif ( this._isUIVisible ) {\n\t\t\t// Update balloon position as the mention list view may change its size.\n\t\t\tthis._balloon.updatePosition( this._getBalloonPanelPositionData( markerMarker, this._mentionsView.position ) );\n\t\t} else {\n\t\t\tthis._balloon.add( {\n\t\t\t\tview: this._mentionsView,\n\t\t\t\tposition: this._getBalloonPanelPositionData( markerMarker, this._mentionsView.position ),\n\t\t\t\twithArrow: false,\n\t\t\t\tsingleViewMode: true\n\t\t\t} );\n\t\t}\n\n\t\tthis._mentionsView.position = this._balloon.view.position;\n\n\t\tthis._mentionsView.selectFirst();\n\t}\n\n\t/**\n\t * Hides the mentions balloon and removes the 'mention' marker from the markers collection.\n\t *\n\t * @private\n\t */\n\t_hideUIAndRemoveMarker() {\n\t\t// Remove the mention view from balloon before removing marker - it is used by balloon position target().\n\t\tif ( this._balloon.hasView( this._mentionsView ) ) {\n\t\t\tthis._balloon.remove( this._mentionsView );\n\t\t}\n\n\t\tif ( this.editor.model.markers.has( 'mention' ) ) {\n\t\t\tthis.editor.model.change( writer => writer.removeMarker( 'mention' ) );\n\t\t}\n\n\t\t// Make the last matched position on panel view undefined so the #_getBalloonPanelPositionData() method will return all positions\n\t\t// on the next call.\n\t\tthis._mentionsView.position = undefined;\n\t}\n\n\t/**\n\t * Renders a single item in the autocomplete list.\n\t *\n\t * @private\n\t * @param {module:mention/mention~MentionFeedItem} item\n\t * @param {String} marker\n\t * @returns {module:ui/button/buttonview~ButtonView|module:mention/ui/domwrapperview~DomWrapperView}\n\t */\n\t_renderItem( item, marker ) {\n\t\tconst editor = this.editor;\n\n\t\tlet view;\n\t\tlet label = item.id;\n\n\t\tconst renderer = this._getItemRenderer( marker );\n\n\t\tif ( renderer ) {\n\t\t\tconst renderResult = renderer( item );\n\n\t\t\tif ( typeof renderResult != 'string' ) {\n\t\t\t\tview = new DomWrapperView( editor.locale, renderResult );\n\t\t\t} else {\n\t\t\t\tlabel = renderResult;\n\t\t\t}\n\t\t}\n\n\t\tif ( !view ) {\n\t\t\tconst buttonView = new ButtonView( editor.locale );\n\n\t\t\tbuttonView.label = label;\n\t\t\tbuttonView.withText = true;\n\n\t\t\tview = buttonView;\n\t\t}\n\n\t\treturn view;\n\t}\n\n\t/**\n\t * Creates a position options object used to position the balloon panel.\n\t *\n\t * @param {module:engine/model/markercollection~Marker} mentionMarker\n\t * @param {String|undefined} preferredPosition The name of the last matched position name.\n\t * @returns {module:utils/dom/position~Options}\n\t * @private\n\t */\n\t_getBalloonPanelPositionData( mentionMarker, preferredPosition ) {\n\t\tconst editor = this.editor;\n\t\tconst editing = this.editor.editing;\n\t\tconst domConverter = editing.view.domConverter;\n\t\tconst mapper = editing.mapper;\n\n\t\treturn {\n\t\t\ttarget: () => {\n\t\t\t\tlet modelRange = mentionMarker.getRange();\n\n\t\t\t\t// Target the UI to the model selection range - the marker has been removed so probably the UI will not be shown anyway.\n\t\t\t\t// The logic is used by ContextualBalloon to display another panel in the same place.\n\t\t\t\tif ( modelRange.start.root.rootName == '$graveyard' ) {\n\t\t\t\t\tmodelRange = editor.model.document.selection.getFirstRange();\n\t\t\t\t}\n\n\t\t\t\tconst viewRange = mapper.toViewRange( modelRange );\n\t\t\t\tconst rangeRects = Rect.getDomRangeRects( domConverter.viewRangeToDom( viewRange ) );\n\n\t\t\t\treturn rangeRects.pop();\n\t\t\t},\n\t\t\tlimiter: () => {\n\t\t\t\tconst view = this.editor.editing.view;\n\t\t\t\tconst viewDocument = view.document;\n\t\t\t\tconst editableElement = viewDocument.selection.editableElement;\n\n\t\t\t\tif ( editableElement ) {\n\t\t\t\t\treturn view.domConverter.mapViewToDom( editableElement.root );\n\t\t\t\t}\n\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\tpositions: getBalloonPanelPositions( preferredPosition )\n\t\t};\n\t}\n}\n\n// Returns the balloon positions data callbacks.\n//\n// @param {String} preferredPosition\n// @returns {Array.<module:utils/dom/position~Position>}\nfunction getBalloonPanelPositions( preferredPosition ) {\n\tconst positions = {\n\t\t// Positions the panel to the southeast of the caret rectangle.\n\t\t'caret_se': targetRect => {\n\t\t\treturn {\n\t\t\t\ttop: targetRect.bottom + VERTICAL_SPACING,\n\t\t\t\tleft: targetRect.right,\n\t\t\t\tname: 'caret_se'\n\t\t\t};\n\t\t},\n\n\t\t// Positions the panel to the northeast of the caret rectangle.\n\t\t'caret_ne': ( targetRect, balloonRect ) => {\n\t\t\treturn {\n\t\t\t\ttop: targetRect.top - balloonRect.height - VERTICAL_SPACING,\n\t\t\t\tleft: targetRect.right,\n\t\t\t\tname: 'caret_ne'\n\t\t\t};\n\t\t},\n\n\t\t// Positions the panel to the southwest of the caret rectangle.\n\t\t'caret_sw': ( targetRect, balloonRect ) => {\n\t\t\treturn {\n\t\t\t\ttop: targetRect.bottom + VERTICAL_SPACING,\n\t\t\t\tleft: targetRect.right - balloonRect.width,\n\t\t\t\tname: 'caret_sw'\n\t\t\t};\n\t\t},\n\n\t\t// Positions the panel to the northwest of the caret rect.\n\t\t'caret_nw': ( targetRect, balloonRect ) => {\n\t\t\treturn {\n\t\t\t\ttop: targetRect.top - balloonRect.height - VERTICAL_SPACING,\n\t\t\t\tleft: targetRect.right - balloonRect.width,\n\t\t\t\tname: 'caret_nw'\n\t\t\t};\n\t\t}\n\t};\n\n\t// Returns only the last position if it was matched to prevent the panel from jumping after the first match.\n\tif ( positions.hasOwnProperty( preferredPosition ) ) {\n\t\treturn [\n\t\t\tpositions[ preferredPosition ]\n\t\t];\n\t}\n\n\t// By default return all position callbacks.\n\treturn [\n\t\tpositions.caret_se,\n\t\tpositions.caret_sw,\n\t\tpositions.caret_ne,\n\t\tpositions.caret_nw\n\t];\n}\n\n// Creates a RegExp pattern for the marker.\n//\n// Function has to be exported to achieve 100% code coverage.\n//\n// @param {String} marker\n// @param {Number} minimumCharacters\n// @returns {RegExp}\nexport function createRegExp( marker, minimumCharacters ) {\n\tconst numberOfCharacters = minimumCharacters == 0 ? '*' : `{${ minimumCharacters },}`;\n\n\tconst openAfterCharacters = env.features.isRegExpUnicodePropertySupported ? '\\\\p{Ps}\\\\p{Pi}\"\\'' : '\\\\(\\\\[{\"\\'';\n\tconst mentionCharacters = env.features.isRegExpUnicodePropertySupported ? '\\\\p{L}\\\\p{N}' : 'a-zA-ZÀ-ž0-9';\n\n\t// The pattern consists of 3 groups:\n\t// - 0 (non-capturing): Opening sequence - start of the line, space or an opening punctuation character like \"(\" or \"\\\"\",\n\t// - 1: The marker character,\n\t// - 2: Mention input (taking the minimal length into consideration to trigger the UI),\n\t//\n\t// The pattern matches up to the caret (end of string switch - $).\n\t// (0: opening sequence )(1: marker )(2: typed mention )$\n\tconst pattern = `(?:^|[ ${ openAfterCharacters }])([${ marker }])([_${ mentionCharacters }]${ numberOfCharacters })$`;\n\n\treturn new RegExp( pattern, 'u' );\n}\n\n// Creates a test callback for the marker to be used in the text watcher instance.\n//\n// @param {String} marker\n// @param {Number} minimumCharacters\n// @returns {Function}\nfunction createTestCallback( marker, minimumCharacters ) {\n\tconst regExp = createRegExp( marker, minimumCharacters );\n\n\treturn text => regExp.test( text );\n}\n\n// Creates a text matcher from the marker.\n//\n// @param {String} marker\n// @returns {Function}\nfunction getFeedText( marker, text ) {\n\tconst regExp = createRegExp( marker, 0 );\n\n\tconst match = text.match( regExp );\n\n\treturn match[ 2 ];\n}\n\n// The default feed callback.\nfunction createFeedCallback( feedItems ) {\n\treturn feedText => {\n\t\tconst filteredItems = feedItems\n\t\t// Make the default mention feed case-insensitive.\n\t\t\t.filter( item => {\n\t\t\t\t// Item might be defined as object.\n\t\t\t\tconst itemId = typeof item == 'string' ? item : String( item.id );\n\n\t\t\t\t// The default feed is case insensitive.\n\t\t\t\treturn itemId.toLowerCase().includes( feedText.toLowerCase() );\n\t\t\t} )\n\t\t\t// Do not return more than 10 items.\n\t\t\t.slice( 0, 10 );\n\n\t\treturn Promise.resolve( filteredItems );\n\t};\n}\n\n// Checks if a given key code is handled by the mention UI.\n//\n// @param {Number}\n// @returns {Boolean}\nfunction isHandledKey( keyCode ) {\n\tconst handledKeyCodes = [\n\t\tkeyCodes.arrowup,\n\t\tkeyCodes.arrowdown,\n\t\tkeyCodes.enter,\n\t\tkeyCodes.tab,\n\t\tkeyCodes.space,\n\t\tkeyCodes.esc\n\t];\n\n\treturn handledKeyCodes.includes( keyCode );\n}\n","import OPMacroTocPlugin from './plugins/op-macro-toc-plugin';\nimport OPMacroEmbeddedTable from './plugins/op-macro-embedded-table/embedded-table-plugin';\nimport OPMacroWpButtonPlugin from './plugins/op-macro-wp-button/op-macro-wp-button-plugin';\nimport OpUploadPlugin from './plugins/op-upload-plugin';\nimport OPChildPagesPlugin from \"./plugins/op-macro-child-pages/op-macro-child-pages-plugin\";\nimport Essentials from \"@ckeditor/ckeditor5-essentials/src/essentials\";\nimport UploadAdapter from \"@ckeditor/ckeditor5-adapter-ckfinder/src/uploadadapter\";\nimport AutoFormat from \"@ckeditor/ckeditor5-autoformat/src/autoformat\";\nimport Bold from \"@ckeditor/ckeditor5-basic-styles/src/bold\";\nimport Code from \"@ckeditor/ckeditor5-basic-styles/src/code\";\nimport Strikethrough from \"@ckeditor/ckeditor5-basic-styles/src/strikethrough\"\nimport Italic from \"@ckeditor/ckeditor5-basic-styles/src/italic\";\nimport BlockQuote from \"@ckeditor/ckeditor5-block-quote/src/blockquote\";\nimport Heading from \"@ckeditor/ckeditor5-heading/src/heading\";\nimport Image from \"@ckeditor/ckeditor5-image/src/image\";\nimport ImageCaption from \"@ckeditor/ckeditor5-image/src/imagecaption\";\nimport ImageStyle from \"@ckeditor/ckeditor5-image/src/imagestyle\";\nimport ImageToolbar from \"@ckeditor/ckeditor5-image/src/imagetoolbar\";\nimport Link from \"@ckeditor/ckeditor5-link/src/link\";\nimport List from \"@ckeditor/ckeditor5-list/src/list\";\nimport Paragraph from \"@ckeditor/ckeditor5-paragraph/src/paragraph\";\nimport Typing from \"@ckeditor/ckeditor5-typing/src/typing\";\nimport OPHelpLinkPlugin from \"./plugins/op-help-link-plugin/op-help-link-plugin\";\nimport CodeBlockPlugin from \"./plugins/code-block/code-block\";\nimport OPPreviewPlugin from \"./plugins/op-preview.plugin\";\nimport Table from \"@ckeditor/ckeditor5-table/src/table\";\nimport TableToolbar from \"@ckeditor/ckeditor5-table/src/tabletoolbar\";\nimport PasteFromOffice from '@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice';\nimport TodoList from \"@ckeditor/ckeditor5-list/src/todolist\";\nimport OPMacroListPlugin from \"./plugins/op-macro-list-plugin\";\nimport OPAttachmentListenerPlugin from './plugins/op-attachment-listener-plugin';\nimport OpImageAttachmentLookup from './plugins/op-image-attachment-lookup/op-image-attachment-lookup-plugin';\nimport CommonMark from './commonmark/commonmark';\nimport OPSourceCodePlugin from './plugins/op-source-code.plugin';\n// import Mention from \"../forked/ckeditor5-mention/src/mention\";\nimport Mention from \"@ckeditor/ckeditor5-mention/src/mention\";\nimport {MentionCaster} from './mentions/mentions-caster';\n\n// We divide our plugins into separate concerns here\n// in order to enable / disable each group by configuration\nexport const opMacroPlugins = [\n\tOPMacroTocPlugin,\n\tOPMacroEmbeddedTable,\n\tOPMacroWpButtonPlugin,\n\tOPChildPagesPlugin,\n];\n\nexport const opImageUploadPlugins = [\n\tOpUploadPlugin,\n\tOPAttachmentListenerPlugin\n];\n\nexport const builtinPlugins = [\n\tEssentials,\n\tUploadAdapter,\n\tAutoFormat,\n\tBold,\n\tCode,\n\tItalic,\n\tStrikethrough,\n\tBlockQuote,\n\tHeading,\n\tImage,\n\tImageCaption,\n\tImageStyle,\n\tImageToolbar,\n\tOpImageAttachmentLookup,\n\tLink,\n\tList,\n\tTodoList,\n\tParagraph,\n\tTyping,\n\n\t// Built-in mentions\n\tMention,\n\tMentionCaster,\n\tPasteFromOffice,\n\n\tOPHelpLinkPlugin,\n\tCodeBlockPlugin,\n\tOPPreviewPlugin,\n\tOPSourceCodePlugin,\n\n\tCommonMark,\n\tTable,\n\tTableToolbar,\n\n\tOPMacroListPlugin,\n\n].concat(\n\t// OpenProject Macro plugin group\n\topMacroPlugins,\n\n\t// OpenProject image upload plugins\n\topImageUploadPlugins,\n);\n","import EmbeddedTableEditing from './embedded-table-editing';\nimport Widget from '@ckeditor/ckeditor5-widget/src/widget';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport EmbeddedTableToolbar from './embedded-table-toolbar';\n\nexport default class OPMacroEmbeddedTable extends Plugin {\n\tstatic get requires() {\n\t\treturn [ EmbeddedTableEditing, Widget, EmbeddedTableToolbar ];\n\t}\n\n\tstatic get pluginName() {\n\t\treturn 'OPMacroEmbeddedTable';\n\t}\n\n\tstatic get buttonName() {\n\t\treturn EmbeddedTableEditing.buttonName;\n\t}\n}\n","import Widget from '@ckeditor/ckeditor5-widget/src/widget';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport OPMacroWpButtonEditing from './op-macro-wp-button-editing';\nimport OPMacroWpButtonToolbar from './op-macro-wp-button-toolbar';\n\nexport default class OPMacroWpButtonPlugin extends Plugin {\n\tstatic get requires() {\n\t\treturn [ OPMacroWpButtonEditing, Widget, OPMacroWpButtonToolbar ];\n\t}\n\n\tstatic get pluginName() {\n\t\treturn 'OPMacroWpButton';\n\t}\n\n\tstatic get buttonName() {\n\t\treturn OPMacroWpButtonEditing.buttonName;\n\t}\n}\n","import Widget from '@ckeditor/ckeditor5-widget/src/widget';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport OPChildPagesEditing from './op-macro-child-pages-editing';\nimport OPChildPagesToolbar from './op-macro-child-pages-toolbar';\n\nexport default class OPChildPagesPlugin extends Plugin {\n\tstatic get requires() {\n\t\treturn [ OPChildPagesEditing, Widget, OPChildPagesToolbar ];\n\t}\n\n\tstatic get pluginName() {\n\t\treturn 'OPChildPages';\n\t}\n\n\tstatic get buttonName() {\n\t\treturn OPChildPagesEditing.buttonName;\n\t}\n}\n","import Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';\nimport OpUploadResourceAdapter from './op-upload-resource-adapter';\nimport {getOPResource} from './op-context/op-context';\nimport ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload';\n\nexport default class OpUploadPlugin extends Plugin {\n\n static get requires() {\n return [FileRepository, ImageUpload];\n }\n\n static get pluginName() {\n return 'OpUploadPlugin';\n }\n\n init() {\n this.editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {\n\t\t\tconst resource = getOPResource(this.editor);\n\t\t\treturn new OpUploadResourceAdapter(loader, resource, this.editor);\n\t\t}\n }\n}\n","import Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport Selection from '@ckeditor/ckeditor5-engine/src/model/selection';\n\nexport default class OPAttachmentListenerPlugin extends Plugin {\n\tstatic get pluginName() {\n\t\treturn 'OPAttachmentListener';\n\t}\n\n\tinit() {\n\t\tlet editor = this.editor;\n\n\t\teditor.model.on('op:attachment-removed', (_, urls) => {\n\t\t\tthis.removeDeletedImage(urls)\n\t\t});\n\t}\n\n\tremoveDeletedImage(urls) {\n\t\tlet root = this.editor.model.document.getRoot();\n\n\t\tfor (const child of Array.from(root.getChildren())) {\n\t\t\tif (child.name === 'image' && urls.indexOf(child.getAttribute('src')) > -1) {\n\t\t\t\tconst selection = new Selection( child, 'on' );\n\n\t\t\t\tthis.editor.model.deleteContent(selection);\n\t\t\t}\n\t\t}\n\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 essentials/essentials\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';\nimport Enter from '@ckeditor/ckeditor5-enter/src/enter';\nimport ShiftEnter from '@ckeditor/ckeditor5-enter/src/shiftenter';\nimport Typing from '@ckeditor/ckeditor5-typing/src/typing';\nimport Undo from '@ckeditor/ckeditor5-undo/src/undo';\n\n/**\n * A plugin including all essential editing features. It represents a set of features that enables similar functionalities\n * to a `<textarea>` element.\n *\n * It includes:\n *\n * * {@link module:clipboard/clipboard~Clipboard},\n * * {@link module:enter/enter~Enter},\n * * {@link module:enter/shiftenter~ShiftEnter},\n * * {@link module:typing/typing~Typing},\n * * {@link module:undo/undo~Undo}.\n *\n * This plugin set does not define any block-level containers (such as {@link module:paragraph/paragraph~Paragraph}).\n * If your editor is supposed to handle block content, make sure to include it.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Essentials extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ Clipboard, Enter, ShiftEnter, Typing, Undo ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Essentials';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/bold\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport BoldEditing from './bold/boldediting';\nimport BoldUI from './bold/boldui';\n\n/**\n * The bold feature.\n *\n * For a detailed overview check the {@glink features/basic-styles Basic styles feature documentation}\n * and the {@glink api/basic-styles package page}.\n *\n * This is a \"glue\" plugin which loads the {@link module:basic-styles/bold/boldediting~BoldEditing bold editing feature}\n * and {@link module:basic-styles/bold/boldui~BoldUI bold UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Bold extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ BoldEditing, BoldUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Bold';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/code\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport CodeEditing from './code/codeediting';\nimport CodeUI from './code/codeui';\n\nimport '../theme/code.css';\n\n/**\n * The code feature.\n *\n * For a detailed overview check the {@glink features/basic-styles Basic styles feature documentation}\n * and the {@glink api/basic-styles package page}.\n *\n * This is a \"glue\" plugin which loads the {@link module:basic-styles/code/codeediting~CodeEditing code editing feature}\n * and {@link module:basic-styles/code/codeui~CodeUI code UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Code extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ CodeEditing, CodeUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Code';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/italic\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ItalicEditing from './italic/italicediting';\nimport ItalicUI from './italic/italicui';\n\n/**\n * The italic feature.\n *\n * For a detailed overview check the {@glink features/basic-styles Basic styles feature documentation}\n * and the {@glink api/basic-styles package page}.\n *\n * This is a \"glue\" plugin which loads the {@link module:basic-styles/italic/italicediting~ItalicEditing} and\n * {@link module:basic-styles/italic/italicui~ItalicUI} plugins.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Italic extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ItalicEditing, ItalicUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Italic';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 basic-styles/strikethrough\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport StrikethroughEditing from './strikethrough/strikethroughediting';\nimport StrikethroughUI from './strikethrough/strikethroughui';\n\n/**\n * The strikethrough feature.\n *\n * For a detailed overview check the {@glink features/basic-styles Basic styles feature documentation}\n * and the {@glink api/basic-styles package page}.\n *\n * This is a \"glue\" plugin which loads the {@link module:basic-styles/strikethrough/strikethroughediting~StrikethroughEditing} and\n * {@link module:basic-styles/strikethrough/strikethroughui~StrikethroughUI} plugins.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Strikethrough extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ StrikethroughEditing, StrikethroughUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Strikethrough';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 block-quote/blockquote\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport BlockQuoteEditing from './blockquoteediting';\nimport BlockQuoteUI from './blockquoteui';\n\n/**\n * The block quote plugin.\n *\n * For more information about this feature check the {@glink api/block-quote package page}.\n *\n * This is a \"glue\" plugin which loads the {@link module:block-quote/blockquoteediting~BlockQuoteEditing block quote editing feature}\n * and {@link module:block-quote/blockquoteui~BlockQuoteUI block quote UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class BlockQuote extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ BlockQuoteEditing, BlockQuoteUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'BlockQuote';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 heading/heading\n */\n\nimport HeadingEditing from './headingediting';\nimport HeadingUI from './headingui';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport '../theme/heading.css';\n\n/**\n * The headings feature.\n *\n * For a detailed overview, check the {@glink features/headings Headings feature documentation}\n * and the {@glink api/heading package page}.\n *\n * This is a \"glue\" plugin which loads the {@link module:heading/headingediting~HeadingEditing heading editing feature}\n * and {@link module:heading/headingui~HeadingUI heading UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Heading extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ HeadingEditing, HeadingUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Heading';\n\t}\n}\n\n/**\n * The configuration of the heading feature. Introduced by the {@link module:heading/headingediting~HeadingEditing} feature.\n *\n * Read more in {@link module:heading/heading~HeadingConfig}.\n *\n * @member {module:heading/heading~HeadingConfig} module:core/editor/editorconfig~EditorConfig#heading\n */\n\n/**\n * The configuration of the heading feature.\n * The option is used by the {@link module:heading/headingediting~HeadingEditing} feature.\n *\n *\t\tClassicEditor\n *\t\t\t.create( {\n * \t\t\t\theading: ... // Heading feature config.\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.\n *\n * @interface HeadingConfig\n */\n\n/**\n * The available heading options.\n *\n * The default value is:\n *\n *\t\tconst headingConfig = {\n *\t\t\toptions: [\n *\t\t\t\t{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },\n *\t\t\t\t{ model: 'heading1', view: 'h2', title: 'Heading 1', class: 'ck-heading_heading1' },\n *\t\t\t\t{ model: 'heading2', view: 'h3', title: 'Heading 2', class: 'ck-heading_heading2' },\n *\t\t\t\t{ model: 'heading3', view: 'h4', title: 'Heading 3', class: 'ck-heading_heading3' }\n *\t\t\t]\n *\t\t};\n *\n * It defines 3 levels of headings. In the editor model they will use `heading1`, `heading2`, and `heading3` elements.\n * Their respective view elements (so the elements output by the editor) will be: `h2`, `h3`, and `h4`. This means that\n * if you choose \"Heading 1\" in the headings dropdown the editor will turn the current block to `<heading1>` in the model\n * which will result in rendering (and outputting to data) the `<h2>` element.\n *\n * The `title` and `class` properties will be used by the `headings` dropdown to render available options.\n * Usually, the first option in the headings dropdown is the \"Paragraph\" option, hence it's also defined on the list.\n * However, you don't need to define its view representation because it's handled by\n * the {@link module:paragraph/paragraph~Paragraph} feature (which is required by\n * the {@link module:heading/headingediting~HeadingEditing} feature).\n *\n * You can **read more** about configuring heading levels and **see more examples** in\n * the {@glink features/headings Headings} guide.\n *\n * Note: In the model you should always start from `heading1`, regardless of how the headings are represented in the view.\n * That's assumption is used by features like {@link module:autoformat/autoformat~Autoformat} to know which element\n * they should use when applying the first level heading.\n *\n * The defined headings are also available as values passed to the `'heading'` command under their model names.\n * For example, the below code will apply `<heading1>` to the current selection:\n *\n *\t\teditor.execute( 'heading', { value: 'heading1' } );\n *\n * @member {Array.<module:heading/heading~HeadingOption>} module:heading/heading~HeadingConfig#options\n */\n\n/**\n * Heading option descriptor.\n *\n * @typedef {Object} module:heading/heading~HeadingOption\n * @property {String} model Name of the model element to convert.\n * @property {module:engine/view/elementdefinition~ElementDefinition} view Definition of a view element to convert from/to.\n * @property {String} title The user-readable title of the option.\n * @property {String} class The class which will be added to the dropdown item representing this option.\n * @property {String} [icon] Icon used by {@link module:heading/headingbuttonsui~HeadingButtonsUI}. It can be omitted when using\n * the default configuration.\n * @extends module:engine/conversion/conversion~ConverterDefinition\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 image/image\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ImageEditing from '../src/image/imageediting';\nimport Widget from '@ckeditor/ckeditor5-widget/src/widget';\nimport ImageTextAlternative from './imagetextalternative';\n\nimport '../theme/image.css';\n\n/**\n * The image plugin.\n *\n * For a detailed overview, check the {@glink features/image image feature} documentation.\n *\n * This is a \"glue\" plugin which loads the following plugins:\n *\n * * {@link module:image/image/imageediting~ImageEditing},\n * * {@link module:image/imagetextalternative~ImageTextAlternative}.\n *\n * Usually, it is used in conjuction with other plugins from this package. See the {@glink api/image package page}\n * for more information.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Image extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ImageEditing, Widget, ImageTextAlternative ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Image';\n\t}\n}\n\n/**\n * The configuration of the image features. Used by the image features in the `@ckeditor/ckeditor5-image` package.\n *\n * Read more in {@link module:image/image~ImageConfig}.\n *\n * @member {module:image/image~ImageConfig} module:core/editor/editorconfig~EditorConfig#image\n */\n\n/**\n * The configuration of the image features. Used by the image features in the `@ckeditor/ckeditor5-image` package.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n * \t\t\t\timage: ... // Image feature options.\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.\n *\n * @interface ImageConfig\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 image/imagecaption\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ImageCaptionEditing from './imagecaption/imagecaptionediting';\n\nimport '../theme/imagecaption.css';\n\n/**\n * The image caption plugin.\n *\n * For a detailed overview, check the {@glink features/image#image-captions image caption} documentation.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageCaption extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ImageCaptionEditing ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ImageCaption';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 image/imagestyle\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ImageStyleEditing from './imagestyle/imagestyleediting';\nimport ImageStyleUI from './imagestyle/imagestyleui';\n\n/**\n * The image style plugin.\n *\n * For a detailed overview, check the {@glink features/image#image-styles image styles} documentation.\n *\n * This is a \"glue\" plugin which loads the {@link module:image/imagestyle/imagestyleediting~ImageStyleEditing}\n * and {@link module:image/imagestyle/imagestyleui~ImageStyleUI} plugins.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageStyle extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ImageStyleEditing, ImageStyleUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ImageStyle';\n\t}\n}\n\n/**\n * Available image styles.\n *\n * The default value is:\n *\n *\t\tconst imageConfig = {\n *\t\t\tstyles: [ 'full', 'side' ]\n *\t\t};\n *\n * which configures two default styles:\n *\n * * the \"full\" style which does not apply any class, e.g. for images styled to span 100% width of the content,\n * * the \"side\" style with the `.image-style-side` CSS class.\n *\n * See {@link module:image/imagestyle/utils~defaultStyles} to learn more about default\n * styles provided by the image feature.\n *\n * The {@link module:image/imagestyle/utils~defaultStyles default styles} can be customized,\n * e.g. to change the icon, title or CSS class of the style. The feature also provides several\n * {@link module:image/imagestyle/utils~defaultIcons default icons} to choose from.\n *\n *\t\timport customIcon from 'custom-icon.svg';\n *\n *\t\t// ...\n *\n *\t\tconst imageConfig = {\n *\t\t\tstyles: [\n *\t\t\t\t// This will only customize the icon of the \"full\" style.\n *\t\t\t\t// Note: 'right' is one of default icons provided by the feature.\n *\t\t\t\t{ name: 'full', icon: 'right' },\n *\n *\t\t\t\t// This will customize the icon, title and CSS class of the default \"side\" style.\n *\t\t\t\t{ name: 'side', icon: customIcon, title: 'My side style', className: 'custom-side-image' }\n *\t\t\t]\n *\t\t};\n *\n * If none of the default styles is good enough, it is possible to define independent custom styles, too:\n *\n *\t\timport fullSizeIcon from '@ckeditor/ckeditor5-core/theme/icons/object-center.svg';\n *\t\timport sideIcon from '@ckeditor/ckeditor5-core/theme/icons/object-right.svg';\n *\n *\t\t// ...\n *\n *\t\tconst imageConfig = {\n *\t\t\tstyles: [\n *\t\t\t\t// A completely custom full size style with no class, used as a default.\n *\t\t\t\t{ name: 'fullSize', title: 'Full size', icon: fullSizeIcon, isDefault: true },\n *\n *\t\t\t\t{ name: 'side', title: 'To the side', icon: sideIcon, className: 'side-image' }\n *\t\t\t]\n *\t\t};\n *\n * Note: Setting `title` to one of {@link module:image/imagestyle/imagestyleui~ImageStyleUI#localizedDefaultStylesTitles}\n * will automatically translate it to the language of the editor.\n *\n * Read more about styling images in the {@glink features/image#image-styles Image styles guide}.\n *\n * The feature creates commands based on defined styles, so you can change the style of a selected image by executing\n * the following command:\n *\n *\t\teditor.execute( 'imageStyle' { value: 'side' } );\n *\n * The feature also creates buttons that execute the commands. So, assuming that you use the\n * default image styles setting, you can {@link module:image/image~ImageConfig#toolbar configure the image toolbar}\n * (or any other toolbar) to contain these options:\n *\n *\t\tconst imageConfig = {\n *\t\t\ttoolbar: [ 'imageStyle:full', 'imageStyle:side' ]\n *\t\t};\n *\n * @member {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat>} module:image/image~ImageConfig#styles\n */\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module image/imagetoolbar\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport { getSelectedImageWidget } from './image/utils';\nimport WidgetToolbarRepository from '@ckeditor/ckeditor5-widget/src/widgettoolbarrepository';\n/**\n * The image toolbar plugin. It creates and manages the image toolbar (the toolbar displayed when an image is selected).\n *\n * For a detailed overview, check the {@glink features/image#image-contextual-toolbar image contextual toolbar} documentation.\n *\n * Instances of toolbar components (e.g. buttons) are created using the editor's\n * {@link module:ui/componentfactory~ComponentFactory component factory}\n * based on the {@link module:image/image~ImageConfig#toolbar `image.toolbar` configuration option}.\n *\n * The toolbar uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ImageToolbar extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get requires() {\n return [WidgetToolbarRepository];\n }\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'ImageToolbar';\n }\n /**\n\t * @inheritDoc\n\t */\n afterInit() {\n const editor = this.editor;\n const t = editor.t;\n const widgetToolbarRepository = editor.plugins.get(WidgetToolbarRepository);\n widgetToolbarRepository.register('image', {\n ariaLabel: t('b'),\n items: editor.config.get('image.toolbar') || [],\n getRelatedElement: getSelectedImageWidget\n });\n }\n} /**\n * Items to be placed in the image toolbar.\n * This option is used by the {@link module:image/imagetoolbar~ImageToolbar} feature.\n *\n * Assuming that you use the following features:\n *\n * * {@link module:image/imagestyle~ImageStyle} (with a default configuration),\n * * {@link module:image/imagetextalternative~ImageTextAlternative},\n *\n * three toolbar items will be available in {@link module:ui/componentfactory~ComponentFactory}:\n * `'imageStyle:full'`, `'imageStyle:side'`, and `'imageTextAlternative'` so you can configure the toolbar like this:\n *\n *\t\tconst imageConfig = {\n *\t\t\ttoolbar: [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ]\n *\t\t};\n *\n * Of course, the same buttons can also be used in the\n * {@link module:core/editor/editorconfig~EditorConfig#toolbar main editor toolbar}.\n *\n * Read more about configuring toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.\n *\n * @member {Array.<String>} module:image/image~ImageConfig#toolbar\n */","import Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport {getOPResource} from '../op-context/op-context';\nimport {originalSrcAttribute} from '../../commonmark/commonmarkdataprocessor';\n\n\nexport function replaceImageAttachmentsByName(resource) {\n\treturn dispatcher => {\n\t\tdispatcher.on('attribute:src:image', converter, { priority: 'highest' } );\n\t};\n\n\tfunction converter( evt, data, conversionApi ) {\n\n\t\t// We do not consume the attribute since we want the regular attribute\n\t\t// converter to run as well.\n\t\tlet src = data.attributeNewValue;\n\n\t\t// If the resource is not attachable or src has been nulled, do nothing\n\t\tif (!(src && resource.lookupDownloadLocationByName)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst match = resource.lookupDownloadLocationByName(src);\n\t\tdata.attributeNewValue = match || src;\n\t}\n}\n\nexport function replaceNamedAttachmentWithUrl(resource) {\n\treturn dispatcher => {\n\t\tdispatcher.on('attribute:src:image', converter, { priority: 'highest' } );\n\t};\n\n\tfunction converter( evt, data, conversionApi ) {\n\n\t\t// We do not consume the attribute since we want the regular attribute\n\t\t// converter to run as well.\n\t\tlet src = data.attributeNewValue;\n\n\t\t// If the resource is not attachable or src has been nulled, do nothing\n\t\tif (!(src && resource.lookupDownloadLocationByName)) {\n\t\t\treturn;\n\t\t}\n\n\n\t\tconst match = resource.lookupDownloadLocationByName(src);\n\t\tdata.attributeNewValue = match || src;\n\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst figure = conversionApi.mapper.toViewElement( data.item );\n\t\tconst img = figure.getChild( 0 );\n\n\t\tif (match) {\n\t\t\tviewWriter.setAttribute(originalSrcAttribute, src, img );\n\t\t}\n\t}\n}\n\n\nexport default class OpImageAttachmentLookup extends Plugin {\n\tstatic get pluginName() {\n\t\treturn 'OpImageAttachmentLookup';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst conversion = editor.conversion;\n\t\tconst resource = getOPResource(editor);\n\n\t\tconversion\n\t\t\t.for('editingDowncast')\n\t\t\t.add(replaceImageAttachmentsByName(resource));\n\n\t\t// Temporarily replace the src attribute with data-src attribute to avoid loading\n\t\tconversion\n\t\t\t.for('dataDowncast')\n\t\t\t.add(replaceNamedAttachmentWithUrl(resource));\n\t}\n\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 link/link\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport LinkEditing from './linkediting';\nimport LinkUI from './linkui';\n\n/**\n * The link plugin.\n *\n * This is a \"glue\" plugin that loads the {@link module:link/linkediting~LinkEditing link editing feature}\n * and {@link module:link/linkui~LinkUI link UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Link extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ LinkEditing, LinkUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Link';\n\t}\n}\n\n/**\n * The configuration of the {@link module:link/link~Link} feature.\n *\n * Read more in {@link module:link/link~LinkConfig}.\n *\n * @member {module:link/link~LinkConfig} module:core/editor/editorconfig~EditorConfig#link\n */\n\n/**\n * The configuration of the {@link module:link/link~Link link feature}.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n * \t\t\t\tlink: ... // Link feature configuration.\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.\n * @interface LinkConfig\n */\n\n/**\n * When set to `true`, the `target=\"blank\"` and `rel=\"noopener noreferrer\"` attributes are automatically added to all external links\n * in the editor. \"External links\" are all links in the editor content starting with `http`, `https`, or `//`.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n *\t\t\t\tlink: {\n *\t\t\t\t\taddTargetToExternalLinks: true\n *\t\t\t\t}\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * Internally, this option activates a predefined {@link module:link/link~LinkConfig#decorators automatic link decorator}\n * that extends all external links with the `target` and `rel` attributes.\n *\n * **Note**: To control the `target` and `rel` attributes of specific links in the edited content, a dedicated\n * {@link module:link/link~LinkDecoratorManualDefinition manual} decorator must be defined in the\n * {@link module:link/link~LinkConfig#decorators `config.link.decorators`} array. In such scenario,\n * the `config.link.addTargetToExternalLinks` option should remain `undefined` or `false` to not interfere with the manual decorator.\n *\n * It is possible to add other {@link module:link/link~LinkDecoratorAutomaticDefinition automatic}\n * or {@link module:link/link~LinkDecoratorManualDefinition manual} link decorators when this option is active.\n *\n * More information about decorators can be found in the {@link module:link/link~LinkConfig#decorators decorators configuration}\n * reference.\n *\n * @default false\n * @member {Boolean} module:link/link~LinkConfig#addTargetToExternalLinks\n */\n\n/**\n * Decorators provide an easy way to configure and manage additional link attributes in the editor content. There are\n * two types of link decorators:\n *\n * * {@link module:link/link~LinkDecoratorAutomaticDefinition Automatic} &ndash; They match links against pre–defined rules and\n * manage their attributes based on the results.\n * * {@link module:link/link~LinkDecoratorManualDefinition Manual} &ndash; They allow users to control link attributes individually,\n * using the editor UI.\n *\n * Link decorators are defined as objects with key-value pairs, where the key is the name provided for a given decorator and the\n * value is the decorator definition.\n *\n * The name of the decorator also corresponds to the {@glink framework/guides/architecture/editing-engine#text-attributes text attribute}\n * in the model. For instance, the `isExternal` decorator below is represented as a `linkIsExternal` attribute in the model.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n *\t\t\t\tlink: {\n *\t\t\t\t\tdecorators: {\n *\t\t\t\t\t\tisExternal: {\n *\t\t\t\t\t\t\tmode: 'automatic',\n *\t\t\t\t\t\t\tcallback: url => url.startsWith( 'http://' ),\n *\t\t\t\t\t\t\tattributes: {\n *\t\t\t\t\t\t\t\ttarget: '_blank',\n *\t\t\t\t\t\t\t\trel: 'noopener noreferrer'\n *\t\t\t\t\t\t\t}\n *\t\t\t\t\t\t},\n *\t\t\t\t\t\tisDownloadable: {\n *\t\t\t\t\t\t\tmode: 'manual',\n *\t\t\t\t\t\t\tlabel: 'Downloadable',\n *\t\t\t\t\t\t\tattributes: {\n *\t\t\t\t\t\t\t\tdownload: 'file.png',\n *\t\t\t\t\t\t\t}\n *\t\t\t\t\t\t},\n *\t\t\t\t\t\t// ...\n *\t\t\t\t\t}\n *\t\t\t\t}\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * To learn more about the configuration syntax, check out the {@link module:link/link~LinkDecoratorAutomaticDefinition automatic}\n * and {@link module:link/link~LinkDecoratorManualDefinition manual} decorator option reference.\n *\n * **Warning:** Currently, link decorators work independently of one another and no conflict resolution mechanism exists.\n * For example, configuring the `target` attribute using both an automatic and a manual decorator at the same time could end up with\n * quirky results. The same applies if multiple manual or automatic decorators were defined for the same attribute.\n *\n * **Note**: Since the `target` attribute management for external links is a common use case, there is a predefined automatic decorator\n * dedicated for that purpose which can be enabled by turning a single option on. Check out the\n * {@link module:link/link~LinkConfig#addTargetToExternalLinks `config.link.addTargetToExternalLinks`}\n * configuration description to learn more.\n *\n * See also the {@glink features/link#custom-link-attributes-decorators link feature guide} for more information.\n *\n * @member {Object.<String, module:link/link~LinkDecoratorDefinition>} module:link/link~LinkConfig#decorators\n */\n\n/**\n * Represents a link decorator definition ({@link module:link/link~LinkDecoratorManualDefinition `'manual'`}\n * or {@link module:link/link~LinkDecoratorAutomaticDefinition `'automatic'`}).\n *\n * @interface LinkDecoratorDefinition\n */\n\n/**\n * Link decorator type.\n *\n * Check out the {@glink features/link#custom-link-attributes-decorators link feature guide} for more information.\n *\n * @member {'manual'|'automatic'} module:link/link~LinkDecoratorDefinition#mode\n */\n\n/**\n * Describes an automatic {@link module:link/link~LinkConfig#decorators link decorator}. This decorator type matches\n * all links in the editor content against a function that decides whether the link should receive a pre–defined set of attributes.\n *\n * It takes an object with key-value pairs of attributes and a callback function that must return a Boolean value based on the link's\n * `href` (URL). When the callback returns `true`, attributes are applied to the link.\n *\n * For example, to add the `target=\"_blank\"` attribute to all links in the editor starting with `http://`, the\n * configuration could look like this:\n *\n *\t\t{\n *\t\t\tmode: 'automatic',\n *\t\t\tcallback: url => url.startsWith( 'http://' ),\n *\t\t\tattributes: {\n *\t\t\t\ttarget: '_blank'\n *\t\t\t}\n *\t\t}\n *\n * **Note**: Since the `target` attribute management for external links is a common use case, there is a predefined automatic decorator\n * dedicated for that purpose that can be enabled by turning a single option on. Check out the\n * {@link module:link/link~LinkConfig#addTargetToExternalLinks `config.link.addTargetToExternalLinks`}\n * configuration description to learn more.\n *\n * @typedef {Object} module:link/link~LinkDecoratorAutomaticDefinition\n * @property {'automatic'} mode Link decorator type. It is `'automatic'` for all automatic decorators.\n * @property {Function} callback Takes a `url` as a parameter and returns `true` if the `attributes` should be applied to the link.\n * @property {Object} attributes Key-value pairs used as link attributes added to the output during the\n * {@glink framework/guides/architecture/editing-engine#conversion downcasting}.\n * Attributes should follow the {@link module:engine/view/elementdefinition~ElementDefinition} syntax.\n */\n\n/**\n * Describes a manual {@link module:link/link~LinkConfig#decorators link decorator}. This decorator type is represented in\n * the link feature's {@link module:link/linkui user interface} as a switch that the user can use to control the presence\n * of a predefined set of attributes.\n *\n * For instance, to allow the users to manually control the presence of the `target=\"_blank\"` and\n * `rel=\"noopener noreferrer\"` attributes on specific links, the decorator could look as follows:\n *\n *\t\t{\n *\t\t\tmode: 'manual',\n *\t\t\tlabel: 'Open in a new tab',\n *\t\t\tattributes: {\n *\t\t\t\ttarget: '_blank',\n *\t\t\t\trel: 'noopener noreferrer'\n *\t\t\t}\n *\t\t}\n *\n * @typedef {Object} module:link/link~LinkDecoratorManualDefinition\n * @property {'manual'} mode Link decorator type. It is `'manual'` for all manual decorators.\n * @property {String} label The label of the UI button that the user can use to control the presence of link attributes.\n * @property {Object} attributes Key-value pairs used as link attributes added to the output during the\n * {@glink framework/guides/architecture/editing-engine#conversion downcasting}.\n * Attributes should follow the {@link module:engine/view/elementdefinition~ElementDefinition} syntax.\n */\n","/**\n * @license Copyright (c) 2003-2019, 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 list/list\n */\n\nimport ListEditing from './listediting';\nimport ListUI from './listui';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\n/**\n * The list feature.\n *\n * This is a \"glue\" plugin that loads the {@link module:list/listediting~ListEditing list editing feature}\n * and {@link module:list/listui~ListUI list UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class List extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ListEditing, ListUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'List';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 list/todolist\n */\n\nimport TodoListEditing from './todolistediting';\nimport TodoListUI from './todolistui';\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport '../theme/todolist.css';\n\n/**\n * The to-do list feature.\n *\n * This is a \"glue\" plugin that loads the {@link module:list/todolistediting~TodoListEditing to-do list editing feature}\n * and the {@link module:list/todolistui~TodoListUI to-do list UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TodoList extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ TodoListEditing, TodoListUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'TodoList';\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 mention/mention\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport MentionEditing, { _toMentionAttribute } from './mentionediting';\nimport MentionUI from './mentionui';\n\nimport '../theme/mention.css';\n\n/**\n * The mention plugin.\n *\n * For a detailed overview, check the {@glink features/mentions Mention feature documentation}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Mention extends Plugin {\n\t/**\n\t * Creates a mention attribute value from the provided view element and optional data.\n\t *\n\t *\t\teditor.plugins.get( 'Mention' ).toMentionAttribute( viewElement, { userId: '1234' } );\n\t *\n\t *\t\t// For a view element: <span data-mention=\"@joe\">@John Doe</span>\n\t *\t\t// it will return:\n\t *\t\t// { id: '@joe', userId: '1234', _uid: '7a7bc7...', _text: '@John Doe' }\n\t *\n\t * @param {module:engine/view/element~Element} viewElement\n\t * @param {String|Object} [data] Additional data to be stored in the mention attribute.\n\t * @returns {module:mention/mention~MentionAttribute}\n\t */\n\ttoMentionAttribute( viewElement, data ) {\n\t\treturn _toMentionAttribute( viewElement, data );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Mention';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ MentionEditing, MentionUI ];\n\t}\n}\n\n/**\n * The configuration of the {@link module:mention/mention~Mention} feature.\n *\n * Read more in {@link module:mention/mention~MentionConfig}.\n *\n * @member {module:mention/mention~MentionConfig} module:core/editor/editorconfig~EditorConfig#mention\n * @type {Array.<module/mention~MentionFeed>}\n */\n\n/**\n * The configuration of the mention feature.\n *\n * Read more about {@glink features/mentions#configuration configuring the mention feature}.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n *\t\t\t\tmention: ... // Mention feature options.\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.\n *\n * @interface MentionConfig\n */\n\n/**\n * The list of mention feeds supported by the editor.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n *\t\t\t\tplugins: [ Mention, ... ],\n *\t\t\t\tmention: {\n *\t\t\t\t\tfeeds: [\n *\t\t\t\t\t\t{\n *\t\t\t\t\t\t\tmarker: '@',\n *\t\t\t\t\t\t\tfeed: [ '@Barney', '@Lily', '@Marshall', '@Robin', '@Ted' ]\n *\t\t\t\t\t\t},\n *\t\t\t\t\t\t...\n * \t\t\t\t\t]\n *\t\t\t\t}\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * You can provide many mention feeds but they must use different `marker`s.\n * For example, you can use `'@'` to autocomplete people and `'#'` to autocomplete tags.\n *\n * @member {Array.<module:mention/mention~MentionFeed>} module:mention/mention~MentionConfig#feeds\n */\n\n/**\n * The mention feed descriptor. Used in {@link module:mention/mention~MentionConfig `config.mention`}.\n *\n * See {@link module:mention/mention~MentionConfig} to learn more.\n *\n *\t\t// Static configuration.\n *\t\tconst mentionFeedPeople = {\n *\t\t\tmarker: '@',\n *\t\t\tfeed: [ '@Alice', '@Bob', ... ],\n *\t\t\tminimumCharacters: 2\n *\t\t};\n *\n *\t\t// Simple synchronous callback.\n *\t\tconst mentionFeedTags = {\n *\t\t\tmarker: '#',\n *\t\t\tfeed: searchString => {\n *\t\t\t\treturn tags\n *\t\t\t\t\t// Filter the tags list.\n *\t\t\t\t\t.filter( tag => {\n *\t\t\t\t\t\treturn tag.toLowerCase().includes( queryText.toLowerCase() );\n *\t\t\t\t\t} )\n *\t\t\t\t\t// Return 10 items max - needed for generic queries when the list may contain hundreds of elements.\n *\t\t\t\t\t.slice( 0, 10 );\n *\t\t\t}\n * \t\t};\n *\n *\t\tconst tags = [ 'wysiwyg', 'rte', 'rich-text-edior', 'collaboration', 'real-time', ... ];\n *\n *\t\t// Asynchronous callback.\n *\t\tconst mentionFeedPlaceholders = {\n *\t\t\tmarker: '$',\n *\t\t\tfeed: searchString => {\n *\t\t\t\treturn getMatchingPlaceholders( searchString );\n *\t\t\t}\n * \t\t};\n *\n *\t\tfunction getMatchingPlaceholders( searchString ) {\n *\t\t\treturn new Promise( resolve => {\n *\t\t\t\tdoSomeXHRQuery( result => {\n *\t\t\t\t\t// console.log( result );\n *\t\t\t\t\t// -> [ '$name', '$surname', '$postal', ... ]\n *\n *\t\t\t\t\tresolve( result );\n * \t\t\t\t} );\n *\t\t\t} );\n *\t\t}\n *\n * @typedef {Object} module:mention/mention~MentionFeed\n * @property {String} [marker] The character which triggers autocompletion for mention. It must be a single character.\n * @property {Array.<module:mention/mention~MentionFeedItem>|Function} feed Autocomplete items. Provide an array for\n * a static configuration (the mention feature will show matching items automatically) or a function which returns an array of\n * matching items (directly, or via a promise). If a function is passed, it is executed in the context of the editor instance.\n * @property {Number} [minimumCharacters=0] Specifies after how many characters the autocomplete panel should be shown.\n * @property {Function} [itemRenderer] A function that renders a {@link module:mention/mention~MentionFeedItem}\n * to the autocomplete panel.\n */\n\n/**\n * The mention feed item. It may be defined as a string or a plain object.\n *\n * When defining a feed item as a plain object, the `id` property is obligatory. Additional properties\n * can be used when customizing the mention feature bahavior\n * (see {@glink features/mentions#customizing-the-autocomplete-list \"Customizing the autocomplete list\"}\n * and {@glink features/mentions#customizing-the-output \"Customizing the output\"} sections).\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n *\t\t\t\tplugins: [ Mention, ... ],\n *\t\t\t\tmention: {\n *\t\t\t\t\tfeeds: [\n *\t\t\t\t\t\t// Feed items as objects.\n *\t\t\t\t\t\t{\n *\t\t\t\t\t\t\tmarker: '@',\n *\t\t\t\t\t\t\tfeed: [\n *\t\t\t\t\t\t\t\t{\n *\t\t\t\t\t\t\t\t\tid: '@Barney',\n *\t\t\t\t\t\t\t\t\tfullName: 'Barney Bloom'\n *\t\t\t\t\t\t\t\t},\n *\t\t\t\t\t\t\t\t{\n *\t\t\t\t\t\t\t\t\tid: '@Lily',\n *\t\t\t\t\t\t\t\t\tfullName: 'Lily Smith'\n *\t\t\t\t\t\t\t\t},\n *\t\t\t\t\t\t\t\t{\n *\t\t\t\t\t\t\t\t\tid: '@Marshall',\n *\t\t\t\t\t\t\t\t\tfullName: 'Marshall McDonald'\n *\t\t\t\t\t\t\t\t},\n *\t\t\t\t\t\t\t\t{\n *\t\t\t\t\t\t\t\t\tid: '@Robin',\n *\t\t\t\t\t\t\t\t\tfullName: 'Robin Hood'\n *\t\t\t\t\t\t\t\t},\n *\t\t\t\t\t\t\t\t{\n *\t\t\t\t\t\t\t\t\tid: '@Ted',\n *\t\t\t\t\t\t\t\t\tfullName: 'Ted Cruze'\n *\t\t\t\t\t\t\t\t},\n *\t\t\t\t\t\t\t\t// ...\n *\t\t\t\t\t\t\t]\n *\t\t\t\t\t\t},\n *\n *\t\t\t\t\t\t// Feed items as plain strings.\n *\t\t\t\t\t\t{\n *\t\t\t\t\t\t\tmarker: '#',\n *\t\t\t\t\t\t\tfeed: [ 'wysiwyg', 'rte', 'rich-text-edior', 'collaboration', 'real-time', ... ]\n *\t\t\t\t\t\t},\n * \t\t\t\t\t]\n *\t\t\t\t}\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * @typedef {Object|String} module:mention/mention~MentionFeedItem\n * @property {String} id A unique ID of the mention. It must start with the marker character.\n * @property {String} [text] Text inserted into the editor when creating a mention.\n */\n\n/**\n * Represents a mention in the model.\n *\n * See {@link module:mention/mention~Mention#toMentionAttribute `Mention#toMentionAttribute()`}.\n *\n * @interface module:mention/mention~MentionAttribute\n * @property {String} id The ID of a mention. It identifies the mention item in the mention feed.\n * @property {String} _uid An internal mention view item ID. Should be passed as an `option.id` when using\n * {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement writer.createAttributeElement()}.\n * @property {String} _text Helper property that stores the text of the inserted mention. Used for detecting a broken mention\n * in the editing area.\n */\n","export function MentionCaster( editor ) {\n // The upcast converter will convert <a class=\"mention\" href=\"\" data-user-id=\"\">\n // elements to the model 'mention' attribute.\n editor.conversion.for( 'upcast' ).elementToAttribute( {\n view: {\n name: 'a',\n key: 'data-mention',\n classes: 'mention',\n attributes: {\n href: true,\n 'data-user-id': true\n }\n },\n model: {\n key: 'mention',\n value: viewItem => {\n // The mention feature expects that the mention attribute value\n // in the model is a plain object with set of additional attributes.\n // In order to create proper object use `toMentionAttribute` helper method:\n const mentionAttribute = editor.plugins.get( 'Mention' ).toMentionAttribute( viewItem, {\n // Add any other properties that you need.\n link: viewItem.getAttribute( 'href' ),\n userId: viewItem.getAttribute( 'data-user-id' )\n } );\n\n return mentionAttribute;\n }\n },\n converterPriority: 'high'\n\t} );\n\n\t// editor.conversion\n\t// \t.for( 'editingDowncast' )\n\t// \t.attributeToElement( {\n\t// \t\tmodel: 'mention',\n\t// \t\tconverterPriority: 'high',\n\t// \t\tview: ( modelAttributeValue, viewWriter ) => {\n\t// \t\t\t// Do not convert empty attributes (lack of value means no mention).\n\t// \t\t\tif ( !modelAttributeValue ) {\n\t// \t\t\t\treturn;\n\t// \t\t\t}\n\n\t// \t\t\treturn viewWriter.createAttributeElement( 'a', {\n\t// \t\t\t\tclass: 'mention',\n\t// \t\t\t\t'data-type': modelAttributeValue.type,\n\t// \t\t\t\t'data-mention': modelAttributeValue.id,\n\t// \t\t\t\t'href': modelAttributeValue.link\n\t// \t\t\t} );\n\t// \t\t},\n\t// \t} );\n\n\teditor.conversion\n\t\t.for('downcast')\n\t\t.attributeToElement({\n\t\t\tmodel: 'mention',\n\t\t\tconverterPriority: 'high',\n\t\t\tview: (modelAttributeValue, writer) => {\n\t\t\t\t// Do not convert empty attributes (lack of value means no mention).\n\t\t\t\tif ( !modelAttributeValue ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst element = writer.createAttributeElement(\n\t\t\t\t\t'span',\n\t\t\t\t\t{\n\t\t\t\t\t\t'class': 'mention',\n\t\t\t\t\t\t'data-type': modelAttributeValue.type || '',\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\treturn element;\n\t\t\t}\n\t\t});\n}\n","/**\n * @license Copyright (c) 2003-2019, 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 paste-from-office/pastefromoffice\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport GoogleDocsNormalizer from './normalizers/googledocsnormalizer';\nimport MSWordNormalizer from './normalizers/mswordnormalizer';\nimport Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';\n\n/**\n * The Paste from Office plugin.\n *\n * This plugin handles content pasted from Office apps and transforms it (if necessary)\n * to a valid structure which can then be understood by the editor features.\n *\n * Transformation is made by a set of predefined {@link module:paste-from-office/normalizer~Normalizer normalizers}.\n * This plugin includes following normalizers:\n * * {@link module:paste-from-office/normalizers/mswordnormalizer~MSWordNormalizer Microsoft Word normalizer}\n * * {@link module:paste-from-office/normalizers/googledocsnormalizer~GoogleDocsNormalizer Google Docs normalizer}\n *\n * For more information about this feature check the {@glink api/paste-from-office package page}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class PasteFromOffice extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'PasteFromOffice';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ Clipboard ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst normalizers = [];\n\n\t\tnormalizers.push( new MSWordNormalizer() );\n\t\tnormalizers.push( new GoogleDocsNormalizer() );\n\n\t\teditor.plugins.get( 'Clipboard' ).on(\n\t\t\t'inputTransformation',\n\t\t\t( evt, data ) => {\n\t\t\t\tif ( data.isTransformedWithPasteFromOffice ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst htmlString = data.dataTransfer.getData( 'text/html' );\n\t\t\t\tconst activeNormalizer = normalizers.find( normalizer => normalizer.isActive( htmlString ) );\n\n\t\t\t\tif ( activeNormalizer ) {\n\t\t\t\t\tactiveNormalizer.execute( data );\n\n\t\t\t\t\tdata.isTransformedWithPasteFromOffice = true;\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ priority: 'high' }\n\t\t);\n\t}\n}\n","// This SVG file import will be handled by webpack's raw-text loader.\n// This means that imageIcon will hold the source SVG.\nimport imageIcon from './../../icons/help.svg';\n\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nexport default class OPHelpLinkPlugin extends Plugin {\n\n\tstatic get pluginName() {\n\t\treturn 'OPHelpLinkPlugin';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst helpURL = editor.config.get('openProject.helpURL');\n\n\t\teditor.ui.componentFactory.add( 'openProjectShowFormattingHelp', locale => {\n\t\t\tconst view = new ButtonView( locale );\n\n\t\t\tview.set( {\n\t\t\t\tlabel: window.I18n.t('js.inplace.link_formatting_help'),\n\t\t\t\ticon: imageIcon,\n\t\t\t\ttooltip: true\n\t\t\t} );\n\n\t\t\t// Callback executed once the image is clicked.\n\t\t\tview.on( 'execute', () => {\n\t\t\t\twindow.open(helpURL, '_blank');\n\t\t\t} );\n\n\t\t\treturn view;\n\t\t} );\n\t}\n}\n","\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport CodeBlockEditing from './code-block-editing';\nimport CodeBlockToolbar from './code-block-toolbar';\n\nexport default class CodeBlockPlugin extends Plugin {\n\tstatic get pluginName() {\n\t\treturn 'CodeBlock';\n\t}\n\n\tstatic get requires() {\n\t\treturn [ CodeBlockEditing, CodeBlockToolbar ];\n\t}\n}\n","// This SVG file import will be handled by webpack's raw-text loader.\n// This means that imageIcon will hold the source SVG.\nimport imageIcon from '../icons/preview.svg';\n\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport {getOPPath, getOPPreviewContext, getOPService} from './op-context/op-context';\nimport {enableItems, disableItems} from '../helpers/button-disabler';\n\nexport default class OPPreviewPlugin extends Plugin {\n\n\tstatic get pluginName() {\n\t\treturn 'OPPreview';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tlet previewing = false;\n\t\tlet unregisterPreview = null;\n\n\t\teditor.ui.componentFactory.add( 'preview', locale => {\n\t\t\tconst view = new ButtonView( locale );\n\n\t\t\tview.set( {\n\t\t\t\tlabel: this.label,\n\t\t\t\ticon: imageIcon,\n\t\t\t\ttooltip: true,\n\t\t\t} );\n\n\n\t\t\tlet showPreview = function(preview) {\n\t\t\t\tlet $mainEditor = jQuery(editor.ui.getEditableElement()).parent();\n\t\t\t\tlet $reference;\n\n\t\t\t\tif ($mainEditor.length) {\n\t\t\t\t\t$reference = $mainEditor;\n\t\t\t\t} else {\n\t\t\t\t\t$reference = $editable;\n\t\t\t\t}\n\n\t\t\t\tlet $previewWrapper = jQuery('<div class=\"ck-editor__preview\"></div>');\n\t\t\t\t$reference.siblings('.ck-editor__preview').remove();\n\n\t\t\t\tconst previewService = getOPService(editor, 'ckEditorPreview');\n\t\t\t\tunregisterPreview = previewService.render($previewWrapper[0], preview);\n\n\t\t\t\t$reference.hide();\n\t\t\t\t$reference.after($previewWrapper);\n\n\t\t\t\tdisableItems(editor, view);\n\t\t\t};\n\n\t\t\tlet getAndShowPreview = function() {\n\t\t\t\tlet link = getOPPreviewContext(editor);\n\t\t\t\tlet url = getOPPath(editor).api.v3.previewMarkup(link);\n\n\t\t\t\tjQuery\n\t\t\t\t\t.ajax({\n\t\t\t\t\t\tdata: editor.getData(),\n\t\t\t\t\t\turl: url,\n\t\t\t\t\t\tresponse_type: 'text',\n\t\t\t\t\t\tcontentType: 'text/plain; charset=UTF-8',\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t}).done(showPreview);\n\t\t\t};\n\n\t\t\tlet disablePreviewing = function() {\n\t\t\t\tlet $mainEditor = jQuery(editor.ui.getEditableElement()).parent();\n\n\t\t\t\tunregisterPreview();\n\t\t\t\t$mainEditor.siblings('.ck-editor__preview').remove();\n\t\t\t\t$mainEditor.show();\n\n\t\t\t\tenableItems(editor);\n\t\t\t};\n\n\n\t\t\t// Callback executed once the image is clicked.\n\t\t\tview.on('execute', () => {\n\t\t\t\tif (previewing) {\n\t\t\t\t\tpreviewing = false;\n\n\t\t\t\t\tdisablePreviewing();\n\t\t\t\t} else {\n\t\t\t\t\tpreviewing = true;\n\n\t\t\t\t\tgetAndShowPreview();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn view;\n\t\t} );\n\t}\n\n\tget label() {\n\t\treturn window.I18n.t('js.editor.preview');\n\t}\n}\n","// This SVG file import will be handled by webpack's raw-text loader.\n// This means that imageIcon will hold the source SVG.\nimport sourceIcon from '../icons/source.svg';\nimport wysiwygIcon from '../icons/wysiwyg.svg';\n\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport {getOPPath, getOPPreviewContext, getOPService} from './op-context/op-context';\nimport {enableItems, disableItems} from '../helpers/button-disabler';\n\nexport default class OPSourceCodePlugin extends Plugin {\n\n\tstatic get pluginName() {\n\t\treturn 'OPSourceCode';\n\t}\n\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tlet inSourceMode = false;\n\t\tlet labels = {\n\t\t\tsource: window.I18n.t('js.editor.mode.manual'),\n\t\t\twysiwyg: window.I18n.t('js.editor.mode.wysiwyg'),\n\t\t}\n\n\n\t\teditor.ui.componentFactory.add( 'opShowSource', locale => {\n\t\t\tconst view = new ButtonView( locale );\n\n\t\t\tview.set( {\n\t\t\t\tlabel: labels.source,\n\t\t\t\tclass: '',\n\t\t\t\ticon: sourceIcon,\n\t\t\t\ttooltip: true,\n\t\t\t} );\n\n\n\t\t\tlet showSource = function(preview) {\n\t\t\t\tlet $mainEditor = jQuery(editor.ui.getEditableElement()).parent();\n\t\t\t\tlet $reference;\n\n\t\t\t\tif ($mainEditor.length) {\n\t\t\t\t\t$reference = $mainEditor;\n\t\t\t\t} else {\n\t\t\t\t\t$reference = $editable;\n\t\t\t\t}\n\n\t\t\t\tlet $sourceWrapper = jQuery('<div class=\"ck-editor__source\"></div>');\n\t\t\t\t$reference.siblings('.ck-editor__source').remove();\n\n\t\t\t\t$reference.hide();\n\t\t\t\t$reference.after($sourceWrapper);\n\n\t\t\t\tdisableItems(editor, view);\n\n\t\t\t\teditor.fire('op:source-code-enabled');\n\n\t\t\t\tview.set( {\n\t\t\t\t\tlabel: labels.wysiwyg,\n\t\t\t\t\tclass: '-source-enabled',\n\t\t\t\t\ticon: wysiwygIcon,\n\t\t\t\t\ttooltip: true,\n\t\t\t\t} );\n\n\t\t\t};\n\n\t\t\tlet hideSource = function() {\n\t\t\t\tlet $mainEditor = jQuery(editor.ui.getEditableElement()).parent();\n\n\t\t\t\teditor.fire('op:source-code-disabled');\n\n\t\t\t\t$mainEditor.siblings('.ck-editor__source').remove();\n\t\t\t\t$mainEditor.show();\n\n\t\t\t\tenableItems(editor);\n\n\t\t\t\tview.set( {\n\t\t\t\t\tlabel: labels.source,\n\t\t\t\t\tclass: '',\n\t\t\t\t\ticon: sourceIcon,\n\t\t\t\t\ttooltip: true,\n\t\t\t\t} );\n\t\t\t};\n\n\n\t\t\t// Callback executed once the image is clicked.\n\t\t\tview.on('execute', () => {\n\t\t\t\tif (inSourceMode) {\n\t\t\t\t\tinSourceMode = false;\n\t\t\t\t\thideSource();\n\t\t\t\t} else {\n\t\t\t\t\tinSourceMode = true;\n\t\t\t\t\tshowSource();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn view;\n\t\t} );\n\t}\n\n}\n","/**\n * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md.\n */\n\nimport CommonMarkDataProcessor from './commonmarkdataprocessor';\n\n// Simple plugin which loads the data processor.\n// eslint-disable-next-line no-unused-vars\nexport default function CommonMarkPlugin( editor ) {\n\teditor.data.processor = new CommonMarkDataProcessor();\n}\n\n","/**\n * @license Copyright (c) 2003-2019, 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 table/table\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport TableEditing from './tableediting';\nimport TableUI from './tableui';\nimport Widget from '@ckeditor/ckeditor5-widget/src/widget';\n\nimport '../theme/table.css';\n\n/**\n * The table plugin.\n *\n * For a detailed overview, check the {@glink features/table Table feature documentation}.\n *\n * This is a \"glue\" plugin which loads the {@link module:table/tableediting~TableEditing table editing feature}\n * and {@link module:table/tableui~TableUI table UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Table extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ TableEditing, TableUI, Widget ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Table';\n\t}\n}\n\n/**\n * The configuration of the table features. Used by the table features in the `@ckeditor/ckeditor5-table` package.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n * \t\t\t\ttable: ... // Table feature options.\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.\n *\n * @interface TableConfig\n */\n\n/**\n * The configuration of the {@link module:table/table~Table} feature.\n *\n * Read more in {@link module:table/table~TableConfig}.\n *\n * @member {module:table/table~TableConfig} module:core/editor/editorconfig~EditorConfig#table\n */\n","/**\n * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n/**\n * @module table/tabletoolbar\n */\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport {\n getSelectedTableWidget,\n getTableWidgetAncestor\n} from './utils';\nimport WidgetToolbarRepository from '@ckeditor/ckeditor5-widget/src/widgettoolbarrepository';\n/**\n * The table toolbar class. It creates toolbars for the table feature and its content (for now only for a table cell content).\n *\n * Table toolbar shows up when a table widget is selected. Its components (e.g. buttons) are created based on the\n * {@link module:table/table~TableConfig#tableToolbar `table.tableToolbar` configuration option}.\n *\n * Table content toolbar shows up when the selection is inside the content of a table. It creates its component based on the\n * {@link module:table/table~TableConfig#contentToolbar `table.contentToolbar` configuration option}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TableToolbar extends Plugin {\n /**\n\t * @inheritDoc\n\t */\n static get requires() {\n return [WidgetToolbarRepository];\n }\n /**\n\t * @inheritDoc\n\t */\n static get pluginName() {\n return 'TableToolbar';\n }\n /**\n\t * @inheritDoc\n\t */\n afterInit() {\n const editor = this.editor;\n const t = editor.t;\n const widgetToolbarRepository = editor.plugins.get(WidgetToolbarRepository);\n const tableContentToolbarItems = editor.config.get('table.contentToolbar');\n const tableToolbarItems = editor.config.get('table.tableToolbar');\n if (tableContentToolbarItems) {\n widgetToolbarRepository.register('tableContent', {\n ariaLabel: t('c'),\n items: tableContentToolbarItems,\n getRelatedElement: getTableWidgetAncestor\n });\n }\n if (tableToolbarItems) {\n widgetToolbarRepository.register('table', {\n ariaLabel: t('c'),\n items: tableToolbarItems,\n getRelatedElement: getSelectedTableWidget\n });\n }\n }\n} /**\n * Items to be placed in the table content toolbar.\n * The {@link module:table/tabletoolbar~TableToolbar} plugin is required to make this toolbar working.\n *\n * Assuming that you use the {@link module:table/tableui~TableUI} feature, the following toolbar items will be available\n * in {@link module:ui/componentfactory~ComponentFactory}:\n *\n * * `'tableRow'`,\n * * `'tableColumn'`,\n * * `'mergeTableCells'`.\n *\n * You can thus configure the toolbar like this:\n *\n *\t\tconst tableConfig = {\n *\t\t\tcontentToolbar: [ 'tableRow', 'tableColumn', 'mergeTableCells' ]\n *\t\t};\n *\n * Of course, the same buttons can also be used in the\n * {@link module:core/editor/editorconfig~EditorConfig#toolbar main editor toolbar}.\n *\n * Read more about configuring toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.\n *\n * @member {Array.<String>} module:table/table~TableConfig#contentToolbar\n */\n /**\n * Items to be placed in the table toolbar.\n * The {@link module:table/tabletoolbar~TableToolbar} plugin is required to make this toolbar working.\n *\n * You can thus configure the toolbar like this:\n *\n *\t\tconst tableConfig = {\n *\t\t\ttableToolbar: [ 'blockQuote' ]\n *\t\t};\n *\n * Of course, the same buttons can also be used in the\n * {@link module:core/editor/editorconfig~EditorConfig#toolbar main editor toolbar}.\n *\n * Read more about configuring toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.\n *\n * @member {Array.<String>} module:table/table~TableConfig#tableToolbar\n */","import Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport { createDropdown, addToolbarToDropdown } from '@ckeditor/ckeditor5-ui/src/dropdown/utils';\n\nimport {opMacroPlugins} from \"../op-plugins\";\n\n/**\n * Adding a drop down list of macros to the toolbar.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class OPMacroListPlugin extends Plugin {\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst disabledPluginNames = (editor.config.get('removePlugins') || []).map(p => p.pluginName);\n\t\tconst dropdownTooltip = window.I18n.t('js.editor.macro.dropdown.chose_macro');\n\n\t\t// Skip if we don't have any macros here\n\t\tif (editor.config.get('openProject.disableAllMacros') === true) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Register UI component.\n\t\teditor.ui.componentFactory.add( 'macroList', locale => {\n\t\t\tconst dropdownItems = [];\n\t\t\tfor ( const macroPlugin of opMacroPlugins ) {\n\t\t\t\tif (disabledPluginNames.indexOf(macroPlugin.pluginName) !== -1) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst listItem = editor.ui.componentFactory.create(macroPlugin.buttonName);\n\t\t\t\tdropdownItems.push(listItem);\n\t\t\t}\n\t\t\tconst dropdownView = createDropdown( locale );\n\n\t\t\taddToolbarToDropdown(dropdownView, dropdownItems);\n\t\t\tdropdownView.buttonView.set( {\n\t\t\t\tisOn: false,\n\t\t\t\twithText: true,\n\t\t\t\ttooltip: dropdownTooltip,\n\t\t\t\tlabel: window.I18n.t('js.editor.macro.dropdown.macros')\n\t\t\t} );\n\t\t\tdropdownView.toolbarView.isVertical = true;\n\t\t\tdropdownView.toolbarView.className = 'op-macro-list-button';\n\n\t\t\treturn dropdownView;\n\t\t} );\n\t}\n}\n","export function customItemRenderer( item ) {\n const itemElement = document.createElement( 'span' );\n\n\titemElement.classList.add( 'mention-list-item' );\n\titemElement.textContent = item.name;\n\n return itemElement;\n}\n","import { userMentions } from \"./mentions/user-mentions\";\nimport { workPackageMentions } from \"./mentions/work-package-mentions\";\nimport {customItemRenderer} from './mentions/mentions-item-renderer';\n\nexport const defaultConfig = {\n\theading: {\n\t\toptions: [\n\t\t\t{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },\n\t\t\t{ model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },\n\t\t\t{ model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },\n\t\t\t{ model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' },\n\t\t\t{ model: 'heading4', view: 'h4', title: 'Heading 4', class: 'ck-heading_heading4' },\n\t\t\t{ model: 'heading5', view: 'h5', title: 'Heading 5', class: 'ck-heading_heading5' }\n\t\t]\n\t},\n\ttoolbar: {\n\t\t// Will be defined by each build\n\t},\n\tOPMacroEmbeddedTable: {\n\t\ttoolbar: [\n\t\t\t'opEditEmbeddedTableQuery',\n\t\t]\n\t},\n\tOPMacroWpButton: {\n\t\ttoolbar: [\n\t\t\t'opEditWpMacroButton',\n\t\t]\n\t},\n\tOPWikiIncludePage: {\n\t\ttoolbar: [\n\t\t\t'opEditWikiIncludeMacroButton',\n\t\t]\n\t},\n\tOPCodeBlock: {\n\t\ttoolbar: [\n\t\t\t'opEditCodeBlock',\n\t\t]\n\t},\n\tOPChildPages: {\n\t\ttoolbar: [\n\t\t\t'opEditChildPagesMacroButton',\n\t\t]\n\t},\n\timage: {\n\t\ttoolbar: [\n\t\t\t'imageStyle:full',\n\t\t\t'|',\n\t\t\t'imageTextAlternative'\n\t\t]\n\t},\n\ttable: {\n\t\tcontentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells' ]\n\t},\n\n\tmention: {\n\t\tfeeds: [\n\t\t\t{\n\t\t\t\tmarker: '@',\n\t\t\t\tfeed: userMentions,\n\t\t\t\titemRenderer: customItemRenderer,\n\t\t\t\tminimumCharacters: 0\n\t\t\t},\n\t\t\t{\n\t\t\t\tmarker: '#',\n\t\t\t\tfeed: workPackageMentions,\n\t\t\t\titemRenderer: customItemRenderer,\n\t\t\t\tminimumCharacters: 1\n\t\t\t},\n\t\t]\n\t},\n\n\tlanguage: 'en'\n};\n","import { getOPResource, getOPPath } from \"../plugins/op-context/op-context\";\n\nexport function userMentions(queryText) {\n\t let editor = this;\n\t let resource = getOPResource(editor);\n\n\t // Unsupported context does not allow mentioning\n\t if (!(resource && resource._type === 'WorkPackage')) {\n\t\treturn [];\n\t }\n\n\tconst project_id = resource.project.idFromLink;\n\tconst url = getOPPath(editor).api.v3.principals(project_id, queryText);\n\tlet base = window.OpenProject.urlRoot + `/users/`;\n\n\treturn new Promise((resolve, reject) => {\n\t\tjQuery\n\t\t\t.getJSON(url, collection => {\n\t\t\t\tresolve(collection._embedded.elements.map(user => {\n\t\t\t\t\tconst type = user._type.toLowerCase();\n\t\t\t\t\tconst displayText = `${type}#${user.id}`;\n\t\t\t\t\tconst id = `@${user.id}`;\n\t\t\t\t\treturn { type: 'user', id: id, text: displayText, name: user.name, link: base + user.id };\n\t\t\t\t}));\n\t\t\t});\n\t\t})\n}\n","import { getOPResource, getOPPath } from \"../plugins/op-context/op-context\";\n\nexport function workPackageMentions(query) {\n\tconst url = window.OpenProject.urlRoot + `/work_packages/auto_complete.json`;\n\tlet base = window.OpenProject.urlRoot + `/work_packages/`;\n\n\treturn new Promise((resolve, reject) => {\n\t\tjQuery\n\t\t\t.getJSON(url, {q: query, scope: 'all'}, collection => {\n\t\t\t\tresolve(collection.map(wp => {\n\t\t\t\t\tconst id = `#${wp.id}`;\n\t\t\t\t\treturn { type: 'work_package', id: id, text: id, name: wp.to_s, link: base + wp.id };\n\t\t\t\t}));\n\t\t\t});\n\t\t})\n}\n","import {opImageUploadPlugins, opMacroPlugins} from './op-plugins';\n\nexport function configurationCustomizer(editorClass) {\n\treturn (wrapper, configuration) => {\n\t\tconst context = configuration.openProject.context;\n\n\t\t// We're going to remove some plugins from the default configuration\n\t\t// when we detect they are unsupported in the current context\n\t\tconfiguration.removePlugins = configuration.removePlugins || [];\n\n\t\t// Disable uploading if there is no resource with uploadAttachment\n\t\tconst resource = context.resource;\n\t\tif (!(resource && resource.canAddAttachments)) {\n\t\t\tconfiguration.removePlugins.push(...opImageUploadPlugins.map(el => el.pluginName))\n\t\t}\n\n\t\t// Disable macros entirely\n\t\tif (context.macros === false) {\n\t\t\tconfiguration.openProject.disableAllMacros = true;\n\t\t\tconfiguration.removePlugins.push(...opMacroPlugins.map(el => el.pluginName))\n\t\t}\n\n\t\t// Enable selective macros\n\t\tif (Array.isArray(context.macros)) {\n\t\t\tconst disabledMacros = opMacroPlugins.filter(plugin => context.macros.indexOf(plugin.pluginName) === -1);\n\t\t\tconfiguration.removePlugins.push(...disabledMacros);\n\t\t}\n\n\t\t// Return the original promise for instance creation\n\t\treturn editorClass.create(wrapper, configuration);\n\t};\n}\n","import DecoupledEditorBase from '@ckeditor/ckeditor5-editor-decoupled/src/decouplededitor';\nimport {builtinPlugins} from './op-plugins';\nimport {defaultConfig} from \"./op-ckeditor-config\";\nimport {configurationCustomizer} from './op-config-customizer';\n\nexport class ConstrainedEditor extends DecoupledEditorBase {}\nexport class FullEditor extends DecoupledEditorBase {}\n\n// Export the two common interfaces\nwindow.OPConstrainedEditor = ConstrainedEditor;\nwindow.OPClassicEditor = FullEditor;\n\nFullEditor.createCustomized = configurationCustomizer(FullEditor);\nFullEditor.builtinPlugins = builtinPlugins;\nFullEditor.defaultConfig = Object.assign({}, defaultConfig);\nFullEditor.defaultConfig.toolbar = {\n\t\titems: [\n\t\t\t'heading',\n\t\t\t'|',\n\t\t\t'bold',\n\t\t\t'italic',\n\t\t\t'strikethrough',\n\t\t\t'code',\n\t\t\t'insertCodeBlock',\n\t\t\t'link',\n\t\t\t'bulletedList',\n\t\t\t'numberedList',\n\t\t\t'todoList',\n\t\t\t'imageUpload',\n\t\t\t'blockQuote',\n\t\t\t'|',\n\t\t\t'insertTable',\n\t\t\t'macroList',\n\t\t\t'|',\n\t\t\t'undo',\n\t\t\t'redo',\n\t\t\t'openProjectShowFormattingHelp',\n\t\t\t'|',\n\t\t\t'preview',\n\t\t\t'opShowSource'\n\t\t]\n};\n\nConstrainedEditor.createCustomized = configurationCustomizer(ConstrainedEditor);\nConstrainedEditor.builtinPlugins = builtinPlugins;\nConstrainedEditor.defaultConfig = Object.assign({}, defaultConfig);\nConstrainedEditor.defaultConfig.toolbar = {\n\titems: [\n\t\t'bold',\n\t\t'italic',\n\t\t'strikethrough',\n\t\t'code',\n\t\t'insertCodeBlock',\n\t\t'link',\n\t\t'bulletedList',\n\t\t'numberedList',\n\t\t'todoList',\n\t\t'imageUpload',\n\t\t'blockQuote',\n\t\t'|',\n\t\t'openProjectShowFormattingHelp',\n\t\t'preview',\n\t\t'opShowSource'\n\t]\n};\n"],"sourceRoot":""}